【问题标题】:fscanf() in C, format for varying length lineC 中的 fscanf(),用于变长行的格式
【发布时间】:2020-02-18 16:06:07
【问题描述】:

所以我有一个文件,其中包含以下形式的数据:

...
5,25,15,16,1,3,Dwyfor_Meirionnydd
5,34,33,26,12,22,Gower
5,7,28,35,4,23,Islwyn
2,20,12,Llanelli
5,4,5,17,7,21,Merthyr_Tydfil_and_Rhymney
5,5,4,35,28,27,Monmouth
4,5,14,19,15,Montgomeryshire
7,0,32,17,5,12,20,33,Neath
2,38,24,Newport_East
...

我需要读取每一行并将其放入结构中,以便存储第一个无符号整数,接下来的 n 个无符号整数存储在数组中,然后存储最后的字符串。例如,第二行是:

number-of-elements: 5
array: {34,33,26,12,22}
name: "Gower"

number 告诉我们array 中有多少项目。我有这个数据的结构。我将如何为此创建格式?

【问题讨论】:

  • 类似struct{int length, int *data, char *name};malloc
  • 这被称为 CSV(逗号分隔变量)解析,并且有许多 CSV 解析策略,但如果我从头开始这样做,我最喜欢的是将文件分成几行,然后中断这条线变成一个字符串数组,然后变成数字等。
  • @Owl 大多数(全部?)CSV 解析器都不擅长处理这种特定格式,因为它们需要表格数据。 OP 的数据不是表格(所有行的列数不相等,数据实际上是嵌套的)。
  • , 是分隔符 - 读取每个石灰,直到找到 \n 并在读取新行时 - 使用临时 char 数组从文件中读取和存储字符,直到遇到分隔符 - 发现使用 atoimemset 临时数组。阅读整篇文章直到EOF - 我的评论中缺少很多你需要弄清楚的东西
  • 我确实有一个现有的结构,第一个整数告诉我们数组中有多少项。 (为清楚起见,已编辑问题)

标签: c file file-io


【解决方案1】:

通常你只需要在一个循环中单独调用 fscanf 来读取元素:

struct entry {
    int   data_size;
    int   *data;
    char  *name;
};


while (fscanf(input, "%d", &num) == 1) {
    struct entry *e = malloc(sizeof *e);
    e->data_size = num;
    e->data = malloc(num * sizeof e->data[0]);
    for (int i = 0; i < num; ++i) {
        if (fscanf(input, " ,%d", &e->data[i]) != 1) {
            fprintf(stderr, "Data format error\n");
            exit(1); } }
    if (fscanf(input, " ,%ms", &e->name) != 1) {
        fprintf(stderr, "Data format error\n");
        exit(1); }
    // read a record into 'e' -- store it into a data structure somewhere
}

【讨论】:

    【解决方案2】:

    scanf 函数不支持可变数量的格式。您需要根据元素的数量更改传递给函数的内容。

    处理此问题的最佳方法是读取一行,然后使用strtok 将其拆分为标记,然后使用sscanf 解析出循环中的每个单独元素。

    char line[100];
    while (fgets(line, sizeof(line), fp)) {
        int count, i;
        int *array;
        char *name, *p;
    
        // read the count
        p = strtok(line, ",");
        sscanf(p, "%d", &count);
    
        // allocate space for the array
        array = malloc(count * sizeof(int));
        // read each element
        for (i=0; i<count; i++) {
            p = strtok(NULL, ",");
            sscanf(p, "%d", array + i);
        }
    
        // read the name
        p = strtok(NULL, "\n");
        name = strdup(p);
    
        // do something with count, array, and name
    }
    

    请注意,这假定文件中的每一行格式正确,因此不会验证格式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多