Опция getopt_long() с необязательным аргументом
Я пытаюсь создать опцию с необязательным аргументом, используя getopt_long().
Вот мой код:
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"debug", no_argument, NULL, 'd'},
{"config", optional_argument, NULL, 'c'},
{NULL, 0, NULL, 0}
};
while ((ch = getopt_long(argc, argv, "hdc::", long_options, NULL)) != -1) {
// check to see if a single character or long option came through
switch (ch) {
case 'h':
opt.help = true;
break;
case 'd':
opt.debug = true;
break;
case 'c':
printf("C-Option: %s\n", optarg);
if (optarg != NULL) {
opt.configFile = optarg;
}
break;
}
}
Я пытаюсь аргументировать -c
необязательно, поэтому вы можете запустить программу с этими параметрами:
-c test.cfg
-> optarg = "test.cfg"
-c
-> optarg = null
Если я установлю c::
чем optarg
всегда null
,
Если я установлю c:
чем я получаю ошибку: option requires an argument -- 'c'
Что я не прав? Есть ли другие варианты, которые я могу установить?
1 ответ
Если опция имеет необязательный аргумент, он должен быть записан непосредственно после символа опции, если он присутствует.
Ваш код работает как положено:
./a.out -c some_argument --> "C-Option: (null)"
./a.out -csome_argument --> "C-Option: some_argument"
./a.out -c=some_argument --> "C-Option: =some_argument"
Вы можете рассмотреть добавление необязательных имен аргументов с помощью '='
, как в приведенном выше примере. Вот еще один вопрос, который обсуждает проблему.
ОБНОВИТЬ
Я видел хорошее решение этой проблемы в ссылке на другой вопрос, упомянутый выше. Идея состоит в том, чтобы проверить, следуя опции, которая принимает аргумент, чтобы увидеть, если следующая строка в argv[]
это вариант. Если нет, то предполагается, что это аргумент. Затем аргумент обрабатывается, и optind
продвигается соответственно. Вот как эта идея может быть применена к вашей проблеме:
case 'c':
if (optarg == NULL && argv[optind] != NULL
&& argv[optind][0] != '-') { // not an option
printf("C-Option: %s\n", argv[optind]);
opt.configFile = argv[optind];
++optind;
} else { // handle case of argument immediately after option
printf("C-Option: %s\n", optarg);
if (optarg != NULL) {
opt.configFile = optind;
}
break;
Этот код приведет к следующему выводу:
./a.out -csome_argument --> "C-Option: some_argument"
./a.out -c some_argument --> "C-Option: some_argument"