C: параметры синтаксического анализа в правильном направлении

Я пытаюсь разобрать два варианта в программе на Си.

Программа называется так:

./a.out [OPTIONS] [DIRECTORY 1] [DIRECTORY 2]

Программа синхронизирует две директории и имеет две опции. (-r) для рекурсивной синхронизации (папка внутри папки) и (-n) скопировать файл с локального на удаленный, если он не существует в удаленном.

Options are:
-r : recursive
-n : copy file if it doesn't exist in remote folder

Так зовем:

./a.out -r D1 D2

будет рекурсивно синхронизировать все файлы и каталоги из D1 в D2, Файлы представлены в D1 и не присутствует в D2 игнорируются

И зовет:

./a.cout -rn D1 D2

будет делать то же самое, но файлы, присутствующие в D1 и не присутствует в D2 копируются в D2,

Проблема в том, что вызов ./a.out -rn это не то же самое, что звонить ./a.out -nr а также ./a.out -r -n не работает ни потому, что (-n) не является D1,

Вот как я реализую главное.

int main(int argc, char** argv) {
  int next_option = 0;
  const char* const short_options = "hrn:";

  const struct option long_options[] = {
    { "help",      0, NULL,  'h' },
    { "recursive", 1, NULL,  'r' },
    { "new", 1, NULL,  'n' },
    { NULL,        0, NULL,  0   }
  };

  int recursive = 0;
  int new = 0;

  do {
    next_option = getopt_long(argc, argv, short_options, long_options, NULL);

    switch(next_option) {
      case 'r':
        recursive = 1;
        break;

      case 'n':
        new = 1;
        break;

      case 'h':
        print_help();
        return 0;

      case -1:
        break;

      default:
        print_help();
        return -1;
    }

  } while(next_option != -1);

  sync(argv[2], argv[3], recursive, new);

  return EXIT_SUCCESS;
}

2 ответа

Решение

У вас есть две (потенциальные) проблемы здесь:

  1. У вас есть шальные : в вашей короткой строке параметра. Это делает -n выбрать опцию, которая проглатывает любое следующее r, У вас также есть длинные параметры для обязательных аргументов.

  2. Вы жестко закодировали номера аргументов негибким способом и не проверяете их существование.

Попробуй это:

int main(int argc, char** argv) {
  int next_option = 0;
  const char* const short_options = "hrn";
  extern int optind;

  const struct option long_options[] = {
    { "help",      no_argument, NULL,  'h' },
    { "recursive", no_argument, NULL,  'r' },
    { "new",       no_argument, NULL,  'n' },
    { NULL,        no_argument, NULL,  0   }
  };

  int recursive = 0;
  int new = 0;

  do {
    next_option = getopt_long(argc, argv, short_options, long_options, NULL);

    switch(next_option) {
      case 'r':
        recursive = 1;
        break;

      case 'n':
        new = 1;
        break;

      case 'h':
        print_help();
        return 0;

      case -1:
        break;

      default:
        print_help();
        return -1;
    }

  } while(next_option != -1);

  if (optind + 1 >= argc)
    return -1;

  sync(argv[optind], argv[optind+1], recursive, new);

  return EXIT_SUCCESS;
}

Проблема с использованием командной строки, такой как -r -n потому что вы жестко закодировали индексы в вызове sync, Вы не должны этого делать.

Если вы читаете getopt_long Страница справочника (всегда, когда у вас есть проблемы с функцией!), тогда вы заметите эту строку:

Если дополнительных символов нет, getopt () возвращает -1. Тогда optind - это индекс в argv первого элемента argv, который не является опцией.

Прочитайте второе предложение внимательно.

Другие вопросы по тегам