其他分享
首页 > 其他分享> > (十五)文件 -- 4. 面向行的I/O

(十五)文件 -- 4. 面向行的I/O

作者:互联网

4. 面向行的I/O

由于文件通常被划分成行,因此很有必要一次读入整行数据。

stdio.h中执行这一操作的函数为fgets,其函数原型为:

string fgets(char buffer[], int bufsize, FILE *infile);

此函数的作用在于将下一行文件读入字符数组buffer中。

通常,fgets在读入第一个换行字符后停止读取,但如果该行的长度超过了由函数参数bufsize限定的长度,则fgets函数将提前返回。

因此,buffer数组中表示终止的空字符前应为一换行符,除非该行文件过长,超出buffer的限制。


无论fgets读入的是一整行还是此行的一部分,通常情况下都会返回一个指针,指向函数中的第一个参数(即字符数组buffer)。

如果fgets在文件的末尾调用,则返回NULL


相应的输出函数为fputs,其函数原型为

void fputs(string str, FILE *outfile);

调用函数fputs可将字符从一个字符串复制到输出文件,直至达到该字符串的末尾为止。


可以利用fgetsfputs来实现 上一节 中介绍的函数CopyFile,该程序如下所示:

static void CopyFile(FILE *infile, FILE *outfile) {
    char buffer[MaxLine];
    while (fgets(buffer, MaxLine, infile)!=NULL) {
        fputs(buffer, outfile);
    }
}

当使用函数fgets时,必须为输入行提供一个缓冲区。

CopyFile这个例子中,数组的空间是由声明

char buffer[MaxLine];

在当前帧中显式分配的。

需要注意的是,此缓冲区的内存空间将在函数返回时释放。

如果想要将行中的字符更长久地存储起来,需将它们存储在函数调用结束后仍然存在的内存空间中。
通常来说,从堆中动态分配内存是一种更简便的方法。


如果对多次fgets调用使用同一个临时缓冲区,则需要为之分配新的内存空间。

仅有赋值是不够的。例如,下面的代码从一个输入文件中读入两行数据,并将它们存储在字符串变量line1line2中:

void ReadTwoLines(FILE *infile) {
    char buffer[MaxLine];
    string line1, line2;
    fgets(buffer, MaxLine, infile);
    line1 = buffer;
    fgets(buffer, MaxLine, infile);
    line2 = buffer;
}

上述代码使得line1line2的内容相同,出现这样的问题是因为,变量buffer虽然在概念上是一个字符串,在内存中占有特定的空间,但赋值语句:

line1=buffer;

仅仅将buffer的地址赋给了变量line1

当程序继续执行,要重新利用这块空间读入第二行文件时,同一块空间就用来存放第二个字符串了。

这样变量line1line2最终指向了相同的内存,因此两者的值是相同的字符串。


常见错误:

如果使用同一个字符缓冲区从同一个文件中读入多行,要记住在读入下一行数据之前,需要将数据从缓冲区中复制到其他存储空间。

如果不进行这样的操作,前一行的内容将被覆盖。


解决这个问题的办法之一是利用strlib库中的函数CopyString将每一个字符串写入各自的堆内存中,如下所示:

void ReadTwoLines(FILE *infile) {
    char buffer[MaxLine];
    string line1, line2;
    fgets(buffer, MaxLine, infile);
    line1 = CopyString(buffer);
    fgets(buffer, MaxLine, infile);
    line2 = CopyString(buffer);
}

另外一个解决方案就是利用在simpio.h中定义的函数ReadLine,它可以避免与fgets相关的其他问题:


fgets相比,ReadLine具有以下优点:

函数ReadLine在遇到文件结束符时返回NULL





参考

《C语言的科学和艺术》 —— 15 文件

标签:读入,--,buffer,十五,缓冲区,fgets,MaxLine,infile,面向
来源: https://blog.csdn.net/m0_38111466/article/details/117063108