我正在创建一个C99程序,我需要一些帮助来摆脱代码的一些冗余。我想将以下代码转换为函数的两个调用,但我不知道该怎么做。
我想读两个文件(每个文件有15个入口)并将其内容放入两个数组中。问题是这些数组的数据类型不同。
这就是我所拥有的:
typedef char string[30];
int
_vInt[15];
string
_vString[15];
FILE
*_fInt,
*_fString;
int main(){
...
for(int i = 0; !feof(_fInt) && i < 15; ++i){
fscanf(_fInt, "%d", &_vInt[i]);
...
}
for(int i = 0; !feof(_fString) && i < 15; ++i){
fscanf(_fString, "%s", _vString[i]);
...
}
...
}
所以,我不想两次使用这个for
。我宁愿两次调用函数:
readFile(_fInt, "%d", _vInt);
readFile(_fString, "%s", _vString);
问题在于我不知道函数的原型应该如何,也不知道我应该如何使用它。
是的,我可以使用丑陋的void *
解决方案......
答案 0 :(得分:1)
您可以使用宏。
#define readFile(file, fmt, arr) \
for (int i = 0; !feof(file) && i < 15; ++i) { \
fscanf(file, fmt, arr[i]); \
}
readFile(_fInt, "%d", &_vInt);
readFile(_fString, "%s", _vString);
答案 1 :(得分:1)
另一种解决方案是在readFile()函数中使用枚举类型和表。
#include <stdlib.h>
#include <stdio.h>
// Put in Header file
typedef char string[30];
typedef enum {
ITInt = 0,
ITString = 1,
ITMax
} InputTypes;
// Should be in module with readFile()
struct inputTypeEntry_s{
const char *format;
size_t sz;
};
struct inputTypeEntry_s inputTypeLUT[ITMax] = {
{ "%d", sizeof(int) }, // ITInt
{ "%s", sizeof(string) }, // ITString
};
int readFile(FILE *fp, InputTypes type, void *data) {
char *ptr = (char *)data;
for(int i = 0; !feof(fp) && i < 15; ++i){
fscanf(fp, inputTypeLUT[type].format, ptr + (i * inputTypeLUT[type].sz) );
}
return 0;
}
答案 2 :(得分:0)
你可以将类型提取到(void *)
,但它不会很漂亮。
void foo(FILE *file, const char *format, void *arr, size_t size) {
for(int i = 0; !feof(file) && i < 15; ++i){
fscanf(file, format, ((char *)arr) + (size * i));
...
}
}
函数调用看起来像
foo(_fInt, "%d", (void *)&_vInt, sizeof(int))
答案 3 :(得分:0)
由于您提到可以使用C11功能,这里是一个使用C11类型泛型表达式的示例。我用它来删除传递格式字符串的要求:
#include <stdio.h>
typedef char string[30];
#define generic_arg(X) _Generic(X, string: X, \
default: &X)
#define generic_format(X) _Generic(X, string: "%s", \
int: "%d")
#define readFile(file, variable) for (int i = 0; i < 15; i++) \
{ \
fscanf(file, \
generic_format(variable[i]), \
generic_arg(variable[i])); \
}
int main(void)
{
int _vInt[15];
string _vString[15];
FILE *_fInt = fopen("ints", "r");
FILE *_fString = fopen("strings", "r");
readFile(_fInt, _vInt);
readFile(_fString, _vString);
for (int i = 0; i < 15; i++)
{
printf("%d %s\n", _vInt[i], _vString[i]);
}
fclose(_fInt);
fclose(_fString);
return 0;
}
我不确定这是否是一个非常好的例子 - 它肯定比你的双循环解决方案更复杂,但我认为它符合你的要求。