您在两个系统上都调用了未定义的行为;你得到不同的结果并不奇怪。
printf() 的 POSIX 规范说:
0
对于d,i,o,u,x,X,a,A,e,f,@9876543343@,f,@98765 987654336@ 和 G 转换说明符,前导零(在符号或基数的任何指示之后)用于填充字段宽度而不是执行空格填充,除非在转换无穷大或 NaN 时。如果“0”和“-”标志都出现,则“0”标志将被忽略。对于d、i、o、u、x 和X 转换说明符,如果指定了精度,则应忽略“0”标志。 [CX] ⌦ 如果 '0' 和 <apostrophe> 标志都出现,则在零填充之前插入分组字符。对于其他转换,行为未定义。 ⌫
(关于解析该语句的注意事项。“⌫”的出现表明“其他转换”注释仅适用于同时出现的 0 和 '。但是,检查 C11 标准(ISO/ IEC 9899:2011),它说:
0
对于d,i,o,u,x,X,a,A,e,E,F,E,F,E 987654365@ 和 G 转换,前导零
(在符号或基础的任何指示之后)用于填充字段宽度而不是
比执行空间填充,除非在转换无穷大或 NaN 时。如果
0 和 - 标志都出现,0 标志被忽略。对于d、i、o、u、x 和 X
转换,如果指定了精度,0 标志将被忽略。对于其他
转换,行为未定义。
我认为结束标记“⌫”在 POSIX 材料中放错了位置。)
因此,要获得可靠的行为,您必须更有创造力。第一步是从格式字符串中删除0。
您还需要增加缓冲区的大小;你写的超出了结尾。
可能是这样的:
#include <stdio.h>
#include <string.h>
int main(void)
{
char test[25];
char a[4] = "a12";
snprintf(test, sizeof(test), "%19s\n", a);
size_t leading_blanks = strspn(test, " ");
memset(test, '0', leading_blanks);
printf("%s", test);
return 0;
}
输出:
0000000000000000a12
如果您需要在一行中处理多个值,每个值都需要补零,有多种方法可以处理它。一种选择是这样的(通过所有相同大小的字段来简化用例):
#include <string.h>
#include <stdio.h>
int main(void)
{
char buffer[128];
char *data[] = { "a12", "syzygy.sv.example.com", "192.168.234.119", "Quasimodo" };
snprintf(buffer, sizeof(buffer), "%20.20s%20.20s%20.20s%20.20s",
data[0], data[1], data[2], data[3]);
for (int i = 0; i < 4; i++)
{
size_t leading_blanks = strspn(&buffer[20*i], " ");
memset(&buffer[20*i], '0', leading_blanks);
}
printf("%s\n", buffer);
return 0;
}
输出是:
00000000000000000a12syzygy.sv.example.co00000192.168.234.11900000000000Quasimodo
您可以小心地创建更精细的格式:
#include <string.h>
#include <stdio.h>
struct Field
{
int width;
char pad;
};
static struct Field fields[] =
{
{ .width = 12, .pad = '0', },
{ .width = 30, .pad = '@', },
{ .width = 15, .pad = '.', },
{ .width = 25, .pad = '-', },
};
enum { NUM_FIELDS = sizeof(fields) / sizeof(fields[0]) };
static char *data[][4] =
{
{ "a12", "syzygy.sv.example.com", "192.168.234.119", "Quasimodo" },
{ "zzx2341", "zulu.za.example.com", "192.168.23.19", "Beowulf" },
{ "reynard", "coffee.br.example.com", "192.168.5.9", "William the Conqueror" },
{ "peanut", "koala.au.example.com", "192.168.93.12", "Quasimodo" },
};
enum { NUM_ROWS = sizeof(data) / sizeof(data[0]) };
int main(void)
{
for (int i = 0; i < NUM_ROWS; i++)
{
char buffer[1024];
char *bufptr = buffer;
size_t buflen = sizeof(buffer);
for (int j = 0; j < NUM_FIELDS; j++)
{
int nbytes = snprintf(bufptr, buflen, "[%*.*s]", fields[j].width,
fields[j].width, data[i][j]);
if ((size_t)nbytes > buflen)
{
fprintf(stderr, "Overlength: %zu required\n",
sizeof(buffer) - buflen + nbytes + 1);
return 1;
}
size_t leading_blanks = strspn(bufptr + 1, " ");
memset(bufptr + 1, fields[j].pad, leading_blanks);
bufptr += nbytes;
buflen -= nbytes;
}
printf("%s\n", buffer);
}
return 0;
}
输出:
[000000000a12][@@@@@@@@@syzygy.sv.example.com][192.168.234.119][----------------Quasimodo]
[00000zzx2341][@@@@@@@@@@@zulu.za.example.com][..192.168.23.19][------------------Beowulf]
[00000reynard][@@@@@@@@@coffee.br.example.com][....192.168.5.9][----William the Conqueror]
[000000peanut][@@@@@@@@@@koala.au.example.com][..192.168.93.12][----------------Quasimodo]