значение getopt остается нулевым

Я передаю свои входные данные программы, и я мог видеть их в argv, но у getopt, похоже, нет аргумента, которого я ожидаю.

Вот как я запускаю свою прогу: ./my_prog -X -f имя файла

<snip>
while ((opt = getopt(argc, argv, "Xf:eE:dD")) != EOF) {
    switch (opt) {
       case 'X':
       case 'f':
                if (optarg == NULL)
                fput("no point of living", fp);         << for debugging

</snip>

Я всегда получаю optarg как null. ЗАЧЕМ?


person hari    schedule 23.06.2011    source источник
comment
Вы видите отладочное сообщение для -X или для -f?   -  person mu is too short    schedule 23.06.2011
comment
Но вы уверены, что это -f, а не просто провал из -X?   -  person mu is too short    schedule 23.06.2011
comment
на -X ничего делать не хочу. Переход к -f и имя файла захвата. возможно?   -  person hari    schedule 24.06.2011
comment
Если вы не хотите ничего делать с -X, поставьте break сразу после case.   -  person mu is too short    schedule 24.06.2011


Ответы (4)


В вашей строке аргумента нет : после X (например, X: f), поэтому optarg всегда будет нулевым.

Я также укажу, что обычно в операторе switch вам нужен перерыв после каждого случая (как правило, не всегда, но обычно при разборе аргументов), поэтому:

switch ( ... ) {
    case 'X': {
        // do something
    } break;

    case 'f': {
        // do something else
    } break;
}
person par    schedule 23.06.2011
comment
имя файла должно быть optarg для -f ?? - person hari; 23.06.2011
comment
У меня Xf, а не X:f, поэтому optarg для -X всегда будет NULL, но почему он NULL для -f?? Это потому, что я не ломаюсь после Х?? - person hari; 23.06.2011
comment
Основываясь на вашем коде, я ожидаю, что optarg НЕ будет NULL при оценке opt=='f'. Это должно быть имя файла. Возможно, разместить больше кода? - person par; 23.06.2011
comment
@hari Вы говорите, что он печатает нет смысла ДВА раза, когда вы запускаете его как ./my_prog -X -f имя файла? Если это так, что-то еще не так, поэтому опубликуйте код для полного компилируемого примера, который показывает такое поведение. - person nos; 23.06.2011
comment
@nos Нет. Он не печатает смысла жизни для -f - что неверно, на самом деле. Он должен иметь optarg в качестве имени файла. optarg не должен быть нулевым для -f. - person hari; 23.06.2011
comment
Я просто должен был прерваться после X. Всем спасибо. - person hari; 25.06.2011

Для тех, кто еще может попасть на эту страницу: From http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html#Using-Getopt: An option character in this string can be followed by a colon (‘:’) to indicate that it takes a required argument. If an option character is followed by two colons (‘::’), its argument is optional; this is a GNU extension.

поэтому в своем аргументе вы можете использовать: «X:f:e:E:d:D:»

Была такая же проблема.

person Diogo    schedule 30.03.2012

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

Вы должны убедиться, что устанавливаете внешнюю переменную libc opterr = 0, прежде чем вызывать getopt; если вы не сбрасываете его и getopt ранее имела ошибку в другом приложении в вашей системе, которое его использовало, он не будет работать для аргумента. Я также повторю существующую точку зрения, что, поскольку у вас нет оператора break после case 'X':, это верный признак проблемы, поскольку он не пройдет.

getopt обрабатывает только один аргумент за раз, поэтому попадание из случая X в случай f — плохой поступок. У вас всегда должен быть разрыв в каждом операторе case switch, если вы не абсолютно уверены, что он провалится (что, по моему опыту, очень редко). В качестве еще одной общей хорошей практики вы должны всегда заключать блоки кода в { } (ссылаясь на ваше условное выражение), если только это не оператор return или break или что-то еще, что приводит к тому, что поток программы выпадает из текущей или родительской области блока или для входа в новую область через вызов функции или метода.

Я думаю, что ваша строка опций Xf:eE:dD в порядке. Это указывает на то, что:

1) Далее будут просто флаги опций, которые всегда имеют нулевой аргумент: XedD

2) Для следующих опций потребуется аргумент: fE

Если это та функциональность, которую вы ищете, данная строка опций в порядке. Если вы используете GNU libc, в соответствии с другим приведенным выше ответом вы можете использовать :: после параметра в строке параметра, чтобы указать, что параметр может иметь аргумент, но не обязательно.

Итак, в верхней части файла убедитесь, что у вас есть как минимум:

extern int opterr;

Затем прямо перед тем, как вы вызовете getopt в первый раз в своем коде, установите opterr в 0.

e.g.

opterr = 0;

while ((opt = getopt(argc, argv, "Xf:eE:dD")) != EOF) {
    switch (opt) {
       case 'X':
       case 'f':
                if (optarg == NULL)
                fput("no point of living", fp);         << for debugging

Это должно хотя бы частично решить вашу проблему. Вот ссылка на пример:

http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html

Ваше здоровье,

Джон

person jhyry    schedule 20.06.2014
comment
Спасибо, что опубликовали это. Я дергал себя за волосы, пытаясь заставить мой код работать, и opterr=0 исправил это. - person ; 05.01.2016
comment
Так рад, что это помогло вам. Я помню, когда я имел дело с этим давным-давно, и все это сводило меня с ума на несколько часов. - person jhyry; 15.04.2017

Я знаю, что это старо, но недавно я заметил, что поведение изменилось в том, как я использовал getopt много лет назад. Возможно, это была другая среда, но я обнаружил, что для ее использования сегодня требуется, чтобы optarg был НЕПОСРЕДСТВЕННО после флага (без пробела), в противном случае optarg имеет значение null.

Используя ваш пример, замените ./my_prog -X -f filename на ./my_prog -X -ffilename

Я считаю, что это работает нормально, даже если это кажется неправильным. Надеюсь, это поможет кому-то еще позже. Обязательно попробуйте оба способа.

person BoeroBoy    schedule 09.07.2021