14

不正なオプションに遭遇した場合getopt、またはgetopt_long遭遇した場合、問題のあるオプション文字をに格納しますoptopt。違法なオプションが長いオプションである場合、どこでそのオプションが何であったかを知ることができますか?そして、何か意味のあるものがそこに保存されoptoptますか?

opterr = 0自動的に出力されるエラーメッセージを抑制するように設定しました。好きな場所に印刷または記録できる独自のメッセージを作成したいのですが、認識されないオプションの名前を含めたいと思います。

4

2 に答える 2

7

マニュアルページがこれらの詳細の真上にあることは間違いありませんが、ソースコードから十分なヒントを収集できます。たとえば、glibc-xyz / posix/getopt.cのglibcの実装_getopt_internal_rです。(おそらく、それがこのGNU拡張関数の唯一の興味深い実装ですか?)

そのコードは、誤ったlongオプションに遭遇すると、0に設定されます。これは、間違いなく非NULであるoptopt場合に、このケースを誤ったshortオプションと区別するのに役立つと思います。optopt

opterr != 0ほとんどの場合、誤ったlongオプションをとして出力するときに生成されるエラーメッセージargv[optind]と、後のコード(常にまたは-控えめに-少なくともほとんど)は、後でoptind戻る前に増分します。

したがって、このプログラムを検討してください。

#include <getopt.h>
#include <stdio.h>

int main(int argc, char **argv) {
  struct option longopts[] = {
    { "foo", no_argument, NULL, 'F' },
    { NULL, 0, NULL, 0 }
  };
  int c;

  do {
    int curind = optind;
    c = getopt_long(argc, argv, "f", longopts, NULL);
    switch (c) {
    case 'f':  printf("-f\n");  break;
    case 'F':  printf("--foo\n");  break;
    case '?':
      if (optopt)  printf("bad short opt '%c'\n", optopt);
      else  printf("bad long opt \"%s\"\n", argv[curind]);
      break;
    case -1:
      break;
    default:
      printf("returned %d\n", c);
      break;
    }
  } while (c != -1);

  return 0;
}

$ ./longopt -f -x --bar --foo
-f
./longopt:無効なオプション-'x'
bad short opt'x'
./longopt:認識されないオプション'--bar'
bad long opt "-バー」
--foo

したがって、これらの場合、のpre- getopt_longvalueをキャッシュするoptindことにより、メッセージと同じ悪いオプションを簡単に出力できopterrます。

__nextcharglibc実装が(「認識されないオプション」の場合)ではなく独自に使用することargv[optind]は検討に値するため、これはすべての場合に完全に正しいとは限りませんが、開始するには十分なはずです。

optindとの繰り返しの呼び出しとの関係を注意深く考えるgetopt_longと、印刷argv[cached_optind]はかなり安全になると思います。 optopt短いオプションの場合、単語内のどの文字が問題であるかを知る必要があるために存在しますが、長いオプションの場合、問題は現在の単語全体です(形式のオプション引数をモジュロで削除します=param)。そして、現在の単語はgetopt_long、(着信)optind値で見ている単語です。

optopt = 0ドキュメントに書かれた保証がない場合でも、私はその振る舞いを利用することについてはやや楽観的ではありません。

于 2010-04-27T21:50:41.397 に答える
6

私が見つけることができる最も近いものは、あなたがBADCH返品を受け取った場合argv、それを引き起こしたアイテムはargv[optind-1]. 問題の引数を見つけるためのより良い方法があるはずです。

于 2010-04-27T21:30:27.280 に答える