Как посчитать аргумент с пробелом и ввод как один аргумент в C?

Я ввожу следующую командную строку:

./file -a 1 -b2 -a5 -b 55 -b4

Вывод, который я получаю:

a: 1
argv[1]: -a
b: 2
argv[2]: 1
a: 5
argv[3]: -b2
b: 55
argv[4]: -a5
b: 4
argv[5]: -b
Counter: 5

Результат, который я хочу получить, должен быть:

a: 1
argv[1]: -a 1
b: 2
argv[2]: -b2
a: 5
argv[3]: -a5
b: 55
argv[4]: -b 55
b: 4
argv[5]: -b4
Counter: 5

Аргументы с пробелом в настоящее время считаются как 2 аргумента. Я хотел бы, чтобы моя программа учитывала его только как 1 аргумент (я хочу, чтобы он видел «-a 1». Не «-a» и «1» отдельно).

Это исходный код, который я использую, я получаю результаты:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

int main(int argc, char *argv[]) 
{
    int opt = 0;
    int quantum1 = 0, quantum2 = 0;
    int counter = 0;

    while ((opt = getopt(argc, argv,"a:b:")) != -1) 
    {
        switch (opt) 
        {                           
             case 'a' : 
                quantum1 = atoi(optarg); 
                printf("a: %d\n", quantum1);
                break;

             case 'b' : 
                quantum2 = atoi(optarg);
                printf("b: %d\n", quantum2);
                break;

             default: 
                printf("Error\n");
                return 1;
                break;
        }
        counter++;
        printf("argv[%d]: %s\n", counter, argv[counter]);
    }

    printf("Counter: %d\n", counter);

    return 0;
}

Примечание. Предлагаемые кавычки работают, но мне не разрешено использовать кавычки или любые другие символы.


person Lord Rixuel    schedule 30.03.2014    source источник


Ответы (2)


Использовать

./file "-a 1" -b2 -a5 "-b 55" -b4

сделать «-a 1» первым аргументом и «-b 55» четвертым аргументом.

Если теперь вам разрешено использовать кавычки, вы можете избежать пробела в Linux, используя:

./file -a\ 1 -b2 -a5 -b\ 55 -b4
person R Sahu    schedule 30.03.2014
comment
Мне не разрешено использовать обратную косую черту или любые другие символы. Это должна быть только опция (-a) и ввод (1). - person Lord Rixuel; 30.03.2014
comment
Если вам не разрешено использовать одинарную кавычку, двойную кавычку или escape-символ, я не думаю, что в любом случае вы можете заставить свою программу получать -a 1 в качестве одного аргумента. - person R Sahu; 30.03.2014
comment
Он уже получает -a 1 в качестве единственного аргумента. Смотрите мой ответ. - person user3386109; 30.03.2014

Проблема не в том, как анализируются аргументы. Проблема в том, как код отображает аргументы. В частности, когда между параметром и аргументом существует пробел, optind увеличивается на два. optind — это внешняя переменная, которую getopt использует для отслеживания следующего индекса в массиве argv.

Поэтому, если вы просто удалите counter и строки, показанные ниже, вы обнаружите, что ваш код уже работает правильно.

    counter++;
    printf("argv[%d]: %s\n", counter, argv[counter]);

printf("Counter: %d\n", counter);

Если вам абсолютно необходимо подсчитать количество найденных аргументов, просто обновите counter в каждом операторе case, например.

        case 'a' :
            counter++;
            ...

        case 'b' :
            counter++;
            ...

а затем распечатать счетчик в конце. Вас смущает строка printf("argv[%d]: %s\n", counter, argv[counter]);. Эта строка не служит никакой полезной цели и должна быть удалена.


Для командной строки ./test -a1 -b 2 строки в argv будут

argv[0]: "./test"
argv[1]: "-a1"
argv[2]: "-b"
argv[3]: "2"

Когда вы вызываете getopt в первый раз, он будет читать argv[1] и распознает -a как одну из указанных вами опций, поэтому он разбивает строку на две части и возвращает 'a', устанавливая optarg в "1".

Когда вы вызовете getopt во второй раз, он будет читать argv[2] и распознает опцию -b. Поскольку вы указали, что -b принимает аргумент, но argv[2] не содержит аргумента, getopt примет argv[3] в качестве аргумента. Следовательно, он возвращает 'b' при установке optarg на "2".

Суть в том, что getopt предназначен для игнорирования пробела между параметром и его аргументом. Это достигается путем обработки двух строк из argv, если пользователь помещает пробел между параметром и его аргументом.

person user3386109    schedule 30.03.2014
comment
Я понимаю. Счетчик считает -a 1 и -a1 как 1 аргумент, но argv[счетчик] не отображает -a 1 и -a1 как один. - person Lord Rixuel; 31.03.2014
comment
Когда я ввожу cmd: ./test -a1 -b 2 Счетчик правильно считает argc (есть 3 argc). Когда я пытаюсь отобразить argv[counter-1] (argv начинается с регистра 0), он отображает не -b 2, а вместо этого -b. - person Lord Rixuel; 31.03.2014
comment
@LordRixuel Я обновил ответ, чтобы объяснить, как getopt обрабатывает строки в массиве argv. - person user3386109; 31.03.2014
comment
Так нельзя ли включить пробел между опцией и ее аргументом? - person Lord Rixuel; 01.04.2014