Где возможно, я бы рекомендовал изменить синтаксис аргумента команды, чтобы избежать числовых аргументов, либо передав число в качестве аргумента опции (например, -n -5
), либо разрешив его только после разделителя опции --
.
Для случаев, когда изменение синтаксиса аргумента невозможно, в разделе BUGS справочной страницы BSD getopt (3) описан способ сделать это.Я изменил их решение, чтобы избежать optreset
, который не указан в POSIX и не поддерживается glibc :
int ch;
long num;
char *numarg;
while ((ch = getopt(argc, argv, "0123456789")) != -1) {
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
numarg = argv[optind - 1];
if (numarg[0] == '-' && numarg[1] == ch && numarg[2] == '\0') {
num = '0' - ch;
} else if ((numarg = argv[optind]) != NULL && numarg[1] == ch) {
char *ep;
int numoptind = optind;
num = strtol(numarg, &ep, 10);
if (*ep != '\0') {
fprintf(stderr, "illegal number -- %s\n", numarg);
return EXIT_FAILURE;
}
/* Advance getopt internal state to next argument. */
while (optind == numoptind) {
ch = getopt(argc, argv, "0123456789");
assert(ch >= '0' && ch <= '9');
}
} else {
fprintf(stderr, "number after other options -- %s\n", numarg);
return EXIT_FAILURE;
}
break;
default:
/* Unrecognized option character. Error printed by getopt. */
return EXIT_FAILURE;
}
}
Вы можете заменить getopt
с getopt_long
и при необходимости добавьте дополнительные короткие или длинные опции.