параметр команды синтаксического анализа со значениями по умолчанию и ограничениями диапазона в C

Мне нужно проанализировать аргументы командной строки в C. Мои аргументы в основном int или float со значениями по умолчанию и ограничениями диапазона.

Я начал реализовывать что-то вроде этого:

option_float(float* out, int argc, char* argv, char* name, description,
    float default_val, int is_optional, float min_value, float max_value)

который я называю, например:

float* pct;
option_float(pct, argc, argv, "pct", "My super percentage option", 50, 1,
    FALSE, 0, 100)

Однако я не хочу изобретать велосипед!

Моя цель - иметь проверку на ошибки ограничений диапазона, выдавать ошибку, если опция не является необязательной и не установлена. И сгенерируйте справочное сообщение, обычно предоставляемое функцией usage ().

Текст использования будет выглядеть так:

--pct     My super percentage option (default : 50). Should be in [0, 100]

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

Какие альтернативы вы бы порекомендовали?


person agramfort    schedule 26.12.2010    source источник
comment
Помощники по синтаксическому анализу аргументов для C / UNIX рассматривают некоторые варианты (возможно, на сайте есть другие вопросы, это общая потребность). Я не знаю ни одного, который бы отвечал всем вашим требованиям, но gengetopt уменьшил бы объем кода, который вам нужно написать.   -  person dmckee --- ex-moderator kitten    schedule 26.12.2010
comment
Gengetopt, к сожалению, является GPL, но gopt и glib кажутся хорошими кандидатами. Я изучу эти два варианта. Спасибо   -  person agramfort    schedule 27.12.2010


Ответы (1)


Предполагая, что вы пишете код для Linux ...

Попробуйте getopt_long (man 3 getopt_long) для параметров с двойным тире.

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

В любом случае, если вы хотите использовать свои функции, как определено, ваш примерный вызов не будет работать так, как определено.

Упрощенный пример:

int main( int argc, char **argv )
{
  float pct = 0.0
  if( !GetArgs(argc, argv, &pct) )
    DoStuff(pct)
}

int GetArgs( int argc, char **argv, float *thePct )
{
  extern char *optarg;
  int  rc = 0;

  (*thePct) = 50.0  /* default val */

  while( (opt = getopt(argc, argv, "hp:")) != -1 )
  {
    switch( opt )
    {
      case  'p':
            (*thePct) = atof( optarg );
            break;

      case  'h':
            MyUsage();  /* Explain everything */
            rc = -1;
            break;
    }
  }

  if( !rc )
  {
    rc = ValidatePct( (*thePct),   /* value to check */
                      0.0,         /* low pct val */
                      100.0 );     /* hi pct val */

    /* Other validations here */

    if( !rc )
      MyUsage();
  }
}

Это позволит сделать такой вызов:

$ myprogram -p 45.0

Если вы придерживаетесь парсеров getopt и getopt_long, вы также можете создавать командные строки, которые принимают параметры, за которыми следует N других аргументов, таких как grep, например:

grep -in -e "SomeRegex" file1, file2, ..., fileN

Вы ведь не программист на PERL из чистого любопытства?

person buzzwang    schedule 27.12.2010
comment
это приятный и простой дизайн для getopt, но все же слишком многословный для программиста Python, которым я являюсь;) Я исследую gopt и glib, как было предложено выше. Благодарность - person agramfort; 27.12.2010
comment
Это название игры с C. Это язык гораздо более низкого уровня, чем Python. - person buzzwang; 28.12.2010