sscanf not working?

Igor 6.22A on windows 7:

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


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.
If you have a known structure of the string being returned, I would recommend using either StringByKey or treating it as a space/tab delimited list. Then you can use StringFromList to get the value after the nth space/tab

I've found both of these methods to be much more reliable ways of extracting values from a string; but that's my opinion.
I suspect there is also a REGEX pattern that would do the trick nicely. I have to wait though for my morning coffee to take further effect before I might be able to puzzle it out :-)

--
J. J. Weimer
Chemistry / Chemical & Materials Engineering, UAHuntsville
Here is the documentation for the s format specifier:

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
johnweeks wrote:

s Stores text up to the next white space into a string.


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.
I was not aware of the specification of %s to store up to the next whitespace - honestly I'm surprised I have never encountered problems due to this before!

Thanks a lot to all for the help.