Для чего я понимаю из ваших комментариев, я ожидал бы, что код будет выглядеть примерно так. Непонятно, почему у вас есть аргумент c
.
int main(int argc, char **argv)
{
int opt;
int i_flag = 0;
int b_flag = 0;
int c_flag = 0;
while ((opt = getopt(argc, argv, "bci")) != -1)
{
switch (opt)
{
case 'b':
b_flag = 1;
break;
case 'c':
c_flag = 1;
break;
case 'i':
i_flag = 1;
break;
default:
fprintf(stderr, "Usage: %s [-bci] [file ...]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
if (optind < argc)
{
for (int i = optarg; i < argc; i++)
{
FILE *fp = fopen(argv[i], "r");
if (fp == 0)
fprintf(stderr, "%s: failed to open file %s\n", argv[i]);
else
{
process_file(fp, argv[i], b_flag, c_flag, i_flag);
fclose(fp);
}
}
}
else
{
process_file(stdin, "-", b_flag, c_flag, i_flag);
}
return 0;
}
Предупреждение: Неоткомпилированный код.
process_file()
функция имеет сигнатуру, такие как:
void process_file(FILE *fp, const char *fn, int b_flag, int c_flag, int i_flag);
Если вы хотите переписать файлы, вы должны решить, будете ли вы обрабатывать стандартный ввод (без имени файла), и если да, то как. Если вы просто напишете новый файл на стандартный вывод, легко обрабатывать и стандартный ввод.
Вы можете изменить код, чтобы определить, удалось ли выполнить process_file()
(например, оно возвращает целое число вместо void
) и изменить статус выхода программы в соответствии с тем, успешно ли были обработаны все файлы. Вы можете решить, что вашим функциям не требуется имя файла (что позволяет вам указывать имя, например "-"
или "/dev/stdin"
для стандартного ввода).
Вы можете сделать флаги глобальными переменными, а функция process_file()
может применять соответствующие преобразования к каждой строке. Вы можете сделать несколько преобразований для каждого файла, открыв и закрыв файл между каждым преобразованием или перематывая файл между каждым преобразованием, если хотите. Однако это будет медленнее, чем выполнение трех преобразований параллельно.
ГНУ версия getopt()
обеспечивает аргумент перестановку, так что вы можете выполнить:
program -b -c -i name-of-file
program name-of-file -b -c -i
program -b name-of-file -i -c
и они все работают одинаково (и вы все еще используете код, указанный выше). Лично мне это не нравится, но я старомодный. Вы можете отключить его, если будете осторожны - один из способов - через переменную среды POSIXLY_CORRECT. Вы также можете организовать для getopt()
, чтобы вернуть файлы, как если бы они были аргументами с кодом опции '\1'
(Control-A).
Ну, у вас уже есть цикл, поэтому ваш код уже обрабатывает несколько аргументов ('break' просто выходит из' switch', а не цикла). В чем именно проблема? – NPE
Вы можете установить переменные 'got_flag_b',' got_flag_c' и т. Д. В ваш 'switch' и только после того, как вы зациклились на всех параметрах, запустите свою прикладную логику в зависимости от значений этих переменных.Существует [расширение GNU] (https://www.gnu.org/software/libc/manual/html_node/Getopt.html), чтобы обрабатывать длинные варианты, но я думаю, что это примерно так, как вы можете идти на C без используя генерацию кода. – 5gon12eder
Не то, что я использую getopt, но этот код обрабатывает несколько аргументов (отсюда и цикл). Для части «порядок не имеет значения» вы должны просто установить булевские флаги в этом цикле, а затем просто действовать в соответствии с флагами. –