c - 为什么 fgets 可以在两次调用时正常工作?

标签 c fgets

我是 C 语言的新手(几年)。我想知道为什么 fgets() 可以很好地处理两个调用,而不是一个。变量是:

  FILE *dat;
  int i; 
  char buff [22];
  char *file; 
  i = 0;
  dat = fopen(file__dat, "r");

这是包含两个调用的代码:

    for (i = 0; i < num; i++) {
        fgets(buff, 22, dat);
        printf("%s\n", buff);
        file = strtok(buff, ",");
        strcpy (aparell [i].Name, file);
        file = strtok(NULL, ",");
        strcpy(aparell[i].MAC, file);
        fgets(buff, 22, dat);
    }

一个电话:

    for (i = 0; i < num; i++) {
        fgets(buff, 22, dat);
        printf("%s\n", buff);
        file = strtok(buff, ",");
        strcpy(aparell [i].Name, file);
        file = strtok(NULL, ",");
        strcpy(aparell[i].MAC, file);
    }

文件是:

CTRL-000,31A0E321456C
CTRL-001,AE45F3123BAA
CTRL-002,2956FECA24A3
CTRL-003,AA345FCC23FA
CTRL-004,FA345778123A
CTRL-502,34F45A3423DD 

提前致谢。 :)

最佳答案

第一个fgets(buff, 22, dat);从流中读取最多21个字节,正好是换行序列前第一行的字节数:CTRL-000,31A0E321456C.

随后的 strtok() 调用确实找到了标记,并且该行被正确解析。

在循环的下一次迭代中,fgets(buff, 22, dat); 读取换行符并停在那里,导致第二个 strtok 失败并返回 。由于您不测试返回值,strcpy (aparell[i].MAC,file); 具有未定义的行为,因为 file 是空指针。

当您添加一个额外 fgets() 时,换行符被读取并被忽略,下一次迭代读取下一行。

您应该通过增加缓冲区大小并测试 fgets()strtok() 的返回值来修复代码,以避免未定义的行为。您还应该将 \n 视为分隔符,以避免将其包含在最后一个字段中。

这是一个改进的版本:

char buff[128];

for (i = 0; i < num; i++) {
    if (!fgets(buff, sizeof buf, dat)) {
        fprintf(stderr, "missing input\n");
        break;
    }
    printf("%s", buff);
    file = strtok(buff, ",\n");
    if (file == NULL) {
        fprintf(stderr, "invalid input\n");
        break;
    }
    strcpy(aparell[i].Name, file);
    file = strtok(NULL, ",\n");
    if (file == NULL) {
        fprintf(stderr, "invalid input\n");
        break;
    }
    strcpy(aparell[i].MAC, file);
}

请注意,在使用 strcpy() 复制到结构字段之前,您还应该检查字符串的长度。

另请注意,strtok() 在解析输入时有一个缺点:它将任何分隔符序列视为单个分隔符。因此它无法处理空字段,例如 ,31A0E321456CCTRL-000,

关于c - 为什么 fgets 可以在两次调用时正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49877987/

相关文章:

c - Open MP Schedules - 寻找循环的最佳参数

c++程序来监视目录的更改

c - 使用 fgets( ) - 内存效率最高的方法

c - 运行多个并发 GMainLoops

c++ - 如何在 C 中使用 printf() 格式化在 double 前面保留空格

c - 使用 dyn.load 在 R x64 中加载已编译的 c 代码的问题

c - strtok() C 字符串到数组

c - fgets 不提示用户输入。有什么不同?

c - gets() 不要求输入,除非在它之前使用 getchar() 或另一个 gets()

c - fgets 中是否需要尾随换行符?