0

I have the weirdest behavior in my perl I just don't seem to figure out. I am parsing a text file, creating a binary sting along the way:

$TDI = $a_stat . "$TDI"; #$a_stat = 0/1
if ( $b_stat ne "X" ) { $TDO = $b_stat . "$TDO" } #$b_stat is 0/1

now, i want to print it formatted, according to the size:

$inputSize = length($TDI);  
$hexSize = sprintf("%.0f", ($inputSize/4)+0.4);  # rounding up
printf ("$inputSize TDI (%0${hexSize}X) TDO (%0${hexSize}X)\n", bin2dec $TDI, bin2dec $TDO);  

This works out fine for 32 bit, but when I change the input size (specifically to input 26, hex 7) it prints out zeros before the hex value. I added a little debug line printf "$inputSize, $hexSize, (%0${hexSize}X)\n", oct($TDI) and got the following (quite amazing) results:

...  
24, 6, (0000AA)
25, 7, (00000000000000000000000000AA) <- 22 unneeded zeros  
26, 7, (00000000000000000000000000AA) <- 22 unneeded zeros  
27, 7, (00000000000000000000000000AA) <- 22 unneeded zeros  
28, 7, (00000000000000000000000000AA) <- 22 unneeded zeros  
29, 8, (000000AA)  
...
(now handling another string)  
25, 7, (0000000000000000000000000000000000000000000000000000000000000008) <- 56 unneeded zeros  
26, 7, (0000000000000000000000000000000000000000000000000000000000000008) <- 56 unneeded zeros  
27, 7, (0000000000000000000000000000000000000000000000000000000000000008) <- 56 unneeded zeros  
28, 7, (0000000000000000000000000000000000000000000000000000000000000008) <- 56 unneeded zeros  
29, 8, (00000008)
...  

At the next loop it gets to 121 zeros and also add 30 zeros to the 5-8 range.

I checked the bin2dec results and they are fine.

Can anyone figure out why I get this anomaly? If possible, please try to refrain from CPAN based suggestions as I'm using perl on a machine disconnected from the net with limited access to CPANs (at work).
EDIT
if someone can suggest a better way of finding the size of the hexa number representing my TDO\ TDI binary strings and\ or can come up with a better idea of how to have agile zeros padding than %0{$hexSize} I'll be happy to hear, specially since it might nullify the problem. Even though I like my code, Its not a catholic marriage...
Thanks for all you helpers and editors.

user2141046
  • 862
  • 2
  • 7
  • 21
  • 1
    so, to boil it down to a simple case, `printf("%025X\n", $somenumber)` doesn't produce the output you expect? What is $somenumber, what output does it produce, and what output did you expect? – ysth Nov 10 '13 at 10:07
  • no, `printf("%07X\n", $somenumber)` is where the problem exists. instead of output of >1234567 it outputs >0000000000000000000000001234567 – user2141046 Nov 10 '13 at 10:11
  • cannot reproduce, it just gives 7 hex digits in that case. Your `$hexSize` calculation looks extremely weird, and suggests `$TDI` is in base 4. WTF? Why don't you calculate the size after converting it to hex? → `my $num = bin2dec ...; my $size = length sprintf "%X", $num; printf "... %0*X\n", $size, $num` – amon Nov 10 '13 at 10:21
  • @user2141046: but what is $somenumber in that case? – ysth Nov 10 '13 at 10:24
  • @amon: your solution doesn't pad with zeros, so i can't use it. btw, i based my rounding function on one of the answers here http://stackoverflow.com/questions/178539/how-do-you-round-a-floating-point-number-in-perl – user2141046 Nov 10 '13 at 10:34

1 Answers1

0

problem solved.

The was problem caused from a rogue $ in the printf:

# bug                                            v
printf ("$inputSize TDI (%0${hexSize}X) TDO (%0${$hexSize}X)\n", bin2dec $TDI, bin2dec $TDO); 
printf ("$inputSize TDI (%0${hexSize}X) TDO (%0${hexSize}X)\n", bin2dec $TDI, bin2dec $TDO); 
# works                                          ^
user2141046
  • 862
  • 2
  • 7
  • 21
  • If that caused an error, please start to `use strict; use warnings` ASAP! That would have caught the error at runtime. Consider also specifying the width as a normal argument instead of interpolating, using the `*` placeholder: `printf "... %0*X", $hexSize, bin2dec $TDI`. – amon Nov 10 '13 at 11:06
  • @amon yes, i know, but since i learned perl from others' scripts (old scripts), i just don't have the structure of using "my" and so on and so forth needed for strict and warning. the %0*X you suggested is a possibility, though i don't really understand the syntax - does the same syntax can be used in other printf\ sprintf as well? – user2141046 Nov 10 '13 at 11:44
  • The `*` can be used as a placeholder for the min-width argument of most printf patterns. It is then taken from the argument list. It is documented in [`perldoc -f sprintf`](http://perldoc.perl.org/functions/sprintf.html#(minimum)-width). Re: strict – I don't `use strict` for quick oneliners that I'll never use again. But for anything else, this is one of the differences between a cobbled-together script full of potential bugs from the 90s, and a modern, reliable, maintainable program. – amon Nov 10 '13 at 12:01
  • @MichaelT how did you do that reverse caret (^) sign? – user2141046 Nov 10 '13 at 19:01
  • It's just the ASCII letter `v` (vee, as in _v_ery simple). – amon Nov 10 '13 at 19:18