解析C中一行中不同类型整数的变量数

解析C中一行中不同类型整数的变量数,c,parsing,arguments,scanf,fgets,C,Parsing,Arguments,Scanf,Fgets,我有一个文件,其中的行由“\n”分隔,其中每一行看起来像 10010 0 19 7 18 或 也就是说,每一行总是有5个或7个空格分隔的值,并且每个值的类型也是事先知道的。我想逐行读取文件,并解析每一行以提取inttypes(SCNi32、SCNu32、SCNx32..)并存储在相应的inttype变量中。最简单的方法是什么?我是C的新手 使用fgets()读取该行。通过将该行拆分为标记来解析该行 使用strtok()将行拆分为令牌 使用atoi()或任何其他字符串将令牌转换为整数 您可能应该

我有一个文件,其中的行由“\n”分隔,其中每一行看起来像

10010 0 19 7 18

也就是说,每一行总是有5个或7个空格分隔的值,并且每个值的类型也是事先知道的。我想逐行读取文件,并解析每一行以提取inttypes(SCNi32、SCNu32、SCNx32..)并存储在相应的inttype变量中。最简单的方法是什么?我是C的新手

  • 使用
    fgets()读取该行。
    通过将该行拆分为标记来解析该行

  • 使用
    strtok()
    将行拆分为令牌

  • 使用
    atoi()
    或任何其他字符串将令牌转换为整数


  • 您可能应该创建一个结构来存储它们,例如:

    typedef struct
    {
      int16_t   a;
      uint32_t  b;
      int8_t    c;
      ...
    } int_stuff_t;
    
    然后你可以写一个长长的列表,比如

    #define GET_FORMAT_SPECIFIER(type) _Generic((type), \
      int16_t:  "%"SCNd16, \
      uint32_t: "%"SCNu32, \
      int8_t:   "%"SCNd8)
    
    fscanf(fp, GET_FORMAT_SPECIFIER(int_stuff.a), &int_stuff.a);
    fscanf(fp, GET_FORMAT_SPECIFIER(int_stuff.b), &int_stuff.b);
    ...
    

    现在,如果你有很多这些,并且它们有各种名称和格式,那么这可能是少数几个有效的情况之一,你应该考虑使用X宏,使代码易于维护。 例如:

    #include <stdio.h>
    #include <stdint.h>
    #include <inttypes.h>
    #include <assert.h>
    
    // X macro (type, name, format)
    #define INT_STUFF_LIST     \
      X(int16_t,  a, SCNd16)   \
      X(uint32_t, b, SCNu32)   \
      X(int8_t,   c, SCNd8)
    
    typedef struct
    {
      #define X(type, name, format) \
      type name;
      INT_STUFF_LIST
      #undef X
    } int_stuff_t;
    
    int main()
    {
      FILE* fp = fopen("something.txt", "r");
      assert(fp != NULL);
    
      int_stuff_t int_stuff;
    
      #define X(type, name, format) \
      fscanf(fp, "%" format, &int_stuff.name);
      INT_STUFF_LIST
      #undef X
    
      fclose(fp);
    }
    
    #包括
    #包括
    #包括
    #包括
    //X宏(类型、名称、格式)
    #定义INT_STUFF_列表\
    X(int16_t,a,SCNd16)\
    X(uint32_t,b,SCNu32)\
    X(int8_t,c,SCNd8)
    类型定义结构
    {
    #定义X(类型、名称、格式)\
    类型名称;
    国际材料清单
    #未定义X
    }内部材料;
    int main()
    {
    FILE*fp=fopen(“something.txt”、“r”);
    断言(fp!=NULL);
    int_stuff_t int_stuff;
    #定义X(类型、名称、格式)\
    fscanf(fp,“%”格式和int_stuff.name);
    国际材料清单
    #未定义X
    fclose(fp);
    }
    
    虽然这只是一个快速而肮脏的示例,但真正的代码应该不断检查每个fscanf调用的结果,以确保它不是EOF。

    正确的方法是阅读C库参考,找出需要使用的函数,然后使用它们。你似乎已经准备好了一个计划,执行它吧。
    #include <stdio.h>
    #include <stdint.h>
    #include <inttypes.h>
    #include <assert.h>
    
    // X macro (type, name, format)
    #define INT_STUFF_LIST     \
      X(int16_t,  a, SCNd16)   \
      X(uint32_t, b, SCNu32)   \
      X(int8_t,   c, SCNd8)
    
    typedef struct
    {
      #define X(type, name, format) \
      type name;
      INT_STUFF_LIST
      #undef X
    } int_stuff_t;
    
    int main()
    {
      FILE* fp = fopen("something.txt", "r");
      assert(fp != NULL);
    
      int_stuff_t int_stuff;
    
      #define X(type, name, format) \
      fscanf(fp, "%" format, &int_stuff.name);
      INT_STUFF_LIST
      #undef X
    
      fclose(fp);
    }