理學(xué)模塊位運算與文件_第1頁
理學(xué)模塊位運算與文件_第2頁
理學(xué)模塊位運算與文件_第3頁
理學(xué)模塊位運算與文件_第4頁
理學(xué)模塊位運算與文件_第5頁
已閱讀5頁,還剩99頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

模塊7位運算與文件

任務(wù)1位運算學(xué)習(xí)目標(biāo)掌握六種位運算的運算符與格式、運算規(guī)則。

7.1.1案例講解

案例1二進制的循環(huán)移位1.問題描述實現(xiàn)二進制的循環(huán)移位。設(shè)待移位的數(shù)為a,移位情況如圖7-1,設(shè)系統(tǒng)中2個字節(jié)存放一個整數(shù)。2.編程分析n位圖7-1二進制的循環(huán)移位圖解該問題的要求在于將待移位數(shù)a分成兩部分,然后交換這兩部分的位置。從而可知,需要增加兩個變量存儲變量a的兩部分的值,而這些操作都需要求助于位運算。程序描述如下:main(){定義無符號整型變量a,b,c定義整型變量n輸入待移位數(shù)a和所移動位數(shù)n對數(shù)a左移16-n位后的結(jié)果給變量b對數(shù)a右移n位后的結(jié)果給變量c對變量b,c做按位或運算,計算結(jié)果給變量c輸出變量a和c}n位n位圖7-1二進制的循環(huán)移位圖解3.編寫源程序/*EX7_1.C*/#include<stdio.h>main(){unsignedshortunsignedA,unsignedB,unsignedC;intintN;printf("請輸入一個無符號整型變量unsignedA的值:");scanf("%u",&unsignedA);printf("請輸入移位位數(shù)intN的值:");

scanf("%d",&intN);unsignedB=unsignedA<<(16–intN);unsignedC=unsignedA>>intN;unsignedC=unsignedC|unsignedB;printf("unsignedA的值:%o\n",unsignedA);printf("unsignedC的值:%o\n",unsignedC);}4.運行結(jié)果圖7-2案例1運行結(jié)果5.歸納分析在本案例中,使用了左移位運算、右移位運算和按位或運算相配合,實現(xiàn)二進制的循環(huán)移位。該程序運行的一個實例,輸入unsignedA的值為174,移動位數(shù)intN的值為2,則運行結(jié)果如圖。其中:十進制數(shù)174(即為八進制數(shù)256)的二進制數(shù)為0000000010101110(按題設(shè)要求為2個字節(jié)),循環(huán)移動2位,則循環(huán)移位后的二進制結(jié)果為1000000000101011(即為八進制數(shù)100053)。

7.1.2基礎(chǔ)理論

C語言中提供給開發(fā)人員一種位的運算,這種位的運算常用在檢測和控制領(lǐng)域中,這和C語言的特性關(guān)系非常大,因為C語言是具有高級語言的特點和低級語言的功能,能完成一些匯編語言所能完成的功能。給開發(fā)人員提供了一定的簡便。C語言提供了六種位運算,下面分別介紹。1.按位與運算(&)

(1)格式:x&y(2)規(guī)則:按位與運算符“&”是雙目運算符。其功能是參加運算的兩數(shù)各對應(yīng)的二進位相與。只有對應(yīng)的兩個二進位均為1時,結(jié)果位才為1,否則為0。參加運算的數(shù)以補碼方式出現(xiàn)。例如:9&5可寫算式如下

00001001

&0000010100000001結(jié)果為:9&5=1。(3)主要用途:用來對某些位清0或保留某些位。例如:把a的高八位清0,保留低八位,可作a&255運算(255的二進制數(shù)為0000000011111111)。2.按位或運算符(|)(1)格式:x|y(2)規(guī)則:按位或運算符“|”是雙目運算符。其功能是參加運算的兩數(shù)各對應(yīng)的二進位相或。只要對應(yīng)的二個二進位有一個為1時,結(jié)果位就為1。參加運算的兩個數(shù)均以補碼出現(xiàn)。例如:9|5可寫算式如下

00001001

|0000010100001101結(jié)果為:9|5=13

(3)主要用途:常用來將源操作數(shù)某些位置1,其他位不變。例如:把a的低八位置1,保留高八位,可作a|255運算(255的二進制數(shù)為0000000011111111)。3.按位異或運算(^)

(1)格式:x^y(2)規(guī)則:按位異或運算符“^”是雙目運算符。其功能是參加運算的兩數(shù)各對應(yīng)的二進位相異或,當(dāng)兩對應(yīng)的二進位相異時,結(jié)果為1。參加運算數(shù)仍以補碼出現(xiàn)。例如:9^5可寫成算式如下

00001001

^0000010100001100

結(jié)果為:9^5=12

(3)主要用途:常用來將源操作數(shù)某些特定位的值取反,其他位不變。

例如:把a的低八位取反,保留高八位,可作a^255運算(255的二進制數(shù)為0000000011111111)。4.求反運算(~)

(1)格式:~x(2)規(guī)則:求反運算符~為單目運算符,具備右結(jié)合性。其功能是對參加運算的數(shù)的各二進位按位求反。例如:~9可寫成算式如下

~00000000000010011111111111110110結(jié)果為:~9=-105.左移運算(<<)(1)格式:x<<位數(shù)(2)規(guī)則:左移運算符“<<”是雙目運算符。其功能是把“<<”左邊的運算數(shù)的各二進位全部左移若干位,“<<”右邊的數(shù)指定移動的位數(shù)。低位補0,高位溢出。例如:設(shè)a=15,a<<2表示把000001111左移為00111100(十進制60)。6.位右移(>>)(1)格式:x>>位數(shù)(2)規(guī)則:使操作數(shù)的各位右移,高位補0,低位溢出。例如:5>>2=100000101右移兩位

00000001

任務(wù)2文件

學(xué)習(xí)目標(biāo)掌握標(biāo)準(zhǔn)設(shè)備輸入、輸出函數(shù)的使用;掌握緩沖文件系統(tǒng)的使用。

7.2.1案例講解

案例1

讀取指定文件內(nèi)容1.問題描述:已知一文本文件“c:\text.txt”的內(nèi)容如下:

#include<stdio.h>voidmain(){printf("helloworld");}編寫程序讀取指定該文本文件的內(nèi)容,并在屏幕上輸出。2.編程分析:程序描述如下:

main(){定義文件指針*fp,定義字符變量ch打開指定的文本文件判斷指定的文本文件是否能打開,假如不能打開,顯示提示信息,并結(jié)束程序使用循環(huán)讀取該文本文件的每個字符,并依次在屏幕上輸出關(guān)閉指定的文本文件

}3.編寫源程序

/*EX7_8.C*/#include<stdio.h>#include<conio.h>/*控制臺輸入輸出*/#include<stdlib.h>/*最常用的系統(tǒng)函數(shù)*/voidmain(){FILE*fileP;charcharC;if((fileP=fopen("c:\\text.txt","r"))==NULL){

printf("不能打開文件,按任意鍵退出!");getch();exit(1);}while((charC=fgetc(fileP))!=EOF)putchar(charC);fclose(fileP);}4.運行結(jié)果圖7-9案例1運行結(jié)果5.歸納分析本例程序的功能是從文件中逐個讀取字符,在屏幕上顯示。程序定義了文件指針fileP,以讀文本文件方式打開文件“text.txt”,并使fileP指向該文件。如打開文件出錯,給出提示并退出程序。While循環(huán)中每次讀出一個字符,只要讀出的字符不是文件結(jié)束標(biāo)志(每個文件末有一結(jié)束標(biāo)志EOF)就把該字符顯示在屏幕上,然后再讀入下一字符。每讀一次,文件內(nèi)部的位置指針向后移動一個字符,文件結(jié)束時,該指針指向EOF。

7.2.2基礎(chǔ)理論

1.文件的概念文件是指存儲在外部介質(zhì)上的數(shù)據(jù)集合體,是操作系統(tǒng)數(shù)據(jù)管理的單位。使用數(shù)據(jù)文件的目的:

(1)數(shù)據(jù)文件的改動不引起程序的改動——程序與數(shù)據(jù)分離;(2)不同程序可以訪問同一數(shù)據(jù)文件中的數(shù)據(jù)——數(shù)據(jù)共享;(3)能長期保存程序運行的中間數(shù)據(jù)或結(jié)果數(shù)據(jù)。2.文件的分類

根據(jù)文件存儲的內(nèi)容的不同,文件可以分為程序文件和數(shù)據(jù)文件兩種。程序文件是程序代碼的集合體,而數(shù)據(jù)文件是指專門用來保存數(shù)據(jù)的文件。根據(jù)文件存儲介質(zhì)的不同,文件又可以分為磁盤文件和設(shè)備文件兩種。磁盤文件是指保存在磁盤或其他外部存儲介質(zhì)上的一個有序數(shù)據(jù)集,可以是C語言的源文件、目標(biāo)文件、可執(zhí)行程序,也可以是一組待輸入處理的原始數(shù)據(jù),或者是一組輸出的結(jié)果。對于源文件、目標(biāo)文件、可執(zhí)行

程序可以稱為程序文件,對于輸入輸出數(shù)據(jù)可稱為數(shù)據(jù)文件。設(shè)備文件是指與主機相聯(lián)的各種外部設(shè)備,如顯示器、打印機、磁盤等。C語言把外部設(shè)備也看作是一個文件來進行管理,把他們的輸入、輸出等同于對磁盤文件的讀和寫。通常把顯示器定義為標(biāo)準(zhǔn)輸出文件,鍵盤指定為標(biāo)準(zhǔn)的輸入文件。

根據(jù)文件的組織形式不同,文件又可以分為ASCII碼文件(也稱為文本文件)和二進制碼文件兩種。ASCII碼文件,每個字節(jié)存放一個字符的ASCII碼。二進制碼文件,數(shù)據(jù)按其在內(nèi)存中的

存儲形式原樣存放。例如:int型數(shù)10000,在內(nèi)存中存儲占用兩個字節(jié),其中1的ASCII為00110001,0的ASCII為00110000,10000的二進制表示為10011100010000。如果分別存儲到文本文件和二進制碼文件中,其形式如下:圖7-10數(shù)據(jù)存儲示意圖

從圖中可以看出來,ASCII碼文件輸入與字符一一對應(yīng),便于對字符進行逐個處理,也便于字符的輸出,但一般占存儲空間較多,而且花費二進制代碼和ASCII代碼之間的轉(zhuǎn)換時間。用二進制文件則可以節(jié)省外部存儲空間和轉(zhuǎn)換的時間,但處理過程比較復(fù)雜。因此,文本文件特點:存儲量大、速度慢、便于對字符操作;二進制碼文件特點:存儲量小、速度快、便于存放中間結(jié)果。3.文件的處理在C語言中,對文件的輸入輸出都是通過文件系統(tǒng)完成的,并不區(qū)分類型,都看成是字符或者是二進制流,按字節(jié)進行處理。輸入輸出數(shù)據(jù)流的開始和結(jié)束只由程序控制而不受物理符號(如回車換行符)的控制。因此我們也把這種文件稱作“流式文件”。文件系統(tǒng)又分為緩沖文件系統(tǒng)和非緩沖文件系統(tǒng)。所謂緩沖文件系統(tǒng)是高級文件系統(tǒng),系統(tǒng)自動地在內(nèi)存區(qū)為每一個正在使用的文件名開辟一個緩沖區(qū),數(shù)據(jù)的輸入輸出都是以這個緩沖區(qū)為中介。所謂非緩沖文件系統(tǒng)是低級文件系統(tǒng),指系統(tǒng)不自動開辟確定大小的緩沖區(qū),而由程序為每個文件設(shè)定緩沖區(qū)。圖7-11和圖7-12分別是緩沖文件系統(tǒng)和非緩沖文件系統(tǒng)。

標(biāo)準(zhǔn)C只采用緩沖文件系統(tǒng),也就是既用緩沖文件系統(tǒng)處理文本文件,也用它來處理二進制文件。在C語言中沒有輸入輸出語句,對文件的讀寫操作都是用標(biāo)準(zhǔn)的輸入輸出庫函數(shù)來實現(xiàn)的。4.緩沖文件系統(tǒng)

(1)FILE類型和文件指針在緩沖文件系統(tǒng)中,使用最多的概念就是“文件指針”。緩沖文件系統(tǒng)為每個使用的文件在內(nèi)存中開辟一個緩沖區(qū),用來存放文件的相關(guān)信息,這些信息被保存在FILE類型的變量中。在stdio.h文件中有FILE類型的定義:typedefstruct{shortlevel;/*緩沖區(qū)空或滿的程度*/unsignedflags;/*文件狀態(tài)標(biāo)志*/charfd;/*文件描述符*/unsignedcharhold;/*如無緩沖區(qū)則不讀取字符*/shortbsize;/*緩沖區(qū)的大小*/unsignedchar*buffer;/*數(shù)據(jù)緩沖區(qū)的位置*/unsignedar*curp;/*指針,當(dāng)前的指向*/unsignedistemp;/*臨時文件*/shorttoken;/*用于有效性檢查*/}FILE;對于普通用戶而言,不必了解FILE類型的結(jié)構(gòu)內(nèi)容,只要知道,每個文件都對應(yīng)一個唯一的文件型指針變量,通過文件指針我們可以對它所指的文件進行各種操作。定義文件型指針變量的一般形式為:FILE*指針變量名;例如:FILE*fileP;fileP是指向FILE類型結(jié)構(gòu)體的指針變量,通過fileP即可找存放某個文件信息的結(jié)構(gòu)變量,然后按結(jié)構(gòu)變量提供的信息可以訪問該文件,實施對文件的操作。習(xí)慣上也籠統(tǒng)地把fileP稱為指向一個文件的指針。5.文件的操作對文件的基本操作有兩種,一種是輸入操作,一種是輸出操作。在訪問文件之前,要先打開文件,然后才能訪問該文件,對文件操作結(jié)束后,還要關(guān)閉該文件。因此對文件的操作,必須遵守“先打開,再讀寫,后關(guān)閉”的規(guī)則,也就是說在進行讀寫操作之前要先打開文件,使用完畢后要關(guān)閉。

(1)文件的打開函數(shù)fopen

fopen函數(shù)用來實現(xiàn)打開一個文件,其調(diào)用的一般形式為:

FILE*fileP;

fileP=fopen(文件名,使用文件方式);

其中,“文件名”是被打開文件的文件名,包括文件的存儲路徑,“使用文件方式”是指文件的類型和操作要求。

例如:fileP=fopen(“file1”,“r”);它表示在當(dāng)前目錄下打開文件file1,使用文件方式為“讀”操作,并使fileP指向該文件。使用文件的方式共有12種,如表7-1所示.表7-1文件使用方式表文件使用方式含義“r”(只讀)打開一個文本文件,只允許讀數(shù)據(jù)“w”(只寫)

打開或建立一個文本文件,只允許寫數(shù)據(jù)“a”(追加)打開一個文本文件,并在文件末尾增加數(shù)據(jù)“rb”(只讀)打開一個二進制文件,只允許讀數(shù)據(jù)“wb”(只寫)打開或建立一個二進制文件,只允許寫數(shù)據(jù)“ab”(追加)打開一個二進制文件,并在文件末尾寫數(shù)據(jù)“r+”(讀寫)打開一個文本文件,允許讀和寫“w+”(讀寫)

建立一個文本文件,允許讀寫“a+”(讀寫)打開一個文本文件,允許讀,或在文件末追加數(shù)據(jù)“rb+”(讀寫)

打開一個二進制文件,允許讀和寫“wb+”(讀寫)

建立一個二進制文件,允許讀和寫“ab+”(讀寫)打開一個二進制文件,允許讀,或在文件末追加數(shù)據(jù)說明:

●用“r”方式打開的文件,該文件必須已經(jīng)存在,且只能從該文件讀出數(shù)據(jù)。

●用“w”方式打開的文件只能向該文件寫入數(shù)據(jù)。若打開的文件不存在,則以指定的文件名建立該文件,若打開的文件已經(jīng)存在,則將該文件刪去,重建一個新文件。

●如果想向一個已存在的文件末尾添加新的信息(不刪除原來的數(shù)據(jù)),則應(yīng)該用“a”方式打開。但此時該文件必須是存在的,否則將會出錯。

●用“r+”、“w+”、“a+”方式打開的文件

既可以用來寫入數(shù)據(jù),也可以用來讀出文件中的數(shù)據(jù)。如果不能打開一個文件時,fopen將返回一個空指針值NULL。在程序中可以用這一信息來判別是否完成打開文件的工作,并作相應(yīng)的處理。因此常用以下程序段打開文件:

if((fileP=fopen("file1","r")==NULL){printf("\n不能打開文件file1\n");exit(0);}(2)文件關(guān)閉函數(shù)fclose文件一旦使用完畢,應(yīng)該用關(guān)閉文件函數(shù)把文件關(guān)閉,以避免文件的數(shù)據(jù)丟失等錯誤。所謂關(guān)閉文件就是使文件指針變量不再指向該文件。調(diào)用的一般形式是:fclose(文件指針);例如:fclose(fileP);

順利完成關(guān)閉文件操作時,fclose函數(shù)返回值為0,否則返回EOF(-1)。6.文件的讀寫和建立文件打開以后,就可以對它進行讀寫操作了。在C語言中提供了多種文件讀寫的函數(shù):字符讀寫函數(shù):fgetc和fputc字符串讀寫函數(shù):fgets和fputs數(shù)據(jù)塊讀寫函數(shù):fread和fwrite格式化讀寫函數(shù):fscanf和fprinf使用以上函數(shù)都要求包含頭文件stdio.h。(1)讀字符函數(shù)fgetc

fgetc函數(shù)的功能是從指定的文件中讀一個字符,讀取的文件必須是以讀或讀寫方式打開的。調(diào)用的形式為:ch=fgetc(fileP);fileP為文件型指針變量,ch為字符變量。其意義是從打開的文件fileP中讀取一個字符并送入ch中。讀字符時遇到文件結(jié)束符,函數(shù)返回一個文件結(jié)束標(biāo)志EOF(-1)。EOF是在stdio.h文件中定義的符號常量,值為-1。(2)寫字符函數(shù)fputc

fputc函數(shù)的功能是把一個字符寫入指定的文件中。調(diào)用的形式為:fputc(ch,fileP);ch是要輸出的字符,它可以是字符常量或者是字符變量。fileP為文件型指針變量。其意義是把字符ch寫入到fileP所指向的文件中。如果寫入成功則返回寫入的字符,如果寫入失敗則返回一個EOF(-1)。(3)讀字符串函數(shù)fgets

fgets函數(shù)的功能是從指定的文件中讀一個字符串到字符數(shù)組中。函數(shù)調(diào)用的形式為:fgets(str,n,fileP);n是一個正整數(shù),為要求得到的字符數(shù),但從文件中讀出的字符串只有n-1個字符,然后在最后一個字符后加上串結(jié)束標(biāo)志'\0',因此得到的字符串共有n個字符。把得到的字符串放在字符數(shù)組str里面。fileP為文件型指針變量。如果在讀完n-1個字符之前遇到換行符或EOF,讀操作即結(jié)束。函數(shù)返回值為str的首地址。(4)寫字符串函數(shù)fputs

fputs函數(shù)的功能是向指定的文件寫入一個字符串。函數(shù)的調(diào)用形式為:fputs(s,fileP)s可以是字符串常量,也可以是字符數(shù)組名,或字符型指針變量。fileP為文件型指針變量。字符串末尾的’\0’不輸出,若輸出成功,函數(shù)值返回為0,失敗則為EOF。7.?dāng)?shù)據(jù)塊讀寫函數(shù)fread和fwrite

有時候需要讀寫一組數(shù)據(jù),如一個數(shù)組的元素,一個結(jié)構(gòu)變量的值等。這時候可以使用讀寫數(shù)據(jù)塊函數(shù),用來讀寫一個數(shù)據(jù)塊。函數(shù)調(diào)用的一般形式為:

fread(buffer,size,count,fileP);fwrite(buffer,size,count,fileP);

其中:buffer是一個指針,在fread函數(shù)中,它表示存放輸入數(shù)據(jù)的首地址,在fwrite函數(shù)中,它表示存放輸出數(shù)據(jù)的首地址。size表示要讀寫的字節(jié)數(shù)。count表示要讀寫的數(shù)據(jù)塊塊數(shù)(即count個size大的數(shù)據(jù)塊)。fileP表示文件指針。8.格式化讀寫函數(shù)fscanf和fprintffscanf函數(shù),fprintf函數(shù)與前面使用的scanf和printf函數(shù)的功能相似,都是格式化讀寫函數(shù)。不同之處在于fscanf函數(shù)和fprintf函數(shù)的讀寫對象不是鍵盤和顯示器,而是磁盤文件。函數(shù)的調(diào)用格式為:

fscanf(文件指針,格式字符串,輸入表列);

fprintf(文件指針,格式字符串,輸出表列);要注意的是,當(dāng)在內(nèi)存和磁盤頻繁交換數(shù)據(jù)的情況下,最好不使用這兩個函數(shù),而使用fread和fwrite函數(shù)。9.文件的定位和測試(1)文件的定位上一節(jié)介紹的對文件的讀寫方式都是順序讀寫,即讀寫文件只能從頭開始,順序讀寫各個數(shù)據(jù)。但在實際問題中常要求只讀寫文件中某一指定的部分,也就是移動文件指針到需要讀寫的位置,再進行讀寫,這種讀寫稱為隨機讀寫。實現(xiàn)隨機讀寫的關(guān)鍵是按要求移動文件指針,這稱為文件的定位。rewind函數(shù):調(diào)用形式為rewind(文件指針);

它的功能是把文件指針重新移到文件的開頭。此函數(shù)沒有返回值。fseek函數(shù):fseek函數(shù)用來移動文件指針,其調(diào)用形式為:

fseek(文件指針,位移量,起始點);其中:“文件指針”指向被移動的文件。“位移量”是指以“起始點”為基點,向前移動的字節(jié)數(shù)。要求位移量是long型數(shù)據(jù),以便在文件的長度大于64K時不會出問題。當(dāng)用常量表示

位移量時,直接在末尾加后綴“L”。“起始點”表示從文件的什么位置開始計算位移量,規(guī)定的起始點有三種:文件首,當(dāng)前位置和文件尾。其表示方法如表7-2所示。表7-2文件指針三種起始點起始點表示符號數(shù)字表示文件首SEEK__SET0當(dāng)前位置SEEK__CUR1文件末尾SEEK__END2

fseek函數(shù)一般用于二進制文件,這是因為文本文件要進行轉(zhuǎn)換,在計算位置的時候會出現(xiàn)錯誤。(2)文件檢測函數(shù)C語言中常用的文件檢測函數(shù)有以下幾個:●文件結(jié)束檢測函數(shù)feof()調(diào)用格式:feof(文件指針);功能:判斷文件是否處于文件結(jié)束位置,如文件結(jié)束,則返回值為1,否則為0?!褡x寫文件出錯檢測函數(shù)ferror()調(diào)用格式:ferror(文件指針);功能:檢查文件在用各種輸入輸出函數(shù)進行讀寫時是否出錯。如ferror返回值為0表示未出錯,否則表示有錯?!裎募鲥e標(biāo)志和文件結(jié)束標(biāo)志置0函數(shù)clearerr()調(diào)用格式:clearerr(文件指針);功能:用于清除出錯標(biāo)志和文件結(jié)束標(biāo)志,使它們?yōu)?值。

7.2.3技能訓(xùn)練

【實驗7.2.1】編寫程序,從鍵盤上輸入一系列字符,寫到磁盤文件file中,以#作為輸入的結(jié)束標(biāo)志,然后把文件中的內(nèi)容在屏幕上輸出。【指導(dǎo)】本實驗的功能是執(zhí)行了兩次磁盤文件操作:先用fputc函數(shù)把輸入的字符放在fileP指向的文件中,然后把文件中的內(nèi)容用fgetc函數(shù)逐個讀取,在屏幕上顯示。程序定義了文件指針fileP,先以寫方式打開文本文件file,并使fileP指向該文件。如打開文件出錯,給出提示并退出程序。輸入字符到文件中的循環(huán)是以輸入“#”作為循環(huán)結(jié)束的標(biāo)志;然后再以讀方式打開文本文件file,循環(huán)讀取文本文件的每一個字符,并顯示在屏幕上,并以EOF作為循環(huán)的結(jié)束標(biāo)志,也就是判斷是否讀到文件的結(jié)尾。每次文件操作結(jié)束后,都要用fclose函數(shù)關(guān)閉文件。

/*EX7_9.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>voidmain()()

{FILE*fileP;charcharC;if((fileP=fopen("file","w"))==NULL){printf("不能打開文件\n");exit(0);}printf(“請輸入字符:\n”);while((charC=getchar())!=’#’){

fputc(charC,fileP);}fclose(fileP);if((fileP=fopen("file","r"))==NULL){printf("不能打開文件\n");exit(0);}printf("文件內(nèi)容為:\n");charC=fgetc(fileP);

while(charC!=EOF){putchar(charC);charC=fgetc(fileP);}fclose(fileP);}該程序首先打開當(dāng)前目錄中文件名為file的文件,然后從鍵盤上輸入字符并存儲到文件file

中,輸入完成后關(guān)閉文件file,最后再次打開文件file,并輸出文件file中的字符。圖7-13為該程序的一次運行實例.圖7-13程序EX7_9運行結(jié)果【實驗7.2.2】有兩個磁盤文件a1.txt和a2.txt,各存放若干行字母,今要求把這兩個文件中的信息按行交叉合并(即先是a1.txt的的第一行,接著是a2.txt中的第一行,然后是a1.txt的第二行,跟著是a2.txt的第二行,…),輸出到一個新文件a3.txt中去?!局笇?dǎo)】以讀方式打開磁盤文件a1.txt和a2.txt,然后依次讀取a1.txt和a2.txt的一行,交叉存入新文件a3.txt,因此可以通過3個循環(huán)語句實現(xiàn)。具體做法為:通過fgets函數(shù)分別獲得文件a1.txt和a2.txt中的每一行字符,分別賦值給字符數(shù)組str1和str2,然后將字符數(shù)組str1和

str2中的內(nèi)容依次寫入文件a3.txt。假如其中某個文件讀取完成,則將另一文件剩余行寫人文件a3.txt后部。

/*EX7_10.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>voidmain()(){FILE*fp1,*fp2,*fp3;charstr1[255],str2[255];if((fp1=fopen("a1.txt","r"))==NULL)

{printf("filea1cannotbeopened\n");exit(0);}if((fp2=fopen("a2.txt","r"))==NULL){printf("filea2cannotbeopened\n");exit(0);}if((fp3=fopen("a3.txt","w+"))==NULL){printf("filea3cannotbeopened\n");exit(0);}while(fgets(str1,255,fp1)!=NULL&&fgets(str2,255,fp2)!=NULL){fputs(str1,fp3);fputs(str2,fp3);}while(fgets(str1,255,fp1)!=NULL)

{fputs(str1,fp3);}while(fgets(str2,255,fp2)!=NULL){fputs(str2,fp3);}/*charcharC;//以下注釋掉的代碼,為查看文件a1、a2、a3的內(nèi)容,以檢查運行效果rewind(fp1);rewind(fp2);rewind(fp3);printf("a1文件內(nèi)容為:\n");charC=fgetc(fp1);while(charC!=EOF){putchar(charC);charC=fgetc(fp1);}printf("a2文件內(nèi)容為:\n");charC=fgetc(fp2);while(charC!=EOF){putchar(charC);charC=fgetc(fp2);}printf("a3文件內(nèi)容為:\n");charC=fgetc(fp3);while(charC!=EOF){putchar(charC);charC=fgetc(fp3);}*/fclose(fp1);fclose(fp2);fclose(fp3);}去掉上述代碼中的注釋符號,該程序的一次運行實例如下圖7-14。圖7-14程序EX7_10運行結(jié)果【實驗7.2.3】從鍵盤輸入兩個學(xué)生數(shù)據(jù),寫入一個文件中,再讀出這兩個學(xué)生的數(shù)據(jù)顯示在屏幕上?!局笇?dǎo)】該實驗需要一個數(shù)據(jù)結(jié)構(gòu)來存儲學(xué)生信息,因此需要定義一個學(xué)生結(jié)構(gòu)體。并將輸入后的學(xué)生信息寫入文件,再讀出該文件的內(nèi)容,顯示在屏幕上。每個學(xué)生的信息包含一組數(shù)據(jù),因此使用數(shù)據(jù)塊讀寫函數(shù)fread和fwrite來完成對文件的讀寫,程序如下。

/*EX7_11.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>structstu{charname[10];intnum;intage;charaddr[20];}stu_1[2],stu_2[2],*p,*q;main()(){FILE*fp;p=stu_1;q=stu_2;inti;if((fp=fopen("stu_list","wb+"))==NULL){printf("Cannotopenfilestrikeanykeyexit!");exit(0);}printf("inputdata\n");for(i=0;i<2;i++,p++)scanf("%s%d%d%s",p->name,&p->num,&p->age,p->addr);p=stu_1;fwrite(p,sizeof(structstu),2,fp);rewind(fp);fread(q,sizeof(structstu),2,fp);printf("NAME\tNUMBER\tAGE\tADDR\n");for(i=0;i<2;i++,q++)printf("%s\t%5d%7d\t%s\n",q->name,q->num,q->age,q->addr);fclose(fp);}本例程序定義了一個結(jié)構(gòu)stu,說明了兩個結(jié)構(gòu)數(shù)組stu_1和stu_2以及兩個結(jié)構(gòu)指針變量p和q。p指向stu_1,q指向stu_2。程序以讀寫方式打開二進制文件“stu_list”,輸入二個學(xué)生數(shù)據(jù)之后,寫入該文件中,然后用rewind函數(shù)把文件內(nèi)部位置指針重新移到文件首,讀出兩個學(xué)生數(shù)據(jù)后,在屏幕上顯示。圖7-15程序EX7_11運行結(jié)果【實驗7.2.4】用fscanf和fprintf函數(shù)完成實驗7.2.3的問題?!局笇?dǎo)】與函數(shù)fread和fwrite相比,fscanf和fprintf函數(shù)每次只能讀寫一個結(jié)構(gòu)數(shù)組元素,因此采用了循環(huán)語句來讀寫全部數(shù)組元素,程序如下。

/*EX7_12.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>structstu{charname[10];intnum;intage;charaddr[20];}stu_1[2],stu_2[2],*p,*q;main()(){FILE*fp;p=stu_1;q=stu_2;inti;if((fp=fopen("stu_list","wb+"))==NULL){printf("Cannotopenfilestrikeanykeyexit!");exit(0);}printf("inputdata\n");for(i=0;i<2;i++,p++)scanf("%s%d%d%s",p->name,&p->num,&p->age,p->addr);p=stu_1;for(i=0;i<2;i++,p++)fprintf(fp,"%s%d%d%s\n",p->name,p->num,p->age,p->addr);rewind(fp);for(i=0;i<2;i++,q++)fscanf(fp,"%s%d%d%s\n",q->name,&q->num,&q->age,q->addr);printf("NAME\tNUMBER\tAGE\tADDR\n");q=stu_2;for(i=0;i<2;i++,q++)printf("%s\t%5d%7d\t%s\n",q->name,q->num,q->age,q->addr);fclose(fp);}本程序中fscanf和fprintf函數(shù)每次只能讀寫一個結(jié)構(gòu)數(shù)組元素,因此采用了循環(huán)語句來讀寫全部數(shù)組元素。還要注意指針變量p,q由于循環(huán)改變了它們的值,因此在程序中分別對它們重新賦予了數(shù)組的首地址。圖7-16程序EX7_12運行結(jié)果【實驗7.2.5】在學(xué)生文件stu_list中讀出第二個學(xué)生的數(shù)據(jù)。【指導(dǎo)】前兩個實驗對文件的讀取都是順序讀出,而該實驗只讀寫文件stu_list中某一指定部分的內(nèi)容。因此用函數(shù)fseek先將文件內(nèi)部的位置指針移動到需要讀寫的位置,然后再使用函數(shù)fread讀取指定數(shù)據(jù)。/*EX7_13.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>structstu{charname[10];intnum;intage;charaddr[20];}student,*p;main()(){FILE*fp;inti=1;p=&student;if((fp=fopen("stu_list","rb"))==NULL){printf("Cannotopenfilestrikeanykeyexit!");getch()();exit(1);}rewind(fp);fseek(fp,i*sizeof(structstu),0);fread(p,sizeof(structstu),1,fp);printf("name\tnumber\tageaddr\n");printf("%s\t%5d%7d%s\n",p->name,p->num,p->age,p->addr);}該程序的一次運行實例如下圖7-17。圖7-17程序EX7_13運行結(jié)果

7.2.4拓展與練習(xí)

【練習(xí)】利用本章的學(xué)習(xí)內(nèi)容實現(xiàn)簡單的文件加密?!局笇?dǎo)】每次對原文中的一個字符進行加密,再將加密后的這個字符存儲到密文,直到將原文中的每個字符做如上處理后,才結(jié)束該加密程序。具體做法為:首先通過鍵盤輸入加密密鑰,然后讀取原文中的每一個字符,與加密密鑰進行異或操作,得到該字符的加密密文,然后將該加密密文存入密文中,直到處理完原文中的每個字符,程序如下。/*EX7_14.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>voidmain(){ FILE*originalfile,*Cipherfile;charcharC; intintCipher;intintN; printf("請輸入密鑰intN的值:");scanf("%d",&intN); if((originalfile=fopen("test","rb"))==NULL) {printf("不能打開文件\n");exit(0); } if((Cipherfile=fopen("Ciphertext","wb"))==NULL) {printf("不能打開文件\n");exit(0); }charC=fgetc(originalfile);while(charC!=EOF) {intCipher=(int)(charC)^intN; fputc((char)(intCipher),Cipherfile);charC=fgetc(originalfile); }fclose(Cipherfile);fclose(originalfile);}該程序?qū)崿F(xiàn)了較簡單對稱加密的一種算法。在C語言中,一個int型數(shù)據(jù)占2個字節(jié),因此該程序可以有65536個加密密鑰?,F(xiàn)假設(shè)輸入加密密鑰1234,其執(zhí)行效果如圖7-18至圖7-20。圖7-18程序EX7_14運行結(jié)果圖7-19程序EX7_14加密前原文內(nèi)容圖7-20程序EX7_14加密后密文內(nèi)容此外,該實例只是為了說明通過C語言中的位運算與文件處理解決問題的方法。在實際中,加密算法要復(fù)雜得多,對它的處理相對也比較復(fù)雜。例如該程序可以使用不同的加密密鑰進行多次加密,或者配合使用其他位運算,對原文實現(xiàn)非對稱加密等方法,都可以增加密文的破解難度,以達到文件傳輸過程中的安全性。解密為加密的逆過程,因此解密程序可以作為課后練習(xí),由自己編程運行。

7.2.5編程規(guī)范與常見錯誤

1.使用文件時忘記打開文件;2.用只讀方式打開,卻企圖向該文件輸出數(shù)據(jù);3.文件使用完,忘記關(guān)閉文件等錯誤。因此文件打開前,應(yīng)做到對文件的狀態(tài)進行檢查。

7.2.6貫通案例之八

1.問題描述:在貫通案例七的基礎(chǔ)上實現(xiàn)學(xué)生成績管理系統(tǒng)的加載文件,保存文件兩個功能。2.編寫程序/*函數(shù)功能:保存學(xué)生記錄文件 函數(shù)參數(shù):結(jié)構(gòu)體指針head,指向存儲學(xué)生信息的結(jié)構(gòu)體數(shù)組的首地址 整型變量n,表示學(xué)生人數(shù) 整型變量m,表示考試科目函數(shù)返回值:無*//*EX7_15.C*/voidSaveScoreFile(STU*head,constintn,constintm){ FILE*fp; inti; STU*p=head; if((fp=fopen("record","wb"))==NULL) { printf("cannotopenfile\n"); exit(1); }printf("\nSavingfile\n"); fwrite(&n,sizeof(int),1,fp); fwrite(&m,sizeof(int),1,fp); for(i=0;i<n;i++) { fwrite(head+i,sizeof(structstudent),1,fp); } fclose(fp); return;}/*函數(shù)功能:加載學(xué)生記錄文件 函數(shù)參數(shù):結(jié)構(gòu)體指針head,指向存儲學(xué)生信息的結(jié)構(gòu)體數(shù)組的首地址 整型變量n,表示學(xué)生人數(shù) 整型變量m,表示考試科目函數(shù)返回值:結(jié)構(gòu)體指針head,指向存儲學(xué)生信息的結(jié)構(gòu)體數(shù)組的首地址*/

溫馨提示

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

評論

0/150

提交評論