"fgets" 在 while 循环中的意外行为
Unexpected behavior from "fgets" in a while loop
我正在尝试使用 fgets 逐行读取文件,但它不起作用。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_SIZE 500
int main(int argc, char const *argv[])
{
char *line;
FILE *arq;
//abre o arquivo para leitura
if ((arq = fopen (argv[1], "r")) == NULL){
printf ("erro ao abrir arquivo\n");
exit (1);
}
//aloca espaco para a linha
if ((line = (char*) calloc (MAX_LINE_SIZE, sizeof(char))) == NULL){
printf ("erro ao alocar memoria\n");
exit (1);
}
//para cada linha
while (fgets (line, MAX_LINE_SIZE, arq) != NULL){
printf ("%s\n", line);
}
//desaloca a memoria
free (line);
//fecha o arquivo
fclose (arq);
return 0;
}
如果我的输入文件的第一行短于 MAX_LINE_SIZE 中指定的大小,在同一交互中,fgets 开始用第二行的内容覆盖第一行的内容。例如,将 MAX_LINE_SIZE = 14 与此输入文本一起使用:
AAAAAAA
BBBBBBBBBB
我得到这个输出:
Gabriels-MacBook-Air:Desktop Gabriel$ make
gcc teste.c;./a.out input.txt
BBBBBAA
BBBBB
我认为fgets方法是识别换行符,然后,它将写入指针移动到字符串的开头并继续读取直到到达MAX_INE_SIZE。但为什么?有人可以帮我吗?谢谢!
也许您的文件包含与您的平台不匹配的行尾?如果您的文件使用 CR 作为行尾(旧 MacOS)并且您 运行 在类 Unix 平台上这样做,您会得到这种行为。
代码编译正常,定义为 MAX_LINE_SIZE = 14。我尝试了几种不同的方法来获取输出,唯一可行的方法是替换你的 space 字符用 ^M 输入 "AAAAAAA BBBBBBBBBB"。所以您可能想查看您的输入文件并查看其中是否有 ^M。 ^M 是 ASCII 13,它是一个马车 return.
除此之外,代码使用 clang 在 FreeBSD 机器上编译。正如有人提到的那样,强烈建议不要转换 malloc、realloc、calloc 和其他内存分配函数的结果。也不需要它,因为 void* 与所有指针类型兼容。
另外。我必须将以下行添加到测试程序的顶部以获得带有 1 个警告的编译:
#include <stdio.h>
#include <stdlib.h>
#define MAX_LINE_SIZE 14
所以你的代码确实有效,我相信问题出在输入中。
我正在尝试使用 fgets 逐行读取文件,但它不起作用。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_SIZE 500
int main(int argc, char const *argv[])
{
char *line;
FILE *arq;
//abre o arquivo para leitura
if ((arq = fopen (argv[1], "r")) == NULL){
printf ("erro ao abrir arquivo\n");
exit (1);
}
//aloca espaco para a linha
if ((line = (char*) calloc (MAX_LINE_SIZE, sizeof(char))) == NULL){
printf ("erro ao alocar memoria\n");
exit (1);
}
//para cada linha
while (fgets (line, MAX_LINE_SIZE, arq) != NULL){
printf ("%s\n", line);
}
//desaloca a memoria
free (line);
//fecha o arquivo
fclose (arq);
return 0;
}
如果我的输入文件的第一行短于 MAX_LINE_SIZE 中指定的大小,在同一交互中,fgets 开始用第二行的内容覆盖第一行的内容。例如,将 MAX_LINE_SIZE = 14 与此输入文本一起使用:
AAAAAAA
BBBBBBBBBB
我得到这个输出:
Gabriels-MacBook-Air:Desktop Gabriel$ make
gcc teste.c;./a.out input.txt
BBBBBAA
BBBBB
我认为fgets方法是识别换行符,然后,它将写入指针移动到字符串的开头并继续读取直到到达MAX_INE_SIZE。但为什么?有人可以帮我吗?谢谢!
也许您的文件包含与您的平台不匹配的行尾?如果您的文件使用 CR 作为行尾(旧 MacOS)并且您 运行 在类 Unix 平台上这样做,您会得到这种行为。
代码编译正常,定义为 MAX_LINE_SIZE = 14。我尝试了几种不同的方法来获取输出,唯一可行的方法是替换你的 space 字符用 ^M 输入 "AAAAAAA BBBBBBBBBB"。所以您可能想查看您的输入文件并查看其中是否有 ^M。 ^M 是 ASCII 13,它是一个马车 return.
除此之外,代码使用 clang 在 FreeBSD 机器上编译。正如有人提到的那样,强烈建议不要转换 malloc、realloc、calloc 和其他内存分配函数的结果。也不需要它,因为 void* 与所有指针类型兼容。
另外。我必须将以下行添加到测试程序的顶部以获得带有 1 个警告的编译:
#include <stdio.h>
#include <stdlib.h>
#define MAX_LINE_SIZE 14
所以你的代码确实有效,我相信问题出在输入中。