从C

时间:2017-03-30 08:00:49

标签: c parsing arguments scanf fgets

我有一个文件,其中的行以'\ n'分隔,其中每行看起来都是

10010 0 19 7 18

10014 -1 -1 -1 11 10db8 1

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

2 个答案:

答案 0 :(得分:0)

  1. 使用fgets()读取该行,将该行拆分为令牌。

  2. 使用strtok()将行划分为令牌。

  3. 使用atoi()或任何其他字符串将整数转换为整数。

答案 1 :(得分:0)

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

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);
}

虽然这只是一个快速的&amp;肮脏的例子,真实的代码应该不断检查每个fscanf调用的结果,以确保它不是EOF。