2013-05-22 46 views
0

我有以下代码:命令行解析/ 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("%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); 
     } 
    } 
} 

文件名,stdoutFilenamestderrFilename全球变量。 如果我所说的解析方法为:

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

这有什么错呢?

+0

@nos我的理解OP需要'testfile.txt'了'“-ftest/TESTFILE.TXT”'的这就是为什么我说用'/' –

+0

@GrijeshChauhan号命令行参数分隔用空格breal,为了getopt()工作,你需要将字符串拆分成类似shell的功能。 (这是在空白) – nos

+0

@nos以及我不知道! :( –

回答

4

有几件事情错了,可能会或可能不会是你的问题的原因:

使用释放的内存

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

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

复位getopt的()

如果你叫的getopt之前,你需要重新设置一些变量,因此它可以扫描一遍,(见的解释getopt的手册页)。你需要做的:

optind = 0; 

索引错误argv中 argv中的第一个指数是按照约定的程序名称,没有任何程序参数。 所以确保你的argv [0]不是你的任何论点。但它必须是一个有效的字符串,而不是一个NULL指针。

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

添加sentiel做argv

的主要传统的argv()与NULL指针结束后,您的模拟的argv也应该如此。 while循环之后,执行

argv[argc] = NULL; 
+0

错误是在执行scanOptions之前调用free(cmdLine)。然后我还添加了一行argv [argC++] = strdup(“dummy”);在推送argv中的项目之前,有一个伪造的argv [0]。谢谢。 – salvo

+0

argv [argC++] =“dummy”...不需要strdup; – salvo

-1

这是很复杂和错误phrone。你不能保持这一点。改用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>(); 
+1

的OP是关于C所以升压不能在这里帮助。 – alk

0

我不能评论添加到您的文章。但我想知道以下几点: -

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

scanOptions(argc,argv);

+0

这应该是一个评论,因为它没有回答这个问题。 – alk

+0

因为没有主...这是一个DLL的一部分,我想用一个类似main的命令行调用解析方法 – salvo

+0

@alk,评论功能似乎在我的帐户中被禁用 –

2

getopt(3)认为argv[0]是程序名,因此只能分析论据argv[1]argv[2],等...

要使其工作,在parse()初始化argc1,当你建立你的临时数组:

int argc = 1; 
+2

为什么这是downvoted?似乎找到了问题,首先这样做。 –

0

getopt期望的参数从索引1被存储在argv

argv[0]按惯例使用的程序名称。

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

int argc = 0; 

是:

int argc = 1; 
+0

你是否赞成其他回答说这个?你的回答和downvote同时出现在我身上。 –

+0

@andrewcooke:不,我对它表示赞同,因为它对我来说似乎是正确的,显然...... ;-)这不是在这里打架,不是吗? S-/ – alk

+0

好的,对不起。 andrew –

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] = “伪”;以填充argv [0]并在scanOptions之后调用free(cmdLine)。

+0

虽然这似乎是正确的,但解释并不会改善这个答案。另外:对'pthread_attr_init()'的调用是什么? – alk

+0

对pthread_attr_init ...的调用是为了别的,这与问题无关......解决方法是添加argv [argC++] =“dummy”;以填充argv [0]并在scanOptions之后调用free(cmdLine)。 – salvo