如果程序被指定像这样运行,那么在c++中解析命令行参数的最佳方式是什么:

prog [-abc] [input [output]]

是否有某种方法可以在标准库中实现这一点,或者我需要自己编写代码?


相关:

在unicode c++应用程序中解析命令行参数


当前回答

这是我最喜欢的执行命令行的方式,特别是,但绝对不是只有在效率是一个问题。这可能看起来有点过分,但我认为这种过分有一些缺点。

使用gperf进行高效的C/ c++命令行处理

缺点:

您必须首先运行一个单独的工具来生成C/ c++哈希表的代码 不支持特定的命令行接口。例如,posix简写系统“-xyz”用一个破折号声明多个选项是很难实现的。

优点:

Your command line options are stored separately from your C++ code (in a separate configuration file, which doesn't need to be read at runtime, only at compile time). All you have in your code is exactly one switch (switching on enum values) to figure out which option you have Efficiency is O(n) where n is the number of options on the command line and the number of possible options is irrelevant. The slowest part is possibly the implementation of the switch (sometimes compilers tend to implement them as if else blocks, reducing their efficiency, albeit this is unlikely if you choose contiguous values, see: this article on switch efficiency ) The memory allocated to store the keywords is precisely large enough for the keyword set and no larger. Also works in C

使用像eclipse这样的IDE,您可能可以自动化运行gperf的过程,因此您惟一需要做的就是在配置文件和switch语句中添加一个选项,然后按build…

我使用了一个批处理文件来运行gperf,并做了一些清理,并使用sed添加了包含保护(在gperf生成的.hpp文件上)…

所以,在你的软件中有非常简洁干净的代码和一个自动生成的哈希表文件,你真的不需要手动更改。我怀疑boost::program_options即使没有效率作为优先级,实际上也能打败它。

其他回答

提高program_options。

还有另一种选择是精益平均c++选项解析器:

http://optionparser.sourceforge.net

它是一个只包含头文件的库(实际上只有一个头文件),与所有其他建议不同 也是独立的,即它没有任何依赖关系。特别是,它不依赖于STL。它甚至不使用异常或任何其他需要库支持的东西。这意味着它可以与普通C语言或其他语言链接,而无需引入“外国”库。

像boost::program_options一样,它的API提供了方便的直接访问选项, 也就是说,你可以这样写代码

如果 (选项[帮助]) ... ;

and

int VERBOSE = options[VERBOSE].count();

然而,与boost::program_options不同的是,这只是使用一个带有(用户提供的)enum索引的数组。这提供了没有权重的关联容器的便利。

它有良好的文档记录,并具有公司友好的许可证(MIT)。

tlmc++ OP包含了一个很好的格式化程序,用于使用可以执行的消息 行换行和列对齐在本地化程序时非常有用,因为它可以确保即使在具有较长消息的语言中输出也会很好。它还省去了手动格式化80列的麻烦。

Following from my comment and from rbaleksandar's answer, the arguments passed to any program in C are string values. You are provided the argument count (argc) which gives you the argument indexes zero-based beginning with the name of the program currently being run (which is always argv[0]). That leaves all arguments between 1 - argc as the user supplied arguments for your program. Each will be a string that is contained in the argument vector (which is a pointer to an array of strings you will seen written as char *argv[], or equivalently as a function parameter char **argv) Each of the strings argv[1] to argv[argc-1] are available to you, you simply need to test which argument is which.

这将允许您分离,并使它们可用为命令(cmd),选项(opt)和最后的参数(arg)到您的cmd。

Now it is worth noting, that the rules of your shell (bash, etc..) apply to the arguments passed to your program, word-splitting, pathname and variable expansion apply before your code gets the arguments. So you must consider whether single or more commongly double-quoting will be required around any of your arguments to prevent the normal shell splitting that would otherwise apply (e.g. ls -al my file.txt would results in 4 user-supplied arguments to your code, while ls -al "my file.txt" or ls -al my\ file.txt which would result in the 3 your were expecting.

把所有这些放在一起,您的简短解析可以像下面这样完成。(你也可以自由地做你喜欢的,使用一个开关而不是嵌套的if等…)

#include <stdio.h>

int main (int argc, char **argv) {

    char *cmd = NULL,   /* here, since you are using the arguments  */
         *opt = NULL,   /* themselves, you can simply use a pointer */
         *arg = NULL;   /* or the argument itself without a copy    */

    /* looping using the acutal argument index & vector */
    for (int i = 1; i < argc; i++) {
        if (*argv[i] != '-') {      /* checking if the 1st char is - */
            if (!cmd)               /* cmd is currently NULL, and    */
                cmd = argv[i];      /* no '-' it's going to be cmd   */
            else                    /* otherwise, cmd has value, so  */
                arg = argv[i];       /* the value will be opt        */
        }
        else                /* here the value has a leading '-', so  */
            opt = argv[i];  /* it will be the option */
    }

    printf ("\n cmd : %s\n opt : %s\n arg : %s\n\n",
            cmd, opt, arg);

    return 0;
}

使用/输出示例

如果你运行代码,你会发现它为参数提供了分离,并提供了单独的指针,以方便它们的使用:

$ ./bin/parse_cmd ls -la ./cs3000

 cmd : ls
 opt : -la
 arg : ./cs3000

(需要注意的是,如果你的任务是构建一个命令字符串,你需要复制多个值来表示opt或arg,那么你不能再简单地使用指针,而需要创建存储,要么通过简单的数组声明而不是指针开始,或者你可以根据需要动态分配存储,例如malloc, calloc和/或realloc。然后,您将有可用的存储空间来复制和连接其中的值。)

如果这是你的挑战,那么在所有这些答案之间,你应该知道如何处理你的问题。如果你必须更进一步,实际上让你的程序执行带有opt和arg的cmd,那么你会想要查看fork来生成一个半独立的进程,在其中运行将执行你的cmd opt和arg,使用类似于execv或execvp的东西。祝你好运,如果你有进一步的问题,请发表评论。

有很多好的库可用。

Boost Program Options是一个相当重量级的解决方案,因为将它添加到项目中需要构建Boost,而且语法有点令人困惑(在我看来)。但是,它几乎可以做任何事情,包括让命令行选项覆盖配置文件中设置的选项。

SimpleOpt是一个相当全面但简单的命令行处理器。它是一个单一的文件,具有简单的结构,但只处理将命令行解析为选项,您必须进行所有的类型和范围检查。它适用于Windows和Unix,并且还附带了一个适用于Windows的glob版本。

getopt在Windows上可用。它与Unix机器上的相同,但它通常是一个GPL库。

如果这是linux/unix,那么使用的标准是gnu getopt

http://www.gnu.org/s/libc/manual/html_node/Getopt.html