printf bad ?

John Macdonald john-Z7w/En0MP3xWk0Htik3J/w at public.gmane.org
Sat Mar 19 02:35:13 UTC 2005


On Sat, Mar 19, 2005 at 12:57:39AM +0200, Peter wrote:
> 
> On Fri, 18 Mar 2005, Henry Spencer wrote:
> 
> >On Fri, 18 Mar 2005, Peter wrote:
> >>printf "%05d" 08
> >>it says 'invalid number' for any number of 0's before the 8. Why does it
> >>think it's octal ?!
> >
> >Because the syntax of the arguments (after the format string) to the
> >printf command is defined -- in the POSIX standard -- to be the same as
> >that of C constants, with some minor extensions, and in C, a leading 0
> >means an octal number.  (The fact that the FSF's documentation for the
> >printf command fails to discuss this is a documentation bug.)
> 
> Point taken.
> 
> >>printf "%05d" 10#08
> >>-bash: printf: 10#08: invalid number
> >>
> >>(according to the bash manual that notation should force decimal - it
> >>does not - not in quotes and not in ticks and not with a
> >>backslash-escaped '#').
> >
> >That notation is for the $(( )) construct, the shell's built-in expression
> >evaluation; it doesn't apply everywhere.  If you try this:
> >
> >	printf "%05d" $((10#08))
> >
> >you'll find that it works.
> 
> Yes it does. The explanation for the b#n syntax is in the 'Arithmetic 
> Evaluation' section of the bash manpage but I failed to realize it 
> applies only in that context (I would expect anything being treated as a 
> number, and not escaped, to be subjected to this expansion - but there 
> may be cases where this may not be good).

As far as bash is concerned, the argument to printf is just
a bunch of characters, not a string.  Imagine a program
addinventory that takes an incoming shipment and adds it to
the amount of inventory on hand - with pairs of arguments that
are part-key and quantity-received.

addinventory x3y2 24
addinventory 0z99 144
addinventory 0x33 75

You wouldn't want bash to change the part key on the last
command to 51 because bash decided to treat it as a number?

> >
> >That is an interesting notion, but it is *not* the specification for
> >strtoul().  You don't have to guess how these things work; it's
> >documented.
> 
> Yes, but it's painful imho. Is there a well-known workaround to make it 
> work with 'automatic' base recognition as I suggested ? One way would be 
> to strip leading 0's if they are followed by a character that may be a 
> digit in any of the bases strtoul accepts. e.g. something like:
> 
> 	// chars that do not introduce a 0%c... base escape and are not octal
> 	#define STRTOUL_CHARS \
> 		"089abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWYZ"
> 	char *my_strtoul(char *a, char **z, int b)
> 	{
> 	    if(!b)
> 	        while( *a && *(a+1) && (*a=='0') &&
> 	            (!strchr(STRTOUL_CHARS,*(a+1))) )
> 	                ++a;
>  	    return(strtoul(a,z,b));
> 	}
> 
> This would make 008 a decimal number and 00a a number in base 11. If 
> someone needs octal he shall call my_strtoul with argument 3 == 8.
> 
> There are other ways to write this (and it may be incorrect - not 
> tested!). The code above will probably force octal numbers to be read as 
> something else (decimal probably) so it cannot coexist with default 
> strtoul but it fixes my problem (I think).

Why would 008 be decimal and not base 9?  Is 0101 binary
or octal?

If you guess the base from which digits are used, there are
lots of numbers in that base that can't be written because
they happen to only use small digits.

-- 
--
The Toronto Linux Users Group.      Meetings: http://tlug.ss.org
TLUG requests: Linux topics, No HTML, wrap text below 80 columns
How to UNSUBSCRIBE: http://tlug.ss.org/subscribe.shtml





More information about the Legacy mailing list