解析c中的.conf文件

时间:2011-11-17 17:04:05

标签: c arrays parsing configuration-files variable-assignment

也许这个桥可能已经多次交叉过了......阅读一个简单的文本.conf文件并对其条目进行操作。

就我而言,文件格式很简单..一系列令牌和作业,如:

token_name_1    value

使用制表符作为字段分隔符,并为每个记录使用unix行结尾。

.conf文件直接改变某些程序配置,所有程序配置都存储在一个结构中。 Integer,float,char []和* char类型的变量在结构中表示。

快速但无聊的方法涉及,例如:

if (strcasecmp(token,"token_name_1")==0)
    token_name_1=value;

但是我确定在一个很好的紧密循环中做这件事会很好。在C.

因此,最好构造一个数组,该数组提供指向我希望公开的每个结构变量的指针;另一个提供变量名称;第三个描述存储的数据类型和所需的默认值。

这些看起来像这样:

const char* allowed_tokens[] =
{
    "loglevel",
    "debugecho",
    "errorSqlDisable",
    "ClearErrorDbOnExit",
    "\0"    // terminates list
}

int *varpointers[] =
{
    &appinfo.nLogLevel,
    &appinfo.debugEcho,
    &appinfo.OWFSLogLevel,
    &appinfo.OWFSLogEchoToDisplay,
    0   // terminates list
};

char *varDatatypes_defaults[] =
{
    "I|6",      // for LOG_INFO
    "B|false",
    "I|0",  
    "B|true",
    "\0"    // terminates list
};

循环看起来像这样(伪代码):

row=0;
while (read a line of the .conf file into cLine)
{
    get the token_name and value from cLine
    check if allowed_tokens[row]==0 and if true, exit the loop
    // example cLine= "debugecho    false"
    find match to "debugecho" in allowed_tokens.  This provides an offset into varpointers and varDatatypes.
    get the default data type and default value tokens from varDattypes_defaults[row]
    Do the assignment.  For example, if the data type=="I":
      *varpointers[row]=atoi(value);

    ++row;
}

这项技术运作良好,但有两个问题。

  1. 最好将三个阵列组合成一个阵列。这里有最好的做法吗?
  2. 指针数组(varpointers [])定义为* int。我这样做是因为我希望它能保持指针。但是,如果指向的变量不是整数数据类型,则会触发警告:从不兼容的指针类型初始化。当然,char *和int *不能混合......那么如何使用单个指针数组呢?
  3. 我意识到我可以用c ++完成所有这些。在这一点上,这种奢侈品不是一种选择。

3 个答案:

答案 0 :(得分:2)

您可以按结构将它们组合成一个数组,例如

typedef struct { char *token; void *var; char *defaults; } the_type;

the_type the_data[] = { { "loglevel",  (void*)&appinfo.nLogLevel, "I|6" },
                        { "debugecho", (void*)&appinfo.debugEcho, "B|false" }, 
                      ... 
                      };

通用指针类型为void *。您的代码必须确保在实际写入指向的变量时使用正确的类型,例如*(int*)the_data[0] = 42;

答案 1 :(得分:1)

我会使用枚举来指定类型,因此您不必解析字符串。这些值可以存储在一个联合中。

typedef enum {
    BOOLEAN,
    INTEGER,
} type_t;

typedef union value {
    bool boolean;
    int integer;
} value_t;

typedef struct token {
    char *name;
    type_t type;
    value_t value;
} token_t;

现在您可以定义默认值:

token_t data[] = {
    { "loglevel", INTEGER, { 6 } },
    { "debugecho", BOOLEAN, { false } },
    { "errorSqlDisable", INTEGER, { 0 } },
    { "ClearErrorDbOnExit", BOOLEAN, { true } },
    { 0 }
};

如果配置键的数量变大,这将变得非常麻烦。您可能想要考虑将配置存储在哈希表或树中。

这是一个似乎可以实现你想要的短example

答案 2 :(得分:0)

  1. 如果我们谈论相同的数据类型,请使用双指针(获得数组数组)
  2. 声明一个包含指针的结构,然后使用指向结构的指针来处理。
  3. 为了声明一般指针,可以使用void而不是int。但是每次你必须抛出指针才能正确使用它。