Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

Strange behaviour when combining foreach and printf #6555

Closed p5pRT closed 20 years ago

p5pRT commented 20 years ago

Migrated from rt.perl.org#22599 (status was 'resolved')

Searchable as RT22599$

p5pRT commented 20 years ago

From stephane.zuckerman@etu.utc.fr

his is a bug report for perl from szuckerm@​etu.utc.fr\, generated with the help of perlbug 1.33 running under perl v5.6.1.


# Under a Windows 2000 platform\, I tried to solve some exercices from lama # book​: # Here is the result :

sub fmtPrint2 {   print "What is the width ?\n";   chop (my $width = \);   print "Please enter the strings to display :\n";   my @​strings = \;   foreach(@​strings) {   printf "%${width}s"\, $_;   } } &fmtPrint2;

# When launching the script\, this is what I get :

D​:\Programmation_Perl>perl -w learning_perl.pl What is the width ? -60 Please enter the strings to display : foo bar bar foo ^Z foo   bar   bar   foo



Flags​:   category=core   severity=low


Site configuration information for perl v5.6.1​:

Configured by ActiveState at Tue Feb 4 15​:34​:07 2003.

Summary of my perl5 (revision 5 version 6 subversion 1) configuration​:   Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x86-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   usethreads=undef use5005threads=undef useithreads=define usemultiplicity=define   useperlio=undef d_sfio=undef uselargefiles=undef usesocks=undef   use64bitint=undef use64bitall=undef uselongdouble=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -O1 -MD -Zi -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DPERL_MSVCRT_READFIX'\,   optimize='-O1 -MD -Zi -DNDEBUG'\,   cppflags='-DWIN32'   ccversion=''\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=10   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=4   alignbytes=8\, usemymalloc=n\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -libpath​:"D​:\Program Files\Perl\lib\CORE" -machine​:x86'   libpth="D​:\Program Files\Microsoft Visual Studio\VC98\mfc\lib" "D​:\Program Files\Microsoft Visual Studio\VC98\lib" "D​:\Program Files\Perl\lib\CORE"   libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib   perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=yes\, libperl=perl56.lib   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -libpath​:"D​:\Program Files\Perl\lib\CORE" -machine​:x86'

Locally applied patches​:   ACTIVEPERL_LOCAL_PATCHES_ENTRY


@​INC for perl v5.6.1​:   D​:/Program Files/Perl/lib   D​:/Program Files/Perl/site/lib   .


Environment for perl v5.6.1​:   HOME (unset)   LANG (unset)   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)   PATH=D​:\Program Files\Perl\bin\;D​:\Program Files\texmf\miktex\bin\;C​:\WINNT\system32;C​:\WINNT;C​:\WINNT\System32\Wbem;D​:\Program Files\SecureCRT;D​:\Program Files\NMapWin\\bin;C​:\Program Files\Fichiers communs\Adaptec Shared\System;D​:\Program Files\Microsoft Visual Studio\Common\Tools\WinNT;D​:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin;D​:\Program Files\Microsoft Visual Studio\Common\Tools;D​:\Program Files\Microsoft Visual Studio\VC98\bin   PERL_BADLANG (unset)   SHELL (unset)

-- "Je deteste les ordinateurs : ils font toujours ce que je dis\, jamais ce que je veux !"

p5pRT commented 20 years ago

From Robin.Barker@npl.co.uk

Thanks for the report.

The output is correct because each string in @​strings has "\n" at the end.

printf does not work well with embedded formatting characters\, in this case it has to print "foo\n" left justified in 60 character width. So it prints "foo\n" (4 characters) then prints the remaining 56 spaces - on a new line. You would have seen less deceptive results if the strings you input were different lengths.

If you replace   my @​strings = \; by
  chop(my @​strings = \);

and   printf "%${width}s"\, $_; by   printf "%${width}s\n"\, $_;

you should get the output you expect - try different length input to be sure.

Robin

P.S. It is often clearer to write​:   printf "%${width}s"\, $_; as   printf "%*s"\, $width\, $_;

See perldoc -f sprintf

-----Original Message----- From​: Stephane Zuckerman [mailto​:perlbug-followup@​perl.org] Sent​: 06 June 2003 09​:29 To​: perl5-porters@​perl.org Subject​: [perl #22599] Strange behaviour when combining foreach and printf

# New Ticket Created by Stephane Zuckerman # Please include the string​: [perl #22599] # in the subject line of all future correspondence about this issue. # \<URL​: http​://rt.perl.org/rt2/Ticket/Display.html?id=22599 >

his is a bug report for perl from szuckerm@​etu.utc.fr\, generated with the help of perlbug 1.33 running under perl v5.6.1.


# Under a Windows 2000 platform\, I tried to solve some exercices from lama # book​: # Here is the result :

sub fmtPrint2 {   print "What is the width ?\n";   chop (my $width = \);   print "Please enter the strings to display :\n";   my @​strings = \;   foreach(@​strings) {   printf "%${width}s"\, $_;   } } &fmtPrint2;

# When launching the script\, this is what I get :

D​:\Programmation_Perl>perl -w learning_perl.pl What is the width ? -60 Please enter the strings to display : foo bar bar foo ^Z foo   bar   bar   foo



Flags​:   category=core   severity=low


Site configuration information for perl v5.6.1​:

Configured by ActiveState at Tue Feb 4 15​:34​:07 2003.

Summary of my perl5 (revision 5 version 6 subversion 1) configuration​:   Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x86-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   usethreads=undef use5005threads=undef useithreads=define usemultiplicity=define   useperlio=undef d_sfio=undef uselargefiles=undef usesocks=undef   use64bitint=undef use64bitall=undef uselongdouble=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -O1 -MD -Zi -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DPERL_MSVCRT_READFIX'\,   optimize='-O1 -MD -Zi -DNDEBUG'\,   cppflags='-DWIN32'   ccversion=''\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=10   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=4   alignbytes=8\, usemymalloc=n\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -libpath​:"D​:\Program Files\Perl\lib\CORE" -machine​:x86'   libpth="D​:\Program Files\Microsoft Visual Studio\VC98\mfc\lib" "D​:\Program Files\Microsoft Visual Studio\VC98\lib" "D​:\Program Files\Perl\lib\CORE"   libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib   perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=yes\, libperl=perl56.lib   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -libpath​:"D​:\Program Files\Perl\lib\CORE" -machine​:x86'

Locally applied patches​:   ACTIVEPERL_LOCAL_PATCHES_ENTRY


@​INC for perl v5.6.1​:   D​:/Program Files/Perl/lib   D​:/Program Files/Perl/site/lib   .


Environment for perl v5.6.1​:   HOME (unset)   LANG (unset)   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)   PATH=D​:\Program Files\Perl\bin\;D​:\Program Files\texmf\miktex\bin\;C​:\WINNT\system32;C​:\WINNT;C​:\WINNT\System32\Wbe m;D​:\Program Files\SecureCRT;D​:\Program Files\NMapWin\\bin;C​:\Program Files\Fichiers communs\Adaptec Shared\System;D​:\Program Files\Microsoft Visual Studio\Common\Tools\WinNT;D​:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin;D​:\Program Files\Microsoft Visual Studio\Common\Tools;D​:\Program Files\Microsoft Visual Studio\VC98\bin   PERL_BADLANG (unset)   SHELL (unset)

-- "Je deteste les ordinateurs : ils font toujours ce que je dis\, jamais ce que je veux !"


This e-mail and any attachments may contain confidential and/or privileged material; it is for the intended addressee(s) only. If you are not a named addressee\, you must not use\, retain or disclose such information.

NPL Management Ltd cannot guarantee that the e-mail or any attachments are free from viruses.

NPL Management Ltd. Registered in England and Wales. No​: 2937881 Registered Office​: Teddington\, Middlesex\, United Kingdom TW11 0LW.


p5pRT commented 20 years ago

From stephane.zuckerman@etu.utc.fr

Dear Robin\,

Thank you for answering so fast.

... And sorry for giving an erroneous bug report :-)

P.S. It is often clearer to write​: printf "%${width}s"\, $_; as printf "%*s"\, $width\, $_;

See perldoc -f sprintf

I thought it would be less "C-like" if I avoided the '*' ... My mistake :-)

Thanks a lot !

-- "Je deteste les ordinateurs : ils font toujours ce que je dis\, jamais ce que je veux !"

p5pRT commented 20 years ago

@rspier - Status changed from 'new' to 'resolved'

p5pRT commented 20 years ago

From @rgs

Stephane Zuckerman (via RT) wrote​:

sub fmtPrint2 { print "What is the width ?\n"; chop (my $width = \); print "Please enter the strings to display :\n"; my @​strings = \; foreach(@​strings) { printf "%${width}s"\, $_; } } &fmtPrint2;

# When launching the script\, this is what I get :

D​:\Programmation_Perl>perl -w learning_perl.pl What is the width ? -60 Please enter the strings to display : foo bar bar foo ^Z foo bar bar foo

This is expected behavior. Remember that the strings you've entered have a trailing \n.

p5pRT commented 20 years ago

@rgs - Status changed from 'open' to 'resolved'

p5pRT commented 20 years ago

From Robin.Barker@npl.co.uk

The attached patch causes a warning to be issued if the string to be left-justified by s?printf contains a newline. I have put the warning in the existing printf class​: perhaps it should be in a new class.

Robin

-----Original Message----- From​: Robin Barker [mailto​:Robin.Barker@​npl.co.uk] Sent​: 06 June 2003 17​:16 To​: 'perl5-porters@​perl.org' Cc​: 'Stephane Zuckerman ' Subject​: RE​: [perl #22599] Strange behaviour when combining foreach and pr intf

Thanks for the report.

The output is correct because each string in @​strings has "\n" at the end.

printf does not work well with embedded formatting characters\, in this case it has to print "foo\n" left justified in 60 character width. So it prints "foo\n" (4 characters) then prints the remaining 56 spaces - on a new line. You would have seen less deceptive results if the strings you input were different lengths.

If you replace   my @​strings = \; by
  chop(my @​strings = \);

and   printf "%${width}s"\, $_; by   printf "%${width}s\n"\, $_;

you should get the output you expect - try different length input to be sure.

Robin

P.S. It is often clearer to write​:   printf "%${width}s"\, $_; as   printf "%*s"\, $width\, $_;

See perldoc -f sprintf

-----Original Message----- From​: Stephane Zuckerman [mailto​:perlbug-followup@​perl.org] Sent​: 06 June 2003 09​:29 To​: perl5-porters@​perl.org Subject​: [perl #22599] Strange behaviour when combining foreach and printf

# New Ticket Created by Stephane Zuckerman # Please include the string​: [perl #22599] # in the subject line of all future correspondence about this issue. # \<URL​: http​://rt.perl.org/rt2/Ticket/Display.html?id=22599 >

his is a bug report for perl from szuckerm@​etu.utc.fr\, generated with the help of perlbug 1.33 running under perl v5.6.1.


# Under a Windows 2000 platform\, I tried to solve some exercices from lama # book​: # Here is the result :

sub fmtPrint2 {   print "What is the width ?\n";   chop (my $width = \);   print "Please enter the strings to display :\n";   my @​strings = \;   foreach(@​strings) {   printf "%${width}s"\, $_;   } } &fmtPrint2;

# When launching the script\, this is what I get :

D​:\Programmation_Perl>perl -w learning_perl.pl What is the width ? -60 Please enter the strings to display : foo bar bar foo ^Z foo   bar   bar   foo



Flags​:   category=core   severity=low


Site configuration information for perl v5.6.1​:

Configured by ActiveState at Tue Feb 4 15​:34​:07 2003.

Summary of my perl5 (revision 5 version 6 subversion 1) configuration​:   Platform​:   osname=MSWin32\, osvers=4.0\, archname=MSWin32-x86-multi-thread   uname=''   config_args='undef'   hint=recommended\, useposix=true\, d_sigaction=undef   usethreads=undef use5005threads=undef useithreads=define usemultiplicity=define   useperlio=undef d_sfio=undef uselargefiles=undef usesocks=undef   use64bitint=undef use64bitall=undef uselongdouble=undef   Compiler​:   cc='cl'\, ccflags ='-nologo -O1 -MD -Zi -DNDEBUG -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DPERL_MSVCRT_READFIX'\,   optimize='-O1 -MD -Zi -DNDEBUG'\,   cppflags='-DWIN32'   ccversion=''\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=undef\, longlongsize=8\, d_longdbl=define\, longdblsize=10   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=4   alignbytes=8\, usemymalloc=n\, prototype=define   Linker and Libraries​:   ld='link'\, ldflags ='-nologo -nodefaultlib -debug -opt​:ref\,icf -libpath​:"D​:\Program Files\Perl\lib\CORE" -machine​:x86'   libpth="D​:\Program Files\Microsoft Visual Studio\VC98\mfc\lib" "D​:\Program Files\Microsoft Visual Studio\VC98\lib" "D​:\Program Files\Perl\lib\CORE"   libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib   perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib   libc=msvcrt.lib\, so=dll\, useshrplib=yes\, libperl=perl56.lib   Dynamic Linking​:   dlsrc=dl_win32.xs\, dlext=dll\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags='-dll -nologo -nodefaultlib -debug -opt​:ref\,icf -libpath​:"D​:\Program Files\Perl\lib\CORE" -machine​:x86'

Locally applied patches​:   ACTIVEPERL_LOCAL_PATCHES_ENTRY


@​INC for perl v5.6.1​:   D​:/Program Files/Perl/lib   D​:/Program Files/Perl/site/lib   .


Environment for perl v5.6.1​:   HOME (unset)   LANG (unset)   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)   PATH=D​:\Program Files\Perl\bin\;D​:\Program Files\texmf\miktex\bin\;C​:\WINNT\system32;C​:\WINNT;C​:\WINNT\System32\Wbe m;D​:\Program Files\SecureCRT;D​:\Program Files\NMapWin\\bin;C​:\Program Files\Fichiers communs\Adaptec Shared\System;D​:\Program Files\Microsoft Visual Studio\Common\Tools\WinNT;D​:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin;D​:\Program Files\Microsoft Visual Studio\Common\Tools;D​:\Program Files\Microsoft Visual Studio\VC98\bin   PERL_BADLANG (unset)   SHELL (unset)

-- "Je deteste les ordinateurs : ils font toujours ce que je dis\, jamais ce que je veux !"


This e-mail and any attachments may contain confidential and/or privileged material; it is for the intended addressee(s) only. If you are not a named addressee\, you must not use\, retain or disclose such information.

NPL Management Ltd cannot guarantee that the e-mail or any attachments are free from viruses.

NPL Management Ltd. Registered in England and Wales. No​: 2937881 Registered Office​: Teddington\, Middlesex\, United Kingdom TW11 0LW.



This e-mail and any attachments may contain confidential and/or privileged material; it is for the intended addressee(s) only. If you are not a named addressee\, you must not use\, retain or disclose such information.

NPL Management Ltd cannot guarantee that the e-mail or any attachments are free from viruses.

NPL Management Ltd. Registered in England and Wales. No​: 2937881 Registered Office​: Teddington\, Middlesex\, United Kingdom TW11 0LW.


p5pRT commented 20 years ago

From Robin.Barker@npl.co.uk

leftjust.gz

p5pRT commented 20 years ago

From @rgs

Robin Barker wrote​:

The attached patch causes a warning to be issued if the string to be left-justified by s?printf contains a newline. I have put the warning in the existing printf class​: perhaps it should be in a new class.

A few comments :

+ if( left && ckWARN(WARN_PRINTF) && strchr(eptr\, '\n') && + (PL_op->op_type == OP_PRTF || PL_op->op_type == OP_SPRINTF)) + Perl_warner(aTHX_ packWARN(WARN_PRINTF)\, + "Newline in left-justified string for %sprintf"\, + (PL_op->op_type == OP_PRTF) ? "" : "s");

I'd use OP_NAME here\, but that's a matter of taste.

+open F\, ">".($^O eq 'VMS'? 'NL​:' : '/dev/null') ;

This makes my portability bells ring. But apparently it works\, because I can see other places where it's used. For example t/test.pl.

Is this documented somewhere ? Should it be ? where ? How does it work ?

p5pRT commented 20 years ago

From Robin.Barker@npl.co.uk

Coding by cut-and-paste.

The first piece of code is copied from earlier in sv.c for the other WARN_PRINTF warning.

The C\ in lib/warnings/sv is copied from earlier in that file (from the earlier printf warnings). I know nothing about how portable it is.

Sorry

Robin

-----Original Message----- From​: Rafael Garcia-Suarez [mailto​:rgarciasuarez@​free.fr] Sent​: 11 June 2003 23​:23 To​: Robin Barker Cc​: perl5-porters@​perl.org Subject​: Re​: [PATCH] RE​: [perl #22599] Strange behaviour when combining foreac h and printf

Robin Barker wrote​:

The attached patch causes a warning to be issued if the string to be left-justified by s?printf contains a newline. I have put the warning in the existing printf class​: perhaps it should be in a new class.

A few comments :

+ if( left && ckWARN(WARN_PRINTF) && strchr(eptr\, '\n') && + (PL_op->op_type == OP_PRTF || PL_op->op_type == OP_SPRINTF))

+ Perl_warner(aTHX_ packWARN(WARN_PRINTF)\, + "Newline in left-justified string for %sprintf"\, + (PL_op->op_type == OP_PRTF) ? "" : "s");

I'd use OP_NAME here\, but that's a matter of taste.

+open F\, ">".($^O eq 'VMS'? 'NL​:' : '/dev/null') ;

This makes my portability bells ring. But apparently it works\, because I can see other places where it's used. For example t/test.pl.

Is this documented somewhere ? Should it be ? where ? How does it work ?


This e-mail and any attachments may contain confidential and/or privileged material; it is for the intended addressee(s) only. If you are not a named addressee\, you must not use\, retain or disclose such information.

NPL Management Ltd cannot guarantee that the e-mail or any attachments are free from viruses.

NPL Management Ltd. Registered in England and Wales. No​: 2937881 Registered Office​: Teddington\, Middlesex\, United Kingdom TW11 0LW.


p5pRT commented 20 years ago

From @rgs

Robin Barker wrote​:

The attached patch causes a warning to be issued if the string to be left-justified by s?printf contains a newline. I have put the warning in the existing printf class​: perhaps it should be in a new class.

Thanks\, applied as #19752.

p5pRT commented 20 years ago

@rgs - Status changed from 'open' to 'resolved'