《C語(yǔ)言程序設(shè)計(jì)》課件2第10章_第1頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件2第10章_第2頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件2第10章_第3頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件2第10章_第4頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件2第10章_第5頁(yè)
已閱讀5頁(yè),還剩92頁(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文件的打開(kāi)與關(guān)閉10.3文件的讀/寫(xiě)操作10.4文件檢測(cè)函數(shù)10.5文件的定位10.6程序舉例習(xí)題10

本章學(xué)習(xí)要求:

1.了解文件的分類,了解文件函數(shù)使用時(shí)包含的頭文件。

2.掌握文件類型指針的定義,掌握文件打開(kāi)與關(guān)閉函數(shù)的使用,掌握文件讀/寫(xiě)操作函數(shù)的使用,掌握文件定位函數(shù)的使用,了解文件的檢索。

在前面所學(xué)的程序中,所有的程序都只能在運(yùn)行時(shí)輸入信息以及顯示執(zhí)行的結(jié)果,卻不能將一次輸入多次使用,并且又不能將執(zhí)行的結(jié)果保存起來(lái)以供查看,例如,在創(chuàng)建鏈表的實(shí)例中每次運(yùn)行時(shí)必須輸入一次鏈表中所有元素的信息,無(wú)法保存下來(lái),同時(shí)對(duì)經(jīng)過(guò)處理(如插入元素)的鏈表結(jié)果也無(wú)法保存下來(lái)。并且在運(yùn)行時(shí)如果需要輸入大量的數(shù)據(jù),在程序調(diào)試過(guò)程中也是比較麻煩的。因此,這就需要學(xué)習(xí)使用C語(yǔ)言編程對(duì)文件進(jìn)行訪問(wèn)。

10.1.1文件的概念與分類

文件(file)在程序設(shè)計(jì)中是一個(gè)比較重要的概念。一般來(lái)說(shuō),文件就是指存儲(chǔ)在外存儲(chǔ)器上數(shù)據(jù)的集合。每個(gè)文件都有一個(gè)屬于自己的名字,稱為文件名。文件名是讀取文件的依據(jù),也是標(biāo)識(shí)文件的方式,就像我們?nèi)说拿质敲總€(gè)人的標(biāo)識(shí)一樣。操作系統(tǒng)就是通過(guò)文件名對(duì)各種文件進(jìn)行存取和處理的,即“按名存取”。10.1文件概述

1.文件的分類

根據(jù)文件中數(shù)據(jù)的存儲(chǔ)形式,一般可以將文件分成文本文件和二進(jìn)制文件兩種。

文本文件又稱為ASCII碼文件。在這種文件中是以字符為單位進(jìn)行存放的,每個(gè)字節(jié)存放一個(gè)字符的ASCII碼值(取值范圍0~127)。例如,一個(gè)整數(shù)3267,它是由4個(gè)數(shù)字字符組成,在文本文件中需要用4個(gè)字節(jié)來(lái)存放4個(gè)數(shù)字字符,如圖10.1(a)所示。二進(jìn)制文件是以二進(jìn)制位(bit)為單位的,數(shù)據(jù)按其在內(nèi)存中的存儲(chǔ)形式直接存放到文件中,即在二進(jìn)制文件中,數(shù)據(jù)與該數(shù)據(jù)的二進(jìn)制形式是一致的,其中的一個(gè)字節(jié)并不代表一個(gè)字符。例如,同樣的一個(gè)整數(shù)3267,化成二進(jìn)制數(shù)為110011000011,因此,它在二進(jìn)制文件中只需要占2個(gè)字節(jié),如圖10.1(b)所示。

圖10.1整數(shù)3267在文件中的存儲(chǔ)形式

2.緩沖文件系統(tǒng)

C語(yǔ)言編譯系統(tǒng)對(duì)文件的處理有兩種方式,分別采用緩沖文件系統(tǒng)方式與非緩沖文件系統(tǒng)方式進(jìn)行。

緩沖文件系統(tǒng)是指系統(tǒng)自動(dòng)地為正在被使用的文件在內(nèi)存中開(kāi)辟一個(gè)緩沖區(qū)。當(dāng)需要向外存中的文件輸出數(shù)據(jù)時(shí),必須先將數(shù)據(jù)送到為該文件開(kāi)辟的緩沖區(qū)中,當(dāng)緩沖區(qū)充滿后才一起送到外存中。當(dāng)需要對(duì)外存中的文件讀入數(shù)據(jù)時(shí),也先從外存一次將一批數(shù)據(jù)讀入緩沖區(qū)(將緩沖區(qū)充滿或?qū)⑺璧臄?shù)據(jù)全部讀入),然后再?gòu)木彌_區(qū)中將數(shù)據(jù)逐個(gè)讀入。在這種文件系統(tǒng)中,對(duì)文件的輸入/輸出是通過(guò)為該文件開(kāi)辟的緩沖區(qū)進(jìn)行的。緩沖文件系統(tǒng)又稱為高級(jí)文件系統(tǒng)。非緩沖文件系統(tǒng)是指系統(tǒng)不自動(dòng)為文件開(kāi)辟緩沖區(qū),而是由用戶程序自己為文件設(shè)定緩沖區(qū)。非緩沖文件系統(tǒng)又稱為低級(jí)文件系統(tǒng)。

ANSIC標(biāo)準(zhǔn)采用的是緩沖文件系統(tǒng),對(duì)文件的操作都通過(guò)標(biāo)準(zhǔn)庫(kù)函數(shù)來(lái)實(shí)現(xiàn)。

3.文件操作的步驟

程序?qū)ξ募M(jìn)行操作時(shí),一般要經(jīng)過(guò)以下三個(gè)步驟:

(1)打開(kāi)文件。用標(biāo)準(zhǔn)庫(kù)函數(shù)fopen()打開(kāi)文件,它通知編譯系統(tǒng)三個(gè)信息:需要打開(kāi)的文件名;使用文件的方式(讀還是寫(xiě)等);使用的文件指針。編譯系統(tǒng)將需要的文件調(diào)入內(nèi)存緩沖區(qū)。

(2)文件讀寫(xiě)。用文件輸入或輸出函數(shù)對(duì)文件進(jìn)行讀寫(xiě),這些輸入或輸出函數(shù)與前面介紹的標(biāo)準(zhǔn)輸入與輸出函數(shù)在功能上有相似之處,但在使用上又不相同。

(3)關(guān)閉文件。文件讀寫(xiě)完畢,用標(biāo)準(zhǔn)庫(kù)函數(shù)fclose()關(guān)閉文件。它的主要功能是將數(shù)據(jù)從內(nèi)存真正寫(xiě)入磁盤(pán)(否則數(shù)據(jù)可能還在內(nèi)存緩沖區(qū)中),切斷文件指針與文件名之間的聯(lián)系,釋放文件指針。如果文件使用完后不關(guān)閉可能會(huì)造成數(shù)據(jù)的丟失。因此,我們?cè)谑褂梦募r(shí),如果文件不再使用時(shí),及時(shí)關(guān)閉文件是一個(gè)好習(xí)慣。當(dāng)然,當(dāng)程序正常運(yùn)行結(jié)束時(shí),系統(tǒng)也會(huì)自動(dòng)關(guān)閉所有已經(jīng)打開(kāi)的文件。10.1.2文件類型指針

在進(jìn)行文件操作時(shí),要用文件指針。文件指針用來(lái)指向緩沖區(qū)中文件當(dāng)前操作的位置,當(dāng)文件指針與某個(gè)文件連接后,用戶就通過(guò)文件指針而不是文件名來(lái)存取文件。文件指針是由系統(tǒng)在頭文件stdio.h中定義的結(jié)構(gòu)類型,類型名為FILE,其成員分別用來(lái)存放文件名、文件狀態(tài)標(biāo)志及緩沖區(qū)大小等信息。有興趣的讀者可以到TurboC編譯系統(tǒng)的include文件夾中參閱stdio.h文件內(nèi)容,通常情況下不用了解其中的細(xì)節(jié),只要能用類型名FILE來(lái)定義文件指針就可以了。定義文件指針的一般形式如下:

FILE*指針變量名表列;

其中,指針變量名表列是指可以一次定義一個(gè)到多個(gè)文件指針,每個(gè)文件指針可以用于存放一個(gè)文件緩沖區(qū)的首地址。例如:

FILE*fp1,*fp2;

定義了名為fp1和fp2的兩個(gè)文件指針,可以由fopen()函數(shù)將它們分別指向一個(gè)文件。

注意:一個(gè)文件指針只能指向一個(gè)文件。如果想打開(kāi)幾個(gè)文件,就應(yīng)該有幾個(gè)文件指針。

10.2.1文件的打開(kāi)

打開(kāi)文件要用庫(kù)函數(shù)fopen(),其調(diào)用的一般格式如下:

FILE*fp;/*也可以用其他文件指針變量名,這里用fp作為文件指針變量名*/

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

從上述格式可以看出,要想打開(kāi)一個(gè)文件,必須先為該文件定義一個(gè)文件類型指針,然后才能用fopen()函數(shù)打開(kāi)文件。10.2文件的打開(kāi)與關(guān)閉

fopen()函數(shù)在調(diào)用時(shí)有兩個(gè)參數(shù):“文件名”與“文件使用方式”,它們都是字符串。其中“文件名”是要打開(kāi)的文件的名字,當(dāng)然可以帶文件路徑,但在文件路徑中的“\”必須使用轉(zhuǎn)義字符,例如:fopen("c:\\tc20\\t.txt","w")就是正確打開(kāi)帶路徑文件的方式;“文件使用方式”規(guī)定了打開(kāi)文件的目的,如表10.1所示。

fopen()函數(shù)的主要功能是為需要打開(kāi)的文件分配一個(gè)緩沖區(qū),并返回該緩沖區(qū)的首地址。如果文件打開(kāi)不成功(可能找不到對(duì)應(yīng)的文件),則返回NULL(或0),NULL是一個(gè)空指針值,也是由stdio.h頭文件定義的。

表10.1文件使用方式為確保文件的正常操作,有必要在程序中檢測(cè)文件是否正常打開(kāi),即打開(kāi)文件的操作是否成功。常用下面的程序段來(lái)打開(kāi)文件:

if((fp=fopen("filename","w"))==NULL)

{printf("Cannotopenfile!\n");exit(1);}

這樣,當(dāng)文件不能正常打開(kāi)時(shí),屏幕提示“Cannotopenfile!”,程序運(yùn)行終止,返回操作系統(tǒng)。exit()函數(shù)的功能是終止程序運(yùn)行,關(guān)閉文件并返回操作系統(tǒng),它也是在stdio.h頭文件中定義的;如果文件打開(kāi)成功,程序就可以繼續(xù)執(zhí)行。10.2.2文件的關(guān)閉

對(duì)文件操作完成后,必須關(guān)閉文件,以保證本次文件操作有效。文件關(guān)閉使用fclose()標(biāo)準(zhǔn)庫(kù)函數(shù),其一般形式如下:

fclose(文件指針變量名);

例如,要關(guān)閉前面的文件指針變量fp指向的文件,可以使用fclose(fp);來(lái)關(guān)閉。若關(guān)閉成功則返回0,否則返回EOF(即-1)??梢杂胒error()函數(shù)來(lái)測(cè)試。

10.3.1文件讀函數(shù)

對(duì)文件進(jìn)行讀操作,是指從外存儲(chǔ)器的文件中向程序輸入數(shù)據(jù)。

在C語(yǔ)言中,讀文件的函數(shù)主要有:fgetc()、fread()、fscanf()。

10.3文件的讀/寫(xiě)操作

1.?fgetc()函數(shù)

fgetc()函數(shù)的功能是:從指定的文件讀入一個(gè)字符。其一般格式如下:

charc;

c=fgetc(fp);

其中:fp是已經(jīng)定義過(guò)的文件指針變量,該函數(shù)從fp指向的文件中的當(dāng)前位置讀取一個(gè)字符,并將該字符的ASCII碼值保存到字符變量c中。

當(dāng)讀到文件末尾或讀取出錯(cuò)時(shí),該函數(shù)返回一個(gè)文件結(jié)束標(biāo)志EOF(-1)。因?yàn)樽址腁SCII碼為非負(fù)值,所以可以用EOF(-1)作為結(jié)束標(biāo)志,即當(dāng)讀入的字符值等于EOF時(shí)表示文件已經(jīng)結(jié)束。

2.?fgets()函數(shù)

fgets()函數(shù)的功能是:從指定的文件中讀出一個(gè)字符串,其一般格式如下:

fgets(s,n,fp);

其中:s可以是字符型數(shù)組名或字符串指針,n是指定讀入的字符個(gè)數(shù),fp是文件指針變量。使用上面格式最多從文件中讀出n-1個(gè)字符,并將讀出的字符串存入指針s。當(dāng)函數(shù)讀取的字符達(dá)到指定的個(gè)數(shù)(n-1個(gè)),或者接收到換行符,再或者接收到文件結(jié)束標(biāo)志EOF時(shí),將在讀取的字符后面自動(dòng)添加一個(gè)字符串結(jié)束標(biāo)志'\0';若有換行符,則將換行符保留在'\0'字符之后;若有EOF,則不保留文件結(jié)束標(biāo)志EOF。

該函數(shù)如果執(zhí)行成功,返回讀取的字符串指針;如果失敗,則返回空指針,此時(shí),s中的內(nèi)容不確定。

3.?fread()函數(shù)

fread()函數(shù)的功能是:從指定的文件中讀入一組數(shù)據(jù)。其一般格式如下:

fread(buffer,size,count,fp);

其中:buffer表示存放讀入數(shù)據(jù)的內(nèi)存首地址,比如數(shù)組名;size表示每個(gè)數(shù)據(jù)項(xiàng)的字節(jié)數(shù);count表示數(shù)據(jù)項(xiàng)個(gè)數(shù);fp表示文件指針變量。

本函數(shù)是從fp指向的文件中,一次讀出長(zhǎng)度為size字節(jié)的count個(gè)數(shù)據(jù)項(xiàng),然后存放在buffer中。在讀出過(guò)程中,自動(dòng)把文件中的回車符、表示制表符和換行符的轉(zhuǎn)義序列轉(zhuǎn)換成換行符。該函數(shù)如果執(zhí)行成功,則返回實(shí)際讀出的數(shù)據(jù)項(xiàng)個(gè)數(shù);如果讀出數(shù)據(jù)項(xiàng)比調(diào)用中所需數(shù)據(jù)項(xiàng)少,則出錯(cuò)。關(guān)于出錯(cuò)的判斷見(jiàn)下一節(jié)的介紹。

4.?fscanf()函數(shù)

fscanf()函數(shù)的功能是:從指定的文件中格式化讀取數(shù)據(jù)。其一般格式如下:

fscanf(文件指針變量,格式控制串,地址表);

本函數(shù)與格式輸入函數(shù)scanf()很相似,其中,“格式控制串”和“地址表”的用法與scanf()函數(shù)相同。它們的區(qū)別就在于,scanf()函數(shù)是從鍵盤(pán)輸入數(shù)據(jù),而fscanf()函數(shù)是從文件讀入數(shù)據(jù),因此在fscanf()函數(shù)參數(shù)中多了一個(gè)文件指針,用于指出從哪個(gè)文件讀入數(shù)據(jù)。該函數(shù)如果執(zhí)行成功,則返回讀取項(xiàng)目的個(gè)數(shù);如果遇到文件末尾,則返回EOF;如果賦值失敗,則返回0。10.3.2文件寫(xiě)函數(shù)

對(duì)文件進(jìn)行寫(xiě)操作,就是將程序中處理好的數(shù)據(jù)寫(xiě)到指定的文件中。

在C語(yǔ)言中,讀文件的函數(shù)主要有fputc()、fputs()、fwrite()和fprintf()。

1.?fputc()函數(shù)

fputc()函數(shù)的功能是:將一個(gè)字符寫(xiě)到指定的文件中。其一般格式如下:

fputc(c,fp);

該函數(shù)將字符變量c中的字符碼值寫(xiě)入fp指向的文件當(dāng)前位置。如果寫(xiě)成功,則返回寫(xiě)入文件的字符,否則返回EOF。

例10.1

先從鍵盤(pán)輸入一串字符寫(xiě)入文件t1.txt中(當(dāng)輸入“#”時(shí)結(jié)束),并將文件t1.txt中的信息復(fù)制到文件t2.txt,最后在屏幕上顯示出文件t2.txt中的內(nèi)容。

問(wèn)題分析:本例可以分成三步進(jìn)行,第一步:從鍵盤(pán)輸入一串字符寫(xiě)入文件t1.txt,在進(jìn)行第二步前,必須將文件t1.txt的文件指針fp1復(fù)位到文件開(kāi)頭(可以使用rewind()函數(shù)或?qū)⑽募P(guān)閉,再打開(kāi));第二步:從文件t1.txt將內(nèi)容復(fù)制到文件t2.txt中,再將文件t2.txt的文件指針fp2復(fù)位到文件開(kāi)頭;第三步:將文件t2.txt的內(nèi)容顯示到屏幕上。程序如下:

#include<stdio.h>

main()

{charc;

FILE*fp1,*fp2;

if((fp1=fopen("t1.txt","w+"))==NULL)

{printf("Cannotopent1.txt!\n");exit(1);}

if((fp2=fopen("t2.txt","w+"))==NULL)

{printf("Cannotopent2.txt!\n");exit(1);}

while((c=getchar())!='#')/*從鍵盤(pán)輸入字符存入文件t1.txt中*/

fputc(c,fp1);

rewind(fp1);/*將文件t1.txt的文件指針移到文件開(kāi)頭*/

while((c=fgetc(fp1))!=EOF) /*將文件t1.txt的內(nèi)容復(fù)制到文 件t2.txt*/

fputc(c,fp2);

rewind(fp2);

while((c=fgetc(fp2))!=EOF) /*將文件t2.txt中的內(nèi)容輸出到 屏幕上*/

putchar(c);

fclose(fp1);fclose(fp2);

}

2.?fputs()函數(shù)

fputs()函數(shù)的功能是:將一個(gè)字符串寫(xiě)入指定的文件中。其一般格式如下:

fputs(s,fp);

其中,s可以是字符型數(shù)組名或字符串指針,fp是文件指針變量。

使用上面格式可以將字符串寫(xiě)入由fp指向的文件中,字符串結(jié)束標(biāo)志'\0'字符不寫(xiě)入。

該函數(shù)如果執(zhí)行成功,則返回寫(xiě)入的最后一個(gè)字符;如果失敗,則返回EOF。

例10.2

將字符串寫(xiě)入文件和讀出文件。

#include<stdio.h>

#include<string.h>

main()

{charstr[80],str1[80];

FILE*fp;

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

{printf("Cannotopent.txt!\n");exit(1);}

gets(str);

fputs(str,fp); /*將字符串寫(xiě)入文件中*/

rewind(fp); /*將文件指針復(fù)位到文件開(kāi)頭*/

fgets(str1,strlen(str)+1,fp); /*從文件中將字符串讀出*/

puts(str1); /*輸出到屏幕上*/

fclose(fp);

}

3.?fwrite()函數(shù)

fwrite()函數(shù)的功能是:將一組數(shù)據(jù)寫(xiě)到指定的文件中。其一般格式如下:

fwrite(buffer,size,count,fp);

其中:buffer 存放讀入數(shù)據(jù)的內(nèi)存首地址,比如數(shù)組名

size每個(gè)數(shù)據(jù)項(xiàng)的字節(jié)數(shù)

count數(shù)據(jù)項(xiàng)個(gè)數(shù)

fp文件指針變量本函數(shù)是向fp指向的文件中一次寫(xiě)入一個(gè)由buffer指向的數(shù)據(jù)塊,該數(shù)據(jù)塊共有count個(gè)數(shù)據(jù)項(xiàng),每個(gè)數(shù)據(jù)項(xiàng)有size個(gè)字節(jié)。

該函數(shù)如果執(zhí)行成功,則返回實(shí)際寫(xiě)入的數(shù)據(jù)項(xiàng)個(gè)數(shù);如果寫(xiě)入的數(shù)據(jù)項(xiàng)比調(diào)用中所需數(shù)據(jù)項(xiàng)少,則出錯(cuò)。關(guān)于出錯(cuò)的判斷見(jiàn)下一節(jié)的介紹。

例10.3

記錄型信息的訪問(wèn)。

在學(xué)習(xí)結(jié)構(gòu)體的時(shí)候我們就知道,真實(shí)的信息數(shù)據(jù)通常都是以記錄形式存在,而這種記錄可以通過(guò)結(jié)構(gòu)體來(lái)實(shí)現(xiàn),本例就是實(shí)現(xiàn)文件中記錄型信息的訪問(wèn)。

程序如下:

#include<stdio.h>

voidput_in(); /*聲明函數(shù)*/

voidget_out(); /*聲明函數(shù)*/

structstudent /*定義結(jié)構(gòu)體類型*/

{charname[10];

intscore;

}

main()

{

printf("Recorddataaccess!\n\n");

put_in(); /*調(diào)用文件寫(xiě)入函數(shù)*/

get_out(); /*調(diào)用文件讀出函數(shù)*/

}

/*寫(xiě)入文件函數(shù)*/

voidput_in()

{FILE*fp;

structstudentstud[]={{"張三",67},{"李四",78},{"王五",89},{"田三",92},{"趙七",54},

{"劉八",48}};

if((fp=fopen("stud.dat","wb"))==NULL)

{printf("Cannotcreatstud.dat!\n");exit(1);}

fwrite(stud,sizeof(structstudent),6,fp); /*將結(jié)構(gòu)體數(shù)組寫(xiě)入 文件中*/

fclose(fp);

printf("OK!\n");

}

/*讀出文件數(shù)據(jù)函數(shù)*/

voidget_out()

{FILE*fp;

structstudentstud[6];

inti;

if((fp=fopen("stud.dat","rb"))==NULL)

{printf("Cannotopenstud.dat!\n");exit(1);}

fread(stud,sizeof(structstudent),6,fp); /*從文件中讀出數(shù)據(jù) 放入結(jié)構(gòu)體數(shù)組*/

printf("姓名\t成績(jī)\n");

printf("----\t----\n");

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

printf("%s\t%d\n",stud[i].name,stud[i].score);

printf("\n");

fclose(fp);

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

Recorddataaccess!

OK!

姓名成績(jī)

--------

張三67

李四78

王五89

田三92

趙七54

劉八48

4.?fprintf()函數(shù)

fprintf()函數(shù)的功能是:向指定的文件中格式化寫(xiě)入數(shù)據(jù)。其一般格式如下:

fprintf(文件指針變量,格式控制串,輸出表);

其中:輸出表是由表達(dá)式組成的表列。

本函數(shù)與格式輸出函數(shù)printf()很相似,其中“格式控制串”和“輸出表”的用法與printf()函數(shù)相同。它們的區(qū)別就在于,printf()函數(shù)是將數(shù)據(jù)輸出到顯示屏幕上,而fprintf()函數(shù)是將數(shù)據(jù)輸出到文件中,因此在fprintf()函數(shù)參數(shù)中多了一個(gè)文件指針,用于指出將數(shù)據(jù)輸出到哪個(gè)文件中。

fprintf()函數(shù)與fscanf()函數(shù)是對(duì)應(yīng)的,最好結(jié)合使用。即使用fprintf()函數(shù)向文件中格式化寫(xiě)入數(shù)據(jù),而用fscanf()函數(shù)將數(shù)據(jù)從文件中格式化讀出。因此,在使用fprintf()函數(shù)時(shí),其格式應(yīng)與用fscanf()函數(shù)將數(shù)據(jù)從該文件讀出時(shí)的格式一致,否則會(huì)導(dǎo)致讀/寫(xiě)錯(cuò)誤。

該函數(shù)如果執(zhí)行成功,則返回實(shí)際寫(xiě)入文件的字符個(gè)數(shù);若出現(xiàn)錯(cuò)誤,則返回負(fù)數(shù)。

例10.4

從鍵盤(pán)輸入一個(gè)整數(shù)、一個(gè)實(shí)數(shù)、一個(gè)字符,將其寫(xiě)入文件ttt.txt,再將其從文件中讀出,輸出到屏幕上。

問(wèn)題分析:本例可以先分別定義一個(gè)整型、實(shí)型、字符型變量,再?gòu)逆I盤(pán)各輸入一個(gè)值,使用fprintf()函數(shù)將三個(gè)值按相應(yīng)格式寫(xiě)入到文件ttt.txt中,再使用fscanf()函數(shù)從文件中讀出,并使用格式輸出printf()函數(shù)輸出到屏幕上。程序如下:

#include<stdio.h>

main()

{inta,a1;floatb,b1;charc,c1;

FILE*fp;

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

{printf("Cannotopenfile!\n");exit(1);}

printf("Pleasea,b,c:");

scanf("%d,%f,%c",&a,&b,&c);

fprintf(fp,"%d,%f,%c",a,b,c);

/*rewind(fp);*//*將文件指針置于文件開(kāi)頭位置*/

fclose(fp);

fp=fopen("ttt.txt","r");

fscanf(fp,"%d,%f,%c",&a1,&b1,&c1);

printf("%d,%f,%c\n",a,b,c);

printf("%d,%f,%c\n",a1,b1,c1);

}注意:程序中將三個(gè)數(shù)寫(xiě)入文件后,將文件關(guān)閉,再以只讀的方式打開(kāi),并且重新格式化讀出數(shù)據(jù)。如果不這樣做(寫(xiě)入文件后馬上讀出)就會(huì)造成讀出的數(shù)據(jù)不對(duì),為什么呢?因?yàn)槲覀兿蛭募袑?xiě)完數(shù)據(jù)后,文件指針此時(shí)停留在文件尾,如果馬上讀取就會(huì)從文件指針當(dāng)前位置向后讀,顯然讀取的數(shù)據(jù)不對(duì)。要想解決這樣的問(wèn)題,可以使用兩種方法:①使用rewind(fp)函數(shù)將文件指針移到文件開(kāi)頭位置;②先將文件關(guān)閉,再以只讀的方式打開(kāi)。

文件檢測(cè)函數(shù)用于檢測(cè)文件指針是否到文件末尾,或文件讀/寫(xiě)操作中是否出現(xiàn)錯(cuò)誤等情況,以便能正確地進(jìn)行文件的存取。10.4文件檢測(cè)函數(shù)

1.?feof()函數(shù)

feof()函數(shù)用于二進(jìn)制文件結(jié)束檢測(cè)。對(duì)于文本文件,通??捎肊OF作為結(jié)束標(biāo)志,EOF的值為-1,因?yàn)槿魏蜛SCII碼都不可能取負(fù)值,所以它在文本文件中不會(huì)產(chǎn)生沖突。而對(duì)于二進(jìn)制文件,-1可能是字節(jié)數(shù)據(jù)的值,所以EOF不能作為二進(jìn)制文件的結(jié)束標(biāo)志。因此,二進(jìn)制文件結(jié)束的判斷只能使用feof()函數(shù)來(lái)完成,它的一般格式如下:

feof(fp);

其中:fp是已定義過(guò)的文件指針。該函數(shù)用于檢測(cè)文件是否結(jié)束,如果結(jié)束則返回非0值;否則返回0值。

2.?ferror()函數(shù)

ferror()函數(shù)用于檢測(cè)文件讀/寫(xiě)時(shí)是否發(fā)生錯(cuò)誤,其一般格式如下:

ferror(fp);

其中:fp是已定義過(guò)的文件指針。如果在文件讀/寫(xiě)過(guò)程中未發(fā)生錯(cuò)誤,則返回0值;否則,返回非0值。

3.?clearerr()函數(shù)

clearerr函數(shù)用于將文件的出錯(cuò)標(biāo)志和文件結(jié)束標(biāo)志置0。當(dāng)調(diào)用的文件輸入或輸出函數(shù)出錯(cuò)時(shí),ferror()函數(shù)給出非0的標(biāo)志,并一直保持此非0值,直到使用clearerr()函數(shù)或rewind()函數(shù)時(shí)才重新置0。其一般格式如下:

clearerr(fp);

其中:fp是已定義過(guò)的文件指針。使用clearerr()函數(shù)可以及時(shí)清除出錯(cuò)標(biāo)志。

為了正確地對(duì)文件進(jìn)行讀/寫(xiě)操作,在一個(gè)文件被打開(kāi)后,系統(tǒng)就為該文件設(shè)置一個(gè)讀/寫(xiě)指針,用于指示當(dāng)前讀/寫(xiě)的位置。當(dāng)進(jìn)行一次讀/寫(xiě)操作后,文件的讀/寫(xiě)指針位置自動(dòng)向后移動(dòng)。每次打開(kāi)文件總是從文件開(kāi)始位置進(jìn)行讀/寫(xiě)操作的,但有時(shí)文件經(jīng)過(guò)讀/寫(xiě)后,還需要回到文件頭;或有時(shí)需要直接修改文件中的某個(gè)部分內(nèi)容。對(duì)于這樣的情況,最好使用文件的定位函數(shù)。10.5文?件?的?定?位文件的定位函數(shù)主要有以下幾種。

1.?rewind()函數(shù)

有時(shí)文件經(jīng)過(guò)讀/寫(xiě)后,還需要回到文件頭以便訪問(wèn),而此時(shí)卻因?yàn)榍懊娴奈募僮魇刮募羔樢苿?dòng)到文件的其他位置,這時(shí)就需要重置文件指針使其回到文件頭。

rewind()函數(shù)的功能是:將文件指針重置于文件開(kāi)頭位置。其一般格式如下:

rewind(fp);

其中:fp是已定義過(guò)的文件指針。

2.?fseek()函數(shù)

fseek()函數(shù)的主要功能是:將文件的讀/寫(xiě)指針移動(dòng)到指定的位置。其一般格式如下:

fseek(fp,偏移量,起始位置);

其中:fp是已定義過(guò)的文件指針;起始位置是指移動(dòng)文件讀/寫(xiě)指針的參考位置,它有以下三個(gè)值:

SEEK_SET或0

表示文件開(kāi)頭

SEEK_CUR或1表示當(dāng)前讀/寫(xiě)的位置

SEEK_END或2表示文件末尾偏移量是相對(duì)“起始位置”的偏移字節(jié)數(shù),它要求是long型數(shù)據(jù)(可正可負(fù))。例如:

fseek(fp,100L,1);/*將文件指針從當(dāng)前讀/寫(xiě)位置向文件尾方向 移動(dòng)100個(gè)字節(jié)*/

fseek(fp,-10L,2);/*將文件指針從文件尾向文件頭方向移動(dòng)10 個(gè)字節(jié)*/

fseek(fp,100L,0);/*將文件指針從文件頭向文件尾方向移動(dòng)100 個(gè)字節(jié)*/

fseek()函數(shù)的意義在于:可以把文件指針移到文件的任何位置,實(shí)現(xiàn)對(duì)文件的隨機(jī)讀/寫(xiě)操作。

3.?ftell()函數(shù)

在程序執(zhí)行中,如果想要獲取文件指針的當(dāng)前位置,可以使用ftell()函數(shù)來(lái)完成。

ftell()函數(shù)的功能是:返回文件的當(dāng)前讀/寫(xiě)位置。其一般格式如下:

ftell(fp);

其中:fp是已定義過(guò)的文件指針。該函數(shù)如果執(zhí)行成功,則返回相對(duì)于文件頭的位移量(字節(jié)數(shù)),否則返回-1L。

例10.5

設(shè)有結(jié)構(gòu)體數(shù)組定義如下:

structstudent

{charname[10];

charsection[20];

intage,score;

}st[]={{"王小二","商學(xué)院",23,78},{"阮小二","理學(xué)院",22,80},{"阮小七",

"信息院",

21,65},{"孫二","人文學(xué)院",23,58},{"張三","農(nóng)學(xué)院",22,92}};10.6程序舉例編寫(xiě)如下程序:首先建立名為my_stud.dat的二進(jìn)制文件,用于保存給結(jié)構(gòu)體數(shù)組所賦的值;然后對(duì)上述學(xué)生數(shù)據(jù)按成績(jī)排序(降序),并將排完序的數(shù)據(jù)添加到原文件,并顯示到屏幕上。程序如下:

#include<stdio.h>

structstudent

{charname[10];

charsection[20];

intage,score;

}st[10]={{"王小二","商學(xué)院",23,78},{"阮小二","理學(xué)院",22,80},{"阮小七","信息院",

21,65},{"孫二","人文學(xué)院",23,58},{"張三","農(nóng)學(xué)院",22,92}},work;

voidsort()

{inti,j;

FILE*fp;

if((fp=fopen("my_stud.dat","rb"))==NULL)

{printf("Filecannotopen!\n");exit(1);}

for(i=0;i<5;i++) /*將數(shù)據(jù)從文件中讀出*/

fread(&st[i],sizeof(structstudent),1,fp);

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

for(j=i+1;j<5;j++)

if(st[i].score<st[j].score)

{work=st[i];

st[i]=st[j];

st[j]=work;

}

fclose(fp);

fp=fopen("my_stud.dat","ab");

fseek(fp,0,SEEK_END);

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

fwrite(&st[i],sizeof(structstudent),1,fp);

fclose(fp);

}

main()

{intk;

FILE*fp;

if((fp=fopen("my_stud.dat","wb"))==NULL)

{printf("Filecannotopen!\n");exit(1);}

for(k=0;k<5;k++) /*將數(shù)據(jù)寫(xiě)入文件*/

fwrite(&st[k],sizeof(structstudent),1,fp);

fclose(fp);

sort();

fp=fopen("my_stud.dat","rb");

clrscr();

printf("-----------排序前數(shù)據(jù)------------\n");

for(k=0;k<10;k++) /*將數(shù)據(jù)從文件中讀出*/

{fread(&st[k],sizeof(structstudent),1,fp);

printf("%s,%s,%d,%d\n",st[k].name,st[k].section,st[k].age,st[k].score);

if(k==4)

printf("-----------排序后數(shù)據(jù)-------------\n");

}

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

-----------排序前數(shù)據(jù)-------------

王小二,商學(xué)院,23,78

阮小二,理學(xué)院,22,80

阮小七,信息院,21,65

孫二,人文學(xué)院,23,58

張三,農(nóng)學(xué)院,22,92

-----------排序后數(shù)據(jù)-------------

張三,農(nóng)學(xué)院,22,92

阮小二,理學(xué)院,22,80

王小二,商學(xué)院,23,78

阮小七,信息院,21,65

孫二,人文學(xué)院,23,58

例10.6

建立my_stud.dat文件,將初始化的結(jié)構(gòu)化數(shù)組中的數(shù)據(jù)放入該文件中,并查詢出成績(jī)不及格的學(xué)生和成績(jī)優(yōu)良(>=80分)的學(xué)生。

程序如下:

/*成績(jī)查詢程序*/

#include<stdio.h>

structstudent

{charname[10];

charsection[20];

intage,score;

}st[]={{"王小二","商學(xué)院",23,78},{"阮小二","理學(xué)院",22,80},{"阮小七","信息院",21,65},

{"孫二","人文學(xué)院",23,58},{"張三","農(nóng)學(xué)院",22,92}};

main()

{FILE*fp;intk;

printf("成績(jī)查詢\n\n");

if((fp=fopen("my_stud.dat","wb"))==NULL)

{printf("Filecannotopen!\n");exit(1);}

for(k=0;k<5;k++) /*將數(shù)據(jù)寫(xiě)入文件中*/

fwrite(&st[k],sizeof(structstudent),1,fp);

fclose(fp);

if((fp=fopen("my_stud.dat","rb"))==NULL)

{printf("Filecannotopen!\n");exit(1);}

for(k=0;k<5;k++) /*將數(shù)據(jù)從文件中讀出*/

fread(&st[k],sizeof(structstudent),1,fp);

k=0;printf("不及格者姓名\t成績(jī)\n");

while(!feof(fp))

{fseek(fp,(long)sizeof(structstudent)*k,SEEK_SET);

fread(&st,sizeof(structstudent),1,fp);

if(st[k].score<60&&!feof(fp))

printf("%s\t\t%d\n",st[k].name,st[k].score);

k++;

}

rewind(fp);

k=0;printf("優(yōu)良者姓名\t成績(jī)\n");

while(!feof(fp))

{fseek(fp,(long)sizeof(structstudent)*k,SEEK_SET);

fread(&st,sizeof(structstudent),1,fp);

if(st[k].score>=80&&!feof(fp))

printf("%s\t\t%d\n",st[k].name,st[k].score);

k++;

}

fclose(fp);

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

成績(jī)查詢

不及格者姓名成績(jī)

孫二 58

優(yōu)良者姓名成績(jī)

阮小二 80

張三 92

例10.7

文本文件查看程序。

請(qǐng)完成類似DOS下type命令的功能,用于查看指定文本文件的內(nèi)容。查看的格式如:L10-07<文本文件名>。

/*L10-07.c*/

/*文本文件查看程序L10-07.c*/

#include<stdio.h>

main(intargc,char*argv[])

/*變量argc用來(lái)檢測(cè)輸入的參數(shù)項(xiàng) 目個(gè)數(shù),argv[]為一個(gè)字符指針數(shù)組,用于存放參數(shù)*/

{FILE*fp;

charletter[256];/*從文件中得到的數(shù)據(jù)將要存入的數(shù)組*/

intc,i;

if(argc<2)

{printf("命令的格式應(yīng)是:L10-07<文件名>\n");exit(1);}

if((fp=fopen(argv[1],"r"))==NULL)

{printf("不能打開(kāi)%s文件!\n",argv[1]);exit(1);}

do

{i=0;

while((c=fgetc(fp))!=EOF) /*從文件中讀出字符,并放到 字符數(shù)組letter中*/

{letter[i]=c;i++;

if(c=='\n')break;

}

letter[i]='\0';

printf("%s",letter); /*輸入字符數(shù)組*/

}while(c!=EOF);

fclose(fp);

}

說(shuō)明:先將程序編譯成可執(zhí)行文件L10-07.exe,再在DOS提示符下輸入以下命令行:

L10-07L10-07.c

這樣可以得到本例的源程序文件。

一、選擇題

1.

C語(yǔ)言文件的組成成分是()。

A.記錄B.數(shù)據(jù)行C.數(shù)據(jù)塊D.字符(字節(jié))系列

2.

C語(yǔ)言中,數(shù)據(jù)文件的存取方式為()。

A.只能順序存取

B.只能隨機(jī)存取(也叫直接存取)

C.可以順序存取和隨機(jī)存取

D.只能從文件的開(kāi)頭進(jìn)行存取習(xí)題10

3.以C語(yǔ)言中,用“a”方式打開(kāi)一個(gè)已含有10個(gè)字符的文本文件,并寫(xiě)入了8個(gè)新字符,則該文件中存放的字符是()。

A.新寫(xiě)入的8個(gè)字符

B.新寫(xiě)入的8個(gè)字符覆蓋原有字符中的前8個(gè)字符,保留原有的后2個(gè)字符

C.原有的10個(gè)字符在前,新寫(xiě)入的8個(gè)字符在后

D.新寫(xiě)入的8個(gè)字符在前,原有的10個(gè)字符在后

4.當(dāng)已存在一個(gè)t.txt文件時(shí),執(zhí)行函數(shù)fopen("t.txt","r+")的功能是()。

A.打開(kāi)t.txt文件,清除原有內(nèi)容

B.打開(kāi)t.txt文件,只能寫(xiě)入新的內(nèi)容

C.打開(kāi)t.txt文件,只能讀取原有的內(nèi)容

D.打開(kāi)t.txt文件,可以讀取和寫(xiě)入新的內(nèi)容

5.若用fopen()函數(shù)打開(kāi)一個(gè)新的二進(jìn)制文件,該文件可以讀也可以寫(xiě),則文件的使用方式是()。

A.

"ab+"B.

"wb+"C.

"rb+"D.

"ab"

6.若用fopen()函數(shù)打開(kāi)一個(gè)已存在的文件文件,保留該文件原有數(shù)據(jù)且可以讀也可以寫(xiě),則文件打開(kāi)方式是()。

A.

"r+"B.

"w+"C.

"a+"D.

"a"

7.

fseek函數(shù)可以實(shí)現(xiàn)的操作是()。

A.改變文件位置指針的當(dāng)前位置B.文件的順序讀/寫(xiě)

C.文件的隨機(jī)讀/寫(xiě)

D.以上都不對(duì)

8.以下不能將文件指針移到文件開(kāi)頭的函數(shù)是()。

A.

rewind(fp);

B.

fseek(fp,0,SEEK_SET);

C.

fseek(fp,-(long)ftell(fp),SEEK_CUR);

D.

fseek(fp,0,SEEK_END);

9.

fread(buf,64,2,fp)的功能是()。

A.從fp指向的文件中讀出整數(shù)64,并存放在buf中

B.從fp指向的文件中讀出整數(shù)64和2,并存放在buf中

C.從fp指向的文件中讀出64個(gè)字節(jié)的字符,并存放在buf中

D.從fp指向的文件中讀出2個(gè)64個(gè)字節(jié)的字符,并存放在buf中

10.檢測(cè)文件指針fp在文件頭的條件是()。

A.

fp==0 B.

ftell(fp)==0

C.

fseek(fp,0,SEEK_SET) D.

feof(fp)

11.

fgets(s,n,fp)函數(shù)的功能是從文件讀出字符串并存入內(nèi)存首地址s,以下敘述中正確的是()。

A.

n代表最少能讀出n個(gè)字符串

B.

n代表最多能讀出n個(gè)字符

C.

n代表最少能讀出n-1個(gè)字符串

D.

n代表最多能讀出n-1個(gè)字符

12.若fp是指向某文件的指針,且已讀到該文件的末尾,則函數(shù)feof(fp)的返回值是()。

A.

EOF B.-1 C.非0值 D.

NULL

13.執(zhí)行fseek(fp,-20L,1);后的結(jié)果是()。

A.將文件指針從當(dāng)前位置向文件末尾方向移動(dòng)20字節(jié)

B.將文件指針從文件頭向文件末尾方向移動(dòng)20字節(jié)

C.將文件指針從當(dāng)前位置向文件頭方向移動(dòng)20字節(jié)

D.將文件指針從文件末尾向文件頭方向移動(dòng)20字節(jié)

14.下列敘述中正確的是()。

A.

EOF只能作為二進(jìn)制文件的結(jié)束標(biāo)志,feof()只能用來(lái)判斷文本文件是否結(jié)束

B.

EOF只能作為文本文件的結(jié)束標(biāo)志,feof()只能用來(lái)判斷二進(jìn)制文件是否結(jié)束

C.

EOF可作為文本文件和二進(jìn)制文件的結(jié)束標(biāo)志,feof()只能用來(lái)判斷文本文件是否結(jié)束

D.

EOF只能作為文件文件的結(jié)束標(biāo)志,feof()則可以用來(lái)判斷文本文件和二進(jìn)制文件是否結(jié)束

15.若fp為文件指針,且文件已經(jīng)正確打開(kāi),則以下語(yǔ)句的輸出結(jié)果為()。

fseek(fp,0,SEEK_END);

n=ftell(fp);

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

A.

fp所指文件的長(zhǎng)度,以字節(jié)為單位

B.

fp所指文件的當(dāng)前位置,以比特為單位

C.

fp所指文件的長(zhǎng)度,以比特為單位

D.

fp所指文件的當(dāng)前位置,以字節(jié)為單位

16.已知A盤(pán)根目錄下的一個(gè)文本數(shù)據(jù)文件data.dat中存儲(chǔ)了100個(gè)int型數(shù)據(jù),若需要修改該文件中已經(jīng)存在的若干個(gè)數(shù)據(jù)的值,只能調(diào)用一次fopen函數(shù),已有聲明語(yǔ)句“FILE*fp;”,則fopen函數(shù)的正確調(diào)用形式是()。

A.

fp=fopen("a:\\data.dat","r+");

B.

fp=fopen("a:\\data.dat","w+");

C.

fp=fopen("a:\\data.dat","a+");

D.

fp=fopen("a:\\data.dat","w");

17.已知有語(yǔ)句“FILE*fp;intx=123;fp=fopen("out.dat

","w");”,如果需要將變量x的值以文本形式保存到一個(gè)磁盤(pán)文件out.dat中,則以下函數(shù)調(diào)用形式中,正確的是()。

A.

fprintf("%d",x);

B.

fprintf(fp,"%d",x);

C.

fprintf("%d",x,fp);

D.

fprintf("out.dat","%d",x);

18.完成將文件指針fp重新指向文件開(kāi)頭的函數(shù)是()。

A.

feof(fp) B.

rewind(fp)

C.

fseek(fp) D.

ftell(fp)

19.要打開(kāi)一個(gè)已存在的非空文件“file”用于修改,正確的語(yǔ)句是()。

A.

fp=fopen("file","r");

B.

fp=fopen("file","a+");

C.

fp=fopen("file","w");

D.

fp=fopen("file","r+");

20.

fgets(str,n,fp)函數(shù)從文件中讀出一個(gè)字符串,以下正確的敘述是()。

A.字符串讀出后不會(huì)自動(dòng)加入'\0'

B.

fp是file類型的指針

C.

fgets函數(shù)將讀出文件中最多n-1個(gè)字符

D.

fgets函數(shù)將讀出文件中最多n個(gè)字符

二、填空題

1.已知聲明語(yǔ)句:“FILE*fp1,*fp2;longa[2]={12345678,12345678};”,當(dāng)執(zhí)行了以下語(yǔ)句后,文件f1.dat和f2.dat長(zhǎng)度分別為_(kāi)_________字節(jié)和_________字節(jié)。

fp1=fopen("f1.dat","w");fprintf(fp1,"%ld%ld",a[0],a[1]);fclose(fp1);

fp1=fopen("f2.dat","wb");fwrite(a,sizeof(long),2,fp2);fclose(fp2);

2.當(dāng)程序讀/寫(xiě)數(shù)據(jù)文件時(shí),需要有聲明語(yǔ)句“FILE*fp;”,在該聲明語(yǔ)句之前必須包含頭文件_______

溫馨提示

  • 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)論