7

I want to scan lines like

"[25, 28] => 34"

I wrote a small program to test it out:

#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;
}

compiling this gives

warning: unknown escape sequence '\]'

and the output

a1 = 25
a2 = 28
i = -1073746244

If I change it to

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

I get no compiler complaints but still

a1 = 25
a2 = 28
i = -1073746244

I know the problem is in the second token because

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

gives

a1 = 25
a2 = 28
i = 34

But I want to use a terminating condition for the second token. How do I do that?

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
highBandWidth
  • 16,751
  • 20
  • 84
  • 131

5 Answers5

12

You want

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

Note the three consecutive ] characters -- the first is the character you don't want to match in the %[ set, the second ends the set starting with the %[ and the third matches the ] character in the input

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
5

As others have mentioned... I'm not exactly sure what you want to do here...

Assuming that the things between the brackets are always integers, you could just do:

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

If you're really insistent about using regex and wanting some generic stuff passed in between the brackets, what you're looking for is:

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

the second regex should be matching all characters except the ] at the end. I believe that you were trying to escape the ] before, but this isn't necessary and the compiler is throwing an error because it doesn't know how to handle that escape.

There are 3 ] in the capture clause for a2 because the first is saying, "don't include this character in the character match set," the second is closing off the character match set, and the third matches the ] in the [25, 28] => 34 input.

If I totally misunderstood your question, just clarify and I can revise.

photoionized
  • 5,092
  • 20
  • 23
3

It look like your question basically boils down to "how to include the ] character into a scanf scanset". It is possible and you don't need to escape it. Specifically for that purpose the language specification states that when the ] character immediately follows the opening [ character or immediately follows the opening ^ character, that ] is considered to be a part of the scanset, not a closing bracket. So, in your case the format specifier is supposed to look as "[%[^,], %[^]]] => %i". No \ necessary.

I see that you almost got it right, except that you forgot the third ] character after the second scanset.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

It sounds to me like a compiler (or, actually, library) bug (though you do need a third right-bracket, not just two). According to the standard (C99, §7.19.6.2):

If the conversion specifier begins with [] or [^], the right bracket character is in the scanlist and the next following right bracket character is the matching right bracket that ends the specification;

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
-2

Try:

sscanf(line, "[%s, %s] => %d", a1, a2, &i);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ColWhi
  • 1,077
  • 6
  • 16
  • 1
    -1 won't work -- `%s` matches everything up to the next whitespace, so it will absorb the following punctuation character (`,` or `]`) and the subsequent match will fail. – Chris Dodd Apr 21 '11 at 23:05