note 55837 added to function.sprintf
| From: | webmaster at cafe-clope dot net | Date: | Mon, 15 Aug 2005 04:47:58 +0000 |
| Subject: | note 55837 added to function.sprintf | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-93660@lists.php.net to get a copy of this message | ||
trying to fix the multibyte non-compliance of sprintf, I came to that :
<?php
function mb_sprintf($format) {
$argv = func_get_args() ;
array_shift($argv) ;
return mb_vsprintf($format, $argv) ;
}
function mb_vsprintf($format, $argv) {
$newargv = array() ;
preg_match_all("
\%('.+|[0 ]|)([1-9][0-9]*|)sU", $format, $results,
PREG_SET_ORDER) ;
foreach($results as $result) {
list($string_format, $filler, $size) = $result ;
if(strlen($filler)>1)
$filler = substr($filler, 1) ;
while(!is_string($arg = array_shift($argv)))
$newargv[] = $arg ;
$pos = strpos($format, $string_format) ;
$format = substr($format, 0, $pos)
. ($size ? str_repeat($filler, $size-strlen($arg)) : '')
. str_replace('%', '%%', $arg)
. substr($format, $pos+strlen($string_format))
;
}
return vsprintf($format, $newargv) ;
}
?>
handle with care :
1. that function was designed mostly for utf-8. i guess it won't work with any static mb
encoding.
2. my configuration sets the mbstring.func_overload configuration directive to 7, so you may wish to
replace substr, strlen, etc. with mb_* equivalents.
3. since preg_* doesn't complies with mb strings, I used a '.+' in the regexp to
symbolize an escaped filler character. That means, %'xy5s pattern will match, unfortunately. It
is recomended to remove the '+', unless you are intending to use an mb char as filler.
4. the filler fills at left, and only at left.
5. I couldn't succeed with a preg_replace thing : the problem was to use the differents lengths
of the string arguements in the same replacement, string or callback. That's why the code is
much longuer than I expected.
6. The pattern wil not match any %1\$s thing... just was too complicated for me.
7. Although it has been tested, and works fine within the limits above, this is much more a draft
than a end-user function. I would enjoy any improvment.
The test code below shows possibilities, and explains the problem that occures with an mb string
argument in sprintf.
<?php
header("content-type:text/plain; charset=UTF-8") ;
$mb_string = "xéxàx" ;
echo sprintf("%010s", $mb_string), " [octet-size: ", str_sizeof($mb_string) ,
" ; count: ", strlen(sprintf("%010s", $mb_string)), " characters]\n" ;
echo mb_sprintf("%010s", $mb_string), " [octet-size: ", str_sizeof($mb_string) ,
" ; count: ", strlen(mb_sprintf("%010s", $mb_string)), "
characters]\n" ;
echo "\n" ;
echo mb_sprintf("%''10s\n%'010s\n%'û10s\n%10d\n%'x10s\n%010s\n%
10s\n%010s\n%'1s\n", "zero", "one", "two", 3,
"four", "îve", "%s%i%x", "éveñ", "eight") ;
?>
----
Manual Page -- http://www.php.net/manual/en/function.sprintf.php
Edit -- http://master.php.net/manage/user-notes.php?action=edit+55837
Delete: added to the manual -- http://master.php.net/manage/user-notes.php?action=delete+55837&report=yes&reason=added+to+the+manual
Delete: bad code -- http://master.php.net/manage/user-notes.php?action=delete+55837&report=yes&reason=bad+code
Delete: spam -- http://master.php.net/manage/user-notes.php?action=delete+55837&report=yes&reason=spam
Delete: useless -- http://master.php.net/manage/user-notes.php?action=delete+55837&report=yes&reason=useless
Delete: non-english -- http://master.php.net/manage/user-notes.php?action=delete+55837&report=yes&reason=non-english
Delete: other reasons -- http://master.php.net/manage/user-notes.php?action=delete+55837&report=yes
Reject -- http://master.php.net/manage/user-notes.php?action=reject+55837&report=yes
Search -- http://master.php.net/manage/user-notes.php