6

誰かが getopt 関数を手伝ってくれますか?

メインで次のことを行うと:

char *argv1[] = {"testexec","-?"};
char *argv2[] = {"testexec","-m","arg1"};
int  cOption;
/* test for -? */

setvbuf(stdout,(char*)NULL,_IONBF,0);
printf("\n argv1 ");
while (( cOption = getopt (2, argv1, "m:t:n:fs?")) != -1) {
    switch(cOption){
        case 'm':
            printf("\n -m Arg : %s \n",optarg);
            break;
        case '?':
            printf("\n -? Arg ");
            break;
        case 'n':
            printf("\n -n Arg : %s \n",optarg);
            break;
    }
}

printf("\n argv2 ");

while (( cOption = getopt (3, argv2, "m:t:n:fs?")) != -1) {
    switch(cOption){
        case 'm':
            printf("\n -m Arg : %s \n",optarg);
            break;
        case '?':
            printf("\n -? Arg : %s \n",optarg);
            break;
        case 'n':
            printf("\n -n Arg : %s \n",optarg);
            break;
    }
}

古い libc バージョンを使用する rhel3 でこのコードを実行しています。どちらが正確かはわかりません。

ここでの問題は、argv2 で 2 回目に getopt が機能しないことです。しかし、最初の getopt 呼び出しを argv1 でコメントアウトすると、機能します。

誰かが私がここで間違っていることを教えてもらえますか?

4

4 に答える 4

13

argv1 と 2 は 0 で終わる必要があります:

char* argv1[] = {"par1", "par2", 0};

編集:OK、getoptのmanページを読んだところ、これが見つかりました:

変数 optind は、argv で処理される次の要素のインデックスです。システムは、この値を 1 に初期化します。呼び出し元は、同じ argv のスキャンを再開するため、または新しい引数ベクトルをスキャンするときに、値を 1 にリセットできます。

そのため、getopt での 2 つの呼び出しの間に optind=1 を設定すると、期待どおりに機能します。

于 2009-02-11T07:45:22.583 に答える
4

この関数は、やgetopt()などのいくつかのグローバル変数を使用して、呼び出し間の状態情報を保存します。オプションの 1 つのセットの処理を終了した後、次のオプションのセットで問題を引き起こしている変数にデータが残っています。変数をクリアすることで呼び出し間の状態をリセットしようとする可能性がありますが、関数が文書化されていない他の変数を使用する可能性があり、それらをすべて取得したかどうかわからないため、それが機能するかどうかはわかりません; さらに、それは完全に移植性がありません (つまり、実装が変更された場合、コードが壊れます)。詳細については、man ページを参照してください。できる限り、特定のプログラムで複数の引数セットに使用しないことをお勧めします。optindoptarggetoptgetopt()getopt()

の状態をリセットする実際の関数があるかどうかはgetoptわかりません (または、関数の再入可能バージョンで、状態を独自の変数に保存できるようになる可能性があります)...一度そのようなものを見たのを覚えているようです。でも今探しても見つからない(-_-;)

于 2009-02-11T07:48:20.720 に答える
2

マニュアルページに記載されているように:

「複数の引数ベクトルをスキャンしたり、同じベクトルを複数回再スキャンしたり、optstring の先頭で '+' や '-' などの GNU 拡張機能を使用したり、スキャン間で POSIXLY_CORRECT の値を変更したりするプログラム。従来の値である 1 ではなく、optind を 0 にリセットして、getopt() を再初期化する必要があります。

于 2013-10-01T12:54:37.180 に答える
1

代わりに getopt_long() を使用しない理由はありますか? ほとんどのプラットフォームでは、getopt() は、長い引数を無効にするスイッチを指定して _getopt_long() を呼び出すだけです。これは、Linux、BSD、さらには HelenOS のような新しい OS など、私が知っている (まだ使用している) ほぼすべてのプラットフォームに当てはまります。

あなたのプログラムを使っている人にとっては、少なくともプログラムの使い方に慣れるまでは、長いオプションを持つ方がはるかに簡単です。

getopt_long() を使用すると、2 つ (またはそれ以上) のオプション インデックスを使用できます。これらは、引数の処理が完了した後も「ライブ」のままにすることができます。対処。

これにより、引数の数と、両方の呼び出しで実際に渡されたオプションの数を簡単に比較できます。他にも多くの利点があります..時代遅れのインターフェースを使用しないことを検討してください.

getopt.h を見れば、私の言いたいことがわかるでしょう。

于 2009-02-11T08:04:32.397 に答える