关于string:sprintf(),在C语言中不尾随空格

sprintf() without trailing null space in C

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


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


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

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

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

您需要知道要替换多少个字符(但是将它们放在字符串的中间时,您可能仍然知道)。

之所以可行,是因为snprintf()的某些实现不保证写入终止字符-大概是为了与stncpy()之类的功能兼容。

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

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

此后,将" 123 "替换为" Joe "。

在snprintf()保证即使字符串被截断后仍为空终止的实现上,这将行不通。因此,如果需要考虑代码的可移植性,则应避免这种情况。

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

但是,MacOS和BSD(也许是Linux)总是以null结尾。


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

1
2
3
4
5
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);

应屈服

need 10 chars starting here: abcdefghij


这是内存受限设备的选项。为了减少内存消耗,需要权衡速度。有时我必须这样做以更新打印到LCD的字符串的中间。

这个想法是,您首先使用大小为零的缓冲区调用snprintf,以确定哪个索引将被空终止符破坏。

您可以在此处运行以下代码:https://rextester.com/AMOOC49082

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#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\
"
, 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\
"
, 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\
"
, buf);

  return 0;
}

打印buf:123de


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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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;


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

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