首页 > 解决方案 > fgets 正在返回一个空白屏幕

问题描述

我是 C 新手,这是我的第一个项目,并且一直在自学。在我的程序中,我的一个函数需要从文件中读取一行,并将其存储在一个 char 数组中。当我使用 gdb 跟踪程序时,数组 (line[]) 只是零。这导致我的程序返回错误“错误:资产文件中的一行缺少':'分隔符\ n”这是我的代码:

//return the line number (0 based) that the cmd is on, -1 if absent
int locateCmd(char cmd[]) {
        int lineIndex = -1;     //-1, because lineIndex is incramented before the posible return
        char cmdTemp[10] = "\0";

        //create a compareable cmd with correct cmd that has its remaining values zeroed out
        char cmdCmp[10] = "\0";
        memset(cmdCmp, 0, sizeof(cmdCmp));
        for (int i = 0; i < strlen(cmd); i++) {
                cmdCmp[i] = cmd[i];
        }

        FILE *file = fopen(ASSET_FILE, "r");

        //loop until target line is reached
        while (strcmp(cmdTemp, cmdCmp) != 0)  {
                //check if last line is read
                if (lineIndex == lineCounter(file)-1) {
                        return -1;
                }

                memset(cmdTemp, 0, sizeof(cmdTemp));
                char line[61];
                fgets(line, 61, file);
                //set cmdTemp to the command on current line
                lineIndex++;
                for (int i = 0; line[i] != ':'; i++) {
                        cmdTemp[i] = line[i];

                        //return error if line doesn't contain a ':'
                        if (line[i] = '\n') {
                        printf("Error: a line in the asset file lacks a ':' separator\n");
                        exit(1);
                        }
                }
        }

        return lineIndex;
}

在某些情况下,这个函数被传递了一个命令,它的工作是读取一个看起来像这样的文档:

command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand

并选择存储传递的命令 (cmd[]) 的行。

问题出在第 24 行的 fgets 上。我已将此代码的相关部分分离到一个较小的测试程序中,它工作正常。有效的测试程序是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[]) {
    FILE *file = fopen("tutorInfo.txt", "r");
    char line[61];
    fgets(line, 61, file);
    printf("%s\n", line);
}

我的测试程序的正确执行让我相信我的函数中的其他代码导致了这个问题,但我不确定是什么。需要注意的是,有问题的代码与我的示例程序具有相同的导入。任何帮助将非常感激。

标签: cfilefgets

解决方案


由于 OP 没有提供最小、完整和可验证的示例,我必须根据问题中提供的功能描述来回答。

我已经介绍了一些错误和极端情况,但我确定我错过了一些。该方法也效率低下,因为文件被一遍又一遍地读取,而不是解析一次并返回哈希/映射/目录以便于查找。在现实生活中的代码中,我会使用GLib之类的东西,而不是浪费时间尝试重新发明轮子……

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LINE_BUFFER_LENGTH 200

unsigned int locateCmd(FILE *fh, const char *key, const char **cmd_line) {
  unsigned int found = 0;
  size_t key_length = strlen(key);
  *cmd_line = NULL;

  /* make sure to start read from start of file */
  rewind(fh);

  unsigned int line_no = 0;
  static char buffer[LINE_BUFFER_LENGTH];
  while (!feof(fh) && (found == 0)) {
    // NOTE: EOF condition will be checked on the next iteration
    fgets(buffer, sizeof(buffer), fh);
    size_t length = strlen(buffer);
    line_no++;

    if (buffer[length - 1] != '\n') {
      printf("line %u is too long, aborting!\n", line_no);
      return(0);
    }

    if ((strncmp(key, buffer, key_length) == 0) &&
        (buffer[key_length] == ':')) {
      found              = line_no;
      buffer[length - 1] = '\0'; // strip line ending
      *cmd_line          = &buffer[key_length + 1];
    }
  }

  return(found);
}

int main(int argc, char *argv[]) {
  FILE *fh = fopen("dummy.txt", "r");
  if (!fh) {
    perror("file open");
    return(1);
  }

  int ret = 0;
  while (--argc > 0) {
    const char *cmd;
    const char *key  = *++argv;
    unsigned line_no = locateCmd(fh, key, &cmd);
    if (line_no != 0) {
      printf("key '%s' found on line %u: %s\n", key, line_no, cmd);
      ret = 0;
    } else {
      printf("key '%s' not found!\n", key);
    };
  }

  if (fclose(fh) != 0) {
    perror("file close");
    return(1);
  }

  return(ret);
}

测试输入dummy.txt

command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand
brokenline

foo:bar
toolong:sadflkjaLKFJASDJFLKASJDFLKSAJ DLFKJ SLDKJFLKASDFASDFKJASKLDJFLKASJDFLKJASDLKFJASLKDFJLKASDJFLKASJDLFKJASDKLFJKLASDJFLKSAJDFLKJASDLKFJKLASDJFLKASJDFKLJASDLKFJLKASDJFLKASJDFLKJSADLKFJASLKDJFLKC

一些测试运行:

$ gcc -Wall -o dummy dummy.c
$ ./dummy command foo bar
key 'command' found on line 1: aBunchOfInfoOnTheComand
key 'foo' found on line 5: bar
line 6 is too long, aborting!
key 'bar' not found!

推荐阅读