文件的基本操作http://jpkc.nwu.edu.cn/jsjjc/ebooks/p12.htm

 

第12章  文件的基本操作

在實際應用中,大量的信息不可能每次都從鍵盤輸入,而一般都是以文件的形式存儲在外存上。此外,有時還需要保存計算機的處理結果,需要在外存上做永久性的保存,而不是簡單地在顯示器上顯示。所有這些操作都和文件的處理有關。

因此,本章主要以磁盤文件爲主,介紹Turbo C 2.0提供的基本文件操作函數。

12.1  文件操作的引入

現在,有這樣一個問題需要解決:有10個人合作寫某一軟件的說明書,每人各寫一部分,而且每部分最終要合在一起以一個文本文件的形式存放在計算機中。需要編寫一個程序將這10個文本文件連接在一起,形成一個具有全部內容的文本文件。

對於這一問題,該如何解決呢?

以前,大家已經學習了C語言的基本輸入/輸出函數,通過C語言的基本輸入/輸出函數(如scanf()、printf()、getchar()、putchar()、gets()、puts()等)可以很方便地進行信息的輸入/輸出,從而可以解決一些基本的輸入/輸出問題。

但對於該問題,以前的解決方法顯然不能滿足要求。爲了解決此類問題,C語言提供了文件操作函數。

12.2  文件的基本概念

所謂“文件”,一般指存儲在外部介質上的有組織的數據集合。

數據只有以一種永久性的方式存放起來才能在需要時被方便地訪問。在計算機中,數據可以永久性地存儲在軟盤、硬盤、光盤這樣的設備上,此時,操作系統就會在這些設備上爲存儲的數據分配足夠大的空間。存儲數據的目的是爲了以後能夠讀取文件內容,所以系統允許用戶爲所分配的存儲區域指定名字(文件名),並將數據寫到這些區域中。其實,這些存儲在存儲介質上的特定區域裏的信息的集合就是文件。

以前學習到的輸入和輸出,都是暫時性的輸入與輸出,即在應用程序運行時,從鍵盤輸入數據,運行結果在顯示器上顯示。當應用程序終止時,這些數據將全部消失。但在實際的程序運行中,常常需要將一些數據(運行的最終結果或中間數據)輸出到外存上存儲起來,以後需要時再從外存輸入到計算機內存,所有這些都需要通過磁盤文件來完成。

12.2.1  C語言支持的文件格式

C語言支持的是流式文件,它把文件看做由一個一個的字符(字節)數據組成的序列。根據數據的組織和操作形式,可分爲ASCII文件和二進制文件。

 

1.ASCII文件

ASCII文件又稱爲文本文件,它是在一個字節的存儲單元上存放一個字符(在外存上存放的是該字符的ASCII碼,每個字符將佔一個字節)。

例如:存儲ABC,它將在外存上佔3個存儲單元,用來存放010000010100001001000011。其中,01000001爲A的ASCII碼,01000010爲B的ASCII碼,01000011爲C的ASCII碼。每個ASCII碼佔據8位。如圖12.1所示。

圖12.1  ABC的ASCII文件存放方式

又如:有一個整數257,在內存中佔2個字節(0000000100000001),如果按ASCII形式輸出,它將在外存上佔3個字節,用於存放每一位數字的ASCII碼。如圖12.2所示。

圖12.2  257的ASCII文件存放方式

2.二進制文件

二進制文件是把內存中的數據按其在內存中的存儲格式在磁盤上原樣保存。

例如:有一個整數257,在內存中佔2個字節(0000000100000001),如圖12.3所示,所以按二進制格式輸出時,在外存上也只佔2個字節,如圖12.4所示。

  

         圖12.3  257在內存中的表現方式               圖12.4  257的二進制文件存放方式

對字符而言,由於其外存存儲格式和內存表示格式相同,所以,在外存上也存放每個字符的ASCII碼,以ABC的存儲爲例,如圖12.5所示。

圖12.5  ABC的二進制文件存放方式

3.兩種存儲格式的區別

用ASCII碼格式存儲文件,一個字節代表一個字符,便於對字符進行逐個處理,也便於輸出字符。但佔較多存儲空間,而且要花費一些時間進行轉換(二進制碼與ASCII碼間的轉換)。

用二進制格式存儲文件,可以節省外存空間和轉換時間,但字節並不與字符對應,不能直接輸出字符形式。

在實際的軟件開發中,中間結果數據一般都需要暫時保存在外存上以便以後使用,在這種情況下,常用二進制文件方式進行保存。

注意:① 在C語言中,一個文件是一個字節流或二進制流。它把數據看做是一連串不考慮記錄界限的字符(字節)。② 在C語言中,對文件的存取是以字符(字節)爲單位的,數據輸入/輸出的開始和結束僅受程序控制而不受物理符號(如回車換行符)控制,這種文件被稱爲流式文件。

12.2.2  緩衝文件系統

ANSI C採用緩衝文件系統,它既可用於處理文本文件,又可用於處理二進制文件。

1.緩衝文件系統

所謂“緩衝文件系統”,是指系統自動地在內存區爲每一個正在使用的文件開闢一個緩衝區,從內存向磁盤輸出數據必須先送到內存中的緩衝區(用戶寫文件由用戶調用相關函數完成),緩衝區被充滿後數據才被一併輸出到磁盤中(系統寫文件由系統自動完成);如果從磁盤向內存讀取數據,則一次從磁盤文件將一批數據輸入到內存緩衝區,然後從緩衝區逐個地將數據輸送到程序數據區(存入程序變量)。緩衝區的大小由各個具體的C語言版本確定,一般爲512字節。其工作過程如圖12.6所示。

圖12.6  緩衝文件系統工作原理

2.標準級文件讀/寫

在C語言中,沒有提供輸入/輸出語句,所有輸入/輸出都是通過函數實現的,對文件的讀/寫也是通過庫函數實現的。

對文件處理有兩級方法:即標準級和系統級。

所謂標準級,就是這些函數更符合C語言的普通標準,與其他機器上的C語言更兼容,更容易移植到其他機器、操作系統上。對程序員來說,標準級函數更高級,也更容易使用,功能更強。另外,它支持文件緩衝系統,磁盤存取次數較少,效率更高。

在使用標準級函數時,經常把被操作的文件看做是一個字符流。所以標準級函數有時也被稱爲流式輸入/輸出函數。

所謂系統級,是指這些函數往往直接調用操作系統,正因爲如此,系統級函數速度更快,內存佔用更少,但兼容性更差。

對程序員來說,系統級函數使用起來比較困難,對操作系統的依賴性較強,它們功能交叉,沒有自動緩衝能力,也沒有格式輸入/輸出的能力,且移植性較差。

標準級函數有時被錯誤地理解爲只提供流式輸入/輸出,即把文件看做字符流或字符序列。雖然大部分情況下它們是這樣被使用的,但這些函數的功能卻不只這些。例如,可以通過標準級函數進行格式化的輸入/輸出,可以對文件進行隨機存取,也可以按塊或按記錄方式對文件進行存取。

12.2.3  文件操作的基本思路

進行文件操作的基本思路如下:

(1)在文件進行讀/寫之前,首先使用庫函數fopen()打開該文件。fopen()的作用是建立文件和操作系統之間的連接,進行必要的通信(實現所謂對文件的按名操作),並返回一個在以後可以用於文件讀/寫操作的指針。

(2)文件被打開後,就要考慮使用哪種方式進行文件的讀/寫。其中以庫函數fgetc()和fputc()最爲簡單。fgetc()的作用是從文件讀取一個字符,然後將其存放到用戶自己定義的變量中;fputc()的作用是將一個字符寫到文件中。

(3)當對文件的操作完成後,就要使用庫函數fclose()關閉文件。關閉文件操作將釋放不再需要的文件指針,並能保證信息被完整地存儲。

12.3  文件基本操作

標準級函數有緩衝功能和安全保護功能,易於使用,然而使用它的最大好處還在於它的兼容性。

12.3.1  文件指針

1.FILE結構

標準級函數添加的許多功能都是由於它使用了FILE這個數據結構,每當打開一個文件進行標準輸入/輸出時,系統就建立了一個FILE結構,並返回一個指向這個結構的指針。對於隨後所有的操作,都以這個結構指針(下面稱爲文件指針,有時也稱爲文件流指針)爲基礎進行。

FILE數據結構:

 

typedef  struct

 {

  short             level;

  unsigned          flags;

  char              fd;

  unsigned char      hold;

  short             bsize;

  unsigned char      *buffer;

  unsigned char      *curp;

  unsigned          istemp;

  short             token;

}FILE;

 

FILE結構中的字段fd稱爲文件柄。因爲標準級的輸入/輸出操作支持緩衝區操作,假設開始時進行標準級的輸入,後來轉入系統級的輸入,等到再次使用標準級輸入時,緩衝區中的內容就可能不再和文件中的數據相一致。所以,不應混合使用系統級的文件柄和標準級的文件指針。

2.文件指針的定義

程序員不應直接存取FILE結構中的任何一個數據域,因爲它們僅供內部使用。這裏列出這個結構只是爲了方便讀者理解C語言是怎樣維護一個文件的。不同的C編譯系統可能定義了完全不同的結構,但其結構的名字可能仍然是FILE。

在文件的標準級操作過程中,可以通過文件指針來使用文件。

文件指針變量的定義如下:

 

FILE *文件指針;

 

例如:

 

FILE *fp;

 

定義fp是一個指向FILE類型結構體的指針變量。可以使fp指向某一文件的結構體變量,從而通過該結構體變量中的文件信息能夠訪問該文件。也就是說,通過文件指針變量能夠找到與它相關的文件。

如果有n個文件,一般應設n個文件指針變量(指向FILE類型結構體的指針變量),使它們分別指向n個文件(確切地說,指向該文件的信息結構體),以實現對文件的訪問。

12.3.2  文件的打開與關閉

在使用文件時,應該遵守文件的基本使用規則:先打開,再使用,最後關閉。

在讀/寫文件之前,應該首先打開該文件,然後再對其進行相應的讀/寫操作,當所需的操作完成後,關閉該文件。

文件的打開操作爲文件的使用做準備,它爲將要使用的文件創建相應的數據結構,並和相應的存儲空間發生聯繫。文件的關閉則是將文件的一些相關信息進行保存。

在文件操作完成時,如果沒有執行正確的文件關閉操作就可能造成文件相應信息的丟失,導致文件被損壞。因此,在使用文件時應正確地對文件進行打開和關閉操作。

1.文件的打開

ANSI C規定了標準輸入/輸出函數庫,用fopen()函數來實現打開文件。

fopen()函數的一般形式爲:

 

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

 

說明:文件名爲將要打開的文件的名字,可以帶路徑。如果是已經存在的文件,則文件應該爲全名,即包括其主文件名和擴展名。使用文件方式用於說明使用者對文件的操作方式。

在書寫路徑時注意路徑分隔符“\”的正確表示“\\”,勿使用雙反斜線“//”和反斜線“/”,這是程序員經常犯的一個錯誤。

例如:

 

FILE  *fp1,*fp2,*fp3;

fp1=fopen("abc", "r");

fp2=fopen ("d:\\mydoc\\stu.dat","r");

fp3=fopen("a1.txt","r");

 

表示以只讀方式打開文件abc、d:\mydoc\stu.dat和文件a1.txt。其中,fp1、fp2、fp3爲文件指針。可見,在打開一個文件時通知給編譯系統三個信息:需要打開的文件名、文件的使用方式、文件指針。文件的常見使用方式如表12.1所示。


表12.1  文件的常見使用方式

使用方式

文件不存在

文件已經存在

“r”

只讀

報告出現一個錯誤

打開、只讀一個文本文件

“w”

只寫

建立、打開、只寫一個文本文件

打開該文本文件,並使文件內容爲空,只寫

“a”

追加

建立和打開一個文本文件,只進行追加

打開一個文本文件,只向末尾進行追加

“rb”

只讀

報告出現一個錯誤

打開、只讀一個二進制文件

“wb”

只寫

建立、打開、只寫一個二進制文件

打開該二進制文件,並使文件內容爲空,只寫

“ab”

追加

建立和打開一個二進制文件,只進行追加

打開一個二進制文件,只向末尾進行追加

“r+”

讀/寫

報告出現一個錯誤

打開、讀和寫一個文本文件

“w+”

讀/寫

建立、打開一個文本文件,讀和寫

打開一個文本文件,並使文件內容爲空,讀和寫

“a+”

讀/寫

建立、打開一個文本文件、讀和追加

打開一個文本文件、讀和追加

“rb+”

讀/寫

報告出現一個錯誤

打開、讀和寫一個二進制文件

“wb+”

讀/寫

建立、打開一個二進制文件,讀和寫

打開一個二進制文件,並使文件內容爲空,讀和寫

“ab+”

讀/寫

建立、打開一個二進制文件、讀和追加

打開一個二進制文件、讀和追加

 

說明:

用“r”方式打開的文件只能讀而不能寫,且該文件應該已經存在,不能打開一個並不存在的文件,否則出錯。

用“w”方式打開的文件只能用於向該文件寫數據,而不能從該文件讀數據。如果原來不存在該文件,系統會新建立一個以指定名字爲文件名的新文件,並打開它。如果文件存在,則在打開時將該文件刪去,然後重新建立一個新文件。

③ 如果希望向文件末尾添加新的數據(不刪除原有數據),則應該用“a”方式打開。但此時該文件必須已存在,否則將得到出錯信息。打開時,文件位置指針移到文件末尾。

用“r+”、“w+”、“a+”方式打開文件時既可以讀也可以寫。用“r+”方式時,該文件必須已經存在,以便能向計算機輸入數據;否則出錯。用“w+”方式打開一個文件時,可以向文件中寫入數據,也可以從文件中讀出數據。用“a+”方式打開的文件不被刪去,位置指針移到文件末尾,可以添加也可以讀。

⑤ 如果無法打開一個文件,fopen()函數將會帶回一個出錯信息。出錯的原因可能是用“r”方式打開一個並不存在的文件;磁盤出故障;磁盤已滿無法建立新文件等。此時fopen()函數將帶回一個空指針值NULL(NULL在“stdio.h”文件中已被定義爲0)。

常用下面的方法打開一個文件:

 

if((fp=fopen("file","r"))==NULL)

 {

  printf("cannot open this file\n");

  exit(0);

}

 

先檢查打開是否出錯,如果出錯就在終端上輸出“cannot open this file”。exit函數的作用是關閉所有文件,終止正調用的過程。待程序員檢查出錯誤並修改後再運行。

2.文件的關閉

當一個文件使用結束時,應該關閉它,以防止其被誤用而造成文件信息的破壞和文件信息的丟失。從本質上講,“關閉”就是讓文件指針變量不再指向該文件,也就是文件指針變量與文件的聯繫斷開,此後不能再通過該指針對該文件進行讀/寫操作。除非再次打開,使該指針變量重新指向該文件。C語言中使用fclose()函數關閉文件。

fclose()函數的一般形式爲

 

fclose(文件指針);

 

例如:

 

fclose(fp);

 

該語句的作用是將fopen()函數打開文件時所帶回的指針賦給fp,用fclose()函數斷開它們之間的聯繫。

在程序終止之前關閉所有仍在使用的文件是我們應該遵守的基本規則,如果不關閉文件將會造成數據丟失。

因爲標準C支持緩衝文件系統,如果數據未充滿緩衝區而程序結束運行,系統會自動釋放其文件緩衝區,從而導致緩衝區中數據的丟失。用fclose()函數關閉文件,可以很好地解決和避免這個問題,它先把緩衝區中的數據輸出到磁盤文件,然後才釋放文件指針變量和緩衝區空間。

當然,fclose()函數也帶回一個值:當成功地執行了關閉操作,其返回值爲0;如果返回值爲非0,則表示關閉時有錯誤發生。

12.3.3  字節級的文件的讀/寫

所謂“字節級的文件讀/寫”,是指文件的讀/寫是以字節爲單位的。文件在打開之後,就可以進行信息的讀取與保存。常用的讀/寫函數有:fputc()函數和fgetc()函數。

1.文件位置指針

文件位置指針和文件指針是兩個不同的概念。文件位置指針用於表示當前正在讀/寫的數據在文件中的位置。當一個文件被打開後,文件位置指針總是指向文件的開始,即指向第一個數據。當其指向文件末尾時,表示文件結束。

在進行文件讀/寫時,總是從文件位置指針處開始進行讀/寫,當讀/寫完成之後,文件位置指針會自動後移。

當然,用戶也可以通過相應的庫函數來移動文件位置指針。

2.fputc()函數

fputc()函數的一般形式爲

 

int fputc(char ch , FILE *fp);

 

該函數的功能是將字符ch寫到fp對應的磁盤文件中。其中ch是需要輸出的字符,它可以是一個字符型數據,也可以是一個整數(對應的字符的ASCII碼值)。fp爲文件指針變量,它是使用fopen()函數後所得到的函數返回值。

fputc()函數也返回一個值:如果輸出成功則返回值就是輸出的字符;如果輸出失敗,則返回一個EOF。EOF是在“stdio.h”文件中定義的合法整數。

【例12.1】  從鍵盤讀入字符並存入文件,直到用戶輸入一個“#”符爲止。

分析  由於需要保存的是字符,所以需要創建一個文本文件。從鍵盤每輸入一個字符,便將其寫入文件,反覆輸入,直到輸入“#”符爲止。所輸入的字符就構成新文件的內容。

 

#include  "stdio.h"

main()

{

  char filename[20];

  FILE *fp;

  char  ch;

  scanf("%s",filename);

  if((fp=fopen(filename, "w"))==NULL)

  {

   printf("can't create the file\n");

   exit(0);

  }

  while((ch=getchar())!='#')

    fputc(ch,fp);

  fclose(fp);

}

3.fgetc()函數

fgetc()函數的一般形式爲

 

int fgetc(FILE *fp);

 

該函數的功能是從指定文件讀入一個字符,該文件必須是以讀或讀/寫方式打開的。

例如:

 

ch=fgetc(fp);

 

其中,fp爲文件指針變量,它和要讀取的文件相關聯。ch爲字符變量,fgetc()函數會返回一個字符,賦給ch(ch也可以是整型變量,此時是將fgetc()返回的字符的ASCII碼值賦予ch)。如果在執行fgetc()函數讀字符時遇到文件結束符,則函數返回一個文件結束標誌EOF。

【例12.2】  從一個磁盤文件順序讀入字符並在屏幕上顯示出來。

 

#include  "stdio.h"

main()

{

  FILE  *fp;

  char ch; 

  if((fp=fopen("d:\\my.dat","r"))==NULL)

   {

    printf("\n this file does not exit\n");

    exit(1);

   }

  while((ch=fgetc(fp))!=EOF)

    putchar(ch);

  fclose(fp);

}

 

注意:EOF是不可輸出字符,因此不能在屏幕上顯示。由於字符的ASCII碼不可能出現-1,因此EOF定義爲-1是合適的。當讀入的字符值等於EOF時,表示讀入的已不是正常的字符而是文件結束符,但這隻適用於對文本文件的讀/寫。

12.3.4  文件結束判斷函數

在二進制文件中,信息都是以數值方式存在的。EOF的值可能就是所要處理的二進制文件中的信息。這就出現了需要讀入有用數據卻被處理爲“文件結束”的情況。爲了解決這個問題,ANSI C提供了一個feof()函數,可以用它來判斷文件是否結束。

feof(fp)用於測試fp所指向的文件的當前狀態是否爲“文件結束”。如果是,函數feof(fp)的值爲1(真),否則爲0(假)。

如果想以正確的順序讀入一個文件(包括文本文件與二進制文件)中的數據,文件結束判斷就應該使用feof()函數。

例12.2的代碼可以修改爲

 

#include  "stdio.h"

main()

{

  FILE  *fp;

  int  ch;

  if((fp=fopen("d:\\my.dat","r"))==NULL)

   {printf("\n this file does not exit\n");

    exit(1);}

  while(!feof(fp))

   {ch=fgetc(fp);

    putchar(ch);}

  fclose(fp);

}

 

在文件的讀/寫過程中,當文件未結束時,feof(fp)的值爲0,循環繼續;當文件結束時,feof(fp)的值爲1,退出循環。

【例12.3】  編寫一個程序,完成文件的複製功能。

 

#include "stdio.h"

main()

{

  char sou_flise[20],targ_file[20];

  FILE  *d_in, *d_out;

  scanf("%s",sou_file);

  scanf("%s",targ_file);

  if((d_in=fopen(sou_file, "rb"))==NULL))

   {

      printf("Cannot open the source file \n");

      exit(0);

   }

  if((d_out=fopen(targ_file, "wb"))==NULL)

    {

      printf("\n Cannot create the targefile \n");

      exit(0);

    }

  while (!feof(d_in))

    fputc(fgetc(d_in),d_out);

  fclose(d_in);

  fclose(d_out);

}

 

【例12.4】  有兩個磁盤文件x和y,各存放一行字母,要求把這兩個文件中的信息合併(按字母順序排列),結果輸出到一個新文件z中。

分析  結果要求按字母順序保存,可以先將兩個文件中的內容讀到一個字符數組中,然後對字符數組中的內容進行排序,最後將排序結果寫入新文件即可。

 

#include "stdio.h"

void get_inf(FILE,*fp,char str[],int *n)         /*讀文件*/

{

  while(!feof(fp)) str[(*n)++]=fgetc(fp);

}

void sort_inf(char str[],int n)                 /*對內容進行排序*/

{ int i,j;

 for(i=0;i<n-1;i++)

    for(j=i+1;j<n;j++)

       if(str[i]>str[j])

        {t=str[i];str[i]=str[j];str[j]=t;}

}

main()

{

  FILE *fp;

  int i,j,n,ni;

  int len=0;                               /*存放字符串長度*/

  char str[160],t,ch;

  if((fp=fopen("x","r"))==NULL)

   {

    printf("file x cannot be opened\n");

    exit(0);

   }

  get_inf(fp,str,&len)

  fclose(fp);

  if((fp=fopen("y","r"))==NULL)

   {

    printf("file y cannot be opened\n");

    exit(1);

   }

  get_inf(fp,str,&len)

  fclose(fp);

  sort_inf(str,len);

  if((fp=fopen("z","w"))==NULL)

   {

    printf("file z cannot be created\n");

    exit(0);

   }

  for(i=0;i<len;i++)

     fputc(str[i],fp);

  fclose(fp);

}

12.4  文件基本應用舉例

【例12.5】  編寫一個程序,從鍵盤輸入10個學生的學號將其存入文件中。

分析  假定一個學號11位,可以認爲它由11個數字或字符組成。存放一個學生學號的過程便歸結爲向文件中寫11個字符的過程。

 

#include "stdio.h"

void write_code(FILE *fp,char code[]) /*向文件中寫一個學號*/

{int i=0;

 while(code[i]!= ' \0')

      fputc(code[i++],fp);

}

main()

{

  char code[12];

  FILE *fp;

  if((fp=fopen("d:\\student.dat","w"))==NULL)

    {

      printf("\n this file can not be created \n");

      exit(1);

    }

  for(i=0;i<10;)

    {

     scanf("%s",code);

     if(strlen(code)!=11)

       {

         printf("\n code error,reinput")

         continue;

        }

      write_code(fp,code);

      i++;

     }

  fclose (fp);

}

 

【例12.6】  在計算機的D盤上存在文本文件data.dat,該文件存放了全校學生的學號,編寫程序,統計2001級、2002級、2003級、2004級的學生人數。

分析  文本文件data.dat是一個已經存在的文件,它可用例12.5的方法產生。假定一個學號11位,可以每次從文件中讀出11個字節,將其存入一個字符數組中。取出該字符數組的前4個字節,便可得到該學生的年級。定義一個大小爲4的整型數組存放各年級的學生數目。

 

#include "stdio.h"

void get_code(FILE *fp,char code[])      /*從文件中讀一個學號*/

{int i=0;

 for(i=0;i<11;i++) code[i++]=fgetc(fp);

 code[i]='\0';                        /*增加結束標誌*/

}

main()

{

  char code[12],grade[5];

  int num[4]={0},i;

  FILE *fp;

  if((fp=fopen("d:\\data.dat","r"))==NULL)

    {

     printf("\n this file does not exit \n");

     exit(1);

    }

 while(!feof(fp))

   {

    get_code(fp,code);

    num[strcmp(strncpy(grade,code,4), "2001")]++;

   }

  fclose(fp);

}

 

注意:strncpy(grade,code,4)是將code的前4個字符複製到 grade中。strcmp(strncpy (grade,code,4),“2001”)的返回值爲兩個字符串的差,若第一個字符串爲“2002”,則strcmp(“2002”,“2001”)的值爲1。

【例12.7】  在計算機的D盤上存在文本文件data.dat,該文件存放了全校學生的學號,編寫程序,將2001級、2002級、2003級、2004級學生的學號分別取出存放到D盤根目錄下的data2001.dat、data2002.dat、data2003.dat、data2004.dat中。

 

#include "stdio.h"

void write_code(FILE *fp,char code[]) /*向文件中寫一個學號*/

{int i=0;

 while(code[i]!='\0')

   fputc(code[i++],fp);

}

void get_code(FILE *fp,char code[]) /*從文件中讀一個學號*/

{int i=0;

 for(i=0;i<11;i++) code[i++]=fgetc(fp);

 code[i]= '\0';   /*增加結束標誌*/

}

main()

{

  char code[12],grade[5];

  int i;

  FILE *fp,*targ_fp[4];

  if((fp=fopen("d:\\data.dat", "r"))==NULL)

    {

     printf("\n this file does not exit \n");

     exit(1);

    }

  if((targ_fp[0]=fopen("d:\\data2001.dat","w"))==NULL)

    {

     printf("\n this file can not be created \n");

     exit(2);

    }

  if((targ_fp[1]=fopen("d:\\data2002.dat","w"))==NULL)

    {

     printf("\n this file can not be created \n");

     exit(3);

    }

  if((targ_fp[2]=fopen("d:\\data2003.dat","w"))==NULL)

    {

     printf("\n this file can not be created \n");

     exit(4);

    }

  if((targ_fp[3]=fopen("d:\\data2004.dat","w"))==NULL)

    {

     printf("\n this file can not be created \n");

     exit(5);

    }

  while(!feof(fp))

    {

     get_code(fp,code);

     write_code(targ_fp[strcmp(strcpy(grade,code,4),"2001")],code);

    }

  for(i=0;i<4;i++) fclose(targ_fp[i]);

  fclose(fp);

}

習題

一、選擇題

1.以“w”方式打開文本文件“A:\aa.dat”,若該文件已存在,則         

   A.新寫入數據被追加到文件末尾

   B.文件被清空,從文件頭開始存放新寫入數據

   C.顯示出錯信息

   D.新寫入數據被插入到文件首部

2.從磁盤文件讀字符的fgetc函數,其函數原型(頭)正確的是         

   A.FILE* fgetc(char)                                        B.int fgetc(FILE *,char)

   C.int fgetc(FILE *)                                                 D.int fgetc(char,FILE *)

3.對於文件操作方式“rb+”,準確的說法是         

   A.可讀/寫文本文件                                         B.只讀二進制文件

   C.只讀文本文件                                             D.可讀/寫二進制文件

4.數據-324在二進制文件和文本文件中所佔的字節數分別是         

   A.2,2                        B.2,4                       C.4,2                      D.4,4

5.爲了向文本文件尾部增加數據,打開文件的方式應採用         

   A.“a”                       B.“r+”                   C.“w”                    D.“w+”

6.將一個整數10002存到磁盤上,以ASCII碼和二進制格式存儲,所佔用的字節數分別是         

   A.2和2                       B.2和5                     C.5和2                     D.5和5

7.在文件使用方式中,字符串“rb”表示         

   A.打開一個已存在的二進制文件,只能讀取數據

   B.打開一個文本文件,只能寫入數據

   C.打開一個已存在的文本文件,只能讀取數據

   D.打開一個二進制文件,只能寫入數據

二、填空題

1.下面程序把從終端讀入的文本(用@作爲文本結束標誌)輸出到一個名爲“bi.dat”的新文件中,請填空。

 

#include "stdio.h"

FILE *fp;

{ char ch;

  if( (fp=fopen (           ) )= = NULL)exit(0);

  while( (ch=getchar( )) !='@')                 ;

  fclose(fp);

}

 

2.以下程序的功能是從鍵盤上輸入一個字符串,把該字符串中的小寫字母轉換爲大寫字母,輸出到文件“test.txt”中,然後從該文件讀出字符串並顯示,請填空。

 

#include  "stdio.h"

main()

{

 FILE *fp;

 char str[100]; int i=0;

 if((fp=fopen("text.txt",             ))==NULL)

   { printf("can't open this file.\n");exit(0);}

 printf("input astring:\n");

 gest(str);

 while (str[i])

   {

    if(str[i]='a'&&str[i]<='z')

        str[i]=         ;

    fputc(str[i],fp);

    i++;

    }

 fclose(fp);

 fp=fopen("test.txt",            );

 i=0;

 while(!feof(fp)) str[i++]=fgetc(fp);

 str[i]='\0';

 printf("%s\n",str);

 fclose(fp);

}

 

3.使文件內部指針P重新指向文件頭的語句是_________。

4.判斷文本文件是否結束時所使用的符號常量EOF的值是______。

5.建立一個磁盤文件,文件名和內容由鍵盤輸入。

 

#include "stdio.h"

main()

{

   char ch, fname[20];

   _______________;

   scanf("%s",fname);

   if ((fp=fopen (________,"w",))==NULL)

     exit (0);

   ch=getchar ();

   while (ch!='*')

     {

       fputc (ch,fp);

       putchar (ch);

       ch=getchar ();

     }

 fclose ( ________);

}

 

輸入磁盤文件名:filec.c

輸入一個字符串:Program C*

三、程序設計題

1.編寫程序,比較兩個文件,並顯示它們的第一個不相同的行。

2.從鍵盤輸入一個字符串,將其存入文件中。

3.編寫程序,對文件內容進行簡單加密。加密規則:任意字母用其後面的第2個字母替換。

4.編寫程序,對文件內容進行解密。解密規則:任意字母用其前面的第2個字母替換。

5.從兩個文本文件中讀出全部內容,按字母順序排序,排序結果存入新文件。

6.把文本文件“x1.dat”複製到文本文件“x2.dat”中,要求僅複製“x1.dat”中的英文字符。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章