Ignore '+' and space flags for unsigned printf conversions

C only applies the '+' and space flags to signed conversions, so
fmt::sprintf("%+u", 42) should give "42" like printf does, not "+42".
The same goes for %o, %x and %X.
This commit is contained in:
fhgffy 2026-10-08 23:56:57 +08:00
parent 10cda465ed
commit ed97d9a3a2
2 changed files with 17 additions and 0 deletions

View File

@ -545,6 +545,9 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
if (it == end) report_error("invalid format string");
char type = static_cast<char>(*it++);
if (is_integral_type(arg.type())) {
// The '+' and space flags only apply to signed conversions.
if (type == 'u' || type == 'o' || type == 'x' || type == 'X')
specs.set_sign(sign::none);
// Normalize type.
switch (type) {
case 'i':

View File

@ -169,6 +169,14 @@ TEST(printf_test, plus_flag) {
// '+' flag and space flag are both ignored for non-numeric types.
EXPECT_PRINTF("x", "%+ c", 'x');
EXPECT_PRINTF("x", "% +c", 'x');
// '+' flag is ignored for unsigned conversions.
EXPECT_PRINTF("42", "%+u", 42);
EXPECT_PRINTF("42", "%+o", 042);
EXPECT_PRINTF("2a", "%+x", 0x2a);
EXPECT_PRINTF("2A", "%+X", 0x2a);
EXPECT_PRINTF("0x002a", "%+#06x", 0x2a);
EXPECT_PRINTF("", "%+.0u", 0);
}
TEST(printf_test, minus_flag) {
@ -199,6 +207,12 @@ TEST(printf_test, space_flag) {
// ' ' flag is ignored for non-numeric types.
EXPECT_PRINTF("x", "% c", 'x');
// ' ' flag is ignored for unsigned conversions.
EXPECT_PRINTF("42", "% u", 42);
EXPECT_PRINTF("42", "% o", 042);
EXPECT_PRINTF("0002a", "% 05x", 0x2a);
EXPECT_PRINTF("2A", "% X", 0x2a);
}
TEST(printf_test, hash_flag) {