5

在 C 语言中,如何使用键值对配置某些程序的初始设置,其中任何或全部:纯文本配置文件、环境变量和命令行上的选项。此外,如何确定哪种方法的值会覆盖其他两种方法的值。然后,如果值已更改,则可选择更新配置文件。

最简单的方法是什么?如果有的话,最被接受的方法是什么?是否有一个最好是小型的开源程序来提供一个很好的例子来说明如何做到这一点?

4

6 回答 6

5

基础:

  • 要使用环境变量配置程序,可以使用 stdlib.h 中定义的 getenv 函数。
  • 要使用命令行参数配置程序,请声明主函数,如“int main(int argc, const char* const* argv)”,并使用循环遍历 argv 数组中的参数。它的大小由 argc 给出。
  • 要使用配置文件配置您的程序,最好选择一些为您执行此操作的库,而不是发明另一种自定义配置文件格式。请注意,根据您的目标平台,还有一些库可以解析命令行参数。

哪个设置源应该相互覆盖取决于应用程序,但在我看来,通常命令行参数 > 环境变量 > 配置文件最有意义。

这是从环境和命令行获取配置的示例,命令行覆盖环境:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char* const* argv) {
    int i;
    const char* myConfigVar;

    // get default setting from environment
    myConfigVar = getenv("MY_CONFIG_VAR");

    // if the variable wasn't defined, initialize to hardcoded default
    if (!myConfigVar)
        myConfigVar = "default value";

    // parse commandline arguments
    // start at 1, because argv[0] contains the name of the program
    for (i = 1; i < argc; ++i) {
        if (strcmp("--my-config-var", argv[i]) == 0) {
            if (i + 1 < argc)
                myConfigVar = argv[i + 1];
            else
                printf("missing value for my-config-var argument\n");
        }
    }

    printf("myConfigVar = '%s'\n", myConfigVar);
    return 0;
}

您已经看到它很快就会变得非常冗长和乏味,因此如果您想要的目标平台存在一个现有的库,那么最好使用现有的库,或者至少将这种代码分解为许多函数。

另一个有趣的选择是将脚本语言绑定到您的应用程序,然后您可以让您的应用程序只读取和“执行”您的设置文件,并且用户可以配置设置文件以从环境读取一些设置,从命令行读取一些设置,例如。这实际上取决于应用程序的类型和大小以及您的目标受众是否值得这样做。

于 2009-05-08T12:54:56.437 回答
5

Eric Raymond 在The Art of Unix Programming第 10 节中涵盖了很多内容显然这是以 Unix 为中心,但大多数原则都可以应用于任何操作系统。

于 2009-05-08T14:15:07.010 回答
2

有大量的库用于处理各种格式的配置文件解析。寻找两种流行的选择 XML 和 INI 格式。编写自定义解析器可能不是一个好主意,因为它可能需要大量工作而收效甚微或毫无收获。是一个用于解析 INI 文件的随机 C 库,XML 留作练习。

设置之间的优先级通常是命令行选项覆盖任何“环境”设置。我会建议这样的优先级,按重要性降序排列:

  1. 命令行选项覆盖任何东西
  2. 设置文件是下一个
    • 有时在用户的本地文件和系统全局文件之间拆分
  3. 接下来是环境变量

但是 2 和 3 很可能会颠倒过来。

于 2009-05-08T12:31:20.397 回答
2

这个问题不是很清楚。问题是“存在哪些机制?”、“参数和格式的约定是什么?”还是“我应该如何混合和匹配?”?

有几种非常标准的方法(至少在 unix 世界中):

  • 环境变量
  • 配置文件
  • 命令行参数
  • 作为上述的子集,在命令行上指定的配置文件

要选择用于您自己的程序的方法,请在冻结您自己的选择、阅读一些博客、阅读一些书籍之前从公认的实践规范中检查许多程序……

配置文件可能是跨操作系统最可移植的。

治疗可能会变得相当复杂。如果命令行参数可能会影响配置文件或环境变量的解释,但您仍然希望命令行推翻其他机制(一个好主意),您可能需要三遍:

  1. 解析命令行并设置任何影响进一步设置的变量(比如要读取哪个配置文件)
  2. 处理配置文件和环境变量(什么顺序?)
  3. 重新运行命令行以覆盖所有其他设置。

在 unix 传统中,请查看getoptand getopt_long。还要考虑像这样的工具gengetopt

您可以通过制作设置环境变量的 shell 脚本来简化配置文件问题(但这会将您锁定在 unix 模型中)。解析纯文本很容易且跨平台,但需要编写更多代码。使用标准格式和库对用户的构建环境提出了要求,但应该可以避免错误和混乱。


如果你的配置环境比较复杂,把配置状态封装在一个结构体中,可以根据需要进行传递是非常有帮助的。这是 采用的方法gengetopt,我发现它很有用。

于 2009-05-08T12:34:18.967 回答
1

对于这方面的类 Unix 设计模式,请查看 Raymond 的“ Unix编程艺术。它讨论了命令行参数优先于环境变量和配置文件等。

于 2009-05-08T14:30:21.357 回答
1

Lua语言的部分动机是需要为一组工具提供一个定义良好的配置语言。将 Lua 集成为配置语言仍然很容易。一个相当完整的示例在《Lua 编程》一书中,该书的旧版本可在线获得。第 25 章描述了使用 Lua C API 将 Lua 作为配置语言嵌入,以及您可能想要这样做的原因。

于 2009-05-09T01:13:19.253 回答