简体   繁体   English

如何使用文件,环境和/或命令行初始化C程序?

[英]How to initialise a C program using file, environment and/or command line?

In C, how to configure the initial settings for some program, using key-value pairs, with any or all of: a plain text configuration file , environment variables, and options on the command line. 在C中,如何使用键值对配置某些程序的初始设置,使用以下任何一个或全部:命令行上的纯文本配置文件 ,环境变量和选项。 Also, how to decide which method's values overide those from either of the other two. 此外,如何确定哪个方法的值超过其他两个方法中的任何一个。 Then if values have been changed, to optionally update the configuration file. 然后,如果已更改值,则可以选择更新配置文件。

What's the simplest way to do this, and what if any, are the most accepted methods? 最简单的方法是什么?如果有的话,最常用的方法是什么? Is there a, preferably small, open source program that gives a good example of how this can be done? 是否有一个,最好是小型的开源程序,它提供了一个很好的例子来说明如何做到这一点?

The basics: 基础:

  • To configure your program using environment variables, you can use the getenv function defined in stdlib.h. 要使用环境变量配置程序,可以使用stdlib.h中定义的getenv函数。
  • To configure your program using command line arguments, declare your main function like 'int main(int argc, const char* const* argv)', and use a loop to go over the arguments in the argv array. 要使用命令行参数配置程序,请将主函数声明为'int main(int argc,const char * const * argv)',并使用循环来遍历argv数组中的参数。 It's size is given by argc. 它的大小由argc给出。
  • To configure your program using a configuration file, preferably pick some library doing this for you instead of inventing yet another custom config file format. 要使用配置文件配置程序,最好选择一些为您执行此操作的库,而不是发明另一种自定义配置文件格式。 Note that depending on the platform you target, there are also libraries to parse commandline arguments. 请注意,根据您定位的平台,还有用于解析命令行参数的库。

Which settings source should override each other depends on the application, but in my opinion generally commandline argument > environment variable > configuration file makes most sense. 哪个设置源应该相互覆盖取决于应用程序,但在我看来,一般命令行参数>环境变量>配置文件最有意义。

Here is an example of getting configuration from environment and commandline, with commandline overriding environment: 以下是使用命令行覆盖环境从环境和命令行获取配置的示例:

#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;
}

You already see it becomes very long and tedious very soon, so better use an existing library if one exists for your desired target platform(s), or at least factor this kind of code into a number of functions. 您已经看到它很快变得非常冗长乏味,因此如果存在所需的目标平台,或者至少将这种代码考虑到许多函数中,那么最好使用现有的库。

Another interesting option is to bind a scripting language to your application, then you could make your application only read and "execute" your settings file, and the user could configure the settings file to read some settings from the environment and some from the commandline, for example. 另一个有趣的选择是将脚本语言绑定到您的应用程序,然后您可以使您的应用程序只读取并“执行”您的设置文件,用户可以配置设置文件以从环境中读取一些设置,从命令行读取一些设置,例如。 It really depends on type and size of the application and your target audience whether this is worth doing though. 这实际上取决于应用程序的类型和大小以及目标受众是否值得这样做。

Eric Raymond在Unix编程的第10部分中介绍了很多这方面。显然,这是以Unix为中心的,但大多数原则都可以应用于任何操作系统。

There are tons of libraries for dealing with configuration file parsing, for various formats. 对于各种格式,有大量的库用于处理配置文件解析。 Look for XML and INI formats, for two popular choices. 寻找两种流行选择的XML和INI格式。 Writing a custom parser is probably a bad idea, since it can be a lot of work for little or no gain. 编写自定义解析器可能是一个坏主意,因为它很少或根本没有收获。 Here is a random C library for parsing INI files, XML is left as an exercise. 是一个用于解析INI文件的随机C库,XML留作练习。

The priority between settings is usually such that command line options override any "environmental" settings. 设置之间的优先级通常是命令行选项覆盖任何“环境”设置。 I would suggest priorities like this, in falling order of importance: 我会按照重要性的下降顺序建议这样的优先事项:

  1. Command line options override anything 命令行选项覆盖任何内容
  2. Settings file is next 设置文件是下一个
    • Sometimes split between user's local, and system global files 有时在用户的本地和系统全局文件之间分配
  3. Next come environment variables 接下来是环境变量

But the 2 and 3 might well be flipped. 但是2和3可能会被翻转。

The question is not terribly clear. 问题不是很清楚。 Is the question "what mechanisms exist?", "what are the conventions for arguments and formats?", or "how you should I mix and match?"? 问题是“存在什么机制?”,“参数和格式的约定是什么?”,或者“我应该如何混合搭配?”?

There are several pretty standard ways (at least in the unix world): 有几种非常标准的方法(至少在unix世界中):

  • environment variables 环境变量
  • configuration files 配置文件
  • command line arguments 命令行参数
  • as a subset of the above, config files specified on the command line 作为上述的子集,在命令行上指定的配置文件

To choose what methods to use for your own program, examine many programs from the canon of accepted practice before you freeze your own choices, read some blogs, read some books... 要选择用于您自己的程序的方法,在冻结自己的选择,阅读一些博客,阅读一些书籍之前,从已接受的实践经典中检查许多程序......

Configuration files are probably the most portable across operating systems. 配置文件可能是跨操作系统最便携的。

The treatment can get fairly complicated. 治疗可能会相当复杂。 If the command line arguments might affect the interpretation of config files or environment variable, but you still want the command line to overrule the other mechanisms (a good idea) you may need three passes: 如果命令行参数可能会影响配置文件或环境变量的解释,但您仍然希望命令行覆盖其他机制(一个好主意),您可能需要三次传递:

  1. Parse the command line and set any variables which affect further settings (say which config file to read) 解析命令行并设置任何影响进一步设置的变量(说明要读取哪个配置文件)
  2. Handle config files and environment variable (what order?) 处理配置文件和环境变量(什么顺序?)
  3. Re-run the command line to override all other settings. 重新运行命令行以覆盖所有其他设置。

In the unix tradition look at getopt and getopt_long . 在unix传统中看看getoptgetopt_long Also consider tools like gengetopt 还要考虑像gengetopt这样的工具

You can simplify you config file problem by making them shell scripts that set environment variables (but this locks you into a unix model). 您可以通过设置用于设置环境变量的shell脚本来简化配置文件问题(但这会将您锁定为unix模型)。 Parsing plain text is easy and cross platform, but makes more code to write. 解析纯文本很容易和跨平台,但编写更多代码。 Using a standard format and a library puts requirements on your user's build environment, but should save on bugs and confusion. 使用标准格式和库会对用户的构建环境提出要求,但应该节省错误和混淆。


If your configuration environment is complicated, it is very helpful to encapsulate the configuration state in a structure which can be passed around as needed. 如果您的配置环境很复杂,那么将配置状态封装在可以根据需要传递的结构中非常有用。 This is the approach taken by gengetopt , and I have found it to be useful. 这是gengetopt采用的方法,我发现它很有用。

For Unix-like design patterns in this area, look at Raymond's "The Art of Unix Programming ". 对于这个领域的类Unix设计模式,请看Raymond的“ Unix 编程 艺术 ”。 It discusses the prioritization of command line arguments over environment variables and configuration files, and so on. 它讨论了命令行参数在环境变量和配置文件上的优先级,等等。

The Lua language partly got its start motivated by the need to have a well-defined configuration language for a collection of tools. Lua语言的部分原因在于需要为一组工具提供定义明确的配置语言。 It remains quite easy to integrate Lua as a configuration language. 将Lua集成为配置语言仍然非常容易。 A fairly complete example is in the book Programming in Lua, an older edition of which is available online. 一个相当完整的例子出现在“Lua编程”一书中,该版本的旧版本可在线获取。 Chapter 25 describes using the Lua C API to embed Lua as a configuration language, and reasons why you might want to do this. 第25章介绍如何使用Lua C API将Lua嵌入为配置语言,并说明您可能希望这样做的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM