版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第9章文件9.1文件概述9.2文件指針9.4文件的讀/寫(xiě)9.5文件的定位9.6文件檢測(cè)函數(shù)
文件是計(jì)算機(jī)中經(jīng)常使用的一個(gè)重要概念。本章在敘述文件概念的基礎(chǔ)上,介紹文
件的基本操作和應(yīng)用,講解文件操作的基本過(guò)程,使讀者熟悉C語(yǔ)言中有關(guān)文件處理的庫(kù)函數(shù)。
學(xué)習(xí)重點(diǎn):
文件指針
文件的讀寫(xiě)
9.1.1文件的定義
文件是指存儲(chǔ)在外部介質(zhì)(如磁盤(pán)和磁帶等外存儲(chǔ)器)上的數(shù)據(jù)或信息的集合。例如:源程序文件中保存著源程序,文本文件中保存著文本數(shù)據(jù),聲音文件中保存著聲音數(shù)據(jù)等。
為標(biāo)識(shí)一個(gè)文件,每個(gè)文件都必須有一個(gè)文件名,其一般結(jié)構(gòu)為:
主文件名[.擴(kuò)展名]9.1文件概述文件命名規(guī)則遵循操作系統(tǒng)的約定。計(jì)算機(jī)通過(guò)文件名對(duì)文件進(jìn)行讀、寫(xiě)、修改和刪除等操作。
C語(yǔ)言實(shí)現(xiàn)文件操作的途徑主要有兩種:一是通過(guò)操作系統(tǒng)。由于操作系統(tǒng)是以文件為單位對(duì)數(shù)據(jù)進(jìn)行管理的,因此可以直接引用操作系統(tǒng)的系統(tǒng)調(diào)用,這屬于低級(jí)的操作,使用方法相對(duì)復(fù)雜,在現(xiàn)在的程序設(shè)計(jì)中已經(jīng)很少使用;二是通過(guò)由C語(yǔ)言編譯系統(tǒng)提供的一套用于文件操作的庫(kù)函數(shù),也稱(chēng)為“標(biāo)準(zhǔn)輸入/輸出庫(kù)”。本章介紹通過(guò)標(biāo)準(zhǔn)輸入/輸出庫(kù)來(lái)使用文件。9.1.2文件的分類(lèi)
可以從不同的角度對(duì)C語(yǔ)言的文件進(jìn)行分類(lèi):
(1)從用戶(hù)的角度看,文件可分為普通文件和設(shè)備文件。
普通文件是指駐留在磁盤(pán)或其他外部介質(zhì)上的數(shù)據(jù)集合,可以是源文件、目標(biāo)文件、可執(zhí)行程序,也可以是一組待輸入處理的原始數(shù)據(jù)或一組輸出的結(jié)果。
設(shè)備文件是指與主機(jī)相連的各種外部設(shè)備,如顯示器、打印機(jī)、鍵盤(pán)等。在操作系統(tǒng)中,外部設(shè)備也被看做是一個(gè)文件,并對(duì)其進(jìn)行管理,將它們的輸入、輸出等同于對(duì)磁盤(pán)文件的讀和寫(xiě)。通常把顯示器定義為標(biāo)準(zhǔn)輸出文件,一般情況下在屏幕上顯示有關(guān)信息就是向標(biāo)準(zhǔn)輸出文件輸出。如前面經(jīng)常使用的printf、putchar函數(shù)就是這類(lèi)輸出。
鍵盤(pán)通常被指定為標(biāo)準(zhǔn)的輸入文件,從鍵盤(pán)上輸入就意味著從標(biāo)準(zhǔn)輸入文件上輸入數(shù)據(jù)。scanf、getchar函數(shù)就屬于這類(lèi)輸入。
(2)從數(shù)據(jù)組織形式的角度來(lái)看,文件可分為ASCII文件和二進(jìn)制文件。數(shù)據(jù)的組織形式是指數(shù)據(jù)在磁盤(pán)上的存儲(chǔ)形式。
ASCII文件又稱(chēng)文本(TEXT)文件,它的數(shù)據(jù)是采用ASCII碼形式存儲(chǔ)的。每一個(gè)字節(jié)放一個(gè)ASCII代碼,代表一個(gè)字符。這樣的好處是便于對(duì)字符進(jìn)行逐個(gè)處理,也便于輸出字符。劣勢(shì)是占存儲(chǔ)空間較多,而且要花費(fèi)轉(zhuǎn)換時(shí)間(二進(jìn)制形式與ASCII碼間的轉(zhuǎn)換)。
二進(jìn)制文件與ASCII文件不同,它是把內(nèi)存中的數(shù)據(jù)按其在內(nèi)存中的存儲(chǔ)形式原樣輸出到磁盤(pán)上存放。這樣可以節(jié)省外存空間和轉(zhuǎn)換時(shí)間,但一個(gè)字節(jié)并不對(duì)應(yīng)一個(gè)字符,不能直接輸出字符形式。圖9-1int型十進(jìn)制數(shù)1024的存儲(chǔ)形式例如:int型的十進(jìn)制數(shù)1024用ASCII形式輸出要占用4個(gè)字節(jié);若按二進(jìn)制形式輸出則只占用2個(gè)字節(jié)。如圖9-1所示。
(3)從C語(yǔ)言對(duì)文件處理方法的角度來(lái)看,可以將文件分為緩沖文件系統(tǒng)和非緩沖文件系統(tǒng)。
所謂“緩沖文件系統(tǒng)”,是指系統(tǒng)自動(dòng)地在內(nèi)存區(qū)為每個(gè)正在使用的文件開(kāi)辟一個(gè)緩沖區(qū)。從內(nèi)存向磁盤(pán)輸出數(shù)據(jù)必須先送到內(nèi)存中的緩沖區(qū),裝滿(mǎn)緩沖區(qū)后再一起送到磁盤(pán)去。如果從磁盤(pán)向內(nèi)存讀入數(shù)據(jù),則一次從磁盤(pán)文件將一批數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿(mǎn)緩沖區(qū)),然后再?gòu)木彌_區(qū)逐個(gè)地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(給程序變量),如圖9-2所示。緩沖區(qū)的大小由各個(gè)具體的C語(yǔ)言版本確定,一般為512字節(jié)。
圖9-2文件的寫(xiě)入—寫(xiě)出所謂“非緩沖文件系統(tǒng)”,是指系統(tǒng)不自動(dòng)開(kāi)辟確定大小的緩沖區(qū),而由程序?yàn)槊總€(gè)文件設(shè)定緩沖區(qū)。
用緩沖文件系統(tǒng)進(jìn)行的輸入/輸出又稱(chēng)為高級(jí)磁盤(pán)輸入/輸出,用非緩沖進(jìn)行的輸入/輸出又稱(chēng)為低級(jí)輸入/輸出系統(tǒng)。ANSIC標(biāo)準(zhǔn)不采用非緩沖文件系統(tǒng),而只采用緩沖文件系統(tǒng)。也就是說(shuō),既用緩沖文件系統(tǒng)處理文本文件,也用它來(lái)處理二進(jìn)制文件。
本章只介紹ANSIC標(biāo)準(zhǔn)中的緩沖文件系統(tǒng)及其相關(guān)的庫(kù)函數(shù)。
在緩沖文件系統(tǒng)中,涉及到的關(guān)鍵概念是“文件指針”。
對(duì)每個(gè)正在使用的文件都要定義一個(gè)FILE結(jié)構(gòu)體類(lèi)型變量,該變量用于存放文件的有關(guān)信息,如文件名、文件狀態(tài)等。9.2文件指針
FILE結(jié)構(gòu)體類(lèi)型不需要用戶(hù)自己定義,它是由系統(tǒng)事先定義的,固定包含在頭文件stdio.h中。其類(lèi)型定義如下:
typedef
struct
{
short level; /*緩沖區(qū)“滿(mǎn)”或“空”的程度*/
unsigned flags; /*文件狀態(tài)標(biāo)志*/
char fd; /*文件描述符*/
unsignedchar hold; /*如無(wú)緩沖區(qū)不讀取字符*/
short bsize; /*緩沖區(qū)的大小*/
unsignedchar *buffer; /*數(shù)據(jù)緩沖區(qū)的位置*/
unsignedchar *curp; /*當(dāng)前讀寫(xiě)位置*/
unsigned istemp; /*臨時(shí)文件,指示器*/
short token; /*用于有效性檢查*/
}FILE;
FILE是該結(jié)構(gòu)體類(lèi)型的類(lèi)型名。在C程序中,凡是要對(duì)已打開(kāi)的文件進(jìn)行操作,都要通過(guò)指向該文件的FILE結(jié)構(gòu)體變量的指針。為此,需要在程序中定義一個(gè)FILE型(文件型)指針變量。
文件型指針變量定義的形式為:
FILE*文件型指針名;
例如:
FILE*fp;
fp定義為一個(gè)FILE結(jié)構(gòu)體類(lèi)型的指針變量。通過(guò)fp可尋找存放某個(gè)文件信息的結(jié)構(gòu)體變量,然后按結(jié)構(gòu)體變量提供的信息找到該文件,從而實(shí)施對(duì)文件的操作。習(xí)慣上也籠統(tǒng)地把fp稱(chēng)為指向一個(gè)文件的指針。
文件在進(jìn)行讀/寫(xiě)操作之前要先打開(kāi),使用完畢要關(guān)閉。所謂打開(kāi)文件,實(shí)際上是建立文件的各種有關(guān)信息,并使文件指針指向該文件,以便進(jìn)行其他操作。關(guān)閉文件則斷開(kāi)指針與文件之間的聯(lián)系,也就禁止再對(duì)該文件進(jìn)行操作。
在C語(yǔ)言中,文件操作都是由庫(kù)函數(shù)來(lái)完成的。9.3文件的打開(kāi)與關(guān)閉9.3.1文件打開(kāi)函數(shù)(fopen)
fopen函數(shù)用來(lái)打開(kāi)一個(gè)文件,其調(diào)用的一般形式為:
文件指針名=fopen(文件名,使用文件方式);
其中,“文件名”是被打開(kāi)文件的文件名,它是字符串常量或字符串?dāng)?shù)組;“使用文件方式”是指文件的類(lèi)型和操作要求;“文件指針名”是一個(gè)FILE類(lèi)型的指針變量,它保存fopen函數(shù)返回指向被打開(kāi)文件的指針。例如:
FILE*fp;
fp=("file1","r");
其功能是在當(dāng)前目錄下打開(kāi)文件file1,只允許進(jìn)行“讀”操作,并使fp指向該文件。
又如:
FILE*fp;
fp=("c:\\a.dat","rb");其功能是打開(kāi)C盤(pán)根目錄下的文件a.dat,這是一個(gè)二進(jìn)制文件,只允許按二進(jìn)制方式進(jìn)行讀操作。
文件使用方式共有12種,表9-1給出了它們的符號(hào)和含義。表9-1文件使用方式的符號(hào)和含義對(duì)于使用文件方式有以下幾點(diǎn)說(shuō)明:
(1)使用文件方式由“r”、“w”、“a”、“b”和“+”五個(gè)字符組成,各字符的含義分
別是:
r(read) 讀
w(write) 寫(xiě)
a(append) 追加
b(banary) 二進(jìn)制文件
+ 讀和寫(xiě)
(2)凡用“r”打開(kāi)一個(gè)文件時(shí),該文件必須已經(jīng)存在,且只能從該文件讀出。
(3)用“w”打開(kāi)的文件只能向該文件寫(xiě)入。若打開(kāi)的文件不存在,則以指定的文件名建立該文件,若打開(kāi)的文件已經(jīng)存在,則將該文件刪去,重建一個(gè)新文件。
(4)若要向一個(gè)已存在的文件追加新的信息,只能用“a”方式打開(kāi)文件。
(5)用“r+”、“w+”、“a+”方式打開(kāi)的文件可以用來(lái)輸入和輸出數(shù)據(jù)。用“r+”方式時(shí)該文件應(yīng)該已經(jīng)存在,以便能向計(jì)算機(jī)輸入數(shù)據(jù)。用“w+”方式則新建立一個(gè)文件,先向此文件寫(xiě)數(shù)據(jù),然后可以讀此文件中的數(shù)據(jù)。用“a+”方式打開(kāi)的文件,原來(lái)的文件不被刪去,位置指針移到文件末尾,則可以添加,也可以讀。
(6)在打開(kāi)一個(gè)文件時(shí),如果出錯(cuò),fopen將返回一個(gè)空指針值NULL。在程序中可以用這一信息來(lái)判別是否完成打開(kāi)文件的工作,并作相應(yīng)的處理。因此常用下面的方法打開(kāi)一個(gè)文件:
if((fp=fopen("file1","r")==NULL)
{
printf("Cannotopenfile1!\n");
exit(0);
}
這段程序的意義是:如果fopen返回的指針為空,則表示不能打開(kāi)文件file1,并給出提示信息“Cannotopenfile1!”,然后執(zhí)行exit(0)退出程序。如果fopen返回的指針不為空,則繼續(xù)執(zhí)行“{}”后面的語(yǔ)句。
(7)把一個(gè)文本文件讀入內(nèi)存時(shí),要將ASCII碼轉(zhuǎn)換成二進(jìn)制碼;而把文件以文本方式寫(xiě)入磁盤(pán)時(shí),也要把二進(jìn)制碼轉(zhuǎn)換成ASCII碼。因此,對(duì)文本文件的讀/寫(xiě)要花費(fèi)較多的轉(zhuǎn)換時(shí)間,對(duì)二進(jìn)制文件的讀/寫(xiě)則不存在這種轉(zhuǎn)換。
(8)在程序開(kāi)始運(yùn)行時(shí),系統(tǒng)自動(dòng)打開(kāi)三個(gè)標(biāo)準(zhǔn)文件,即標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)出錯(cuò)輸出,并分別用文件指針stdin、stdout、stderr指向它們。9.3.2文件關(guān)閉函數(shù)(fclose)
文件一旦使用完畢,應(yīng)用文件關(guān)閉函數(shù)把文件關(guān)閉。文件關(guān)閉后,文件指針變量不再指向該文件,此后不能再通過(guò)該指針對(duì)該文件進(jìn)行讀/寫(xiě)操作,除非再次打開(kāi),使該指針變量重新指向該文件。
fclose函數(shù)調(diào)用的一般形式為:
fclose(文件指針);
例如:
fclose(fp);
正常完成關(guān)閉文件操作時(shí),fclose函數(shù)返回值為0。如返回非零值則表示有錯(cuò)誤發(fā)生。在程序終止之前必須關(guān)閉所有使用的文件。如果不關(guān)閉,可能會(huì)造成數(shù)據(jù)丟失。因?yàn)樵谙蛭募?xiě)數(shù)據(jù)時(shí),先將數(shù)據(jù)輸?shù)骄彌_區(qū),待緩沖區(qū)充滿(mǎn)后才寫(xiě)到磁盤(pán)上的文件中。如果當(dāng)數(shù)據(jù)未充滿(mǎn)緩沖區(qū)而程序結(jié)束運(yùn)行,就會(huì)將緩沖區(qū)中的數(shù)據(jù)丟失。而用fclose函數(shù)關(guān)閉文件,將把緩沖區(qū)中的數(shù)據(jù)寫(xiě)到磁盤(pán)文件,然后釋放文件指針變量。
文件打開(kāi)之后,就可以對(duì)它進(jìn)行讀/寫(xiě)了。C語(yǔ)言編譯系統(tǒng)提供了多種文件讀/寫(xiě)的函數(shù),它們都包含在頭文件stdio.h中。9.4文件的讀/寫(xiě)9.4.1字符讀/寫(xiě)函數(shù)fgetc和fputc
1.讀字符函數(shù)fgetc()
fgetc函數(shù)的功能是從指定的文件中讀取一個(gè)字符,其調(diào)用形式為:
ch=fgetc(fp);
其中,fp為文件型指針變量,ch為字符變量。fgetc函數(shù)返回讀取的字符,并把它賦給ch。若讀取字符時(shí)文件已經(jīng)結(jié)束,則函數(shù)返回文件結(jié)束標(biāo)記EOF。EOF是在頭文件stdio.h中定義的符號(hào)常量,其值為
-1。例如,要從磁盤(pán)文件中順序讀入字符并在屏幕上顯示,可通過(guò)調(diào)用fgetc函數(shù)實(shí)現(xiàn):
while((c=fgetc(fp))!=EOF)
putchar(c);
注意:文件結(jié)束標(biāo)記EOF是不可輸出字符,不能在屏幕上顯示。由于字符的ASCII碼不可能出現(xiàn)
-1,因此EOF定義為
-1是合適的。
對(duì)于fgetc函數(shù)的使用有以下幾點(diǎn)說(shuō)明:
(1)在fgetc函數(shù)調(diào)用中,讀取的文件必須是以讀或讀寫(xiě)方式打開(kāi)的。
(2)讀取字符的結(jié)果也可以不向字符變量賦值,
例如:
fgetc(fp);
但是讀出的字符不能保存。
(3)在文件內(nèi)部有一個(gè)位置指針,用來(lái)指向文件的當(dāng)前讀寫(xiě)字節(jié)。在文件打開(kāi)時(shí),該指針總是指向文件的第一個(gè)字節(jié)。使用fgetc
函數(shù)后,該位置指針將向后移動(dòng)一個(gè)字節(jié),因此可連續(xù)多次使用fgetc函數(shù)來(lái)讀取多個(gè)字符。
應(yīng)注意:文件指針和文件內(nèi)部的位置指針不是一回事。文件指針是指向整個(gè)文件的,須在程序中定義說(shuō)明,只要不重新賦值,文件指針的值是不變的。文件內(nèi)部的位置指針用以指示文件內(nèi)部的當(dāng)前讀寫(xiě)位置,每讀寫(xiě)一次,該指針均向后移動(dòng),它不需在程序中定義說(shuō)明,而是由系統(tǒng)自動(dòng)設(shè)置的。
(4)現(xiàn)在A(yíng)NSIC已允許用緩沖文件系統(tǒng)處理二進(jìn)制文件,而讀入某一個(gè)字節(jié)中的二進(jìn)制數(shù)據(jù)的值有可能是-1,而這又恰好是EOF的值,這就出現(xiàn)了讀入的有用數(shù)據(jù)卻被處理為“文件結(jié)束”的情況。為了解決這個(gè)問(wèn)題,ANSIC提供一個(gè)feof函數(shù)來(lái)判斷文件是否真的結(jié)束。feof(fp)用來(lái)測(cè)試fp所指向的文件當(dāng)前狀態(tài)是否“文件結(jié)束”,如果是,函數(shù)feof(fp)的值為1(真),否則為0(假)。
如果想順序讀入一個(gè)二進(jìn)制文件中的數(shù)據(jù),可以用
while(!feof(fp))
c=fgetc(fp);當(dāng)未遇文件結(jié)束,feof(fp)的值為0,!feof(fp)的值為1,讀入一個(gè)字節(jié)的數(shù)據(jù)賦給整型變量c(可以接著對(duì)這些數(shù)據(jù)進(jìn)行處理)。直到遇文件結(jié)束,feof(fp)的值為1,!feof(fp)的值為0,也就不再執(zhí)行while循環(huán)。
這種方法也適用于文本文件。
【例9-1】在屏幕上顯示文本文件的內(nèi)容。
#include<stdio.h>
#indude<process.h>
voidmain()
{
FILE*fp;
charfilename[20],ch;
printf("Pleaeinputfilename:");
scanf("%s",filename); /*輸入文件名*/
if((fp=fopen(filename,"r"))==NULL) /*打開(kāi)文件*/
{
printf("Cannotopen%s!\n",filename); /*出錯(cuò)處理*/
exit(0);
}
while((ch=fgetc(fp))!=EOF) /*從文件中讀字符*/
putchar(ch); /*顯示從文件讀入的字符*/
fclose(fp); /*關(guān)閉文件*/
}程序運(yùn)行時(shí),先提示輸入文件名(需包含路徑,否則該文件應(yīng)該在程序根目錄下),然后程序以只讀方式打開(kāi)該文件。如果正確打開(kāi)文件,則讀出每個(gè)字符,并顯示在屏幕上,然后關(guān)閉文件;如果打開(kāi)文件時(shí)出錯(cuò),則顯示不能打開(kāi)文件的信息,然后退出程序。
2.寫(xiě)字符函數(shù)fputc()
fputc函數(shù)的功能是將一個(gè)字符輸出到指定文件中,其調(diào)用形式為:
fputc(ch,fp);
其中,ch是要輸出的字符(可為字符常量或字符變量),fp為文件型指針變量。函數(shù)將字符(ch的值)輸出到fp所指向的文件中。如果輸出成功,則返回值就是輸出的字符;如果輸出失敗,則返回EOF。
前面介紹過(guò)的putchar函數(shù)其實(shí)就是從fputc函數(shù)派生出來(lái)的。putchar(c)是用#define定義的宏:
#defineputchar(c)fputc(c,stdout)其中,stdout是系統(tǒng)定義的文件指針變量,它指向終端輸出;fputc(c,stdout)的作用是將c的值輸出到終端。用宏putchar(c)比寫(xiě)fputc(c,stdout)簡(jiǎn)單一些,從用戶(hù)的角度,可以把putchar(c)看做函數(shù)而不必嚴(yán)格地稱(chēng)它為宏。
對(duì)于fputc函數(shù)的使用有以下幾點(diǎn)說(shuō)明:
(1)被寫(xiě)入的文件可以用寫(xiě)、讀寫(xiě)、追加方式打開(kāi)。用寫(xiě)或讀寫(xiě)方式打開(kāi)一個(gè)已存在的文件時(shí),將清除原有的文件內(nèi)容。寫(xiě)入字符從文件首開(kāi)始。如需保留原有文件內(nèi)容,希望把寫(xiě)入的字符存放到文件末,必須以追加方式打開(kāi)文件。被寫(xiě)入的文件若不存在,則創(chuàng)建該文件。
(2)每寫(xiě)入一個(gè)字符,文件內(nèi)部位置指針向后移動(dòng)一個(gè)字節(jié)。
【例9-2】編程完成文本文件的復(fù)制。
#include<stdio.h>
voidmain()
{
FILE*fp1,*fp2;
charfile1[20],file2[20],ch;
printf("Pleaseinputfilename1:");
scanf("%s",file1);
printf("Pleaseinputfilename2:");
scanf("%s",file2);
if((fp1=fopen(file1,"r"))==NULL)/*以“只讀”方式打開(kāi)文件1*/
{
printf("Cannotopen%s!\n",file1);
exit(0);
}
if((fp2=fopen(file2,"w"))==NULL) /*以“寫(xiě)”方式打開(kāi)文件2*/
{
printf("Cannotopen%s!\n",file2);
exit(0);
}
while((ch=fgetc(fp1))!=EOF) /*從文件fp1中讀字符*/
fputc(ch,fp2); /*寫(xiě)入文件fp2中*/
fclose(fp1); /*關(guān)閉兩個(gè)文件*/
fclose(fp2);
}
程序運(yùn)行結(jié)果為:
Pleaseinputfilename1:e:\test.txt<回車(chē)>
Pleaseinputfilename2:e:\test1.txt<回車(chē)>
test.txt為原有文件,在E盤(pán)根目錄下;test1.txt為新復(fù)制的文件,也在E盤(pán)根目錄下。
也可以在輸入命令行時(shí)把兩個(gè)文件名一起輸入。這時(shí)要用到main函數(shù)的參數(shù)。程序可改為:
#include<stdio.h>
voidmain(int
argc,char*argv[])
{
FILE*fp1,*fp2;
charch;
if(argc!=3)
{
printf("Mustinputtwofilenames!\n");
exit(0);
}
if((fp1=fopen(argv[1],"r"))==NULL)/*以“只讀”方式打開(kāi)文件1*/
{
printf("Cannotopen%s!\n",argv[1]);
exit(0);
}
if((fp2=fopen(argv[2],"w"))==NULL)/*以“寫(xiě)”方式打開(kāi)文件2*/
{
printf("Cannotopen%s!\n",argv[2]);
exit(0);
}
while((ch=fgetc(fp1))!=EOF) /*從文件fp1中讀字符*/
fputc(ch,fp2); /*寫(xiě)入文件fp2中*/
fclose(fp1); /*關(guān)閉兩個(gè)文件*/
fclose(fp2);
}假設(shè)該程序的源文件名為MyCopy.c,經(jīng)編譯、連接后得到的可執(zhí)行文件名為
MyCopy.exe,
把它放在C盤(pán)根目錄下,
則在DOS命令提示符窗口中,
可按如下方式復(fù)制
文件:
C:\>MyCopy
e:\test.txte:\test1.txt<回車(chē)>9.4.2字符串讀/寫(xiě)函數(shù)fgets和fputs
fgets()和fputs()函數(shù)是以字符串為單位對(duì)文件進(jìn)行讀/寫(xiě)的,由于這兩個(gè)函數(shù)在使用中往往是一次讀/寫(xiě)一行,所以也稱(chēng)為行讀/寫(xiě)函數(shù)。
1.讀字符串函數(shù)fgets()
fgets函數(shù)的功能是從指定的文件中讀一個(gè)字符串到字符數(shù)組中,其調(diào)用形式為:
fgets(字符數(shù)組名,n,文件指針);
其中,n是一個(gè)正整數(shù),表示從文件中讀出n-1個(gè)字符,并在最后一個(gè)字符后加上串結(jié)束標(biāo)志
'\0',將它們一起放入字符數(shù)組中。如果在讀入n-1個(gè)字符結(jié)束之前遇到換行符或EOF,讀入即結(jié)束。如果操作正確,函數(shù)的返回值為字符數(shù)組的首地址;如果文件結(jié)束或出錯(cuò),則函數(shù)的返回值為NULL。
【例9-3】從D盤(pán)根目錄下的test.txt文件中讀入一個(gè)含10個(gè)字符的字符串。
#include<stdio.h>
voidmain()
{
FILE*fp;
charstr[11];
if((fp=fopen("d:\\test.txt","r"))==NULL)
{
printf("Cannotopenfile!");
exit(0);
}
fgets(str,11,fp);
printf("\n%s\n",str);
fclose(fp);
}本例定義了一個(gè)字符數(shù)組str共11個(gè)字節(jié),在以只讀文件方式打開(kāi)D盤(pán)上文件test.txt后,從中讀出10個(gè)字符送入str數(shù)組,在數(shù)組最后一個(gè)單元內(nèi)將加上
'\0',然后在屏幕上顯示輸出str數(shù)組。
2.寫(xiě)字符串函數(shù)fputs()
fputs函數(shù)的功能是向指定的文件寫(xiě)入一個(gè)字符串,其調(diào)用形式為:
fputs(字符串,文件指針);
其中,“字符串”可以是字符串常量,也可以是字符數(shù)組名或字符型指針變量,例如:
fputs("abcd",fp);
其意義是把字符串
"abcd"
寫(xiě)入fp所指的文件之中。
【例9-4】從鍵盤(pán)輸入若干行字符存入D盤(pán)根目錄下的文件file.txt中。
#include<stdio.h>
#include<string.h>
voidmain()
{
FILE*fp;
charstr[81];
if((fp=fopen("D:\\file.txt","w"))==NULL)
{
printf("Cannotopenfile!\n");
exit(0);
}
while(strlen(gets(str))>0)
{
fputs(str,fp);fputs("\n",fp);
}
fclose(fp);
}程序以只寫(xiě)方式打開(kāi)D盤(pán)根目錄下的文件file.txt后,用一個(gè)while循環(huán)來(lái)完成從鍵盤(pán)輸入字符串,并把字符串寫(xiě)到文件中。gets(str)表示從鍵盤(pán)獲取字符串,并把它保存到字符數(shù)組str中。strlen()函數(shù)測(cè)試輸入的字符串的字符個(gè)數(shù),如果大于0,則用函數(shù)fputs把保存在str中的字符串寫(xiě)到文件中。fputs("\n",fp)表示向文件中輸入一個(gè)換行符,使位置指針移到下一行開(kāi)始。9.4.3數(shù)據(jù)塊讀/寫(xiě)函數(shù)fread和fwrite
C語(yǔ)言提供了讀寫(xiě)整塊數(shù)據(jù)的函數(shù)fread和fwrite。它們可用來(lái)讀/寫(xiě)一組數(shù)據(jù),如一個(gè)數(shù)組元素,一個(gè)結(jié)構(gòu)體變量的值等。
讀數(shù)據(jù)塊函數(shù)調(diào)用的一般形式為:
fread(buffer,size,count,fp);
寫(xiě)數(shù)據(jù)塊函數(shù)調(diào)用的一般形式為:
fwrite(buffer,size,count,fp);
其中:buffer是一個(gè)指針。在fread函數(shù)中,它表示存放輸入數(shù)據(jù)的首地址;在fwrite函數(shù)中,它表示存放輸出數(shù)據(jù)的首地址。size表示數(shù)據(jù)塊的字節(jié)數(shù)。count表示要讀/寫(xiě)的數(shù)據(jù)塊塊數(shù)。fp表示文件指針。
例如:
fread(fa,4,5,fp);
其意義是從fp所指的文件中,每次讀4個(gè)字節(jié)(一個(gè)實(shí)數(shù))送入實(shí)數(shù)數(shù)組fa中,連續(xù)讀5次,即讀5個(gè)實(shí)數(shù)到fa中。
【例9-5】定義一個(gè)包含學(xué)生信息的結(jié)構(gòu)體變量,其中包括學(xué)號(hào)、姓名、年齡、班級(jí)等幾個(gè)成員。然后從鍵盤(pán)輸入3個(gè)學(xué)生的信息,并把它們存儲(chǔ)到D盤(pán)根目錄下的文件student.dat中。
源程序如下:
#include<stdio.h>
structstudent
{
intnumber;
charname[10];
intage;
charclass[10];
};
voidmain()
{
FILE*fp;
structstudents;
inti,size;
size=sizeof(structstudent);
if((fp=fopen("D:\\student.dat","wb"))==NULL)
{
printf("Cannotopenthefile!");
exit(0);
}
for(i=0;i<3;i++)
{
scanf("%d%s%d%s",&s.number,&,&s.age,&s.class);
fwrite(&s,size,1,fp);
}
fclose(fp);
}程序運(yùn)行結(jié)果為:
101wang20200203<回車(chē)>
102zeng19200203<回車(chē)>
103zhang19200203<回車(chē)>
該程序定義了一個(gè)結(jié)構(gòu)體類(lèi)型student。先打開(kāi)或建立D盤(pán)上的二進(jìn)制文件student.dat,然后用一個(gè)for循環(huán)依次輸入3個(gè)學(xué)生的學(xué)號(hào)、姓名、年齡和班級(jí)。每輸入一個(gè)學(xué)生的信息,就把它寫(xiě)入文件。sizeof(structstudent)是求結(jié)構(gòu)體類(lèi)型student的長(zhǎng)度(字節(jié)數(shù))。fwrite(&s,size,1,fp)是把結(jié)構(gòu)體變量的內(nèi)容寫(xiě)入fp所指的文件中,注意必須傳遞變量s的地址給函數(shù),“1”表示輸出1個(gè)結(jié)構(gòu)體變量的內(nèi)容。
【例9-6】D盤(pán)根目錄下的文件student.dat中存儲(chǔ)有學(xué)生的學(xué)號(hào)、姓名、年齡、班級(jí)等信息,編寫(xiě)程序把年齡小于20歲的學(xué)生信息顯示出來(lái)。
源程序如下:
#include<stdio.h>
structstudent
{
intnumber;
charname[10];
intage;
charclass[10];
};
voidmain()
{
FILE*fp;
structstudents;
intsize;
size=sizeof(structstudent);
if((fp=fopen("D:\\student.dat","rb"))==NULL)
{
printf("Cannotopenthefile!");
exit(0);
}
while(!feof(fp))
{
fread(&s,size,1,fp);
if(s.age<20)
printf("%d%s%d%s\n",s.number,,s.age,s.class);
}
fclose(fp);
}
程序運(yùn)行結(jié)果為:
102zeng19200203
103zhang192002039.4.4格式化讀/寫(xiě)函數(shù)fscanf和fprintf
函數(shù)fscanf和fprintf與前面使用的scanf和printf功能相似,都是格式化讀/寫(xiě)函數(shù)。兩者的區(qū)別在于:fscanf和fprintf的讀/寫(xiě)對(duì)象是磁盤(pán)文件;scanf和printf的讀/寫(xiě)對(duì)象是標(biāo)準(zhǔn)輸入/輸出設(shè)備(鍵盤(pán)/顯示器)。
fscanf函數(shù)和fprintf函數(shù)的調(diào)用形式分別為:
fscanf(文件指針,格式字符串,輸入表列);
fprintf(文件指針,格式字符串,輸出表列);
例如:
fscanf(fp,"%d%s",&i,s);該語(yǔ)句是從fp所指的文件中讀入一個(gè)整數(shù)和一個(gè)字符串,分別送給整型變量i和字符數(shù)組s。
又如:
fprintf(fp,"%d%c",j,ch);
該語(yǔ)句把整型變量j和字符變量ch的值依次寫(xiě)入fp所指的文件中。
可以看到,函數(shù)fscanf和fprintf與函數(shù)scanf和printf的格式也非常類(lèi)似,只是多了文件指針項(xiàng),用于指明要操作的文件,而格式字符串和輸入/輸出表列與scanf和printf中的規(guī)則完全一致?!纠?-7】從鍵盤(pán)輸入一個(gè)字符串和一個(gè)十進(jìn)制整數(shù),并將它們寫(xiě)入test.txt文件中,然后再?gòu)膖est.txt文件中讀出并顯示在屏幕上。
源程序如下:
#include<stdio.h>
voidmain()
{
chars[81];
inta;
FILE*fp;
if((fp=fopen("test.txt","w"))==NULL) /*以寫(xiě)方式打開(kāi)文本文件*/
{
printf("Cannotopenfile.\n");
exit(0);
}
printf("Pleaseinputastringandainteger:\n");
fscanf(stdin,"%s%d",s,&a); /*從標(biāo)準(zhǔn)輸入設(shè)備(鍵盤(pán))上讀取數(shù)據(jù)*/
fprintf(fp,"%s%d",s,a); /*以格式輸出方式寫(xiě)入文件*/
fclose(fp); /*寫(xiě)文件結(jié)束關(guān)閉文件*/
printf("Begoingtoprintastringandaintegerfromthefiletest.txt!\n");
if((fp=fopen("test.txt","r"))==NULL) /*以讀方式打開(kāi)文本文件*/
{
printf("Cannotopenfile.\n");
exit(0);
}
fscanf(fp,"%s%d",s,&a); /*以格式輸入方式從文件讀取數(shù)據(jù)*/
fprintf(stdout,"%s%d\n",s,a); /*將數(shù)據(jù)顯示到標(biāo)準(zhǔn)輸出設(shè)備(屏幕)上*/
fclose(fp); /*讀文件結(jié)束關(guān)閉文件*/
}
程序運(yùn)行結(jié)果為:
Pleaseinputastringandainteger:
abce12359<回車(chē)>
Begoingtoprintastringandaintegerfromthefiletest.txt!
abce12359
該程序在從鍵盤(pán)輸入數(shù)據(jù)時(shí)使用fscanf(stdin,"%s%d",s,&a),它同scanf("%s%d",s,&a)的功能相同。同樣,fprintf(stdout,"%s%d\n",s,a)與printf("%s%d\n",s,a)的功能也相同。
前面提到,文件中有一個(gè)位置指針,指向當(dāng)前讀/寫(xiě)的位置。文件剛打開(kāi)時(shí),位置指針指向開(kāi)始位置或者末尾。利用前面介紹的函數(shù)讀/寫(xiě)后,位置指針則會(huì)往后移動(dòng)相應(yīng)長(zhǎng)度的距離。也就是說(shuō),文件的讀/寫(xiě)是順序往后進(jìn)行的,但在實(shí)際問(wèn)題中有時(shí)需要只讀/寫(xiě)文件中某一指定的部分。為此,C語(yǔ)言編譯系統(tǒng)提供了移動(dòng)文件位置指針的函數(shù)。9.5文?件?的?定?位9.5.1fseek函數(shù)
fseek函數(shù)用來(lái)移動(dòng)文件的位置指針,其調(diào)用形式為:
fseek(文件指針,位移量,起始點(diǎn));
其中:“文件指針”指向文件?!拔灰屏俊北硎疽苿?dòng)的字節(jié)數(shù),要求位移量是long型數(shù)據(jù),以便在文件長(zhǎng)度大于64
KB時(shí)不會(huì)出錯(cuò)。當(dāng)用常量表示位移量時(shí),要求加后綴“L”。“起始點(diǎn)”表示從何處開(kāi)始計(jì)算位移量,規(guī)定的起始點(diǎn)有三種:文件首,當(dāng)前位置和文件尾。其表示方法如表9-2所示。表9-2起始點(diǎn)的表示例如:
fseek(fp,100L,0);
其意義是把fp所指文件的位置指針移到離文件首100個(gè)字節(jié)處。
又如:
fseek(fp,
-10L,2);
其意義是將位置指針從文件末尾處向后退(即往文件開(kāi)始方向)10個(gè)字節(jié)。
應(yīng)該注意的是:fseek函數(shù)一般用于二進(jìn)制文件,因?yàn)槲谋疚募l(fā)生字符轉(zhuǎn)換,計(jì)算位置時(shí)往往會(huì)發(fā)生混亂。
【例9-8】例9-5中,在D盤(pán)根目錄下的文件student.dat中存儲(chǔ)了3個(gè)學(xué)生的學(xué)號(hào)、姓名、年齡、班級(jí)等信息,編寫(xiě)程序把第2個(gè)學(xué)生信息顯示出來(lái)。
源程序如下:
#include<stdio.h>
structstudent
{
intnumber;
charname[10];
intage;
charclass[10];
};
voidmain()
{
FILE*fp;
structstudents;
inti,size;
size=sizeof(structstudent);
if((fp=fopen("D:\\student.dat","rb"))==NULL)
{
printf("Cannotopenthefile!");
exit(0);
}
fseek(fp,size,0);
fread(&s,size,1,fp);
printf("%d%s%d%s\n",s.number,,s.age,s.class);
fclose(fp);
}程序運(yùn)行結(jié)果為:
102zeng19200203
該程序中的fseek(fp,size,0)將文件的位置指針相對(duì)于文件開(kāi)始向后移動(dòng)一個(gè)student結(jié)構(gòu)體的字節(jié)數(shù),即移到第2個(gè)學(xué)生信息的開(kāi)始位置。9.5.2rewind函數(shù)
rewind函數(shù)的作用是使位置指針重新返回文件的開(kāi)頭,其調(diào)用形式為:
rewind(文件指針);
例如:
rewind(fp);
其意義是將fp所指文件的位置指針重新移到文件開(kāi)頭。
【例9-9
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2022年小學(xué)教師資格考試《綜合素質(zhì)》每日一練試題 含答案
- 2022-2024年三年高考1年模擬地理試題分類(lèi)匯編:地球上的大氣(解析版)
- 2022-2024年江蘇中考英語(yǔ)試題匯編:?jiǎn)雾?xiàng)選擇之冠詞、名詞和代詞(教師)
- 2024年綠化用地租賃與生態(tài)旅游項(xiàng)目合作合同2篇
- 2024年鋼管物流服務(wù)標(biāo)準(zhǔn)協(xié)議版B版
- 2024版二手房定金合同模板集錦3篇
- 2024年知識(shí)產(chǎn)權(quán)授權(quán)許可與運(yùn)營(yíng)管理委托合同3篇
- 2024版?zhèn)}單質(zhì)押融資業(yè)務(wù)監(jiān)管協(xié)議
- 2024旅游行業(yè)知識(shí)產(chǎn)權(quán)保護(hù)免責(zé)協(xié)議書(shū)范本維護(hù)知識(shí)產(chǎn)權(quán)3篇
- 2024年貸款居間服務(wù)具體合同版B版
- 2024年度危廢培訓(xùn)完整課件
- 福建師范大學(xué)《教育學(xué)(含教師職業(yè)道德)》2023-2024學(xué)年第一學(xué)期期末試卷
- 蘋(píng)果三星專(zhuān)利之爭(zhēng)
- 人教版2024-2025學(xué)年六年級(jí)數(shù)學(xué)上冊(cè)5.4 扇形的面積 同步練習(xí)(附答案解析)
- 《Java程序設(shè)計(jì)應(yīng)用開(kāi)發(fā)》全套教學(xué)課件
- 學(xué)校食堂菜譜及定價(jià)方案
- 高考英語(yǔ)一輪復(fù)習(xí)英語(yǔ)語(yǔ)法專(zhuān)題復(fù)習(xí):時(shí)態(tài)和語(yǔ)態(tài)課件(共45張)
- 必背知識(shí)點(diǎn)梳理-2024-2025學(xué)年人教版生物七年級(jí)上冊(cè)
- 2024-2030年中國(guó)非物質(zhì)文化遺產(chǎn)行業(yè)市場(chǎng)深度分析及競(jìng)爭(zhēng)格局與投資策略研究報(bào)告
- 2023-2024學(xué)年部編版道德與法治三年級(jí)上冊(cè)期末檢測(cè)題及答案(共3套)
- 血透并發(fā)癥低血壓
評(píng)論
0/150
提交評(píng)論