如何在C程序中读取文本文件的最后一行?



我正在尝试学习C语言,基本上我想做的是读取一个文件并将其放入我创建的结构体中,然后我将使用该结构体做其他事情,但我想先完成第一部分。比方说,我有一个文本文件,名称为caps。txt,其内容为:

picard 95
janeway 90
pike 15

(注意最后一行是'pike 15')

所以我创建了一个像这样的程序:
#include <stdio.h>
#include <stdlib.h> //for exit()
#include <string.h>
#include <ctype.h>
struct captain
{
char capName[10];
int number;
};
typedef struct captain captain;
int main()
{
FILE* file = fopen("captain.txt","r");
if (file == NULL)
{
printf("nerror opening file");
exit(1);
}
else{
printf("nfile is opened");
}
char buffer[50];
fgets(buffer,50,file);
while (!feof(file))
{
captain c;
sscanf(buffer, "%s %d", &c.capName, &c.number);
printf("nc captain is: %s %d", c.capName, c.number);
fgets(buffer,50,file);
}
fclose(file);
return 0;
}

控制台上的输出是

file is opened
c captain is: picard 95
c captain is: janeway 90
Process returned 0 (0x0)   execution time : 0.006 s
Press any key to continue.

因此派克船长在太空中失踪了…因为当我向文本文件中添加新行时它会变成这样:

picard 95
janeway 90
pike 15

(注意'pike 15'后面的换行符)

那么我的输出就正确了。所以我知道我的程序没有解释文件末尾缺少换行符的原因……怎么解呢?

比较这两个程序,一个(错误地)使用feof(),另一个根本不使用它。第一种方法与问题中的代码非常接近——它忽略了fgets()的返回值,这对它不利。第二种方法只测试fgets()的返回值;不需要使用feof()

eof53.c

#include <stdio.H>
int main(void)
{
char buffer[256];
fgets(buffer, sizeof(buffer), stdin);
while (!feof(stdin))
{
printf("[%s]n", buffer);
fgets(buffer, sizeof(buffer), stdin);
}
return 0;
}

eof71.c

#include <stdio.H>
int main(void)
{
char buffer[256];
while (fgets(buffer, sizeof(buffer), stdin) != NULL)
printf("[%s]n", buffer);
return 0;
}

给定一个包含3字节的数据文件abc- 0x41 ('A'), 0x42 ('B'), 0x43 ('C')并且没有换行符,我得到以下结果:

$ eof53 < abc
$ eof71 < abc
[ABC]
$

在MacOS Big Sur 11.6.6上进行了测试。

请注意,fgets()在读取(仅)不完整的行时不会报告EOF(通过返回空指针),但根据经验,feof()确实会报告EOF -正确,因为文件输入已经结束,即使fgets()确实返回一个字符串(但不是一行)的数据。

正如规范的Q&Awhile (!feof(file))总是错误的!使用feof()而不是测试I/O函数的返回值会导致不好的结果。

最新更新