5

C++ プログラムで、必要な引数を指定した "long-only" オプションを使用したいと考えています。以下は、 getopt_long()を使用した最小限の例ですが、機能していません。

#include <getopt.h>
#include <cstdlib>
#include <iostream>
using namespace std;

void help (char ** argv)
{
  cout << "`" << argv[0] << "` experiments with long options." << endl;
}

void parse_args (int argc, char ** argv, int & verbose, int & param)
{
  int c = 0;
  while (1)
  {
    static struct option long_options[] =
      {
        {"help", no_argument, 0, 'h'},
        {"verbose", required_argument, 0, 'v'},
        {"param", required_argument, 0, 0}
      };
    int option_index = 0;
    c = getopt_long (argc, argv, "hv:",
                     long_options, &option_index);
    cout << "c=" << c << endl;
    if (c == -1)
      break;
    switch (c)
    {
    case 0:
      if (long_options[option_index].flag != 0)
        break;
      printf ("option %s", long_options[option_index].name);
      if (optarg)
        printf (" with arg %s", optarg);
      printf ("\n");
      break;
    case 'h':
      help (argv);
      exit (0);
    case 'v':
      verbose = atoi(optarg);
      break;
    case 'param':
      param = atoi(optarg);
      break;
    case '?':
      abort ();
    default:
      abort ();
    }
  }
}

int main (int argc, char ** argv)
{
  int verbose = 0;
  int param = 0;
  parse_args (argc, argv, verbose, param);
  cout << "verbose=" << verbose << " param=" << param << endl;
  return EXIT_SUCCESS;
}

次のコマンドでコンパイルします (gcc バージョン 4.1.2 20080704 Red Hat 4.1.2-46):

g++ -Wall test.cpp

それは私にこれを教えてくれます:

test.cpp:44:10: warning: character constant too long for its type

結果は次のとおりです。

$ ./a.out -v 2 --param 3
c=118
c=0
option param with arg 3
c=-1
verbose=2 param=0

ideoneで動作させようとしましたが、オプションさえ認識しません-v

別の質問のコメントでtrojanfoeが示したように、GNU tarが行うため、「ロングオンリー」オプションを使用できるはずです。しかし、GNU tar はargpを使用しており、そのソース コードを理解するのは困難です。

誰かがGNUgetopt_long()またはargp().

4

4 に答える 4

7

2 つの問題があります。

  1. サンプル コード (リンク) によると、構造体で定義されている最後のオプションは{0,0,0,0}. 定義を次のように変更することをお勧めします

    static struct option long_options[] =
      {
        {"help", no_argument, 0, 'h'},
        {"verbose", required_argument, 0, 'v'},
        {"param", required_argument, 0, 0},
        {0,0,0,0}
      };
    
  2. (さらに重要なことに)「param」オプションを実際に処理するコードを含める必要があります。次の'0'場合に行います。

    case 0:
      if (long_options[option_index].flag != 0)
        break;
      if (strcmp(long_options[option_index].name,"param") == 0)
        param = atoi(optarg);
      break;
    

ご覧のとおり、strcmp関数を使用して文字列を比較しています。そのためには、する必要があります#include <cstring>。ちなみに、の#include <cstdio>使用にも必要ですprintf

これらの変更により、プログラムは正しく機能しました (GCC 4.5.1 でテスト済み)。

于 2012-04-18T16:26:33.813 に答える
5

あなたのケースステートメントでは、次のものを使用しています:

case 'param':

コンパイラはその場所に単一の文字を期待しているため、警告が表示されます。

于 2012-04-18T15:49:47.047 に答える
0

option_index実は、このように、いつのc値が値になるのかを確認する必要があることに気づきました0。このようなケースはGNUlibcの例には含まれていないため、次のようになります。

switch (c)
{
case 0:
  if (long_options[option_index].flag != 0)
    break;
  if (option_index == 2)
  {
    param = atoi(optarg);
    break;
  }
case 'h':
  help (argv);
  exit (0);
case 'v':
  verbose = atoi(optarg);
  break;
case '?':
  abort ();
default:
  abort ();
}
于 2012-04-18T16:23:17.310 に答える
0

別の解決策は、構造体オプションで定義された「フラグ」メンバー値を使用することです。

以下のようにオプションを設定します。

int param_flag = 0;

{"param", required_argument, &param_flag, 1}

それで;

case 0:
    if (param_flag == 1) {
        do_something;
    }

struct オプションの詳細については、man getopt_long を参照してください。

于 2016-10-26T09:47:10.923 に答える