Yes, this is a problem with all versions printfthat I know of. I will briefly discuss this issue in this answer as well as this one .
For C, I don’t know a library that will do this for you, but if someone has it, it will be an ICU.
Perl Unicode:: GCString CPAN , Unicode . Unicode № 11: .
, 1 , 2 . , , , . columns, , .
Unicode . Unicode, , "" ( CJK) .

umenu, , .
Unicode:: LineBreak, Unicode::GCString . Unicode № 14: Unicode.
umenu, Perl v5.14:
use utf8;
use v5.14;
use strict;
use warnings;
use warnings qw(FATAL utf8);
use open qw(:std :utf8);
use charnames qw(:full :short);
use Unicode::Normalize;
use List::Util qw(max);
use Unicode::Collate::Locale;
use Unicode::GCString;
sub pad($$$);
sub colwidth(_);
sub entitle(_);
my %price = (
"γύρος" => 6.50,
"pears" => 2.00,
"linguiça" => 7.00,
"xoriço" => 3.00,
"hamburger" => 6.00,
"éclair" => 1.60,
"smørbrød" => 5.75,
"spätzle" => 5.50,
"包子" => 7.50,
"jamón serrano" => 4.45,
"pêches" => 2.25,
"シュークリーム" => 1.85,
"막걸리" => 4.00,
"寿司" => 9.99,
"おもち" => 2.65,
"crème brûlée" => 2.00,
"fideuà" => 4.20,
"pâté" => 4.15,
"お好み焼き" => 8.00,
);
my $width = 5 + max map { colwidth } keys %price;
my $coll = new Unicode::Collate::Locale locale => "ja";
for my $item ($coll->sort(keys %price)) {
print pad(entitle($item), $width, ".");
printf " €%.2f\n", $price{$item};
}
sub pad($$$) {
my($str, $width, $padchar) = @_;
return $str . ($padchar x ($width - colwidth($str)));
}
sub colwidth(_) {
my($str) = @_;
return Unicode::GCString->new($str)->columns;
}
sub entitle(_) {
my($str) = @_;
$str =~ s{ (?=\pL)(\S) (\S*) }
{ ucfirst($1) . lc($2) }xge;
return $str;
}
, , , - , , , , :
print pad(entitle($item), $width, ".");
, .
, , printf, , , .