Sscanf с многострочной строкой - PullRequest
3 голосов
/ 18 ноября 2010

У меня есть строка с несколькими строками, и я хочу использовать sscanf для соответствия ее частям. Однако кажется, что он работает только с соответствующими данными, содержащимися в первой строке.

Например, если у меня есть строка:

"age1: x \ r \ n возраст2: х "

И используя sscanf:

sscanf (строка, age1:% d, & i); - это работает
sscanf (строка, "age2:% d", & j); - однако это не так.

Есть идеи?

Ответы [ 5 ]

5 голосов
/ 18 ноября 2010

Как уже говорили другие, sscanf не помнит, сколько данных было прочитано, и продвигает входные данные, как scanf и fscanf. Используйте спецификатор %n, чтобы запомнить, сколько данных было прочитано, и выполнить ввод самостоятельно:

int bytesRead;
if(sscanf(string, "age 1: %d\n%n", &i, &bytesRead) == 1) &&
   sscanf(string + bytesRead, "age 2: %d", &j) == 1)
{
    // success
}
else
{
    // parsing failed
}

Спецификатор %n говорит: «скажи мне, сколько байтов ввода было прочитано до этой точки, и сохрани его в следующем аргументе (который должен быть указателем на int)». Поместив его в конец строки формата, мы можем выяснить, сколько входных данных было проанализировано. Также обратите внимание, что я добавил новую строку после %d, чтобы мы использовали пробел после первого целого числа; в противном случае, когда мы попытаемся прочитать "age 2", он увидит символ новой строки вместо символа a, и синтаксический анализ не будет выполнен, потому что это не соответствует.

1 голос
/ 18 ноября 2010

Использование sscanf не изменит строку как поток, поэтому во втором вызове sscanf оно начнет сопоставлять age2 с age1, а поскольку оно не совпадает, оно не будет читать значение.

Вы можете либо выполнить второе чтение после содержимого прочитанного в первом, либо вы также можете прочитать его сразу:

sscanf(string, "age1: %d \n\r age2: %d", &i, &j);
1 голос
/ 18 ноября 2010
  1. Вы проверяли статус возврата с sscanf()?
  2. Какое число вы ожидали преобразовать в строку в виде x?
  3. Так как каждый вызов sscanf() начинается в начале, 'Age2:' не совпадает с 'Age1:', и, следовательно, преобразование не выполняется.

Обратите внимание, что любой символ в строке формата, который не является частью спецификатора преобразования, должен точно совпадать. Таким образом, когда сканирование видит 2 из «Age2», оно находит 1 из «Age1» в строке, и сканирование завершается с ошибкой в ​​этой точке. Исключением является то, что пробелу соответствует любая последовательность пробелов - см. Код ниже.

Пример кода:

#include <stdio.h>

int main(void)
{
    const char string[] = "Age1: 3\r\nAge2: 5\r\n";
    const char *scan[] = { "Age1: %d", "Age2: %d", "Age1: %d Age2: %d" };
    int age1, age2;
    int rc;

    if ((rc = sscanf(string, scan[0], &age1)) != 1)
        printf("scan failed on '%s'\n", scan[0]);
    else
        printf("scan passed on '%s' - age %d\n", scan[0], age1);

    if ((rc = sscanf(string, scan[1], &age2)) != 1)
        printf("scan failed on '%s'\n", scan[1]);
    else
        printf("scan passed on '%s' - age %d\n", scan[1], age2);

    if ((rc = sscanf(string, scan[2], &age1, &age2)) != 2)
        printf("scan failed on '%s'\n", scan[2]);
    else
        printf("scan passed on '%s' - age1 %d, age2 %d\n", scan[2], age1, age2);

    return 0;
}

Пример вывода

scan passed on 'Age1: %d' - age 3
scan failed on 'Age2: %d'
scan passed on 'Age1: %d Age2: %d' - age1 3, age2 5
0 голосов
/ 18 ноября 2010

Строка не может вспомнить, где был sscanf после окончания чтения первой строки. (Если вы этого хотите, вы можете посмотреть возвращаемое значение и запомнить его самостоятельно.)

Но вы можете сделать это за один звонок:

sscanf(string, "age1: %d age2: %d", &i, &j);
0 голосов
/ 18 ноября 2010

если вы ограничены c (то есть не можете использовать std :: getline), тогда самый простой способ - это читать данные по символу за раз и анализировать их самостоятельно.

Вы можете использовать atoi и atof для преобразования любых чисел

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...