




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
C語(yǔ)言程序設(shè)計(jì)姚望舒計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院蘇州大學(xué)C語(yǔ)言程序設(shè)計(jì)姚望舒1第10章對(duì)文件的輸入輸出10.1C文件的有關(guān)基本知識(shí)10.2打開(kāi)與關(guān)閉文件10.3順序讀寫數(shù)據(jù)文件10.4隨機(jī)讀寫數(shù)據(jù)文件10.5文件讀寫的出錯(cuò)檢測(cè)第10章對(duì)文件的輸入輸出10.1C文件的有關(guān)基本知識(shí)210.1C文件的有關(guān)基本知識(shí)10.1.1什么是文件10.1.2文件名10.1.3文件的分類10.1.4文件緩沖區(qū)10.1.5文件類型指針10.1C文件的有關(guān)基本知識(shí)10.1.1什么是文件3C語(yǔ)言程序設(shè)計(jì)第10章對(duì)文件的輸入輸出[精]課件4C語(yǔ)言程序設(shè)計(jì)第10章對(duì)文件的輸入輸出[精]課件5C語(yǔ)言程序設(shè)計(jì)第10章對(duì)文件的輸入輸出[精]課件610.1.1什么是文件輸入輸出是數(shù)據(jù)傳送的過(guò)程,數(shù)據(jù)如流水一樣從一處流向另一處,因此常將輸入輸出形象地稱為流(stream),即數(shù)據(jù)流。流表示了信息從源到目的端的流動(dòng)。輸入操作時(shí),數(shù)據(jù)從文件流向計(jì)算機(jī)內(nèi)存輸出操作時(shí),數(shù)據(jù)從計(jì)算機(jī)流向文件“流”是一個(gè)傳輸通道,數(shù)據(jù)可以從運(yùn)行環(huán)境流入程序中,或從程序流至運(yùn)行環(huán)境10.1.1什么是文件輸入輸出是數(shù)據(jù)傳送的過(guò)程,數(shù)據(jù)如流水710.1.1什么是文件從C程序的觀點(diǎn)來(lái)看,無(wú)論程序一次讀寫一個(gè)字符,或一行文字,或一個(gè)指定的數(shù)據(jù)區(qū),作為輸入輸出的各種文件或設(shè)備都是統(tǒng)一以邏輯數(shù)據(jù)流的方式出現(xiàn)的。C語(yǔ)言把文件看作是一個(gè)字符(或字節(jié))的序列。一個(gè)輸入輸出流就是一個(gè)字符流或字節(jié)(內(nèi)容為二進(jìn)制數(shù)據(jù))流。10.1.1什么是文件從C程序的觀點(diǎn)來(lái)看,無(wú)論程序一次讀寫810.1.1什么是文件C的數(shù)據(jù)文件由一連串的字符(或字節(jié))組成,而不考慮行的界限,兩行數(shù)據(jù)間不會(huì)自動(dòng)加分隔符,對(duì)文件的存取是以字符(字節(jié))為單位的。輸入輸出數(shù)據(jù)流的開(kāi)始和結(jié)束僅受程序控制而不受物理符號(hào)(如回車換行符)控制,這就增加了處理的靈活性。這種文件稱為流式文件。10.1.1什么是文件C的數(shù)據(jù)文件由一連串的字符(或字節(jié))910.1.2文件名文件要有一個(gè)唯一的文件標(biāo)識(shí),以便用戶識(shí)別和引用。文件標(biāo)識(shí)包括三部分:(1)文件路徑(2)文件名主干(3)文件后綴10.1.2文件名文件要有一個(gè)唯一的文件標(biāo)識(shí),以便用戶識(shí)別1010.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面文件路徑文件名主干文件后綴10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。1110.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面文件名10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。1210.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面命名規(guī)則遵循標(biāo)識(shí)符的命名規(guī)則10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。1310.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面一般不超過(guò)3個(gè)字母(doc、txt、dat、c、cpp、obj、exe、ppt、bmp等)10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。1410.1.3文件的分類根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件可分為ASCII文件和二進(jìn)制文件。數(shù)據(jù)在內(nèi)存中是以二進(jìn)制形式存儲(chǔ)的,如果不加轉(zhuǎn)換地輸出到外存,就是二進(jìn)制文件如果要求在外存上以ASCII代碼形式存儲(chǔ),則需要在存儲(chǔ)前進(jìn)行轉(zhuǎn)換ASCII文件又稱文本文件,每一個(gè)字節(jié)放一個(gè)字符的ASCII代碼10.1.3文件的分類根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件可分為A1510.1.3文件的分類字符一律以ASCII形式存儲(chǔ)數(shù)值型數(shù)據(jù)既可以用ASCII形式存儲(chǔ),也可以用二進(jìn)制形式存儲(chǔ)如有整數(shù)10000,如果用ASCII碼形式輸出到磁盤,則在磁盤中占5個(gè)字節(jié)(每一個(gè)字符占一個(gè)字節(jié)),而用二進(jìn)制形式輸出,則在磁盤上只占4個(gè)字節(jié)(用VC++C時(shí))10.1.3文件的分類字符一律以ASCII形式存儲(chǔ)1610.1.3文件的分類(1)(0)(0)(0)(0)ASCII形式二進(jìn)制形式(10000)10.1.3文件的分類(1)(0)(0)(0)(0)ASC1710.1.4文件緩沖區(qū)ANSIC標(biāo)準(zhǔn)采用“緩沖文件系統(tǒng)”處理數(shù)據(jù)文件所謂緩沖文件系統(tǒng)是指系統(tǒng)自動(dòng)地在內(nèi)存區(qū)為程序中每一個(gè)正在使用的文件開(kāi)辟一個(gè)文件緩沖區(qū)10.1.4文件緩沖區(qū)ANSIC標(biāo)準(zhǔn)采用“緩沖文件系統(tǒng)”1810.1.4文件緩沖區(qū)從內(nèi)存向磁盤輸出數(shù)據(jù)必須先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才一起送到磁盤去如果從磁盤向計(jì)算機(jī)讀入數(shù)據(jù),則一次從磁盤文件將一批數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再?gòu)木彌_區(qū)逐個(gè)地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(給程序變量)10.1.4文件緩沖區(qū)從內(nèi)存向磁盤輸出數(shù)據(jù)必須先送到內(nèi)存中1910.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)磁盤從內(nèi)存向磁盤輸出數(shù)據(jù)裝滿緩沖區(qū)10.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖2010.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)磁盤從磁盤向計(jì)算機(jī)讀入數(shù)據(jù)充滿緩沖區(qū)10.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖2110.1.5文件類型指針緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文件類型指針”,簡(jiǎn)稱“文件指針”每個(gè)被使用的文件都在內(nèi)存中開(kāi)辟一個(gè)相應(yīng)的文件信息區(qū),用來(lái)存放文件的有關(guān)信息(如文件的名字、文件狀態(tài)及文件當(dāng)前位置等)這些信息是保存在一個(gè)結(jié)構(gòu)體變量中的。該結(jié)構(gòu)體類型是由系統(tǒng)聲明的,取名為FILE10.1.5文件類型指針緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文2210.1.5文件類型指針聲明FILE結(jié)構(gòu)體類型的信息包含在頭文件“stdio.h”中一般設(shè)置一個(gè)指向FILE類型變量的指針變量,然后通過(guò)它來(lái)引用這些FILE類型變量10.1.5文件類型指針聲明FILE結(jié)構(gòu)體類型的信息包含2310.1.5文件類型指針FILE
*fp1,*fp2,*fp3;文件f1的文件信息區(qū)fp1文件f2的文件信息區(qū)fp2文件f3的文件信息區(qū)fp310.1.5文件類型指針FILE*fp1,*fp2,*2410.2打開(kāi)與關(guān)閉文件10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件10.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件10.2打開(kāi)與關(guān)閉文件10.2.1用fopen函數(shù)打開(kāi)數(shù)2510.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件對(duì)文件讀寫之前應(yīng)該“打開(kāi)”該文件,在使用結(jié)束之后應(yīng)“關(guān)閉”該文件。所謂“打開(kāi)”是指為文件建立相應(yīng)的信息區(qū)(用來(lái)存放有關(guān)文件的信息)和文件緩沖區(qū)(用來(lái)暫時(shí)存放輸入輸出的數(shù)據(jù))。10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件對(duì)文件讀寫之前應(yīng)該2610.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在編寫程序時(shí),在打開(kāi)文件的同時(shí),一般都指定一個(gè)指針變量指向該文件,也就是建立起指針變量與文件之間的聯(lián)系,這樣就可以通過(guò)該指針變量對(duì)文件進(jìn)行讀寫所謂“關(guān)閉”是指撤銷文件信息區(qū)和文件緩沖區(qū)10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在編寫程序時(shí),在打2710.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件fopen函數(shù)的調(diào)用方式為:FILE*fopen(文件名,使用文件方式);例如:
fopen(“a1”,”r”);表示要打開(kāi)名為“a1”的文件,使用文件方式為“讀入”fopen函數(shù)的返回值是指向a1文件的指針10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件fopen函數(shù)的調(diào)2810.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件通常將fopen函數(shù)的返回值賦給一個(gè)指向文件的指針變量。如:FILE*fp;fp=fopen(“a1”,”r”);fp和文件a1相聯(lián)系,fp指向了a1文件a1:有兩種形式文件名:表示文件在工程路徑絕對(duì)路徑:絕對(duì)路徑+文件名10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件通常將fopen函2910.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在打開(kāi)一個(gè)文件時(shí),通知編譯系統(tǒng)以下3個(gè)信息:①需要訪問(wèn)的文件的名字②使用文件的方式(“讀”還是“寫”等)③讓哪一個(gè)指針變量指向被打開(kāi)的文件使用文件方式參見(jiàn)教材表10.1。10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在打開(kāi)一個(gè)文件時(shí),30說(shuō)明:(1)用“r”方式打開(kāi)的文件只能用于向計(jì)算機(jī)輸入而不能用作向該文件輸出數(shù)據(jù),而且該文件應(yīng)該已經(jīng)存在,并存有數(shù)據(jù),這樣程序才能從文件中讀數(shù)據(jù)。不能用“r”方式打開(kāi)一個(gè)并不存在的文件,否則出錯(cuò)。說(shuō)明:31說(shuō)明:(2)用“w”方式打開(kāi)的文件只能用于向該文件寫數(shù)據(jù)(即輸出文件),而不能用來(lái)向計(jì)算機(jī)輸入。如果原來(lái)不存在該文件,則在打開(kāi)文件前新建立一個(gè)以指定的名字命名的文件。如果原來(lái)已存在一個(gè)以該文件名命名的文件,則在打開(kāi)文件前先將該文件刪去,然后重新建立一個(gè)新文件。說(shuō)明:32說(shuō)明:(3)如果希望向文件末尾添加新的數(shù)據(jù)(不希望刪除原有數(shù)據(jù)),則應(yīng)該用“a”方式打開(kāi)但此時(shí)應(yīng)保證該文件已存在;否則將得到出錯(cuò)信息。打開(kāi)文件時(shí),文件讀寫標(biāo)記移到文件末尾說(shuō)明:33說(shuō)明:(4)用r+、w+、a+方式打開(kāi)的文件既可以用來(lái)輸入數(shù)據(jù),也可以用來(lái)輸出數(shù)據(jù)。用r+方式時(shí)該文件應(yīng)該已經(jīng)存在。用w+方式則新建立一個(gè)文件,先向此文件寫數(shù)據(jù),然后可以讀此文件中的數(shù)據(jù)。用a+方式打開(kāi)的文件,原來(lái)的文件不被刪去,文件讀寫位置標(biāo)記移到文件末尾,可以添加,也可以讀。說(shuō)明:34說(shuō)明:(5)如果打開(kāi)失敗,fopen函數(shù)將會(huì)帶回一個(gè)出錯(cuò)信息。fopen函數(shù)將帶回一個(gè)空指針值NULL常用下面的方法打開(kāi)一個(gè)文件:if((fp=fopen(“file1”,’r″))==NULL)
{printf(“cannotopenthisfile\n”);exit(0);
}終止正在執(zhí)行的程序說(shuō)明:終止正在執(zhí)行的程序35說(shuō)明:(6)C標(biāo)準(zhǔn)建議用表10.1列出的文件使用方式打開(kāi)文本文件或二進(jìn)制文件,但目前使用的有些C編譯系統(tǒng)可能不完全提供所有這些功能說(shuō)明:36說(shuō)明:(7)計(jì)算機(jī)輸從ASCII文件讀入字符時(shí),遇到回車換行符,系統(tǒng)把它轉(zhuǎn)換為一個(gè)換行符,在輸出時(shí)把換行符轉(zhuǎn)換成為回車和換行兩個(gè)字符。在用二進(jìn)制文件時(shí),不進(jìn)行這種轉(zhuǎn)換,在內(nèi)存中的數(shù)據(jù)形式與輸出到外部文件中的數(shù)據(jù)形式完全一致,一一對(duì)應(yīng)。說(shuō)明:37說(shuō)明:(8)程序中可以使用3個(gè)標(biāo)準(zhǔn)的流文件:標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、標(biāo)準(zhǔn)出錯(cuò)輸出流。系統(tǒng)已對(duì)這3個(gè)文件指定了與終端的對(duì)應(yīng)關(guān)系標(biāo)準(zhǔn)輸入流是從終端的輸入標(biāo)準(zhǔn)輸出流是向終端的輸出標(biāo)準(zhǔn)出錯(cuò)輸出流是當(dāng)程序出錯(cuò)時(shí)將出錯(cuò)信息發(fā)送到終端說(shuō)明:38程序開(kāi)始運(yùn)行時(shí)系統(tǒng)自動(dòng)打開(kāi)這3個(gè)標(biāo)準(zhǔn)流文件。因此,程序編寫者不需要在程序中用fopen函數(shù)打開(kāi)它們。所以以前我們用到的從終端輸入或輸出到終端都不需要打開(kāi)終端文件。程序開(kāi)始運(yùn)行時(shí)系統(tǒng)自動(dòng)打開(kāi)這3個(gè)標(biāo)準(zhǔn)流文件。因此,程序編寫者3910.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件關(guān)閉文件用fclose函數(shù)。fclose函數(shù)調(diào)用的一般形式為fclose(文件指針);例如:
fclose(fp);如果不關(guān)閉文件將會(huì)丟失數(shù)據(jù)。10.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件關(guān)閉文件用fcl4010.3順序讀寫數(shù)據(jù)文件在順序?qū)憰r(shí),先寫入的數(shù)據(jù)存放在文件中前面,后寫入的數(shù)據(jù)存放在文件中后面在順序讀時(shí),先讀文件中前面的數(shù)據(jù),后讀文件中后面的數(shù)據(jù)對(duì)順序讀寫來(lái)說(shuō),對(duì)文件讀寫數(shù)據(jù)的順序和數(shù)據(jù)在文件中的物理順序是一致的順序讀寫需要用庫(kù)函數(shù)實(shí)現(xiàn)10.3順序讀寫數(shù)據(jù)文件在順序?qū)憰r(shí),先寫入的數(shù)據(jù)存放在文件4110.3順序讀寫數(shù)據(jù)文件10.3.1怎樣向文件讀寫字符10.3.2怎樣向文件讀寫一個(gè)字符串10.3.3用格式化的方式讀寫文件10.3.4用二進(jìn)制方式向文件讀寫一組數(shù)據(jù)10.3順序讀寫數(shù)據(jù)文件10.3.1怎樣向文件讀寫字符4210.3.1怎樣向文件讀寫字符讀寫一個(gè)字符的函數(shù)10.3.1怎樣向文件讀寫字符讀寫一個(gè)字符的函數(shù)43
例10.1從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上去,直到用戶輸入一個(gè)“#”為止。
解題思路:用fgetc函數(shù)從鍵盤逐個(gè)輸入字符,然后用fputc函數(shù)寫到磁盤文件即可。例10.1從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上去,44#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp;charch,filename[10];printf("請(qǐng)輸入所用的文件名:");scanf("%s",filename);if((fp=fopen(filename,“w”))==NULL) {printf("無(wú)法打開(kāi)此文件\n");exit(0);}ch=getchar();接收最后輸入的回車符輸入文件名只寫用exit函數(shù)時(shí)加#include<stdio.h>接收最后輸入的回車符輸入45printf(“請(qǐng)輸入一個(gè)字符串(以#結(jié)束):");ch=getchar();while(ch!=‘#’) {fputc(ch,fp);putchar(ch); ch=getchar(); }
fclose(fp);putchar(‘\n’);return0;}printf(“請(qǐng)輸入一個(gè)字符串(以#結(jié)束):");46
例10.2將一個(gè)磁盤文件中的信息復(fù)制到另一個(gè)磁盤文件中。今要求將上例建立的file1.dat文件中的內(nèi)容復(fù)制到另一個(gè)磁盤文件file2.dat中。解題思路:處理此問(wèn)題的算法是:從file1.dat文件中逐個(gè)讀入字符,然后逐個(gè)輸出到file2.dat中。例10.2將一個(gè)磁盤文件中的信息復(fù)制到另一個(gè)磁盤文件中47#include<stdio.h>#include<stdlib.h>intmain(){FILE*in,*out;charch,infile[10],outfile[10];printf("輸入讀入文件的名字:");scanf("%s",infile);printf("輸入輸出文件的名字:");scanf(“%s”,outfile);if((in=fopen(infile,“r”))==NULL){printf("無(wú)法打開(kāi)此文件\n");exit(0);}if((out=fopen(outfile,“w”))==NULL){printf("無(wú)法打開(kāi)此文件\n");exit(0);}改為rb和wb,則復(fù)制一個(gè)二進(jìn)制文件改為rb和wb,則復(fù)制一個(gè)二進(jìn)制文件#include<stdio.h>改為rb和wb,則復(fù)制一48while(!feof(in)){ch=fgetc(in);
fputc(ch,out);putchar(ch);}putchar(‘\n’);fclose(in);fclose(out);return0;}檢查當(dāng)前讀寫位置是否移到文件末尾while(!feof(in))檢查當(dāng)前讀寫位置49feof()函數(shù)功能:用于判斷文件讀取是否結(jié)束,如果已經(jīng)讀到文件結(jié)束處,這時(shí),再進(jìn)行讀取操作時(shí),feof()函數(shù)非0,否則返回0.//錯(cuò)誤程序charc;
while(!feof(fp))
{
c=fgetc(fp);
printf("%c\n",c);
}//正確程序charc;
c=fgetc(fp);
while(!feof(fp))
{
printf("%c\n",c);
c=fgetc(fp);
}feof()函數(shù)功能://錯(cuò)誤程序//正確程序5010.3.2怎樣向文件讀寫一個(gè)字符串讀寫一個(gè)字符串的函數(shù)10.3.2怎樣向文件讀寫一個(gè)字符串讀寫一個(gè)字符串的函數(shù)51說(shuō)明:fgets函數(shù)的函數(shù)原型為:char*fgets(char*str,intn,FILE*fp);其作用是從文件讀入一個(gè)字符串調(diào)用時(shí)可以寫成:fgets(str,n,fp);說(shuō)明:52說(shuō)明:fgets(str,n,fp);中n是要求得到的字符個(gè)數(shù),但實(shí)際上只讀n-1個(gè)字符,然后在最后加一個(gè)’\0’字符,這樣得到的字符串共有n個(gè)字符,把它們放到字符數(shù)組str中如果在讀完n-1個(gè)字符之前遇到換行符“\n”或文件結(jié)束符EOF,讀入即結(jié)束,但將所遇到的換行符“\n”也作為一個(gè)字符讀入執(zhí)行fgets成功,返回str數(shù)組首地址,如果一開(kāi)始就遇到文件尾或讀數(shù)據(jù)錯(cuò),返回NULL說(shuō)明:53說(shuō)明:fputs函數(shù)的函數(shù)原型為:intfputs(char*str,FILE*fp);str指向的字符串輸出到fp所指向的文件中調(diào)用時(shí)可以寫成:fputs(″China”,fp);fputs函數(shù)中第一個(gè)參數(shù)可以是字符串常量、字符數(shù)組名或字符型指針字符串末尾的′\0′不輸出,也不自動(dòng)添加換行符號(hào)。輸出成功,函數(shù)值為0;失敗,函數(shù)值為EOF說(shuō)明:54
例10.3從鍵盤讀入若干個(gè)字符串,對(duì)它們按字母大小的順序排序,然后把排好序的字符串送到磁盤文件中保存。解題思路:為解決問(wèn)題,可分為三個(gè)步驟:從鍵盤讀入n個(gè)字符串,存放在一個(gè)二維字符數(shù)組中,每一個(gè)一維數(shù)組存放一個(gè)字符串;對(duì)字符數(shù)組中的n個(gè)字符串按字母順序排序,排好序的字符串仍存放在字符數(shù)組中;將字符數(shù)組中的字符串順序輸出。例10.3從鍵盤讀入若干個(gè)字符串,對(duì)它們按字母大小的順55#include<stdio.h>#include<stdlib.h>#include<string.h>intmain(){FILE*fp;charstr[3][10],temp[10];inti,j,k,n=3;printf(“Enterstrings:\n”);for(i=0;i<n;i++)gets(str[i]);#include<stdio.h>56for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(str[k],str[j])>0)k=j;if(k!=i) {strcpy(temp,str[i]); strcpy(str[i],str[k]); strcpy(str[k],temp);}}for(i=0;i<n-1;i++)57if((fp=fopen(“D:\\CC\\string.dat”,“w”))==NULL){printf("can'topenfile!\n");exit(0);}printf("\nThenewsequence:\n");for(i=0;i<n;i++) {fputs(str[i],fp);fputs(“\n”,fp); printf(“%s\n”,str[i]);} fclose(fp);return0;}人為地輸出一個(gè)’\n’if((fp=fopen(“D:\\CC\\stri58思考:從文件string.dat中讀回字符串,并在屏幕上顯示,應(yīng)如何編寫程序?思考:59#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp;charstr[3][10];inti=0;if((fp=fopen(“D:\\CC\\string.dat”,“r”))==NULL){printf("can'topenfile!\n");exit(0);}while(fgets(str[i],10,fp)!=NULL){printf("%s",str[i]);i++;}fclose(fp);return0;}不用人為地輸出’\n’#include<stdio.h>不用人為地輸出’\n’6010.3.3用格式化的方式讀寫文件一般調(diào)用方式為:fprintf(文件指針,格式字符串,輸出表列);fscanf(文件指針,格式字符串,輸入表列);如:fprintf(fp,”%d,%6.2f”,i,f);fscanf(fp,”%d,%f”,&i,&f);10.3.3用格式化的方式讀寫文件一般調(diào)用方式為:61文件讀寫舉例L104.c在D盤根目錄下有文件A.txt,該文件包含n行字符數(shù)據(jù)。編寫程序完成如下功能:編寫函數(shù)讀取A.txt文件的數(shù)據(jù)。編寫函數(shù),將文件中所有非數(shù)字字符以其ASCII值轉(zhuǎn)換成數(shù)字字符,例如:’A‘轉(zhuǎn)換成’6‘和’5‘兩個(gè)數(shù)字字符,并輸出到屏幕上。編寫函數(shù),將原文件中的字符以其ASCII值輸出到D盤根目錄下的文件B.txt中。文件讀寫舉例L104.c在D盤根目錄下有文件A.txt,該文6210.3.4用二進(jìn)制方式向文件讀寫一組數(shù)據(jù)一般調(diào)用形式為:fread(buffer,size,count,fp);fwrite(buffer,size,count,fp);
10.3.4用二進(jìn)制方式向文件讀寫一組數(shù)據(jù)一般調(diào)用形式為:6310.3.4用二進(jìn)制方式向文件讀寫一組數(shù)據(jù)buffer:是一個(gè)地址對(duì)fread來(lái)說(shuō),它是用來(lái)存放從文件讀入的數(shù)據(jù)的存儲(chǔ)區(qū)的地址對(duì)fwrite來(lái)說(shuō),是要把此地址開(kāi)始的存儲(chǔ)區(qū)中的數(shù)據(jù)向文件輸出size:要讀寫的字節(jié)數(shù)count:要讀寫多少個(gè)數(shù)據(jù)項(xiàng)fp:FILE類型指針10.3.4用二進(jìn)制方式向文件讀寫一組數(shù)據(jù)buffer:是64
例10.5從鍵盤輸入10個(gè)學(xué)生的有關(guān)數(shù)據(jù),然后把它們轉(zhuǎn)存到磁盤文件上去。
解題思路:定義有10個(gè)元素的結(jié)構(gòu)體數(shù)組,用來(lái)存放10個(gè)學(xué)生的數(shù)據(jù)從main函數(shù)輸入10個(gè)學(xué)生的數(shù)據(jù)用save函數(shù)實(shí)現(xiàn)向磁盤輸出學(xué)生數(shù)據(jù)用fwrite函數(shù)一次輸出一個(gè)學(xué)生的數(shù)據(jù)例10.5從鍵盤輸入10個(gè)學(xué)生的有關(guān)數(shù)據(jù),然后把它們轉(zhuǎn)65#include<stdio.h>#defineSIZE10typedefstructStudent_type{charname[10];intnum;intage;charaddr[15];}TAGSTUDENT;TAGSTUDENTstud[SIZE];#include<stdio.h>66voidsave(){FILE*fp;inti;if((fp=fopen("stu.dat","wb"))==NULL){printf("cannotopenfile\n");return;}for(i=0;i<SIZE;i++)if(fwrite(&stud[i],
sizeof(structStudent_type),1,fp)!=1)printf("filewriteerror\n");fclose(fp);}10+4+4+15=33,實(shí)際上開(kāi)辟36字節(jié),是4的倍數(shù)當(dāng)前路徑下的文件voidsave()10+4+4+15=33,實(shí)際67intmain(){inti;printf(“enterdataofstudents:\n");for(i=0;i<SIZE;i++)scanf("%s%d%d%s",stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);save();return0;}intmain()68為了驗(yàn)證在磁盤文件“stu.dat”中是否已存在此數(shù)據(jù),可以用以下程序從“stu.dat”文件中讀入數(shù)據(jù),然后在屏幕上輸出。為了驗(yàn)證在磁盤文件“stu.dat”中是否已存在此數(shù)據(jù),可以69#include<stdio.h>#include<stdlib.h>#defineSIZE10structStudent_type{charname[10];intnum;intage;charaddr[15];}stud[SIZE];#include<stdio.h>70intmain(){inti;FILE*fp;if((fp=fopen("stu.dat","rb"))==NULL){printf("cannotopenfile\n");exit(0);}for(i=0;i<SIZE;i++){fread(&stud[i],sizeof(structStudent_type),1,fp);printf(“%-10s%4d%4d%-15s\n”,stud[i].name,stud[i].num,stud[i].age,stud[i].addr);}fclose(fp);return0;}intmain()71
如果修改例10.4:從已有的二進(jìn)制文件“stu.list”中,讀入數(shù)據(jù)并輸出到“stu.dat”文件中,應(yīng)如何修改程序?
解題思路:編寫load函數(shù)main函數(shù)中再調(diào)用load函數(shù)如果修改例10.4:從已有的二進(jìn)制文件“stu.list72voidload(){FILE*fp;inti;if((fp=fopen("stu_list","rb"))==NULL){printf("cannotopeninfile\n");return;}for(i=0;i<SIZE;i++)if(fread(&stud[i],sizeof(structstudent_type),1,fp)!=1){if(feof(fp)) {fclose(fp);return;}printf("filereaderror\n");}fclose(fp);}voidload()73intmain(){load();
save();return0;}intmain()7410.4隨機(jī)讀寫數(shù)據(jù)文件對(duì)文件進(jìn)行順序讀寫比較容易理解,也容易操作,但有時(shí)效率不高隨機(jī)訪問(wèn)不是按數(shù)據(jù)在文件中的物理位置次序進(jìn)行讀寫,而是可以對(duì)任何位置上的數(shù)據(jù)進(jìn)行訪問(wèn),顯然這種方法比順序訪問(wèn)效率高得多10.4隨機(jī)讀寫數(shù)據(jù)文件對(duì)文件進(jìn)行順序讀寫比較容易理解,也7510.4隨機(jī)讀寫數(shù)據(jù)文件10.4.1文件位置標(biāo)記及其定位10.4.2隨機(jī)讀寫10.4隨機(jī)讀寫數(shù)據(jù)文件10.4.1文件位置標(biāo)記及其定位7610.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記為了對(duì)讀寫進(jìn)行控制,系統(tǒng)為每個(gè)文件設(shè)置了一個(gè)文件讀寫位置標(biāo)記(簡(jiǎn)稱文件標(biāo)記),用來(lái)指示“接下來(lái)要讀寫的下一個(gè)字符的位置”10.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記7710.4.1文件位置標(biāo)記及其定位文件指針讀寫當(dāng)前位置文件尾1.文件位置標(biāo)記文件頭10.4.1文件位置標(biāo)記及其定位文件指針讀寫當(dāng)前位置文件尾7810.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記一般情況下,在對(duì)字符文件進(jìn)行順序讀寫時(shí),文件標(biāo)記指向文件開(kāi)頭,進(jìn)行讀的操作時(shí),就讀第一個(gè)字符,然后文件標(biāo)記向后移一個(gè)位置,在下一次讀操作時(shí),就將位置標(biāo)記指向的第二個(gè)字符讀入。依此類推,直到遇文件尾,結(jié)束10.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記7910.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記如果是順序?qū)懳募?,則每寫完一個(gè)數(shù)據(jù)后,文件標(biāo)記順序向后移一個(gè)位置,然后在下一次執(zhí)行寫操作時(shí)把數(shù)據(jù)寫入指針?biāo)傅奈恢谩V钡桨讶繑?shù)據(jù)寫完,此時(shí)文件位置標(biāo)記在最后一個(gè)數(shù)據(jù)之后10.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記8010.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記可以根據(jù)讀寫的需要,人為地移動(dòng)了文件標(biāo)記的位置。文件標(biāo)記可以向前移、向后移,移到文件頭或文件尾,然后對(duì)該位置進(jìn)行讀寫——隨機(jī)讀寫隨機(jī)讀寫可以在任何位置寫入數(shù)據(jù),在任何位置讀取數(shù)據(jù)10.4.1文件位置標(biāo)記及其定位1.文件位置標(biāo)記8110.4.1文件位置標(biāo)記及其定位2.文件位置標(biāo)記的定位可以強(qiáng)制使文件位置標(biāo)記指向指定的位置可以用以下函數(shù)實(shí)現(xiàn):(1)用rewind函數(shù)使文件標(biāo)記指向文件開(kāi)頭rewind函數(shù)的作用是使文件標(biāo)記重新返回文件的開(kāi)頭,此函數(shù)沒(méi)有返回值。10.4.1文件位置標(biāo)記及其定位2.文件位置標(biāo)記的定位82
例10.5有一個(gè)磁盤文件,內(nèi)有一些信息。要求第一次將它的內(nèi)容顯示在屏幕上,第二次把它復(fù)制到另一文件上。例10.5有一個(gè)磁盤文件,內(nèi)有一些信息。要求第一次將它83解題思路:因?yàn)樵诘谝淮巫x入完文件內(nèi)容后,文件標(biāo)記已指到文件的末尾,如果再接著讀數(shù)據(jù),就遇到文件結(jié)束標(biāo)志,feof函數(shù)的值等于1(真),無(wú)法再讀數(shù)據(jù)必須在程序中用rewind函數(shù)使位置指針?lè)祷匚募拈_(kāi)頭解題思路:84#include<stdio.h>intmain(){FILE*fp1,*fp2;fp1=fopen(“file1.dat”,“r”);fp2=fopen(“file2.dat”,“w”);while(!feof(fp1))putchar(getc(fp1));putchar(10);
rewind(fp1);while(!feof(fp1))putc(getc(fp1),fp2);fclose(fp1);fclose(fp2);return0;}#include<stdio.h>8510.4.1文件位置標(biāo)記及其定位2.文件位置標(biāo)記的定位可以強(qiáng)制使文件標(biāo)記指向指定的位置可以用以下函數(shù)實(shí)現(xiàn):(2)用fseek函數(shù)改變文件標(biāo)記fseek函數(shù)的調(diào)用形式為:fseek(文件類型指針,位移量,起始點(diǎn))起始點(diǎn)0代表“文件開(kāi)始位置”,1為“當(dāng)前位置”,2為“文件末尾位置”10.4.1文件位置標(biāo)記及其定位2.文件位置標(biāo)記的定位86C標(biāo)準(zhǔn)指定的名字C標(biāo)準(zhǔn)指定的名字87位移量指以起始點(diǎn)為基點(diǎn),向前移動(dòng)的字節(jié)數(shù)。位移量應(yīng)是long型數(shù)據(jù)(在數(shù)字的末尾加一個(gè)字母L)。fseek函數(shù)一般用于二進(jìn)制文件。下面是fseek函數(shù)調(diào)用的幾個(gè)例子:
fseek(fp,100L,0);fseek(fp,50L,1);fseek(fp,-10L,2);位移量指以起始點(diǎn)為基點(diǎn),向前移動(dòng)的字節(jié)數(shù)。位移量應(yīng)是long8810.4.1文件位置標(biāo)記及其定位2.文件位置標(biāo)記的定位可以強(qiáng)制使文件位置標(biāo)記指向指定的位置可以用以下函數(shù)實(shí)現(xiàn):(3)用ftell函數(shù)測(cè)定文件位置標(biāo)記的當(dāng)前位置ftell函數(shù)的作用是得到流式文件中文件位置標(biāo)記的當(dāng)前位置。10.4.1文件位置標(biāo)記及其定位2.文件位置標(biāo)記的定位89由于文件中的文件位置標(biāo)記經(jīng)常移動(dòng),人們往往不容易知道其當(dāng)前位置,所以常用ftell函數(shù)得到當(dāng)前位置,用相對(duì)于文件開(kāi)頭的位移量來(lái)表示。如果調(diào)用函數(shù)時(shí)出錯(cuò)(如不存在fp指向的文件),ftell函數(shù)返回值為-1L。例如:i=ftell(fp);if(i==-1L)printf(“error\n”);由于文件中的文件位置標(biāo)記經(jīng)常移動(dòng),人們往往不容易知道其當(dāng)前位9010.4.2隨機(jī)讀寫
例10.6在磁盤文件上存有10個(gè)學(xué)生的數(shù)據(jù)。要求將第1,3,5,7,9個(gè)學(xué)生數(shù)據(jù)輸入計(jì)算機(jī),并在屏幕上顯示出來(lái)。要求:從例10.4中建立的“stu.dat”中讀入數(shù)據(jù)10.4.2隨機(jī)讀寫例10.6在磁盤文件上存有109110.4.2隨機(jī)讀寫解題思路:按二進(jìn)制只讀方式打開(kāi)文件將文件位置標(biāo)記指向文件的開(kāi)頭,讀入一個(gè)學(xué)生的信息,并把它顯示在屏幕上再將文件標(biāo)記指向文件中第3,5,7,9個(gè)學(xué)生的數(shù)據(jù)區(qū)的開(kāi)頭,讀入相應(yīng)學(xué)生的信息,并把它顯示在屏幕上關(guān)閉文件10.4.2隨機(jī)讀寫解題思路:92#include<stdio.h>#include<stdlib.h>structSt{charname[10];intnum;intage;charaddr[15];}stud[10];#include<stdio.h>93intmain(){inti;FILE*fp;if((fp=fopen(“stu.dat”,“rb”))==NULL){printf("cannotopenfile\n");exit(0);}for(i=0;i<10;i+=2){fseek(fp,i*sizeof(structSt),0);fread(&stud[i],sizeof(structSt),1,fp);printf(“%-10s%4d%4d%-15s\n”,stud[i].name,stud[i].num,stud[i].age,stud[i].addr);}fclose(fp);return0;}intmain()9410.5文件讀寫的出錯(cuò)檢測(cè)1.ferror函數(shù)ferror函數(shù)的一般調(diào)用形式為ferror(fp);如果返回值為0,表示未出錯(cuò),否則表示出錯(cuò)每次調(diào)用輸入輸出函數(shù),都產(chǎn)生新的ferror函數(shù)值,因此調(diào)用輸入輸出函數(shù)后立即檢查調(diào)用fopen時(shí),ferror的初始值自動(dòng)置為010.5文件讀寫的出錯(cuò)檢測(cè)1.ferror函數(shù)9510.5文件讀寫的出錯(cuò)檢測(cè)2.clearerr函數(shù)作用是使文件錯(cuò)誤標(biāo)志和文件結(jié)束標(biāo)志置為0調(diào)用一個(gè)輸入輸出函數(shù)時(shí)出現(xiàn)錯(cuò)誤(ferror值為非零值),立即調(diào)用clearerr(fp),使ferror(fp)值變0,以便再進(jìn)行下一次檢測(cè)只要出現(xiàn)文件讀寫錯(cuò)誤標(biāo)志,它就一直保留,直到對(duì)同一文件調(diào)用clearerr函數(shù)或rewind函數(shù),或任何其他一個(gè)輸入輸出函數(shù)10.5文件讀寫的出錯(cuò)檢測(cè)2.clearerr函數(shù)96補(bǔ)充:文件讀取結(jié)束的方法使用feof()函數(shù)適用于:文本文件和二進(jìn)制文件舉例(1)L105.c:在D盤有一文本文件A.txt,要求將文件復(fù)制到E盤,并重命名為B.txt文件,并將文件內(nèi)容輸出到屏幕上。補(bǔ)充:文件讀取結(jié)束的方法使用feof()函數(shù)97補(bǔ)充:文件讀取結(jié)束的方法舉例(2)在D盤有一二進(jìn)制文件data02.dat,文件中包含不超過(guò)50個(gè)整數(shù)信息,要求讀取所有數(shù)據(jù),并將數(shù)據(jù)按從低到高排序,然后將排序后的數(shù)據(jù)輸出到屏幕上和D盤下的文本文件data02.txt中補(bǔ)充:文件讀取結(jié)束的方法舉例(2)98補(bǔ)充:文件讀取結(jié)束的方法舉例(3)在D盤有一二進(jìn)制文件data_book.dat,文件中包含不超過(guò)50個(gè)book的信息,要求讀取所有書(shū)本數(shù)據(jù),并按書(shū)的價(jià)格從低到高排序,然后將所有書(shū)本信息輸出到屏幕上和D盤下的文本文件data_book.txt中,其中book信息結(jié)構(gòu)如下:struct_Book{charname[20];charauthor[20];floatprice;//價(jià)格}補(bǔ)充:文件讀取結(jié)束的方法舉例(3)99補(bǔ)充:文件讀取結(jié)束的方法使用fseek()函數(shù)計(jì)算文件數(shù)據(jù)塊個(gè)數(shù)步驟:打開(kāi)文件使用fseek(fp,0,SEEK_END)定位文件指針到文件末端使用size=ftell(fp)計(jì)算二進(jìn)制文件的字節(jié)數(shù)使用num=size/sizeof(信息塊大小)計(jì)算信息塊數(shù)量使用fseek(fp,0,SEEK_SET)重新定位文件指針到文件開(kāi)始位置使用循環(huán)讀取num塊數(shù)據(jù)就ok只適用于二進(jìn)制文件舉例(2)補(bǔ)充:文件讀取結(jié)束的方法使用fseek()函數(shù)計(jì)算文件數(shù)據(jù)塊100補(bǔ)充例題9設(shè)D盤根目錄下有一個(gè)二進(jìn)制文件data9.dat,該文件中存放了不超過(guò)100個(gè)的若干字符。編寫一個(gè)程序,將該文件中可能的字符'A'替換成字符'#',可能的字符'B'替換成字符'*'。補(bǔ)充例題9設(shè)D盤根目錄下有一個(gè)二進(jìn)制文件data9.dat,101C語(yǔ)言程序設(shè)計(jì)姚望舒計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院蘇州大學(xué)C語(yǔ)言程序設(shè)計(jì)姚望舒102第10章對(duì)文件的輸入輸出10.1C文件的有關(guān)基本知識(shí)10.2打開(kāi)與關(guān)閉文件10.3順序讀寫數(shù)據(jù)文件10.4隨機(jī)讀寫數(shù)據(jù)文件10.5文件讀寫的出錯(cuò)檢測(cè)第10章對(duì)文件的輸入輸出10.1C文件的有關(guān)基本知識(shí)10310.1C文件的有關(guān)基本知識(shí)10.1.1什么是文件10.1.2文件名10.1.3文件的分類10.1.4文件緩沖區(qū)10.1.5文件類型指針10.1C文件的有關(guān)基本知識(shí)10.1.1什么是文件104C語(yǔ)言程序設(shè)計(jì)第10章對(duì)文件的輸入輸出[精]課件105C語(yǔ)言程序設(shè)計(jì)第10章對(duì)文件的輸入輸出[精]課件106C語(yǔ)言程序設(shè)計(jì)第10章對(duì)文件的輸入輸出[精]課件10710.1.1什么是文件輸入輸出是數(shù)據(jù)傳送的過(guò)程,數(shù)據(jù)如流水一樣從一處流向另一處,因此常將輸入輸出形象地稱為流(stream),即數(shù)據(jù)流。流表示了信息從源到目的端的流動(dòng)。輸入操作時(shí),數(shù)據(jù)從文件流向計(jì)算機(jī)內(nèi)存輸出操作時(shí),數(shù)據(jù)從計(jì)算機(jī)流向文件“流”是一個(gè)傳輸通道,數(shù)據(jù)可以從運(yùn)行環(huán)境流入程序中,或從程序流至運(yùn)行環(huán)境10.1.1什么是文件輸入輸出是數(shù)據(jù)傳送的過(guò)程,數(shù)據(jù)如流水10810.1.1什么是文件從C程序的觀點(diǎn)來(lái)看,無(wú)論程序一次讀寫一個(gè)字符,或一行文字,或一個(gè)指定的數(shù)據(jù)區(qū),作為輸入輸出的各種文件或設(shè)備都是統(tǒng)一以邏輯數(shù)據(jù)流的方式出現(xiàn)的。C語(yǔ)言把文件看作是一個(gè)字符(或字節(jié))的序列。一個(gè)輸入輸出流就是一個(gè)字符流或字節(jié)(內(nèi)容為二進(jìn)制數(shù)據(jù))流。10.1.1什么是文件從C程序的觀點(diǎn)來(lái)看,無(wú)論程序一次讀寫10910.1.1什么是文件C的數(shù)據(jù)文件由一連串的字符(或字節(jié))組成,而不考慮行的界限,兩行數(shù)據(jù)間不會(huì)自動(dòng)加分隔符,對(duì)文件的存取是以字符(字節(jié))為單位的。輸入輸出數(shù)據(jù)流的開(kāi)始和結(jié)束僅受程序控制而不受物理符號(hào)(如回車換行符)控制,這就增加了處理的靈活性。這種文件稱為流式文件。10.1.1什么是文件C的數(shù)據(jù)文件由一連串的字符(或字節(jié))11010.1.2文件名文件要有一個(gè)唯一的文件標(biāo)識(shí),以便用戶識(shí)別和引用。文件標(biāo)識(shí)包括三部分:(1)文件路徑(2)文件名主干(3)文件后綴10.1.2文件名文件要有一個(gè)唯一的文件標(biāo)識(shí),以便用戶識(shí)別11110.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面文件路徑文件名主干文件后綴10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。11210.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面文件名10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。11310.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面命名規(guī)則遵循標(biāo)識(shí)符的命名規(guī)則10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。11410.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面一般不超過(guò)3個(gè)字母(doc、txt、dat、c、cpp、obj、exe、ppt、bmp等)10.1.2文件名文件路徑表示文件在外部存儲(chǔ)設(shè)備中的位置。11510.1.3文件的分類根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件可分為ASCII文件和二進(jìn)制文件。數(shù)據(jù)在內(nèi)存中是以二進(jìn)制形式存儲(chǔ)的,如果不加轉(zhuǎn)換地輸出到外存,就是二進(jìn)制文件如果要求在外存上以ASCII代碼形式存儲(chǔ),則需要在存儲(chǔ)前進(jìn)行轉(zhuǎn)換ASCII文件又稱文本文件,每一個(gè)字節(jié)放一個(gè)字符的ASCII代碼10.1.3文件的分類根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件可分為A11610.1.3文件的分類字符一律以ASCII形式存儲(chǔ)數(shù)值型數(shù)據(jù)既可以用ASCII形式存儲(chǔ),也可以用二進(jìn)制形式存儲(chǔ)如有整數(shù)10000,如果用ASCII碼形式輸出到磁盤,則在磁盤中占5個(gè)字節(jié)(每一個(gè)字符占一個(gè)字節(jié)),而用二進(jìn)制形式輸出,則在磁盤上只占4個(gè)字節(jié)(用VC++C時(shí))10.1.3文件的分類字符一律以ASCII形式存儲(chǔ)11710.1.3文件的分類(1)(0)(0)(0)(0)ASCII形式二進(jìn)制形式(10000)10.1.3文件的分類(1)(0)(0)(0)(0)ASC11810.1.4文件緩沖區(qū)ANSIC標(biāo)準(zhǔn)采用“緩沖文件系統(tǒng)”處理數(shù)據(jù)文件所謂緩沖文件系統(tǒng)是指系統(tǒng)自動(dòng)地在內(nèi)存區(qū)為程序中每一個(gè)正在使用的文件開(kāi)辟一個(gè)文件緩沖區(qū)10.1.4文件緩沖區(qū)ANSIC標(biāo)準(zhǔn)采用“緩沖文件系統(tǒng)”11910.1.4文件緩沖區(qū)從內(nèi)存向磁盤輸出數(shù)據(jù)必須先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才一起送到磁盤去如果從磁盤向計(jì)算機(jī)讀入數(shù)據(jù),則一次從磁盤文件將一批數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再?gòu)木彌_區(qū)逐個(gè)地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(給程序變量)10.1.4文件緩沖區(qū)從內(nèi)存向磁盤輸出數(shù)據(jù)必須先送到內(nèi)存中12010.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)磁盤從內(nèi)存向磁盤輸出數(shù)據(jù)裝滿緩沖區(qū)10.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖12110.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)磁盤從磁盤向計(jì)算機(jī)讀入數(shù)據(jù)充滿緩沖區(qū)10.1.4文件緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖12210.1.5文件類型指針緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文件類型指針”,簡(jiǎn)稱“文件指針”每個(gè)被使用的文件都在內(nèi)存中開(kāi)辟一個(gè)相應(yīng)的文件信息區(qū),用來(lái)存放文件的有關(guān)信息(如文件的名字、文件狀態(tài)及文件當(dāng)前位置等)這些信息是保存在一個(gè)結(jié)構(gòu)體變量中的。該結(jié)構(gòu)體類型是由系統(tǒng)聲明的,取名為FILE10.1.5文件類型指針緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文12310.1.5文件類型指針聲明FILE結(jié)構(gòu)體類型的信息包含在頭文件“stdio.h”中一般設(shè)置一個(gè)指向FILE類型變量的指針變量,然后通過(guò)它來(lái)引用這些FILE類型變量10.1.5文件類型指針聲明FILE結(jié)構(gòu)體類型的信息包含12410.1.5文件類型指針FILE
*fp1,*fp2,*fp3;文件f1的文件信息區(qū)fp1文件f2的文件信息區(qū)fp2文件f3的文件信息區(qū)fp310.1.5文件類型指針FILE*fp1,*fp2,*12510.2打開(kāi)與關(guān)閉文件10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件10.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件10.2打開(kāi)與關(guān)閉文件10.2.1用fopen函數(shù)打開(kāi)數(shù)12610.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件對(duì)文件讀寫之前應(yīng)該“打開(kāi)”該文件,在使用結(jié)束之后應(yīng)“關(guān)閉”該文件。所謂“打開(kāi)”是指為文件建立相應(yīng)的信息區(qū)(用來(lái)存放有關(guān)文件的信息)和文件緩沖區(qū)(用來(lái)暫時(shí)存放輸入輸出的數(shù)據(jù))。10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件對(duì)文件讀寫之前應(yīng)該12710.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在編寫程序時(shí),在打開(kāi)文件的同時(shí),一般都指定一個(gè)指針變量指向該文件,也就是建立起指針變量與文件之間的聯(lián)系,這樣就可以通過(guò)該指針變量對(duì)文件進(jìn)行讀寫所謂“關(guān)閉”是指撤銷文件信息區(qū)和文件緩沖區(qū)10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在編寫程序時(shí),在打12810.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件fopen函數(shù)的調(diào)用方式為:FILE*fopen(文件名,使用文件方式);例如:
fopen(“a1”,”r”);表示要打開(kāi)名為“a1”的文件,使用文件方式為“讀入”fopen函數(shù)的返回值是指向a1文件的指針10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件fopen函數(shù)的調(diào)12910.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件通常將fopen函數(shù)的返回值賦給一個(gè)指向文件的指針變量。如:FILE*fp;fp=fopen(“a1”,”r”);fp和文件a1相聯(lián)系,fp指向了a1文件a1:有兩種形式文件名:表示文件在工程路徑絕對(duì)路徑:絕對(duì)路徑+文件名10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件通常將fopen函13010.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在打開(kāi)一個(gè)文件時(shí),通知編譯系統(tǒng)以下3個(gè)信息:①需要訪問(wèn)的文件的名字②使用文件的方式(“讀”還是“寫”等)③讓哪一個(gè)指針變量指向被打開(kāi)的文件使用文件方式參見(jiàn)教材表10.1。10.2.1用fopen函數(shù)打開(kāi)數(shù)據(jù)文件在打開(kāi)一個(gè)文件時(shí),131說(shuō)明:(1)用“r”方式打開(kāi)的文件只能用于向計(jì)算機(jī)輸入而不能用作向該文件輸出數(shù)據(jù),而且該文件應(yīng)該已經(jīng)存在,并存有數(shù)據(jù),這樣程序才能從文件中讀數(shù)據(jù)。不能用“r”方式打開(kāi)一個(gè)并不存在的文件,否則出錯(cuò)。說(shuō)明:132說(shuō)明:(2)用“w”方式打開(kāi)的文件只能用于向該文件寫數(shù)據(jù)(即輸出文件),而不能用來(lái)向計(jì)算機(jī)輸入。如果原來(lái)不存在該文件,則在打開(kāi)文件前新建立一個(gè)以指定的名字命名的文件。如果原來(lái)已存在一個(gè)以該文件名命名的文件,則在打開(kāi)文件前先將該文件刪去,然后重新建立一個(gè)新文件。說(shuō)明:133說(shuō)明:(3)如果希望向文件末尾添加新的數(shù)據(jù)(不希望刪除原有數(shù)據(jù)),則應(yīng)該用“a”方式打開(kāi)但此時(shí)應(yīng)保證該文件已存在;否則將得到出錯(cuò)信息。打開(kāi)文件時(shí),文件讀寫標(biāo)記移到文件末尾說(shuō)明:134說(shuō)明:(4)用r+、w+、a+方式打開(kāi)的文件既可以用來(lái)輸入數(shù)據(jù),也可以用來(lái)輸出數(shù)據(jù)。用r+方式時(shí)該文件應(yīng)該已經(jīng)存在。用w+方式則新建立一個(gè)文件,先向此文件寫數(shù)據(jù),然后可以讀此文件中的數(shù)據(jù)。用a+方式打開(kāi)的文件,原來(lái)的文件不被刪去,文件讀寫位置標(biāo)記移到文件末尾,可以添加,也可以讀。說(shuō)明:135說(shuō)明:(5)如果打開(kāi)失敗,fopen函數(shù)將會(huì)帶回一個(gè)出錯(cuò)信息。fopen函數(shù)將帶回一個(gè)空指針值NULL常用下面的方法打開(kāi)一個(gè)文件:if((fp=fopen(“file1”,’r″))==NULL)
{printf(“cannotopenthisfile\n”);exit(0);
}終止正在執(zhí)行的程序說(shuō)明:終止正在執(zhí)行的程序136說(shuō)明:(6)C標(biāo)準(zhǔn)建議用表10.1列出的文件使用方式打開(kāi)文本文件或二進(jìn)制文件,但目前使用的有些C編譯系統(tǒng)可能不完全提供所有這些功能說(shuō)明:137說(shuō)明:(7)計(jì)算機(jī)輸從ASCII文件讀入字符時(shí),遇到回車換行符,系統(tǒng)把它轉(zhuǎn)換為一個(gè)換行符,在輸出時(shí)把換行符轉(zhuǎn)換成為回車和換行兩個(gè)字符。在用二進(jìn)制文件時(shí),不進(jìn)行這種轉(zhuǎn)換,在內(nèi)存中的數(shù)據(jù)形式與輸出到外部文件中的數(shù)據(jù)形式完全一致,一一對(duì)應(yīng)。說(shuō)明:138說(shuō)明:(8)程序中可以使用3個(gè)標(biāo)準(zhǔn)的流文件:標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、標(biāo)準(zhǔn)出錯(cuò)輸出流。系統(tǒng)已對(duì)這3個(gè)文件指定了與終端的對(duì)應(yīng)關(guān)系標(biāo)準(zhǔn)輸入流是從終端的輸入標(biāo)準(zhǔn)輸出流是向終端的輸出標(biāo)準(zhǔn)出錯(cuò)輸出流是當(dāng)程序出錯(cuò)時(shí)將出錯(cuò)信息發(fā)送到終端說(shuō)明:139程序開(kāi)始運(yùn)行時(shí)系統(tǒng)自動(dòng)打開(kāi)這3個(gè)標(biāo)準(zhǔn)流文件。因此,程序編寫者不需要在程序中用fopen函數(shù)打開(kāi)它們。所以以前我們用到的從終端輸入或輸出到終端都不需要打開(kāi)終端文件。程序開(kāi)始運(yùn)行時(shí)系統(tǒng)自動(dòng)打開(kāi)這3個(gè)標(biāo)準(zhǔn)流文件。因此,程序編寫者14010.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件關(guān)閉文件用fclose函數(shù)。fclose函數(shù)調(diào)用的一般形式為fclose(文件指針);例如:
fclose(fp);如果不關(guān)閉文件將會(huì)丟失數(shù)據(jù)。10.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件關(guān)閉文件用fcl14110.3順序讀寫數(shù)據(jù)文件在順序?qū)憰r(shí),先寫入的數(shù)據(jù)存放在文件中前面,后寫入的數(shù)據(jù)存放在文件中后面在順序讀時(shí),先讀文件中前面的數(shù)據(jù),后讀文件中后面的數(shù)據(jù)對(duì)順序讀寫來(lái)說(shuō),對(duì)文件讀寫數(shù)據(jù)的順序和數(shù)據(jù)在文件中的物理順序是一致的順序讀寫需要用庫(kù)函數(shù)實(shí)現(xiàn)10.3順序讀寫數(shù)據(jù)文件在順序?qū)憰r(shí),先寫入的數(shù)據(jù)存放在文件14210.3順序讀寫數(shù)據(jù)文件10.3.1怎樣向文件讀寫字符10.3.2怎樣向文件讀寫一個(gè)字符串10.3.3用格式化的方式讀寫文件10.3.4用二進(jìn)制方式向文件讀寫一組數(shù)據(jù)10.3順序讀寫數(shù)據(jù)文件10.3.1怎樣向文件讀寫字符14310.3.1怎樣向文件讀寫字符讀寫一個(gè)字符的函數(shù)10.3.1怎樣向文件讀寫字符讀寫一個(gè)字符的函數(shù)144
例10.1從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上去,直到用戶輸入一個(gè)“#”為止。
解題思路:用fgetc函數(shù)從鍵盤逐個(gè)輸入字符,然后用fputc函數(shù)寫到磁盤文件即可。例10.1從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上去,145#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp;charch,filename[10];printf("請(qǐng)輸入所用的文件名:");scanf("%s",filename);if((fp=fopen(filename,“w”))==NULL) {printf("無(wú)法打開(kāi)此文件\n");exit(0);}ch=getchar();接收最后輸入的回車符輸入文件名只寫用exit函數(shù)時(shí)加#include<stdio.h>接收最后輸入的回車符輸入146printf(“請(qǐng)輸入一個(gè)字符串(以#結(jié)束):");ch=getchar();while(ch!=‘#’) {fputc(ch,fp);putchar(ch); ch=getchar(); }
fclose(fp);putchar(‘\n’);return0;}printf(“請(qǐng)輸入一個(gè)字符串(以#結(jié)束):");147
例10.2將一個(gè)磁盤文件中的信息復(fù)制到另一個(gè)磁盤文件中。今要求將上例建立的file1.dat文件中的內(nèi)容復(fù)制到另一個(gè)磁盤文件file2.dat中。解題思路:處理此問(wèn)題的算法是:從file1.dat文件中逐個(gè)讀入字符,然后逐個(gè)輸出到file2.dat中。例10.2將一個(gè)磁盤文件中的信息復(fù)制到另一個(gè)磁盤文件中148#include<stdio.h>#include<stdlib.h>intmain(){FILE*in,*out;charch,infile[10],outfile[10];printf("輸入讀入文件的名字:");scanf("%s",infile);printf("輸入輸出文件的名字:");scanf(“%s”,outfile);if((in=fopen(infile,“r”))==NULL){printf("無(wú)法打開(kāi)此文件\n");exit(0);}if((out=fopen(outfile,“w”))==NULL){printf("無(wú)法打開(kāi)此文件\n");exit(0);}改為rb和wb,則復(fù)制一個(gè)二進(jìn)制文件改為rb和wb,則復(fù)制一個(gè)二進(jìn)制文件#include<stdio.h>改為rb和wb,則復(fù)制一149while(!feof(in)){ch=fgetc(in);
fputc(ch,out);putchar(ch);}putchar(‘\n’);fclose(in);fclose(out);return0;}檢查當(dāng)前讀寫位置是否移到文件末尾while(!feof(in))檢查當(dāng)前讀寫位置150feof()函數(shù)功能:用于判斷文件讀取是否結(jié)束,如果已經(jīng)讀到文件結(jié)束處,這時(shí),再進(jìn)行讀取操作時(shí),feof()函數(shù)非0,否則返回0.//錯(cuò)誤程序charc;
while(!feof(fp))
{
c=fgetc(fp);
printf("%c\n",c);
}//正確程序charc;
c=fgetc(fp);
while(!feof(fp))
{
printf("%c\n",c);
c=fgetc(fp);
}feof()函數(shù)功能://錯(cuò)誤程序//正確程序15110.3.2怎樣向文件讀寫一個(gè)字符串讀寫一個(gè)字符串的函數(shù)10.3.2怎樣向文件讀寫一個(gè)字符串讀寫一個(gè)字符串的函數(shù)152說(shuō)明:fgets函數(shù)的函數(shù)原型為:char*fgets(char*str,intn,FILE*fp);其作用是從文件讀入一個(gè)字符串調(diào)用時(shí)可以寫成:fgets(str,n,fp);說(shuō)明:153說(shuō)明:fgets(str,n,fp);中n是要求得到的字符個(gè)數(shù),但實(shí)際上只讀n-1個(gè)字符,然后在最后加一個(gè)’\0’字符,這樣得到的字符串共有n個(gè)字符,把它們放到字符數(shù)組str中如果在讀完n-1個(gè)字符之前遇到換行符“\n”或文件結(jié)束符EOF,讀入即結(jié)束,但將所遇到的換行符“\n”也作為一個(gè)字符讀入執(zhí)行fgets成功,返回str數(shù)組首地址,如果一開(kāi)始就遇到文件尾或讀數(shù)據(jù)錯(cuò),返回NULL說(shuō)明:154說(shuō)明:fputs函數(shù)的函數(shù)原型為:intfputs(char*str,FILE*fp);str指向的字符串輸出到fp所指向的文件中調(diào)用時(shí)可以寫成:fputs(″China”,fp);fputs函數(shù)中第一個(gè)參數(shù)可以是字符串常量、字符數(shù)組名或字符型指針字符串末尾的′\0′不輸出,也不自動(dòng)添加換行符號(hào)。輸出成功,函數(shù)值為0;失敗,函數(shù)值為EOF說(shuō)明:155
例10.3從鍵盤讀入若干個(gè)字符串,對(duì)它們按字母大小的順序排序,然后把排好序的字符串送到磁盤文件中保存。解題思路:為解決問(wèn)題,可分為三個(gè)步驟:從鍵盤讀入n個(gè)字符串,存放在一個(gè)二維字符數(shù)組中,每一個(gè)一維數(shù)組存放一個(gè)字符串;對(duì)字符數(shù)組中的n個(gè)字符串按字母順序排序,排好序的字符串仍存放在字符數(shù)組中;將字符數(shù)組中的字符串順序輸出。例10.3從鍵盤讀入若干個(gè)字符串,對(duì)它們按字母大小的順156#include<stdio.h>#include<stdlib.h>#include<string.h>intmain(){FILE*fp;charstr[3][10],temp[10];inti,j,k,n=3;printf(“Enterstrings:\n”);for(i=0;i<n;i++)gets(str[i]);#include<stdio.h>157for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(str[k],str[j])>0)k=j;if(k!=i) {strcpy(temp,str[i]); strcpy(str[i],str[k]); strcpy(str[k],temp);}}for(i=0;i<n-1;i++)158if((fp=fopen(“D:\\CC\\string.dat”,“w”))==NULL){printf("can'topenfile!\n");exit(0);}printf("\nThenewsequence:\n");for(i=0;i<n;i++) {fputs(str[i],fp);fputs(“\n”,fp); printf(“%s\n”,str[i]);} fclose(fp);return0;}人為地輸出一個(gè)’\n’if((fp=fopen(“D:\\CC\\stri159思考:從文件string.dat中讀回字符串,并在屏幕上顯示,應(yīng)如何編寫程序?思考:160#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp;charstr[3][10];inti=0;if((fp=fopen(“D:\\CC\\string.dat”,“r”))==NULL){printf("can'topenfile!\n");exit(0);}while(fgets(str[i],10,fp)!=NULL){printf("%s",str[i]);i++;}fclose(fp);return0;}不用人為地輸出’\n’#include<stdio.h>不用人為地輸出’\n’16110.3.3
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 經(jīng)濟(jì)仲裁協(xié)議書(shū)格式
- 小區(qū)門頭購(gòu)買協(xié)議書(shū)
- 企業(yè)履約監(jiān)管協(xié)議書(shū)
- 土方完工結(jié)算協(xié)議書(shū)
- 租賃輪椅使用協(xié)議書(shū)
- 景觀小品轉(zhuǎn)讓協(xié)議書(shū)
- 集體農(nóng)田轉(zhuǎn)讓協(xié)議書(shū)
- 舞蹈老師合伙協(xié)議書(shū)
- 消防裝備評(píng)估協(xié)議書(shū)
- 臨時(shí)簡(jiǎn)易購(gòu)房協(xié)議書(shū)
- 湖南省炎德英才名校聯(lián)考聯(lián)合體2024-2025學(xué)年高二下學(xué)期3月月考-數(shù)學(xué)+答案
- 蔬菜水果食材配送服務(wù)投標(biāo)方案(技術(shù)方案)
- 《高效能NLP溝通技巧》課件
- 電力應(yīng)急物資儲(chǔ)備與管理
- 中國(guó)公民健康素養(yǎng)-基本知識(shí)與技能(2024年版)試題及答案
- 【語(yǔ)文】第三單元整本書(shū)閱讀《駱駝祥子》圈點(diǎn)、批注、做筆記課件-2024-2025學(xué)年統(tǒng)編版語(yǔ)文七年級(jí)下冊(cè)
- 新目錄監(jiān)理規(guī)劃2025
- 2024年天翼云認(rèn)證運(yùn)維工程師考試復(fù)習(xí)題庫(kù)(含答案)
- 儲(chǔ)能項(xiàng)目竣工報(bào)告
- 《偉大的友誼》(配套PPT)課件
- 松脂采割技術(shù)
評(píng)論
0/150
提交評(píng)論