我很好奇如何以灵活的方式编写C代码来读取输入文件。
作为一个非常简单的示例,假设我有变量a
,b
,c
和d
。我可以按如下方式编写输入文件
a = 1.0
b = 5.0
c = 2.33
d = 0.9
而且,如果我声明a
,b
,c
和d
属于double
类型,我只需使用
FILE *fr;
// set some default values
double a = 1.0, b = 1.0,
c = 2.0, d = 2.0;
fr = fopen("input_file.txt", "rt");
fscanf(fr, "a = %lf b = %lf c = %lf d = %lf", &a, &b, &c, &d);
printf("%f %f %f %f\n",
a, b, c, d);
读取数据。但这似乎很僵硬,例如a
,b
,c
和d
必须在输入文件中完全按顺序排列,因此输入文件
a = 1.0
c = 5.0
b = 2.33
d = 0.9
不起作用,我无法为
之类的内容添加评论 a = 1.0 // This is parameter foo, must have properties P1, P2 and P3
c = 5.0
b = 2.33
d = 0.9
当我有20个变量而不只是a
,b
,c
和d
时,这尤其重要。任何有助于使其尽可能灵活的帮助都会很棒。我在Fortran中使用了实现“名单”的代码,这非常灵活,在C中就像是那样很棒。
答案 0 :(得分:2)
转移和扩展评论。
您似乎需要一个结构,例如:
struct VarMap
{
const char *name;
double *data;
} var_map[] =
{
{ "a", &a }, { "b", &b },
{ "c", &c }, { "d", &d },
};
将(运行时)名称映射到不同的变量。然后,您可以使用格式中的"%s = %lf"
来读取名称(%s
允许多字符名称)和值,然后搜索varmap
以查找数据的放置位置
enum { NUM_VARS = sizeof(varmap) / sizeof(varmap[0]) };
char name[10];
double value;
if (fscanf(fr, "%9s = %lf", name, &value) == 2)
{
int i;
for (i = 0; i < NUM_VARS; i++)
{
if (strcmp(name, varmap[i].name) == 0)
{
*varmap[i].data = value;
break;
}
}
if (i == NUM_VARS)
{
fprintf(stderr, "Failed to find match for '%s = %g'\n", name, value);
...other error handling?...
}
}
显然,如果你有大量的变量,你会想要考虑二进制搜索甚至基于哈希的名称搜索,你将搜索抽象为函数而不是像上面的代码一样把它写成内联。
varmap
的初始化程序提出了一个限制 - 在大多数情况下,指向的名称和变量在编译时是固定的。另一种机制是使用一组命名变量:
struct NamedVar
{
const char *name;
double value;
};
您可以在结构中使用固定大小的char
数组,或将名称转换为灵活的数组成员。
struct NamedVar
{
double value;
char name[];
};
然后,您可以动态分配struct NamedVar
值,在数组中保留指针,并根据需要添加新的命名变量。
您需要一个函数double named_variable(const char *name)
来获取值,并void set_named_variable(const char *name, double value)
来设置该值。哪种方法最好取决于谁可以设计变量名称以及必须处理多少变量名称。对于4个变量或40个变量,struct VarMap
方法是合理的;对于400个变量或4000个变量,它实际上没有意义,struct NamedVar
方法可能更好。
答案 1 :(得分:0)
大多数配置文件格式都需要解析文件,使用其中包含的数据填充一些通用结构,然后处理这些结构,以便找到与您喜欢的内容相关的值。
检查此stackoverflow链接以获取有关使用XML配置解析库的更多信息:
您最好的选择是使用INI,XML或JSON文件,因此另一种调查途径是为C语言中的人员寻找解析器。