scanf

Definition: sequence paramsets = scanf(string s, string fmt)
Description: Attempt to find a sequence for which sprintf(fmt,params) could have produced s.
Comments: May return more than one set, for example
    res = scanf("one two three","%s %s") -- res is {{"one","two three"},{"one two","three"}}

Note that scanf relies heavily on literal separators, especially spaces. It is illegal to specify back-to-back strings, integers, or atoms with format strings such as "%s%s", "%d%d", "%s%d", etc. The one exception is that a string can immediately follow a number, an example of which is "4th" and "%d%s".

Theoretically it might be possible to write a scanf that yields {{1,23},{12,3}} from scanf("123","%d%d") but I for one cannot think of a single practical use, and getting {{"","AB"},{"A","B"},{"AB",""}} from scanf("AB","%s%s") is also of highly questionable worth. Likewise it is deemed completely unnecessary to be able to get {"hello",12} from "hello12", which proves hard, as opposed to getting that same result from "hello 12", which is trivial.

Any width/precision/justify/zerofill details are for the most part quietly ignored: you may get the same results from %d/%d/%d as %02d/%02d/%04d, but obviously the latter might make the intent clearer. If scanf is about to return several possibilities, it tests the results of sprintf and trims the result set down to those with an exact character-by-character match, as long as that last pass does not trim the result set down to zero.

Internally scanf only cares for d/f/s formats; (x/o/b)/(e/g)/(c) are treated as respective aliases, apart from the afore-mentioned final printf trimming stage that is. For more details regarding format strings please refer to printf. All characters not part of a %-group are treated as literal.

There is no way to suggest, let alone force, that say scanf("#FF","%d") should fail but scanf("255","%d") should succeed, and things like scanf("#FF","#%x") simply do not work (sorry), but scanf("#FF","%x") is perfectly fine, apart from the fact that sprintf("%x",{#FF}) produces "FF" not "#FF". Also note that scanf can easily parse say "#DEADBEEF" (as %f) but cannot get a similar result from "DEADBEEF", much like the compiler and source code.

Failure is indicated by {}. Otherwise each element of the results has as many elements as there were format specifications in the format string, in the same order as specfied. A perfect unique and unambiguous result is indicated by length(res)=1.

If you are confident of success, and happy to take the first should more than one result set be returned, then
    {{x,y}} = scanf(line,"%d %d")

is the typical syntax. The double braces are needed to select the first of several possible result sets (not that I can imagine any case where "%d %d" would generate more than one result, but other formats might). Of course
    sequence res = scanf(line,"%d %d")
    if length(res)=0 (or !=1) then return/exit/error end if
    {{x,y}} = res

is the safer way, again needing the double braces.

The parse_date_string() function of timedate is a much better way to process date and time strings.

(programming note: %s is all the wildcard-matching we can handle; ? and * are just literals.)
Example 1:
function isNumber(string s)
    return scanf(s,"%f")!={}
end function
Example 2:
?scanf("file_name.gif","file_%s.%s")        -- {{"name","gif"}}
?scanf("file_test.name.gif","file_%s.%s")   -- {{"test","name.gif"},{"test.name","gif"}}
See Also: printf, sprintf, timedate, parse_date_string