将文件读入包含 C 中枚举的 typedef 结构?
Read file into typedef struct that includes an enum in C?
我无法将文件读入包含 enum
的 typedef struct
。我是C的初学者,所以我真的不知道如何用枚举读入文件。
我能够读取文件并用简单的代码打印出内容,但我需要读入文件并将行中的每个字符串分配给 typedef 结构中的类型。
输入文件看起来像这样:
random.num year model category
Example:
54 2012 model1 type1
这些是我的代码的相关部分:
typedef enum { type1, type2, type3, type4} category;
typedef struct {
int num;
int year;
char make[MAX_MAKE_CHARS];
category category; //enum from above
}item;
//reading in the file I have this:
int create_db(char *f){
char file_contents[100]; // read the file --> ("r") FILE *f = fopen(f, "r");
// check if file can be used
if(f == NULL){
printf("File not found");
exit(1);
}
int i = 0; item item_array[100];
while(fscanf(f, "%d %d %s %s", &item[i].num, &item[i].year, item[i].make, item[i].category) != EOF){
// can't get past the while look where it says "item[i].category
我收到错误:
format ‘%s’ expects argument of type ‘char *’, but argument 6 has type ‘category * {aka enum *}’
由于我是 C 的新手,我对如何将文件读入结构感到困惑。我为 item[i].category
做什么?
不幸的是,enum 是一个仅在代码中有效的符号,并且无法在运行时将此符号作为字符串访问。任何 enum
变量实际上存储为 整数
但是您可以做一些事情:
- 定义一个
char *
的数组,其中包含枚举的符号作为字符串
- 将输入文件中包含的
enum
符号存储在一个临时字符串中
- 检查
scanf
的 return 值
- 调用实用程序函数在常量字符串数组中搜索临时字符串并return获取相应的枚举值
- 如果未找到该字符串,则引发错误
- 如果找到字符串,将枚举值存储在输出结构中
在下面的示例代码中,为清楚起见,我省略了您的 while
(您可以根据问题中未描述的要求将其添加回来):
int tmp_num;
int tmp_year;
char tmp_make[100];
char tmp_category_str[10]; // <-- define the size according to the max enum symbol length
if(fscanf(f, "%d %d %99s %9s", &tmp_num, &tmp_year, tmp_make, tmp_category_str) == 4)
{
int tmp_category;
if( ( tmp_category = check_enum( tmp_category_str ) ) != -1 )
{
Item.num = tmp_num;
Item.year = tmp_year;
strcpy( make, tmp_make );
Item.category = ( category )tmp_category; // The numeric value is stored in the struct
}
else
{
printf( "Invalid 'category' value!\n" );
}
}
注意:
- 我希望
fscanf
的 return 值为 4
- 我将
make
大小更改为 100。目的是以简单的方式显示格式说明符 %s
应包含 arr_size-1
个字符的限制,以确保安全
- 如果提供了一个不匹配任何枚举符号的奇怪字符串值,
check_enum()
将 return -1
现在,只缺少 check_enum()
实现。只需循环搜索输入字符串的 enumSymbols[]
个元素。
char* enumSymbols[] = { "type1", "type2", "type3", "type4" };
int check_enum(char * str)
{
int ret = -1;
if( str )
{
for( int i=0; i<(sizeof(enumSymbols)/sizeof(enumSymbols[0])); i++ )
{
if( strcmp(enumSymbols[i], str) == 0 )
{
ret = i;
break;
}
}
}
return ret;
}
注意: 这可行,但您必须保持数组和枚举对齐。为了防止人为对齐错误,可以生成像 can be implemented. In this answer I explain how to create an aligned enum/struct pair, but in the same way and using the preprocessor stringifier operator #
这样的解决方案,也可以生成对齐的 enum/string 数组 对。
很好,包含了最关键的信息:
Any enum variable is actually stored as an integer
如果您能够将输入格式从枚举的字符串表示更改为整数(即输入中的 0
而不是 type1
),您可以使用 "%d"
在 fscanf.
我无法将文件读入包含 enum
的 typedef struct
。我是C的初学者,所以我真的不知道如何用枚举读入文件。
我能够读取文件并用简单的代码打印出内容,但我需要读入文件并将行中的每个字符串分配给 typedef 结构中的类型。
输入文件看起来像这样:
random.num year model category
Example:
54 2012 model1 type1
这些是我的代码的相关部分:
typedef enum { type1, type2, type3, type4} category;
typedef struct {
int num;
int year;
char make[MAX_MAKE_CHARS];
category category; //enum from above
}item;
//reading in the file I have this:
int create_db(char *f){
char file_contents[100]; // read the file --> ("r") FILE *f = fopen(f, "r");
// check if file can be used
if(f == NULL){
printf("File not found");
exit(1);
}
int i = 0; item item_array[100];
while(fscanf(f, "%d %d %s %s", &item[i].num, &item[i].year, item[i].make, item[i].category) != EOF){
// can't get past the while look where it says "item[i].category
我收到错误:
format ‘%s’ expects argument of type ‘char *’, but argument 6 has type ‘category * {aka enum *}’
由于我是 C 的新手,我对如何将文件读入结构感到困惑。我为 item[i].category
做什么?
不幸的是,enum 是一个仅在代码中有效的符号,并且无法在运行时将此符号作为字符串访问。任何 enum
变量实际上存储为 整数
但是您可以做一些事情:
- 定义一个
char *
的数组,其中包含枚举的符号作为字符串 - 将输入文件中包含的
enum
符号存储在一个临时字符串中 - 检查
scanf
的 return 值
- 调用实用程序函数在常量字符串数组中搜索临时字符串并return获取相应的枚举值
- 如果未找到该字符串,则引发错误
- 如果找到字符串,将枚举值存储在输出结构中
在下面的示例代码中,为清楚起见,我省略了您的 while
(您可以根据问题中未描述的要求将其添加回来):
int tmp_num;
int tmp_year;
char tmp_make[100];
char tmp_category_str[10]; // <-- define the size according to the max enum symbol length
if(fscanf(f, "%d %d %99s %9s", &tmp_num, &tmp_year, tmp_make, tmp_category_str) == 4)
{
int tmp_category;
if( ( tmp_category = check_enum( tmp_category_str ) ) != -1 )
{
Item.num = tmp_num;
Item.year = tmp_year;
strcpy( make, tmp_make );
Item.category = ( category )tmp_category; // The numeric value is stored in the struct
}
else
{
printf( "Invalid 'category' value!\n" );
}
}
注意:
- 我希望
fscanf
的 return 值为 4 - 我将
make
大小更改为 100。目的是以简单的方式显示格式说明符%s
应包含arr_size-1
个字符的限制,以确保安全 - 如果提供了一个不匹配任何枚举符号的奇怪字符串值,
check_enum()
将 return -1
现在,只缺少 check_enum()
实现。只需循环搜索输入字符串的 enumSymbols[]
个元素。
char* enumSymbols[] = { "type1", "type2", "type3", "type4" };
int check_enum(char * str)
{
int ret = -1;
if( str )
{
for( int i=0; i<(sizeof(enumSymbols)/sizeof(enumSymbols[0])); i++ )
{
if( strcmp(enumSymbols[i], str) == 0 )
{
ret = i;
break;
}
}
}
return ret;
}
注意: 这可行,但您必须保持数组和枚举对齐。为了防止人为对齐错误,可以生成像 #
这样的解决方案,也可以生成对齐的 enum/string 数组 对。
Any enum variable is actually stored as an integer
如果您能够将输入格式从枚举的字符串表示更改为整数(即输入中的 0
而不是 type1
),您可以使用 "%d"
在 fscanf.