Подтвердить что ты не робот

C getopt multiple value

Мой аргумент таков:

./a.out -i file1 file2 file3

Как я могу использовать getopt() для получения 3 (или более) входных файлов? Я делаю что-то вроде этого:

while ((opt = getopt(argc, argv, "i:xyz.."))!= -1){
  case 'i':
     input = optarg; 
     break;
  ...
}

Я получаю только file1; как получить file2, file3?

4b9b3361

Ответ 1

Если вам нужно, вы можете начать с argv[optind] и приращения optind самостоятельно. Тем не менее, я бы рекомендовал против этого, так как я считаю, что синтаксис является плохим. (Как вы знаете, когда вы достигли конца списка? Что делать, если у кого-то есть файл с именем - в качестве первого символа?)

Я думаю, что было бы лучше изменить синтаксис:

/a.out -i file1 -i file2 -i file3

Или обрабатывать список файлов в качестве позиционных параметров:

/a.out file1 file2 file3

Ответ 2

Я знаю, что это довольно старый, но я нашел это в своем поиске решения.

while((command = getopt(argc, argv, "a:")) != -1){

    switch(command){
        case 'a':

        (...)

        optind--;
        for( ;optind < argc && *argv[optind] != '-'; optind++){
              DoSomething( argv[optind] );         
        }

        break;
    }

Я обнаружил, что int optind (extern, используемый getopt()) указывает на следующую позицию после "текущего argv", выбранного getopt(); Вот почему я уменьшаю его вначале.

Прежде всего, для проверки цикла, если значение текущего аргумента находится в границах argv (argc - длина массива, поэтому последняя позиция в массиве argv - argc-1). Вторая часть && сравнивается, если следующий аргумент сначала char равен '-'. Если первый char равен '-', тогда у нас заканчиваются следующие значения для текущего аргумента else argv [optind] - наше следующее значение. И так до тех пор, пока argv не закончится или аргумент не закончится.

В конце инкремента optind проверить следующий argv.

Обратите внимание, что, поскольку мы проверяем 'optind < argc 'первая вторая часть условия не будет выполнена, если первая часть не верна, поэтому не стоит беспокоиться о чтении вне границ массива.

PS Я - совершенно новый программист на C, если у кого-то есть улучшения или критика, пожалуйста, поделитесь им.

Ответ 3

Обратите внимание на то, что расширение перестановок с неконформным расширением glibc нарушит любую попытку использовать несколько аргументов для -i таким образом. И в системах, отличных от GNU, "второй аргумент -i" будет интерпретироваться как первый аргумент без опционов, останавливая дальнейший разбор параметров. Учитывая эти проблемы, я бы отбросил getopt и написал собственный синтаксический анализатор командной строки, если вы хотите использовать этот синтаксис, поскольку это не синтаксис, поддерживаемый getopt.

Ответ 4

Я посмотрел и попробовал код выше, но я нашел свое решение немного легче и работал лучше для меня:

Мне нужна была обработка:

-m mux_i2c_group mux_i2c_out

(требуется 2 аргумента).

Вот как это вышло для меня:

case 'm':
    mux_i2c_group = strtol(optarg, &ch_p, 0);

    if (optind < argc && *argv[optind] != '-'){
        mux_i2c_out = strtol(argv[optind], NULL, 0);
        optind++;
    } else {
        fprintf(stderr, "\n-m option require TWO arguments <mux_group> "
                        "<mux_out>\n\n");
        usage();
    }

    use_mux_flag = 1;
    break;

Это захватило первое значение, которое меня как нормальное, а затем просто искало второе значение REQUIRED.

Ответ 5

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

Например, если $files = "file1, file2, file3" -

for i in ${files//,/ } ; do
    ..do stuff with $i..
done