你想要这样的东西:
int Var1 = ReadFromFile(File, "Var1");
int Var2 = ReadFromFile(File, "Var2");
double Var3 = ReadFromFile(File, "Var3");
char* Var4 = ReadFromFile(File, "Var4");
嗯,这是不可能的。
原因是 a) 函数有时不能返回 int,有时不能返回 double,b) 当您从文件中读取所有值时,所有值都以文本值的形式出现,因此您可以得到 int需要代码将文本字符串转换为int 和double。
换句话说 - 没有类型信息就无法完成。
您可以这样做:
int Var1 = ReadIntFromFile(File, "Var1");
int Var2 = ReadIntFromFile(File, "Var2");
double Var3 = ReadDoubleFromFile(File, "Var3");
char* Var4 = ReadTextFromFile(File, "Var3");
这样您就可以为每种类型提供特定的功能。
除非文件非常大,否则我会这样做:
在程序启动时,我会将整个文件读入一个(动态分配的)结构数组。每个结构将有两个字符串,即一个用于保存变量名称的键字符串和另一个用于保存值的字符串。喜欢:
struct key_value
{
char key[32];
char val[992];
};
因此,当fgets 给出类似“Var2 15”的字符串时,必须将字符串拆分为两个字符串,其中第一个字符串复制到key,第二个字符串复制到val。比如:
char row[2000];
int i = 0;
while(fgets(row, sizeof(row), InstFile) != NULL)
{
if (sscanf(row,
"%31s %991s",
key_value_array[i].key,
key_value_array[i].val) != 2)
{
// Error - unexpected format
exit(1); // or something better...
}
++i;
}
strcpy(key_value_array[i].key, "end_of_array");
strcpy(key_value_array[i].val, "");
注意: 上面的代码没有检查key_value_array 的大小是否足以容纳所有键。添加这样的检查我将留给 OP。
我在最后添加了一个额外的结构来指示数组结束。
现在您可以在结构数组中搜索正确的键,如果找到,则根据类型信息转换值字符串。
类似:
int ReadInt(struct key_value * key_value_array, char * var_name)
{
int result = 0;
int i = 0;
while( strcmp(key_value_array[i].key, "end_of_array") != 0 )
{
if( strcmp(key_value_array[i].key, var_name) == 0 )
{
// Variable found
result = atoi(key_value_array[i].val);
break;
}
++i;
}
return result;
}
这种方法的好处是您只需访问文件一次。此外,读取文件的代码完全独立于类型信息。
但是,这里有一个大问题......如果找不到特定的变量名或类型转换失败,代码无法为您提供错误信息。
所以我们需要添加它。
这就是我会做的:
int ReadInt(struct key_value * key_value_array, char * var_name, int* value)
{
int i = 0;
while( strcmp(key_value_array[i].key, "end_of_array") != 0 )
{
if( strcmp(key_value_array[i].key, var_name) == 0 )
{
// Variable found
*value = atoi(key_value_array[i].val);
return 0;
}
++i;
}
return -1; // Error, key not found
}
然后这样称呼它:
int Var1;
if (ReadInt(key_value_array, "Var1", &Var1)
{
// Error handling... perhaps
Var1 = some_default_value;
}
最后一句话:
全局变量是应该避免的。但是,像这样的配置数据是(IMO)一个例外。将文件范围全局数组变量和所有相关函数放在一个编译单元中就可以了。这样就不需要在所有函数调用中传递数组。所以一个电话可能是:
int Var1;
if (ReadInt("Var1", &Var1)
{
// Error handling... perhaps
Var1 = some_default_value;
}