您可能应该创建一个结构来存储它们,例如:
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);
}
虽然这只是一个快速而肮脏的示例,但实际代码应该不断检查每个 fscanf 调用的结果,以确保它不是 EOF。