《C語(yǔ)言程序設(shè)計(jì) 》課件第10章_第1頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第10章_第2頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第10章_第3頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第10章_第4頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第10章_第5頁(yè)
已閱讀5頁(yè),還剩65頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第10章文件10.1文件概述10.2文件處理10.3文件的順序讀寫10.4文件的隨機(jī)讀寫10.5文件檢測(cè)函數(shù)本章小結(jié)

10.1文件概述

在以往的程序中,往往是從鍵盤輸入數(shù)據(jù),并將輸出顯示在計(jì)算機(jī)屏幕上。程序運(yùn)行完畢后,所有數(shù)據(jù)都會(huì)消失。這樣顯然不滿足一些實(shí)際需求。比如,在學(xué)生學(xué)籍管理系統(tǒng)中,需要將學(xué)生的相關(guān)信息以文件形式保存下來(lái)。本章介紹的C語(yǔ)言中文件的相關(guān)知識(shí)正是為了解決此類問(wèn)題。所謂“文件”,是指存放在外部介質(zhì)中的一組相關(guān)數(shù)據(jù)的有序集合。這個(gè)數(shù)據(jù)集合有一個(gè)名字,稱為文件名。操作系統(tǒng)是以文件為單位對(duì)數(shù)據(jù)進(jìn)行管理的。也就是說(shuō),如果想找存放在外部介質(zhì)中的數(shù)據(jù),就必須先按文件名找到所指定的文件,然后再?gòu)脑撐募凶x取數(shù)據(jù)。若要在外部介質(zhì)中存儲(chǔ)數(shù)據(jù),也必須先建立一個(gè)文件(以文件名為標(biāo)識(shí)),然后才能向它輸出數(shù)據(jù)。實(shí)際上,前面各章中已經(jīng)多次使用了文件,例如源程序文件、目標(biāo)文件、可執(zhí)行文件、庫(kù)文件(頭文件)等。在C語(yǔ)言中,文件是一串連續(xù)的字節(jié),每個(gè)字節(jié)均能被單獨(dú)讀取。C語(yǔ)言程序?qū)ξ募奶幚硎峭ㄟ^(guò)標(biāo)準(zhǔn)函數(shù)庫(kù)中的文件操作函數(shù)實(shí)現(xiàn)的,使用這些函數(shù),可以簡(jiǎn)單、高效、安全地訪問(wèn)外部數(shù)據(jù)。此外,C語(yǔ)言中所有的外部設(shè)備均被作為文件對(duì)待,這種文件稱為設(shè)備文件。對(duì)外部設(shè)備的輸入/輸出處理就是讀/寫設(shè)備文件的過(guò)程。設(shè)備文件是指與主機(jī)相連的各種外部設(shè)備,如顯示器、打印機(jī)、鍵盤等。在操作系統(tǒng)中,將外部設(shè)備作為一個(gè)文件來(lái)進(jìn)行管理,它們的輸入、輸出等同于對(duì)磁盤文件的讀和寫。通常把顯示器定義為標(biāo)準(zhǔn)輸出文件。一般情況下,在屏幕上顯示有關(guān)信息就是向標(biāo)準(zhǔn)輸出文件輸出數(shù)據(jù),如前面經(jīng)常使用的printf、putchar函數(shù)就屬于這類輸出。鍵盤通常被指定為標(biāo)準(zhǔn)輸入文件。從鍵盤上輸入就意味著從標(biāo)準(zhǔn)輸入文件上輸入數(shù)據(jù),如scanf、getchar函數(shù)就屬于這類輸入。10.1.1文本文件與二進(jìn)制文件

從文件編碼的方式來(lái)看,文件可分為ASCII文件和二進(jìn)制文件兩種。

ASCII文件也稱為文本文件,這種文件在磁盤中存放時(shí)每個(gè)字符對(duì)應(yīng)一個(gè)字節(jié),用于存放對(duì)應(yīng)的ASCII碼。

例如,數(shù)5678的存儲(chǔ)形式為

ASCII碼:00110101001101100011011100111000

↓↓↓↓

十進(jìn)制碼:5?678

共占用4個(gè)字節(jié)。

ASCII文件可在屏幕上按字符顯示。例如,源程序文件就是ASCII文件,用DOS命令TYPE可顯示文件的內(nèi)容。由于ASCII文件是按字符顯示的,因此能讀懂文件內(nèi)容。

二進(jìn)制文件是按二進(jìn)制的編碼方式來(lái)存放文件的。例如,數(shù)5678的存儲(chǔ)形式為

0001011000101110

只占兩個(gè)字節(jié)。二進(jìn)制文件雖然也可在屏幕上顯示,但其內(nèi)容無(wú)法讀懂。C系統(tǒng)在處理這些文件時(shí),并不區(qū)分類型,都看成是字符流,按字節(jié)進(jìn)行處理。10.1.2文件緩沖區(qū)

文件緩沖區(qū)可以分為輸出文件緩沖區(qū)和輸入文件緩沖區(qū)。

在程序運(yùn)行過(guò)程中,程序要將保存在內(nèi)存中的數(shù)據(jù)寫入磁盤,首先要建立一個(gè)“輸出文件緩沖區(qū)”,這個(gè)緩沖區(qū)是連接計(jì)算機(jī)內(nèi)存數(shù)據(jù)與外存文件的橋梁。當(dāng)向文件輸出數(shù)據(jù)時(shí),準(zhǔn)備輸出的數(shù)據(jù)先送入文件緩沖區(qū),等文件緩沖區(qū)數(shù)據(jù)裝滿后再一起送到文件中。這一過(guò)程稱為“寫文件”,是數(shù)據(jù)輸出過(guò)程。與“寫文件”過(guò)程相對(duì)的是要將保存在文件中的數(shù)據(jù)讀入內(nèi)存。首先要建立一個(gè)“輸入文件緩沖區(qū)”,當(dāng)從文件中輸入數(shù)據(jù)時(shí),也是把準(zhǔn)備輸入的數(shù)據(jù)先送入文件緩沖區(qū),等文件緩沖區(qū)數(shù)據(jù)裝滿之后再整個(gè)送到程序數(shù)據(jù)區(qū)。這一過(guò)程稱為“讀文件”,是數(shù)據(jù)輸入過(guò)程。

圖10-1所示為使用緩沖區(qū)的文件讀?寫示意圖,這種數(shù)據(jù)的讀寫方式提高了程序的執(zhí)行效率。圖10-1使用緩沖區(qū)的文件讀、寫示意圖10.1.3文件的指針

在C語(yǔ)言中用一個(gè)指針變量指向一個(gè)文件,這個(gè)指針?lè)Q為文件指針。通過(guò)文件指針可對(duì)它所指的文件進(jìn)行各種操作。為了能正常使用文件,C語(yǔ)言系統(tǒng)要對(duì)打開(kāi)的每一個(gè)文件從多方面進(jìn)行跟蹤管理,如文件緩沖區(qū)的大小、文件緩沖區(qū)的位置、文件緩沖區(qū)使用的程度、文件操作模式、文件內(nèi)部讀寫位置等,這些信息被記錄在“文件信息區(qū)”的結(jié)構(gòu)體變量中,該變量的數(shù)據(jù)類型由C語(yǔ)言系統(tǒng)事先定義,固定包含在頭文件“stdio.h”中,數(shù)據(jù)類型名為“FILE”。以下是TurboC2.0文件指針類型的定義:

typedefstruct

{

int level; /*緩沖區(qū)被占用的程度*/

unsigned flags; /*文件狀態(tài)標(biāo)記*/

char fd; /*文件描述符*/

unsignedchar hold; /*如無(wú)緩沖區(qū),則不讀取字符*/

short bsize; /*緩沖區(qū)大小*/

unsignedchar *buffer; /*文件緩沖區(qū)指針*/

unsignedchar *curp; /*文件定位指針*/

unsigned istemp; /*臨時(shí)文件標(biāo)識(shí)*/

short token; /*用于合法性檢測(cè)*/

}FILE;這里,F(xiàn)ILE就是所定義的文件指針類型的類型名。在定義中使用了“typedef”關(guān)鍵字,它的作用是把用struct定義的結(jié)構(gòu)體類型命名為“FILE”。

在C語(yǔ)言中,要對(duì)已打開(kāi)的文件進(jìn)行操作,就要通過(guò)指向該文件結(jié)構(gòu)體的指針,因此需要在程序中定義FILE類型的指針變量,并使其指向要操作的文件。

定義文件指針的一般形式為

FILE*指針變量標(biāo)識(shí)符;

例如:

FILE*fp;

表示fp是指向FILE類型結(jié)構(gòu)體的指針變量,通過(guò)fp即可找到存放某個(gè)文件信息的結(jié)構(gòu)體變量,然后按結(jié)構(gòu)體變量提供的信息找到該文件,實(shí)施對(duì)文件的操作。習(xí)慣上,把fp稱為指向一個(gè)文件的指針。 10.2文件處理

10.2.1文件的打開(kāi)

打開(kāi)一個(gè)文件應(yīng)使用fopen函數(shù),其調(diào)用形式為

FILE*fp;

fp=fopen(文件名,使用文件方式);

例如:

FILE*fp;

fp=fopen(“a”,“r”);

其意義是在當(dāng)前目錄下打開(kāi)文件a,只允許進(jìn)行“讀入”(r代表read,即讀入)操作,fopen函數(shù)帶回指向a文件的指針并賦給fp。

又如:

FILE*fphzk;

fphzk=fopen("c:\\hzk16","rb");其意義是打開(kāi)C驅(qū)動(dòng)器磁盤的根目錄下的文件hzk16,這是一個(gè)二進(jìn)制文件,只允許按二進(jìn)制方式進(jìn)行讀操作。兩個(gè)反斜線“\\”中的第一個(gè)表示轉(zhuǎn)義字符,第二個(gè)表示根目錄。

由以上兩個(gè)例子可以看出,在打開(kāi)一個(gè)文件時(shí),通知編譯系統(tǒng)以下3個(gè)信息:

①需要打開(kāi)的文件名;

②文件使用方式;

③讓哪一個(gè)指針變量指向被打開(kāi)的文件。

文件使用方式共有12種,如表10-1所示。對(duì)于文件使用方式有以下幾點(diǎn)說(shuō)明:

(1)文件使用方式由r、w、a、t、b、+六個(gè)字符拼成,各字符的含義是:

r(read):讀;

w(write):寫;

a(append):追加;

t(text):文本文件,可省略不寫;

b(banary):二進(jìn)制文件;

+:讀和寫。

(2)用?"r"?方式打開(kāi)一個(gè)文件時(shí),該文件必須已經(jīng)存在,且只能從該文件讀出數(shù)據(jù)。

(3)用?“w”?方式打開(kāi)一個(gè)文件時(shí),若打開(kāi)的文件不存在,則以指定的文件名建立該文件;若打開(kāi)的文件已經(jīng)存在,則將該文件刷新。以該方式打開(kāi)的文件只能寫,不能讀。

(4)若要向一個(gè)已存在的文件追加新的信息,只能用?“a”?方式打開(kāi)文件,但此時(shí)該文件必須是存在的,否則將會(huì)出錯(cuò)。

(5)在打開(kāi)一個(gè)文件時(shí),如果出錯(cuò),fopen函數(shù)將返回一個(gè)空指針值NULL。在程序中可以用這一信息來(lái)判別是否完成打開(kāi)文件的工作,并作相應(yīng)的處理。因此常用以下程序段打開(kāi)文件:

if((fp=fopen(“c:\\hzk16”,“rb”))==NULL)

{

printf(“\nerroronopenc:\\hzk16file!”);

getch();

exit(1);

}這段程序的含義是,如果返回的指針為空,表示不能打開(kāi)C盤根目錄下的hzk16文件,則給出提示信息“erroronopenc:\\hzk16file!”。getch()的功能是從鍵盤輸入一個(gè)字符,但不在屏幕上顯示。在這里,該行的作用是等待,只有當(dāng)用戶從鍵盤敲任一鍵時(shí),程序才繼續(xù)執(zhí)行,因此用戶可利用這個(gè)等待時(shí)間閱讀出錯(cuò)提示。敲鍵后執(zhí)行exit(1)退出程序。

(6)把一個(gè)文本文件讀入內(nèi)存時(shí),要將ASCII碼轉(zhuǎn)換成二進(jìn)制碼,而把文件以文本方式寫入磁盤時(shí),也要把二進(jìn)制碼轉(zhuǎn)換成ASCII碼,因此文本文件的讀寫要花費(fèi)較多的轉(zhuǎn)換時(shí)間。二進(jìn)制文件的讀寫不存在這種轉(zhuǎn)換。

(7)標(biāo)準(zhǔn)輸入文件(鍵盤)、標(biāo)準(zhǔn)輸出文件(顯示器)、標(biāo)準(zhǔn)出錯(cuò)輸出(出錯(cuò)信息)是由系統(tǒng)打開(kāi)的,可直接使用。10.2.2文件的關(guān)閉

文件一旦使用完畢,應(yīng)用關(guān)閉文件函數(shù)把文件關(guān)閉,以避免文件的數(shù)據(jù)丟失。

用fclose函數(shù)關(guān)閉文件,其調(diào)用形式為

fclose(文件指針);

例如:

fclose(fp);

前面曾把用fopen函數(shù)打開(kāi)文件時(shí)所帶回的指針賦給了fp,現(xiàn)通過(guò)fp把該文件關(guān)閉,此后fp不再指向該文件。正常完成關(guān)閉文件操作后,fclose函數(shù)返回值為0。如返回非零值,則表示有錯(cuò)誤發(fā)生。 10.3文件的順序讀寫

10.3.1字符讀寫函數(shù)fgetc和fputc

1.讀字符函數(shù)fgetc

fgetc函數(shù)的調(diào)用形式為

字符變量=fgetc(文件指針);

例如:

ch=fgetc(fp);其中:fp為文件指針變量;ch為字符變量。該語(yǔ)句表示從打開(kāi)的文件fp中讀取一個(gè)字符并送入ch中。在使用fgetc函數(shù)時(shí),應(yīng)注意以下幾點(diǎn):

(1)在fgetc函數(shù)調(diào)用中,讀取的文件必須是以讀或讀寫方式打開(kāi)的。

(2)讀取字符的結(jié)果可以不向字符變量賦值,例如:

fgetc(fp);

但是讀出的字符不能保存。

(3)在文件內(nèi)部有一個(gè)位置指針,用來(lái)指向文件的當(dāng)前讀寫字節(jié)。在文件打開(kāi)時(shí),該指針總是指向文件的第一個(gè)字節(jié)。使用fgetc函數(shù)后,該位置指針將向后移動(dòng)一個(gè)字節(jié)。因此可連續(xù)多次使用fgetc函數(shù)讀取多個(gè)字符。注意文件指針和文件內(nèi)部的位置指針是不一樣的。文件指針是指向整個(gè)文件的,須在程序中定義說(shuō)明,只要不重新賦值,文件指針的值是不變的。文件內(nèi)部的位置指針用以指示文件內(nèi)部的當(dāng)前讀寫位置,每讀寫一次,該指針均向后移動(dòng),它不需在程序中定義說(shuō)明,而是由系統(tǒng)自動(dòng)設(shè)置的。

2.寫字符函數(shù)fputc

fputc函數(shù)的功能是把一個(gè)字符寫入指定的文件中,其調(diào)用形式為

fputc(字符量,文件指針);

其中,待寫入的字符量可以是字符常量或變量。例如:

fputc('a',fp);

其意義是把字符a寫入fp所指向的文件中。對(duì)于fputc函數(shù)的使用也要說(shuō)明幾點(diǎn):

(1)被寫入的文件可以用寫?讀寫?追加方式打開(kāi)。用寫或讀寫方式打開(kāi)一個(gè)已存在的文件時(shí),將清除原有的文件內(nèi)容,寫入字符從文件首開(kāi)始。如需保留原有文件的內(nèi)容,且希望寫入的字符從文件末開(kāi)始存放,則必須以追加方式打開(kāi)文件。被寫入的文件若不存在,則創(chuàng)建該文件。

(2)每寫入一個(gè)字符,文件內(nèi)部的位置指針向后移動(dòng)一個(gè)字節(jié)。

(3)fputc函數(shù)有一個(gè)返回值,如寫入成功則返回寫入的字符,否則返回一個(gè)EOF??捎么藖?lái)判斷寫入是否成功。

【例10.1】把從鍵盤輸入的一個(gè)字符串寫入磁盤文件example.txt中。

程序如下:

#include“stdio.h”

main()

{

charch;

FILE*fp;

fp=fopen(“example.txt”,“w”);

printf(“Enterastring:”);

while((ch=getchar())!=‘\n’)

fputc(ch,fp);

fclose(fp);

}本程序使用?"w"?方式打開(kāi)example.txt文件,實(shí)際上就是創(chuàng)建example.txt文件。該文件的內(nèi)容是鍵盤輸入的內(nèi)容。example.txt是一個(gè)文本文件,可以使用任何文本編輯程序閱讀該文件。比如可以使用記事本程序打開(kāi)example.txt文件查看它的內(nèi)容。

【例10.2】把一個(gè)文本文件的內(nèi)容復(fù)制到另一個(gè)文本文件中。

程序如下:

#include“stdio.h”

main()

{

charch,source[10],target[10];

FILE*fp_s,*fp_t;

printf(“Enterthesourcefilename:”);

scanf(“%s”,source);

printf(“Enterthetargetfilename:”);

scanf("%s",target);

if((fp_s=fopen(source,“r”))==NULL)

{

printf(“cannotopensourcefile.\n”);

exit(1);

}

if((fp_t=fopen(target,“w”))==NULL)

{

printf(“cannotopentargetfile.\n”);

exit(1);

}

while(!feof(fp_s))

fputc(fgetc(fp_s),fp_t);

fclose(fp_s);

fclose(fp_t);

}程序運(yùn)行結(jié)果:

Enterthesourcefilename:example.txt

Enterthetargetfilename:try.txt

其中:example.txt是要復(fù)制的源文件名,是已經(jīng)存在的一個(gè)文本文件;try.txt是要形成的目標(biāo)文件名。程序運(yùn)行結(jié)束后,example.txt文件復(fù)制到try.txt文件中。10.3.2字符串讀寫函數(shù)fgets和fputs

1.字符串讀函數(shù)fgets

fgets函數(shù)的功能是從指定的文件中讀一個(gè)字符串到字符數(shù)組中,其調(diào)用形式為

fgets(字符數(shù)組名,n,文件指針);

其中的n是一個(gè)正整數(shù),表示從文件中讀出的字符串不超過(guò)n?-?1個(gè)字符。注意,應(yīng)在讀入的最后一個(gè)字符后加上串結(jié)束標(biāo)志?'\0'。

例如:

fgets(str,n,fp);

其意義是從fp所指的文件中讀出n-1個(gè)字符送入字符數(shù)組str中。

2.字符串寫函數(shù)fputs

fputs函數(shù)的功能是向指定的文件寫入一個(gè)字符串,其調(diào)用形式為

fputs(字符串,文件指針);

其中字符串可以是字符串常量,也可以是字符數(shù)組。

例如:

fputs("abcd",fp);

其意義是把字符串?"abcd"?寫入fp所指的文件之中。

【例10.3】將字符串?“VisualC++”?和?“Visualbasic”?依次存入文件text中,然后將第一個(gè)字符串讀出并在屏幕上顯示出來(lái)。

程序如下:

#include“stdio.h”

main()

{

FILE*fp;

charstring[20];

fp=fopen(“text”,“w+”);

fputs(“VisualC++\n”,fp);

fputs(“Visualbasic\n”,fp);

rewind(fp);

fgets(string,20,fp);

puts(string);

fclose(fp);

}

程序運(yùn)行結(jié)果:

VisualC++10.3.3數(shù)據(jù)塊讀寫函數(shù)fread和fwrite

讀數(shù)據(jù)塊函數(shù)fread調(diào)用的一般形式為

fread(buffer,size,count,fp);

寫數(shù)據(jù)塊函數(shù)fwrite調(diào)用的一般形式為

fwrite(buffer,size,count,fp);

其中:buffer是一個(gè)指針,在fread函數(shù)中表示存放輸入數(shù)據(jù)的首地址,在fwrite函數(shù)中表示存放輸出數(shù)據(jù)的首地址;size表示數(shù)據(jù)塊的字節(jié)數(shù);count表示要讀寫的數(shù)據(jù)塊塊數(shù);fp表示文件指針。

例如:

fread(fa,4,5,fp);

其意義是從fp所指的文件中,每次讀4個(gè)字節(jié)(一個(gè)實(shí)數(shù))送入實(shí)數(shù)組fa中,連續(xù)讀5次,即讀5個(gè)實(shí)數(shù)到fa中。

【例10.4】將幾個(gè)變量中所存放的數(shù)字寫入一個(gè)文件中,然后再?gòu)奈募凶x出并在屏幕上顯示出來(lái)。

程序如下:

#include<stdio.h>

#include<stdlib.h>

voidmain()

{

FILE*fp;

charc=‘a(chǎn)’,c1;

inti=123,i1;

longl=2004184001L,l1;

doubled=4.5678,d1;

/*檢查能否以讀寫方式打開(kāi)或建立文本文件text1.txt*/

if((fp=fopen("test1.txt","wt+"))==NULL)

{

printf(“不能打開(kāi)文件.\n”);

exit(1);

}

/*通過(guò)函數(shù)fwrite將幾個(gè)變量所存放的數(shù)據(jù)寫入文件*/

fwrite(&c,sizeof(char),1,fp);

fwrite(&i,sizeof(int),1,fp);

fwrite(&l,sizeof(long),1,fp);

fwrite(&d,sizeof(double),1,fp);

/*重新定位指針到文件首部*/

rewind(fp);

/*通過(guò)函數(shù)fread將數(shù)據(jù)讀出文件*/

fread(&c1,sizeof(char),1,fp);

fread(&i1,sizeof(int),1,fp);

fread(&l1,sizeof(long),1,fp);

fread(&d1,sizeof(double),1,fp);

/*輸出*/

printf"c1=%c\n",c1);

printf("i1=%d\n",i1);

printf("l1=%ld\n",l1);

printf("d1=%f\n",d1);

fclose(fp);

}

程序運(yùn)行結(jié)果:

c1=a

i1=123

l1=2004184001

d1=4.567800

【例10.5】

將數(shù)組中所存放的字符寫入一個(gè)文本文件中,然后再?gòu)奈募凶x出并在屏幕上顯示出來(lái)。

程序如下:

#include<string.h>

#include<stdio.h>

#include<stdlib.h>

intmain(void)

{

FILE*fp;

charmsg[]=“thisisatest”;

charbuf[20];

/*檢查能否以讀寫方式打開(kāi)或建立文本文件text2.txt*/

if((fp=fopen("test2.txt","wt+"))==NULL)

{

printf(“不能打開(kāi)文件.\n”);

exit(1);

}

/*通過(guò)函數(shù)fwrite將幾個(gè)變量所存放的數(shù)據(jù)寫入文件*/

fwrite(msg,strlen(msg)+1,1,fp);

/*重新定位指針到文件首部*/

rewind(fp);

/*通過(guò)函數(shù)fread將數(shù)據(jù)讀出文件*/

fread(buf,strlen(msg)+1,1,fp);

printf("%s\n",buf);

fclose(fp);

return0;

}程序運(yùn)行結(jié)果:

thisisatest

本例程序定義了一個(gè)字符數(shù)組msg,程序以讀寫方式打開(kāi)文本文件test2.txt,將字符數(shù)組中所存放的字符寫入該文件中,然后把文件內(nèi)部的位置指針移到文件首,讀出文件中的數(shù)據(jù)到字符數(shù)組buf中,并輸出到屏幕上顯示。

【例10.6】從鍵盤錄入兩個(gè)學(xué)生的數(shù)據(jù),把這些數(shù)據(jù)保存到一個(gè)文件中,然后再?gòu)奈募凶x出并在屏幕上顯示出來(lái)。

程序如下:

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

structstu

{

charname[10];

intnum;

intage;

charaddr[15];

};

voidmain()

{

FILE*fp;

structstuboya[2],boyb[2],*pp,*qq;

charch;

inti;

/*pp指向boya,qq指向boyb*/

pp=boya;

qq=boyb;

/*以讀寫方式打開(kāi)二進(jìn)制文件“stu_list.dat”*/

if((fp=fopen(“stu_list.dat”,“wb+”))==NULL)

{

printf("不能打開(kāi)文件,按任意鍵退出!\n");

getch();

exit(1);

}

/*輸入兩個(gè)學(xué)生的數(shù)據(jù)*/

printf("\ninputdata\n");

for(i=0;i<2;i++,pp++)

scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);

/*寫數(shù)據(jù)到文件*/

pp=boya;

fwrite(pp,sizeof(structstu),2,fp);

/*關(guān)閉文件,保證緩沖區(qū)的信息寫入到文件中*/

fclose(fp);

/*再次以只讀形式打開(kāi)文件*/

if((fp=fopen(“stu_list.dat”,“rb”))==NULL)

{

printf(“不能打開(kāi)文件,按任意鍵退出!\n”);

getch();

exit(1);

}

/*把文件內(nèi)部的位置指針移到文件首,讀出兩個(gè)學(xué)生的數(shù)據(jù)后,在屏幕上顯示*/

rewind(fp);

fread(qq,sizeof(structstu),2,fp);

printf(“\n\nname\tnumberageaddr\n”);

for(i=0;i<2;i++,qq++)

{

printf(“%s\t%5d\t”,qq->name,qq->num);

printf(“%7d\t%s\n”,qq->age,qq->addr);

}fclose(fp);

}本例程序定義了一個(gè)結(jié)構(gòu)體stu,說(shuō)明了兩個(gè)結(jié)構(gòu)體數(shù)組boya和boyb以及兩個(gè)結(jié)構(gòu)體指針變量pp和qq。pp指向boya,qq指向boyb。程序以讀寫方式打開(kāi)二進(jìn)制文件“stu_list.dat”,輸入兩個(gè)學(xué)生的數(shù)據(jù)后,將其寫入該文件中,然后把文件內(nèi)部的位置指針移到文件首,讀出兩個(gè)學(xué)生的數(shù)據(jù),并在屏幕上顯示出來(lái)。10.3.4格式化讀寫函數(shù)fscanf和fprintf

fscanf函數(shù)和fprintf函數(shù)與前面使用的scanf函數(shù)和printf函數(shù)的功能相似,都是格式化讀寫函數(shù)。兩者的區(qū)別在于fscanf函數(shù)和fprintf函數(shù)的讀寫對(duì)象不是鍵盤和顯示器,而是磁盤文件。這兩個(gè)函數(shù)的調(diào)用格式分別為

fscanf(文件指針,格式字符串,輸入表列);

fprintf(文件指針,格式字符串,輸出表列);

例如:

fscanf(fp,"%d%s",&i,s);

fprintf(fp,"%d%c",j,ch);

【例10.7】

將文件data1.txt中的4行5列的二維數(shù)組數(shù)據(jù)寫入內(nèi)存,將數(shù)組元素逐個(gè)增1后寫入文件data2.txt中。

程序如下:

#include<stdio.h>

main()

{

FILE*fp1,*fp2;

inti,j,a[4][5];

if((fp1=fopen(“F:\\data1.txt”,“r”))==NULL)

{

printf(“Can’topenfile1\n”);

return;

}

if((fp2=fopen(“F:\\data2.txt”,“w”))==NULL)

{

printf(“Can’topenfile2\n”);

return;

}

for(i=0;i<4;i++)

{

for(j=0;j<5;j++)

{

fscanf(fp1,“%d\t”,&a[i][j]);

a[i][j]+=1;

fprintf(fp2,“%d”,a[i][j]);

}

fprintf(fp2,“\n”);

}

fclose(fp1);

fclose(fp2);

}

【例10.8】

從一給定的文本文件test3.txt中讀出數(shù)據(jù),并將其存放到相應(yīng)的變量中,且在屏幕上顯示出來(lái)。設(shè)文本文件test3.txt中存放的內(nèi)容為

HELLO!1234

若要將上述信息讀出到變量中,則需在程序中定義一個(gè)字符數(shù)組和一個(gè)整型變量,然后用fscanf函數(shù)將文本文件test3.txt中的內(nèi)容以?%s和?%d的格式讀出,并分別存放到字符數(shù)組和整型變量中,最后將字符數(shù)組和變量中的內(nèi)容在屏幕上顯示出來(lái)。程序如下:

#include<stdlib.h>

#include<stdio.h>

#include<conio.h>

voidmain(void)

{

inti;

charstr[20];

FILE*fp;

/*檢查能否以只讀形式打開(kāi)文件test3.txt,如果失敗,則提前退出,結(jié)束程序*/

if((fp=fopen("test3.txt","rt"))==NULL)

{

printf(“不能打開(kāi)文件,按任意鍵退出!\n”);

getch();

exit(1);

}

/*讀數(shù)據(jù)到字符數(shù)組str和變量i中*/

fscanf(fp,“%s%d”,str,&i);

/*輸出到屏幕*/

printf(“%s,%d”,str,i);

fclose(fp);

}

程序運(yùn)行結(jié)果:

HELLO!,1234

【例10.9】從鍵盤錄入兩個(gè)學(xué)生的數(shù)據(jù),把這些數(shù)據(jù)保存到一個(gè)文本文件中,再?gòu)脑撐谋疚募凶x出并在屏幕上顯示出來(lái)(用函數(shù)fscanf和fprintf實(shí)現(xiàn))。

程序如下:

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

structstu

{

charname[10];

intnum;

intage;

charaddr[15];

};

voidmain()

{

FILE*fp;

charch;

inti;

structstuboya[2],boyb[2],*pp,*qq;

/*?pp指向boya,qq指向boyb?*/

pp=boya;

qq=boyb;

/*以讀寫方式打開(kāi)二進(jìn)制文件"stu_list.txt"?*/

if((fp=fopen("stu_list1.txt","w+"))==NULL)

{

printf("不能打開(kāi)文件,按任意鍵退出!\n");

getch();

exit(1);

}

/*輸入兩個(gè)學(xué)生的數(shù)據(jù)*/

printf("\ninputdata\n");

for(i=0;i<2;i++,pp++)

scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);

/*將兩個(gè)學(xué)生的數(shù)據(jù)輸出到文件指針?biāo)赶虻奈募?/

pp=boya;

for(i=0;i<2;i++,pp++)

{

fprintf(fp,“%s%d%d%s\n”,pp->name,pp->num,pp->age,pp->addr);

/*關(guān)閉文件,保證緩沖區(qū)的信息寫入到文件中*/

fclose(fp);

/*再次以只讀形式打開(kāi)文件*/

if((fp=fopen(“stu_list1.txt”,“r”))==NULL)

{

printf(“不能打開(kāi)文件,按任意鍵退出!”);

getch();

exit(1);

}

/*把文件內(nèi)部的位置指針移到文件首,讀出兩個(gè)學(xué)生的數(shù)據(jù)后,在屏幕上顯示*/

rewind(fp);

for(i=0;i<2;i++,qq++)

{

fscanf(fp,“%s%d%d%s\n”,qq->name,&qq->num,&qq->age,qq->addr);

}

printf(“\n\nname\tnumberageaddr\n”);

qq=boyb;

for(i=0;i<2;i++,qq++)

{

printf("%s\t%5d%7d%s\n",qq->name,qq->num,qq->age,qq->addr);

}fclose(fp);

}本程序中函數(shù)fscanf和fprintf每次只能讀寫一個(gè)結(jié)構(gòu)體數(shù)組元素,因此,采用了循環(huán)語(yǔ)句來(lái)讀寫全部數(shù)組元素。還應(yīng)注意,循環(huán)改變了指針變量pp和qq的值,因此,在程序中分別對(duì)它們重新賦予了數(shù)組的首地址。

關(guān)于fprintf函數(shù),在使用時(shí)還應(yīng)注意它向文件輸出的是ASCII碼。特別在輸出數(shù)值時(shí),要輸出的是該數(shù)值的ASCII碼,而不是數(shù)值本身。

10.4文件的隨機(jī)讀寫

10.4.1文件定位

移動(dòng)文件內(nèi)部的位置指針的函數(shù)主要有兩個(gè),即rewind函數(shù)和fseek函數(shù)。

rewind函數(shù)的調(diào)用形式為

rewind(文件指針);

它的功能是把文件內(nèi)部的位置指針移到文件首。

fseek函數(shù)用于改變文件的位置指針,其調(diào)用形式為

fseek(文件指針,位移量,起始點(diǎn));其中:“文件指針”指向被移動(dòng)的文件;“起始點(diǎn)”表示從何處開(kāi)始計(jì)算位移量,規(guī)定的起始點(diǎn)有三種,即文件首、當(dāng)前位置和文件末尾,ANSIC標(biāo)準(zhǔn)指定的起始點(diǎn)的表示符號(hào)如表10-2所示;“位移量”表示以“起始點(diǎn)”為基點(diǎn)移動(dòng)的字節(jié)數(shù),ANSIC和大多數(shù)C版本要求位移量是long型數(shù)據(jù),以便在文件長(zhǎng)度大于64?KB時(shí)不會(huì)出錯(cuò)。當(dāng)用常量表示位移量時(shí),要求加后綴“L”。例如:

fseek(fp,100L,0);

其意義是把位置指針移到離文件首100個(gè)字節(jié)處。

fseek函數(shù)一般用于二進(jìn)制文件。在文本文件中由于要進(jìn)行轉(zhuǎn)換,故往往計(jì)算的位置會(huì)出現(xiàn)錯(cuò)誤。10.4.2隨機(jī)讀寫函數(shù)rewind和fseek

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論