提问人:Emil Lang 提问时间:5/26/2022 最后编辑:Jonathan LefflerEmil Lang 更新时间:5/27/2022 访问量:314
如何在 C 程序中读取文本文件的最后一行?[复制]
How do I read the last line of a text file in a C program? [duplicate]
问:
我正在尝试学习 C 语言,基本上我想做的是读取一个文件并将其放入我创建的结构中,然后稍后我将使用该结构做其他事情,但我想先完成第一部分。假设我有一个名为 captains.txt 的文本文件,内容是:
picard 95
janeway 90
pike 15
(请注意,最后一行只是“派克 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”后面的换行符)
然后我的输出变得正确。所以我知道我的程序没有考虑到文件末尾缺少换行符的问题......那么我该如何解决这个问题呢?
答:
1赞
Jonathan Leffler
5/27/2022
#1
比较这两个程序,一个(错误)使用,一个根本不使用它。第一个与问题中的代码密切相关——它忽略了 from 的返回值,这对它不利。第二个仅测试 ;它没有必要使用.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 个字节的数据文件——0x41 ()、0x42 ()、0x43 () 且没有换行符,我得到以下结果:abc
'A'
'B'
'C'
$ eof53 < abc
$ eof71 < abc
[ABC]
$
这是在 MacOS Big Sur 11.6.6 上测试的。
请注意,在读取(仅)不完整的行时,不会报告 EOF(通过返回空指针),但根据经验,确实会报告 EOF——正确,因为文件输入已结束,即使确实返回了数据字符串(但不是一行)。fgets()
feof()
fgets()
正如规范问答中所解释的,while (!feof(file))
is always wrong!,使用而不是测试 I/O 函数的返回值会导致糟糕的结果。feof()
评论
fgets()
{LINE_MAX}
字节,没有NUL
字符,每个字符都以<换行符>
结尾。该定义允许将具有单个<换行符>
或完全空的文件的文件称为文本文件。如果文件以不完整的行结尾,则根据此定义,它不是严格意义上的文本文件。