即使文件不为空,fgets仍返回NULL

时间:2018-11-27 04:22:35

标签: c fopen fgets

我有以下代码:

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。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:3)

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

#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”之类的辅助检查)。

    < / li> 在可能的情况下,
  4. 从main返回“ return”优于“ exit()”。

答案 1 :(得分:3)

除了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

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