![第10章 對文件輸入輸出_第1頁](http://file4.renrendoc.com/view/167044de3fe88a7a3fd0ad5fd29327b2/167044de3fe88a7a3fd0ad5fd29327b21.gif)
![第10章 對文件輸入輸出_第2頁](http://file4.renrendoc.com/view/167044de3fe88a7a3fd0ad5fd29327b2/167044de3fe88a7a3fd0ad5fd29327b22.gif)
![第10章 對文件輸入輸出_第3頁](http://file4.renrendoc.com/view/167044de3fe88a7a3fd0ad5fd29327b2/167044de3fe88a7a3fd0ad5fd29327b23.gif)
![第10章 對文件輸入輸出_第4頁](http://file4.renrendoc.com/view/167044de3fe88a7a3fd0ad5fd29327b2/167044de3fe88a7a3fd0ad5fd29327b24.gif)
![第10章 對文件輸入輸出_第5頁](http://file4.renrendoc.com/view/167044de3fe88a7a3fd0ad5fd29327b2/167044de3fe88a7a3fd0ad5fd29327b25.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第10章對文件的輸入輸出10.1C文件的有關(guān)基本知識10.2打開與關(guān)閉文件10.3順序讀寫數(shù)據(jù)文件10.4隨機讀寫數(shù)據(jù)文件10.5文件讀寫的出錯檢測10.1C文件的有關(guān)基本知識10.1.1什么是文件10.1.2文件名10.1.3文件的分類10.1.4文件緩沖區(qū)10.1.5文件類型指針10.1.1什么是文件文件有不同的類型,在程序設(shè)計中,主要用到兩種文件:(1)程序文件。包括源程序文件(后綴為.c)、目標文件(后綴為.obj)、可執(zhí)行文件(后綴為.exe)等。這種文件的內(nèi)容是程序代碼。文件有不同的類型,在程序設(shè)計中,主要用到兩種文件:(2)數(shù)據(jù)文件。文件的內(nèi)容不是程序,而是供程序運行時讀寫的數(shù)據(jù),如在程序運行過程中輸出到磁盤(或其他外部設(shè)備)的數(shù)據(jù),或在程序運行過程中供讀入的數(shù)據(jù)。如一批學(xué)生的成績數(shù)據(jù),或貨物交易的數(shù)據(jù)等。本章主要討論的是數(shù)據(jù)文件在以前各章中所處理的數(shù)據(jù)的輸入和輸出,從終端的鍵盤輸入數(shù)據(jù),運行結(jié)果輸出到終端顯示器上常常需要將一些數(shù)據(jù)輸出到磁盤上保存起來,以后使用這就要用到磁盤文件操作系統(tǒng)把各種設(shè)備都統(tǒng)一作為文件處理從操作系統(tǒng)的角度看,每一個與主機相聯(lián)的輸入輸出設(shè)備都看作是文件。例如,終端鍵盤是輸入文件顯示屏和打印機是輸出文件“文件”指存儲在外部介質(zhì)(如磁盤)上數(shù)據(jù)的集合一批數(shù)據(jù)是以文件的形式存放在外部介質(zhì)上的操作系統(tǒng)是以文件為單位對數(shù)據(jù)進行管理想找存放在外部介質(zhì)上的數(shù)據(jù),先按文件名找到所指定的文件,然后再從該文件讀數(shù)據(jù)要向外部介質(zhì)上存儲數(shù)據(jù)也必須先建立一個文件(以文件名作為標志),才能向它輸出數(shù)據(jù)輸入輸出是數(shù)據(jù)傳送的過程,數(shù)據(jù)如流水一樣從一處流向另一處,因此常將輸入輸出形象地稱為流(stream),即數(shù)據(jù)流。流表示了信息從源到目的端的流動。輸入操作時,數(shù)據(jù)從文件流向計算機內(nèi)存輸出操作時,數(shù)據(jù)從計算機流向文件無論是用Word打開或保存文件,還是C程序中的輸入輸出都是通過操作系統(tǒng)進行的“流”是一個傳輸通道,數(shù)據(jù)可以從運行環(huán)境流入程序中,或從程序流至運行環(huán)境從C程序的觀點來看,無論程序一次讀寫一個字符,或一行文字,或一個指定的數(shù)據(jù)區(qū),作為輸入輸出的各種文件或設(shè)備都是統(tǒng)一以邏輯數(shù)據(jù)流的方式出現(xiàn)的。C語言把文件看作是一個字符(或字節(jié))的序列。一個輸入輸出流就是一個字符流或字節(jié)(內(nèi)容為二進制數(shù)據(jù))流。C的數(shù)據(jù)文件由一連串的字符(或字節(jié))組成,而不考慮行的界限,兩行數(shù)據(jù)間不會自動加分隔符,對文件的存取是以字符(字節(jié))為單位的。輸入輸出數(shù)據(jù)流的開始和結(jié)束僅受程序控制而不受物理符號(如回車換行符)控制,這就增加了處理的靈活性。這種文件稱為流式文件。10.1.2文件名文件要有一個唯一的文件標識,以便用戶識別和引用。文件標識包括三部分:(1)文件路徑(2)文件名主干(3)文件后綴文件路徑表示文件在外部存儲設(shè)備中的位置。如:D:\CC\temp\file1.dat表示file1.dat文件存放在D盤中的CC目錄下的temp子目錄下面文件路徑文件名主干文件后綴D:\CC\temp\file1.dat文件名D:\CC\temp\file1.dat一般不超過3個字母(doc、txt、dat、out、cpp、obj、exe、ppt、bmp等)命名規(guī)則遵循標識符的命名規(guī)則10.1.3文件的分類根據(jù)數(shù)據(jù)的組織形式,數(shù)據(jù)文件可分為ASCII文件(文本文件)和二進制文件。數(shù)據(jù)在內(nèi)存中是以二進制形式存儲的,如果不加轉(zhuǎn)換地、按其在內(nèi)存中的存儲形式原樣輸出到外存(如:磁盤),就是二進制文件如果要求在外存上以ASCII代碼形式存儲,則需要在存儲前進行轉(zhuǎn)換ASCII文件又稱文本文件,每一個字節(jié)放一個字符的ASCII代碼字符一律以ASCII形式存儲數(shù)值型數(shù)據(jù)既可以用ASCII形式存儲,也可以用二進制形式存儲如有整數(shù)10000,如果用ASCII碼形式輸出到磁盤,則在磁盤中占5個字節(jié)(每一個字符占一個字節(jié)),而用二進制形式輸出,則在磁盤上只占4個字節(jié)(用VC++時)0011000100110000001100000011000000110000(1)(0)(0)(0)(0)ASCII形式00000000000000000010011100010000二進制形式(10000)ASCII文件和二進制文件的比較ASCII文件便于對字符進行逐個處理,也便于輸出字符。但一般占存儲空間較多,而且要花費轉(zhuǎn)換時間。二進制文件可以節(jié)省外存空間和轉(zhuǎn)換時間,但一個字節(jié)并不對應(yīng)一個字符,不能直接輸出字符形式。一般中間結(jié)果數(shù)據(jù)需要暫時保存在外存上,以后又需要輸入內(nèi)存的,常用二進制文件保存。10.1.4文件緩沖區(qū)ANSIC標準采用“緩沖文件系統(tǒng)”處理數(shù)據(jù)文件所謂緩沖文件系統(tǒng)是指系統(tǒng)自動地在內(nèi)存區(qū)為程序中每一個正在使用的文件開辟一個文件緩沖區(qū)從內(nèi)存向磁盤輸出數(shù)據(jù)必須先送到內(nèi)存中的緩沖區(qū),裝滿緩沖區(qū)后才一起送到磁盤去如果從磁盤向計算機讀入數(shù)據(jù),則一次從磁盤文件將一批數(shù)據(jù)輸入到內(nèi)存緩沖區(qū)(充滿緩沖區(qū)),然后再從緩沖區(qū)逐個地將數(shù)據(jù)送到程序數(shù)據(jù)區(qū)(給程序變量)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)磁盤從內(nèi)存向磁盤輸出數(shù)據(jù)裝滿緩沖區(qū)程序數(shù)據(jù)區(qū)輸出文件緩沖區(qū)輸入文件緩沖區(qū)磁盤從磁盤向計算機讀入數(shù)據(jù)充滿緩沖區(qū)10.1.5文件類型指針緩沖文件系統(tǒng)中,關(guān)鍵的概念是“文件類型指針”,簡稱“文件指針”每個被使用的文件都在內(nèi)存中開辟一個相應(yīng)的文件信息區(qū),用來存放文件的有關(guān)信息(如文件的名字、文件狀態(tài)及文件當(dāng)前位置等)這些信息是保存在一個結(jié)構(gòu)體變量中的。該結(jié)構(gòu)體類型是由系統(tǒng)聲明的,取名為FILE聲明FILE結(jié)構(gòu)體類型的信息包含在頭文件“stdio.h”中一般設(shè)置一個指向FILE類型變量的指針變量,然后通過它來引用這些FILE類型變量FILE
*fp1,*fp2,*fp3;文件f1的文件信息區(qū)fp1文件f2的文件信息區(qū)fp2文件f3的文件信息區(qū)fp310.2打開與關(guān)閉文件10.2.1用fopen函數(shù)打開數(shù)據(jù)文件10.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件10.2.1用fopen函數(shù)打開數(shù)據(jù)文件對文件讀寫之前應(yīng)該“打開”該文件,在使用結(jié)束之后應(yīng)“關(guān)閉”該文件。所謂“打開”是指為文件建立相應(yīng)的信息區(qū)(用來存放有關(guān)文件的信息)和文件緩沖區(qū)(用來暫時存放輸入輸出的數(shù)據(jù))。在編寫程序時,在打開文件的同時,一般都指定一個指針變量指向該文件,也就是建立起指針變量與文件之間的聯(lián)系,這樣就可以通過該指針變量對文件進行讀寫所謂“關(guān)閉”是指撤銷文件信息區(qū)和文件緩沖區(qū)fopen函數(shù)的調(diào)用方式為:fopen(文件名,使用文件方式);例如:
fopen(“a1”,”r”);表示要打開名為“a1”的文件,使用文件方式為“讀入”fopen函數(shù)的返回值是指向a1文件的指針通常將fopen函數(shù)的返回值賦給一個指向文件的指針變量。如:FILE*fp;fp=fopen(“a1”,”r”);fp和文件a1相聯(lián)系,fp指向了a1文件當(dāng)前路徑下的文件在打開一個文件時,通知編譯系統(tǒng)以下3個信息:①需要訪問的文件的名字②使用文件的方式(“讀”還是“寫”等)③讓哪一個指針變量指向被打開的文件使用文件方式參見教材P335表10.1。說明:(1)用“r”方式打開的文本文件只能用于向計算機輸入而不能用作向該文件輸出數(shù)據(jù),而且該文件應(yīng)該已經(jīng)存在,并存有數(shù)據(jù),這樣程序才能從文件中讀數(shù)據(jù)。不能用“r”方式打開一個并不存在的文件,否則出錯。說明:(2)用“w”方式打開的文本文件只能用于向該文件寫數(shù)據(jù)(即輸出文件),而不能用來向計算機輸入。如果原來不存在該文件,則在打開文件前新建立一個以指定的名字命名的文件。如果原來已存在一個以該文件名命名的文件,則在打開文件前先將該文件刪去,然后重新建立一個新文件。說明:(3)如果希望向文本文件末尾添加新的數(shù)據(jù)(不希望刪除原有數(shù)據(jù)),則應(yīng)該用“a”方式打開但此時應(yīng)保證該文件已存在;否則將得到出錯信息。打開文件時,文件讀寫標記移到文件末尾說明:(4)用r+、w+、a+方式打開的文本文件既可以用來輸入數(shù)據(jù),也可以用來輸出數(shù)據(jù)。用r+方式時該文件應(yīng)該已經(jīng)存在。用w+方式則新建立一個文件,先向此文件寫數(shù)據(jù),然后可以讀此文件中的數(shù)據(jù)。用a+方式打開的文件,原來的文件不被刪去,文件讀寫位置標記移到文件末尾,可以添加,也可以讀。說明:(5)如果打開失敗,fopen函數(shù)將會帶回一個出錯信息。fopen函數(shù)將帶回一個空指針值NULL常用下面的方法打開一個文件:if((fp=fopen(“file1”,”r”))==NULL)
{printf(“cannotopenthisfile\n”);exit(0);
}終止正在執(zhí)行的程序說明:(6)C標準建議用表10.1列出的文件使用方式打開文本文件或二進制文件,但目前使用的有些C編譯系統(tǒng)可能不完全提供所有這些功能說明:(7)計算機從ASCII文件讀入字符時,遇到回車換行符,系統(tǒng)把它轉(zhuǎn)換為一個換行符;
在輸出時把換行符轉(zhuǎn)換成為回車和換行兩個字符。
在用二進制文件時,不進行這種轉(zhuǎn)換,在內(nèi)存中的數(shù)據(jù)形式與輸出到外部文件中的數(shù)據(jù)形式完全一致,一一對應(yīng)。說明:(8)程序中可以使用3個標準的流文件:標準輸入流、標準輸出流、標準出錯輸出流。系統(tǒng)已對這3個文件指定了與終端的對應(yīng)關(guān)系標準輸入流是從終端的輸入標準輸出流是向終端的輸出標準出錯輸出流是當(dāng)程序出錯時將出錯信息發(fā)送到終端程序開始運行時系統(tǒng)自動打開這3個標準流文件。因此,程序編寫者不需要在程序中用fopen函數(shù)打開它們。所以以前我們用到的從終端輸入或輸出到終端都不需要打開終端文件。10.2.2用fclose函數(shù)關(guān)閉數(shù)據(jù)文件關(guān)閉文件用fclose函數(shù)。fclose函數(shù)調(diào)用的一般形式為:fclose(文件指針);
例如:
fclose(fp);使文件指針變量不指向該文件,也就是文件指針變量與文件“脫鉤”,此后不能再通過該指針對原來與其相聯(lián)系的文件進行讀寫操作。返回值:關(guān)閉成功返回值為0;否則返回EOF(-1)如果不關(guān)閉文件將會丟失數(shù)據(jù)。10.3順序讀寫數(shù)據(jù)文件在順序?qū)憰r,先寫入的數(shù)據(jù)存放在文件前面,后寫入的數(shù)據(jù)存放在文件后面在順序讀時,先讀文件中前面的數(shù)據(jù),后讀文件中后面的數(shù)據(jù)對順序讀寫來說,對文件讀寫數(shù)據(jù)的順序和數(shù)據(jù)在文件中的物理順序是一致的
順序讀寫需要用庫函數(shù)實現(xiàn)10.3.1怎樣向文件讀寫字符10.3.2怎樣向文件讀寫一個字符串10.3.3用格式化的方式讀寫文件10.3.4用二進制方式向文件讀寫一組數(shù)據(jù)10.3.1怎樣向文件讀寫字符函數(shù)名調(diào)用形式功能返回值fgetcfgetc(fp)從fp指向的文件讀入一個字符讀成功,帶回所讀的字符,失敗則返回文件結(jié)束標志EOF(即-1)fputcfputc(ch,fp)把字符ch寫到文件指針變量fp所指向的文件中寫成功,返回值就是輸出的字符;輸出失敗,則返回EOF(即-1)讀寫一個字符的函數(shù)常見的讀取字符操作從一個文本文件順序讀入字符并在屏幕上顯示出來:
ch=fgetc(fp);while(ch!=EOF)
{
putchar(ch);ch=fgetc(fp);
}注意:EOF不是可輸出字符,因此不能在屏幕上顯示。由于字符的ASCII碼不可能出現(xiàn)-1,因此EOF定義為-1是合適的。當(dāng)讀入的字符值等于-1時,表示讀入的已不是正常的字符而是文件結(jié)束符。從一個二進制文件順序讀入字符while(!feof(fp)){ch=fgetc(fp);}注意:ANSIC提供一個feof()函數(shù)來判斷文件是否真的結(jié)束。如果是文件結(jié)束,函數(shù)feof(fp)的值為1(真);否則為0(假)。以上也適用于文本文件的讀取
例10.1從鍵盤輸入一些字符,逐個把它們送到磁盤上去,直到用戶輸入一個“#”為止。
解題思路:從鍵盤逐個輸入字符,然后用fputc函數(shù)寫到磁盤文件即可。#include<stdio.h>#include<stdlib.h>intmain(){FILE*fp;charch,filename[10];printf("請輸入所用的文件名:");scanf("%s",filename);if((fp=fopen(filename,“w”))==NULL) {printf("無法打開此文件\n");exit(0);}ch=getchar();接收最后輸入的回車符輸入文件名只寫用exit函數(shù)時加結(jié)束printf(“請輸入一個字符串(以#結(jié)束):");ch=getchar();while(ch!=‘#’) {fputc(ch,fp);putchar(ch); ch=getchar(); }
fclose(fp);putchar(10);return0;}
例10.2將一個磁盤文件中的信息復(fù)制到另一個磁盤文件中。今要求將上例建立的file1.dat文件中的內(nèi)容復(fù)制到另一個磁盤文件file2.dat中。解題思路:處理此問題的算法是:從file1.dat文件中逐個讀入字符,然后逐個輸出到file2.dat中。#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("無法打開此文件\n");exit(0);}if((out=fopen(outfile,“w”))==NULL){printf("無法打開此文件\n");exit(0);}改為rb和wb,則復(fù)制一個二進制文件改為rb和wb,則復(fù)制一個二進制文件while(!feof(in)){ch=fgetc(in);
fputc(ch,out);putchar(ch);}putchar(10);fclose(in);fclose(out);return0;}檢查當(dāng)前讀寫位置是否移到文件末尾10.3.2怎樣向文件讀寫一個字符串讀寫一個字符串的函數(shù)函數(shù)名調(diào)用形式功能返回值fgetsfgets(str,n,fp)從fp指向的文件讀入長度為(n-1)的字符串,存放到字符數(shù)組str中讀成功,返回地址str,失敗則返回NULL)fputsfputs(str,fp)str所指向的字符串寫到文件指針變量fp所指向的文件中寫成功,返回0;否則返回非0值說明:fgets函數(shù)的函數(shù)原型為:char*fgets(char*str,intn,FILE*fp);其作用是從文件讀入一個字符串調(diào)用時可以寫成:fgets(str,n,fp);說明:fgets(str,n,fp);中n是要求得到的字符個數(shù),但實際上只讀n-1個字符,然后在最后加一個’\0’字符,這樣得到的字符串共有n個字符,把它們放到字符數(shù)組str中如果在讀完n-1個字符之前遇到換行符“\n”或文件結(jié)束符EOF,讀入即結(jié)束,但將所遇到的換行符“\n”也作為一個字符讀入執(zhí)行fgets成功,返回str數(shù)組首地址,如果一開始就遇到文件尾或讀數(shù)據(jù)錯,返回NULL說明:fputs函數(shù)的函數(shù)原型為:intfputs(char*str,FILE*fp);str指向的字符串輸出到fp所指向的文件中調(diào)用時可以寫成:fputs(“China”,fp);fputs函數(shù)中第一個參數(shù)可以是字符串常量、字符數(shù)組名或字符型指針字符串末尾的′\0′不輸出輸出成功,函數(shù)值為0;失敗,函數(shù)值為EOF
例10.3從鍵盤讀入若干個字符串,對它們按字母大小的順序排序,然后把排好序的字符串送到磁盤文件中保存。解題思路:為解決問題,可分為三個步驟:從鍵盤讀入n個字符串,存放在一個二維字符數(shù)組中,每一個一維數(shù)組存放一個字符串;對字符數(shù)組中的n個字符串按字母順序排序,排好序的字符串仍存放在字符數(shù)組中;將字符數(shù)組中的字符串順序輸出。#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]);for(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);}}if((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]);}return0;}人為地輸出一個’\n’思考:從文件string.dat中讀回字符串,并在屏幕上顯示,應(yīng)如何編寫程序?#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’10.3.3用格式化的方式讀寫文件一般調(diào)用方式為:fprintf(文件指針,格式字符串,輸出表列);fscanf(文件指針,格式字符串,輸入表列);如:fprintf(fp,”%d,%6.2f”,i,f);fscanf(fp,”%d,%f”,&i,&f);注意:用fprintf和fscanf函數(shù)對磁盤文件讀寫,使用方便,容易理解,但由于在輸入時要將ASCII碼轉(zhuǎn)換為二進制形式,在輸出時又要將二進制形式轉(zhuǎn)換成字符,花費時間比較多。因此,在內(nèi)存與磁盤頻繁交換數(shù)據(jù)的情況下,最好不用fprintf和fscanf函數(shù),而用fread和fwrite函數(shù)。10.3.4用二進制方式向文件讀寫一組數(shù)據(jù)一般調(diào)用形式為:fread(buffer,size,count,fp);fwrite(buffer,size,count,fp);fread(buffer,size,count,fp);fwrite(buffer,size,count,fp);buffer:是一個地址(指針)對fread來說,它是用來存放從文件讀入的數(shù)據(jù)的存儲區(qū)的地址對fwrite來說,是要把此地址開始的存儲區(qū)中的數(shù)據(jù)向文件輸出size:要讀寫的字節(jié)數(shù)count:要讀寫多少個數(shù)據(jù)項fp:FILE類型指針
例10.4從鍵盤輸入10個學(xué)生的有關(guān)數(shù)據(jù),然后把它們轉(zhuǎn)存到磁盤文件上去。
解題思路:定義有10個元素的結(jié)構(gòu)體數(shù)組,用來存放10個學(xué)生的數(shù)據(jù)從main函數(shù)輸入10個學(xué)生的數(shù)據(jù)用save函數(shù)實現(xiàn)向磁盤輸出學(xué)生數(shù)據(jù)用fwrite函數(shù)一次輸出一個學(xué)生的數(shù)據(jù)#include<stdio.h>#defineSIZE10structStudent_type{charname[10];intnum;intage;charaddr[15];}stud[SIZE];voidsave(){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,實際上開辟36字節(jié),是4的倍數(shù)當(dāng)前路徑下的文件intmain(){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;}為了驗證在磁盤文件“stu.dat”中是否已存在此數(shù)據(jù),可以用以下程序從“stu.dat”文件中讀入數(shù)據(jù),然后在屏幕上輸出。#include<stdio.h>#include<stdlib.h>#defineSIZE10structStudent_type{charname[10];intnum;intage;charaddr[15];}stud[SIZE];intmain(){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;}
如果修改例10.4:從已有的二進制文件“stu.list”中,讀入數(shù)據(jù)并輸出到“stu.dat”文件中,應(yīng)如何修改程序?
解題思路:編寫load函數(shù),從磁盤文件中讀二進制數(shù)據(jù)main函數(shù)中再調(diào)用load函數(shù)voidload(){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);}intmain(){load();
save();return0;}10.4隨機讀寫數(shù)據(jù)文件對文件進行順序讀寫比較容易理解,也容易操作,但有時效率不高隨機訪問不是按數(shù)據(jù)在文件中的物理位置次序進行讀寫,而是可以對任何位置上的數(shù)據(jù)進行訪問,顯然這種方法比順序訪問效率高得多順序讀寫和隨機讀寫順序讀寫:位置指針按字節(jié)位置順序移動。隨機讀寫:讀寫完上一個字符(字節(jié))后,并不一定要讀寫其后續(xù)的字符(字節(jié)),而可以讀些文件中任意位置上所需要的字符(字節(jié))。10.4.1文件位置標記及其定位10.4.2隨機讀寫10.4.1文件位置標記及其定位1.文件位置標記為了對讀寫進行控制,系統(tǒng)為每個文件設(shè)置了一個文件讀寫位置標記(簡稱文件標記),用來指示“接下來要讀寫的下一個字符的位置”文件指針讀寫當(dāng)前位置文件尾1.文件位置標記文件頭1.文件位置標記一般情況下,在對字符文件進行順序讀寫時,文件標記指向文件開頭,進行讀的操作時,就讀第一個字符,然后文件標記向后移一個位置,在下一次讀操作時,就將位置標記指向的第二個字符讀入。依此類推,直到遇文件尾,結(jié)束1.文件位置標記如果是順序?qū)懳募瑒t每寫完一個數(shù)據(jù)后,文件標記順序向后移一個位置,然后在下一次執(zhí)行寫操作時把數(shù)據(jù)寫入指針所指的位置。直到把全部數(shù)據(jù)寫完,此時文件位置標記在最后一個數(shù)據(jù)之后可以根據(jù)讀寫的需要,人為地移動了文件標記的位置。文件標記可以向前移、向后移,移到文件頭或文件尾,然后對該位置進行讀寫——隨機讀寫隨機讀寫可以在任何位置寫入數(shù)據(jù),在任何位置讀取數(shù)據(jù)2.文件位置標記的定位可以強制使文件位置標記指向指定的位置可以用以下函數(shù)實現(xiàn):(1)用rewind函數(shù)使文件標記指向文件開頭rewind函數(shù)的作用是使文件標記重新返回文件的開頭,此函數(shù)沒有返回值。
例10.5有一個磁盤文件,內(nèi)有一些信息。要求第一次將它的內(nèi)容顯示在屏幕上,第二次把它復(fù)制到另一文件上。解題思路:因為在第一次讀入完文件內(nèi)容后,文件標記已指到文件的末尾,如果再接著讀數(shù)據(jù),就遇到文件結(jié)束標志,feof函數(shù)的值等于1(真),無法再讀數(shù)據(jù)必須在程序中用rewind函數(shù)使位置指針返回文件的開頭#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;}(2)用fseek函數(shù)改變文件標記fseek函數(shù)的調(diào)用形式為:fseek(文件類型指針,位移量,起始點)
起始點0代表“文件開始位置”,1為“當(dāng)前位置”,2為“文件末尾位置”C標準指定的名字起始點名
字用數(shù)字代表文件開始位置SEEK_SET0文件當(dāng)前位置SEEK_CUR1文件末尾位置SEEK_END2位移量指以起始點為基點,向前移動的字節(jié)數(shù)。位移量應(yīng)是long型數(shù)據(jù)(在數(shù)字的末尾加一個字母L)。fseek函數(shù)一般用于二進制文件。下面是fseek函數(shù)調(diào)用的幾個例子:
fseek(fp,100L,0);//將位置指針移到離文件頭100個字節(jié)處fseek(fp,50L,1);//將位置指針移到離當(dāng)前位置50個字節(jié)處fseek(fp,-10L,2);將位置指針從文件末尾處向后退10個字節(jié)(3)用ftell函數(shù)測定文件位置標記的當(dāng)前位置ftell函數(shù)的作用是得到流式文件中文件位置標記的當(dāng)前位置。由于文件中的文件位置標記經(jīng)常移動,人們往往不容易知道其當(dāng)前位置,所以常用ftell函數(shù)得到當(dāng)前位置,用相對于文件開頭的位移量來表示。如果調(diào)用函數(shù)時出錯(如不存在fp指向的文件),ftell函數(shù)返回值為-1L。例如:i=ftell(fp);if(i==-1L)printf(“error\n”);10.4.2隨機讀寫
例10.6在磁盤文件上存有10個學(xué)生的數(shù)據(jù)。要求將第1,3,5,7,9個學(xué)生數(shù)據(jù)輸入計算機,并在屏幕上顯示出來。要求:從例10.4中建立的“stu.dat”中讀入數(shù)據(jù)解題思路:按二進制只讀方式打開文件將文件位置標記指向文件的開頭,讀入一個學(xué)生的信息,并把它顯示在屏幕上再將文件標記指向文件中第3,5,7,9個學(xué)生的數(shù)據(jù)區(qū)的開頭,讀入相應(yīng)學(xué)生的信息,并把它顯示在屏幕上關(guān)閉文件#include<stdio.h>#include<stdlib.h>structSt{charname[10];intnum;intage;charaddr[15];}stud[10];intmain(){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(&stu
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 珠海新型泳池工程施工方案
- 達州五年級抽考數(shù)學(xué)試卷
- 2025年度股權(quán)投資基金投資合同模板-專業(yè)投資與風(fēng)險共擔(dān)協(xié)議
- 2025年度城市綠化工程抗滑樁施工合同范本
- 五年級蘇教版數(shù)學(xué)上冊《小數(shù)的意義》聽評課記錄
- 2025年度花椒病蟲害防治與生態(tài)保護服務(wù)合同
- 現(xiàn)代商業(yè)環(huán)境下心理健康的中醫(yī)維護策略
- 電商平臺節(jié)日促銷活動的用戶體驗優(yōu)化
- 人教版數(shù)學(xué)七年級下冊聽評課記錄5.1.3《 同位角、內(nèi)錯角、同旁內(nèi)角》
- 2025年度紅磚批發(fā)合作協(xié)議書二零二五年度建筑材料供應(yīng)合同
- 小學(xué)六年級數(shù)學(xué)上冊《簡便計算》練習(xí)題(310題-附答案)
- 青海省西寧市海湖中學(xué)2025屆中考生物仿真試卷含解析
- 2024年河南省《輔警招聘考試必刷500題》考試題庫及答案【全優(yōu)】
- -情景交際-中考英語復(fù)習(xí)考點
- 安全隱患報告和舉報獎勵制度
- 地理標志培訓(xùn)課件
- 2023行政主管年終工作報告五篇
- 2024年中國養(yǎng)老產(chǎn)業(yè)商學(xué)研究報告-銀發(fā)經(jīng)濟專題
- GA/T 1003-2024銀行自助服務(wù)亭技術(shù)規(guī)范
- 公園衛(wèi)生保潔考核表
- 培訓(xùn)如何上好一堂課
評論
0/150
提交評論