sscanf not working?
josh.liptonduffin
I'm sure I'm being totally brain-dead about this, but I can't understand what sscanf is doing. The job is almost trivial, yet I keep getting an unexpected output.
I'm trying to pull values out of a long text file to track the convergence of a particular calculation. I'm trying to pull out one string, one float, and one integer from a single line of text as follows:
function testsscanf()
variable Ene, nCycles
string method
string message = " SCF Done: E(RB3LYP) = -13257.9144422 A.U. after 15 cycles\r"
string formatString = " SCF Done: E(%s) = %f A.U. after %d cycles\r" //this format string doesn't work!!
sscanf message, formatString, method, Ene, nCycles
print method, Ene, nCycles
end
variable Ene, nCycles
string method
string message = " SCF Done: E(RB3LYP) = -13257.9144422 A.U. after 15 cycles\r"
string formatString = " SCF Done: E(%s) = %f A.U. after %d cycles\r" //this format string doesn't work!!
sscanf message, formatString, method, Ene, nCycles
print method, Ene, nCycles
end
When I call the function the first string (called 'method') contains the string "RB3LYP)". Why is the trailing parenthesis getting included, when it's already in the format string? Moreover it causes sscanf to miss the two variables that follow, I guess because the indexing gets messed up. However, if I remove that right parenthesis from the format string so that it reads:
string formatString = " SCF Done: E(%s = %f A.U. after %d cycles\r" //format string works by removing ")" after %s
now I'm able to parse the float and integer (and of course the string still contains the close parenthesis).
I'm probably missing something, but this seems like a bug.
I've found both of these methods to be much more reliable ways of extracting values from a string; but that's my opinion.
December 12, 2012 at 06:56 am - Permalink
--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
December 12, 2012 at 09:12 am - Permalink
s Stores text up to the next white space into a string.
And that is exactly what happened in your example. It's possible that you could use format modifiers (like %.6s maybe?) if the number of characters in your code number is always the same. But I think it would be more robust as others have suggested, to parse it by some other means.
Regular expressions can be very powerful. But as Jim Prouty says, regular expressions may be the solution to a problem, but then you have two problems... If there is a simple solution that doesn't use them, it's usually preferable. In your string, you can use StrSearch() to find the two parens, then extract the code using those indices.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
December 12, 2012 at 09:36 am - Permalink
And this is also why your sscanf doesn't work. If I have
formatString = " SCF Done: E(%s) = %f A.U. after %d cycles\r"
then Igor gives me
RB3LYP) 0 0
Since the last ')' will be eaten by the %s, it is clear that sscanf will be unable the match the ')' in the format string, and it gives up. But if you use
formatString = " SCF Done: E(%s = %f A.U. after %d cycles\r"
then it will work.
Then just drop the trailing ')' from the method string and you'll be all set.
I don't think this situation calls for a regexp or another way of parsing. Just continue using sscanf but keep the above in mind.
December 12, 2012 at 11:34 am - Permalink
Thanks a lot to all for the help.
December 12, 2012 at 11:54 am - Permalink