有没有办法使用 C sprintf() 函数而不在其输出末尾添加一个 '\0' 字符?我需要在固定宽度字符串的中间编写格式化文本。
8 回答
没有办法告诉sprintf()
不要写一个尾随空值。您可以做的是使用sprintf()
写入临时字符串,然后strncpy()
仅复制您想要的字节。
sprintf 返回写入的字符串的长度(不包括空终端),您可以使用它来了解空终端的位置,并将空终端字符更改为其他字符(即空格)。这将比使用 strncpy 更有效。
unsigned int len = sprintf(str, ...);
str[len] = '<your char here>';
您不能使用 sprintf() 执行此操作,但您可以使用 snprintf() 执行此操作,具体取决于您的平台。
您需要知道要替换多少个字符(但是当您将它们放入字符串的中间时,您可能无论如何都知道这一点)。
这是因为 snprintf() 的某些实现不保证写入终止字符 - 大概是为了与 stncpy() 等函数兼容。
char message[32] = "Hello 123, it's good to see you.";
snprintf(&message[6],3,"Joe");
此后,“123”被“乔”取代。
即使字符串被截断,在 snprintf() 保证空终止的实现上,这将不起作用。所以如果代码可移植性是一个问题,你应该避免这种情况。
大多数基于 Windows的 snprintf() 版本都表现出这种行为。
但是,MacOS和 BSD(也许还有 linux)似乎总是空终止。
您还可以使用固定宽度字符串作为格式字符串,如下所示:
char my_fixed_width_string_format[] = "need 10 chars starting here: %10s";
char my_fixed_width_string[40];
char string_to_print[] = "abcdefghijklmnop";
sprintf(my_fixed_width_string, my_fixed_width_string_format, string_to_print;
printf(my_fixed_width_string);
应该产生
从这里开始需要 10 个字符:abcdefghij
由于您正在写入固定区域,因此您可以这样做:
// pointer to fixed area we want to write to
char* s;
// number of bytes needed, not including the null
int r = snprintf(0, 0, <your va_args here>);
// char following the last char we will write - null goes here
char c = s[r + 1];
// do the formatted write
snprintf(s, r + 1, <your_va_args here>);
// replace what was overwritten
s[r + 1] = c;
实际上,如果您使用 snprintf,此示例不会添加 null:
char name[9] = "QQ40dude";
unsigned int i0To100 = 63;
_snprintf(&name[2],2,"%d",i0To100);
printf(name);// output will be: QQ63dude
这是内存受限设备的一个选项。它以速度换取使用更少的 RAM。我有时必须这样做来更新打印到 LCD 上的字符串的中间部分。
这个想法是您首先使用零大小的缓冲区调用 snprintf 以确定哪个索引将被空终止符破坏。
您可以在此处运行以下代码:https ://rextester.com/AMOOC49082
#include <stdio.h>
#include <string.h>
int main(void)
{
char buf[100] = { 'a', 'b', 'c', 'd', 'e' };
const size_t buf_size = sizeof(buf);
const int i = 123;
int result = snprintf(buf, 0, "%i", i);
if (result < 0)
{
printf("snprintf error: %i\n", result);
return -1;
}
int clobbered_index = result; //this index will get the null term written into it
if (result >= buf_size)
{
printf("buffer not large enough. required %i chars\n", result + 1);
return -1;
}
char temp_char = buf[clobbered_index];
result = snprintf(buf, buf_size, "%i", i); //add result error checking here to catch future mistakes
buf[clobbered_index] = temp_char;
printf("buf:%s\n", buf);
return 0;
}
印刷buf:123de
看这里:http ://en.wikipedia.org/wiki/Printf
printf("%.*s", 3, "abcdef") 将导致打印 "abc"