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

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論