2016-04-05 2 views
0

Я использую getopt для синтаксического анализа параметров из командной строки, и у меня возникли проблемы, чтобы распознать необязательный порядок параметров.getopt не получает параметры в некотором порядке

Я хочу, чтобы достичь этих случаев:

$ ./program -i file.html -o output.html #ex 1 
$ ./program -i -o file.html output.html #ex 2 
$ ./program -o output.html -i file.html #ex 3 

мой код выглядит следующим образом

while((c = getopt(argc, argv, "hi:o:")) != -1) { 
    switch(c) { 
     case 'h': 
      //prints the help file 
      break; 
     case 'i': 
      ivalue = optarg; 
      break; 
     case 'f': 
      fvalue = optarg; 
      break; 
     case '?': 
      //prints an error 
      break; 
     default: 
      abort(); 
    } 
} 

для отладки лучше это я писал вне время

for(int i = optind; i < argc; i++) { 
    printf("non optional argument %s\n", argv[i]); 
    return 0; 
} 

, поэтому примеры 1 и 3 правильно работают, а пример 2 не получает параметры прямо. Сначала я подумал, что с этой функцией просто невозможно, но затем в примере this я видел это.

Существует также вопрос о бонусе: как получилось, что вызов программы без параметров не abort()?

Я использую ubuntu 15.10 и gcc 5.2.1, установленный с apt-get (dunno, если полезен, но лучше безопасно, что жаль).

+2

Пример №2 не соответствует стандарту командной строки POSIX (реализуется 'getopt'). Опционные аргументы должны следовать за опцией напрямую. – interjay

+1

Пример, с которым вы связались, смутил вас. Вы видите опцию '-a', заменяемую на разные позиции, но обратите внимание, что этот параметр не принимает аргумент. Параметр '-o' принимает аргумент и замечает, что ни один из примеров там не вставляет' -a' между '-o' и его аргументом. Как заметил @interjay, когда опция принимает аргумент, этот аргумент должен следовать за опцией напрямую. –

ответ

0

в this пример я видел [возможно].

Нет, вы этого не сделали. Ваш параметр -i требует аргумента, но в вашем нерабочем случае вы пытаетесь вставить другой параметр между -i и его аргументом. Это недопустимо - если опция принимает аргумент, необязательный или обязательный, этот аргумент (если он предоставлен) должен немедленно следовать букве опций. Приведенный вами пример не отличается по-разному.

То, что вы пытаетесь сделать, не только не поддерживается getopt(), оно не соответствует стандартным соглашениям Unix. Более того, хотя он мог бы работать так, как вы себе представляете, для опций с требуется аргументов, он полностью неработоспособный для опций с факультативно аргументов. Когда аргументы являются необязательными, нет возможности правильно сопоставить их с их параметрами, если им не требуется следовать напрямую.

Существует также бонусный вопрос: как получилось, что вызов программы без параметров не прерывается()?

Зачем ему это?Если в командной строке не указаны параметры, то getopt() возвращает -1 при первом вызове, а тело цикла никогда не выполняется. Чтобы получить код abort() из вашего кода, вам нужно указать опцию, которая находится в строке параметров, но для которой вы не указываете конкретный случай, или параметр, требующий аргумента, но не предоставляющий аргумент (в котором событие getopt() возвращает ':', для которого вы не предоставляете конкретный случай). Поскольку код в настоящее время написан, это должно быть -o, либо с аргументом, либо без него, или -i без аргумента.

0

То, что вы пытаетесь сделать, невозможно с getopt. "i:" в вашей optstring означает, что если параметр -i присутствует, он должен иметь аргумент. В вашем втором примере это означает, что -o интерпретируется как аргумент -i, а не как опция.

Если вы на Linux и связь с Glibc вы можете использовать :: GNU расширения (например. "hi::o:"), чтобы сделать -i принимать необязательный аргумент. Однако это нарушит ваш первый и третий примеры, поскольку необязательный аргумент должен появиться сразу после опции (например, -ifile.html).

Смежные вопросы