是否可以使用getopt_long来解析类似于C程序中的命令行参数的字符串数组?

时间:2022-06-01 16:56:49

I am aware that getopt should be used to parse command line arguments, and not strings.

我知道getopt应该用于解析命令行参数,而不是字符串。

However, I am confused by the fact that if I pass it an array of strings that "looks like" the argv variable, getopt_long seems to work, but only the first time that I call it. For the second, and all the subsequent times, that I call it it ignores any arguments and returns the default ones.

但是,我很困惑的事实是,如果我传递一个“看起来像”argv变量的字符串数组,getopt_long似乎工作,但只是我第一次调用它。对于第二个以及随后的所有时间,我称之为忽略任何参数并返回默认参数。

The reason I am doing this is that I am turning an application that used to take command line arguments in an "interactive" version of it that asks the user for some arguments, then does some actions based on those arguments, then asks for more arguments and so on.

我这样做的原因是我正在转变一个应用程序,该应用程序在其“交互”版本中使用命令行参数,询问用户某些参数,然后根据这些参数执行某些操作,然后请求更多参数等等。

The following code is a minimal example that reproduces the error

以下代码是重现错误的最小示例

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

struct input_parameters{
    char * d; // data set
};

int solver_help(int argc, char* const argv[], struct input_parameters * p)
{
  int c;

  p->d = "default name";

  while (1)
  {
      static struct option long_options[] =
      {
          {"data",  required_argument,     0, 'd'},
          {0, 0, 0, 0}
      };
      /* getopt_long stores the option index here. */
      int option_index = 0;

      c = getopt_long (argc, argv, "d:",
                       long_options, &option_index);

      /* Detect the end of the options. */
      if (c == -1)
        break;

      switch (c)
      {
          case 'd': p->d = optarg;
              break;
          default:
              printf("wrong option specification\n");
              exit(-1);
      }
  }

  return 0 ;


}    


int main () {

    int argc_first = 3;
    char * const argv_first[] = { "getopt_test", "--data", "first" };
    struct input_parameters first_input;
    solver_help(argc_first, argv_first, &first_input);

    printf("I think the data is: %s\n", first_input.d);

    int argc_second = 3;
    char * const argv_second[] = { "getopt_test","--data", "second" };
    struct input_parameters second_input;
    solver_help(argc_second, argv_second, &second_input);

    printf("I think the data is: %s\n", second_input.d);

    return 0;
}

The output of this code is

这段代码的输出是

I think the data is: first
I think the data is: default name

1 个解决方案

#1


3  

From the manual page for getopt:

从getopt的手册页:

In order to use getopt() to evaluate multiple sets of arguments, or to evaluate a single set of arguments multiple times, the variable optreset must be set to 1 before the second and each additional set of calls to getopt(), and the variable optind must be reinitialized.

为了使用getopt()来计算多组参数,或者多次计算一组参数,必须在第二个和每个额外的getopt()调用和变量之前将变量optreset设置为1。 optind必须重新初始化。

Modifying your code slightly gives you the desired results:

稍微修改您的代码可以获得所需的结果:

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

struct input_parameters {
    char * d; // data set
};

int solver_help(int argc, char* const argv[], struct input_parameters * p)
{
    p->d = "default name";

    static struct option long_options[] =
    {
        {"data",  required_argument,     0, 'd'},
        {0, 0, 0, 0}
    };

    int option_index = 0;

    optreset = 1;     /*  ADD THIS  */
    optind = 1;       /*  ADD THIS  */

    int c = getopt_long(argc, argv, "d:",
                        long_options, &option_index);

    switch ( c )
    {
        case -1:
            break;

        case 'd':
            p->d = optarg;
            break;

        default:
            printf("in default case...\n");
            printf("wrong option specification\n");
            exit(EXIT_FAILURE);
    }

    return 0;
}    

int main(void) {

    int argc_first = 3;
    char * const argv_first[] = { "getopt_test", "--data", "first" };
    struct input_parameters first_input;
    solver_help(argc_first, argv_first, &first_input);

    printf("I think the data is: %s\n", first_input.d);

    int argc_second = 3;
    char * const argv_second[] = { "getopt_test","--data", "second" };
    struct input_parameters second_input;
    solver_help(argc_second, argv_second, &second_input);

    printf("I think the data is: %s\n", second_input.d);

    return 0;
}

with output:

paul@horus:~/src/sandbox$ ./go
I think the data is: first
I think the data is: second
paul@horus:~/src/sandbox$ 

#1


3  

From the manual page for getopt:

从getopt的手册页:

In order to use getopt() to evaluate multiple sets of arguments, or to evaluate a single set of arguments multiple times, the variable optreset must be set to 1 before the second and each additional set of calls to getopt(), and the variable optind must be reinitialized.

为了使用getopt()来计算多组参数,或者多次计算一组参数,必须在第二个和每个额外的getopt()调用和变量之前将变量optreset设置为1。 optind必须重新初始化。

Modifying your code slightly gives you the desired results:

稍微修改您的代码可以获得所需的结果:

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

struct input_parameters {
    char * d; // data set
};

int solver_help(int argc, char* const argv[], struct input_parameters * p)
{
    p->d = "default name";

    static struct option long_options[] =
    {
        {"data",  required_argument,     0, 'd'},
        {0, 0, 0, 0}
    };

    int option_index = 0;

    optreset = 1;     /*  ADD THIS  */
    optind = 1;       /*  ADD THIS  */

    int c = getopt_long(argc, argv, "d:",
                        long_options, &option_index);

    switch ( c )
    {
        case -1:
            break;

        case 'd':
            p->d = optarg;
            break;

        default:
            printf("in default case...\n");
            printf("wrong option specification\n");
            exit(EXIT_FAILURE);
    }

    return 0;
}    

int main(void) {

    int argc_first = 3;
    char * const argv_first[] = { "getopt_test", "--data", "first" };
    struct input_parameters first_input;
    solver_help(argc_first, argv_first, &first_input);

    printf("I think the data is: %s\n", first_input.d);

    int argc_second = 3;
    char * const argv_second[] = { "getopt_test","--data", "second" };
    struct input_parameters second_input;
    solver_help(argc_second, argv_second, &second_input);

    printf("I think the data is: %s\n", second_input.d);

    return 0;
}

with output:

paul@horus:~/src/sandbox$ ./go
I think the data is: first
I think the data is: second
paul@horus:~/src/sandbox$