如何在 C 程序中读取文本文件的最后一行?
How do I read the last line of a text file in a C program?
我正在尝试学习 C 语言,基本上我想做的是读取一个文件并将其放入我创建的结构中,然后我将用该结构做其他事情,但我想先通过第一部分。假设我有一个名为 captains.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.
因此派克船长在 space 中不见了......几乎是字面意思,因为当我向文本文件添加新行时,它变成了这样:
picard 95
janeway 90
pike 15
(注意'pike 15'后的换行符)
然后我的输出就正确了。所以我知道我的程序没有考虑文件末尾缺少换行符的问题......那么我该如何解决这个问题?
比较这两个程序,一个(误)使用 feof()
和一个根本不使用它。第一个与问题中的代码密切相关——它忽略了 fgets()
中的 return 值而不利于它。第二个只测试来自 fgets()
的 return 值;它不需要使用 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(通过 return 空指针),但根据经验,feof()
确实会报告 EOF — 正确, 由于文件输入已经结束,即使 fgets()
做了 return 一个字符串(但不是一行)数据。
如规范问答 while (!feof(file))
is always wrong! 中所述,使用 feof()
而不是测试 I/O 函数中的 return 值会导致错误结果。
我正在尝试学习 C 语言,基本上我想做的是读取一个文件并将其放入我创建的结构中,然后我将用该结构做其他事情,但我想先通过第一部分。假设我有一个名为 captains.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.
因此派克船长在 space 中不见了......几乎是字面意思,因为当我向文本文件添加新行时,它变成了这样:
picard 95
janeway 90
pike 15
(注意'pike 15'后的换行符)
然后我的输出就正确了。所以我知道我的程序没有考虑文件末尾缺少换行符的问题......那么我该如何解决这个问题?
比较这两个程序,一个(误)使用 feof()
和一个根本不使用它。第一个与问题中的代码密切相关——它忽略了 fgets()
中的 return 值而不利于它。第二个只测试来自 fgets()
的 return 值;它不需要使用 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(通过 return 空指针),但根据经验,feof()
确实会报告 EOF — 正确, 由于文件输入已经结束,即使 fgets()
做了 return 一个字符串(但不是一行)数据。
如规范问答 while (!feof(file))
is always wrong! 中所述,使用 feof()
而不是测试 I/O 函数中的 return 值会导致错误结果。