Как выбрать один из вариантов?
Я экспериментирую с POSIX getopt
функция и столкнулся с некоторой проблемой. Я хочу предоставить режим (чтение или запись) для приложения через аргументы командной строки. Поэтому я попытался сделать что-то вроде этого:
enum mode{
read,
write
};
enum mode mode;
int opt;
while((opt = getopt("rw")) != -1){
switch(opt){
case 'w':
mode = write;
break;
case 'r':
mode = read;
break;
default:
fprintf(stderr, "Usage: %s [-r-w]\n", argv[0]");
exit(1);
}
}
Проблема в том, как это работает, теперь можно пройти оба -r
а также -w
вариант, который не имеет смысла. Я хочу, чтобы был выбран только один из двух режимов.
Что такое "идиоматический" способ сделать это?
3 ответа
Как выбрать один из вариантов?
Я хочу, чтобы пользователь выбрал ровно один режим.
Создайте вспомогательную функцию, которая допускает один и только один допустимый режим.
enum mode get_mode(void) {
int opt = getopt("rw");
if (opt != -1 && getopt("rw") == -1) {
switch(opt){
case 'w': return write;
case 'r': return read;
}
}
fprintf(stderr, "Usage: %s [-r-w]\n", argv[0]");
exit(1);
}
Если бы это был я, я бы использовал что-то вроде этого:
enum mode { DEFAULT, READ, WRITE };
enum mode mode = DEFAULT;
int opt;
while ((opt = getopt("rw")) != -1)
{
switch (opt)
{
case 'w':
if (mode == READ)
err_exit("cannot use mutually exclusive options -r and -w");
mode = WRITE;
break;
case 'r':
if (mode == WRITE)
err_exit("cannot use mutually exclusive options -r and -w");
mode = READ;
break;
default:
fprintf(stderr, "Usage: %s [-r|-w]\n", argv[0]);
exit(1);
}
}
if (mode == DEFAULT)
mode = READ; // Or write, whichever is your default
Обратите внимание, что это позволяет избежать использования неинициализированной переменной mode
,
Я предполагаю подходящую функцию err_exit()
который сообщает об ошибке и выходит. Моя реализация также имеет err_usage()
который будет использоваться err_usage("[-r|-w]");
(и использует вызов функции, err_setarg0(argv[0])
, чтобы записать название программы). Вы можете найти мои реализации в моем хранилище SOQ (вопросы о переполнении стека) на GitHub в виде файлов stderr.c
а также stderr.h
в подкаталоге src / libsoq.
Я также избегаю использовать такие имена, как read
а также write
поскольку они также используются для функций и поэтому скрыты константами перечисления в нижнем регистре (они находятся в пространстве имен обычного идентификатора, так же, как функции и переменные). На самом деле, я бы, вероятно, использовал такой префикс, как OPT_
(следовательно, OPT_DEFAULT
, OPT_READ
, OPT_WRITE
) чтобы избежать коллизий с другими возможными использованиями имен.
Это настолько субъективно, это не очень хороший вопрос, но вот некоторые мысли:
(1) Один из подходов - иметь только один вариант. Поведение по умолчанию читается, если указана опция -w, то режим записывается.
(2) Некоторые Unix-программы решают проблему, говоря "Последний аргумент выигрывает"
(3) Еще один подход заключается в использовании отдельных переменных и обнаружении условия, что оба флага были установлены.
Я видел все три подхода. Возможно, есть и другие идеи.