argc / argv中的命令行解析

时间:2013-05-22 08:42:07

标签: c command-line argv getopt argc

我有以下代码:

void parse(char *commandLine) {
    int rc = 0;
    int argc = 0;
    char *cmdLine;
    char *argv[MAX_ARGS];
    filename = NULL;
    stdoutFilename = NULL;
    stderrFilename = NULL;
    cmdLine = strdup(commandLine);
    char *param = strtok(cmdLine, " ");
    while (param && argc < MAX_ARGS) {
        argv[argc++] = param;
        param = strtok(NULL, " ");
        printf("%s\n", argv[argc-1]);
    }
    free(cmdLine);
    scanOptions(argc, argv);
    printf("Filename %s\n", filename);

...

void scanOptions(int argc, char *argv[]) {
    int c ;
    while ((c = getopt (argc, argv, "Df:e:o:")) != -1) {
        switch (c) {
            case 'D': __debug = 1; break;
            case 'f': filename = strdup(optarg); break;
            case 'o': stdoutFilename = strdup(optarg); break;
            case 'e': stderrFilename = strdup(optarg); break;
            default: fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
        }
    }
}

filename,stdoutFilenamestderrFilename全局变量。 如果我将解析方法称为:

parse("-ftest/testfile.txt") the variable filename is not set and the call to 
printf("Filename %s\n", filename); prints "Filename (null)".

这有什么问题?

6 个答案:

答案 0 :(得分:4)

有一些问题,可能是也可能不是你问题的原因:

使用已释放的内存

free(cmdLine);
scanOptions(argc, argv);

你不能在这里释放cmdLine,因为你的strtok()调用会将cmdLine中的指针指定给你的argv。 free()它在scanOptions()之后,但如果直接保存任何optarg指针,它们将指向空间,你有free()'d - 你使用strdup(),这样你就可以安全了。

重置getopt()

如果您之前调用了getopt,则需要重置其中的一些变量,以便它可以再次扫描,(有关说明,请参阅getopt手册页)。你需要这样做:

optind = 0;

argv中的索引错误 argv中的第一个索引按惯例是程序名,而不是任何程序参数。 因此,请确保您的argv [0]不是您的任何参数。但它需要是一个有效的字符串而不是例如一个NULL指针。

argv [1]应该是第一个参数。

将一个sentiel添加到argv

main()的传统argv以NULL指针结束,您的模拟argv也应如此。 在while循环之后,执行

argv[argc] = NULL;

答案 1 :(得分:2)

getopt(3)认为argv[0]是程序名称,因此只会解析argv[1]argv[2]等的参数...

要使其正常运行,请在构建临时数组时在argc中将1初始化为parse()

int argc = 1;

答案 2 :(得分:0)

我无法为您的帖子添加评论。但我想知道以下内容: -

为什么你不能直接从Main调用scanOptions()。

scanOptions(argc,argv);

答案 3 :(得分:0)

getopt期望参数存储在argv的索引1上。

按惯例

argv[0]由程序名称使用。

所以你可能想改变你的代码:

int argc = 0;

是:

int argc = 1;

答案 4 :(得分:0)

我添加了正确的代码片段以供参考:

    char *param = strtok(cmdLine, " ");
    argv[argc++] = "dummy";
    while (param && argc < MAX_ARGS) {
        argv[argc++] = param;
        param = strtok(NULL, " ");
    }
    scanOptions(argc, argv);
    free(cmdLine);

解决方案是添加argv [argc ++] =“dummy”;填写argv [0]并在scanOptions之后调用free(cmdLine)。

答案 5 :(得分:-1)

这远非复杂和错误的错误。你不能保持这个。请改用boost :: program_options。

看起来像:

namespace po = boost::program_options;

boost::program_options::variables_map vars;

po::options_description options("Command line options");

options.add_options()
    ("help", "display this help message and exit")
    ("in", po::value<std::string>()->default_value("file1.txt"), "input file")
    ("out", "output file");

po::store(po::parse_command_line(argc, argv, options), vars);
po::notify(vars);

std::string infile = vars["in"].as<std::string>();