Как соответствовать второй раз при использовании sscanf - PullRequest
2 голосов
/ 31 марта 2019

Я новичок в C и столкнулся с проблемой при использовании sscanf () в C.

Мой код предлагает пользователю ввести несколько строк данных. Отдельные данные похожи на кортеж Python (1, 3) или (-3, 2), и каждая строка может содержать несколько «кортежей», разделенных нулями или несколькими пробелами, мой код приведен ниже,

char buffer[100];

while(fgets(buffer, sizeof buffer, stdin) != NULL) {
    while(sscanf(&buffer, "%*[^0-9|-]%i%*[^0-9|-]%i", &key, &value) != 1) {
        break;
    }
    printf("key==%d, value==%d\n", key, value);
}

Я использую fgets для чтения каждой строки, которую вводит пользователь, и sscanf для получения кортежа, но кажется, что sscanf не может сопоставить второй кортеж в одной строке (или как сопоставить). Зачем? Или есть какие-то более мудрые решения для моей проблемы?

1 Ответ

3 голосов
/ 31 марта 2019

Спецификатор %n даст количество символов, обработанных при сканировании, и сохранит его в виде int.
Скопируйте их в смещении, чтобы выполнить итерацию по линии.
Это sscanf может возвращать EOF, 0, 1 или 2. Попробуйте использовать == 2, так как вы хотите отсканировать два целых числа.

char buffer[100];
int offset = 0;
int scanned = 0;
while ( fgets ( buffer, sizeof buffer, stdin) != NULL) {
    offset = 0;
    scanned = 0;
    while ( sscanf ( buffer + offset, "%*[^0-9|-]%i%*[^0-9|-]%i%n", &key, &value, &scanned) == 2) {
        offset += scanned;
        printf("key==%d,value==%d\n",key,value);
    }
}

В случае, если %n не работает, strchr можно использовать для поиска (, sscanf (и двух целых чисел, а затем найти закрывающее ). Повтор.
Это использует предложение @ WeatherVane гораздо более простой строки формата.

char buffer[100];
char *begin = NULL;
char *end = NULL;
while ( fgets ( buffer, sizeof buffer, stdin) != NULL) {
    end = buffer;
    while ( begin = strchr ( end, '(')) {//get pointer to (
        if ( sscanf ( begin, "(%d ,%d", &key, &value) == 2) {//scan ( and two integers
            printf("key==%d,value==%d\n",key,value);
        }
        end = strchr ( begin, ')');//get pointer to )
        if ( ! end) {
            break;//did not find )
        }
    }
}

Другая стратегия может использовать strspn и strcspn

char buffer[100];
size_t begin = 0;
size_t count = 0;
while ( fgets ( buffer, sizeof buffer, stdin) != NULL) {
    begin = 0;
    while ( buffer[begin]) {// not zero
        count = strcspn ( &buffer[begin], "-0123456789");//count of non digit or -
        begin += count;
        if ( sscanf ( &buffer[begin], "%d ,%d", &key, &value) == 2) {//scan ( and two integers
            printf("key==%d,value==%d\n",key,value);
        }
        count = strspn ( &buffer[begin], " ,-0123456789");//count space , - or digit
        begin += count;
    }
}
...