版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
高級語言程序設(shè)計揭安全jieanquan@163.com江西師范大學(xué)計算機信息工程學(xué)院高級語言程序設(shè)計——基于計算思維能力培養(yǎng)高級語言程序設(shè)計——基于計算思維能力培養(yǎng)第9章文件及其應(yīng)用揭安全jieanquan@163.com江西師范大學(xué)計算機信息工程學(xué)院主要內(nèi)容文件概述文件的打開和關(guān)閉文件檢測函數(shù)文件讀寫操作文件隨機讀寫本章思維導(dǎo)圖學(xué)生
文件信息的創(chuàng)建9.19.1引例——學(xué)生文件信息的創(chuàng)建例如,在命令行下執(zhí)行:8_5<stu.txt>out.txtStu.txt輸入輸出重定向文件概述9.29.2文件概述9.2.1流的概念在C語言中的每個串行輸入源和輸出目標(biāo)被稱為“流”。輸入流是一個串行數(shù)據(jù)源,可以為程序提供輸入數(shù)據(jù)輸出流是串行數(shù)據(jù)的目的地,可以接收程序的輸出。流充當(dāng)了程序和輸入輸出設(shè)備之間的橋梁,這使得程序在輸入輸出數(shù)據(jù)時可以采用統(tǒng)一的方式來工作,而不必去關(guān)注具體的物理設(shè)備是什么。<stdio.h>提供了3個標(biāo)準(zhǔn)流流名稱流含義默認連接外設(shè)stdin標(biāo)準(zhǔn)輸入鍵盤stdout標(biāo)準(zhǔn)輸出屏幕stderr標(biāo)準(zhǔn)錯誤屏幕9.2.2文件的分類1、文本文件與二進制文件
C語言的<stdio.h>支持兩種類型的文件:文本文件(也稱ASCII文件)和二進制文件。在文本文件中,用字節(jié)來存儲字符,這使人們可以檢查或編輯文件。在二進制文件中,字節(jié)不一定表示字符,有可能是某數(shù)值型數(shù)據(jù)的某些bit位。例如,假設(shè)有變量聲明語句: shortinta=32767;在二進制文件中,變量a僅占2個字節(jié)的存儲空間,如圖9-3所示。圖9-31、文本文件與二進制文件
圖9-4而把變量a的值存入到文本文件中則需要5個字節(jié)的存儲空間,如圖9-4所示。例如,假設(shè)有變量聲明語句: shortinta=32767;1、文本文件與二進制文件
另外,文本文件還有以下特性:文本文件分為若干行。文本文件的每一行通常以一兩個特殊字符結(jié)尾,在Windows中,行末的標(biāo)記是回車符與換行符。文本文件可以包含一個特殊的“文件末尾”標(biāo)記。一些操作系統(tǒng)允許在文本文件的末尾使用一個特殊的字節(jié)作為標(biāo)記。在Windows中,標(biāo)記為'\x1a'(Ctrl+Z)。1、文本文件與二進制文件
2、緩沖文件與非緩沖文件
C語言中可使用以下兩種文件系統(tǒng):緩沖文件系統(tǒng),又稱為標(biāo)準(zhǔn)文件系統(tǒng)或高級文件系統(tǒng)。是一種高效、方便且常用的文件系統(tǒng)。后面要學(xué)習(xí)的文件操作函數(shù)都是基于緩沖文件系統(tǒng)的。非標(biāo)準(zhǔn)緩沖文件系統(tǒng),又稱低級文件系統(tǒng)。該系統(tǒng)與機器有關(guān),節(jié)省內(nèi)存,執(zhí)行效率高,但是應(yīng)用難度大。圖9-5文件緩沖區(qū)工作原理9.2.3文件指針stdio.h中定義了文件結(jié)構(gòu)體類型FILE。typedefstruct{ shortlevel; /*緩沖區(qū)‘滿’或‘空’的程度*/ unsignedflags; /*文件狀態(tài)標(biāo)志*/ charfd; /*文件描述符*/ unsignedcharhold; /*如無緩沖區(qū)不讀字符*/ shortbsize; /*緩沖區(qū)的大小*/ unsignedchar*buffer; /*數(shù)據(jù)緩沖區(qū)的位置*/ unsignedchar*curp; /*指針當(dāng)前的指向*/ unsignedistemp; /*臨時文件指示器*/ shorttoken; /*用于有效性檢查*/}FILE; C語言中對流的訪問是通過文件指針實現(xiàn)的,文件指針的類型為FILE*。用文件指針表示特定的流具有標(biāo)準(zhǔn)的名字,如stdin、stdout和stderr等;我們可以根據(jù)程序需要聲明一些另外的文件指針。例如:FILE*fp1,*fp2;定義了兩個文件指針fp1和fp2??梢酝ㄟ^文件打開函數(shù)將文件指針連接到指定的文件上。文件的打開與關(guān)閉9.39.3.1文件的打開1、fopen函數(shù)打開文件要使用庫函數(shù)fopen(),其函數(shù)原型為:FILE*fopen(constchar*filename,constchar*mode);fopen函數(shù)返回一個文件指針。例如:fp=fopen("in.dat","r");fp=fopen("d:\\cprogram\\test.c","r");為何要用\\注意:當(dāng)打開的文件不存在或建立新文件時沒有訪問權(quán)限等將導(dǎo)致無法打開文件,此時fopen函數(shù)會返回空指針。因此打開文件后要測試fopen函數(shù)返回值以確保文件是否被正確打開。2、讀寫模式模式字符串含義"r"或"rt"打開文本文件用于讀"rb"打開二進制文件用于讀"w"或"wt"打開文本文件用于寫(文件不需要存在)"wb"打開二進制文件用于寫(文件不需要存在)"a"或"at"打開文本文件用于追加(文件不需要存在)"ab"打開二進制文件用于追加(文件不需要存在)"r+"或"rt+"打開文本文件用于讀和寫,從文件頭開始"rb+"打開二進制文件用于讀和寫,從文件頭開始模式字符串含義"w+"或"wt+"打開文本文件用于讀和寫(如果文件存在就覆蓋原文件)"wb+"打開二進制文件用于讀和寫(如果文件存在就覆蓋原文件)"a+"或"at+"打開文本文件用追加方式進行讀和寫"ab+"打開二進制文件用追加方式進行讀和寫2、讀寫模式9.3.2文件的關(guān)閉C語言使用fclose函數(shù)來關(guān)閉已打開的文件。其函數(shù)原型如下:intfclose(FILE*filename);其中filename是文件指針,指向已打開的文件。9.3.2文件的關(guān)閉文件檢測函數(shù)9.49.4.1檢測文件末尾函數(shù)feof()函數(shù)用來檢測文件讀寫位置指針是否已到文件末尾。feof()的調(diào)用格式為:feof(fp);fp是文件指針,如果文件讀寫位置指針已到文件末尾,則函數(shù)返回非0值(邏輯真);否則函數(shù)返回0值(邏輯假)。例如,我們常用下面的語句來控制文件讀寫:
while(!feof(fp))
文件讀/寫語句;9.4.1檢測文件末尾函數(shù)9.4.2檢測出錯函數(shù)ferror()函數(shù)可用來檢測輸入輸出函數(shù)的每次調(diào)用是否有錯,函數(shù)的調(diào)用格式是:ferror(fp)正常時函數(shù)返回0值,出錯時函數(shù)返回非值(邏輯真)。一般在調(diào)用輸入輸出函數(shù)后可調(diào)用該函數(shù),以檢查輸入輸出函數(shù)的引用是否正確。例如:
文件讀寫語句; if(ferror(fp)) printf("文件讀寫錯誤!\n");9.4.2檢測出錯函數(shù)文件的讀寫操作9.59.5.1字符讀/寫函數(shù)1、字符讀函數(shù)fgetc()該函數(shù)用來從文件讀取一個字符,其函數(shù)原型為:intfgetc(FILE*fp);從fp讀出一個字符,將位置指針指向下一個字符,若讀成功,則返回該字符;若讀到文件尾,則返回EOF。常見的用法:while(!feof(fp)) {ch=fgetc(fp); … }
對文本文件還可以用以下的形式來判斷文件是否已讀到文件末尾。while((ch=fgetc(fp))!=EOF) …9.5.1字符讀/寫函數(shù)2、字符寫函數(shù)fputc()該函數(shù)用來將一個字符寫入文件。其函數(shù)原型為:intfputc(intch,FILE*fp);其中,ch是字符常量或字符變量,fp是文件指針。該語句的功能是把字符ch寫入到fp所指向的文件中;如果函數(shù)執(zhí)行成功,則返回ch;否則,返回EOF。例如:fputc('A',fp);
將大寫字母'A'寫入fp指示的文件中。9.5.2字符讀/寫函數(shù)應(yīng)用實例【例9.1】編寫一個程序,將從鍵盤輸入若干行字符串存入9_1.txt文件,并將文件中的內(nèi)容重新讀出顯示到屏幕上(以'#'作為輸入結(jié)束標(biāo)志)。【分析】可首先將鍵盤上輸入的若干文本行寫入文件,再重新以只讀方式打開文件,將其內(nèi)容讀出后顯示在屏幕上。#include<stdio.h>intmain(){charch;FILE*fp;
fp=fopen("9_1.txt","w"); //以寫方式打開文本文件if(fp!=NULL){printf("請輸入若干行文本,以#結(jié)束輸入:\n");while((ch=getchar())!='#')//循環(huán)寫入fputc(ch,fp);fclose(fp);}elseprintf("文件創(chuàng)建失??!\n");fp=fopen("9_1.txt","r"); //以讀方式打開文本文件if(fp!=NULL){printf("文件內(nèi)容是:\n");while(!feof(fp)) //循環(huán)讀出{ch=fgetc(fp);putchar(ch); //可用fputc(ch,stdout)代替putchar(ch)}fclose(fp); //關(guān)閉文件}elseprintf("文件打開失?。n");return0;}請輸入若干行文本,以#結(jié)束輸入:
TeachyouhowtoreadCprograms↙TeachyouhowtowriteCprograms↙TeachyouhowtodebugCprograms#↙文件內(nèi)容是:TeachyouhowtoreadCprogramsTeachyouhowtowriteCprogramsTeachyouhowtodebugCprograms9.5.3字符串讀/寫函數(shù)函數(shù)fgets和fputs分別用于從指定的文件中讀出一個字符串和把一個字符串寫入指定的文件。1、字符串讀函數(shù)fgets()函數(shù)fgets可以從指定文件中讀入一行字符串并存入到字符數(shù)組中。其函數(shù)原型為:char*fgets(char*s,intn,FILE*fp);
例如,若字符數(shù)組s的大小為20,則:fgets(s,20,fp);
從fp指向的文件中讀取最大長度為19的字符串存入s。
利用這一特性,我們可以用:fgets(s,sizeof(s),stdin);
來限定從鍵盤輸入的字符串的大小,這比直接用gets(s)函數(shù)要安全,可以防止輸入數(shù)據(jù)過長而導(dǎo)致非法訪問內(nèi)存。2、字符串寫函數(shù)fputs()函數(shù)fputs可以將一個字符串寫入指定的文件,其函數(shù)原型為:intfputs(constchar*s,FILE*fp);9.5.4字符串讀/寫函數(shù)應(yīng)用實例【例9.2】從鍵盤輸入一行字符串:“TeachyouhowtodesigngoodCprograms”,將其追加到text01.txt文本中去。【分析】因要向text01.txt中追加信息,所以應(yīng)該將其打開方式設(shè)置為a。#include<stdio.h>#defineN80intmain(){chars[N];FILE*fp;
fp=fopen("text01.txt","a");if(fp!=NULL){printf("請輸入一行文本:\n");fgets(s,N,stdin); //從鍵盤輸入字符串fputs(s,fp); //寫入文件fclose(fp); //關(guān)閉文件}elseprintf("文件打開失?。n");}9.5.5格式化讀/寫函數(shù)1、格式化讀函數(shù)fscanf()fscanf的函數(shù)原型為:intfscanf(FILE*fp,constchar*format,變量地址列表);如果函數(shù)執(zhí)行成功,則返回正確輸入項的個數(shù);若執(zhí)行失敗,則返回0。例:
fscanf(fp,"%s%d",name,&age);2、格式化寫函數(shù)fprintf()fprintf的函數(shù)原型為:intfprintf(FILE*fp,constchar*format,輸出項列表);例如:fprintf(fp,"%12s%6d",name,age);將字符串name和整型變量age的值存入fp指向的文件。9.5.6格式化讀/寫函數(shù)應(yīng)用實例【例9.3】為例8.5中的程序設(shè)計從文件讀數(shù)據(jù)的函數(shù)和將學(xué)生數(shù)據(jù)存盤的函數(shù)。(1)增加從文件讀數(shù)據(jù)函數(shù)intreadData(stuStrus[],char*filename),從文件filename中讀入學(xué)生信息,存入學(xué)生數(shù)組s,函數(shù)返回讀取的學(xué)生人數(shù);(2)增加函數(shù)voidsaveData(stuStrus[],char*filesname,intn),將學(xué)生信息存入filename文件。數(shù)據(jù)格式:可以通過feof函數(shù)來判斷對文件的讀寫是否到達文件末尾。/*@函數(shù)名稱:readData入口參數(shù):stuStrus[],char*filename@函數(shù)功能:從文件filename讀入學(xué)生信息存入s,返回正確讀取的學(xué)生人數(shù)*/intreadData(stuStrus[],char*filename){FILE*fp;fp=fopen(filename,"r");if(fp!=NULL){intn=0,i;while(!feof(fp)){fscanf(fp,"%s",s[n].id); //讀入準(zhǔn)考證號fscanf(fp,"%s",s[n].name); //讀入姓名for(i=0;i<4;i++) //讀入4門課程成績fscanf(fp,"%f",&s[n].score[i]);n++;}fclose(fp);returnn; //返回有效學(xué)生人數(shù)}elsereturn0;}/*@函數(shù)名稱:saveData入口參數(shù):stuStrus[]char*filename,intn@函數(shù)功能:學(xué)生信息存盤函數(shù)*/voidsaveData(stuStru*s,char*filename,intn){FILE*fp;inti,j;fp=fopen(filename,"w");if(fp!=NULL){for(i=0;i<n;i++,s++){fprintf(fp,"%-12s",s->id); //輸出準(zhǔn)考證號fprintf(fp,"%-12s",s->name); //輸出姓名for(j=0;j<4;j++) //輸出成績fprintf(fp,"%-8.2f",s->score[j]);fprintf(fp,"%-8.2f\n",s->total);//輸出總分}fclose(fp);//關(guān)閉文件}elseprintf("文件保存失敗!\n");}intmain(){stuStrus[N];intn;n=readData(s,"studata.txt"); //從文件讀數(shù)據(jù)sum(s,n); //求和quickSort(s,0,n-1); //按總分由高到低排序print(s,n); //輸出saveData(s,"9_3.txt",n); //存盤return0;}準(zhǔn)考證號姓名語文數(shù)學(xué)英語綜合總分-----------------------------------------------------------------------------110100105楊婷130.00132.00128.00256.00646.00110100104劉潔121.00105.00130.00250.00606.00110100102李科108.00130.00125.00241.00604.00110100101王曉東112.00120.00121.00230.00583.00110100103趙國慶99.0098.00101.00200.00498.009.5.7數(shù)據(jù)塊讀/寫函數(shù)1、數(shù)據(jù)塊讀函數(shù)fread()fread函數(shù)用于從文件中讀出一個數(shù)據(jù)塊,其函數(shù)原型為:unsignedfread(void*buffer,unsignedsize,unsignedcount,FILE*fp);fwrite函數(shù)用于向文件寫入一個數(shù)據(jù)塊,其函數(shù)原型為:unsignedfwrite(constvoid*buffer,unsignedsize,unsignedcount,FILE*fp);2、數(shù)據(jù)塊寫函數(shù)fwrite()例9.3中的saveData函數(shù)對每一個學(xué)生數(shù)據(jù),是采用逐個數(shù)據(jù)項的方式來輸出到文件中的,這種方式的優(yōu)點是文件中的數(shù)據(jù)按固定的格式呈現(xiàn),便于用戶用記事本直接瀏覽,但操作的效率較低。采用fwrite()函數(shù)一次性將學(xué)生結(jié)構(gòu)體數(shù)組的n個元素寫入文件具有較高的存取效率。但該函數(shù)寫入數(shù)據(jù)時是將內(nèi)存數(shù)據(jù)塊直接寫入文件,因此宜采用二進制文件為宜。同時應(yīng)注意,用fwrite()寫入文件的數(shù)據(jù)應(yīng)該用fread()函數(shù)按相應(yīng)地格式來進行讀取,才能正確的還原數(shù)據(jù)。9.5.8數(shù)據(jù)塊讀/寫函數(shù)應(yīng)用實例(1)wirteToFile函數(shù),采用fwrite函數(shù)保存學(xué)生數(shù)據(jù)至文件。(2)readFromFile函數(shù),采用fread函數(shù)從文件讀入學(xué)生數(shù)據(jù)至某學(xué)生結(jié)構(gòu)體數(shù)組,并將結(jié)果顯示到屏幕上?!纠?.4】為例9.3的程序設(shè)計函數(shù):voidwriteToFile(stuStrus[],char*filename,intn){FILE*fp;fp=fopen(filename,"wb"); //打開文件if(fp!=NULL){ fwrite(s,sizeof(stuStru),n,fp); //寫文件 fclose(fp);}elseprintf("文件保存失??!\n");}/*@函數(shù)名稱:readFromFile入口參數(shù):stuStrus[]char*filename@函數(shù)功能:從文件filename讀入學(xué)生信息存入s,返回正確讀取的學(xué)生人數(shù)*/intreadFromFile(stuStrus[],char*filename){FILE*fp;intn=0,k;fp=fopen(filename,"rb");//打開文件if(fp!=NULL){while(1){k=fread(s+n,sizeof(stuStru),1,fp);//讀取一條記錄if(k!=1)break;//未讀取成功表明文件已結(jié)束n++;}returnn; //返回成功讀取的記錄總數(shù)fclose(fp);}else{printf("讀取數(shù)據(jù)失??!\n"); return0;}}intmain(){stuStrus[N],t[N];intn;n=readData(s,"studata.txt"); //從文件讀數(shù)據(jù)sum(s,n); //求和quickSort(s,0,n-1); //按總分由高到低排序writeToFile(s,"9_4.dat",n); //存盤n=readFromFile(t,"9_4.dat"); //讀取數(shù)據(jù)存入數(shù)組tprint(t,n); //輸出學(xué)生數(shù)據(jù)return0;}文件的隨機讀寫9.69.6文件的隨機讀寫按讀寫方式分為:順序文件與隨機文件。順序文件是指只能按順序讀寫的文件,如存儲在磁帶上的文件就是順序文件。隨機文件是指可以隨機讀寫文件任意位置內(nèi)容的文件,如存儲在磁盤、DVD等介質(zhì)上的文件大部分都為隨機文件。9.6.1文件的定位文件定位有關(guān)的函數(shù):fseek函數(shù)ftell函數(shù)rewind函數(shù)1、fseek函數(shù)fseek函數(shù)的作用是使文件讀寫位置指針移動到所需要的位置,它的調(diào)用方式為:fseek(文件指針,位移量,起始點);符號名值含義SEEK_SET0文件開頭SEEK_CUR1文件當(dāng)前位置SEEK_END2文件末尾例如,若fp為指向例9.4的學(xué)生排序結(jié)果文件(9_4.dat)的指針,則:fseek(fp,sizeof(stuStru)*2,SEEK_SET);
表示將文件讀寫位置指針從文件開頭向前移動2個記錄的位置,即定位在第3個學(xué)生記錄的起始位置。1、fseek函數(shù)fseek(fp,-sizeof(stuStru)*2,SEEK_END);表示將文件讀寫位置指針從文件末尾向后移動2個記錄的位置,即定位到倒數(shù)第2個學(xué)生記錄的起始位置。注意:fseek()函數(shù)一般用于二進制文件的隨機讀寫。1、fseek函數(shù)2、ftell函數(shù)ftell()函數(shù)用于返回文件讀寫位置指針相對于文件頭的字節(jié)數(shù),其值為long類型,出錯時返回-1。其調(diào)用格式為:ftell(fp);例如:longpostion;if((postion=ftell(fp))==-1L) printf("Afileerrorhasoccurredat%ld.\n",postion);用于通知用戶文件出錯的位置。2、ftell函數(shù)3、rewind函數(shù)使用rewind()函數(shù)可使文件讀寫位置指針重新返回文件的開頭處。調(diào)用格式為:rewind(fp);9.6.2文件隨機讀寫應(yīng)用實例【例9.5】例9.4程序?qū)W(xué)生排序的數(shù)據(jù)存入了二進制文件9_4.dat,編寫程序從文件中由后向前讀取學(xué)生數(shù)據(jù)輸出到屏幕上,并將其結(jié)果保存到二進制文件9_5.dat?!痉治觥靠梢圆捎胒seek()函數(shù)實現(xiàn)從文件末尾向文件頭方向依次讀取數(shù)據(jù)存入內(nèi)存結(jié)構(gòu)體數(shù)組,之后調(diào)用print()函數(shù)輸出。/*@函數(shù)名稱:readFromFile入口參數(shù):stuStrus[],char*filename@函數(shù)功能:從文件filename讀入學(xué)生信息存入s,返回正確讀取的學(xué)生人數(shù)*/intreadFromFile(stuStrus[],char*filename){FILE*fp;intn=0,k;fp=fopen(filename,"rb");//打開文件if(fp!=NULL){fseek(fp,-sizeof(stuStru),SEEK_END);while(1){k=fread(s+n,sizeof(stuStru),1,fp);//讀取一條記錄if(k!=1)break;//未讀取成功表明文件已結(jié)束n++;
fseek(fp,-2*sizeof(stuStru),SEEK_CUR);}returnn;//返回成功讀取的記錄總數(shù)fclose(fp);}else{ printf("讀取數(shù)據(jù)失?。n"); return0; }}intmain(){stuStrus[N];intn;n=readFromFile(s,"9_4.dat");//讀取數(shù)據(jù)存入數(shù)組sprint(s,n); //輸出學(xué)生數(shù)據(jù)writeToFile(s,"9_5.dat",n); //將結(jié)果保存到9_5.datreturn0;}【例9.6】例9.5程序已將按總分遞增的學(xué)生數(shù)據(jù)存入二進制文件9_5.dat中,編寫一個程序,將屬性為{"110100106","柯男",121,130,99,215,565}的學(xué)生數(shù)據(jù)追加到文件末尾,并重新讀取學(xué)生信息后輸出到屏幕上?!痉治觥恳蛞芳佑涗浀轿募?,且對該文件寫完之后需要讀取數(shù)據(jù),因此打開模式應(yīng)設(shè)置為ab+。添加記錄后使用rewind()函數(shù)將文件讀寫指針重新定位到文件頭。#include<stdio.h>#defineN10000structstudent{charid[10]; //準(zhǔn)考證號charname[9]; //姓名floatscore[4]; //大小為4的數(shù)組,分別存儲4門課程分數(shù)floattotal; //總分};typedefstructstudentstuStru;intmain(){stuStrus={"110100106","柯男",121,130,99,215,565};stuStrut;FILE*fp;intk,j;fp=fopen("9_5.dat","ab+");
if(fp!=NULL){fwrite(&s,sizeof(s),1,fp); //將學(xué)生s寫入文件rewind(fp); //重新回到文件頭部printf("%-12s%-12s","準(zhǔn)考證號","姓名"); //輸出表頭printf("%-8s%-8s%-8s%-8s%-8s\n","語文","數(shù)學(xué)","英語","綜合","總分");printf("--------------------------------------------------------\n");
while(1){k=fread(&t,sizeof(t),1,fp); //讀取一條記錄if(k!=1)break; //未讀取成功表明文件已結(jié)束printf("%-12s",t.id); //輸出準(zhǔn)考證號printf("%-12s",); //輸出姓名for(j=0;j<4;j++) //輸出成績printf("%-8.2f",t.score[j]);printf("%-8.2f\n",t.total); //輸出總分} fclose(fp); //關(guān)閉文件}else printf("文件打開失敗!");return0;}準(zhǔn)考證號姓名語文數(shù)學(xué)英語綜合總分-------------------------------------------------------------------------------110100103趙國慶99.0098.00101.00200.00498.00110100101王曉東112.00120.00121.00230.00583.00110100102李科108.00130.00125.00241.00604.00110100104劉潔121.00105.00130.00250.00606.00110100105楊婷130.00132.00128.00256.00646.00110100106柯男121.00130.0099.00215.00565.00【例9.7】(選讀)編寫一個程序,將256色的bmp位圖順時針旋轉(zhuǎn)180度存到另一個文件?!痉治觥恳帉懺摮绦?,首先要了解256色bmp位圖格式。256色bmp位圖包括4個部分,一個位圖文件頭,一個位圖信息頭,一個色表和位圖數(shù)據(jù)本身。位圖文件頭包含關(guān)于這個文件的信息,如從哪里開始是位圖數(shù)據(jù)的定位信息。位圖信息頭含有關(guān)于這幅圖像的信息,例如以象素為單位的寬度和高度。色表中有圖像顏色的RGB值。這三部分共占用文件的前1078個字節(jié),之后的內(nèi)容為位圖數(shù)據(jù)。因此,可以先將源文件的前1078個字節(jié)復(fù)制到目標(biāo)文件,再將之后的文件內(nèi)容從后向前復(fù)制到目標(biāo)文件。從而實現(xiàn)圖像順序時針180度旋轉(zhuǎn)。#include<stdio.h>intmain(intargc,char*argv[]){inti;charc;FILE*fp1,*fp2;if(argc!=3)exit(1);fp1=fopen(argv[1],"rb");
fp2=fopen(argv[2],"wb");第一個命令行參數(shù)為源文件第二個命令行參數(shù)為目標(biāo)文件if(fp1==NULL||fp2==NULL)exit(1);for(i=0;i<1078;i++) //復(fù)制文件頭信息{c=fgetc(fp1);fputc(c,fp2);}
fseek(fp1,-1,SEEK_END);
將文件讀寫位置指針定位到最后一個字節(jié)將位圖信息從后向前復(fù)制到目標(biāo)文件從文件末尾向文件頭移動while(ftell(fp1)>1077) { c=fgetc(fp1); fputc(c,fp2);
fseek(fp1,-2,SEEK_CUR);
} fclose(fp1); fclose(fp2); return0;}編譯后產(chǎn)生9_7.exe文件,設(shè)當(dāng)前文件夾下存有如圖9-8所示的位圖文件(文件名為:rabbit.bmp)在命令行下輸入:>9_7rabbit.bmprabbit2.bmp利用位運算
對文件數(shù)據(jù)加密9.79.7利用位運算對文件數(shù)據(jù)加密9.7.1位運算1、移位運算a<<b的值是將a中的位左移b位后的結(jié)果。每次從a的左端移出一位,在a的右端補一個0。a>>b則是將a中的位右移b位的結(jié)果。如果a是無符號數(shù)或非負數(shù),則右移時會在a的左端補0。如果a是負值,其結(jié)果依賴于編譯器,一些編譯器會在左端補0,而有些則會保留補碼的符號位而補1。因此,考慮到程序的可移植性,最好僅對無符號數(shù)或字符進行移位運算。例如:unsignedshorta=56,b,c;初始時,a的值為(二進制形式):執(zhí)行b=a<<2;語句后,b的值為:執(zhí)行c=a>>1;語句后,c的值為:2、按位求反、按位與、按位或與按位異或運算按位求反、按位與、按位或與按位異或四個運算符分別為:~、&、|和^。例如: unsignedshorta=19,b=67,c;初始時a與b的值分別為:執(zhí)行c=~a;后,c的值為:執(zhí)行c=a&b;后,c的值為:執(zhí)行c=a|b;后,c的值為:執(zhí)行a=a^b;后,a的值為:再次執(zhí)行a=a^b;后,a的值重新回到原值??梢?,將變量連續(xù)與同一個數(shù)進行兩次異或運算后,可以將該數(shù)還原。9.7.2數(shù)據(jù)文件加密實例【例9.7】編寫程序?qū)τ脩裘懊艽a進行加密后存入文件,并模擬用戶登錄系統(tǒng)的驗證過程。#include<stdio.h>#include<stdlib.h>#include<string.h>/*@函數(shù)名稱:set入口參數(shù):charusername[],charpassword[],char*filename@函數(shù)功能:設(shè)置系統(tǒng)密碼*/voidset(charusername[],charpassword[],char*filename){FILE*fp;fp=fopen(filename,"w");inti;charuser[11];charpass[7];strcpy(user,username);strcpy(pass,password);if(fp!=NULL){i=0;while(user[i]){user[i]=user[i]^0x5a;i++;}i=0;
username加密while(pass[i]){pass[i]=pass[i]^0xb4;i++;}fprintf(fp,"%s\n",user);fprintf(fp,"%s\n",pass);fclose(fp);}}password加密/*@函數(shù)名稱:readFile入口參數(shù):charusername[],charpassword[],char*filename@從文件中讀取用戶名與密碼*/voidreadFile(charusername[],charpassword[],char*filename){FILE*fp;inti;fp=fopen(filename,"r");if(fp!=NULL){ fscanf(fp,"%s",username); fscanf(fp,"%s",password); i=0;while(username[i]){username[i]=username[i]^0x5a;i++;}
溫馨提示
- 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. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年茶葉電商平臺入駐與推廣合同范本4篇
- 二零二五年度留學(xué)國際交流項目合作協(xié)議4篇
- 二零二四年機械設(shè)備吊裝工程合同2篇
- 二零二五年度產(chǎn)學(xué)研合作項目質(zhì)量監(jiān)督及驗收協(xié)議3篇
- 二零二五年度歷史建筑保護修繕承包合同4篇
- 二零二五年度藝術(shù)展覽館租賃承包協(xié)議4篇
- 二零二五年度智慧環(huán)保產(chǎn)業(yè)PPP合作框架協(xié)議2篇
- 專項:2024流行音樂巡演票務(wù)總代理協(xié)議版
- 二零二四年生日蛋糕卡會員積分兌換合同范本3篇
- 2025版夏令營活動學(xué)員意外傷害保險合同3篇
- 河南省濮陽市2024-2025學(xué)年高一上學(xué)期1月期末考試語文試題(含答案)
- 割接方案的要點、難點及采取的相應(yīng)措施
- 2025年副護士長競聘演講稿(3篇)
- 2024年08月北京中信銀行北京分行社會招考(826)筆試歷年參考題庫附帶答案詳解
- 原發(fā)性腎病綜合征護理
- (一模)株洲市2025屆高三教學(xué)質(zhì)量統(tǒng)一檢測 英語試卷
- 蘇教版二年級數(shù)學(xué)下冊全冊教學(xué)設(shè)計
- 職業(yè)技術(shù)學(xué)院教學(xué)質(zhì)量監(jiān)控與評估處2025年教學(xué)質(zhì)量監(jiān)控督導(dǎo)工作計劃
- 金字塔原理與結(jié)構(gòu)化思維考核試題及答案
- 基礎(chǔ)護理學(xué)導(dǎo)尿操作
- DB11∕T 1028-2021 民用建筑節(jié)能門窗工程技術(shù)標(biāo)準(zhǔn)
評論
0/150
提交評論