gpt4 book ai didi

c - 在 Solaris 中用字符串中的前导零填充有效,但在 RHEL 中无效

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:26:22 25 4
gpt4 key购买 nike

此程序在一个平台上打印前导 0 的字符串,但在另一个平台上不打印。

#include <stdio.h>
#include <string.h>

int main(void)
{
char test[20];
char a[4]="a12";
sprintf(test,"%019s\n",a);
printf("%s\n",test);
return 0;
}

输出:

Solaris : 0000000000000000a12
RHEL : a12 (left padding with spaces)

如何在两个平台上获得前导零?

最佳答案

您在两个系统上都调用了未定义的行为;你得到不同的结果是一个不足为奇的结果。

printf() 的 POSIX 规范说:

0
For d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversion specifiers, leading zeros (following any indication of sign or base) are used to pad to the field width rather than performing space padding, except when converting an infinity or NaN. If the '0' and '-' flags both appear, the '0' flag is ignored. For d, i, o, u, x, and X conversion specifiers, if a precision is specified, the '0' flag shall be ignored. [CX] ⌦ If the '0' and <apostrophe> flags both appear, the grouping characters are inserted before zero padding. For other conversions, the behavior is undefined. ⌫

(关于解析该语句的注意事项。“⌫”的出现表明“其他转换”注释仅适用于同时出现的 0'。但是,检查 C11 标准(ISO/IEC 9899:2011),它说:

0
For d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversions, leading zeros (following any indication of sign or base) are used to pad to the field width rather than performing space padding, except when converting an infinity or NaN. If the 0 and - flags both appear, the 0 flag is ignored. For d, i, o, u, x, and X conversions, if a precision is specified, the 0 flag is ignored. For other conversions, the behavior is undefined.

我认为结束标记“⌫”在 POSIX Material 中放错了位置。)

因此,要获得可靠的行为,您必须更具创造力。第一步是删除 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]

关于c - 在 Solaris 中用字符串中的前导零填充有效,但在 RHEL 中无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46902702/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com