46

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

4

8 回答 8

45

没有办法告诉sprintf()不要写一个尾随空值。您可以做的是使用sprintf()写入临时字符串,然后strncpy()仅复制您想要的字节。

于 2008-12-10T18:33:32.483 回答
31

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

 unsigned int len = sprintf(str, ...);
 str[len] = '<your char here>';
于 2008-12-10T20:00:32.307 回答
6

您不能使用 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)似乎总是空终止。

于 2008-12-11T16:32:12.087 回答
2

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

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

于 2008-12-11T07:52:24.913 回答
0

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

// 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;
于 2012-07-03T23:01:47.733 回答
0

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

char name[9] = "QQ40dude";  
unsigned int i0To100 = 63;  
_snprintf(&name[2],2,"%d",i0To100);  
printf(name);// output will be: QQ63dude  
于 2015-02-21T18:26:33.240 回答
0

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

于 2019-12-27T21:56:23.127 回答
-2

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

printf("%.*s", 3, "abcdef") 将导致打印 "abc"

于 2010-10-04T13:38:54.013 回答