|
sscanf equivelant for std::string |
Steve Terry
Member #1,989
March 2002
|
I am trying to parse through a post script file and basically am rotating it 90 degrees. I have the methods to do so and all it involves is flipping width and height, adding one line to rotate, and translating by negative height. I was using fstream.getline and reading into a char array of 4096 chars... which in at least one instance overflowed the buffer, this caused a flag to be set and getline never returned anything afterwards, essentially I went into an infinite loop. The reason I was reading into a char array rather than a std::string was the ease of sscanf in parsing the lines. I now found a different getline call which uses std::string and the overflow issue is gone, however when it comes to something like sscanf C++ lacks. What I did use was stringstream and treated the string as a stream object like cin or cout and I got my values but it's not very elegant. For example: // C sscanf(buffer, "some command:[%f %f] other stuff", &val1, &val2);
I have no idea how to do the same in C++ using strings. If I convert it to a stringstream and do: ___________________________________ |
Trent Gamblin
Member #261
April 2000
|
C++ Strings have a method called c_str that returns a C-type string equivalent of the string. std::string s; Maybe you can use that with sscanf?
|
Steve Terry
Member #1,989
March 2002
|
Yes I realize I could do that as well, convert it to a char array, use sscanf on it, allocate a new char array of size of buffer + 1, sprintf, then spit that out to the output file. I was hoping for something more elegant maybe ___________________________________ |
Trent Gamblin
Member #261
April 2000
|
Regular expressions would be perfect IMO.
|
Steve Terry
Member #1,989
March 2002
|
Like boost? I've seen some examples and it looks like overkill, not to mention I couldn't tell what it was doing Any examples? ___________________________________ |
Trent Gamblin
Member #261
April 2000
|
Well I don't know anything about postscript commands so I don't know if this would be useful but just as an example in Perl, to swap the two floats in your example you could use an expression like this: $s =~ s/some command:[([0-9.]+) ([0-9.]+)] other stuff/some command:[\2 \1] other stuff/g In C++ it's almost the same thing, maybe an extra function call to create an expression or something. Then you'd just print out s. Or you could capture the floats into variables and use them later by replacing the \1 and \2 with $var1/$var2: $s =~ m/some command:[([0-9.]+) ([0-9.]+)] other stuff/; $s =~ s/some command:[([0-9.]+) ([0-9.]+)] other stuff/some command:[$var3 $var4] other stuff/g You can match anything easily with regular expressions. It's learning them that's the (somewhat but not really) tricky part. "Mastering Regular Expressions" is a great book. It can easily save you way more time than it takes to read it if you use them regularly. I wouldn't use a text editor that doesn't support regular expressions. [edit]
|
Steve Terry
Member #1,989
March 2002
|
I know what regular expressions are I found some better boost examples, but I was hoping for something built into C++, but am I right in thinking that boost will be Incorporated into C++ before too long? ___________________________________ |
Carrus85
Member #2,633
August 2002
|
Unfortunately, this is one of the main weak points of the C++ standard library; there is really no sscanf equivilant... period. Basically, you have to do it by yourself. In that particular example you gave us, this will do the job: std::string foo = "some command:[10.0 99.9] other stuff..."; float a = 0, b = 0; size_t left_bound = foo.find('[',0) + 1; size_t count = foo.find(']',left_bound) - left_bound; stringstream bar; bar << foo.substr(left_bound, count); bar >> a >> b; Of course, in general, you can emulate sscanf if necessary (pseudo-code) Something like this (probably not the most efficent method, admittantly...) // Example: std::string input = "foo bar 10 20 hello 30" int a,b,c; std::string garbage; stringstream foo; foo << input; input >> garbage >> garbage >> a >> b >> garbage >> c;
|
Trent Gamblin
Member #261
April 2000
|
Yes, regular expressions and other parts of boost are being considered to be part of standard C++.
|
Erkle
Member #3,493
May 2003
|
I can't see what's wrong with: But if its for some kind of script or something then try looking into Boost.Spirit. Something like: float x, y; rule<> my_rule = str_p("some command:[") >> real_p[assign_a(x)] >> real_p[assign_a(y)] >> str_p("]"); if(parse(buffer, my_rule, space_p).full) { // ToDo: Do something with the results; } Warning: Boost.Spirit can be difficult to understand at the best of times but it is useful enough to make up for it.
If the writing above has offended you, you've read it wrong.....fool. |
Bob
Free Market Evangelist
September 2000
|
Why use boost::spirit when boost::regexp will do? -- |
Thomas Fjellstrom
Member #476
June 2000
|
totally serious: Why use Boost::Anything when some simple char/text greping will do? -- |
CGamesPlay
Member #2,559
July 2002
|
Quote: Why use Boost::Anything when some simple char/text greping will do? I agree. I prefer Carrus' (first) method so far over anything else so far in this thread. -- Ryan Patterson - <http://cgamesplay.com/> |
|