3

我从用户那里得到命令行参数。

然后我为命令切换案例,例如:

    case 'f':
         *file_name = optarg;
         break;

我不确定是否需要对指针进行 malloc,因为我不完全理解 optarg。

这就是 file_name 的声明方式:

char **file_name;

我应该做

int length = strlen(optarg); // This gives a warning about types when compiling.

然后 malloc 为字符串长度 + 1?

对于这种问题,malloc应该怎么做呢?请记住,用户正在将 file_name 输入到 **argv。

编辑:这就是我调用这个函数但仍然出现分段错误的方式。

int main(int argc, char **argv)
{
   char **file_name;
   parser(argc, argvm file_name);
}

void parser(int argc, char **argv, char **file_name)
{
  // Switch cases.
}
4

2 回答 2

7

'optarg' 只是一个指向 argv[] 中元素的指针。因此,不分配内存并复制“optarg”指向的值是安全的。

假设使用以下参数调用您的程序:

myapp -a "hello" -b "world"

你的代码是:

#include <stdio.h>
#include <getopt.h>

void parse_options(int argc, char* argv[], char ** first_arg, char ** second_arg)
{
  const char* opt_string = "a:b:";
  int opt = -1;
  opt = getopt(argc, argv, opt_string);
  while (opt != -1) {
    switch(opt) {
      case 'a':
        *first_arg = optarg; /* points to argv[2]="hello" */
        break;
      case 'b':
        *second_arg = optarg; /* points to argv[4]="world" */
        break;
      default:
        break;
      }
    opt = getopt(argc, argv, opt_string);
  }
}

int main(int argc, char* argv[])
{
  char* first = 0;
  char* second = 0;
  parse_options(argc, argv, &first, &second);
  printf("first=%s, second=%s\n", first, second);
  return 0;
}

我的输出:

freebsd% gcc -Wall main.c
freebsd% ./a.out -a hello -b world
first=hello, second=world
于 2013-11-02T23:35:58.197 回答
2

你说你有:

char **file_name;
...
switch (opt)
{
case 'f':
     *file_name = optarg;
     break;
...
}

代码崩溃是因为您没有分配空间或初始化变量file_name

你需要做什么取决于你想要发生什么。通常,您会将定义更改file_name为:

char *file_name = 0;
...
switch (opt)
{
case 'f':
     file_name = optarg;
     break;
...
}

这允许您在循环/切换之后检测是否提供了文件名,如果没有,您可以提供默认值或报告错误。在这种情况下,您可以检测是否先前提供了文件名,如果提供了对象,则可以检测。

另一种方案是您希望-f在命令行上允许多次使用。然后你需要建立一个指针数组,记录它们的数量。你可能会写:

char **file_name = 0;
size_t num_files = 0;
size_t max_files = 0;
...
switch (opt)
{
case 'f':
     if (num_files == max_files)
     {
         size_t new_files = (max_files + 2) * 2;
         void  *new_space = realloc(file_name, new_files * sizeof(*file_name));
         if (new_space == 0)
             ...report out of memory error...
         file_name = new_space;
         max_files = new_files;
     }
     file_name[num_files++] = optarg;
     break;
...
}

这使用了realloc()如果传入的指针为 NULL 的奇数属性,它会模拟malloc(). 或者,您可以在循环外进行初始malloc()分配并在循环内进行(相同)realloc()。大小的计算第一次分配 4 个条目,然后是 12,然后是 28,等等。如果您担心过度分配,您可以realloc()在循环完成后再次使用以将大小调整为正确的大小,但它可能不会对事情产生太大影响。

在循环之后,您有一个可以处理的文件列表:

for (size_t i = 0; i < num_files; i++)
    process_file(file_name[i]);
于 2013-11-03T01:12:42.763 回答