【问题标题】:Read file into typedef struct that includes an enum in C?将文件读入包含 C 中枚举的 typedef 结构?
【发布时间】:2020-09-11 15:33:34
【问题描述】:

我无法将文件读入包含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

我得到错误:

格式“%s”需要“char *”类型的参数,但参数 6 的类型为“category * {aka enum *}”

由于我对 C 完全陌生,我对如何将文件读入结构感到困惑。我该怎么办item[i].category?

【问题讨论】:

  • 可以读取字符串。你不能读这样的枚举。编译器会从程序中删除枚举名称,因此在程序运行时无法保留它们。
  • 有没有办法扫描文件以读取信息,但仍然像其他的一样使用结构中的类别?
  • 需要读入一个char数组并手动解析内容。

标签: c struct enums readfile


【解决方案1】:

不幸的是,enum 是一个仅在代码中有效的符号,并且无法在运行时将这个符号作为字符串访问。任何enum 变量实际上都存储为整数

但是你可以做一些事情:

  • 定义一个 char * 数组,其中包含作为字符串的枚举符号
  • 将输入文件中包含的enum符号存储在临时字符串中
  • 检查scanf的返回值
  • 调用实用函数在字符串常量数组中搜索临时字符串并返回相应的枚举值
  • 如果找不到该字符串,则会引发错误
  • 如果找到字符串,将枚举值存储在输出结构中

在以下示例代码中,为清楚起见,我省略了您的 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 的返回值为4
  • 我将make 的大小更改为100。目的是为了安全起见,格式说明符%s 应包含arr_size-1 字符的限制
  • 如果提供了一个不匹配任何枚举符号的奇怪字符串值,check_enum() 将返回 -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;
}

注意:这可行,但您必须保持数组和枚举对齐。为了防止人为对齐错误,可以实现类似this one 的解决方案。在这个答案中,我解释了如何创建一个对齐的 enum/struct 对,但以同样的方式并使用 preprocessor stringifier operator # 也可以是一个对齐的 enum/string array 对生成。

【讨论】:

  • 非常感谢!现在肯定更有意义了。
【解决方案2】:

Roberto's answer 很好,包含最重要的信息:

任何枚举变量实际上都存储为整数

如果您能够将输入格式从枚举的字符串表示更改为整数(即​​0 而不是输入中的type1),您可以使用 fscanf 中的"%d" 直接读取它。

【讨论】:

    猜你喜欢
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    相关资源
    最近更新 更多