C語言第9章課件_第1頁
C語言第9章課件_第2頁
C語言第9章課件_第3頁
C語言第9章課件_第4頁
C語言第9章課件_第5頁
已閱讀5頁,還剩52頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第9章文件數(shù)據(jù)文件是程序設(shè)計(jì)中的一個(gè)重要概念,是實(shí)現(xiàn)程序和數(shù)據(jù)分離的重要方式。

本章主要內(nèi)容1.了解什么是文件、文件指針及文件的存取方式2.掌握文件的打開和關(guān)閉操作3.掌握文件的讀寫處理函數(shù)及定位函數(shù)的使用4.能編制簡單的順序文件和隨機(jī)文件19.1文件概述

文件是一組相關(guān)數(shù)據(jù)的集合。在C程序設(shè)計(jì)中,按文件的內(nèi)容可以分為兩類:

程序文件是程序的源代碼;數(shù)據(jù)文件是程序運(yùn)行時(shí)需要的原始數(shù)據(jù)及輸出的結(jié)果。這兩類文件都保存在磁盤上,隨時(shí)可以使用。

文件的讀寫:程序運(yùn)行所需要的數(shù)據(jù)就可以從外部文件輸入,而不必從鍵盤輸入,這一過程稱為“取”文件或“讀”文件;將運(yùn)行結(jié)果存儲(chǔ)到外部介質(zhì)上,從而使結(jié)果可以長期保存,這一過程稱為“存”文件或“寫”文件。21.文件的邏輯結(jié)構(gòu)文件的邏輯結(jié)構(gòu)是指按什么形式將一批數(shù)據(jù)組織成文件。(1)文本文件:也稱ASCII文件,是一種字符流文件。文件由一個(gè)個(gè)字符首尾相接而成,其中每個(gè)字符占1字節(jié),存放的是字符的ASCII碼。文本文件的優(yōu)點(diǎn)是可以直接閱讀,而且ASCII代碼標(biāo)準(zhǔn)統(tǒng)一,使文件易于移植,但其缺點(diǎn)是輸入輸出都要進(jìn)行轉(zhuǎn)換,效率低。(2)二進(jìn)制文件:二進(jìn)制文件中的數(shù)據(jù)是按其在內(nèi)存中的存儲(chǔ)形式存放的。二進(jìn)制文件在輸入輸出時(shí),不必進(jìn)行轉(zhuǎn)換,故效率高。但二進(jìn)制文件只能供機(jī)器閱讀,人工無法閱讀,也不能打印。而且,由于不同的計(jì)算機(jī)系統(tǒng)對(duì)數(shù)據(jù)的二進(jìn)制表示也各有差異,因此,可移植性差。一般用二進(jìn)制文件來保存數(shù)據(jù)處理的中間結(jié)果,供本計(jì)算機(jī)以后使用。3將內(nèi)存的數(shù)據(jù)存入文件及將文件中的數(shù)據(jù)讀入內(nèi)存統(tǒng)稱文件的存取。C語言支持的文件存取方式有兩種:順序存取和隨機(jī)存取。(1)順序存取只能依先后次序存取文件中的數(shù)據(jù),存取完第一字節(jié),才能存取第二字節(jié);存取完第n-1字節(jié),才能存取第n字節(jié)。(2)隨機(jī)存取也稱直接存取,可以直接存取文件中指定的數(shù)據(jù),例如,可以直接存取指定的第i個(gè)字節(jié)(或字符),而不管第i-1字節(jié)是否已經(jīng)存取。文件的存取方式與該文件是文本文件還是二進(jìn)制文件無關(guān),即它們都可以用順序方式或隨機(jī)方式進(jìn)行存取。2.文件的存取方式4順序文件和隨機(jī)文件可以進(jìn)行順序存取的文件稱為順序文件。在順序文件中,記錄的邏輯順序和物理順序相同,記錄可以不等長,讀出某一條記錄的速度慢,不能直接對(duì)文件進(jìn)行修改,適宜于對(duì)文件順序批量處理??梢赃M(jìn)行隨機(jī)存取的文件稱為隨機(jī)文件。在隨機(jī)文件中,每條記錄等長,各數(shù)據(jù)項(xiàng)長度固定,每個(gè)記錄有惟一的記錄號(hào)。讀寫文件時(shí),按記錄號(hào)直接讀寫指定的記錄,適宜于隨機(jī)讀寫某條記錄的操作。2.文件的存取方式5文件操作步驟相關(guān)的庫函數(shù)打開文件fopen()文件讀寫fscanf()fprintf()格式I/O函數(shù)getc()putc()字符I/O函數(shù)fgetc()fputc()字符I/O函數(shù)fgets()fputs()字符串I/O函數(shù)fread()fwrite()數(shù)據(jù)塊I/O函數(shù)關(guān)閉文件fclose()(1)打開文件(2)文件讀寫(3)關(guān)閉文件3.文件操作的步驟6【例】將字符串"Beijing","Shanghai","Tianjin","Chongqing"寫入文件ex.txt。#include<stdio.h>FILE*fp;main(){chara[][11]={"Beijing","Shanghai","Tianjin","Chongqing"};inti;if((fp=fopen(“c:\\ex.txt","w"))==NULL){printf("Cannotopenfile\n");exit(1);}for(i=0;i<=3;i++)fputs(a[i],fp);fclose(fp);}

9.2文件的打開與關(guān)閉7在進(jìn)行文件操作時(shí),要用文件指針。

文件指針用來指向文件中當(dāng)前操作的位置,當(dāng)文件指針與某個(gè)文件連接之后,用戶就通過文件指針而不是通過文件名來存取文件。文件指針是一種FILE型的結(jié)構(gòu)變量,C編譯系統(tǒng)已在標(biāo)題文件stdio.h中將FILE結(jié)構(gòu)類型定義好,其中包括文件名、文件狀態(tài)標(biāo)志及緩沖區(qū)大小等信息。定義文件指針的格式為:FILE*fp1,*fp2;這樣,fp1和fp2就成為文件指針,由fopen()函數(shù)可將它們指向指定的文件。1.文件指針8(1)打開文件函數(shù)fopen()FILE*fp;fp=fopen(fname,mode);其中,fname是要打開的文件名,可以是字符串常數(shù)、字符型數(shù)組或字符型指針,文件名可以帶路徑;mode表示文件的使用方式,它規(guī)定了打開文件的目的。文件正常打開后,fopen()函數(shù)的返回值是文件在內(nèi)存中的起始地址,把該地址賦給文件指針fp就建立起文件指針fp和文件fname之間的連接,即fp指向文件fname。此后對(duì)文件的操作就通過文件指針進(jìn)行,而不再使用文件名。如果不能打開指定的文件,則返回NULL。2.打開文件9使用

方式含義使用

方式含義"r"或"rt"打開文本文件,只讀"rb"打開二進(jìn)制文件,只讀"w"或"wt"創(chuàng)建文本文件,只寫"wb"創(chuàng)建二進(jìn)制文件,只寫"a"或"at"打開文本文件,追加"ab"打開二進(jìn)制文件,讀、追加"r+"或"r+t"打開文本文件,讀、覆蓋寫"r+b"打開二進(jìn)制文件,讀、覆蓋寫"w+"或"w+t"創(chuàng)建文本文件,先寫后讀"w+b"創(chuàng)建二進(jìn)制文件,先寫后讀"a+"或"a+t"打開文本文件,讀、追加"a+b"打開二進(jìn)制文件,讀、追加文件使用方式表10為確保文件操作的正常進(jìn)行,有必要在程序中檢測文件是否正常打開,即操作是否成功。常用下面的程序段:if((fp=fopen("fname","w"))==NULL){printf("Cannotopenfile\n");exit(1);}即文件不能正常打開時(shí),屏幕提示“Cannotopenfile.”,程序運(yùn)行終止。exit()函數(shù)的功能是終止程序運(yùn)行,關(guān)閉文件并返回操作系統(tǒng);若文件成功打開,程序就可以繼續(xù)往下執(zhí)行。11

①w方式,只能用于向文本文件寫數(shù)據(jù)。若指定的文件不存在,則創(chuàng)建該文件;若指定的文件已存在,則先刪除文件中的全部內(nèi)容。文件打開時(shí),文件指針指向文件開頭。

②r方式,只能用于從文本文件中讀數(shù)據(jù)。若指定的文件不存在,則出現(xiàn)錯(cuò)誤信息。文件打開時(shí),文件指針指向文件開頭。

③a方式,用于向文件末尾添加數(shù)據(jù)。若指定的文件存在,將它打開,并將文件指針指向文件末尾,新寫入的內(nèi)容被追加在原有數(shù)據(jù)之后;若指定的文件不存在,則創(chuàng)建該文件,這時(shí)文件指針指向的既是文件頭,也是文件尾。④r+,w+,a+方式,用于以既可讀也可寫的方式打開文本文件。r+:用該方式打開文件后,若寫入數(shù)據(jù),則寫入的內(nèi)容只覆蓋新數(shù)據(jù)需要的空間,其后的原有數(shù)據(jù)并不丟失。w+:用該方式打開文件后,文件原有內(nèi)容全部丟失,只能先向文件寫入數(shù)據(jù),然后再讀出。a+:用該方式打開文件后,將文件內(nèi)容保留。讀時(shí)從文件開頭讀,寫時(shí)則追加到文件末尾。⑤上述6種方式加上字母“t”后仍表示對(duì)文本文件打開。⑥上述6種方式加上字母“b”后就表示對(duì)二進(jìn)制文件打開。(2)關(guān)于文件使用方式的說明12文件操作完畢,應(yīng)用fclose()函數(shù)將文件關(guān)閉,以保證本次文件操作有效。調(diào)用格式為:fclose(fp);fp是由fopen()函數(shù)打開文件時(shí)使用的文件指針。該函數(shù)執(zhí)行成功時(shí),返回0值;否則,返回非0值。文件關(guān)閉后,文件指針與文件名脫鉤,文件指針可以再與別的文件連接。文件打開和關(guān)閉的程序示例如下:3.關(guān)閉文件#include<stdio.h>FILE*fp1,*fp2;main(){...fp1=fopen("text1.txt","w");...fp2=fopen("text2.txt","r+");...fclose(fp1);fclose(fp2);...}139.3文件的讀寫操作一個(gè)文件打開后,就可以對(duì)該文件進(jìn)行讀寫。C語言用編譯系統(tǒng)提供的文件輸入輸出函數(shù)實(shí)施文件的讀寫。文本文件和二進(jìn)制文件需要使用不同的文件輸入輸出函數(shù)。149.3.1文本文件讀寫函數(shù)①向文本文件寫入一個(gè)字符函數(shù)fputc()和putc()fputc()和putc()是兩個(gè)完全等價(jià)的函數(shù),它們都用來向指定的文本文件寫入一個(gè)字符,調(diào)用格式為:fputc(ch,fp);putc(ch,fp);其中,ch為欲寫入的字符,可以是字符型常數(shù)或字符型變量;fp為文件指針。該函數(shù)的功能是將一個(gè)字符寫入指定的文件,如果執(zhí)行成功,返回所寫入的字符;否則,返回EOF。EOF是C編譯系統(tǒng)定義的文本文件結(jié)束標(biāo)志,其值為-1,十六進(jìn)制表示為0xFF。

1.字符讀寫函數(shù)fgetc()、getc()和fputc()、putc()15#include<stdio.h>#include<stdlib.h>FILE*fi;voidmain(){chara='A',b='B',c='C';if((fi=fopen("c:\\ex9-1.txt","w"))==NULL)//打開C盤上指定的文件{printf("cannotopenfile\n");exit(1);}fputc(a,fi);//寫文件操作fputc(b,fi);fputc(c,fi);fclose(fi);}

【例】將字符A、B、C和EOF寫入C盤根目錄下的文件ex9-1.txt中。16②從文本文件讀出一個(gè)字符函數(shù)fgetc()和getc()fgetc()和getc()也是一對(duì)完全等價(jià)的函數(shù),它們都用來從指定的文本文件中讀取一個(gè)字符,調(diào)用格式為:ch=fgetc(fp);ch=getc(fp)其中,fp為文件指針。該函數(shù)的功能是從指定的文件讀取一個(gè)字符,并賦給字符型變量ch。如果讀取成功,返回讀取的字符;如果讀取錯(cuò)誤或遇到文件結(jié)束標(biāo)志EOF,則返回EOF。

17#include<stdio.h>#include<stdlib.h>FILE*fi;voidmain(){chara;if((fi=fopen("c:\\ex9-1.txt","r"))==NULL)//打開C盤上指定的文件{printf("cannotopenfile\n");exit(1);}while((a=fgetc(fi))!=EOF)//讀文件putchar(a);//屏幕輸出fclose(fi); printf("\n");}【例】從例9.1建立的文件ex9-1.txt中讀出所有的字符并顯示在屏幕上。18fputs()用來將一個(gè)字符串寫入指定的文本文件,其調(diào)用格式為:fputs(s,fp);其中,s可以是字符型數(shù)組名、字符型指針變量或字符串常數(shù),fp為文件指針。該函數(shù)的功能是將字符串s寫入由fp指向的文件中,字符串末尾的’\0’字符不予寫入。如果函數(shù)執(zhí)行成功,則返回所寫的最后一個(gè)字符;否則,返回EOF。2.字符串讀寫函數(shù)fgets()和fputs()(1)向文本文件寫入字符串函數(shù)fputs()19#include<stdio.h>#include<stdlib.h>FILE*fi;voidmain(){chara[][20]={"VisualC++","BASIC","MicorsoftSQL","COBOL","PL-1"};inti;if((fi=fopen("c:\\ex9-2.txt","w"))==NULL){printf("Cannotopenfile\n");exit(1);}for(i=0;i<=4;i++)fputs(a[i],fi);fclose(fi);}【例】將字符串"VisualC++","BASIC","MicorsoftSQL","COBOL","PL-1"寫入文件ex9-2.txt。20#include<stdio.h>#include<stdlib.h>FILE*fi;voidmain(){inti;

chara[][20]={"VisualStudio.NET\n","JavaScript\n","Pascal\n"};if((fi=fopen("c:\\ex9-2.txt","a"))==NULL){printf("Cannotopenfile\n");exit(1);}for(i=0;i<=2;i++)fputs(a[i],fi);fclose(fi);}【例】在上例創(chuàng)建的ex9-2.txt文件的末尾追加三個(gè)字符串"VisualStudio.NET"、"JavaScript"和"Pascal"。程序以“a”方式將文件ex9-2.txt打開后,文件指針自動(dòng)指向文件末尾,因此,由循環(huán)中fputs()函數(shù)寫入的三個(gè)字符串將依次追加在文件的末尾。21fgets()用來從指定的文本文件中讀取字符串,其調(diào)用格式為:fgets(s,n,fp);其中,s可以是字符型數(shù)組名或字符串指針,n是指定讀入的字符個(gè)數(shù),fp是文件指針。該函數(shù)的功能是最多讀取n-1個(gè)字符,并將讀入的字符串存入字符串指針s。當(dāng)函數(shù)讀取的字符或者達(dá)到指定的個(gè)數(shù),或者接收到換行符,或者接收到文件結(jié)束標(biāo)志EOF時(shí),將在讀取的字符后面自動(dòng)添加一個(gè)‘\0’字符;若有換行符,則將換行符予以保留(換行符在‘\0’字符之前);若有EOF,則不予保留。該函數(shù)如果執(zhí)行成功,返回讀取的字符串;如果失敗,則返回空指針,這時(shí),s中的內(nèi)容不確定。(2)從文本文件讀出字符串函數(shù)fgets()22#include<stdio.h>#include<stdlib.h>FILE*fi;voidmain(){inti;chara[7][20];if((fi=fopen("c:\\ex9-2.txt","r"))==NULL){printf("Cannotopenfile\n");exit(1);}for(i=0;i<7;i++) {fgets(a[i],20,fi);if(i%2==0)//從文件中讀取字符串并printf("%s",a[i]);//顯示第0、2、4、6號(hào)字符串 }fclose(fi);}【例】從由例9.3和9.4建立的文本文件ex9-2.txt中讀出各個(gè)字符串并將其中第0、2、4、6號(hào)字符串顯示在屏幕上。23格式讀寫函數(shù)是比較通用的文本文件輸入輸出函數(shù),通過使用不同的格式轉(zhuǎn)換說明符,可以讀寫不同類型的數(shù)據(jù)。(1)格式寫文件函數(shù)fprintf()fprintf()用來將輸出項(xiàng)按指定的格式寫入指定的文本文件,其調(diào)用格式為:fprintf(fp,format,arg1,arg2,...,argn);其中,fp為文件指針,format為指定的格式控制字符串,arg1~argn為輸出項(xiàng),可以是字符、字符串或各種類型的數(shù)值。該函數(shù)的功能是按格式控制字符串format給定的格式,將輸出項(xiàng)arg1,arg2,...,argn的值,寫入fp所指向的文件中。函數(shù)如果執(zhí)行成功,返回實(shí)際寫入文件的字符個(gè)數(shù);若出現(xiàn)錯(cuò)誤,返回負(fù)數(shù)。

fprintf()中格式控制的使用與printf()相同。

3.格式讀寫函數(shù)fscanf()和fprintf()24

【例】將下表數(shù)據(jù)寫入文件ex9-3.txt。公司類型重量TOSHIBAJ-3100SGT6.8kgNECPC-9801LS8.8kgFUJITSUFMTOWNS11.0kgHITACHIB16X7.3kg#include<stdio.h>#include<stdlib.h>FILE*f;voidmain(){inti;charpc[][10]={"TOSHIBA","J-3100SGT","6.8kg","NEC","PC-9801LS","8.8kg","FUJITSU","FMTOWNS","11.0kg"};if((f=fopen("c:\\ex9-3.txt","w"))==NULL){printf("Cannotopenfile");exit(1);}for(i=0;i<=6;i+=3)fprintf(f,"%10s%10s%6s",pc[i],pc[i+1],pc[i+2]);fclose(f);}25本程序運(yùn)行后,文件中各字符串的存放形式(x代表空格)為:xxxTOSHIBAxJ-3100SGTx6.8kgxxxxxxxNEC......11.0kgpc[0]pc[1]pc[2]pc[3]......pc[8]10字節(jié)10字節(jié)6字節(jié)10字節(jié)......6字節(jié)注意,格式化寫入時(shí)按右對(duì)齊方式寫入,例如,pc[0]的10個(gè)字節(jié)的內(nèi)容為:TOSHIBA26fscanf()用來按格式從指定的文本文件中讀取數(shù)據(jù),其調(diào)用格式為:

fscanf(fp,format,arg1,arg2,...,argn);其中,fp為文件指針,format為格式控制字符串,arg1~argn為輸入項(xiàng)的地址。該函數(shù)的功能是從文件指針fp所指的文本文件中讀取數(shù)據(jù),按格式控制字符串format所給定的格式賦給輸入項(xiàng)arg1,arg2,...,argn。如果該函數(shù)執(zhí)行成功,返回讀取項(xiàng)目的個(gè)數(shù);如果遇到文件末尾,返回EOF;如果賦值失敗,返回0。(2)格式讀文件函數(shù)fscanf()27#include<stdio.h>#include<stdlib.h>voidmain(){FILE*f;charpc[9][10];inti;if((f=fopen("c:\\ex9-3.txt","r"))==NULL){printf("Cannotopenfile");exit(1);}for(i=0;i<=6;i+=3)fscanf(f,"%s%s%s",pc[i],pc[i+1],pc[i+2]);fclose(f);printf("公司類型重量\n");for(i=0;i<=6;i+=3)printf("%10s%10s%7s\n",pc[i],pc[i+1],pc[i+2]);}【例】讀出上例所建立文件ex9-3.txt中的數(shù)據(jù)。289.3.2二進(jìn)制文件讀寫函數(shù)(1)寫數(shù)據(jù)塊函數(shù)fwrite()fwrite()用于向二進(jìn)制文件寫入一個(gè)數(shù)據(jù)塊,其調(diào)用格式為:

fwrite(buf,size,count,fp);其中,buf可以是數(shù)組名或指向數(shù)組的指針,用于提供要寫入文件的數(shù)據(jù);size是無符號(hào)整型表達(dá)式,用于規(guī)定要寫入的每個(gè)數(shù)據(jù)項(xiàng)的長度(字節(jié)數(shù));count是整型表達(dá)式,用于指定數(shù)據(jù)項(xiàng)的個(gè)數(shù);fp是文件指針。

該函數(shù)的功能是向fp所指的文件中寫入一個(gè)由buf指向的數(shù)據(jù)塊,該數(shù)據(jù)塊共有count個(gè)數(shù)據(jù)項(xiàng),每個(gè)數(shù)據(jù)項(xiàng)有size個(gè)字節(jié)。如果執(zhí)行成功,返回實(shí)際寫入的數(shù)據(jù)項(xiàng)個(gè)數(shù);若所寫數(shù)據(jù)項(xiàng)少于實(shí)際需要的數(shù)據(jù)項(xiàng),則出錯(cuò)。

1.數(shù)據(jù)塊讀寫函數(shù)fread()和fwrite()29#include<stdio.h>#include<stdlib.h>FILE*fp;voidmain(){intsam[10],i;if(!(fp=fopen("c:\\ex9-4.dat","wb"))){printf("Cannotopenfile\n");exit(1);}for(i=0;i<10;i++)scanf("%d",&sam[i]);fwrite(sam,sizeof(sam),1,fp);fclose(fp);}【例】從鍵盤輸入10個(gè)整數(shù),將它們存放在int型數(shù)組sam中,將該數(shù)組作為一個(gè)數(shù)據(jù)塊寫入文件ex9-4.dat中。用“wb”方式打開文件,從鍵盤輸入10個(gè)整數(shù)存放在數(shù)組sam中,然后用fwrite()將數(shù)組sam作為一個(gè)數(shù)據(jù)塊寫入文件ex9-4.dat。在程序的fwrite(sam,sizeof(sam),1,fp)語句中,從sizeof(sam)可以看出數(shù)據(jù)塊是以整個(gè)數(shù)組為單位的,故數(shù)據(jù)塊個(gè)數(shù)為1,若將該語句改成fwrite(sam,sizeof(int),10,fp);數(shù)據(jù)塊就以一個(gè)整數(shù)為單位,這時(shí),數(shù)據(jù)塊個(gè)數(shù)應(yīng)該是10。30fread()用于從二進(jìn)制文件中讀出一個(gè)數(shù)據(jù)塊,調(diào)用格式為:

fread(buf,size,count,fp);其中,buf、size、count和fp的含義和用法與fwrite()完全相同。該函數(shù)的功能是從fp所指的文件中,一次讀出長度為size字節(jié)的count個(gè)數(shù)據(jù)項(xiàng),然后存放在buf中。在讀入過程中,自動(dòng)把文件中的回車符和表示制表符和換行符的轉(zhuǎn)義序列轉(zhuǎn)換成換行符。函數(shù)執(zhí)行成功時(shí),返回實(shí)際讀入的數(shù)據(jù)項(xiàng)個(gè)數(shù);如果讀出項(xiàng)目比調(diào)用中所需項(xiàng)目少,則出錯(cuò)。(2)讀數(shù)據(jù)塊函數(shù)fread()31#include<stdio.h>#include<stdlib.h>FILE*fp;voidmain(){intb[10],i;if(!(fp=fopen("c:\\ex9-4.dat","rb"))){printf("Cannotopenfile\n");exit(1);}if(fread(b,sizeof(int),10,fp)!=10)//讀取的數(shù)據(jù)塊不足{if(!feof(fp))//已到文件末尾printf("prematureendoffile\n");else//讀取過程中出錯(cuò)printf("filereaderror\n");exit(1);}fclose(fp);for(i=0;i<10;i++)printf("%d",b[i]);}【例】從例9.8建立的二進(jìn)制文件ex9-4.dat中讀取10個(gè)整數(shù)存入數(shù)組b,并在屏幕上顯示這10個(gè)數(shù)。以“rb”方式打開文件,用fread()讀入含10個(gè)整數(shù)的數(shù)據(jù)塊存入數(shù)組b,再由printf()的格式控制將數(shù)組b中的二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)輸出。322.其他二進(jìn)制文件讀寫函數(shù)fgetc()、fputc()、fgets()、fputs()既可以用于讀寫文本文件,也可以用于讀寫二進(jìn)制文件,因?yàn)樗鼈儾僮鞯膶?duì)象都是字符,無論是在文本文件中,還是在二進(jìn)制文件中,字符都是按其ASCII碼的形式表示和存儲(chǔ)的,二者并沒有區(qū)別。當(dāng)文件用“w”、“r”、“a”等方式打開時(shí),它們的作用就是讀寫文本文件,當(dāng)文件用“wb”、“rb”、“ab”等方式打開時(shí),它們的作用就是讀寫二進(jìn)制文件。339.4文件檢測函數(shù)在文本文件中,C編譯系統(tǒng)定義EOF為文本文件的結(jié)束標(biāo)志,EOF的值為-1。由于任何ASCII碼都不可能取負(fù)值,所以它在文本文件中不會(huì)產(chǎn)生沖突。但是在二進(jìn)制文件中,-1有可能是一個(gè)有效的數(shù)據(jù),所以EOF不能作為二進(jìn)制文件的結(jié)束標(biāo)志。為此,C編譯系統(tǒng)定義了feof()函數(shù)用作二進(jìn)制文件的結(jié)束標(biāo)志:feof(fp);如果文件指針已到文件末尾,函數(shù)返回非0值;否則,返回0值。例如,下面的程序段可以控制讀文件操作到文件結(jié)束為止:while(!feof(fp))getc(fp);feof()也可以用作文本文件的結(jié)束標(biāo)志。文件檢測函數(shù)用來檢測文件指針是否已到文件末尾,或文件讀寫操作中是否出現(xiàn)錯(cuò)誤等情況,以便能正確地進(jìn)行文件的存取。1.檢測文件結(jié)尾函數(shù)feof()34ferror()函數(shù)用來檢測文件讀寫時(shí)是否發(fā)生錯(cuò)誤,其調(diào)用格式為:ferror(fp);若未發(fā)生讀寫錯(cuò)誤,返回0值;否則,返回非0值。例如,下面的程序段可用來控制程序的運(yùn)行:if(ferror(fp)){puts("fileerror.");exit(1);}如果讀寫操作中出現(xiàn)錯(cuò)誤,則顯示"fileerror.",并自動(dòng)終止程序的運(yùn)行。 2.檢測文件讀寫出錯(cuò)函數(shù)ferror()35clearerr()函數(shù)用于將文件的出錯(cuò)標(biāo)志和文件結(jié)束標(biāo)志置0。當(dāng)調(diào)用的輸入輸出函數(shù)出錯(cuò)時(shí),ferror()函數(shù)給出非0的標(biāo)志,并一直保持此值,直到使用clearerr()函數(shù)或rewind()函數(shù)時(shí)才重新置0。用clearerr(fp);可及時(shí)清除出錯(cuò)標(biāo)志。3.清除文件末尾和出錯(cuò)標(biāo)志函數(shù)clearerr()369.5文件的順序存取和隨機(jī)存取1.文件指針定位函數(shù)(1)rewind()函數(shù)用rewind()函數(shù)可將文件指針移到文件的開頭,其調(diào)用格式為:rewind(fp);函數(shù)調(diào)用成功返回0值;否則,返回非0值。while(!feof(fp))putchar(fgetc(fp));rewind(fp);while(!feof(fp));putchar(fgetc(fp));可兩次顯示fp所指的文件中的第一個(gè)字符。順序存取時(shí)必須按順序?qū)懭牒妥x出,而隨機(jī)存取時(shí)則可以按任意順序?qū)懭牒妥x出。一個(gè)文件是適合于順序存取還是隨機(jī)存取,不在于它們是文本文件還是二進(jìn)制文件,而在于文件中的記錄長度是否相等:隨機(jī)存取要求每個(gè)記錄的長度必須相等,而順序存取不要求記錄長度必須相等。37用ftell()函數(shù)可以返回文件指針的當(dāng)前位置。ftell(fp);返回值為長整型數(shù),表示相對(duì)于文件頭的字節(jié)數(shù),出錯(cuò)時(shí)返回-1L。longi;if((i=ftell(fp))==-1L)printf("Afileerrorhasoccurredat%ld.\n",i);可以通知用戶在文件的什么位置出現(xiàn)了文件錯(cuò)誤。(2)ftell()函數(shù)38符號(hào)名值含義SEEK_SET0文件開頭SEEK_CUR1文件當(dāng)前位置SEEK_END2文件末尾用fseek()函數(shù)可以將文件指針移動(dòng)到指定的位置:fseek(fp,offset,orng);offset是一個(gè)長整數(shù),表示指針移動(dòng)的字節(jié)數(shù):為負(fù)時(shí),表示向文件頭的方向移動(dòng);為正時(shí),向文件尾的方向移動(dòng);為0時(shí),不移動(dòng)。orng用來指定指針的初始位置,既可以用符號(hào)名,也可以用對(duì)應(yīng)的整數(shù)。該函數(shù)的功能是將指針fp指到以orng為初始位置、移動(dòng)offset個(gè)字節(jié)后的位置上。若成功,則返回0;否則,返回非0。(3)fseek()函數(shù)39假設(shè)一個(gè)二進(jìn)制文件k.dat的每個(gè)記錄含有若干字段,組織成一個(gè)structst型數(shù)據(jù),該文件用指針fp打開后,可以先用fseek()將文件指針定位到文件尾,用ftell()就可以獲得該文件的長度,用文件長度與每個(gè)記錄長度相除,就可以得到該文件所包含的記錄數(shù)。FILE*fp;structst{……};intn,k;fp=fopen("k.dat","rb+");fseek(fp,0,SEEK_END);/*文件指針移到文件尾*/n=ftell(fp);/*文件長度字節(jié)數(shù)*/k=n/sizeof(structst);/*文件記錄數(shù)*/【例】利用ftell()和fseek()確定二進(jìn)制文件的長度(字節(jié)數(shù))和記錄數(shù)。40文件的順序存取是將數(shù)據(jù)按先后次序依次寫入文件或從文件中讀出。因此存取順序文件時(shí),只要清楚文件指針是在文件頭還是在文件尾就可以了,一般不關(guān)心文件指針精確地位于何處。當(dāng)文件剛打開時(shí),文件指針通常位于文件頭(當(dāng)用“a”方式打開時(shí),文件指針才指向文件尾),進(jìn)行讀寫時(shí)文件指針會(huì)自動(dòng)移動(dòng)。在某些情況下,例如,寫入數(shù)據(jù)后希望從頭讀出文件中的數(shù)據(jù),需要用rewind()函數(shù)將文件指針恢復(fù)到文件頭。2.文件的順序存取41只用于順序存取的文件,既可以是文本文件也可以是二進(jìn)制文件,其各個(gè)記錄的長度既可以相等也可以不等。(1)在創(chuàng)建順序文本文件時(shí),最好配對(duì)使用文件讀寫函數(shù),以保證輸入輸出的格式一致。對(duì)只含文字?jǐn)?shù)據(jù)的文本文件,可以配對(duì)使用fgetc()和fputc()、fgets()和fputs();對(duì)既有文字信息,又有數(shù)值信息的文本文件,通常配對(duì)使用fscanf()和fprintf()。下面的程序用來建立一個(gè)記錄長度不等的文本文件score.txt,每次循環(huán)寫入一條記錄。【例9】建立一個(gè)考生檔案文件,包括準(zhǔn)考證號(hào)、考生姓名、畢業(yè)學(xué)校、數(shù)學(xué)、語文、外語、物理、化學(xué)、政治、生物和總分,并能根據(jù)準(zhǔn)考證號(hào)進(jìn)行順序查詢,以通知該考生的考試成績。準(zhǔn)考證號(hào)姓名語文數(shù)學(xué)外語物理化學(xué)生物政治總分1Yumei788170928774832Liuyang838590768178713Wuliang739093656284694Gaoxing817958938775645Liming7885698991817642w方式打開文件輸入一條記錄準(zhǔn)考證號(hào):num姓名:name畢業(yè)學(xué)校:school語文成績:score[0]數(shù)學(xué)成績:score[1]外語成績:score[2]物理成績:score[3]化學(xué)成績:score[4]生物成績:score[5]政治成績:score[6]計(jì)算總分:score[7]寫入該記錄程序運(yùn)行流程圖43#include<stdio.h>#include<stdlib.h>#include<string.h>FILE*fp;voidmain(){inti,score[8];charnum[8],name[11],school[11];if((fp=fopen("d:\\score.txt","w"))==NULL){printf("cannotopenfile.\n");exit(1);}while(1)//輸入考生信息{printf("輸入準(zhǔn)考證號(hào)(0000000結(jié)束輸入):");gets(num);//輸入準(zhǔn)考證號(hào)if(strcmp(num,"0000000")==0)break;//輸入0000000時(shí)結(jié)束printf("輸入姓名:");gets(name);printf("輸入畢業(yè)學(xué)校:");gets(school);printf("輸入語文成績:");scanf("%d",&score[0]);printf("輸入數(shù)學(xué)成績:");scanf("%d",&score[1]);printf("輸入外語成績:");scanf("%d",&score[2]);printf("輸入物理成績:");scanf("%d",&score[3]);printf("輸入化學(xué)成績:");scanf("%d",&score[4]);printf("輸入生物成績:");scanf("%d",&score[5]);printf("輸入政治成績:");scanf("%d%*c",&score[6]);score[7]=0;for(i=0;i<7;i++)//計(jì)算總分score[7]+=score[i];fprintf(fp,"%s%s%s%d%d%d%d%d%d%d%d",num,name,school,score[0],score[1],score[2],score[3],score[4],score[5],score[6],score[7]);//寫入一條記錄}fclose(fp);}44建立文件主要是為了實(shí)現(xiàn)一次建立,多次使用的目的。查詢就是一個(gè)最基本的使用方式。對(duì)順序文件按準(zhǔn)考證號(hào)進(jìn)行順序查詢時(shí),用“r”方式打開已創(chuàng)建好的文本文件,從鍵盤輸入的要查詢的準(zhǔn)考證號(hào)存放在kh[8]中,然后從文件頭開始,每次讀取一條記錄,并將該記錄的的準(zhǔn)考證號(hào)num[]與要查找的準(zhǔn)考證號(hào)kh[]進(jìn)行比較,若相等,就輸出查詢到的信息,并退出循環(huán);若已到文件末尾仍未找到所需記錄,說明該記錄不存在。在循環(huán)讀取記錄的過程中,每讀取一條記錄,文件指針自動(dòng)移動(dòng)到下一條記錄的開頭。因此,在開始新的查詢前,要將文件指針重新定位到文件開頭,以便從文件頭開始查找。

(2)順序文本文件的查詢45rewind(fp)查無此人非0非0輸入要查找的準(zhǔn)考證號(hào)讀入一條記錄顯示該記錄!feof(fp)準(zhǔn)考證號(hào)比較r方式打開文件0046#include<stdio.h>#include<stdlib.h>//exit()#include<string.h>//getch()#include<conio.h>//getch()FILE*fp;voidmain(){inti=0,flag,score[8];charnum[8],name[11],school[11],kh[8],ch;if((fp=fopen("D:\\score.txt","r"))==NULL){printf("cannotopenfile.\n");exit(1);}while(1)//開始查詢{printf("輸入要查詢的準(zhǔn)考證號(hào)(輸入0000000結(jié)束查詢):");gets(kh);if(strcmp(kh,"0000000")==0)break;flag=0;while(!feof(fp))//順序查詢{//讀入一條記錄fscanf(fp,"%s%s%s%d%d%d%d%d%d%d%d",num,name,

school,&score[0],&score[1],&score[2],&score[3],&score[4],&score[5],&score[6],&score[7]);if(strcmp(kh,num)==0)//找到記錄,輸出信息

{printf("NumberNameSchooleChiMatForPhy");printf("CheBioPolTotal\n");printf("%-7s%-10s%-10s%-4d%-4d%-4d",num,name,school,score[0],score[1],score[2]);

printf("%-4d%-4d%-4d%-4d%-5d\n",

score[3],score[4],score[5],score[6],score[7]);flag=1;//設(shè)置提前退出循環(huán)的標(biāo)志break;}}if(!flag)printf("查無此人.\n");printf("按任意鍵繼續(xù)查詢...\n");ch=getch();rewind(fp);//文件指針返回文件開頭}fclose(fp);}47在創(chuàng)建二進(jìn)制文件時(shí),通常用結(jié)構(gòu)變量或數(shù)組來組織記錄,以便能用fread()和fwrite()來進(jìn)行數(shù)據(jù)塊的讀寫,可以提高存取速度。這時(shí),各個(gè)記錄的長度是相等的。建立二進(jìn)制文件score.dat的程序如下:48#include<stdio.h>#include<stdlib.h>#include<string.h>FILE*fp;structstudent{charnum[8];charname[11];charschool[11];intscore[8];}st;//定義結(jié)構(gòu)變量存放學(xué)生記錄voidmain(){inti;if((fp=fopen("D:\\score.dat","wb"))==NULL){printf("cannotopenfile.\n");exit(1);}while(1)//輸入考生信息{printf("輸入準(zhǔn)考證號(hào)(輸入0000000結(jié)束):");gets(st.num);if(strcmp(st.num,"0000000")==0)break;//輸入0000000時(shí)結(jié)束printf("輸入考生姓名:");gets();printf("輸入畢業(yè)學(xué)校:");gets(st.school);printf("輸入語文成績:");scanf("%d",&st.score[0]);printf("輸入數(shù)學(xué)成績:");scanf("%d",&st.score[1]);printf("輸入外語成績:");scanf("%d",&st.score[2]);printf("輸入物理成績:");scanf("%d",&st.score[3]);printf("輸入化學(xué)成績:");scanf("%d",&st.score[4]);printf("輸入生物成績:");scanf("%d",&st.score[5]);printf("輸入政治成績:");

scanf("%d%*c",&st.score[6]);st.score[7]=0;for(i=0;i<7;i++)//計(jì)算總分

st.score[7]+=st.score[i];if(fwrite(&st,sizeof(st),1,fp)!=1)//寫入一條記錄

{puts("Writefileerror.\n");exit(1);}}fclose(fp);}49#include<stdio.h>#include<stdlib.h>#include<string.h>#include<conio.h>FILE*fp;structstudent{charnum[8];charname[11];charschool[11];intscore[8];}st;voidmain(){charkh[8],ch;if((fp=fopen("D:\\score.dat","rb"))==NULL){printf("cannotopenfile.\n");exit(1);}while(1)//開始查詢{printf("輸入待查準(zhǔn)考證號(hào)(輸入0000000結(jié)束查詢):");gets(kh);if(strcmp(kh,"0000000")==0)break;while(!feof(fp))//順序查詢{if(fread(&st,sizeof(st),1,fp)!=1)//讀入一條記錄{puts("查無此人.\n");break;}if(strcmp(kh,st.num)==0)//找到記錄,輸出信息{printf("NumberNameSchooleChiMatForPhy");

printf("CheBioPolTotal\n");printf("%7s%10s%10s%-4d%-4d",st.num,,st.school,st.score[0],st.score[1]);printf("%-4d%-4d%-4d%-4d%-4d%-5d\n",

st.score[2],st.score[3],st.score[4],st.score[5],st.score[6],st.score[7]);break;}}printf("按任意鍵繼續(xù)查詢...\n");ch=getch();rewind(fp);//文件指針返回文件開頭

}fclose(fp);}50隨機(jī)文件是能進(jìn)行隨機(jī)存取的文件,應(yīng)能隨機(jī)地將數(shù)據(jù)寫入文件的指定位置或從文件的指定位置讀取數(shù)據(jù),所以,隨機(jī)文件的各記錄應(yīng)保證長度相等,為此,可以將記錄組織成結(jié)構(gòu)類型來實(shí)現(xiàn)記錄等長的限制;為了實(shí)現(xiàn)隨機(jī)存取,還需要精確知道文件指針當(dāng)前位于何處(用ftell()函數(shù)可以確定文件指針的當(dāng)前位置),還要用fseek()函數(shù)將文件指針精確定位到所希望的位置,然后才能進(jìn)行讀寫。由于用fseek()函數(shù)對(duì)文本文件定位時(shí)容易出錯(cuò),因此,隨機(jī)文件通常是二進(jìn)制文件。由于隨機(jī)文件需要按記錄號(hào)安排該記錄在文件中的位置,因此,在寫文件時(shí),應(yīng)有一個(gè)能確定記錄位置的標(biāo)志。3.文件的隨機(jī)存取51用結(jié)構(gòu)類型組織學(xué)生信息,包括學(xué)號(hào)和分?jǐn)?shù)。輸入時(shí)不必按學(xué)號(hào)的順序進(jìn)行,只要輸入學(xué)號(hào)和分?jǐn)?shù),程序自動(dòng)將該記錄寫到文件相應(yīng)的位置上。在進(jìn)行文件指針定位時(shí),要使用fseek()函數(shù),而fseek()函數(shù)在對(duì)文本文件定位時(shí)容易出錯(cuò),因此,隨機(jī)文件通常是二進(jìn)制文件。該程序流程如圖所示?!纠繉W(xué)生考試成績登錄程序。要求登錄學(xué)號(hào)和分?jǐn)?shù)兩個(gè)信息,其中,學(xué)號(hào)也用作記錄的編號(hào)。wb方式打開文件輸入學(xué)號(hào)和成績由學(xué)號(hào)計(jì)算記錄號(hào)寫入該記錄記錄定位

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論