【问题标题】:fgets returning NULL even though file is not empty [closed]即使文件不为空,fgets也返回NULL [关闭]
【发布时间】:2018-11-27 04:22:35
【问题描述】:

我有以下代码:

void readFile(FILE* fp)
{
    int lines = 4;
    char* line = (char*)malloc(sizeof(char)*100);
    int i;
    for(i = 0; i < lines; i++)
    {
        if(fgets(line, 100, fp)!=NULL)
        {
            printf("\n FGETS NOT NULL \n");
            printf("%s\n", line);
        }
    }
    free(line);
}

int main(int argc, char** argv)
{
    FILE* fp = fopen("t.txt", "r");
    if(fp==NULL)
    {
       printf("Error.\n");
       exit(0);
    }
    readFile(fp);
    return 0;
}

我传递给函数的文件包含:

add $s0 $s1 $s2
sub $s2 $s3 $s6
addi $s2 $s3 15
haltSim

我没有得到任何输出。出于某种原因,fgets 总是返回 NULL。任何帮助将不胜感激!

【问题讨论】:

  • fopen("t.txt", "r"); 是成功还是失败?你怎么知道的? (提示:if (fp == NULL) { perror ("fopen-t.txt"); return 1; } -- 然后是readFile(fp);
  • @DavidC.Rankin 我忘了在此处编写代码时包含检查。已编辑。据我所知,没有错误。
  • 好的,这就是像拇指酸痛一样突出的东西。除了更好地使用固定缓冲区(例如char line[100]; 而不是分配)之外,您对fgets 的使用没有什么明显的。使用您的代码和数据文件,我得到"FGETS NOT NULL\nadd $s0 $s1 $s2...."
  • char* line = (char*)malloc(sizeof(char)*100); 最好写成char *line = malloc(100);。强制转换是不必要的(并且在某些情况下可以掩盖错误),sizeof (char) 根据定义为 1。或者只是char line[100;
  • 在对其中一个答案的评论中,您写道:“代码是一个更小的 [更大?] 项目的一部分(readFile 实际上解析输入并从中创建一个结构,但我“所以问题中的程序没有出现问题——你没有告诉我们。问题在于您没有向我们展示的代码。

标签: c fopen fgets


【解决方案1】:

添加到 paulsm4 的答案,我会更进一步,避免硬编码文件名。 (不要使用幻数或硬编码文件名)

不需要malloc,你会想要阅读Do I cast the result of malloc?。而是使用固定缓冲区很好(但不要跳过)。

例如

#include <stdio.h>

#define MAXC 1024   /* don't SKIMP on buffer size */

void readFile (FILE* fp)
{
    char line[MAXC];

    while (fgets (line, MAXC, fp) != NULL)
    {
        printf("\n FGETS NOT NULL \n");
        printf("%s\n", line);
    }
}

int main (int argc, char **argv)
{
    /* read file given as argv[1] or stdin if no argument given.
     * don't hardcode filenames
     */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    readFile(fp);

    return 0;
}

记住 fgets 读取并在其填充的缓冲区中包含尾随 '\n',因此您可能希望将 printf("%s\n", line); 替换为 printf ("%s", line); 或只是 fputs (line, stdout);

使用/输出示例

$ ./bin/fgetsnull t.txt

 FGETS NOT NULL
add $s0 $s1 $s2


 FGETS NOT NULL
sub $s2 $s3 $s6


 FGETS NOT NULL
addi $s2 $s3 15


 FGETS NOT NULL
haltSim

如果您还有其他问题,请告诉我。

【讨论】:

  • 嗯.. 所以我只是在 linux 发行版上尝试过这个,它似乎工作正常。使用 Cygwin 尝试相同的代码会导致没有输出。这可能与我使用 Cygwin 的事实有关吗?
  • 它不应该有什么不同,(即使有不同的行尾 CRLFLF)。尽管这是我唯一能想到的,但系统之间会有所不同。 Cygwin 在 Windows 上的行为应该与 Linux 上的代码相同(这是标准的目的) 在 Cygwin 环境中是否可能看不到 "t.txt"?我在 Windows 和 VS 上安装 Linux、MinGW 的原因,代码的行为完全一样。
  • 代码是一个小得多的项目的一部分(readFile 实际上解析输入并从中创建一个结构,但我在调试时注释掉了该部分,包括 printf 语句)。奇怪的是,每当我尝试仅使用 main 和 readFile 运行程序时,它都可以正常工作;但是在较大项目的一部分中运行它们会导致没有输出。 (我不认为有任何干扰代码,因为我将大部分代码注释掉以进行调试)。
  • 现在我们到了某个地方...由于您使用另一个堆栈变量或在您读取的函数或 main 中使用未分配的指针,您可能会遇到 Undefined Behavior导致奇怪的行为。编辑并发布实际代码,我敢打赌我可以把它挑出来:)
【解决方案2】:

这是一个略有不同的版本:

#include <stdio.h>

#define MAXLINES 4
#define MAXLEN 100

void readFile(FILE* fp)
{
    char line[MAXLEN];
    int n = 0;
    while ((fgets(line, MAXLEN, fp)) && n < MAXLINES) {
      printf("n: %d, %s\n", n, line);
      ++n;
    }
}

int main(int argc, char** argv)
{
    FILE* fp;
    if (argc < 2) {
      printf ("USAGE: myprog <filename>\n");
      return 1;
    }
    fp = fopen(argv[1], "r");
    if (!fp) {
      perror("File open error");
      return 1;
    }
    readFile(fp);
    fclose (fp);
    return 0;
}

我完全不确定您的原始版本有什么问题 - 如果您有兴趣,单步调试调试器可能会有所帮助。

但有几点:

  1. 你不想要像 4 或 100 这样的“幻数”

  2. 如果您不需要 malloc() - 那就不要。只需声明一个数组。

  3. 如果您在循环中读取文件 - 最好将循环与实际 I/O 绑定(并可能添加辅助检查,如“小于 MAXLINES”)。

  4. 如果可能,从 main 中“return”优于“exit()”。

【讨论】:

  • 我刚刚在 linux 发行版上尝试了我的代码,它似乎工作正常。使用 Cygwin 尝试相同的代码会导致没有输出。这可能与我使用 Cygwin 的事实有关吗?
  • @Rish 1) 在printf() 之后添加fflush(stdout); 以确保输出。 2)添加一些printf("Hello World\n"),即使没有行打印。
  • 嗨 - 我无法想象在 Cygwin 命令提示符下运行一定会有所作为。这里发生了“其他事情”。问:你的编译器是什么? Q:上面的sn-p需要#include &lt;stdio.h&gt;才能编译。您发布的 sn-p 是否还缺少其他内容?问:您是否使用调试器单步执行?问:EVERYALWAYS 是否返回“NULL”?问:如果您创建不同的文件(例如使用 Windows“记事本”)会发生什么?
  • @paulsm4 代码是一个小得多的项目的一部分(readFile 实际上解析输入并从中创建一个结构,但我在调试时注释掉了该部分,包括 printf 语句)。奇怪的是,每当我尝试仅使用 main 和 readFile 运行程序时,它都可以正常工作;但是在较大项目的一部分中运行它们会导致没有输出。 (我不认为有任何干扰代码,因为我将大部分代码注释掉以进行调试)。 1) gcc 2) 是的,包含所有标题 3) 每行返回一个 NULL 4) 没有变化,使用不同的编辑器或环境。
  • @Rish:我刚刚在 Cygwin 上尝试了您的程序,但没有重现问题。我假设你的意思是它是一个更大的项目的一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-04
  • 1970-01-01
  • 2020-11-29
  • 2020-06-08
  • 1970-01-01
  • 2012-08-26
相关资源
最近更新 更多