• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            13.4 文件的讀寫

            文件打開之后,就可以對(duì)它進(jìn)行讀寫了。常用的讀寫函數(shù)如下所述。

            13.4.1 fputc 函數(shù)和 fgetc 函數(shù)(putc 函數(shù)和 getc 函數(shù))

            1. fputc 函數(shù)

            把一個(gè)字符寫到磁盤文件上去。其一般調(diào)用形式為

            fputc (ch,fp);

            其中ch 是要輸出的字符,它可以是一個(gè)字符常量,也可以是一個(gè)字符變量.
            fp 是文件指針變量。fputc (ch,fp) 函數(shù)的作用是將字符(ch的值)輸出到所指向的文件中去。fputc 函數(shù)也帶回一個(gè)值:如果輸出成功,則返回值就是輸出的字符;如果輸出失敗,則返回一個(gè)EOF(即—1)。EOF 是在 stdio.h 文件中定義的符號(hào)常量,值為—1。

                   在第4章介紹過(guò) putchar 函數(shù),其實(shí) putchar 是從 fputc 函數(shù)派生出來(lái)的。putchar(c) 是在 stdio.h 文件中用預(yù)處理命令 #define 定義的宏:

                    #define   putchar(c)   fputc(c,stdout)

                前面已敘述,stdout   是系統(tǒng)定義的文件指針變量,它與終端輸出相聯(lián).
            fputc(c,stdout)的作用是將 c 的值輸出到終端.用宏putchar(c)比寫fputc(c,stdout)
            簡(jiǎn)單一些。從用戶的角度,可以把 putchar(c) 看作函數(shù)而不必嚴(yán)格地稱它為宏。

            2.fgetc 函數(shù)

            從指定的文件讀入一個(gè)字符,該文件必須是以讀或讀寫方式打開的。fgetc 函數(shù)的調(diào)用形式為: ch=fgetc(fp);

            fp 為文件型指針變量,ch 為字符變量。fgetc 函數(shù)帶回一個(gè)字符,賦給 ch。
            如果在執(zhí)行 fgetc 函數(shù)讀字符時(shí)遇到文件結(jié)束符,函數(shù)返回一個(gè)文件結(jié)束標(biāo)志EOF(即—1)。如果想從一個(gè)磁盤文件順序讀入字符并在屏幕上顯示出來(lái),可以用:

            ch=fgetc(fp);
            while(ch!=EOF)
            {
            putchar(ch);
            ch=fgetc(fp);
            }

            注意:EOF 不是可輸出字符,因此不能在屏幕上顯示。由于字符的 ASCII 碼不可能出現(xiàn)—1,因此 EOF 定義為—1是合適的。當(dāng)讀入的字符值等于—1(即EOF)時(shí),表示讀入的已不是正常的字符而是文件結(jié)束符。但以上只適用于讀文本文件的情況。現(xiàn)在 ANSI C 已允許用緩沖文件系統(tǒng)處理二進(jìn)制文件,而讀入某一個(gè)字節(jié)中的二進(jìn)制數(shù)據(jù)的值有可能是—1,而這又恰好是EOF的值.
            這就出現(xiàn)了需要讀入有用數(shù)據(jù)而卻被處理為“文件結(jié)束”的情況。為了解決這個(gè)問題,ANSI C 提供一個(gè) feof 函數(shù)來(lái)判斷文件是否真的結(jié)束。feof(fp)用來(lái)測(cè)試 fp 所指向的文件當(dāng)前狀態(tài)是否“文件結(jié)束”。如果是文件結(jié)束,函數(shù)feof(fp)的值為1(真);否則為0(假)。

            如果想順序讀入一個(gè)二進(jìn)制文件中的數(shù)據(jù),可以用:

            while(! feof(fp))
            {
            c=fgetc(fp);
            ……
            }

            當(dāng)未遇文件結(jié)束,feof(fp)的值為0,! feof(fp) 的值為1,讀入一個(gè)字節(jié)的數(shù)據(jù)賦給整型變量c,并接著對(duì)其進(jìn)行所需的處理。直到遇文件結(jié)束,feof(fp)值為1,! feof(fp) 值為0,不再執(zhí)行 while 循環(huán).

            這種方法也適用于文本文件。

            3. fputc 和 fgetc函數(shù)使用舉例

            在掌握了以上幾種函數(shù)以后,可以編制一些簡(jiǎn)單的使用文件的程序。

            例13 .1 從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上去,直到輸入一個(gè)“#”為止。程序如下: (本例有錯(cuò)誤)
            #include "stdio.h"
            #include "stdlib.h"
            void main()
            {
                FILE * fp;
                char ch,filename[10];
                scanf("%s",filename);
                if((fp=fopen(filename,"W"))==NULL)
                 {
                 printf("cannot open file\n");
                 exit(0);
                 }
                 ch=getchar();
                 ch=getchar();
                 while(ch!='#')
                 {
                 fputc(ch,fp);
                 putchar(ch);
                 ch=getchar();
                 }
                 putchar(10);
                 fclose(fp);
            }
            運(yùn)行結(jié)果是:
            輸入:file1.c
            cannot open file
            (不能打開文件)

            文件名由鍵盤輸入,賦給字符數(shù)組 filename。 fopen 函數(shù)中的第一個(gè)參數(shù)“文件名” 可以直接寫成字符串常量形式(如file1.c),也可以用字符數(shù)組名,在字符數(shù)組中存放文件名(如本例所用的方法)。本例運(yùn)行時(shí),從鍵盤輸入磁盤文件名 “file1.c” ,然后輸入要寫入該磁盤文件的字符“ computer and c”, '#' 是表示輸入結(jié)束,程序?qū)?“ computer and c” 寫到以命名的磁盤文件中,同時(shí)在屏幕上顯示這些字符 ,以便核對(duì)。exit 是標(biāo)準(zhǔn) C 的庫(kù)函數(shù),作用是使程序終止,用此函數(shù)應(yīng)當(dāng)加入 stdlib 頭文件。

            例13.2 將一個(gè)磁盤文件中的信息復(fù)制到另一個(gè)磁盤文件中。
            (能運(yùn)行,不能復(fù)制 )
            #include<stdlib.h>
            #include<stdio.h>
            void main()
            {
            FILE*in,*out;
            char ch,infile[10],outfile[10];
            printf("Enter the infile name:\n");
            scanf("%s",infile);
            printf("Enter the infile name:\n");
            scanf("%s",outfile);
            if((in=fopen(infile,"r"))==NULL)
            {
            printf("can not open infile\n");
            exit(0);
            }
            if((out=fopen(outfile,"w"))==NULL)
            {
            printf("can not open outfile\n");
            exit(0);
            }
            while(! feof(in)) fputc(fgetc(in),out);
            fclose(in);
            fclose(out);
            }

            運(yùn)行情況如下:
            Enter the infile name:
            file1.txt      (輸入原有磁盤文件名)
            Enter the infile name:
            file2.txt      (輸入新復(fù)制的磁盤文件名)

            程序運(yùn)行結(jié)果是將 file1.txt 文件中的內(nèi)容復(fù)制到 file2.txt 中去。

            以上程序是按文本文件方式處理的。也可以用此程序來(lái)復(fù)制一個(gè)二進(jìn)制文件,只需將兩個(gè) fopen 函數(shù)中的 r 和 w 分別改為 rb 和 wb 即可。

            也可以在輸入命令行時(shí)把兩個(gè)文件名一起輸入。這時(shí)要用到 main 函數(shù)的參數(shù)。程序可改為:
            #include<stdlib.h>
            #include<stdio.h>
            void main(int agc,char *argv[])
            {
            FILE * in,* out;
            char ch;
            if(argc !=3)
            {
            printf("You forgot to enter a filename\n");
            exit(0);
            }
            if((in=fopen(argv[1],"r"))==NULL)
            {
               printf("cannot open infile\n");
            exit(0);
            }
            if((out=fopen(argv[2],"w"))==NULL)
            {
               printf("cannot open infile\n");
            exit(0);
            }
            while(! feof(in)) fputc(fgetc(in),out);
            fclose(in);
            fclose(out);
            }


            假若本程序的原文件名為 1.c 經(jīng)編譯連接后得到的可執(zhí)行文件名為 1.exe ,則在DOS命令工作方式下,可以輸入以下的命令行:C>1 file1.c file2.c 即在輸入可執(zhí)行文件名后,再輸入兩個(gè)參數(shù) file1.c 和 file2.c ,分別輸入到 argv[1]和 argv[2]中,argv[0]的內(nèi)容為a,argc 的值等于3(因?yàn)榇嗣钚泄灿?個(gè)參數(shù)) 。如果輸入的參數(shù)少于3個(gè),則程序會(huì)輸出:“You forgot to enter a filename”
            (你忘了輸入一個(gè)文件名)。程序執(zhí)行結(jié)果是將 file1.c 中的信息復(fù)制到 file2.c 中。可以用以下命令驗(yàn)證:
            C>type file1.c
            computer and c
            (這是 file1.c 文件中的信息)

            C>type file2.c
            computer and c
            (這是 file2.c 文件中的信息。可見 file1.c已復(fù)制到 file2.c 中了)。

            最后說(shuō)明一點(diǎn),為了書寫方便,系統(tǒng)把 fputc 和 fgetc 定義為宏名putc 和getc:

            #define putc(ch,fp) fputc(ch,fp)
            #define getc(fp) fgetc(fp)

            這是在 stdio.h 中定義的。因此,用 putc 和 fputc 及用 getc 和 fgetc 是一樣的。一般可以把它們作為相同的函數(shù)來(lái)對(duì)待。


             


               13.4.2 fead 函數(shù)和 fwrite 函數(shù)

            用 getc 和 putc 函數(shù)可以用來(lái)讀寫文件中的一個(gè)字符。但是常常要求一次讀入一組數(shù)據(jù)(例如,一個(gè)實(shí)數(shù)或一個(gè)結(jié)構(gòu)體變量的值),ANSI C 標(biāo)準(zhǔn)提出設(shè)置兩個(gè)函數(shù)(fead 函數(shù)和 fwrite 函數(shù)),用來(lái)讀寫一個(gè)數(shù)據(jù)塊。它們的一般調(diào)用形式為:

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

            其中:buffer:是一個(gè)指針.對(duì) fread 來(lái)說(shuō),它是讀入數(shù)據(jù)的存放地址. 對(duì)fwrite 來(lái)說(shuō),
            是要輸出數(shù)據(jù)的地址(以上指的是起始地址)。

            size : 要讀寫的字節(jié)數(shù)。
            count: 要進(jìn)行讀寫多少個(gè) size 字節(jié)的數(shù)據(jù)項(xiàng)。
                  fp: 文件型指針。

            如果文件以二進(jìn)制形式打開,用 fead 和 fwrite 函數(shù)就可以讀寫任何類型的信息,例如: fead(f,4,2,fp);      其中 f 是一個(gè)實(shí)型數(shù)組名。一個(gè)實(shí)型變量占4個(gè)字節(jié)。這個(gè)函數(shù)從所指向的文件讀入2個(gè)4個(gè)字節(jié)的數(shù)據(jù),存儲(chǔ)到數(shù)組 f 中。
            如果有一個(gè)如下的結(jié)構(gòu)體類型:

            struct student_type
            {
            char   name[10];
            int   num;
            int   age;
            char   addr[30];
            }stud[40];

            結(jié)構(gòu)體數(shù)組 stud 有40個(gè)元素,每一個(gè)元素用來(lái)存放一個(gè)學(xué)生的數(shù)據(jù)(包括姓名、學(xué)號(hào)、年齡、地址)。假設(shè)學(xué)生的數(shù)據(jù)已存放在磁盤文件中,可以用下面的 for 語(yǔ)句和 fread 函數(shù)讀入40個(gè)學(xué)生的數(shù)據(jù):

            for(i=0;i<40;i++)
            fread(&stud[i],sizeof(struct student_type),1,fp);

            同樣,以下 for 語(yǔ)句和 fwrite 函數(shù)可以將內(nèi)存中的學(xué)生數(shù)據(jù)輸出到磁盤文件中去:

            for(i=0;i<40;i++)
            fwrite(&stud[i],sizeof(struct student_type),1,fp);

            如果 fead 和 fwrite 調(diào)用成功,則函數(shù)返回值為 count 的值,既輸入或輸出數(shù)據(jù)項(xiàng)的完整個(gè)數(shù)。

            下面寫出一個(gè)完整的程序。

            例13.3   從鍵盤輸入4個(gè)學(xué)生的有關(guān)數(shù)據(jù),然后把它們轉(zhuǎn)存到磁盤文件上去。
            #include "stdio.h"
            #define SIZE 4
            struct student_type
            {char name[10];
            int age;
            int num;
            char addr[15];

            }stud[SIZE];
            void save()
            {
               FILE * fp;
               int i;
               if((fp=fopen("stu_list","wb"))==NULL)
               {
               printf("cannot open file\n");
               return;
               }
               for(i=0;i<SIZE;i++)
               if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1)
                printf("file write error\n");
                fclose(fp);
            }
            void main()
            {
            int i;
            for(i=0;i<SIZE;i++)
            scanf("%s%d%d%s",stud[i].name,&stud[i].age,&stud[i].num,stud[i].addr);
            save();
            }

            在main 函數(shù)中,從終端鍵盤輸入4個(gè)學(xué)生的數(shù)據(jù),然后調(diào)用 save 函數(shù),將這些數(shù)據(jù)輸出到以 " stu_list "命名的磁盤文件中。fwrite 函數(shù)的作用是將一個(gè)
            長(zhǎng)度為29字節(jié)數(shù)據(jù)塊送到 stu_list 文件中(一個(gè) student_type 類型結(jié)構(gòu)體變量的長(zhǎng)度為它的成員長(zhǎng)度之和,即10+2+2+15=29)。
            運(yùn)行情況如下:
            輸入4個(gè)學(xué)生的姓名、學(xué)號(hào)、年齡和地址:

            Zhang 1001 18 room_101  
            Fun    1002 18   room_102        
            Tan      1003 18   room_103              
                Lin 1004   21   room_104

                程序運(yùn)行時(shí),屏幕上并無(wú)輸出任何信息,只是將從鍵盤輸入的數(shù)據(jù)送到此盤文件上。為了驗(yàn)證在磁盤文件 “ stu_list ”中是否已存在此數(shù)據(jù),可以用以下程序從 stu_list 文件中讀入數(shù)據(jù),然后在屏幕上輸出。
            #include "stdio.h"
            #define SIZE 4
            struct student_type
            {
            int age;
            int num;
            char addr[15];
            char name[10];
            }stud[SIZE];
            void main()
            {
            int i;
            FILE * fp;
            fp=fopen("stu_list","rb");
            for(i=0;i<SIZE;i++)
            {
               fread(&stud[i],sizeof(struct student_type),1,fp);
            printf("%-10s %4d %4d %-15s\n",stud[i].name,&stud[i].age,&stud[i].num,stud[i].addr);
            }
            fclose(fp);
            }

            請(qǐng)注意:輸入輸出數(shù)據(jù)的狀況。從鍵盤輸入4個(gè)學(xué)生的數(shù)據(jù)是 ASCII 碼,也就是文本文件。在送到計(jì)算機(jī)內(nèi)存時(shí),回車和換行符轉(zhuǎn)換成一個(gè)換行符。再?gòu)膬?nèi)存以 “wb”方式(二進(jìn)制寫)輸出到 stu_list 文件,此時(shí)不發(fā)生字符轉(zhuǎn)換,按內(nèi)存中存儲(chǔ)形式原樣輸出到磁盤文件上。在上面驗(yàn)證程序中,又用“fread ”函數(shù)從 stu_list 文件向內(nèi)存讀入數(shù)據(jù),注意此時(shí)用的是“rb” 方式,即二進(jìn)制方式,數(shù)據(jù)按原樣輸入,也不發(fā)生字符轉(zhuǎn)換。也就是這時(shí)候內(nèi)存中的數(shù)據(jù)恢復(fù)到第一個(gè)程序向 “ stu_list ” 輸出以前的情況。最后在驗(yàn)證程序中,用printf 函數(shù)輸出到屏幕,printf 是格式輸出函數(shù),輸出 ASCII 碼,在屏幕上顯示字符。換行符又轉(zhuǎn)換為回車加換行符。

            如果企圖從 “ stu_list ”文件中以 “r ”方式讀入數(shù)據(jù)就會(huì)出錯(cuò)。

            fread 和 fwrire 函數(shù)一般用于二進(jìn)制文件的輸入輸出。因?yàn)樗鼈兪前磾?shù)據(jù)塊的長(zhǎng)度來(lái)處理輸入輸出的,在字符發(fā)生轉(zhuǎn)換的情況下很可能出現(xiàn)與原設(shè)想的情況不同。 例如,寫成:fread(&stud[i],sizeof(struct student_type),1,stdin);   企圖從終端鍵盤輸入數(shù)據(jù),這在語(yǔ)法上并不存在錯(cuò)誤,編譯能通過(guò)。如果用以下形式輸入數(shù)據(jù): Zhang 1001 18 room_101  
                                                       ……

            由于 fread 函數(shù)要求一次輸入29個(gè)字節(jié)(而不問這些字節(jié)的內(nèi)容),因此輸入數(shù)據(jù)中的空格也作為輸入數(shù)據(jù)而不作為數(shù)據(jù)間的分隔符了。連空格也存儲(chǔ)到 stud[i] 中了,顯然是不對(duì)的。

            這個(gè)題目要求的是從鍵盤輸入數(shù)據(jù),如果已有的數(shù)據(jù)已經(jīng)以二進(jìn)制形式存儲(chǔ)在一個(gè)磁盤文件 stu_dat 中,要求從其中讀入數(shù)據(jù)并輸出到 stu_list 文件中,可以編寫一個(gè) load 函數(shù),從磁盤文件中讀二進(jìn)制數(shù)據(jù)。

            #include "stdio.h"
            #define SIZE 4
            struct student_type
            {
            int age;
            int num;
            char addr[15];
            char name[10];
            }stud[SIZE];
            void load()
            {
                              FILE * fp;
            int i;
            if((fp=fopen("stu_dat","rb"))==NULL)
            {
               printf("cannot open file\n");
               return;
                          }
               for(i=0;i<SIZE;i++)
               if(fread(&stud[i],sizeof(struct student_type),1,fp)!=1)
            { if(feof(fp))
            { fclose(fp);
                return;
            }
                printf("file write error\n");
            }
                fclose(fp);
            }
            main()
            {
            load();
            save();
            }

             


            13.4.3   fprintf (從文件中輸出) 函數(shù)和 fscanf (從文件中讀入) 函數(shù)

            fprintf 函數(shù)、fscanf 函數(shù) 與 printf 函數(shù)、scanf 函數(shù)作用相仿,都是格式讀寫函數(shù)。只有一點(diǎn)不同: fprintf 函數(shù)、fscanf 函數(shù)的讀寫對(duì)象不是終端而是磁盤文件。它們的一般調(diào)用方式為:

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

            例如:

            fprintf(fp,"%d,%6.2f",a,b);

            它的作用是將整型變量 a 和實(shí)型變量 b 的值按 %d 和 %6.2f 的格式輸出到 fp 指向的文件上。如果 i=3,t=4.5 則輸出到磁盤文件上的是以下的字符串:

            3, 4.50

            同樣,用以下函數(shù)可以從磁盤文件上讀入 ASCII 字符:

            fscanf(fp,"%d,%f",&a,&b);

            磁盤文件上如果有這樣的字符:3, 4.5   即將磁盤文件中的數(shù)據(jù) 3送給變量 a,4.5 送給變量 b。

            用 fprintf 和 fscanf 函數(shù)對(duì)磁盤文件讀寫,使用方便,容易理解,但由于在輸入時(shí)要將 ASCII 碼轉(zhuǎn)換為二進(jìn)制形式,在輸出時(shí)又要將二進(jìn)制形式轉(zhuǎn)換成字符,花費(fèi)時(shí)間比較多。因此,在內(nèi)存與磁盤頻繁交換數(shù)據(jù)的情況下,最好不用 fprintf 和 fscanf 函數(shù),而用 fread(從文件中讀) 和 fwrite(往文件中寫) 函數(shù)。


             

                                                        13.4.4 其它讀寫函數(shù)
            1. putw 和 getw 函數(shù)

            大多數(shù) C 編譯系統(tǒng)都提供另外兩個(gè)數(shù):putw 和 getw 函數(shù) ,用來(lái)對(duì)磁盤文件讀寫一個(gè)字(整數(shù))。例如: putw(10,fp);     它的作用是將整數(shù) 10 輸出到 fp指向的文件。而 i=getw(fp);     的作用是從磁盤文件讀一個(gè)整數(shù)到內(nèi)存,賦給整型變量 i。

            如果所用的 C 編譯系統(tǒng)的庫(kù)函數(shù)中不包括 putw 和 getw 函數(shù),可以自己定義這兩個(gè)函數(shù)。putw 函數(shù)如下:

            putw(int i,FILE * fp)
            {
            char * s;                                      圖1:                     i
            s=&i;                                                       00000000    00001010
            putc(s[0],fp);                                                s[0]               s[1]
            putw(s[1],fp);
            return(i);
            }
            當(dāng)調(diào)用 putw 函數(shù)時(shí),如果用 putw(10,fp); 語(yǔ)句, 形參 i 得到實(shí)參傳來(lái)的值 10, 在 putw 函數(shù)中將 i 的地址賦予指針變量 s ,而 s 是指向字符變量的指針變量,因此 s 指向 i 的第 1 個(gè)字節(jié),s+1 指向 i 的第 2 個(gè)字節(jié)。由于 * (s+0)就是 s[0],* (s+1)就是 s[1],因此,s[0]、s[1]分別對(duì)應(yīng)的第 1 個(gè)字節(jié)和第 2 個(gè)字節(jié)。順序輸出s[0]、s[1]就相當(dāng)于輸出了 i 的兩個(gè)字節(jié)中的內(nèi)容,見圖1.
            getw 函數(shù)如下:

            getw(FILE * fp)
            {
            char * s;
            int   i;
            s=char * &i; /*使 s 指向 i 的起始地址 */
            s[0]=getc(fp);
            s[1]=getc(fp);
            return(i);
            }

            putw 和 getw 函數(shù)并不是 ANSI C 標(biāo)準(zhǔn)定義的函數(shù)。許多 C 編譯系統(tǒng)都提供這兩個(gè),但有的不以 putw 和 getw 命名此兩函數(shù),而用其它函數(shù)名,用時(shí)要注意。

            2. 讀寫其它類型數(shù)據(jù)

            如果用 ANSI C 提供的 fread 和 fwrite函數(shù),讀寫任何類型數(shù)據(jù)都是十分方便的。如果所用的系統(tǒng)不提供這兩個(gè)函數(shù),用戶只好自己定義所需函數(shù)。例如,可以定義一個(gè)向磁盤文件寫一個(gè)實(shí)數(shù)(用二進(jìn)制方式)函數(shù) putfloat:

            putfloat(float num,FILE * fp)
            {
            char * s;
            int count;
            s=(char *) &num;
            for(count=0;count<4,count++)
                putc(s[count],fp);
            }

            同樣可以編寫出讀寫任何類型數(shù)據(jù)的函數(shù)。

            3. fgets 函數(shù)和 fputs 函數(shù)

            fgets 函數(shù)的作用是從指定文件讀入一個(gè)字符串。例如:fgets (str,a,fp);   a 為要求得到的字符,但只從 fp指向的文件輸入 a-1 個(gè)字符,然后在最后加一個(gè)‘ \0 ’字符,因此得到的字符串共有 a 個(gè)字符,把它們放到字符數(shù)組 str 中.如果
            在讀完 a-1個(gè)字符之前遇到換行符或 EOF ,讀入即結(jié)束。 fgets 函數(shù)返回值為 str 的首地址。

               fputs 函數(shù)的作用是從指定文件輸出一個(gè)字符串。例如:fputs("Wolong",fp);
            把字符串 “ Wolong ” 輸出到 fp 指向的文件。fputs 函數(shù)中第一個(gè)參數(shù)可以是字符串常量、字符數(shù)組名或字符指針。 字符串末尾的‘ \0 ’ 不輸出。若輸出成功,函數(shù)值為 0;失敗時(shí),為 EOF 。

                 這兩個(gè)函數(shù)類似以前介紹過(guò)的 gets 和 puts 函數(shù), 只是 fgets 和 fputs 函數(shù)以指定的文件為讀寫對(duì)象。

            fgets(從文件中獲取字符串)

            fputs(往文件中寫字符串)

             

            如果所用的 C 編譯系統(tǒng)的庫(kù)函數(shù)中不包括 putw 和 getw 函數(shù),可以自己定義這兩個(gè)函數(shù)。putw 函數(shù)如下:

            putw(int i,FILE * fp)
            {
            char * s;                                      圖1:                     i
            s=&i;                                                       00000000    00001010
            putc(s[0],fp);                                                s[0]               s[1]
            putw(s[1],fp);
            return(i);
            }
            當(dāng)調(diào)用 putw 函數(shù)時(shí),如果用 putw(10,fp); 語(yǔ)句, 形參 i 得到實(shí)參傳來(lái)的值 10, 在 putw 函數(shù)中將 i 的地址賦予指針變量 s ,而 s 是指向字符變量的指針變量,因此 s 指向 i 的第 1 個(gè)字節(jié),s+1 指向 i 的第 2 個(gè)字節(jié)。由于 * (s+0)就是 s[0],* (s+1)就是 s[1],因此,s[0]、s[1]分別對(duì)應(yīng)的第 1 個(gè)字節(jié)和第 2 個(gè)字節(jié)。順序輸出s[0]、s[1]就相當(dāng)于輸出了 i 的兩個(gè)字節(jié)中的內(nèi)容,見圖1.
            getw 函數(shù)如下:

            getw(FILE * fp)
            {
            char * s;
            int   i;
            s=char * &i; /*使 s 指向 i 的起始地址 */
            s[0]=getc(fp);
            s[1]=getc(fp);
            return(i);
            }


            如果用 ANSI C 提供的 fread 和 fwrite函數(shù),讀寫任何類型數(shù)據(jù)都是十分方便的。如果所用的系統(tǒng)不提供這兩個(gè)函數(shù),用戶只好自己定義所需函數(shù)。例如,可以定義一個(gè)向磁盤文件寫一個(gè)實(shí)數(shù)(用二進(jìn)制方式)函數(shù) putfloat:

            putfloat(float num,FILE * fp)
            {
            char * s;
            int count;
            s=(char *) &num;
            for(count=0;count<4,count++)
                putc(s[count],fp);
            }

            同樣可以編寫出讀寫任何類型數(shù)據(jù)的函數(shù)。


            例13.1從鍵盤輸入一些字符,逐個(gè)把它們送到磁盤上,直到輸入一個(gè)"#"為止.程序如下:
            #include<stdlib.h>
            #include<stdio.h>
            void main()
            {
            FILE*fp;
            char ch,filename[10];
            scanf("%s",filename);
            if((fp=fopen(filename,"w"))==NULL)
            {
            printf("can not open file\n");
            exit(0);/*終止程序*/
            }
            ch=getchar();/*接收輸入的一個(gè)字符*/
            ch=getchar();/*這一句可以省略.*/
            while(ch!='#')
            {
            fputc(ch,fp);putchar(ch);
            ch=getchar();
            }
            putchar(10);/*向屏幕輸出一個(gè)換行符*/
            fclose(fp);
            }
            運(yùn)行后的結(jié)果:輸入:is a c# 輸出 a c

             

             

                                                    13.5     文件的定位

            文件中有一個(gè)位置指針,指向當(dāng)前讀寫的位置。如果順序讀寫一個(gè)文件,每次讀寫一個(gè)字符,則讀寫完一個(gè)字符后,該位置指針自動(dòng)移動(dòng)指向下一個(gè)字符位置。如果想改變這樣的規(guī)律,強(qiáng)制使位置指針指向其它指定的位置,可以用后面介紹的有關(guān)函數(shù)。

            13.5.1 rewind 函數(shù)

            rewind 函數(shù)的作用是使位置指針重新返回文件的開頭,此函數(shù)沒有返回值。

            例13.4 有一個(gè)磁盤文件,第一次將它的內(nèi)容顯示在屏幕上,第二次把它復(fù)制到另一文件上。
            #include "stdio.h"
            void main()
            {
            FILE * fp1,* fp2;
            fp1=fopen("file1.txt","r");
            fp2=fopen("file2.txt","w");
            while(! feof(fp1))
            putchar(getc(fp1));
            rewind(fp1);
            while(! feof(fp1))
            putc(getc(fp1),fp2);
            fclose(fp1);
            fclose(fp2);
            }
            (先在某一個(gè)位置上新建立一個(gè)文本文件,命名為file1.txt然后運(yùn)行本程序(在vc編譯系統(tǒng)運(yùn)行過(guò)))如:“ file1.txt ”里面的內(nèi)容是:
                     Nu11              pointer              assignment
                  (無(wú)效的) ( 指示器)(分配、任務(wù)、作業(yè))
            運(yùn)行后的結(jié)果是:

            在第一次將內(nèi)容顯示在屏幕上,file1.txt 的位置指針已指到文件末尾,feof 的值為零(真)。執(zhí)行 rewind 函數(shù) ,使文件的位置指針重新定位于文件開頭,并使 feof 函數(shù)的值恢復(fù)為0(假)。

            fopen (打開文件) fclose(文件關(guān)閉) rewind(重新) putchar(寫一個(gè)字符的函數(shù))feof=end of file (文件末尾)   putc (輸出字符)

            posted on 2010-08-13 08:50 wrh 閱讀(644) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            導(dǎo)航

            <2011年8月>
            31123456
            78910111213
            14151617181920
            21222324252627
            28293031123
            45678910

            統(tǒng)計(jì)

            常用鏈接

            留言簿(19)

            隨筆檔案

            文章檔案

            收藏夾

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            国产精品久久婷婷六月丁香| 午夜人妻久久久久久久久| 91精品国产高清久久久久久91 | 精品久久久久中文字幕一区| 久久久久人妻一区精品| 亚洲精品无码久久久久去q| 久久婷婷国产麻豆91天堂| 亚洲伊人久久成综合人影院| 国产情侣久久久久aⅴ免费| 亚洲?V乱码久久精品蜜桃 | 国产福利电影一区二区三区久久老子无码午夜伦不 | 国产精品VIDEOSSEX久久发布| 久久久午夜精品| 99久久国产免费福利| 亚洲欧美日韩中文久久| 欧美久久综合九色综合| 久久精品国产99国产精品澳门| 久久精品国产亚洲av麻豆蜜芽 | 激情综合色综合久久综合| 亚洲AV无码久久精品狠狠爱浪潮| 久久国产影院| 7777久久亚洲中文字幕| 欧洲人妻丰满av无码久久不卡| 亚洲欧美日韩精品久久亚洲区 | 国产精品免费看久久久香蕉| 久久亚洲AV成人出白浆无码国产| 国产精品久久婷婷六月丁香| 久久国产综合精品五月天| 97超级碰碰碰碰久久久久| 九九精品99久久久香蕉| 婷婷伊人久久大香线蕉AV| 久久精品国产亚洲av麻豆蜜芽| 人妻少妇精品久久| 午夜福利91久久福利| 亚洲午夜久久久| 久久午夜福利无码1000合集| 一本久久免费视频| 99久久香蕉国产线看观香| 777午夜精品久久av蜜臀| 色欲综合久久躁天天躁蜜桃| 精品久久人人爽天天玩人人妻|