C语言 命令行解析在argc/argv



我有以下代码:

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("%sn", argv[argc-1]);
    }
    free(cmdLine);
    scanOptions(argc, argv);
    printf("Filename %sn", 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 %sn", filename); prints "Filename (null)".

那有什么不对吗?

有几件事不对,可能是也可能不是你的问题的原因:

已释放内存使用情况

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]应该是第一个参数

为argv添加一个哨兵

main()的传统argv以NULL指针结束,你的模拟argv也应该这样。在while循环之后,执行

argv[argc] = NULL;

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

要使其工作,在parse()中初始化argc1,同时构建临时数组:

int argc = 1;

getopt期望从索引1开始将参数存储在argv中。

argv[0]按惯例用在程序名后面。

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

int argc = 0;

:

int argc = 1;

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

    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";

我不能给你的帖子添加评论。但我想知道以下内容:-

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

scanOptions(命令行参数个数,argv);

这太复杂了,容易出错。你不能维持这个。请使用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>();

最新更新