版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
模塊7位運(yùn)算與文件
任務(wù)1位運(yùn)算學(xué)習(xí)目標(biāo)掌握六種位運(yùn)算的運(yùn)算符與格式、運(yùn)算規(guī)則。
7.1.1案例講解
案例1二進(jìn)制的循環(huán)移位1.問(wèn)題描述實(shí)現(xiàn)二進(jìn)制的循環(huán)移位。設(shè)待移位的數(shù)為a,移位情況如圖7-1,設(shè)系統(tǒng)中2個(gè)字節(jié)存放一個(gè)整數(shù)。2.編程分析n位圖7-1二進(jìn)制的循環(huán)移位圖解該問(wèn)題的要求在于將待移位數(shù)a分成兩部分,然后交換這兩部分的位置。從而可知,需要增加兩個(gè)變量存儲(chǔ)變量a的兩部分的值,而這些操作都需要求助于位運(yùn)算。程序描述如下:main(){定義無(wú)符號(hào)整型變量a,b,c定義整型變量n輸入待移位數(shù)a和所移動(dòng)位數(shù)n對(duì)數(shù)a左移16-n位后的結(jié)果給變量b對(duì)數(shù)a右移n位后的結(jié)果給變量c對(duì)變量b,c做按位或運(yùn)算,計(jì)算結(jié)果給變量c輸出變量a和c}n位n位圖7-1二進(jìn)制的循環(huán)移位圖解3.編寫(xiě)源程序/*EX7_1.C*/#include<stdio.h>main(){unsignedshortunsignedA,unsignedB,unsignedC;intintN;printf("請(qǐng)輸入一個(gè)無(wú)符號(hào)整型變量unsignedA的值:");scanf("%u",&unsignedA);printf("請(qǐng)輸入移位位數(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.運(yùn)行結(jié)果圖7-2案例1運(yùn)行結(jié)果5.歸納分析在本案例中,使用了左移位運(yùn)算、右移位運(yùn)算和按位或運(yùn)算相配合,實(shí)現(xiàn)二進(jìn)制的循環(huán)移位。該程序運(yùn)行的一個(gè)實(shí)例,輸入unsignedA的值為174,移動(dòng)位數(shù)intN的值為2,則運(yùn)行結(jié)果如圖。其中:十進(jìn)制數(shù)174(即為八進(jìn)制數(shù)256)的二進(jìn)制數(shù)為0000000010101110(按題設(shè)要求為2個(gè)字節(jié)),循環(huán)移動(dòng)2位,則循環(huán)移位后的二進(jìn)制結(jié)果為1000000000101011(即為八進(jìn)制數(shù)100053)。
7.1.2基礎(chǔ)理論
C語(yǔ)言中提供給開(kāi)發(fā)人員一種位的運(yùn)算,這種位的運(yùn)算常用在檢測(cè)和控制領(lǐng)域中,這和C語(yǔ)言的特性關(guān)系非常大,因?yàn)镃語(yǔ)言是具有高級(jí)語(yǔ)言的特點(diǎn)和低級(jí)語(yǔ)言的功能,能完成一些匯編語(yǔ)言所能完成的功能。給開(kāi)發(fā)人員提供了一定的簡(jiǎn)便。C語(yǔ)言提供了六種位運(yùn)算,下面分別介紹。1.按位與運(yùn)算(&)
(1)格式:x&y(2)規(guī)則:按位與運(yùn)算符“&”是雙目運(yùn)算符。其功能是參加運(yùn)算的兩數(shù)各對(duì)應(yīng)的二進(jìn)位相與。只有對(duì)應(yīng)的兩個(gè)二進(jìn)位均為1時(shí),結(jié)果位才為1,否則為0。參加運(yùn)算的數(shù)以補(bǔ)碼方式出現(xiàn)。例如:9&5可寫(xiě)算式如下
00001001
&0000010100000001結(jié)果為:9&5=1。(3)主要用途:用來(lái)對(duì)某些位清0或保留某些位。例如:把a(bǔ)的高八位清0,保留低八位,可作a&255運(yùn)算(255的二進(jìn)制數(shù)為0000000011111111)。2.按位或運(yùn)算符(|)(1)格式:x|y(2)規(guī)則:按位或運(yùn)算符“|”是雙目運(yùn)算符。其功能是參加運(yùn)算的兩數(shù)各對(duì)應(yīng)的二進(jìn)位相或。只要對(duì)應(yīng)的二個(gè)二進(jìn)位有一個(gè)為1時(shí),結(jié)果位就為1。參加運(yùn)算的兩個(gè)數(shù)均以補(bǔ)碼出現(xiàn)。例如:9|5可寫(xiě)算式如下
00001001
|0000010100001101結(jié)果為:9|5=13
(3)主要用途:常用來(lái)將源操作數(shù)某些位置1,其他位不變。例如:把a(bǔ)的低八位置1,保留高八位,可作a|255運(yùn)算(255的二進(jìn)制數(shù)為0000000011111111)。3.按位異或運(yùn)算(^)
(1)格式:x^y(2)規(guī)則:按位異或運(yùn)算符“^”是雙目運(yùn)算符。其功能是參加運(yùn)算的兩數(shù)各對(duì)應(yīng)的二進(jìn)位相異或,當(dāng)兩對(duì)應(yīng)的二進(jìn)位相異時(shí),結(jié)果為1。參加運(yùn)算數(shù)仍以補(bǔ)碼出現(xiàn)。例如:9^5可寫(xiě)成算式如下
00001001
^0000010100001100
結(jié)果為:9^5=12
(3)主要用途:常用來(lái)將源操作數(shù)某些特定位的值取反,其他位不變。
例如:把a(bǔ)的低八位取反,保留高八位,可作a^255運(yùn)算(255的二進(jìn)制數(shù)為0000000011111111)。4.求反運(yùn)算(~)
(1)格式:~x(2)規(guī)則:求反運(yùn)算符~為單目運(yùn)算符,具備右結(jié)合性。其功能是對(duì)參加運(yùn)算的數(shù)的各二進(jìn)位按位求反。例如:~9可寫(xiě)成算式如下
~00000000000010011111111111110110結(jié)果為:~9=-105.左移運(yùn)算(<<)(1)格式:x<<位數(shù)(2)規(guī)則:左移運(yùn)算符“<<”是雙目運(yùn)算符。其功能是把“<<”左邊的運(yùn)算數(shù)的各二進(jìn)位全部左移若干位,“<<”右邊的數(shù)指定移動(dòng)的位數(shù)。低位補(bǔ)0,高位溢出。例如:設(shè)a=15,a<<2表示把000001111左移為00111100(十進(jìn)制60)。6.位右移(>>)(1)格式:x>>位數(shù)(2)規(guī)則:使操作數(shù)的各位右移,高位補(bǔ)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.問(wèn)題描述:已知一文本文件“c:\text.txt”的內(nèi)容如下:
#include<stdio.h>voidmain(){printf("helloworld");}編寫(xiě)程序讀取指定該文本文件的內(nèi)容,并在屏幕上輸出。2.編程分析:程序描述如下:
main(){定義文件指針*fp,定義字符變量ch打開(kāi)指定的文本文件判斷指定的文本文件是否能打開(kāi),假如不能打開(kāi),顯示提示信息,并結(jié)束程序使用循環(huán)讀取該文本文件的每個(gè)字符,并依次在屏幕上輸出關(guān)閉指定的文本文件
}3.編寫(xiě)源程序
/*EX7_8.C*/#include<stdio.h>#include<conio.h>/*控制臺(tái)輸入輸出*/#include<stdlib.h>/*最常用的系統(tǒng)函數(shù)*/voidmain(){FILE*fileP;charcharC;if((fileP=fopen("c:\\text.txt","r"))==NULL){
printf("不能打開(kāi)文件,按任意鍵退出!");getch();exit(1);}while((charC=fgetc(fileP))!=EOF)putchar(charC);fclose(fileP);}4.運(yùn)行結(jié)果圖7-9案例1運(yùn)行結(jié)果5.歸納分析本例程序的功能是從文件中逐個(gè)讀取字符,在屏幕上顯示。程序定義了文件指針fileP,以讀文本文件方式打開(kāi)文件“text.txt”,并使fileP指向該文件。如打開(kāi)文件出錯(cuò),給出提示并退出程序。While循環(huán)中每次讀出一個(gè)字符,只要讀出的字符不是文件結(jié)束標(biāo)志(每個(gè)文件末有一結(jié)束標(biāo)志EOF)就把該字符顯示在屏幕上,然后再讀入下一字符。每讀一次,文件內(nèi)部的位置指針向后移動(dòng)一個(gè)字符,文件結(jié)束時(shí),該指針指向EOF。
7.2.2基礎(chǔ)理論
1.文件的概念文件是指存儲(chǔ)在外部介質(zhì)上的數(shù)據(jù)集合體,是操作系統(tǒng)數(shù)據(jù)管理的單位。使用數(shù)據(jù)文件的目的:
(1)數(shù)據(jù)文件的改動(dòng)不引起程序的改動(dòng)——程序與數(shù)據(jù)分離;(2)不同程序可以訪問(wèn)同一數(shù)據(jù)文件中的數(shù)據(jù)——數(shù)據(jù)共享;(3)能長(zhǎng)期保存程序運(yùn)行的中間數(shù)據(jù)或結(jié)果數(shù)據(jù)。2.文件的分類(lèi)
根據(jù)文件存儲(chǔ)的內(nèi)容的不同,文件可以分為程序文件和數(shù)據(jù)文件兩種。程序文件是程序代碼的集合體,而數(shù)據(jù)文件是指專(zhuān)門(mén)用來(lái)保存數(shù)據(jù)的文件。根據(jù)文件存儲(chǔ)介質(zhì)的不同,文件又可以分為磁盤(pán)文件和設(shè)備文件兩種。磁盤(pán)文件是指保存在磁盤(pán)或其他外部存儲(chǔ)介質(zhì)上的一個(gè)有序數(shù)據(jù)集,可以是C語(yǔ)言的源文件、目標(biāo)文件、可執(zhí)行程序,也可以是一組待輸入處理的原始數(shù)據(jù),或者是一組輸出的結(jié)果。對(duì)于源文件、目標(biāo)文件、可執(zhí)行
程序可以稱(chēng)為程序文件,對(duì)于輸入輸出數(shù)據(jù)可稱(chēng)為數(shù)據(jù)文件。設(shè)備文件是指與主機(jī)相聯(lián)的各種外部設(shè)備,如顯示器、打印機(jī)、磁盤(pán)等。C語(yǔ)言把外部設(shè)備也看作是一個(gè)文件來(lái)進(jìn)行管理,把他們的輸入、輸出等同于對(duì)磁盤(pán)文件的讀和寫(xiě)。通常把顯示器定義為標(biāo)準(zhǔn)輸出文件,鍵盤(pán)指定為標(biāo)準(zhǔn)的輸入文件。
根據(jù)文件的組織形式不同,文件又可以分為ASCII碼文件(也稱(chēng)為文本文件)和二進(jìn)制碼文件兩種。ASCII碼文件,每個(gè)字節(jié)存放一個(gè)字符的ASCII碼。二進(jìn)制碼文件,數(shù)據(jù)按其在內(nèi)存中的
存儲(chǔ)形式原樣存放。例如:int型數(shù)10000,在內(nèi)存中存儲(chǔ)占用兩個(gè)字節(jié),其中1的ASCII為00110001,0的ASCII為00110000,10000的二進(jìn)制表示為10011100010000。如果分別存儲(chǔ)到文本文件和二進(jìn)制碼文件中,其形式如下:圖7-10數(shù)據(jù)存儲(chǔ)示意圖
從圖中可以看出來(lái),ASCII碼文件輸入與字符一一對(duì)應(yīng),便于對(duì)字符進(jìn)行逐個(gè)處理,也便于字符的輸出,但一般占存儲(chǔ)空間較多,而且花費(fèi)二進(jìn)制代碼和ASCII代碼之間的轉(zhuǎn)換時(shí)間。用二進(jìn)制文件則可以節(jié)省外部存儲(chǔ)空間和轉(zhuǎn)換的時(shí)間,但處理過(guò)程比較復(fù)雜。因此,文本文件特點(diǎn):存儲(chǔ)量大、速度慢、便于對(duì)字符操作;二進(jìn)制碼文件特點(diǎn):存儲(chǔ)量小、速度快、便于存放中間結(jié)果。3.文件的處理在C語(yǔ)言中,對(duì)文件的輸入輸出都是通過(guò)文件系統(tǒng)完成的,并不區(qū)分類(lèi)型,都看成是字符或者是二進(jìn)制流,按字節(jié)進(jìn)行處理。輸入輸出數(shù)據(jù)流的開(kāi)始和結(jié)束只由程序控制而不受物理符號(hào)(如回車(chē)換行符)的控制。因此我們也把這種文件稱(chēng)作“流式文件”。文件系統(tǒng)又分為緩沖文件系統(tǒng)和非緩沖文件系統(tǒng)。所謂緩沖文件系統(tǒng)是高級(jí)文件系統(tǒng),系統(tǒng)自動(dòng)地在內(nèi)存區(qū)為每一個(gè)正在使用的文件名開(kāi)辟一個(gè)緩沖區(qū),數(shù)據(jù)的輸入輸出都是以這個(gè)緩沖區(qū)為中介。所謂非緩沖文件系統(tǒng)是低級(jí)文件系統(tǒng),指系統(tǒng)不自動(dòng)開(kāi)辟確定大小的緩沖區(qū),而由程序?yàn)槊總€(gè)文件設(shè)定緩沖區(qū)。圖7-11和圖7-12分別是緩沖文件系統(tǒng)和非緩沖文件系統(tǒng)。
標(biāo)準(zhǔn)C只采用緩沖文件系統(tǒng),也就是既用緩沖文件系統(tǒng)處理文本文件,也用它來(lái)處理二進(jìn)制文件。在C語(yǔ)言中沒(méi)有輸入輸出語(yǔ)句,對(duì)文件的讀寫(xiě)操作都是用標(biāo)準(zhǔn)的輸入輸出庫(kù)函數(shù)來(lái)實(shí)現(xiàn)的。4.緩沖文件系統(tǒng)
(1)FILE類(lèi)型和文件指針在緩沖文件系統(tǒng)中,使用最多的概念就是“文件指針”。緩沖文件系統(tǒng)為每個(gè)使用的文件在內(nèi)存中開(kāi)辟一個(gè)緩沖區(qū),用來(lái)存放文件的相關(guān)信息,這些信息被保存在FILE類(lèi)型的變量中。在stdio.h文件中有FILE類(lèi)型的定義:typedefstruct{shortlevel;/*緩沖區(qū)空或滿(mǎn)的程度*/unsignedflags;/*文件狀態(tài)標(biāo)志*/charfd;/*文件描述符*/unsignedcharhold;/*如無(wú)緩沖區(qū)則不讀取字符*/shortbsize;/*緩沖區(qū)的大小*/unsignedchar*buffer;/*數(shù)據(jù)緩沖區(qū)的位置*/unsignedar*curp;/*指針,當(dāng)前的指向*/unsignedistemp;/*臨時(shí)文件*/shorttoken;/*用于有效性檢查*/}FILE;對(duì)于普通用戶(hù)而言,不必了解FILE類(lèi)型的結(jié)構(gòu)內(nèi)容,只要知道,每個(gè)文件都對(duì)應(yīng)一個(gè)唯一的文件型指針變量,通過(guò)文件指針我們可以對(duì)它所指的文件進(jìn)行各種操作。定義文件型指針變量的一般形式為:FILE*指針變量名;例如:FILE*fileP;fileP是指向FILE類(lèi)型結(jié)構(gòu)體的指針變量,通過(guò)fileP即可找存放某個(gè)文件信息的結(jié)構(gòu)變量,然后按結(jié)構(gòu)變量提供的信息可以訪問(wèn)該文件,實(shí)施對(duì)文件的操作。習(xí)慣上也籠統(tǒng)地把fileP稱(chēng)為指向一個(gè)文件的指針。5.文件的操作對(duì)文件的基本操作有兩種,一種是輸入操作,一種是輸出操作。在訪問(wèn)文件之前,要先打開(kāi)文件,然后才能訪問(wèn)該文件,對(duì)文件操作結(jié)束后,還要關(guān)閉該文件。因此對(duì)文件的操作,必須遵守“先打開(kāi),再讀寫(xiě),后關(guān)閉”的規(guī)則,也就是說(shuō)在進(jìn)行讀寫(xiě)操作之前要先打開(kāi)文件,使用完畢后要關(guān)閉。
(1)文件的打開(kāi)函數(shù)fopen
fopen函數(shù)用來(lái)實(shí)現(xiàn)打開(kāi)一個(gè)文件,其調(diào)用的一般形式為:
FILE*fileP;
fileP=fopen(文件名,使用文件方式);
其中,“文件名”是被打開(kāi)文件的文件名,包括文件的存儲(chǔ)路徑,“使用文件方式”是指文件的類(lèi)型和操作要求。
例如:fileP=fopen(“file1”,“r”);它表示在當(dāng)前目錄下打開(kāi)文件file1,使用文件方式為“讀”操作,并使fileP指向該文件。使用文件的方式共有12種,如表7-1所示.表7-1文件使用方式表文件使用方式含義“r”(只讀)打開(kāi)一個(gè)文本文件,只允許讀數(shù)據(jù)“w”(只寫(xiě))
打開(kāi)或建立一個(gè)文本文件,只允許寫(xiě)數(shù)據(jù)“a”(追加)打開(kāi)一個(gè)文本文件,并在文件末尾增加數(shù)據(jù)“rb”(只讀)打開(kāi)一個(gè)二進(jìn)制文件,只允許讀數(shù)據(jù)“wb”(只寫(xiě))打開(kāi)或建立一個(gè)二進(jìn)制文件,只允許寫(xiě)數(shù)據(jù)“ab”(追加)打開(kāi)一個(gè)二進(jìn)制文件,并在文件末尾寫(xiě)數(shù)據(jù)“r+”(讀寫(xiě))打開(kāi)一個(gè)文本文件,允許讀和寫(xiě)“w+”(讀寫(xiě))
建立一個(gè)文本文件,允許讀寫(xiě)“a+”(讀寫(xiě))打開(kāi)一個(gè)文本文件,允許讀,或在文件末追加數(shù)據(jù)“rb+”(讀寫(xiě))
打開(kāi)一個(gè)二進(jìn)制文件,允許讀和寫(xiě)“wb+”(讀寫(xiě))
建立一個(gè)二進(jìn)制文件,允許讀和寫(xiě)“ab+”(讀寫(xiě))打開(kāi)一個(gè)二進(jìn)制文件,允許讀,或在文件末追加數(shù)據(jù)說(shuō)明:
●用“r”方式打開(kāi)的文件,該文件必須已經(jīng)存在,且只能從該文件讀出數(shù)據(jù)。
●用“w”方式打開(kāi)的文件只能向該文件寫(xiě)入數(shù)據(jù)。若打開(kāi)的文件不存在,則以指定的文件名建立該文件,若打開(kāi)的文件已經(jīng)存在,則將該文件刪去,重建一個(gè)新文件。
●如果想向一個(gè)已存在的文件末尾添加新的信息(不刪除原來(lái)的數(shù)據(jù)),則應(yīng)該用“a”方式打開(kāi)。但此時(shí)該文件必須是存在的,否則將會(huì)出錯(cuò)。
●用“r+”、“w+”、“a+”方式打開(kāi)的文件
既可以用來(lái)寫(xiě)入數(shù)據(jù),也可以用來(lái)讀出文件中的數(shù)據(jù)。如果不能打開(kāi)一個(gè)文件時(shí),fopen將返回一個(gè)空指針值NULL。在程序中可以用這一信息來(lái)判別是否完成打開(kāi)文件的工作,并作相應(yīng)的處理。因此常用以下程序段打開(kāi)文件:
if((fileP=fopen("file1","r")==NULL){printf("\n不能打開(kāi)文件file1\n");exit(0);}(2)文件關(guān)閉函數(shù)fclose文件一旦使用完畢,應(yīng)該用關(guān)閉文件函數(shù)把文件關(guān)閉,以避免文件的數(shù)據(jù)丟失等錯(cuò)誤。所謂關(guān)閉文件就是使文件指針變量不再指向該文件。調(diào)用的一般形式是:fclose(文件指針);例如:fclose(fileP);
順利完成關(guān)閉文件操作時(shí),fclose函數(shù)返回值為0,否則返回EOF(-1)。6.文件的讀寫(xiě)和建立文件打開(kāi)以后,就可以對(duì)它進(jìn)行讀寫(xiě)操作了。在C語(yǔ)言中提供了多種文件讀寫(xiě)的函數(shù):字符讀寫(xiě)函數(shù):fgetc和fputc字符串讀寫(xiě)函數(shù):fgets和fputs數(shù)據(jù)塊讀寫(xiě)函數(shù):fread和fwrite格式化讀寫(xiě)函數(shù):fscanf和fprinf使用以上函數(shù)都要求包含頭文件stdio.h。(1)讀字符函數(shù)fgetc
fgetc函數(shù)的功能是從指定的文件中讀一個(gè)字符,讀取的文件必須是以讀或讀寫(xiě)方式打開(kāi)的。調(diào)用的形式為:ch=fgetc(fileP);fileP為文件型指針變量,ch為字符變量。其意義是從打開(kāi)的文件fileP中讀取一個(gè)字符并送入ch中。讀字符時(shí)遇到文件結(jié)束符,函數(shù)返回一個(gè)文件結(jié)束標(biāo)志EOF(-1)。EOF是在stdio.h文件中定義的符號(hào)常量,值為-1。(2)寫(xiě)字符函數(shù)fputc
fputc函數(shù)的功能是把一個(gè)字符寫(xiě)入指定的文件中。調(diào)用的形式為:fputc(ch,fileP);ch是要輸出的字符,它可以是字符常量或者是字符變量。fileP為文件型指針變量。其意義是把字符ch寫(xiě)入到fileP所指向的文件中。如果寫(xiě)入成功則返回寫(xiě)入的字符,如果寫(xiě)入失敗則返回一個(gè)EOF(-1)。(3)讀字符串函數(shù)fgets
fgets函數(shù)的功能是從指定的文件中讀一個(gè)字符串到字符數(shù)組中。函數(shù)調(diào)用的形式為:fgets(str,n,fileP);n是一個(gè)正整數(shù),為要求得到的字符數(shù),但從文件中讀出的字符串只有n-1個(gè)字符,然后在最后一個(gè)字符后加上串結(jié)束標(biāo)志'\0',因此得到的字符串共有n個(gè)字符。把得到的字符串放在字符數(shù)組str里面。fileP為文件型指針變量。如果在讀完n-1個(gè)字符之前遇到換行符或EOF,讀操作即結(jié)束。函數(shù)返回值為str的首地址。(4)寫(xiě)字符串函數(shù)fputs
fputs函數(shù)的功能是向指定的文件寫(xiě)入一個(gè)字符串。函數(shù)的調(diào)用形式為:fputs(s,fileP)s可以是字符串常量,也可以是字符數(shù)組名,或字符型指針變量。fileP為文件型指針變量。字符串末尾的’\0’不輸出,若輸出成功,函數(shù)值返回為0,失敗則為EOF。7.?dāng)?shù)據(jù)塊讀寫(xiě)函數(shù)fread和fwrite
有時(shí)候需要讀寫(xiě)一組數(shù)據(jù),如一個(gè)數(shù)組的元素,一個(gè)結(jié)構(gòu)變量的值等。這時(shí)候可以使用讀寫(xiě)數(shù)據(jù)塊函數(shù),用來(lái)讀寫(xiě)一個(gè)數(shù)據(jù)塊。函數(shù)調(diào)用的一般形式為:
fread(buffer,size,count,fileP);fwrite(buffer,size,count,fileP);
其中:buffer是一個(gè)指針,在fread函數(shù)中,它表示存放輸入數(shù)據(jù)的首地址,在fwrite函數(shù)中,它表示存放輸出數(shù)據(jù)的首地址。size表示要讀寫(xiě)的字節(jié)數(shù)。count表示要讀寫(xiě)的數(shù)據(jù)塊塊數(shù)(即count個(gè)size大的數(shù)據(jù)塊)。fileP表示文件指針。8.格式化讀寫(xiě)函數(shù)fscanf和fprintffscanf函數(shù),fprintf函數(shù)與前面使用的scanf和printf函數(shù)的功能相似,都是格式化讀寫(xiě)函數(shù)。不同之處在于fscanf函數(shù)和fprintf函數(shù)的讀寫(xiě)對(duì)象不是鍵盤(pán)和顯示器,而是磁盤(pán)文件。函數(shù)的調(diào)用格式為:
fscanf(文件指針,格式字符串,輸入表列);
fprintf(文件指針,格式字符串,輸出表列);要注意的是,當(dāng)在內(nèi)存和磁盤(pán)頻繁交換數(shù)據(jù)的情況下,最好不使用這兩個(gè)函數(shù),而使用fread和fwrite函數(shù)。9.文件的定位和測(cè)試(1)文件的定位上一節(jié)介紹的對(duì)文件的讀寫(xiě)方式都是順序讀寫(xiě),即讀寫(xiě)文件只能從頭開(kāi)始,順序讀寫(xiě)各個(gè)數(shù)據(jù)。但在實(shí)際問(wèn)題中常要求只讀寫(xiě)文件中某一指定的部分,也就是移動(dòng)文件指針到需要讀寫(xiě)的位置,再進(jìn)行讀寫(xiě),這種讀寫(xiě)稱(chēng)為隨機(jī)讀寫(xiě)。實(shí)現(xiàn)隨機(jī)讀寫(xiě)的關(guān)鍵是按要求移動(dòng)文件指針,這稱(chēng)為文件的定位。rewind函數(shù):調(diào)用形式為rewind(文件指針);
它的功能是把文件指針重新移到文件的開(kāi)頭。此函數(shù)沒(méi)有返回值。fseek函數(shù):fseek函數(shù)用來(lái)移動(dòng)文件指針,其調(diào)用形式為:
fseek(文件指針,位移量,起始點(diǎn));其中:“文件指針”指向被移動(dòng)的文件。“位移量”是指以“起始點(diǎn)”為基點(diǎn),向前移動(dòng)的字節(jié)數(shù)。要求位移量是long型數(shù)據(jù),以便在文件的長(zhǎng)度大于64K時(shí)不會(huì)出問(wèn)題。當(dāng)用常量表示
位移量時(shí),直接在末尾加后綴“L”?!捌鹗键c(diǎn)”表示從文件的什么位置開(kāi)始計(jì)算位移量,規(guī)定的起始點(diǎn)有三種:文件首,當(dāng)前位置和文件尾。其表示方法如表7-2所示。表7-2文件指針三種起始點(diǎn)起始點(diǎn)表示符號(hào)數(shù)字表示文件首SEEK__SET0當(dāng)前位置SEEK__CUR1文件末尾SEEK__END2
fseek函數(shù)一般用于二進(jìn)制文件,這是因?yàn)槲谋疚募M(jìn)行轉(zhuǎn)換,在計(jì)算位置的時(shí)候會(huì)出現(xiàn)錯(cuò)誤。(2)文件檢測(cè)函數(shù)C語(yǔ)言中常用的文件檢測(cè)函數(shù)有以下幾個(gè):●文件結(jié)束檢測(cè)函數(shù)feof()調(diào)用格式:feof(文件指針);功能:判斷文件是否處于文件結(jié)束位置,如文件結(jié)束,則返回值為1,否則為0?!褡x寫(xiě)文件出錯(cuò)檢測(cè)函數(shù)ferror()調(diào)用格式:ferror(文件指針);功能:檢查文件在用各種輸入輸出函數(shù)進(jìn)行讀寫(xiě)時(shí)是否出錯(cuò)。如ferror返回值為0表示未出錯(cuò),否則表示有錯(cuò)?!裎募鲥e(cuò)標(biāo)志和文件結(jié)束標(biāo)志置0函數(shù)clearerr()調(diào)用格式:clearerr(文件指針);功能:用于清除出錯(cuò)標(biāo)志和文件結(jié)束標(biāo)志,使它們?yōu)?值。
7.2.3技能訓(xùn)練
【實(shí)驗(yàn)7.2.1】編寫(xiě)程序,從鍵盤(pán)上輸入一系列字符,寫(xiě)到磁盤(pán)文件file中,以#作為輸入的結(jié)束標(biāo)志,然后把文件中的內(nèi)容在屏幕上輸出?!局笇?dǎo)】本實(shí)驗(yàn)的功能是執(zhí)行了兩次磁盤(pán)文件操作:先用fputc函數(shù)把輸入的字符放在fileP指向的文件中,然后把文件中的內(nèi)容用fgetc函數(shù)逐個(gè)讀取,在屏幕上顯示。程序定義了文件指針fileP,先以寫(xiě)方式打開(kāi)文本文件file,并使fileP指向該文件。如打開(kāi)文件出錯(cuò),給出提示并退出程序。輸入字符到文件中的循環(huán)是以輸入“#”作為循環(huán)結(jié)束的標(biāo)志;然后再以讀方式打開(kāi)文本文件file,循環(huán)讀取文本文件的每一個(gè)字符,并顯示在屏幕上,并以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("不能打開(kāi)文件\n");exit(0);}printf(“請(qǐng)輸入字符:\n”);while((charC=getchar())!=’#’){
fputc(charC,fileP);}fclose(fileP);if((fileP=fopen("file","r"))==NULL){printf("不能打開(kāi)文件\n");exit(0);}printf("文件內(nèi)容為:\n");charC=fgetc(fileP);
while(charC!=EOF){putchar(charC);charC=fgetc(fileP);}fclose(fileP);}該程序首先打開(kāi)當(dāng)前目錄中文件名為file的文件,然后從鍵盤(pán)上輸入字符并存儲(chǔ)到文件file
中,輸入完成后關(guān)閉文件file,最后再次打開(kāi)文件file,并輸出文件file中的字符。圖7-13為該程序的一次運(yùn)行實(shí)例.圖7-13程序EX7_9運(yùn)行結(jié)果【實(shí)驗(yàn)7.2.2】有兩個(gè)磁盤(pán)文件a1.txt和a2.txt,各存放若干行字母,今要求把這兩個(gè)文件中的信息按行交叉合并(即先是a1.txt的的第一行,接著是a2.txt中的第一行,然后是a1.txt的第二行,跟著是a2.txt的第二行,…),輸出到一個(gè)新文件a3.txt中去?!局笇?dǎo)】以讀方式打開(kāi)磁盤(pán)文件a1.txt和a2.txt,然后依次讀取a1.txt和a2.txt的一行,交叉存入新文件a3.txt,因此可以通過(guò)3個(gè)循環(huán)語(yǔ)句實(shí)現(xiàn)。具體做法為:通過(guò)fgets函數(shù)分別獲得文件a1.txt和a2.txt中的每一行字符,分別賦值給字符數(shù)組str1和str2,然后將字符數(shù)組str1和
str2中的內(nèi)容依次寫(xiě)入文件a3.txt。假如其中某個(gè)文件讀取完成,則將另一文件剩余行寫(xiě)人文件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)容,以檢查運(yùn)行效果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);}去掉上述代碼中的注釋符號(hào),該程序的一次運(yùn)行實(shí)例如下圖7-14。圖7-14程序EX7_10運(yùn)行結(jié)果【實(shí)驗(yàn)7.2.3】從鍵盤(pán)輸入兩個(gè)學(xué)生數(shù)據(jù),寫(xiě)入一個(gè)文件中,再讀出這兩個(gè)學(xué)生的數(shù)據(jù)顯示在屏幕上。【指導(dǎo)】該實(shí)驗(yàn)需要一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)學(xué)生信息,因此需要定義一個(gè)學(xué)生結(jié)構(gòu)體。并將輸入后的學(xué)生信息寫(xiě)入文件,再讀出該文件的內(nèi)容,顯示在屏幕上。每個(gè)學(xué)生的信息包含一組數(shù)據(jù),因此使用數(shù)據(jù)塊讀寫(xiě)函數(shù)fread和fwrite來(lái)完成對(duì)文件的讀寫(xiě),程序如下。
/*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);}本例程序定義了一個(gè)結(jié)構(gòu)stu,說(shuō)明了兩個(gè)結(jié)構(gòu)數(shù)組stu_1和stu_2以及兩個(gè)結(jié)構(gòu)指針變量p和q。p指向stu_1,q指向stu_2。程序以讀寫(xiě)方式打開(kāi)二進(jìn)制文件“stu_list”,輸入二個(gè)學(xué)生數(shù)據(jù)之后,寫(xiě)入該文件中,然后用rewind函數(shù)把文件內(nèi)部位置指針重新移到文件首,讀出兩個(gè)學(xué)生數(shù)據(jù)后,在屏幕上顯示。圖7-15程序EX7_11運(yùn)行結(jié)果【實(shí)驗(yàn)7.2.4】用fscanf和fprintf函數(shù)完成實(shí)驗(yàn)7.2.3的問(wèn)題。【指導(dǎo)】與函數(shù)fread和fwrite相比,fscanf和fprintf函數(shù)每次只能讀寫(xiě)一個(gè)結(jié)構(gòu)數(shù)組元素,因此采用了循環(huán)語(yǔ)句來(lái)讀寫(xiě)全部數(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ù)每次只能讀寫(xiě)一個(gè)結(jié)構(gòu)數(shù)組元素,因此采用了循環(huán)語(yǔ)句來(lái)讀寫(xiě)全部數(shù)組元素。還要注意指針變量p,q由于循環(huán)改變了它們的值,因此在程序中分別對(duì)它們重新賦予了數(shù)組的首地址。圖7-16程序EX7_12運(yùn)行結(jié)果【實(shí)驗(yàn)7.2.5】在學(xué)生文件stu_list中讀出第二個(gè)學(xué)生的數(shù)據(jù)?!局笇?dǎo)】前兩個(gè)實(shí)驗(yàn)對(duì)文件的讀取都是順序讀出,而該實(shí)驗(yàn)只讀寫(xiě)文件stu_list中某一指定部分的內(nèi)容。因此用函數(shù)fseek先將文件內(nèi)部的位置指針移動(dòng)到需要讀寫(xiě)的位置,然后再使用函數(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);}該程序的一次運(yùn)行實(shí)例如下圖7-17。圖7-17程序EX7_13運(yùn)行結(jié)果
7.2.4拓展與練習(xí)
【練習(xí)】利用本章的學(xué)習(xí)內(nèi)容實(shí)現(xiàn)簡(jiǎn)單的文件加密?!局笇?dǎo)】每次對(duì)原文中的一個(gè)字符進(jìn)行加密,再將加密后的這個(gè)字符存儲(chǔ)到密文,直到將原文中的每個(gè)字符做如上處理后,才結(jié)束該加密程序。具體做法為:首先通過(guò)鍵盤(pán)輸入加密密鑰,然后讀取原文中的每一個(gè)字符,與加密密鑰進(jìn)行異或操作,得到該字符的加密密文,然后將該加密密文存入密文中,直到處理完原文中的每個(gè)字符,程序如下。/*EX7_14.C*/#include<stdio.h>#include<conio.h>#include<stdlib.h>voidmain(){ FILE*originalfile,*Cipherfile;charcharC; intintCipher;intintN; printf("請(qǐng)輸入密鑰intN的值:");scanf("%d",&intN); if((originalfile=fopen("test","rb"))==NULL) {printf("不能打開(kāi)文件\n");exit(0); } if((Cipherfile=fopen("Ciphertext","wb"))==NULL) {printf("不能打開(kāi)文件\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)了較簡(jiǎn)單對(duì)稱(chēng)加密的一種算法。在C語(yǔ)言中,一個(gè)int型數(shù)據(jù)占2個(gè)字節(jié),因此該程序可以有65536個(gè)加密密鑰?,F(xiàn)假設(shè)輸入加密密鑰1234,其執(zhí)行效果如圖7-18至圖7-20。圖7-18程序EX7_14運(yùn)行結(jié)果圖7-19程序EX7_14加密前原文內(nèi)容圖7-20程序EX7_14加密后密文內(nèi)容此外,該實(shí)例只是為了說(shuō)明通過(guò)C語(yǔ)言中的位運(yùn)算與文件處理解決問(wèn)題的方法。在實(shí)際中,加密算法要復(fù)雜得多,對(duì)它的處理相對(duì)也比較復(fù)雜。例如該程序可以使用不同的加密密鑰進(jìn)行多次加密,或者配合使用其他位運(yùn)算,對(duì)原文實(shí)現(xiàn)非對(duì)稱(chēng)加密等方法,都可以增加密文的破解難度,以達(dá)到文件傳輸過(guò)程中的安全性。解密為加密的逆過(guò)程,因此解密程序可以作為課后練習(xí),由自己編程運(yùn)行。
7.2.5編程規(guī)范與常見(jiàn)錯(cuò)誤
1.使用文件時(shí)忘記打開(kāi)文件;2.用只讀方式打開(kāi),卻企圖向該文件輸出數(shù)據(jù);3.文件使用完,忘記關(guān)閉文件等錯(cuò)誤。因此文件打開(kāi)前,應(yīng)做到對(duì)文件的狀態(tài)進(jìn)行檢查。
7.2.6貫通案例之八
1.問(wèn)題描述:在貫通案例七的基礎(chǔ)上實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)的加載文件,保存文件兩個(gè)功能。2.編寫(xiě)程序/*函數(shù)功能:保存學(xué)生記錄文件 函數(shù)參數(shù):結(jié)構(gòu)體指針head,指向存儲(chǔ)學(xué)生信息的結(jié)構(gòu)體數(shù)組的首地址 整型變量n,表示學(xué)生人數(shù) 整型變量m,表示考試科目函數(shù)返回值:無(wú)*//*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,指向存儲(chǔ)學(xué)生信息的結(jié)構(gòu)體數(shù)組的首地址 整型變量n,表示學(xué)生人數(shù) 整型變量m,表示考試科目函數(shù)返回值:結(jié)構(gòu)體指針head,指向存儲(chǔ)學(xué)生信息的結(jié)構(gòu)體數(shù)組的首地址*/
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 復(fù)工安全課件
- 宿遷蘑菇培訓(xùn)課件查找
- 開(kāi)學(xué)收心課件小學(xué)生
- 三年級(jí)品德與社會(huì)下冊(cè)第一單元在愛(ài)的陽(yáng)光下第三課來(lái)自社會(huì)的愛(ài)教案新人教版
- 三年級(jí)數(shù)學(xué)上冊(cè)8分?jǐn)?shù)的初步認(rèn)識(shí)1分?jǐn)?shù)的初步認(rèn)識(shí)第2課時(shí)比較幾分之一的大小教學(xué)設(shè)計(jì)新人教版
- 三年級(jí)科學(xué)上冊(cè)第五單元人與空氣12空氣教案首師大版1
- 《網(wǎng)絡(luò)廣告價(jià)格參考》課件
- 小學(xué)生防火溺水講座課件
- 《結(jié)腸鏡操作法》課件
- 小學(xué)生自學(xué)生字課件圖片
- 實(shí)驗(yàn)診斷學(xué)練習(xí)題庫(kù)(附參考答案)
- 網(wǎng)絡(luò)加速器提供商服務(wù)合同
- 2024版新能源汽車(chē)充電站電線電纜采購(gòu)合同2篇
- 轉(zhuǎn)讓押金協(xié)議合同范例
- 《工業(yè)用二氟草酸硼酸鋰》
- 國(guó)家藥包材檢驗(yàn)標(biāo)準(zhǔn)培訓(xùn)
- 腫瘤科危急重癥護(hù)理
- 江蘇省蘇州市2024-2025學(xué)年第一學(xué)期八年級(jí)英語(yǔ)期末模擬試卷(一)(含答案)
- 2024-2030年中國(guó)加速器行業(yè)發(fā)展趨勢(shì)及運(yùn)營(yíng)模式分析報(bào)告版
- 護(hù)理查房深靜脈置管
- 運(yùn)動(dòng)障礙護(hù)理查房
評(píng)論
0/150
提交評(píng)論