




版權(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文件處理10.3文件的順序讀寫10.4文件的隨機(jī)讀寫10.5文件檢測(cè)函數(shù)本章小結(jié)
10.1文件概述
在以往的程序中,往往是從鍵盤輸入數(shù)據(jù),并將輸出顯示在計(jì)算機(jī)屏幕上。程序運(yùn)行完畢后,所有數(shù)據(jù)都會(huì)消失。這樣顯然不滿足一些實(shí)際需求。比如,在學(xué)生學(xué)籍管理系統(tǒng)中,需要將學(xué)生的相關(guān)信息以文件形式保存下來(lái)。本章介紹的C語(yǔ)言中文件的相關(guān)知識(shí)正是為了解決此類問(wèn)題。所謂“文件”,是指存放在外部介質(zhì)中的一組相關(guān)數(shù)據(jù)的有序集合。這個(gè)數(shù)據(jù)集合有一個(gè)名字,稱為文件名。操作系統(tǒng)是以文件為單位對(duì)數(shù)據(jù)進(jìn)行管理的。也就是說(shuō),如果想找存放在外部介質(zhì)中的數(shù)據(jù),就必須先按文件名找到所指定的文件,然后再?gòu)脑撐募凶x取數(shù)據(jù)。若要在外部介質(zhì)中存儲(chǔ)數(shù)據(jù),也必須先建立一個(gè)文件(以文件名為標(biāo)識(shí)),然后才能向它輸出數(shù)據(jù)。實(shí)際上,前面各章中已經(jīng)多次使用了文件,例如源程序文件、目標(biāo)文件、可執(zhí)行文件、庫(kù)文件(頭文件)等。在C語(yǔ)言中,文件是一串連續(xù)的字節(jié),每個(gè)字節(jié)均能被單獨(dú)讀取。C語(yǔ)言程序?qū)ξ募奶幚硎峭ㄟ^(guò)標(biāo)準(zhǔn)函數(shù)庫(kù)中的文件操作函數(shù)實(shí)現(xiàn)的,使用這些函數(shù),可以簡(jiǎn)單、高效、安全地訪問(wèn)外部數(shù)據(jù)。此外,C語(yǔ)言中所有的外部設(shè)備均被作為文件對(duì)待,這種文件稱為設(shè)備文件。對(duì)外部設(shè)備的輸入/輸出處理就是讀/寫設(shè)備文件的過(guò)程。設(shè)備文件是指與主機(jī)相連的各種外部設(shè)備,如顯示器、打印機(jī)、鍵盤等。在操作系統(tǒng)中,將外部設(shè)備作為一個(gè)文件來(lái)進(jìn)行管理,它們的輸入、輸出等同于對(duì)磁盤文件的讀和寫。通常把顯示器定義為標(biāo)準(zhǔn)輸出文件。一般情況下,在屏幕上顯示有關(guān)信息就是向標(biāo)準(zhǔn)輸出文件輸出數(shù)據(jù),如前面經(jīng)常使用的printf、putchar函數(shù)就屬于這類輸出。鍵盤通常被指定為標(biāo)準(zhǔn)輸入文件。從鍵盤上輸入就意味著從標(biāo)準(zhǔn)輸入文件上輸入數(shù)據(jù),如scanf、getchar函數(shù)就屬于這類輸入。10.1.1文本文件與二進(jìn)制文件
從文件編碼的方式來(lái)看,文件可分為ASCII文件和二進(jìn)制文件兩種。
ASCII文件也稱為文本文件,這種文件在磁盤中存放時(shí)每個(gè)字符對(duì)應(yīng)一個(gè)字節(jié),用于存放對(duì)應(yīng)的ASCII碼。
例如,數(shù)5678的存儲(chǔ)形式為
ASCII碼:00110101001101100011011100111000
↓↓↓↓
十進(jìn)制碼:5?678
共占用4個(gè)字節(jié)。
ASCII文件可在屏幕上按字符顯示。例如,源程序文件就是ASCII文件,用DOS命令TYPE可顯示文件的內(nèi)容。由于ASCII文件是按字符顯示的,因此能讀懂文件內(nèi)容。
二進(jìn)制文件是按二進(jìn)制的編碼方式來(lái)存放文件的。例如,數(shù)5678的存儲(chǔ)形式為
0001011000101110
只占兩個(gè)字節(jié)。二進(jìn)制文件雖然也可在屏幕上顯示,但其內(nèi)容無(wú)法讀懂。C系統(tǒng)在處理這些文件時(shí),并不區(qū)分類型,都看成是字符流,按字節(jié)進(jìn)行處理。10.1.2文件緩沖區(qū)
文件緩沖區(qū)可以分為輸出文件緩沖區(qū)和輸入文件緩沖區(qū)。
在程序運(yùn)行過(guò)程中,程序要將保存在內(nèi)存中的數(shù)據(jù)寫入磁盤,首先要建立一個(gè)“輸出文件緩沖區(qū)”,這個(gè)緩沖區(qū)是連接計(jì)算機(jī)內(nèi)存數(shù)據(jù)與外存文件的橋梁。當(dāng)向文件輸出數(shù)據(jù)時(shí),準(zhǔn)備輸出的數(shù)據(jù)先送入文件緩沖區(qū),等文件緩沖區(qū)數(shù)據(jù)裝滿后再一起送到文件中。這一過(guò)程稱為“寫文件”,是數(shù)據(jù)輸出過(guò)程。與“寫文件”過(guò)程相對(duì)的是要將保存在文件中的數(shù)據(jù)讀入內(nèi)存。首先要建立一個(gè)“輸入文件緩沖區(qū)”,當(dāng)從文件中輸入數(shù)據(jù)時(shí),也是把準(zhǔn)備輸入的數(shù)據(jù)先送入文件緩沖區(qū),等文件緩沖區(qū)數(shù)據(jù)裝滿之后再整個(gè)送到程序數(shù)據(jù)區(qū)。這一過(guò)程稱為“讀文件”,是數(shù)據(jù)輸入過(guò)程。
圖10-1所示為使用緩沖區(qū)的文件讀?寫示意圖,這種數(shù)據(jù)的讀寫方式提高了程序的執(zhí)行效率。圖10-1使用緩沖區(qū)的文件讀、寫示意圖10.1.3文件的指針
在C語(yǔ)言中用一個(gè)指針變量指向一個(gè)文件,這個(gè)指針?lè)Q為文件指針。通過(guò)文件指針可對(duì)它所指的文件進(jìn)行各種操作。為了能正常使用文件,C語(yǔ)言系統(tǒng)要對(duì)打開(kāi)的每一個(gè)文件從多方面進(jìn)行跟蹤管理,如文件緩沖區(qū)的大小、文件緩沖區(qū)的位置、文件緩沖區(qū)使用的程度、文件操作模式、文件內(nèi)部讀寫位置等,這些信息被記錄在“文件信息區(qū)”的結(jié)構(gòu)體變量中,該變量的數(shù)據(jù)類型由C語(yǔ)言系統(tǒng)事先定義,固定包含在頭文件“stdio.h”中,數(shù)據(jù)類型名為“FILE”。以下是TurboC2.0文件指針類型的定義:
typedefstruct
{
int level; /*緩沖區(qū)被占用的程度*/
unsigned flags; /*文件狀態(tài)標(biāo)記*/
char fd; /*文件描述符*/
unsignedchar hold; /*如無(wú)緩沖區(qū),則不讀取字符*/
short bsize; /*緩沖區(qū)大小*/
unsignedchar *buffer; /*文件緩沖區(qū)指針*/
unsignedchar *curp; /*文件定位指針*/
unsigned istemp; /*臨時(shí)文件標(biāo)識(shí)*/
short token; /*用于合法性檢測(cè)*/
}FILE;這里,F(xiàn)ILE就是所定義的文件指針類型的類型名。在定義中使用了“typedef”關(guān)鍵字,它的作用是把用struct定義的結(jié)構(gòu)體類型命名為“FILE”。
在C語(yǔ)言中,要對(duì)已打開(kāi)的文件進(jìn)行操作,就要通過(guò)指向該文件結(jié)構(gòu)體的指針,因此需要在程序中定義FILE類型的指針變量,并使其指向要操作的文件。
定義文件指針的一般形式為
FILE*指針變量標(biāo)識(shí)符;
例如:
FILE*fp;
表示fp是指向FILE類型結(jié)構(gòu)體的指針變量,通過(guò)fp即可找到存放某個(gè)文件信息的結(jié)構(gòu)體變量,然后按結(jié)構(gòu)體變量提供的信息找到該文件,實(shí)施對(duì)文件的操作。習(xí)慣上,把fp稱為指向一個(gè)文件的指針。 10.2文件處理
10.2.1文件的打開(kāi)
打開(kāi)一個(gè)文件應(yīng)使用fopen函數(shù),其調(diào)用形式為
FILE*fp;
fp=fopen(文件名,使用文件方式);
例如:
FILE*fp;
fp=fopen(“a”,“r”);
其意義是在當(dāng)前目錄下打開(kāi)文件a,只允許進(jìn)行“讀入”(r代表read,即讀入)操作,fopen函數(shù)帶回指向a文件的指針并賦給fp。
又如:
FILE*fphzk;
fphzk=fopen("c:\\hzk16","rb");其意義是打開(kāi)C驅(qū)動(dòng)器磁盤的根目錄下的文件hzk16,這是一個(gè)二進(jìn)制文件,只允許按二進(jìn)制方式進(jìn)行讀操作。兩個(gè)反斜線“\\”中的第一個(gè)表示轉(zhuǎn)義字符,第二個(gè)表示根目錄。
由以上兩個(gè)例子可以看出,在打開(kāi)一個(gè)文件時(shí),通知編譯系統(tǒng)以下3個(gè)信息:
①需要打開(kāi)的文件名;
②文件使用方式;
③讓哪一個(gè)指針變量指向被打開(kāi)的文件。
文件使用方式共有12種,如表10-1所示。對(duì)于文件使用方式有以下幾點(diǎn)說(shuō)明:
(1)文件使用方式由r、w、a、t、b、+六個(gè)字符拼成,各字符的含義是:
r(read):讀;
w(write):寫;
a(append):追加;
t(text):文本文件,可省略不寫;
b(banary):二進(jìn)制文件;
+:讀和寫。
(2)用?"r"?方式打開(kāi)一個(gè)文件時(shí),該文件必須已經(jīng)存在,且只能從該文件讀出數(shù)據(jù)。
(3)用?“w”?方式打開(kāi)一個(gè)文件時(shí),若打開(kāi)的文件不存在,則以指定的文件名建立該文件;若打開(kāi)的文件已經(jīng)存在,則將該文件刷新。以該方式打開(kāi)的文件只能寫,不能讀。
(4)若要向一個(gè)已存在的文件追加新的信息,只能用?“a”?方式打開(kāi)文件,但此時(shí)該文件必須是存在的,否則將會(huì)出錯(cuò)。
(5)在打開(kāi)一個(gè)文件時(shí),如果出錯(cuò),fopen函數(shù)將返回一個(gè)空指針值NULL。在程序中可以用這一信息來(lái)判別是否完成打開(kāi)文件的工作,并作相應(yīng)的處理。因此常用以下程序段打開(kāi)文件:
if((fp=fopen(“c:\\hzk16”,“rb”))==NULL)
{
printf(“\nerroronopenc:\\hzk16file!”);
getch();
exit(1);
}這段程序的含義是,如果返回的指針為空,表示不能打開(kāi)C盤根目錄下的hzk16文件,則給出提示信息“erroronopenc:\\hzk16file!”。getch()的功能是從鍵盤輸入一個(gè)字符,但不在屏幕上顯示。在這里,該行的作用是等待,只有當(dāng)用戶從鍵盤敲任一鍵時(shí),程序才繼續(xù)執(zhí)行,因此用戶可利用這個(gè)等待時(shí)間閱讀出錯(cuò)提示。敲鍵后執(zhí)行exit(1)退出程序。
(6)把一個(gè)文本文件讀入內(nèi)存時(shí),要將ASCII碼轉(zhuǎn)換成二進(jìn)制碼,而把文件以文本方式寫入磁盤時(shí),也要把二進(jìn)制碼轉(zhuǎn)換成ASCII碼,因此文本文件的讀寫要花費(fèi)較多的轉(zhuǎn)換時(shí)間。二進(jìn)制文件的讀寫不存在這種轉(zhuǎn)換。
(7)標(biāo)準(zhǔn)輸入文件(鍵盤)、標(biāo)準(zhǔn)輸出文件(顯示器)、標(biāo)準(zhǔn)出錯(cuò)輸出(出錯(cuò)信息)是由系統(tǒng)打開(kāi)的,可直接使用。10.2.2文件的關(guān)閉
文件一旦使用完畢,應(yīng)用關(guān)閉文件函數(shù)把文件關(guān)閉,以避免文件的數(shù)據(jù)丟失。
用fclose函數(shù)關(guān)閉文件,其調(diào)用形式為
fclose(文件指針);
例如:
fclose(fp);
前面曾把用fopen函數(shù)打開(kāi)文件時(shí)所帶回的指針賦給了fp,現(xiàn)通過(guò)fp把該文件關(guān)閉,此后fp不再指向該文件。正常完成關(guān)閉文件操作后,fclose函數(shù)返回值為0。如返回非零值,則表示有錯(cuò)誤發(fā)生。 10.3文件的順序讀寫
10.3.1字符讀寫函數(shù)fgetc和fputc
1.讀字符函數(shù)fgetc
fgetc函數(shù)的調(diào)用形式為
字符變量=fgetc(文件指針);
例如:
ch=fgetc(fp);其中:fp為文件指針變量;ch為字符變量。該語(yǔ)句表示從打開(kāi)的文件fp中讀取一個(gè)字符并送入ch中。在使用fgetc函數(shù)時(shí),應(yīng)注意以下幾點(diǎn):
(1)在fgetc函數(shù)調(diào)用中,讀取的文件必須是以讀或讀寫方式打開(kāi)的。
(2)讀取字符的結(jié)果可以不向字符變量賦值,例如:
fgetc(fp);
但是讀出的字符不能保存。
(3)在文件內(nèi)部有一個(gè)位置指針,用來(lái)指向文件的當(dāng)前讀寫字節(jié)。在文件打開(kāi)時(shí),該指針總是指向文件的第一個(gè)字節(jié)。使用fgetc函數(shù)后,該位置指針將向后移動(dòng)一個(gè)字節(jié)。因此可連續(xù)多次使用fgetc函數(shù)讀取多個(gè)字符。注意文件指針和文件內(nèi)部的位置指針是不一樣的。文件指針是指向整個(gè)文件的,須在程序中定義說(shuō)明,只要不重新賦值,文件指針的值是不變的。文件內(nèi)部的位置指針用以指示文件內(nèi)部的當(dāng)前讀寫位置,每讀寫一次,該指針均向后移動(dòng),它不需在程序中定義說(shuō)明,而是由系統(tǒng)自動(dòng)設(shè)置的。
2.寫字符函數(shù)fputc
fputc函數(shù)的功能是把一個(gè)字符寫入指定的文件中,其調(diào)用形式為
fputc(字符量,文件指針);
其中,待寫入的字符量可以是字符常量或變量。例如:
fputc('a',fp);
其意義是把字符a寫入fp所指向的文件中。對(duì)于fputc函數(shù)的使用也要說(shuō)明幾點(diǎn):
(1)被寫入的文件可以用寫?讀寫?追加方式打開(kāi)。用寫或讀寫方式打開(kāi)一個(gè)已存在的文件時(shí),將清除原有的文件內(nèi)容,寫入字符從文件首開(kāi)始。如需保留原有文件的內(nèi)容,且希望寫入的字符從文件末開(kāi)始存放,則必須以追加方式打開(kāi)文件。被寫入的文件若不存在,則創(chuàng)建該文件。
(2)每寫入一個(gè)字符,文件內(nèi)部的位置指針向后移動(dòng)一個(gè)字節(jié)。
(3)fputc函數(shù)有一個(gè)返回值,如寫入成功則返回寫入的字符,否則返回一個(gè)EOF??捎么藖?lái)判斷寫入是否成功。
【例10.1】把從鍵盤輸入的一個(gè)字符串寫入磁盤文件example.txt中。
程序如下:
#include“stdio.h”
main()
{
charch;
FILE*fp;
fp=fopen(“example.txt”,“w”);
printf(“Enterastring:”);
while((ch=getchar())!=‘\n’)
fputc(ch,fp);
fclose(fp);
}本程序使用?"w"?方式打開(kāi)example.txt文件,實(shí)際上就是創(chuàng)建example.txt文件。該文件的內(nèi)容是鍵盤輸入的內(nèi)容。example.txt是一個(gè)文本文件,可以使用任何文本編輯程序閱讀該文件。比如可以使用記事本程序打開(kāi)example.txt文件查看它的內(nèi)容。
【例10.2】把一個(gè)文本文件的內(nèi)容復(fù)制到另一個(gè)文本文件中。
程序如下:
#include“stdio.h”
main()
{
charch,source[10],target[10];
FILE*fp_s,*fp_t;
printf(“Enterthesourcefilename:”);
scanf(“%s”,source);
printf(“Enterthetargetfilename:”);
scanf("%s",target);
if((fp_s=fopen(source,“r”))==NULL)
{
printf(“cannotopensourcefile.\n”);
exit(1);
}
if((fp_t=fopen(target,“w”))==NULL)
{
printf(“cannotopentargetfile.\n”);
exit(1);
}
while(!feof(fp_s))
fputc(fgetc(fp_s),fp_t);
fclose(fp_s);
fclose(fp_t);
}程序運(yùn)行結(jié)果:
Enterthesourcefilename:example.txt
Enterthetargetfilename:try.txt
其中:example.txt是要復(fù)制的源文件名,是已經(jīng)存在的一個(gè)文本文件;try.txt是要形成的目標(biāo)文件名。程序運(yùn)行結(jié)束后,example.txt文件復(fù)制到try.txt文件中。10.3.2字符串讀寫函數(shù)fgets和fputs
1.字符串讀函數(shù)fgets
fgets函數(shù)的功能是從指定的文件中讀一個(gè)字符串到字符數(shù)組中,其調(diào)用形式為
fgets(字符數(shù)組名,n,文件指針);
其中的n是一個(gè)正整數(shù),表示從文件中讀出的字符串不超過(guò)n?-?1個(gè)字符。注意,應(yīng)在讀入的最后一個(gè)字符后加上串結(jié)束標(biāo)志?'\0'。
例如:
fgets(str,n,fp);
其意義是從fp所指的文件中讀出n-1個(gè)字符送入字符數(shù)組str中。
2.字符串寫函數(shù)fputs
fputs函數(shù)的功能是向指定的文件寫入一個(gè)字符串,其調(diào)用形式為
fputs(字符串,文件指針);
其中字符串可以是字符串常量,也可以是字符數(shù)組。
例如:
fputs("abcd",fp);
其意義是把字符串?"abcd"?寫入fp所指的文件之中。
【例10.3】將字符串?“VisualC++”?和?“Visualbasic”?依次存入文件text中,然后將第一個(gè)字符串讀出并在屏幕上顯示出來(lái)。
程序如下:
#include“stdio.h”
main()
{
FILE*fp;
charstring[20];
fp=fopen(“text”,“w+”);
fputs(“VisualC++\n”,fp);
fputs(“Visualbasic\n”,fp);
rewind(fp);
fgets(string,20,fp);
puts(string);
fclose(fp);
}
程序運(yùn)行結(jié)果:
VisualC++10.3.3數(shù)據(jù)塊讀寫函數(shù)fread和fwrite
讀數(shù)據(jù)塊函數(shù)fread調(diào)用的一般形式為
fread(buffer,size,count,fp);
寫數(shù)據(jù)塊函數(shù)fwrite調(diào)用的一般形式為
fwrite(buffer,size,count,fp);
其中:buffer是一個(gè)指針,在fread函數(shù)中表示存放輸入數(shù)據(jù)的首地址,在fwrite函數(shù)中表示存放輸出數(shù)據(jù)的首地址;size表示數(shù)據(jù)塊的字節(jié)數(shù);count表示要讀寫的數(shù)據(jù)塊塊數(shù);fp表示文件指針。
例如:
fread(fa,4,5,fp);
其意義是從fp所指的文件中,每次讀4個(gè)字節(jié)(一個(gè)實(shí)數(shù))送入實(shí)數(shù)組fa中,連續(xù)讀5次,即讀5個(gè)實(shí)數(shù)到fa中。
【例10.4】將幾個(gè)變量中所存放的數(shù)字寫入一個(gè)文件中,然后再?gòu)奈募凶x出并在屏幕上顯示出來(lái)。
程序如下:
#include<stdio.h>
#include<stdlib.h>
voidmain()
{
FILE*fp;
charc=‘a(chǎn)’,c1;
inti=123,i1;
longl=2004184001L,l1;
doubled=4.5678,d1;
/*檢查能否以讀寫方式打開(kāi)或建立文本文件text1.txt*/
if((fp=fopen("test1.txt","wt+"))==NULL)
{
printf(“不能打開(kāi)文件.\n”);
exit(1);
}
/*通過(guò)函數(shù)fwrite將幾個(gè)變量所存放的數(shù)據(jù)寫入文件*/
fwrite(&c,sizeof(char),1,fp);
fwrite(&i,sizeof(int),1,fp);
fwrite(&l,sizeof(long),1,fp);
fwrite(&d,sizeof(double),1,fp);
/*重新定位指針到文件首部*/
rewind(fp);
/*通過(guò)函數(shù)fread將數(shù)據(jù)讀出文件*/
fread(&c1,sizeof(char),1,fp);
fread(&i1,sizeof(int),1,fp);
fread(&l1,sizeof(long),1,fp);
fread(&d1,sizeof(double),1,fp);
/*輸出*/
printf"c1=%c\n",c1);
printf("i1=%d\n",i1);
printf("l1=%ld\n",l1);
printf("d1=%f\n",d1);
fclose(fp);
}
程序運(yùn)行結(jié)果:
c1=a
i1=123
l1=2004184001
d1=4.567800
【例10.5】
將數(shù)組中所存放的字符寫入一個(gè)文本文件中,然后再?gòu)奈募凶x出并在屏幕上顯示出來(lái)。
程序如下:
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
intmain(void)
{
FILE*fp;
charmsg[]=“thisisatest”;
charbuf[20];
/*檢查能否以讀寫方式打開(kāi)或建立文本文件text2.txt*/
if((fp=fopen("test2.txt","wt+"))==NULL)
{
printf(“不能打開(kāi)文件.\n”);
exit(1);
}
/*通過(guò)函數(shù)fwrite將幾個(gè)變量所存放的數(shù)據(jù)寫入文件*/
fwrite(msg,strlen(msg)+1,1,fp);
/*重新定位指針到文件首部*/
rewind(fp);
/*通過(guò)函數(shù)fread將數(shù)據(jù)讀出文件*/
fread(buf,strlen(msg)+1,1,fp);
printf("%s\n",buf);
fclose(fp);
return0;
}程序運(yùn)行結(jié)果:
thisisatest
本例程序定義了一個(gè)字符數(shù)組msg,程序以讀寫方式打開(kāi)文本文件test2.txt,將字符數(shù)組中所存放的字符寫入該文件中,然后把文件內(nèi)部的位置指針移到文件首,讀出文件中的數(shù)據(jù)到字符數(shù)組buf中,并輸出到屏幕上顯示。
【例10.6】從鍵盤錄入兩個(gè)學(xué)生的數(shù)據(jù),把這些數(shù)據(jù)保存到一個(gè)文件中,然后再?gòu)奈募凶x出并在屏幕上顯示出來(lái)。
程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
structstu
{
charname[10];
intnum;
intage;
charaddr[15];
};
voidmain()
{
FILE*fp;
structstuboya[2],boyb[2],*pp,*qq;
charch;
inti;
/*pp指向boya,qq指向boyb*/
pp=boya;
qq=boyb;
/*以讀寫方式打開(kāi)二進(jìn)制文件“stu_list.dat”*/
if((fp=fopen(“stu_list.dat”,“wb+”))==NULL)
{
printf("不能打開(kāi)文件,按任意鍵退出!\n");
getch();
exit(1);
}
/*輸入兩個(gè)學(xué)生的數(shù)據(jù)*/
printf("\ninputdata\n");
for(i=0;i<2;i++,pp++)
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
/*寫數(shù)據(jù)到文件*/
pp=boya;
fwrite(pp,sizeof(structstu),2,fp);
/*關(guān)閉文件,保證緩沖區(qū)的信息寫入到文件中*/
fclose(fp);
/*再次以只讀形式打開(kāi)文件*/
if((fp=fopen(“stu_list.dat”,“rb”))==NULL)
{
printf(“不能打開(kāi)文件,按任意鍵退出!\n”);
getch();
exit(1);
}
/*把文件內(nèi)部的位置指針移到文件首,讀出兩個(gè)學(xué)生的數(shù)據(jù)后,在屏幕上顯示*/
rewind(fp);
fread(qq,sizeof(structstu),2,fp);
printf(“\n\nname\tnumberageaddr\n”);
for(i=0;i<2;i++,qq++)
{
printf(“%s\t%5d\t”,qq->name,qq->num);
printf(“%7d\t%s\n”,qq->age,qq->addr);
}fclose(fp);
}本例程序定義了一個(gè)結(jié)構(gòu)體stu,說(shuō)明了兩個(gè)結(jié)構(gòu)體數(shù)組boya和boyb以及兩個(gè)結(jié)構(gòu)體指針變量pp和qq。pp指向boya,qq指向boyb。程序以讀寫方式打開(kāi)二進(jìn)制文件“stu_list.dat”,輸入兩個(gè)學(xué)生的數(shù)據(jù)后,將其寫入該文件中,然后把文件內(nèi)部的位置指針移到文件首,讀出兩個(gè)學(xué)生的數(shù)據(jù),并在屏幕上顯示出來(lái)。10.3.4格式化讀寫函數(shù)fscanf和fprintf
fscanf函數(shù)和fprintf函數(shù)與前面使用的scanf函數(shù)和printf函數(shù)的功能相似,都是格式化讀寫函數(shù)。兩者的區(qū)別在于fscanf函數(shù)和fprintf函數(shù)的讀寫對(duì)象不是鍵盤和顯示器,而是磁盤文件。這兩個(gè)函數(shù)的調(diào)用格式分別為
fscanf(文件指針,格式字符串,輸入表列);
fprintf(文件指針,格式字符串,輸出表列);
例如:
fscanf(fp,"%d%s",&i,s);
fprintf(fp,"%d%c",j,ch);
【例10.7】
將文件data1.txt中的4行5列的二維數(shù)組數(shù)據(jù)寫入內(nèi)存,將數(shù)組元素逐個(gè)增1后寫入文件data2.txt中。
程序如下:
#include<stdio.h>
main()
{
FILE*fp1,*fp2;
inti,j,a[4][5];
if((fp1=fopen(“F:\\data1.txt”,“r”))==NULL)
{
printf(“Can’topenfile1\n”);
return;
}
if((fp2=fopen(“F:\\data2.txt”,“w”))==NULL)
{
printf(“Can’topenfile2\n”);
return;
}
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
{
fscanf(fp1,“%d\t”,&a[i][j]);
a[i][j]+=1;
fprintf(fp2,“%d”,a[i][j]);
}
fprintf(fp2,“\n”);
}
fclose(fp1);
fclose(fp2);
}
【例10.8】
從一給定的文本文件test3.txt中讀出數(shù)據(jù),并將其存放到相應(yīng)的變量中,且在屏幕上顯示出來(lái)。設(shè)文本文件test3.txt中存放的內(nèi)容為
HELLO!1234
若要將上述信息讀出到變量中,則需在程序中定義一個(gè)字符數(shù)組和一個(gè)整型變量,然后用fscanf函數(shù)將文本文件test3.txt中的內(nèi)容以?%s和?%d的格式讀出,并分別存放到字符數(shù)組和整型變量中,最后將字符數(shù)組和變量中的內(nèi)容在屏幕上顯示出來(lái)。程序如下:
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
voidmain(void)
{
inti;
charstr[20];
FILE*fp;
/*檢查能否以只讀形式打開(kāi)文件test3.txt,如果失敗,則提前退出,結(jié)束程序*/
if((fp=fopen("test3.txt","rt"))==NULL)
{
printf(“不能打開(kāi)文件,按任意鍵退出!\n”);
getch();
exit(1);
}
/*讀數(shù)據(jù)到字符數(shù)組str和變量i中*/
fscanf(fp,“%s%d”,str,&i);
/*輸出到屏幕*/
printf(“%s,%d”,str,i);
fclose(fp);
}
程序運(yùn)行結(jié)果:
HELLO!,1234
【例10.9】從鍵盤錄入兩個(gè)學(xué)生的數(shù)據(jù),把這些數(shù)據(jù)保存到一個(gè)文本文件中,再?gòu)脑撐谋疚募凶x出并在屏幕上顯示出來(lái)(用函數(shù)fscanf和fprintf實(shí)現(xiàn))。
程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
structstu
{
charname[10];
intnum;
intage;
charaddr[15];
};
voidmain()
{
FILE*fp;
charch;
inti;
structstuboya[2],boyb[2],*pp,*qq;
/*?pp指向boya,qq指向boyb?*/
pp=boya;
qq=boyb;
/*以讀寫方式打開(kāi)二進(jìn)制文件"stu_list.txt"?*/
if((fp=fopen("stu_list1.txt","w+"))==NULL)
{
printf("不能打開(kāi)文件,按任意鍵退出!\n");
getch();
exit(1);
}
/*輸入兩個(gè)學(xué)生的數(shù)據(jù)*/
printf("\ninputdata\n");
for(i=0;i<2;i++,pp++)
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
/*將兩個(gè)學(xué)生的數(shù)據(jù)輸出到文件指針?biāo)赶虻奈募?/
pp=boya;
for(i=0;i<2;i++,pp++)
{
fprintf(fp,“%s%d%d%s\n”,pp->name,pp->num,pp->age,pp->addr);
/*關(guān)閉文件,保證緩沖區(qū)的信息寫入到文件中*/
fclose(fp);
/*再次以只讀形式打開(kāi)文件*/
if((fp=fopen(“stu_list1.txt”,“r”))==NULL)
{
printf(“不能打開(kāi)文件,按任意鍵退出!”);
getch();
exit(1);
}
/*把文件內(nèi)部的位置指針移到文件首,讀出兩個(gè)學(xué)生的數(shù)據(jù)后,在屏幕上顯示*/
rewind(fp);
for(i=0;i<2;i++,qq++)
{
fscanf(fp,“%s%d%d%s\n”,qq->name,&qq->num,&qq->age,qq->addr);
}
printf(“\n\nname\tnumberageaddr\n”);
qq=boyb;
for(i=0;i<2;i++,qq++)
{
printf("%s\t%5d%7d%s\n",qq->name,qq->num,qq->age,qq->addr);
}fclose(fp);
}本程序中函數(shù)fscanf和fprintf每次只能讀寫一個(gè)結(jié)構(gòu)體數(shù)組元素,因此,采用了循環(huán)語(yǔ)句來(lái)讀寫全部數(shù)組元素。還應(yīng)注意,循環(huán)改變了指針變量pp和qq的值,因此,在程序中分別對(duì)它們重新賦予了數(shù)組的首地址。
關(guān)于fprintf函數(shù),在使用時(shí)還應(yīng)注意它向文件輸出的是ASCII碼。特別在輸出數(shù)值時(shí),要輸出的是該數(shù)值的ASCII碼,而不是數(shù)值本身。
10.4文件的隨機(jī)讀寫
10.4.1文件定位
移動(dòng)文件內(nèi)部的位置指針的函數(shù)主要有兩個(gè),即rewind函數(shù)和fseek函數(shù)。
rewind函數(shù)的調(diào)用形式為
rewind(文件指針);
它的功能是把文件內(nèi)部的位置指針移到文件首。
fseek函數(shù)用于改變文件的位置指針,其調(diào)用形式為
fseek(文件指針,位移量,起始點(diǎn));其中:“文件指針”指向被移動(dòng)的文件;“起始點(diǎn)”表示從何處開(kāi)始計(jì)算位移量,規(guī)定的起始點(diǎn)有三種,即文件首、當(dāng)前位置和文件末尾,ANSIC標(biāo)準(zhǔn)指定的起始點(diǎn)的表示符號(hào)如表10-2所示;“位移量”表示以“起始點(diǎn)”為基點(diǎn)移動(dòng)的字節(jié)數(shù),ANSIC和大多數(shù)C版本要求位移量是long型數(shù)據(jù),以便在文件長(zhǎng)度大于64?KB時(shí)不會(huì)出錯(cuò)。當(dāng)用常量表示位移量時(shí),要求加后綴“L”。例如:
fseek(fp,100L,0);
其意義是把位置指針移到離文件首100個(gè)字節(jié)處。
fseek函數(shù)一般用于二進(jìn)制文件。在文本文件中由于要進(jìn)行轉(zhuǎn)換,故往往計(jì)算的位置會(huì)出現(xiàn)錯(cuò)誤。10.4.2隨機(jī)讀寫函數(shù)rewind和fseek
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 買賣合同范本免
- 鹵肉教學(xué)員合同范本
- 上海企業(yè)記賬報(bào)稅合同范本
- 廠區(qū)白蟻防治合同范本
- 吳中區(qū)工程咨詢合同范本
- 課題立項(xiàng)成果申報(bào)書(shū)
- 廠房消防檢測(cè)服務(wù)合同范本
- 單位轉(zhuǎn)讓出租車合同范本
- 賣別墅合同范本
- 廠房拆遷工程合同范例
- 思想道德與法治教案第四章:明確價(jià)值要求踐行價(jià)值準(zhǔn)則
- 寧騷版《公共政策學(xué)》課后答案
- 外陰及陰道炎癥
- (綜合治理)修復(fù)工程指南(試行) - 貴州省重金屬污染防治與土壤修復(fù)網(wǎng)
- 公安筆錄模板之詢問(wèn)嫌疑人(書(shū)面?zhèn)鲉局伟舶讣?
- 員工就餐簽到表
- A-level項(xiàng)目介紹(課堂PPT)
- 故障診斷技術(shù)的國(guó)內(nèi)外發(fā)展現(xiàn)狀(共3頁(yè))
- 航海計(jì)算軟件---ETA計(jì)算器
- 光伏電站運(yùn)維手冊(cè)
- 半導(dǎo)體及集成電路領(lǐng)域的撰寫及常見(jiàn)問(wèn)題
評(píng)論
0/150
提交評(píng)論