Subject: Getting a replacement for sprintf ?!
Message-ID: <ef94acf8-bc29-f666-0b19-efdd505f10d9@virtuell-zuhause.de>
Hi Igorians,
since quite some time I'm starting to dislike the sprintf function.
Main reason is that I need to create a temporary string to be able to work with it and
also that it can not be used in arbitrary code as e.g. %s is limited to x number of characters.
Since quite some time I've been using fmtlib [1] in my C++ projects.
In short it allows you to write something like
fmt::format("The answer is {}.", 42);
and that returns a string with the contents ?The answer is 42.?.
Now there is no use in trying to get that exact syntax working in Igor Pro.
But one could get quite close. Here is a hacky hack example:
Function Examples()
print f("Hi {s_a}!", s_a = "HAL")
print f("Are you up to counting from 0 to {v_a}?", v_a = 10)
print f("Sure ;) Wanna see {w_a}?", w_a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
print f("In this case have fun with {s_a} and {v_a}s.", v_a=0, s_a="ones")
End
Function/S f(format, [v_a, s_a, w_a])
string format
variable v_a
string s_a
WAVE w_a
variable numDefaultParams, i
string str, buf, w_buf
if(ParamIsDefault(v_a))
numDefaultParams += 1
endif
if(ParamIsDefault(s_a))
numDefaultParams += 1
endif
if(ParamIsDefault(w_a))
numDefaultParams += 1
endif
str = format
if(numDefaultParams == 0)
// TODO check that str does not contain {}
return str
endif
if(!ParamIsDefault(v_a))
// TODO make %g configurable from {}
sprintf buf, "%g", v_a
str = ReplaceString("{v_a}", str, buf)
endif
if(!ParamIsDefault(s_a))
// TODO make configurable
str = ReplaceString("{s_a}", str, s_a)
endif
if(!ParamIsDefault(w_a))
// TODO make configurable and support dimensions larger than 1D
// and also other wave types
w_buf = "["
for(i = 0; i < DimSize(w_a, 0); i += 1)
sprintf buf, "%g", w_a[i]
w_buf += buf
if(i != DimSize(w_a, 0) - 1)
w_buf += ", "
endif
endfor
w_buf += "]"
str = ReplaceString("{w_a}", str, w_buf)
endif
return str
End
which gives
?examples()
Hi HAL!
Are you up to counting from 0 to 10?
Sure ;) Wanna see? -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In this case have fun with ones and 0s.
and this is already quite nice (I think) because it avoids both my main problems with sprintf.
My main problem at the moment is that it does not scale with the number of characters per type. If we would support up to 8 characters after the "_" we have already
?print/D 26^8*3
626481193728
combinations and thus a dump approach would need that many optional parameters. And to be usable we would need a way to iterate over them in a way with has sub-linear complexity.
And we would probably also hit a hard-coded limit of the number of optional parameters or maximum line length or ....
Thoughts?
Thomas
[1]: https://github.com/fmtlib/fmt