【问题标题】:Reading an arbitrary number of space-separated chars from a line in file从文件中的一行读取任意数量的空格分隔字符
【发布时间】:2017-09-07 19:41:32
【问题描述】:

我有一个文件,其中一行有任意数量的数字作为整数读取。在一个最小的、可重现的示例中,我创建了一个文件 test.dat,其中仅包含以下行:

 1 2 3 4

然后我尝试使用fgetsstrtok 来实现:

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

int main(){

FILE* fileptr;

fileptr = fopen("test.dat","r");
char line[500];
char *token;

int array[20];
int i = 0;

fgets(line,300,fileptr);

token = strtok(line," ");
array[i] = atoi(token);
printf("%d\n", array[i]);
i++;

while(token != NULL){
    token = strtok(line," ");
    array[i] = atoi(token);
    printf("%d\n", array[i]);
    i++;
}

return 0;
}

但这会导致打印 21 行 1's,然后是 632 行 0's。最后它给出了一个分段错误,因为i 增长大于 20,即为array 分配的空间。我不明白为什么要打印 600 多行,以及为什么我永远无法读取文件中的数字 1。我错过了什么?

注意:我更喜欢使用 fgets 从文件中继续读取,因为这将是对读取整个文件的现有子例程的简单修改。

【问题讨论】:

  • 嗯,不清楚为什么fgets(line,300,fileptr); 中有 300。我希望fgets(line,sizeof line,fileptr);
  • @chux 没有充分的理由——我没有编写该行的原始代码。我会修复它。谢谢。
  • 如果目标是获得“空格分隔的字符”,那么strtok() 就可以了。然而,由于该令牌立即运行彻底atoi(),使用strtol() 而不是strtok()/atoi()更有意义,如parsing a string of multiple whitespace separated integers

标签: c fgets strtok


【解决方案1】:

一些事情:

  • 您没有将循环限制在array 的能力范围内
  • 您的循环结构不正确。所有存储都应在循环内完成;异常值先验不需要存在。
  • 您在循环中调用strtok 是错误的。 strtok 的初始起始的延续应指定 NULL 作为第一个参数。有关更多信息和使用示例,请参阅 strtok 的文档。

这里有一个解决这些问题的例子:

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

int main()
{
    FILE* fileptr = fopen("test.dat","r");
    if (fileptr == NULL)
    {
        perror("Failed to open file: ");
        return EXIT_FAILURE;
    }

    char line[500];
    int array[20];
    const size_t max_size = sizeof array / sizeof *array;
    size_t i = 0;

    if (fgets(line,300,fileptr))
    {
        char *token = strtok(line," ");
        while (i < max_size && token != NULL)
        {
            array[i] = atoi(token);
            printf("%d\n", array[i]);
            ++i;
            token = strtok(NULL, " ");
        }

        // use array and i for whatever you needed
    }

    return EXIT_SUCCESS;
}

输出

1
2
3
4

【讨论】:

  • 感谢您的详细回答。第一次调用后将NULL 传递给strtok 背后的逻辑是什么?
  • @sodiumnitrate 见the documentation of strtok。它将比我更好地解释其目的,并为您提供一个出色的网站,以便在此过程中为将来的查询添加书签。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多