From: Hugo van der Sanden Date: Tue, 16 Jul 2002 16:01:12 +0000 (+0100) Subject: sprintf: fix and docs X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7b8dd722af72d0ca45650fb784c09763c0732e34;p=p5sagit%2Fp5-mst-13.2.git sprintf: fix and docs Message-Id: <200207161501.g6GF1CN00635@crypt.compulink.co.uk> p4raw-id: //depot/perl@17576 --- diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index c422575..d8d8978 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -4886,66 +4886,146 @@ permits these unnecessary but widely-supported conversions: %O a synonym for %lo %F a synonym for %f -Note that the number of exponent digits in the scientific notation by -C<%e>, C<%E>, C<%g> and C<%G> for numbers with the modulus of the +Note that the number of exponent digits in the scientific notation produced +by C<%e>, C<%E>, C<%g> and C<%G> for numbers with the modulus of the exponent less than 100 is system-dependent: it may be three or less (zero-padded as necessary). In other words, 1.23 times ten to the 99th may be either "1.23e99" or "1.23e099". -Perl permits the following universally-known flags between the C<%> -and the conversion letter: +Between the C<%> and the format letter, you may specify a number of +additional attributes controlling the interpretation of the format. +In order, these are: +=over 4 + +=item format parameter index + +An explicit format parameter index, such as C<2$>. By default sprintf +will format the next unused argument in the list, but this allows you +to take the arguments out of order. Eg: + + printf '%2$d %1$d', 12, 34; # prints "34 12" + printf '%3$d %d %1$d', 1, 2, 3; # prints "3 1 1" + +=item flags + +one or more of: space prefix positive number with a space + prefix positive number with a plus sign - left-justify within the field 0 use zeros, not spaces, to right-justify - # prefix non-zero octal with "0", non-zero hex with "0x" - number minimum field width - .number "precision": digits after decimal point for - floating-point, max length for string, minimum length - for integer - l interpret integer as C type "long" or "unsigned long" - h interpret integer as C type "short" or "unsigned short" - If no flags, interpret integer as C type "int" or "unsigned" - -Perl supports parameter ordering, in other words, fetching the -parameters in some explicitly specified "random" ordering as opposed -to the default implicit sequential ordering. The syntax is, instead -of the C<%> and C<*>, to use C<%>IC<$> and C<*>IC<$>, -where the I is the wanted index, from one upwards. For example: - - printf "%2\$d %1\$d\n", 12, 34; # will print "34 12\n" - printf "%*2\$d\n", 12, 3; # will print " 12\n" - -Note that using the reordering syntax does not interfere with the usual -implicit sequential fetching of the parameters: - - printf "%2\$d %d\n", 12, 34; # will print "34 12\n" - printf "%2\$d %d %d\n", 12, 34; # will print "34 12 34\n" - printf "%3\$d %d %d\n", 12, 34, 56; # will print "56 12 34\n" - printf "%2\$*3\$d %d\n", 12, 34, 3; # will print " 34 12\n" - printf "%*3\$2\$d %d\n", 12, 34, 3; # will print " 34 12\n" - -There are also two Perl-specific flags: - - V interpret integer as Perl's standard integer type - v interpret string as a vector of integers, output as - numbers separated either by dots, or by an arbitrary - string received from the argument list when the flag - is preceded by "*" - -Where a number would appear in the flags, an asterisk (C<*>) may be -used instead, in which case Perl uses the next item in the parameter -list as the given number (that is, as the field width or precision). + # prefix non-zero octal with "0", non-zero hex with "0x", + non-zero binary with "0b" + +For example: + + printf '<% d>', 12; # prints "< 12>" + printf '<%+d>', 12; # prints "<+12>" + printf '<%6s>', 12; # prints "< 12>" + printf '<%-6s>', 12; # prints "<12 >" + printf '<%06s>', 12; # prints "<000012>" + printf '<%#x>', 12; # prints "<0xc>" + +=item vector flag + +The vector flag C, optionally specifying the join string to use. +This flag tells perl to interpret the supplied string as a vector +of integers, one for each character in the string, separated by +a given string (a dot C<.> by default). This can be useful for +displaying ordinal values of characters in arbitrary strings: + + printf "version is v%vd\n", $^V; # Perl's version + +Put an asterisk C<*> before the C to override the string to +use to separate the numbers: + + printf "address is %*vX\n", ":", $addr; # IPv6 address + printf "bits are %0*v8b\n", " ", $bits; # random bitstring + +You can also explicitly specify the argument number to use for +the join string using eg C<*2$v>: + + printf '%*4$vX %*4$vX %*4$vX', @addr[1..3], ":"; # 3 IPv6 addresses + +=item (minimum) width + +Arguments are usually formatted to be only as wide as required to +display the given value. You can override the width by putting +a number here, or get the width from the next argument (with C<*>) +or from a specified argument (with eg C<2$>): + + printf '<%s>', "a"; # prints "" + printf '<%6s>', "a"; # prints "< a>" + printf '<%*s>', 6, "a"; # prints "< a>" + printf '<%*2$s>', "a", 6; # prints "< a>" + printf '<%2s>', "long"; # prints "" (does not truncate) + If a field width obtained through C<*> is negative, it has the same effect as the C<-> flag: left-justification. -The C flag is useful for displaying ordinal values of characters -in arbitrary strings: +=item precision, or maximum width + +You can specify a precision (for numeric converions) or a maximum +width (for string conversions) by specifying a C<.> followed by a number. +For floating point formats, this specifies the number of decimal places +to show (the default being 6), eg: + + # these examples are subject to system-specific variation + printf '<%f>', 1; # prints "<1.000000>" + printf '<%.1f>', 1; # prints "<1.0>" + printf '<%.0f>', 1; # prints "<1>" + printf '<%e>', 10; # prints "<1.000000e+01>" + printf '<%.1e>', 10; # prints "<1.0e+01>" + +For integer conversions, specifying a precision implies that the +output of the number itself should be zero-padded to this width: + + printf '<%.6x>', 1; # prints "<000001>" + printf '<%#.6x>', 1; # prints "<0x000001>" + printf '<%-10.6x>', 1; # prints "<000001 >" + +For string conversions, specifying a precision truncates the string +to fit in the specified width: + + printf '<%.5s>', "truncated"; # prints "" + printf '<%10.5s>', "truncated"; # prints "< trunc>" + +You can also get the precision from the next argument using C<.*>: - printf "version is v%vd\n", $^V; # Perl's version - printf "address is %*vX\n", ":", $addr; # IPv6 address - printf "bits are %*vb\n", " ", $bits; # random bitstring + printf '<%.6x>', 1; # prints "<000001>" + printf '<%.*x>', 6, 1; # prints "<000001>" + +You cannot currently get the precision from a specified number, +but it is intended that this will be possible in the future using +eg C<.*2$>: + + printf '<%.*2$x>', 1, 6; # INVALID, but in future will print "<000001>" + +=item size + +For numeric conversions, you can specify the size to interpret the +number as using C, C, C, C, C or C. For integer +conversions, numbers are usually assumed to be whatever the default +integer size is on your platform (usually 32 or 64 bits), but you +can override this to use instead one of the standard C types, as +supported by the compiler used to build Perl: + + l interpret integer as C type "long" or "unsigned long" + h interpret integer as C type "short" or "unsigned short" + q, L or ll interpret integer as C type "long long" or "unsigned long long" + (if your platform supports such a type, else it is an error) + +For floating point conversions, numbers are usually assumed to be +the default floating point size on your platform (double or long double), +but you can force 'long double' with C, C or C if your +platform supports them. + +The size specifier 'V' has no effect for Perl code, but it supported +for compatibility with XS code; it means 'use the standard size for +a Perl integer (or floating-point number)', which is already the +default for Perl code. + +=back If C is in effect, the character used for the decimal point in formatted real numbers is affected by the LC_NUMERIC locale. diff --git a/sv.c b/sv.c index 93e7bb5..b629558 100644 --- a/sv.c +++ b/sv.c @@ -7774,7 +7774,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV We allow format specification elements in this order: \d+\$ explicit format parameter index [-+ 0#]+ flags - \*?(\d+\$)?v vector with optional (optionally specified) arg + v|*(\d+\$)?v vector with optional (optionally specified) arg \d+|\*(\d+\$)? width using optional (optionally specified) arg \.(\d*|\*(\d+\$)?) precision using optional (optionally specified) arg [hlqLV] size @@ -7886,7 +7886,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV q++; if (*q == '*') { q++; - if (EXPECT_NUMBER(q, epix) && *q++ != '$') /* epix currently unused */ + if (EXPECT_NUMBER(q, epix) && *q++ != '$') + goto unknown; + /* XXX: todo, support specified precision parameter */ + if (epix) goto unknown; if (args) i = va_arg(*args, int);