Miq19 has asked for the wisdom of the Perl Monks concerning the following question:

I am dissecting a large data file and at some place want to print out some data. Snippet is
my $last_k = 'NIL'; my $last_n = 'NIL'; foreach my $c (sort @chords) { (my $k, my $n) = split(/;/, $c); if ($last_k eq $k) { if ($last_n ne $n) { my $out = sprintf("Two names: '%-16s', '%-16s' for ", $last_n, $ +n); print $out . " " . &notenames($k) . "\n"; $duplicates++; } } ($last_k, $last_n) = ($k, $n); } print "$duplicates multiple chord names\n";
But the output is ignoring the minimum string widths in the printf() statement
... lines deleted ... Two names: 'E6/11/C#', 'E6/11/Db' for C#/Db4, E4, G#/Ab4, A4, Two names: 'E13/C#', 'E13/Db' for C#/Db4, E4, G#/Ab4, D5, Two names: 'E6/9/C#', 'E6/9/Db' for C#/Db4, E4, G#/Ab4, F#/Gb5 +, Two names: 'C#maj7(b5)', 'Dbmaj7(b5)' for C#/Db4, F4, G4, C5, Two names: 'C#(b5)', 'Db(b5)' for C#/Db4, F4, G4, Two names: 'Fm6#5/C#', 'Fm6#5/Db' for C#/Db4, F4, G#/Ab4, D5, Two names: 'Faug6', 'Faug6/C#' for C#/Db4, F4, A4, D5, Two names: 'A#aug6/D', 'Bbaug6/D' for D4, F#/Gb4, G4, A#/Bb4, Two names: 'F#6/11/D#', 'F#6/11/Eb' for D#/Eb4, F#/Gb4, A#/Bb4 +, B4, Two names: 'F#6/11/Eb', 'Gb6/11/Eb' for D#/Eb4, F#/Gb4, A#/Bb4 +, B4, Two names: 'F#13/D#', 'F#13/Eb' for D#/Eb4, F#/Gb4, A#/Bb4, E5 +, Two names: 'F#maj13/Eb', 'Gbmaj13/Eb' for D#/Eb4, F#/Gb4, A#/B +b4, F5, 372 multiple chord names
For the life of me I cannot see my fault...

Replies are listed 'Best First'.
Re: Minimum width in printf() ignored?
by hippo (Archbishop) on Sep 01, 2024 at 11:14 UTC

    I am not able to reproduce your findings.

    use strict; use warnings; my $out = sprintf ("Two names: '%-16s', '%-16s' for ", 'E6/11/C#', 'E6 +/11/Db'); print $out . "\n";

    I would not usually write it this way but I have preserved your syntax just to show the similarity. This runs and produces the following output:

    Two names: 'E6/11/C# ', 'E6/11/Db ' for

    That is what I expect. Perhaps you could also provide an SSCCE?


    🦛

      Thanks for your support. I tried
      perl -e '$a = "foobar"; printf("#%16s#\n", $a);'
      and got
      # foobar#
      as was to be expected - that was the reason I posted my question here. Even using static strings as you did in your example are working:
      Two names: 'foo ', 'bar ' for D#/Eb4, +F#/Gb4, A#/Bb4, F5,
      It must be something with the two variables, but I have no clue...
Re: Minimum width in printf() ignored?
by Anonymous Monk on Sep 01, 2024 at 15:47 UTC

    Are you sure the code you posted is exactly the same as the code you are running? And that your script is actually executing the sprintf you exhibited?

    My attempt at a SSCE is

    my $last_n = 'E6/11/C#';
    my $n      = 'E6/11/Db';
    sub notenames { return 'unknown' }
    print "Perl $^V\n";
    
          my $out = sprintf("Two names: '%-16s', '%-16s' for ", $last_n, $n);
          print $out . "        " . &notenames($k) . "\n";
    

    with the indented lines cut-and-pasted from your post. I have run this under Perls 5.40.0 and 5.10.1 and gotten

    Perl v5.40.0
    Two names: 'E6/11/C#        ', 'E6/11/Db        ' for         unknown
    

    and

    Perl v5.10.1
    Two names: 'E6/11/C#        ', 'E6/11/Db        ' for         unknown
    

    respectively.

      Found it! The file is binary, so there are binary zero bytes behind the texts when I extract these. I did not think about that and used
      (@c) = $block =~ /(\d{14})(\d\d)(.*)/;
      to extract the contents. Thus the zero bytes were kept as part of $c3. Instead I should have used
      (@c) = $block =~ /(\d{14})(\d\d)([ -z]*)/;
      This now yields
      Two names: 'F#maj13/Eb ', 'Gbmaj13/Eb ' for D#/Eb4, +F#/Gb4, A#/Bb4, F5,
      as I intended it. Thank any way for your help, it pushed me in the right direction!

        Ah-hah! You figured out what we were assuming, that was not in fact true. Good hunting!