Hi I decided to try boost::format for more compact and typesafe formatting of text. However, I am running into some problems. Problem 1 ============== The following line throws boost:bad_format_string exception. std::cout << format("%|1| %|2$3|") % "Hello" % 3 << std::endl; However, this one works std::cout << format("%|1|") % "Hello" << std::endl; All I want to do is use notation for printing character streams i.e. %|1| instead of %1% Is this a bug or I am doing something wrong? Problem 2 ============= How can I print a float such that it appends 0 for remaining precision digits. For e.g. let us say I want to print 0.2 with 5 characters of overall length and till 3 digits of precision. Kind of output I am looking for is 0.200 One would expect that following command may work (as I am indicating left print, fill any remaining characters and till 3 digits of precision after decimal) std::cout << format("#%|1$-05.03|#") % 0.2 << std::endl; // however it prints #0.2 # This command prints something like std::cout << format("#%|1$05.03|#") % 0.2 << std::endl; // it prints #000.2# with C++ cout, I can print it like std::cout << '#' << std::left << std::setfill('0') << std::setw(5) << std::setprecision(3) << 0.2 << '#' << std::endl; so on similar lines I wrote following line. it works, but it seems ugly to use group only for this std::cout << format("#%|1$-05.3|#") % group(setfill('0'), 0.2) << std::endl; // prints #0.200# Does any one has any other suggestions? regards navneet
On Wed, 2004-04-14 at 21:11, Navneet Dalal wrote:
Hi
I decided to try boost::format for more compact and typesafe formatting of text. However, I am running into some problems.
Problem 1 ==============
The following line throws boost:bad_format_string exception. std::cout << format("%|1| %|2$3|") % "Hello" % 3 << std::endl;
the exception comes from parsing.hpp:465 ( " // dont mix positional with non-positionnal directives ") The problem is %|1| is a non-positional directive, and even though the code could assume it should take the first argument, it throws, due to this rule, rather than trying to be clever. What you want is : std::cout << format("%|1$| %|2$3|") % "Hello" % 3 << std::endl; (or |1$1| if you actually want to make sure the first argument's string is at least padded to be one char long)
However, this one works std::cout << format("%|1|") % "Hello" << std::endl;
All I want to do is use notation for printing character streams i.e. %|1| instead of %1%
hmm, not sure what you mean here, but the equivalent to %1% would be %|1$| (it merely wraps up posix printf notation, minus the final type-conversion letter)
Problem 2 =============
How can I print a float such that it appends 0 for remaining precision digits.
For e.g. let us say I want to print 0.2 with 5 characters of overall length and till 3 digits of precision. Kind of output I am looking for is 0.200
what range do you expect the numbers at runtime to lie in ? will they always be in [0.001, 10 [, for instance ? If you cant assume anything on the range of numbers, you must be prepared for all kind of numbers, e.g. 1.002e-34 as well as 1.002e34 For this 'scientific' notation of float numbers (the 'e' printf conversion, [-]d.ddde±dd), it is easy to specify and control the number of digits before/after the radix, whatever the number range. But it is often found ugly to the human eye. You're talking about number 0.2, and for such a number you usually dont want to show any exponent. Then the fixed notation (as many digits necessary, plus radix, plus a *fixed* number of digits) seems to be what you want, but you have to be aware that whatever parameters you choose, a fixed conversion formatting will be unadequate to many numbers, so you should resort to it only when you know the numbers have to lie in some range. example : format("%|05.3f|") % x; x=0.2 -> "0.200" x=1.02e-34 -> "0.00" x=1.02e+34 -> "102000 [..] 000.00" (34 digits plus radix and ".00". Also some float to integral artifact might kick in to mess up the digits beyond float precision) So, if you want to format numbers in a certain range, you might be able to do what you want with fixed conversion. ( "05.3f" is suitable for numbers in [0.001, 10[ . it will hide the value for numbers closer to 0, and will begin taking more space if >=10 ) The default conversion (which is 'g', as general) resorts to scientific when necessary, and use a modified fixed notation otherwise (I say modified, because the 'precision' parameter meaning is changed) cf http://www.opengroup.org/onlinepubs/7908799/xsh/fprintf.html : g,G : The double argument is converted in the style f or e (or in the style E in the case of a G conversion character), with the precision specifying the number of significant digits. If an explicit precision is 0, it is taken as 1. The style used depends on the value converted; style e (or E) will be used only if the exponent resulting from such a conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional portion of the result; a radix character appears only if it is followed by a digit. The fprintf() family of functions may make available character string representations for infinity and NaN.
std::cout << format("#%|1$-05.03|#") % 0.2 << std::endl; // however it prints #0.2 # .. with C++ cout, I can print it like std::cout << '#' << std::left << std::setfill('0') << std::setw(5) << std::setprecision(3) << 0.2 << '#' << std::endl;
you should not try to hack number conversion this way, on the string itself, it's a bit like resorting to : std::cout << "0.200"; :-p in that it assumes too much on the number being converted..
participants (2)
-
Navneet Dalal
-
Samuel Krempp