zoukankan      html  css  js  c++  java
  • 文件输入输出函数fgetc/fputc及fgets/fputs等文件指针位置的变化

    文件打开后才可以对文件进行操作。也就是说,文件必须经历打开-操作-关闭的过程。如前所述,C语言对文件的操作都是通过调用标准I/O库函数来实现的。文件操作实际是指对文件的读写。文件的读操作就是从文件中读出数据,即将文件中的数据输入计算机;文件的写操作是向文件中写入数据,即向文件输出数据。实际上对文件的处理过程就是对文件的输入输出过程。在前面已经介绍了C语言对标准设备文件的输入输出函数,本节讨论对磁盘文件的输入输出函数,这类文件及其相应的函数在实际应用和文件处理中占据重要的地位。C语言提供的缓冲式文件处理函数可分为:

         字符输入输出函数   fgetc和fputc
       字符串输入输出函数  fgets和fputs
       格式化输入输出函数  fscanf和fprintf
       数据块输入输出函数  fread和fwrite
       文件定位函数     feek、rewind和ftell
       其它函数       feof、ferror和clearerr。

    12.3.1 文件的字符输入/输出函数

    1.字符输入函数fgetc( )

         fgetc函数的调用形式为:
         ch = fgetc (fp);

         其中fp为文件型指针变量,ch字符变量。

         fgetc函数的功能是:从指定的文件中读取一个字符。即:从fp所指向的文件(该文件必须是以读或读写方式打开的)中读取一个字符返回,读取的字符赋给变量ch。若读取字符时文件已经结束或出错,fputc函数返回文件结束标记EOF,此时EOF的值为-1。

         例如,要从磁盘文件中顺序读入字符并在屏幕上显示,可通过调用fgetc函数实现:
         while ( (c=fgetc(fp)) != EOF )
           putchar(c);

         注意:文件结束标记EOF是不可输出字符,不能在屏幕上显示。因为EOF是在头文件stdio.h中定义的符号常量,其值为-1,而ASCII码中没用-1,可见,用它作文件结束标记是合适的。

         例12-1:在屏幕上显示文本文件的内容。

       #include <stdio.h>
       main ( )
       { FILE *fp;
        char filename[20], ch;
        printf ("Enter filename:");
        scanf("%s",filename); /* 输入文件名 */
        if ( (fp = fopen (filename,"r"))==NULL) /* 打开文件 */
         { printf("file open error. "); /* 出错处理 */
          exit (0);
         }
        while ( ( ch = fgetc(fp) )!=EOF) /* 从文件中读字符 */
         putchar(ch); /* 显示从文件读入的字符 */
        fclose (fp); /* 关闭文件 */
       }

         例12-2:使用标准输出文件显示文本文件的内容。

       #include <stdio.h>
       main ( )
       { FILE *fp;
        char filename[20], ch;
        printf ("Enter filename:");
        scanf("%s",filename); /* 输入文件名 */
        if ( (fp = fopen (filename,"r"))==NULL) /* 打开文件 */
         { printf("file open error. "); /* 出错处理 */
          exit (0);
         }
        while ( (ch=fgetc(fp) ) != EOF ) /* 从文件中读取字符 */
         fputc(ch,stdout); /* 向标准输出文件中输出(显示) */
        fclose (fp); /* 关闭文件 */
       }

    2.字符输出函数fputc( )

         fputc函数的调用形式为:
         fputc (ch, fp);

         其中:ch是要输出的字符(可为字符常数或字符变量),fp为文件型指针变量。

         fputc函数的功能是:将一个字符输出到指定文件中。即将字符变量ch中的字符输出到fp所指向的文件。若输出操作成功,该函数返回输出的字符;否则,返回EOF。

         例12-3:从键盘输入一字符串,并逐个将字符串的每个字符传送到磁盘文件file中,当输入的字符为"#"时停止输入。

       #include <stdio.h> /* 凡程序中用到标准输入输出函数,必须包含此文件头 */
       main ( )
       { FILE *fp; /* 指向磁盘文件file的指针 */
        char ch; /* 暂存读入字符的字符变量 */
        char filename[15]; /* 存放磁盘文件名的字符数组 */
        scanf("%s", filename); /* 从键盘输入磁盘文件名 */
        if ((fp=fopen(filename,"w"))==NULL) /* 以写方式打开文本文件并判定是否能正常打开 */
         { printf("Cannot open file. "); /* 不能正常打开磁盘文件的处理 */
          exit(0); /* 调用函数exit终止程序运行 */
         }
        while ( (ch=getchar( )) != '#' ) /* 判断输入的是否为字符符串结束标志 */
         fputc(ch, fp); /* 读入的字符写入磁盘文件 */
        fclose(fp); /* 操作结束关闭磁盘文件 */
       }

         例12-4:请编程完成文本文件的复制。

       #include <stdio.h>
       main ( )
       { FILE *fp1, *fp2;
        char file1[20], file2[20], ch;
        printf ("Enter filename1:");
        scanf("%s",file1);
        printf ("Enter filename2:");
        scanf("%s",file2);
        if ( (fp1=fopen(file1,"r")) == NULL ) /* 以"只读"方式打开文件1 */
         { printf("file1 open error. ");
          exit (0);
         }
        if ( (fp2=fopen(file2, "w"))== NULL ) /* 以"写"方式打开文件2 */
         { printf("file2 open error. ");
          exit (0);
         }
        while ( ( ch = fgetc(fp1) ) != EOF ) /* 从文件fp1中读字符 */
         fputc (ch, fp2); /* 写入文件fp2中 */
        fclose (fp1); /* 关闭两个文件 */
        fclose (fp2);
       }

    12.3.2 文件的字符串输入/输出函数

         对文件的输入输出,除了前面介绍的以字符为单位进行处理之外,还允许以字符串为单位进行处理,这也被称为"行处理"。

         C语言提供fgets和fputs函数实现文件的按字符串的读写。

    1.字符串输入函数fgets( )

         fgets函数的调用形式:
         fgets (s, n, fp);

         其中:参数s可以是一个字符数组名,或是指向字符串的指针,n为要读取的最多的字符个数;fp是指向该文件的文件型指针。

         fgets函数的功能是:从fp所指向的文件中读取长度不超过n-1个字符的字符串,并将该字符串放到字符数组s中。如果操作正确,函数的返回值为字符数组s的首地址;如果文件结束或出错,则函数的返回值为NULL。

         情况1:从文件中已经读入了n-1个连续的字符,还没有遇到文件结束标志或行结束标志' ',
         则:s中存入n-1个字符,串尾以串结束标记''结束。

         情况2:从文件中读入字符遇到了行结束标志' ',
         则:s中存入实际读入的字符,串尾为' '和''。

         情况3:在读文件的过程中遇到文件尾(文件结束标志EOF),
         则:s中存入实际读入的字符,串尾为''。文件结束标志EOF不会存入数组。

         情况4:当文件已经结束仍然继续读文件,或读取文件内容发生错误,
         则:函数的返回值为NULL,表示文件结束。例如:现有一个有两行字符的ASCII文件,文件打开后,文件的读写位置指针如图12-3所示。

         若有:char s[5];FILE *fp;fp为指向该文件的指针。则多次执行语句"fgets (s, 5, fp);",每次的执行结果如下:

    第1次执行语句fgets (s, 5, fp):
       文件刚打开时,文件的读写位置指针指向了文件的第1个字符,执行语句:fgets (s, 5, fp)之后,从fp指向的文件中读取的字符串是"abcd ",文件的读写位置指针向前移动了4个字符,字符串在s中的存储形式和文件读写位置指针如图12.4所示。

    第2次执行语句fgets (s, 5, fp):
       从文件的读写位置指针开始,顺序读入字符,遇到' '字符后,函数执行完毕。字符串在s中的存储形式和文件读写位置指针如图12.5所示。

    第3次执行语句fgets (s, 5, fp):
       从文件的读写位置指针开始,顺序读入字符,遇到文件结束标记EOF,函数执行完毕,此时,文件的读写位置指针指向了文件最后一个字符的后面。字符串在s中的存储形式和文件读写位置指针如图12-6所示。

         第4次执行语句fgets (s, 5, fp):
       由于文件的读写位置指针已经指向了文件结束标记EOF,所以函数的返回值为NULL,表示文件已经结束,文件的读写位置指针没有变化。文件读写位置指针如图12-7所示。

         例12-5:显示文件内容并加上行号。

       #include <stdio.h>
       main ( )
       { FILE * fp;
        char file[20], str[10];
        int flag=1, i=0; /* flag标志变量,为1:开始新行。i为行号 */
        printf ("Enter filename:");
        scanf("%s",file);
        if ( ( fp = fopen (file, "r")) == NULL ) /* 打开文件 */
         { printf("file open error. ");
          exit (0); 
         }
        while ( fgets( str,10,fp )!=NULL ) /* 从文件中读出字符串 */
         { if (flag) printf ("%3d:%s", ++i, str); /* 显示行号 */
           else printf ("%s", str);
          if ( str [strlen(str)-1] == ' ' ) flag=1;
           else flag=0;
         }
        fclose (fp);
       }

         本程序的特点是使用一个长度仅为10的小数组来处理文件,程序中充分利用了函数fgets的特点。

    2.字符串输出函数 fputs( )

         fputs函数的调用形式:
         fputs (s, fp);

         其中:s为指向字符串的指针或字符数组名,也可以是字符串常量;fp是指向将要被写入的文件的文件型指针。

         fputs函数的功能是:将s指向的字符串或字符串常量写入fp指向的文件。输出的字符串写入文件时,字符''被自动舍去。函数调用成功,则返回值为0;否则返回EOF。

         例12-6:从键盘输入若干行字符存入磁盘文件file.txt中

       #include <stdio.h>
       #include <string.h>
       main ( )
       { FILE *fp;
        char str[81];
        if ((fp=fopen("file.txt", "w")) == NULL)
           /* 以写方式打开磁盘文本文件file.txt并判断打开操作正常与否 */
         { printf("Cannot open file. "); /* 不能正常打开磁盘文件的处理 */
          exit(0);
         }
        while ( strlen(gets(str)) > 0 )
           /* 读入从键盘输入的一行字符,送入str字符数组 */
        { fputs(str, fp); /* 若该字符串非空则送入磁盘文件file.txt中去 */
         fputs(" ", fp);
        }
        fclose (fp); /* 操作结束关闭磁盘文件 */
       }

         例12-7:复制文本文件。

       #include <stdio.h>
       main ( )
       { FILE *fp1, *fp2;
        char file1[20], file2[20], s[10];
        printf ("Enter filename1:");
        scanf("%s",file1);
        printf ("Enter filename2:");
        scanf("%s",file2);
        if ( ( fp1 = fopen (file1, "r")) == NULL ) /* 打开文本文件1 */
         { printf("file1 open error. "); 
          exit (0);
         }
        if ( ( fp2 = fopen (file2, "w")) == NULL ) /* 打开文本文件2 */
         { printf("file2 open error. "); 
          exit (0);
         }
        while ( fgets( s,10,fp1 ) != NULL ) /* 从文件fp1中读出字符串 */
         fputs ( s, fp2 ); /* 将字符串写入文件fp2中 */
        fclose (fp1);
        fclose (fp2);
       }

    12.3.3 文件的格式化输入输出函数

         前面的章节中介绍了scanf和printf两个格式化输入输出函数,它们适用于标准设备文件。C标准函数库还提供了fscanf和fprintf两个格式化输入输出函数,以满足磁盘文件格式化输入输出的需要。

    1.格式化输入函数 fscanf( )

         fscanf函数的调用形式:
         fscanf (fp, 格式控制串, 输入列表);

         其中:fp指向将要读取文件的文件型指针,格式控制串和输入列表的内容、含义及对应关系与第二章中介绍的scanf函数相同。

         fscanf函数的功能是:从fp指向的文件中,按格式控制符读取相应数据赋给输入列表中的对应变量地址中。例如,
         fscanf (fp, "%d,%f", &i, &t);
       完成从指定的磁盘文件上读取ASCII字符,并按"%d"和"%f"型格式转换成二进制形式的数据送给变量i和t。

    2.格式化输出函数 fprintf( )

         fprintf函数的调用形式:
         fprintf (fp, 格式控制串, 输出列表);

         其中:fp指向将要写入文件的文件指针,格式控制串和输出列表的内容及对应关系与前面章节中介绍的printf函数相同。

         fprintf函数的功能是:将输出列表中的各个变量或常量,依次按格式控制符说明的格式写入fp指向的文件。该函数调用的返回值是实际输出的字符数。

         例12-8.C:从键盘输入一个字符串和一个十进制整数,将它们写入test文件中,然后再从test文件中读出并显示在屏幕上。

       #include <stdio.h>
       main( )
       { char s[80];
        int a;
        FILE *fp;
        if ((fp=fopen("test", "w")) == NULL)  /* 以写方式打开文本文件 */
         { printf ("Cannot open file. ");
          exit(1);
         }
        fscanf (stdin, "%s%d", s, &a); /* 从标准输入设备(键盘)上读取数据 */
        fprintf(fp, "%s %d", s, a); /* 以格式输出方式写入文件 */
        fclose (fp); /* 写文件结束关闭文件 */
        if ((fp=fopen("test", "r")) == NULL)   /* 以读方式打开文本文件 */
         { printf ("Cannot open file. ");
          exit(1);
         }
        fscanf (fp, "%s%d", s, &a); /* 以格式输入方式从文件读取数据 */
        fprintf(stdout, "%s %d ", s, a); /* 将数据显示到标准输出设备(屏幕)上 */
        fclose(fp); /* 读文件结束关闭文件 */
       }

    12.3.4 文件的数据块输入/输出函数

         这类函数是ANSI C标准对缓冲文件系统所做的扩充,以方便文件操作实现一次读写一组数据的功能。例如采用这种方式对数组和结构进行整体的输入输出是比较方便的。

    1.文件数据块读函数fread( )

         fread函数的调用形式:
         fread ( buffer, size, count, fp);

         其中:buffer是一个指针,是指向输入数据存放在内存区的起始地址;size是要输入的字节数;count是要输入大小为size个字节的数据块的个数;fp是文件指针。

         fread函数的功能是:对fp所指向的文件读取count次,每次读取一个大小为size的数据块,将读取的各数据块存到buffer指向的内存区。该函数的返回值是实际读取的count的值。

    2.文件数据块写函数fwrite( )

         fwrite函数的调用形式:
         fwrite ( buffer, size, count, fp);

         fwrite函数的参数及其功能与fread函数类似,只是对文件的操作而言是互逆的,一个是读取,一个是写入。

    例12-9:从键盘输入3个学生的数据,将它们存入文件student;然后再从文件中读出数据,显示在屏幕上。

       #include <stdio.h>
       #define SIZE 3
       struct student /* 定义结构 */
       { long num;
        char name[10];
        int age;
        char address[10];
       } stu[SIZE], out;

       void fsave ( )
       { FILE *fp;
        int i;
        if (( fp=fopen("student","wb")) == NULL )  /* 以二进制写方式打开文件 */
         { printf ("Cannot open file. "); /* 打开文件的出错处理 */
          exit(1); /* 出错后返回,停止运行 */
         }
        for (i=0; i<SIZE; i++) /* 将学生的信息(结构)以数据块形式写入文件 */
         if (fwrite(&stu[i], sizeof(struct student), 1, fp) != 1)
           printf("File write error. "); /* 写过程中的出错处理 */
        fclose (fp); /* 关闭文件 */
       }

       main ( )
       { FILE *fp;
        int i;
        for (i=0; i<SIZE; i++)   /* 从键盘读入学生的信息(结构) */
        { printf("Input student %d:", i+1);
         scanf ("%ld%s%d%s", &stu[i].num, stu[i].name, &stu[i].age, stu[i].address );
        }
        fsave( ); /* 调用函数保存学生信息 */
        fp = fopen ("student", "rb"); /* 以二进制读方式打开数据文件 */
        printf (" No. Name Age Address ");
        while ( fread(&out, sizeof(out), 1, fp) ) /* 以读数据块方式读入信息 */
         printf ("%8ld %-10s %4d %-10s ", out.num, out.name, out.age, out.address );
        fclose(fp); /* 关闭文件 */
       }

  • 相关阅读:
    ajax的基础知识
    前端必备的php的基础知识点
    关于事件的简单汇总
    Django rest-framework(目录)
    Django(目录)
    前端(目录)
    数据库知识(目录)
    数据库基础
    并发编程(目录)
    网络编程
  • 原文地址:https://www.cnblogs.com/socrates-lzstu/p/5374228.html
Copyright © 2011-2022 走看看