Как сделать передачу аргумента в getopt возможной, но не обязательной?
Вот код
bool grep_parse(grep_info *info, char *argv[], int argc, pattern *patterns,
count *count_patt) {
opterr = 0;
int res;
while ((res = getopt(argc, argv, "e:i:v:n:l:c:")) != -1) {
switch (res) {
case 'e':
info->flag_e = true;
patterns->e_patterns[count_patt->e_count] = optarg;
puts("info->flag_e = true;");
printf("-e arg = '%s'\n", optarg);
count_patt->e_count++;
break; case 'i':
info->flag_i = true;
patterns->i_patterns[count_patt->i_count] = optarg;
count_patt->i_count++;
break; case 'l':
info->flag_l = true;
patterns->l_patterns[count_patt->l_count] = optarg;
count_patt->l_count++;
break; case 'v':
info->flag_v = true;
patterns->v_patterns[count_patt->v_count] = optarg;
count_patt->v_count++;
break; case 'c':
patterns->c_patterns[count_patt->c_count] = optarg;
puts("info->flag_c = true;");
printf("-c arg = '%s'\n", optarg);
count_patt->c_count++;
info->flag_c = true;
break; case 'n':
patterns->n_patterns[count_patt->n_count] = optarg;
count_patt->n_count++;
info->flag_n = true;
break;
default:
return false;
}
}
printf("flags processed, optind = %d\n", optind);
if (optind < argc) {
puts("free args:");
for (int i = optind; i < argc; i++)
puts(argv[i]);
}
grep_distribution(info, argv, argc, optind, patterns, count_patt);
return true;
}
void grep_distribution(grep_info *info, char *argv[],
int argc, int optind, pattern *patterns, count *count_patt) {
char *file_name = malloc(sizeof(char));
bool flag = false;
if (argc - optind > 1) {
flag = true;
}
for (int i = optind; i < argc; i++) {
file_name = argv[i];
FILE * file = fopen(argv[i], "r");
if (!file) {
printf("жесть с файлом\n");
} else {
if (info->flag_c) {
grep_c(file, patterns, count_patt->c_count, file_name, flag);
}
if (info->flag_n) {
grep_n(file, patterns->n_patterns, count_patt->n_count, file_name, flag);
}
if (info->flag_e) {
grep_e(file, patterns->e_patterns, count_patt->e_count, file_name, flag);
}
if (info->flag_i) {
grep_i(file, patterns->i_patterns, count_patt->i_count, file_name, flag);
}
if (info->flag_l) {
grep_l(file, patterns->l_patterns, count_patt->l_count, file_name, flag);
}
if (info->flag_v) {
grep_v(file, patterns->v_patterns, count_patt->v_count, file_name, flag);
}
}
}
//free(file_name);
}
Проблема состоит в том, что в случае приведенного ниже примера вывода getopt принимает флаг -е за аргумент. Можно ли сделать так, чтобы он этого не делал? Флаг -с может содержать аргументы, но если далее следует другой флаг, то предполагается, что его паттерн распространяется и на предыдущий (как я поняла из работы grep)
Пример вывода:
pe@vo-a1 grep % gcc -Wall -Werror -Wextra test.c
pe@vo-a1 grep % ./a.out -c -e int -e include test_1_grep.txt
info->flag_c = true;
-c arg = '-e'
flags processed, optind = 3
free args:
int
-e
include
test_1_grep.txt
жесть с файлом
жесть с файлом
жесть с файлом
test_1_grep.txt:0
Ответы (1 шт):
Наверное в man getopt использование optional аргументов описано как-то невнятно.
Если вы хотите, чтобы у ключа -c был необязательный (optional) аргумент, то в строке ключей, передаваемых в getopt() после него надо написать два двоеточия -- ::. Т.е. ваша строка должна иметь вид -- "e:i:v:n:l:c::".
В этом случае аргумент для ключа -c при вызове программы надо задавать без пробела между ключем и аргументом.
Если вызвать программу вот так
./a.out -c123 -e arg
то в цикле разбора аргументов
while ((res = getopt(argc, argv, "e:i:v:n:l:c::")) != -1) {
switch (res) {
.....
будет вызван
case 'c':
и optarg будет равен "123"
При вызове
./a.out -c -e arg
также будет вызван case 'c':, а optarg в этом случае будет установлен в NULL.