Экранирующая квадратная скобка ] в sscanf

Я хочу сканировать строки, например

"[25, 28] => 34"

Я написал небольшую программу для проверки:

#include <cstdlib>
#include <iostream>

int main() {
        char* line = "[25, 28] => 34";
        char a1[100],  a2[100];
        int i;
        sscanf(line, "[%[^,], %[^\]] => %i", a1, a2, &i);
        std::cout << "a1 = " << a1 <<"\na2 = " << a2 << "\ni = "<<i <<"\n";
        return 0;
}

компиляция этого дает

warning: unknown escape sequence '\]'

и вывод

a1 = 25
a2 = 28
i = -1073746244

Если я изменю его на

sscanf(line, "[%[^,], %[^]] => %i", a1, a2, &i);

Я не получаю жалоб на компилятор, но все же

a1 = 25
a2 = 28
i = -1073746244

Я знаю, что проблема во втором токене, потому что

sscanf(line, "[%[^,], %[0123456789]] => %i", a1, a2, &i);

дает

a1 = 25
a2 = 28
i = 34

Но я хочу использовать условие завершения для второго токена. Как я могу это сделать?


person highBandWidth    schedule 21.04.2011    source источник


Ответы (5)


Ты хочешь

sscanf(line, "[%[^,], %[^]]] => %i", a1, a2, &i);

Обратите внимание на три последовательных символа ]: первый — это символ, который не должен сопоставляться в наборе %[, второй завершает набор, начинающийся с %[, а третий соответствует символу ] во входных данных.

person Chris Dodd    schedule 21.04.2011

Как уже упоминали другие... Я не совсем уверен, что вы хотите здесь делать...

Предполагая, что вещи в скобках всегда являются целыми числами, вы можете просто сделать:

int a, b, c;
sscanf(line, "[%d, %d] => %d", &a,&b,&c);

Если вы действительно настаиваете на использовании регулярных выражений и хотите, чтобы какие-то общие вещи были переданы между скобками, вам нужно:

sscanf(line, "[%[^,], %[^]]] => %d", a1, a2, &i);

второе регулярное выражение должно соответствовать всем символам, кроме ] в конце. Я полагаю, что вы пытались избежать ] раньше, но это не обязательно, и компилятор выдает ошибку, потому что он не знает, как справиться с этим выходом.

В предложении захвата для a2 есть 3 ], потому что первое говорит: «не включать этот символ в набор совпадений символов», второе закрывает набор совпадений символов, а третье соответствует ] во входных данных [25, 28] => 34. .

Если я совершенно неправильно понял ваш вопрос, просто уточните, и я могу пересмотреть.

person photoionized    schedule 21.04.2011

Похоже, ваш вопрос в основном сводится к тому, «как включить символ ] в набор сканирования scanf». Это возможно, и вам не нужно этого избегать. Специально для этой цели в спецификации языка указано, что когда символ ] следует сразу за открывающим символом [ или непосредственно за открывающим символом ^, то ] считается частью сканированного набора, а не закрывающей скобкой. Итак, в вашем случае спецификатор формата должен выглядеть как "[%[^,], %[^]]] => %i". \ не требуется.

Я вижу, что вы почти угадали, за исключением того, что вы забыли третий символ ] после второго скансета.

person AnT    schedule 21.04.2011

Для меня это звучит как ошибка компилятора (или, на самом деле, библиотеки) (хотя вам нужна третья правая скобка, а не две). Согласно стандарту (C99, §7.19.6.2):

Если спецификатор преобразования начинается с [] или [^], символ правой скобки находится в списке сканирования, а следующий за ним символ правой скобки является соответствующей правой скобкой, завершающей спецификацию;

person Jerry Coffin    schedule 21.04.2011

ты можешь попробовать

sscanf(line, "[%s, %s] => %d", a1, a2, &i);
person ColWhi    schedule 21.04.2011
comment
-1 не будет работать -- %s сопоставляет все до следующего пробела, поэтому он поглотит следующий знак пунктуации (, или ]), и последующее сопоставление не удастся. - person Chris Dodd; 22.04.2011