C 中的 sprintf() 没有尾随空空格

发布于 2024-07-09 18:03:55 字数 72 浏览 6 评论 0原文

有没有办法使用 C sprintf() 函数而不在其输出末尾添加 '\0' 字符? 我需要在固定宽度字符串的中间写入格式化文本。

Is there a way to use the C sprintf() function without it adding a '\0' character at the end of its output? I need to write formatted text in the middle of a fixed width string.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

止于盛夏 2024-07-16 18:03:55

无法告诉 sprintf() 不写入尾随 null。 您可以做的是使用 sprintf() 写入临时字符串,然后使用 strncpy() 之类的方法仅复制所需的字节。

There is no way to tell sprintf() not to write a trailing null. What you can do is use sprintf() to write to a temporary string, and then something like strncpy() to copy only the bytes that you want.

厌味 2024-07-16 18:03:55

sprintf 返回写入的字符串的长度(不包括空终端),您可以使用它来知道空终端在哪里,并将空终端字符更改为其他字符(即空格)。 这比使用 strncpy 更有效。

 unsigned int len = sprintf(str, ...);
 str[len] = '<your char here>';

sprintf returns the length of the string written (not including the null terminal), you could use that to know where the null terminal was, and change the null terminal character to something else (ie a space). That would be more efficient than using strncpy.

 unsigned int len = sprintf(str, ...);
 str[len] = '<your char here>';
云仙小弟 2024-07-16 18:03:55

您无法使用 sprintf() 执行此操作,但可以使用 snprintf() 执行此操作,具体取决于您的平台。

您需要知道要替换多少个字符(但是当您将它们放入字符串中间时,您可能知道这一点)。

这是有效的,因为 snprintf() 的某些实现不保证写入终止字符 - 大概是为了与 stncpy() 等函数兼容。

char message[32] = "Hello 123, it's good to see you.";

snprintf(&message[6],3,"Joe");

此后,“123”被替换为“Joe”。

在 snprintf() 保证空终止的实现中,即使字符串被截断,这也不起作用。 因此,如果代码可移植性是一个问题,您应该避免这种情况。

大多数基于 Windows 的版本 snprintf() 都表现出这种行为。

但是,MacOS 和 BSD(也许还有 linux) ) 似乎总是以空终止。

You can't do this with sprintf(), but you may be able to with snprintf(), depending on your platform.

You need to know how many characters you are replacing (but as you're putting them into the middle of a string, you probably know that anyway).

This works because some implementations of snprintf() do NOT guarantee that a terminating character is written - presumably for compatibility with functions like stncpy().

char message[32] = "Hello 123, it's good to see you.";

snprintf(&message[6],3,"Joe");

After this, "123" is replaced with "Joe".

On implementations where snprintf() guarantees null termination even if the string is truncated, this won't work. So if code portability is a concern, you should avoid this.

Most Windows-based versions of snprintf() exhibit this behaviour.

But, MacOS and BSD (and maybe linux) appear to always null-terminate.

走过海棠暮 2024-07-16 18:03:55

您还可以使用固定宽度字符串作为格式字符串,如下所示:

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

You could also use your fixed width string as a format string like this:

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);

should yield

need 10 chars starting here: abcdefghij

渔村楼浪 2024-07-16 18:03:55

由于您要写入固定区域,因此可以这样做:

// 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;

Since you're writing to a fixed area, you can do it like this:

// 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;
汹涌人海 2024-07-16 18:03:55

这是内存受限设备的一个选项。 它以牺牲速度来换取使用更少的 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

Here's an option for memory constrained devices. It trades off speed for using less RAM. I sometimes have to do this to update the middle of a string that gets printed to a LCD.

The idea is that you first call snprintf with a zero sized buffer to determine which index will get clobbered by the null terminator.

You can run the below code here: 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;
}

Prints buf:123de

羁〃客ぐ 2024-07-16 18:03:55

实际上,如果您使用 snprintf,此示例将不会添加 null:

char name[9] = "QQ40dude";  
unsigned int i0To100 = 63;  
_snprintf(&name[2],2,"%d",i0To100);  
printf(name);// output will be: QQ63dude  

Actually this example will not add a null if you use snprintf:

char name[9] = "QQ40dude";  
unsigned int i0To100 = 63;  
_snprintf(&name[2],2,"%d",i0To100);  
printf(name);// output will be: QQ63dude  
潜移默化 2024-07-16 18:03:55

看这里:http://en.wikipedia.org/wiki/Printf

printf("%.*s", 3, "abcdef") 将打印“abc”

look here: http://en.wikipedia.org/wiki/Printf

printf("%.*s", 3, "abcdef") will result in "abc" being printed

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文