问题是如果文件末尾没有新行,则fgets显示错误。假设我有2个文本文件,如下,
text1.txt的内容:
German Hoy
43
68
Jesse Boster
88
29
text2.txt的内容:
German Hoy
43
68
Jesse Boster
88
29
我的问题:
当文件结束后还有一行时,程序对text2.txt运行正确。但是,如果我在文件的末尾没有一行,如text1.txt,则不会这样做。我怎样才能解决这个问题?我希望得到相同的结果,无论是否在文件的末尾有一行。 (在这两种情况下,它应该输出相同的结果)
以下是与问题相关的源代码的一部分:
while( fgets (s, 60, file)!=NULL ) {
s[strlen(s)-1] = '\0';
strcpy(tempName, s);
fgets(s, 60, file);
s[strlen(s)-1] = '\0';
sscanf(s, "%d", &tempMid);
fgets(s, 60, file);
s[strlen(s)-1] = '\0';
sscanf(s, "%d", &tempFinal);
setup(tempName, tempMid, tempFinal);
}
使用的系统是LINUX
答案 0 :(得分:3)
可选择剥离新行:
while( fgets (s, 60, file)!=NULL ) {
s[strcspn(s, "\n")] = '\0';
不要使用s[strlen(s)-1] = '\0';
,因为它可能是黑客攻击。 fgets()
读取空字符,就像任何其他非新行字符一样。行中的第一个字符可能是'\0'
,然后OP的代码调用未定义的行为。
此外,在OP代码中,甚至不需要删除潜在的新行字符。
fgets(s, 60, file);
// s[strlen(s)-1] = '\0';
sscanf(s, "%d", &tempMid);
最好测试sccanf()
的返回值或使用strtol()
。
答案 1 :(得分:2)
您可以在s
缓冲区末尾添加额外的新行,无论
fgets(s, 60, file);
length = strlen(s);
s[length] = '\n';
s[length+1] = '\0';
sscanf(s, "%d", &tempFinal);
重要提示:
您必须确保缓冲区长度至少为61个字符以适应新行。
答案 2 :(得分:1)
此代码大约是MCVE:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[60];
char tempName[60];
int tempMid;
int tempFinal;
FILE *file = stdin;
while (fgets(s, 60, file) != NULL)
{
s[strlen(s) - 1] = '\0';
strcpy(tempName, s);
if (fgets(s, 60, file) == NULL)
break;
s[strlen(s) - 1] = '\0';
sscanf(s, "%d", &tempMid);
if (fgets(s, 60, file) == NULL)
break;
s[strlen(s) - 1] = '\0';
sscanf(s, "%d", &tempFinal);
printf("[%s] %d %d\n", tempName, tempMid, tempFinal);
}
return 0;
}
它会将您编写的片段包含在main()
中,并带有两个标头,使其适应标准输入读取,并检查fgets()
调用是否都成功。
我打电话给程序fg17
。当你在两个数据文件上运行时,我得到:
$ fg17 < text1.txt
[German Hoy] 43 68
[Jesse Boster] 88 2
$ fg17 <text2.txt
[German Hoy] 43 68
[Jesse Boster] 88 29
$
这是我的预期,因为你的代码会删除最后一行的最后一个字符,无论它是否是换行符。如果您希望输出包含9
29
,那么您必须更加小心:
s[strcspn(s, "\n")] = '\0';
如果部署了3次更改,则两个程序的输出相同。
有什么区别? strcspn()
返回字符串参数中未找到的字符数 - 或返回空字节的字符数。如果没有换行符,则报告空字节,并且赋值用另一个空字节覆盖空字节 - 无操作。但它是可靠和安全的。