0

我有以下代码:

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

文件名,stdoutFilename并且stderrFilename全局变量。如果我将解析方法称为:

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

那有什么问题?

4

6 回答 6

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] 不是您的任何论点。但它必须是一个有效的字符串,而不是一个空指针。

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

向 argv 添加哨兵

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

argv[argc] = NULL;
于 2013-05-22T08:56:20.977 回答
2

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

为了使它工作,argc1parse()构建你的临时数组时初始化:

int argc = 1;
于 2013-05-22T08:54:05.123 回答
0

我无法在您的帖子中添加评论。但我想知道以下几点:-

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

扫描选项(argc,argv);

于 2013-05-22T08:52:57.967 回答
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)。

于 2013-05-22T09:05:07.433 回答
0

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

argv[0]按约定使用程序的名称。

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

int argc = 0;

成为:

int argc = 1;
于 2013-05-22T08:55:21.270 回答
-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>();
于 2013-05-22T08:47:21.867 回答