第7章文件和結(jié)構(gòu)體(C版)_第1頁
第7章文件和結(jié)構(gòu)體(C版)_第2頁
第7章文件和結(jié)構(gòu)體(C版)_第3頁
第7章文件和結(jié)構(gòu)體(C版)_第4頁
第7章文件和結(jié)構(gòu)體(C版)_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、第七章 文件 與 結(jié)構(gòu)體 文件是根據(jù)特定的目的而收集在一起的有關(guān)數(shù)據(jù)的集合。C+把每一個文件都看成是一個有序的字節(jié)流,每個文件都以文件結(jié)束標(biāo)志結(jié)束,如果要操作某個文件,程序必須首先打開該文件。當(dāng)一個文件被打開后,該文件就和一個流關(guān)聯(lián)起來,這里的流實際上是一個字節(jié)序列。 C+將文件分為文本文件和二進(jìn)制文件。二進(jìn)制文件一般含有特殊的格式或計算機(jī)代碼,如圖文件和可執(zhí)行文件等。文本文件則是可以用任何文字處理程序閱讀和編輯的簡單ASCII文件。 下面我們學(xué)習(xí)如何編寫C+代碼來實現(xiàn)對文本文件的輸入和輸出。 第一節(jié)文件操作 C+語言提供了一批用于文件操作的標(biāo)準(zhǔn)函數(shù),本節(jié)不是介紹文件打開函數(shù)fopen,而是介

2、紹另一個函數(shù)freopen,它們都包含于標(biāo)準(zhǔn)庫cstdio中,文件操作基本步驟如下: (1)打開文件,將文件指針指向文件,決定打開文件類型; (2)對文件進(jìn)行讀、寫操作; (3)在使用完文件后,關(guān)閉文件。一、重定向版【命令格式】 FILE * freopen ( const char * filename, const char * mode, FILE * stream );【參數(shù)說明】 filename: 要打開的文件名 mode: 文件打開的模式,和fopen中的模式(r/w)相同 stream: 文件指針,通常使用標(biāo)準(zhǔn)流文件(stdin/stdout/stderr) 其中stdin是標(biāo)

3、準(zhǔn)輸入流,默認(rèn)為鍵盤;stdout是標(biāo)準(zhǔn)輸出流,默認(rèn)為屏幕;stderr是標(biāo)準(zhǔn)錯誤流,一般把屏幕設(shè)為默認(rèn)。通過調(diào)用freopen,就可以修改標(biāo)準(zhǔn)流文件的默認(rèn)值,實現(xiàn)重定向。【使用方法】 因為文件指針使用的是標(biāo)準(zhǔn)流文件,因此我們可以不定義文件指針。接下來我們使用freopen()函數(shù)以只讀方式r(read)打開輸入文件slyar.in。 格式:freopen(slyar.in, r, stdin); 然后使用freopen()函數(shù)以寫入方式w(write)打開輸出文件slyar.out。 格式:freopen(slyar.out, w, stdout); 接下來的事情就是使用freopen()函

4、數(shù)的優(yōu)點了,我們不再需要修改scanf,printf,cin和cout。而是維持代碼的原樣就可以了。因為freopen()函數(shù)重定向了標(biāo)準(zhǔn)流,使其指向前面指定的文件,省時省力。最后只要使用fclose關(guān)閉輸入文件和輸出文件即可。 格式:fclose(stdin);fclose(stdout); 若要恢復(fù)句柄,可以重新打開標(biāo)準(zhǔn)控制臺設(shè)備文件,只是這個設(shè)備文件的名字是與操作系統(tǒng)相關(guān)的。 格式:freopen(CON, r, stdin);代碼模版: #include /使用freopen語句,須調(diào)用cstdio庫 int main() freopen(slyar.in, r, stdin); fr

5、eopen(slyar.out, w, stdout); /* 中間按原樣寫代碼,什么都不用修改 */ fclose(stdin);fclose(stdout); return 0; 例9.1從in.txt文件中讀入數(shù)據(jù),把它們的和保存out.txt文件中。#includeint main() freopen(in.txt,r,stdin); /定義輸入文件名 freopen(out.txt,w,stdout); /定義輸出文件名 int temp,sum=0; while (scanf(%d,&temp)=1) /(cintemp)從輸入文件中讀入數(shù)據(jù) /在C+中非0為真 sum=sum+t

6、emp; printf(%dn,sum); / coutsumtemp)和(scanf(%d,&temp)=1)主要是用于判斷數(shù)據(jù)是否已經(jīng)讀完,以便及時終止循環(huán)。還可以用成員函數(shù)eof來判斷是否達(dá)到數(shù)據(jù)流的末尾。對scanf、printf和cin、cout語句都適用。二、fopen版 重定向用起來很方便,但并不是所有算法競賽都允許讀寫文件。甚至有的競賽允許訪問文件,但不允許使用freopen這樣的重定向方式讀寫文件,可以使用fopen版,對scanf和printf語句適用。程序如下:#includeusing namespace std;int main() FILE *fin,*fout;

7、fin = fopen(in.txt,rb); /定義輸入文件名 fout = fopen(out.txt,wb); /定義輸出文件名 int temp,sum=0; while (fscanf(fin,%d,&temp)=1) /從輸入文件中讀入數(shù)據(jù) sum=sum+temp; fprintf(fout,%dn,sum); / coutsumendl; fclose(fin);fclose(fout); /關(guān)閉文件,可省略 return 0; 先聲明變量fin和fout(暫且不用管FILE *為何物),把scanf改成fscanf,第一個參數(shù)為fin;把printf改成fprintf,第一個

8、參數(shù)為fout,最后執(zhí)行fclose,關(guān)閉兩個文件。 重定向和fopen兩種方法各有優(yōu)劣。重定向的方法寫起來簡單、自然,但是不能同時讀寫文件和標(biāo)準(zhǔn)輸入輸出;fopen的寫法稍顯繁瑣,但是靈活性比較大(例如可以反復(fù)打開并讀寫文件)。順便說一句,如 果把fopen版的程序改成讀寫標(biāo)準(zhǔn)輸入輸出,只需賦值fin=stdin;fout=stdout;即可,不要調(diào)用fopen和fclose。程序如下:#includeusing namespace std;int main() FILE *fin,*fout; fin=stdin; fout=stdout; /* 本處語句同上 */ fprintf(fou

9、t,%dn,sum); return 0;三、文件輸入輸出流 在C+中,文件輸入流(ifstream)和文件輸出流(ofstream)的類,它們的默認(rèn)輸入輸出設(shè)備都是磁盤文件。+可以在創(chuàng)建對象時,設(shè)定輸入或輸出到哪個文件。由于這些類的定義是在fstream中進(jìn)行的,因此,在使用這此類進(jìn)行輸入輸出操作時,必須要在程序的首部利用#include指令包進(jìn)fstream頭文件。 例如:若想用fin作為輸入對象,fout作為輸出對象,則可以使用如下定義: ifstream fin(輸入文件名.擴(kuò)展名); ofstream fout(輸出文件名.擴(kuò)展名);程序如下:#include /使用文件輸入輸出流,

10、對cin、cout語句適用using namespace std;int main() ifstream fin(in.txt); /定義輸入文件名 ofstream fout(out.txt); /定義輸出文件名 int temp,sum=0; while (fintemp) sum=sum+temp; /從輸入文件中讀入數(shù)據(jù) ;(3)結(jié)構(gòu)體變量的初始化和數(shù)組的初始化類似,例如:student op=gaoxiang,89,90,179;3.成員調(diào)用結(jié)構(gòu)體變量與各個成員之間引用的一般形式為: 結(jié)構(gòu)體變量名.成員名 對于上面定義的結(jié)構(gòu)體變量,我們可以這樣操作: ci

11、; /一般情況下不能寫cinai; ai.total=ai.chinese+ai.math; /就像用整型變量一樣 實際上結(jié)構(gòu)體成員的操作與該成員類型所具有的操作是一致的。 成員運(yùn)算符“.”在存取成員數(shù)值時使用,其優(yōu)先級最高,并具有左結(jié)合性。在處理包含結(jié)構(gòu)體的結(jié)構(gòu)體時,可記作:strua.strub.membb這說明結(jié)構(gòu)體變量strua有結(jié)構(gòu)體成員strub;結(jié)構(gòu)體變量strub有成員membb。4.成員函數(shù)調(diào)用結(jié)構(gòu)體成員函數(shù)調(diào)用的一般形式為:結(jié)構(gòu)體變量名.成員函數(shù)結(jié)構(gòu)體成員函數(shù)默認(rèn)將結(jié)構(gòu)體變量作為引用參數(shù)。 例7.2成績統(tǒng)計。輸入N個學(xué)生的姓名和語文、數(shù)學(xué)的得分,按總分從高到

12、低輸出,分?jǐn)?shù)相同的按輸入先后輸出。輸入格式: 第1行,有一個整數(shù)N,N的范圍是1100;下面有N行,每行一個姓名,2個整數(shù)。姓名由不超過10個的小寫字母組成,整數(shù)范圍是0100。輸出格式: 總分排序后的名單,共N行,每行格式:姓名 語文 數(shù)學(xué) 總分。輸入樣例: 4 gaoxiang 78 96 wangxi 70 99 liujia 90 87 zhangjin 78 91輸出樣例: liujia 90 87 177 gaoxiang 78 96 174 wangxi 70 99 169 zhangjin 78 91 169分析:由于姓名是字符串,分?jǐn)?shù)是整數(shù),如果用數(shù)組保存,則要兩個數(shù)組,比如

13、: string name100; int score1003;這種方法不利于把一個學(xué)生的信息當(dāng)成一個整體處理。下面程序中通過使用結(jié)構(gòu)(struct)類型的方法來解決這個問題。 #include#includeusing namespace std;struct studentstring name;int chinese,math;int total; /定義一個struct的類型,類型名叫:studentstudent a110; /定義一個數(shù)組a,每個元素是student類型int n;int main() cinn;for (int i=0; ;cinai.chines

14、e ai.math;ai.total=ai.chinese+ai.math;for (int i=n-1; i0; i-) for (int j=0; ji; j+) /冒泡排序 if (aj.totalaj+1.total) swap(aj,aj+1); for (int i=0; in; i+) /輸出 ai.chinese ai.math ai.totalendl;return 0; 二、結(jié)構(gòu)體(struct)的使用例7.3 離散化基礎(chǔ)。以后要學(xué)習(xí)使用的離散化方法編程中,通常要知道每個數(shù)排序后的編號(rank值)。輸入格式: 第1行,一個整數(shù)N,范圍在110000

15、;第2行,有N個不相同的整數(shù),每個數(shù)都是int范圍的。輸出格式: 依次輸出每個數(shù)的排名。輸入樣例: 5 8 2 6 9 4輸出樣例: 4 1 3 5 2 分析:排序是必須的,關(guān)鍵是怎樣把排名寫回原來的數(shù)“下面”。程序使用了分別對數(shù)值和下標(biāo)不同關(guān)鍵詞2次排序的辦法來解決這個問題,一個數(shù)據(jù)“節(jié)點”應(yīng)該包含數(shù)值、排名、下標(biāo)3個元素,用結(jié)構(gòu)體比較好。程序如下:#include#includeusing namespace std;struct nodeint data; /數(shù)值int rank; /排名int index; /下標(biāo); /定義struct類型 node a10001;int n;bool

16、 comp1(node x,node y)return x.datay.data; /自定義比較函數(shù) bool comp2(node x,node y)return x.indexn;for (int i=1; iai.data,ai.index=i;sort(a+1,a+1+n,comp1); /根據(jù)值排序,求排名rank for (int i=1; i=n; i+) ai.rank=i;sort(a+1,a+1+n,comp2); /根據(jù)下標(biāo)排序,回到原數(shù)據(jù)次序 for (int i=1; i=n; i+) coutai.rank ;return 0;例7.4 模擬鏈表。在圖論題編程中,通

17、常要運(yùn)用鄰接鏈表數(shù)據(jù)結(jié)構(gòu)。由于動態(tài)指針比靜態(tài)的數(shù)組的存取慢,很多OI選手就用數(shù)組模擬指針?,F(xiàn)在就來學(xué)習(xí)一下這種方法的編程。 有N個點,編號從1到N。有M條邊,每條邊用連接的2個頂點表示,如:(3,8),表示頂點3和8之間的邊(無向邊)。請輸出每個頂點通過邊相鄰的頂點。輸入格式: 第1行,N和M兩個整數(shù),N范圍在15000,M范圍在1100000;下面有M行,每行兩個整數(shù),表示一條邊。輸出格式: N行,第i行的第1個數(shù)k表示有多少邊和i號頂點相連,后面有k個數(shù),表示哪k個頂點和i連接為一條邊。輸入樣例: 5 6 1 3 2 4 1 4 2 3 3 5 2 5輸出樣例: 2 4 3 3 5 3 4

18、 3 5 2 1 2 1 2 2 2 3分析:本題中鄰接鏈表的每個節(jié)點有2個成員: struct node int v; /定點編號 int next; /鏈表的下一個節(jié)點的下標(biāo) ; 一開始我們給足夠大的數(shù)組,保證可以保存所有邊。每讀入一條邊(a,b),把a(bǔ)插入到b的鏈表前,再把b插入到a的鏈表前。程序如下:#includeusing namespace std;struct nodeint v; int next; ; /定義struct類型 node a200001; /無向圖,空間是邊的兩倍 int n,m,p; /p為a數(shù)組的空余空間下標(biāo) int k5001,c5001; /鄰接鏈表的

19、表頭,k數(shù)組記長度 void insert(int u,int v) /把v點插入到u點的鄰接鏈表前 a+p.v=v; /申請一個新節(jié)點 ap.next=cu;cu=p; /插入到u鏈表頭 ku+; /鏈表長度增加 int main()cinnm;for (int i=1; iuv;insert(u,v); /插入v點到鏈表u insert(v,u); /插入u點到鏈表v for (int i=1; i=n; i+)coutki0; j=aj.next) /遍歷鏈表 coutaj.v ;coutendl;return 0;三、聯(lián)合(union)的定義和使用 聯(lián)合也稱為共用體,是一種數(shù)據(jù)格式,能

20、夠存儲不同類型的數(shù)據(jù),但同一時間只能儲存其中的一種類型數(shù)據(jù)。例如:union color int rgb3; int cmyk4; “color c;”可以定義一個顏色變量c,c可以有兩種方式記錄顏色:rgb形式或者cmyk形式,但不能同時記錄。 顯然聯(lián)合的用途之一:當(dāng)數(shù)據(jù)項使用多種格式(但不會同時使用)時,可以節(jié)省空間。例7.5 注冊帳號。某網(wǎng)站收集了N個人的注冊帳號,賬號類型有2種:身份證號、QQ號。請編程用恰當(dāng)?shù)臄?shù)據(jù)結(jié)構(gòu)保存信息,并統(tǒng)計身份證中男性和女性的人數(shù),以及QQ號平均值(取整)。輸入格式: 第1行,一個整數(shù)N,范圍在110000;下面N行,每行一個字符和一個字符串。第一個字符表示

21、賬戶類型,有i、q兩種,第二個字符串是帳號信息。輸出格式: 1行,3個整數(shù)值:男性人數(shù)、女性人數(shù)、QQ號平均值。輸入樣例: 6 iiiq 505165 q 34012459 i出樣例: 2 2 17258812分析:如果只是單純做本題,編程很簡單。但為了展示union的使用方法,為今后編寫復(fù)雜的程序打下基礎(chǔ),程序采用規(guī)范編寫。程序如下:#includeusing namespace std;struct tidchar type; /賬

22、號類型,識別聯(lián)合變量儲存哪個類型union /省略類型名,更方便存取聯(lián)合的成員char idc18; /存儲身份證號 long long qq; /存儲QQ號 ; /定義struct類型 tid a10001;int n;int main() cinn;for (int i=1; iai.type;switch (ai.type) /判斷類型 case i:for (int j=0; jai.idcj;break;case q:cinai.qq;long long sum=0; int c=0; /用于計算QQ號平均值int men=0,women=0; /用于計算男性、女性人數(shù) for (i

23、nt i=1; i=n; i+)if (ai.type=i)if (ai.idc16-0)%2) men+;else women+;if (ai.type=q) sum+=ai.qq,c+;coutmen women sum/c;return 0;注意:union里面不能有空間不確定的數(shù)據(jù)結(jié)構(gòu)類型,比如string。四、枚舉(enum)的定義和使用 C+中枚舉(enum)提供了另一種創(chuàng)建符號常量的方式,有些場合可以代替const,甚至定義另一種自定義類型。例如:enum colorred,green,blue,yellow,black,white;color x; “color x;”定義了一個叫color的枚舉類型,并定義了這個類型的一個變量x。x只能取red、green、white幾個值。 red、green、white可看成符號常量,對應(yīng)數(shù)值0到5,可以當(dāng)成整數(shù)常量運(yùn)行。 枚舉常量默認(rèn)的值從0開

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論