C語言程序設(shè)計課件 第10章_第1頁
C語言程序設(shè)計課件 第10章_第2頁
C語言程序設(shè)計課件 第10章_第3頁
C語言程序設(shè)計課件 第10章_第4頁
C語言程序設(shè)計課件 第10章_第5頁
已閱讀5頁,還剩49頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第10章文件10.1文件概述和文件類型指針10.2文件的打開和關(guān)閉10.3文件的讀/寫10.4文件的定位10.5文件的檢測10.6文件的綜合示例本章小結(jié)

10.1文件概述和文件類型指針

10.1.1文件概述文件(file)是程序設(shè)計中一個重要的概念。在計算機系統(tǒng)中,“文件”是指存儲在外部介質(zhì)上的一組相關(guān)數(shù)據(jù)的有序集合。在前面章節(jié)中,我們采用標(biāo)準輸入(鍵盤輸入)和標(biāo)準輸出(顯示器輸出)模式來處理數(shù)據(jù)信息。但大型程序常把外部介質(zhì)(如磁盤)作為信息載體,用于長期存儲輸入和輸出數(shù)據(jù)。

文件系統(tǒng)中,C語言將輸入/輸出設(shè)備當(dāng)作文件,將輸入/輸出文件作為輸入/輸出流對象進行處理。輸入/輸出是數(shù)據(jù)“流動”的過程。當(dāng)輸入操作時,系統(tǒng)利用“讀操作”使數(shù)據(jù)從文件流向計算機內(nèi)存;當(dāng)輸出操作時,系統(tǒng)利用“寫操作”使數(shù)據(jù)從計算機流向文件(如磁盤、打印機等)。

文件可以從不同的角度來進行分類:

(1)按文件所依附的介質(zhì)分類,有卡片文件、紙帶文件、磁帶文件和磁盤文件等。

(2)按文件內(nèi)容分類,有源文件、目標(biāo)程序文件和數(shù)據(jù)文件等。

(3)按文件操作分類,有輸入文件、輸出文件和輸入/輸出文件。

(4)按文件中的數(shù)據(jù)組織形式分類,有字符文件和二進制文件。

字符文件又稱為ASCII文件或文本文件,按字符方式存儲,可用文本編輯器(如Windows系統(tǒng)中的記事本notepad.exe、寫字板wordpad.exe等)進行直接讀寫,但所占存儲空間較大;二進制文件是以二進制方式存儲的,所占存儲空間小,用文本編輯器不便進行直接讀寫。圖10-1顯示了十進制整數(shù)12345以字符文件存儲和以二進制文件存儲的區(qū)別。在C語言系統(tǒng)中,一個文件就是一個字符(字節(jié))流。圖10-1字符文件和二進制文件的存儲區(qū)別

C語言文件系統(tǒng)有兩種:緩沖文件系統(tǒng)(標(biāo)準I/O)和非緩沖文件系統(tǒng)(系統(tǒng)I/O)。緩沖文件系統(tǒng)的特點是:系統(tǒng)在內(nèi)存為正在使用的每一個文件開辟一個固定容量的“緩沖區(qū)”,當(dāng)執(zhí)行讀操作時,先從磁盤上將指定的文件數(shù)據(jù)寫入緩沖區(qū),待緩沖區(qū)裝滿后再從緩沖區(qū)逐個將數(shù)據(jù)送到程序數(shù)據(jù)區(qū);當(dāng)執(zhí)行寫操作時,先將程序數(shù)據(jù)寫入緩沖區(qū),待緩沖區(qū)裝滿后再送到磁盤,如圖10-2所示。

圖10-2標(biāo)準I/O讀寫文件操作示意圖

由此可以看出,緩沖區(qū)越大,對外設(shè)訪問的次數(shù)就越少,執(zhí)行速度就越快、效率越高。一般來說,文件緩沖區(qū)的大小與編程環(huán)境有關(guān),一般為512B。非緩沖文件,系統(tǒng)的特點是系統(tǒng)不會自動為正在使用的每一個文件開辟緩沖區(qū),而由程序根據(jù)自身的需要及系統(tǒng)的存儲資源情況來為每一個文件設(shè)定緩沖區(qū)。目前仍有許多C版本支持非緩沖文件系統(tǒng),但1983年ANSIC標(biāo)準決定不采用非緩沖區(qū)文件系統(tǒng),因此這里建議讀者不要采用不符合ANSIC標(biāo)準的那些部分,以免降低程序的可移植性。

10.1.2文件類型指針

文件類型指針是緩沖文件系統(tǒng)中最重要的概念。對緩沖文件系統(tǒng)來說,ANSIC在內(nèi)存中為每個被使用的文件開辟一小塊固定大小的區(qū)域,用于存放文件的屬性狀態(tài)(如文件名、緩沖區(qū)的位置與大小等信息),該區(qū)域利用一個結(jié)構(gòu)類型變量存放。該變量的結(jié)構(gòu)類型是由系統(tǒng)定義的,取名為FILE,其定義包含在頭文件stdio.h中,格式如下:

在C語言中,允許用類型FILE定義文件指針。每當(dāng)要對某個文件進行操作時,應(yīng)先定義一個FILE類型文件指針指向該文件,然后通過該文件指針對文件進行操作。文件指針的定義格式為

FILE*文件指針名;

例如:

FILE*fp;

定義了一個FILE類型的文件指針,指針名為fp。

10.2文件的打開和關(guān)閉

10.2.1文件的打開和其他高級語言一樣,對文件進行讀/寫操作之前需要先“打開”該文件。所謂“打開”,是指為文件建立相應(yīng)的信息區(qū)(用來存放文件的相關(guān)信息)和文件緩沖區(qū),并建立文件與它們之間的聯(lián)系。C語言提供了打開文件的函數(shù)fopen()。該函數(shù)原型在stdio.h頭文件中,其調(diào)用格式為FILE*fp;fp=fopen("文件名","文件操作模式");

或者將上述兩句合并為下面一句:

FILE*fp=fopen("文件名","文件操作模式");

其功能是打開一個由“文件名”指向的外部文件,返回值是一個指向該文件的文件指針。在文件名中可以指明存儲盤及文件路徑。若文件打開成功,則fp為一非空指針,否則fp值為NULL。表10-1是“文件操作模式”的類別及含義。.

例如:

FILE*fp;

fp=fopen("d:\\class.txt","r");

其功能是以只讀方式在D盤根目錄下打開名為“class.txt”的文本文件,允許進行讀操作,并使fp指向該文件。C語言中,兩個反斜線“\\”屬于轉(zhuǎn)義字符,代表反斜杠字符“\”。

又如:

FILE*fp;

fp=fopen("c:\\class.txt","rb");

其功能是打開C盤根目錄下的文件“class.txt”,只允許按二進制方式進行讀操作。

對于文件操作模式,有以下幾點說明:

(1)凡用“r”打開一個文件時,該文件必須已經(jīng)存在,且只能從該文件讀取數(shù)據(jù)。

(2)凡用“w”打開的文件,只能向該文件寫入。若打開的文件不存在,則以指定的文件名建立該文件。若打開的文件已經(jīng)存在,則將該文件刪去,以指定的文件名重建一個新文件。

(3)若要向一個已存在的文件追加新的信息,只能用追加(“a”)方式打開文件。但此時該文件必須是存在的,否則將會出錯。

(4)在打開一個文件時,如果出錯,fopen()將返回一個空指針值NULL。在程序中可以用這一信息來判別是否完成打開文件的工作,并進行相應(yīng)的處理。

(5)把一個文本文件讀入內(nèi)存時,系統(tǒng)將ASCII碼轉(zhuǎn)換成二進制碼,而把文件以文本方式寫入磁盤時,系統(tǒng)要把二進制碼轉(zhuǎn)換成ASCII碼,因此文本文件的讀寫要花費較多的轉(zhuǎn)換時間。對二進制文件的讀寫不存在這種轉(zhuǎn)換。

(6)標(biāo)準輸入文件(鍵盤)、標(biāo)準輸出文件(顯示器)和標(biāo)準出錯輸出文件(顯示器)是在程序運行時由系統(tǒng)自動打開的,可直接使用而無須打開與它們相連的終端文件。

例10-1在指定路徑下打開一個文件。

上述程序的功能是:如果返回的指針為空,表示不能打開D盤根目錄下的“class.txt”文件,則給出提示信息“cannotopenfile!”。程序中的exit(0)表示終止程序執(zhí)行并返回值0,其在main()函數(shù)中的作用相當(dāng)于return0。

10.2.2文件的關(guān)閉

文件一旦使用完畢,要用關(guān)閉文件函數(shù)把文件關(guān)閉,以免出現(xiàn)文件數(shù)據(jù)丟失等錯誤。所謂“關(guān)閉文件”,就是使文件指針變量不再指向該文件,即讓文件指針變量與被關(guān)閉的文件“脫鉤”。關(guān)閉文件還可將未滿的輸出緩沖區(qū)數(shù)據(jù)寫入文件,將未滿的輸入緩沖區(qū)數(shù)據(jù)取出,以免數(shù)據(jù)丟失,同時撤銷文件信息區(qū)和緩沖區(qū),斷開文件與內(nèi)存的聯(lián)系。C語言提供了關(guān)閉文件的fclose()函數(shù),該函數(shù)原型也在stdio.h頭文件中,其調(diào)用格式為

fclose(文件指針);

若關(guān)閉文件操作成功,則fclose()函數(shù)返回值為0,否則返回EOF(-1)。

例10-2以只讀方式打開和關(guān)閉一個名為class.txt的二進制文件\n。

10.3文件的讀/寫

當(dāng)文件按指定的工作方式打開以后,就可以對文件進行讀和寫操作了。對文本文件來說,可按字符讀寫或按字符串讀寫;對二進制文件來說,可進行成塊的讀寫或格式化的讀寫。C語言提供了多種文件讀/寫函數(shù),如表10-2所示,這些函數(shù)原型都在stdio.h頭文件中。

10.3.1字符讀/寫函數(shù)

fgetc()和fputc()函數(shù)分別用于對文本文件進行單個字符的讀和寫。其調(diào)用格式分別為

ch=fgetc(fp); /*fp為文件指針*/

fgetc(fp)函數(shù)從文件指針?biāo)赶蛭募漠?dāng)前位置返回一個字符,并將文件指針指示器移到下一個字符位置。如果文件指示器已到文件末尾,則函數(shù)返回一個EOF(EOF是一個符號常量,值為-1,定義在stdio.h頭文件中),表示讀入的不是正常的字符而是文件結(jié)束符。

fputc(ch,fp)函數(shù)將字符ch的值寫入fp所指向文件的當(dāng)前位置(文件內(nèi)部指針指向)處,并將文件內(nèi)部指針后移一位。fputc()函數(shù)的返回值是所寫入字符的值,出錯時返回EOF。讀/寫文件操作完成后,應(yīng)關(guān)閉相應(yīng)文件。

例10-3從鍵盤多次輸入單個字符,存到磁盤文件class.txt中,當(dāng)輸入“#”時結(jié)束。

例10-4先將存放于磁盤的指定文本文件的內(nèi)容按只讀方式讀取,再將其顯示到屏幕上。要求采用帶參數(shù)的main(),指定的磁盤文件名由命令行方式通過鍵盤輸入。

對于fgetc()和fputc()函數(shù)的使用,有以下幾點說明:

(1)在fgetc()函數(shù)調(diào)用中,讀取的文件必須是以只讀或讀/寫方式打開的;而在fputc()函數(shù)調(diào)用中,被寫入的文件可用只寫、讀/寫和追加方式打開。

(2)讀取字符的結(jié)果也可用字符變量保存,例如,ch=fgetc(fp)。

(3)在文件內(nèi)部用位置指針來指向文件的當(dāng)前讀/寫位置,每讀/寫一次,該指針均向后移動。在文件打開時,該指針由系統(tǒng)自動設(shè)置,并總是指向文件的首字節(jié)。

(4)在fputc()函數(shù)調(diào)用中,用只寫方式打開一個文件時,如果原來不存在該文件,則在打開時新建立一個以指定名字命名的文件;如果原來已存在一個以該文件名命名的文件,則在打開時將該文件刪去,然后重新建立一個新文件。

10.3.2字符串讀/寫函數(shù)

C語言提供的fgets()和fputs()函數(shù)分別用于實現(xiàn)對文本文件的字符串讀和寫操作。這兩個函數(shù)的調(diào)用格式分別為

fgets(字符數(shù)組,n,fp);

fputs(字符串,fp);

fgets(字符數(shù)組,n,fp)從指定的文件中將長度n-1的字符串讀到字符數(shù)組中,在最后一個讀取的字符后加結(jié)束符?'\0'。若在讀取n-1個字符之前遇到了換行符或EOF,則讀操作結(jié)束。若讀取數(shù)據(jù)成功,函數(shù)fgets()則返回字符數(shù)組的首地址,否則返回NULL。字符數(shù)組名也可以由字符指針變量代替,本質(zhì)上都是將讀取的字符串存放在相應(yīng)的存儲區(qū)中。

fputs(字符串,fp)向指定文件寫入一個字符串,其中字符串可以是字符串常量、字符數(shù)組名或字符型指針變量。字符串結(jié)束符'\0'不寫入。若寫入成功,則函數(shù)值為0;若寫入失敗,則返回為EOF。

fgets()和fputs()函數(shù)與gets()和puts()函數(shù)類似,只是gets()和puts()函數(shù)以終端為操作對象,而fgets()和fputs()函數(shù)以指定的文本文件為操作對象。

例10-5從test.txt文件中讀取字符串,再寫入例10-3的class.txt文件,并顯示后者的內(nèi)容。

本例中要對兩個文件進行操作,需定義兩個文件變量指針。在操作文件以前,應(yīng)將兩個文件以不同的工作方式打開(不分先后),讀/寫完成后再關(guān)閉文件。程序?qū)懭胛募耐瑫r在屏幕上顯示,故程序運行結(jié)束后,在屏幕上可看到目標(biāo)文件class.txt的內(nèi)容。

例10-6從例10-5的class.txt文件中讀入長度為15個字符的字符串并顯示。

該程序先定義一個16字節(jié)的字符數(shù)組string,且以只讀方式打開文本文件class.txt,讀取15個字符并送入string數(shù)組(在數(shù)組最后一個單元內(nèi)將加上?'\0'),然后在屏幕上顯示string數(shù)組。

例10-7向例10-6中的class.txt文件末尾追加一個字符串,并顯示文件內(nèi)容。

10.3.3格式化讀/寫函數(shù)

C語言提供了對磁盤文件進行格式化讀/寫的函數(shù)fscanf()和fprintf()。這兩個函數(shù)的調(diào)用格式分別為

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

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

fscanf()函數(shù)按指定的格式從“文件指針”指向的磁盤文件上將數(shù)據(jù)讀取并存儲至“輸入列表”指定的數(shù)據(jù)緩存區(qū)中。

fprintf()函數(shù)將“輸出列表”數(shù)據(jù)按指定的格式輸出到“文件指針”指向的磁盤文件上。

由于C語言引入了這兩個格式化輸入/輸出函數(shù),因此文件在存儲格式上滿足某種指定格式。例如:

fscanf(fp,"%d%s",&a,str); /*a為整型普通變量,str為字符指針變量或字符數(shù)組名*/

fprintf(fp,"%d%s",a,str);

例10-8先將兩個學(xué)生記錄,包括姓名、學(xué)號、兩科成績的數(shù)據(jù),以格式化的數(shù)據(jù)格式寫入文本文件grades.txt中,再從該文件中以格式化方法讀出并顯示到屏幕上。

10.3.4數(shù)據(jù)塊讀/寫函數(shù)

前面介紹的幾種讀/寫文件的方法,對于復(fù)雜的數(shù)據(jù)類型無法以整體形式向文件寫入或從文件讀出。為了解決這個問題,C語言提供成塊的讀/寫方式來操作文件,使數(shù)組或結(jié)構(gòu)體等類型可以進行一次性讀/寫。

C語言提供的數(shù)據(jù)塊讀/寫函數(shù)fread()和fwrite(),可用來讀/寫一組數(shù)據(jù)(一個數(shù)據(jù)塊)。數(shù)據(jù)塊讀/寫函數(shù)的調(diào)用格式為

fread(buffer,size,n,fp);

fwrite(buffer,size,n,fp);

其中:buffer是一個緩沖區(qū)指針,在fread()函數(shù)中它表示存放讀取數(shù)據(jù)的首地址,在fwrite()函數(shù)中它表示寫入數(shù)據(jù)的首地址;size表示每次讀/寫的數(shù)據(jù)項的字節(jié)數(shù);n表示要連續(xù)讀/寫的數(shù)據(jù)項個數(shù);fp表示文件指針。每調(diào)用一次數(shù)據(jù)塊讀/寫函數(shù)所傳輸?shù)目傋止?jié)數(shù)等于n×size。

fread()函數(shù)從打開的文件fp中讀取n個數(shù)據(jù)項(每個數(shù)據(jù)項的長度為size個字節(jié)),并放入指定的緩沖區(qū)buffer中,所讀的字節(jié)長度為n?×?size。函數(shù)調(diào)用成功后,返回實際讀取的數(shù)據(jù)項個數(shù);若遇文件結(jié)束或出錯,則返回0。

fwrite()函數(shù)把buffer所指向的n個數(shù)據(jù)項(每個數(shù)據(jù)項的長度為size個字節(jié))寫入已經(jīng)打開的文件fp中。函數(shù)返回值為寫到文件中的數(shù)據(jù)項個數(shù)。

例10-9先從鍵盤輸入兩個學(xué)生數(shù)據(jù),并將其寫入student.txt文件中,再讀取這兩個學(xué)生的數(shù)據(jù)使之顯示在屏幕上。

通常,若輸入數(shù)據(jù)的格式較為復(fù)雜,可采取將各種格式的數(shù)據(jù)全部當(dāng)作字符串來輸入,然后將字符串轉(zhuǎn)換為所需的格式。C語言提供如下格式轉(zhuǎn)換函數(shù)來實現(xiàn)這種操作:

intatoi(char*ptr);

floatatof(char*ptr);

longintatol(char*ptr);

它們分別將字符串轉(zhuǎn)換為整型、浮點型和長整型。在程序中加入這些轉(zhuǎn)換函數(shù)后,在程序運行輸入數(shù)據(jù)時,操作者不必記住每種數(shù)據(jù)的類型,這增強了程序的易用性。使用這些函數(shù)時須將其頭文件math.h或stdlib.h寫在程序的前面。

例10-10將輸入的不同格式的數(shù)據(jù)當(dāng)作字符串輸入例10-8的文件中,然后將其轉(zhuǎn)換,進行文件的成塊讀/寫。

10.4文件的定位

C語言提供了rewind()函數(shù)和fseek()函數(shù)來對文件內(nèi)部的位置指針進行移動操作。rewind()函數(shù)把位置指針重新移動到文件首位置,該函數(shù)無返回值;fseek()函數(shù)把位置指針移動到某一指定位置。這兩個函數(shù)的調(diào)用格式為rewind(FILE*fp);fseek(FILE*fp,longoffset,intorigin);

其中:文件指針“fp”指向欲移動的文件。fseek()函數(shù)中,位移量“offset”表示移動的字節(jié)數(shù)且為“l(fā)ong”型數(shù)據(jù),以便在被打開的文件的長度大于64KB時不會出錯(即文件內(nèi)部的位置指針的移動范圍大于64KB)。當(dāng)用常量表示位移量時,要加后綴“L”(表示是長整型數(shù))。若位移量為正值,則表示從起始點向文件尾方向移動;若位移量為負值,則表示從起始點向文件首方向移動。起始點“origin”表示從何處開始計算位移量。規(guī)定的起始點有3種:文件首、當(dāng)前位置和文件尾,其表示方法如表10-3所示。

fseek()函數(shù)若操作成功,則其返回值為0,否則為非0。例如:

fseek(fp,100L,0); /*將位置指針從文件首向文件尾方向移動100個字節(jié)*/

fseek(fp,-10L,1); /*將位置指針從當(dāng)前位置向文件首方向移動10個字節(jié)*/

需要說明的是,fseek()函數(shù)一般用于二進制文件。在文本文件中由于要進行轉(zhuǎn)換而產(chǎn)生誤差,故往往容易出現(xiàn)因計算誤差導(dǎo)致位置指針指向錯誤的問題。當(dāng)文件內(nèi)部的位置指針按要求進行了移動之后,對文件的隨機讀/寫即可用前面介紹的任一種讀/寫函數(shù)進行讀/寫。常通過fread()和fwrite()函數(shù)與fseek()函數(shù)配合使用來對一個數(shù)據(jù)塊進行讀/寫操作。

例10-11從鍵盤輸入字符串到例10-7的class.txt文件中,重新取出時將所有的英文小寫字母轉(zhuǎn)換為英文大寫字母顯示。

例10-12從例10-9中的student.txt文件中讀取第二個學(xué)生的數(shù)據(jù)。

10.5文件的檢測

常用的文件檢測函數(shù)有以下幾個。(1)文件結(jié)束檢測函數(shù)。其調(diào)用格式為feof(文件指針);該函數(shù)的功能是判斷文件是否處于文件結(jié)束位置,如處于文件結(jié)束位置,則返回值為非零值,否則為0。

(2)讀/寫文件出錯檢測函數(shù)。其調(diào)用格式為

ferror(文件指針);

該函數(shù)的功能是檢查文件在用各種輸入/輸出函數(shù)進行讀寫時是否出錯。如ferror()返回值為0,則表示未出錯,否則表示有錯。

(3)文件出錯標(biāo)志清除函數(shù)。其調(diào)用格式為

clearerr(文件指針);

該函數(shù)的功能是清除出錯標(biāo)志和文件結(jié)束標(biāo)志,使它們?yōu)?值。在C程序中,只

溫馨提示

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

評論

0/150

提交評論