Как можно определить, что требуемый аргумент опции отсутствует?
Я использую getopt_long
на машине GNU/Linux. Инициализируйте список опций как:
static struct option long_options[] = {
{"mode", required_argument, 0, 9},
{0, 0, 0, 0}
};
Иметь следующую строку кода
c = getopt_long(argc, argv, "", long_options, index_ptr);
Когда я запускаю свою программу с командой:
prog --mode
Приведенная выше строка кода возвращает '?' в с, но не ':', как ожидается, в соответствии с getopt(3)
Страница man: "Ошибка и возврат -1 такие же, как для getopt()"
Да, при использовании / разборе коротких опций можно написать в списке опций что-то вроде ":m:", чтобы переменная c в отсутствующем аргументе содержала ":", а не "?", Но что нужно сделать, чтобы различать два случая (отсутствует аргумент, недопустимая опция) при разборе только длинных опций?
Как можно отличить неверную опцию от опции с пропущенным обязательным аргументом?
2 ответа
Единственный способ, с помощью которого я могу достичь вашей цели - провести различие между недопустимым параметром и допустимым параметром с отсутствующим аргументом, - это установить has_arg
поле структуры параметров для optional_argument
, а затем проверить вручную на аргумент. затем getopt_long()
вернет только значение '?' когда есть недопустимая опция, и вы можете проверить, есть ли у указанной опции аргумент, посмотрев в optarg
, Вот пример:
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
int main(int argc, char *argv[])
{
int i, opt;
int index = -1;
static struct option long_options[] = {
{"mode", optional_argument, NULL, 'm'},
{0, 0, 0, 0}
};
/* suppress error messages */
//opterr = 0;
while ((opt = getopt_long(argc, argv, "", long_options, &index)) != -1) {
if (opt == '?') {
/* do something, perhaps: */
//printf("Invalid option \n");
// exit(EXIT_FAILURE);
}
if (opt == 'm' && optarg == NULL) {
printf("Missing argument in '--mode' option\n");
exit(EXIT_FAILURE);
}
}
return 0;
}
Это действительно досадно, что GNU getopt в этом случае не просто возвращает :( Он был так близок к правильному результату, но явно проверяет, существует ли
:
в короткой строке аргументов .
В моем альтернативном решении я использую этоoptopt
устанавливается на соответствующийval
. Это решает проблему с печатью обобщенного сообщения об отсутствующих аргументах опции, но почему-то кажется грязным. Я не проверял это слишком много, будьте осторожны. Он неправильно обрабатывает входные данные с одним-
.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
int main(int argc, char *argv[])
{
static int req, opt;
static struct option long_options[] = {
{"req_flag", required_argument, &req, 1},
{"opt_flag", optional_argument, &opt, 1},
{"req", required_argument, NULL, 'r'},
{"opt", optional_argument, NULL, 'o'},
{"none", no_argument, NULL, 'n'},
{0, 0, 0, 0}
};
/* suppress getopt's own error messages */
opterr = 0;
int c, option_index;
while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
printf("c=%c (%x), option_index=%d, optind=%d, optopt=%c (%x), optarg='%s'\n",
c, c, option_index, optind, optopt, optopt, optarg);
switch (c) {
case 0:
if (optarg != NULL) {
printf("flag for %s was set to %d (optarg=%s)\n",
long_options[option_index].name, *long_options[option_index].flag, optarg);
// the flag's value is probably useless in the case of req_flag because
// if it is required you probably want to change behavior depending
// on the value of optarg and not just its presence :)
// That (and also handling of optarg of optional flags) would need to
// be done here depending on option_index. I wouldn't recommend using this.
} else {
printf("flag for %s was set to %d\n",
long_options[option_index].name, *long_options[option_index].flag);
}
break;
case 'r':
printf("%s=%s\n", long_options[option_index].name, optarg);
break;
case 'o':
if (optarg == NULL) {
printf("%s given w/o argument\n", long_options[option_index].name);
} else {
printf("%s=%s\n", long_options[option_index].name, optarg);
}
break;
case '?':
if (optopt == 0) {
printf("Invalid option: %s\n", argv[optind-1]);
} else {
printf("Missing argument for long option %s\n", argv[optind-1]);
}
exit(EXIT_FAILURE);
}
}
return 0;
}