用于字符串连接的snprintf

Jer*_*ian 19 c string

我使用snprintf将字符串连接到char数组:

char buf[20] = "";
snprintf(buf, sizeof buf, "%s%s", buf, "foo");
printf("%s\n", buf);
snprintf(buf, sizeof buf, "%s%s", buf, " bar");
printf("%s\n", buf);
Run Code Online (Sandbox Code Playgroud)

问题是第二次连接buf而不是添加"bar",替换"foo"它.输出如下:

foo
bar
Run Code Online (Sandbox Code Playgroud)

第一个%s应该保留buf(在这种情况下保持"foo").第二个%s应该附加"bar"它.对?

我究竟做错了什么?

Ben*_*igt 29

你违反了restrict合同snprintf,声明没有其他参数可以与缓冲区重叠.

无论如何,将输入复制到自身都是浪费精力. snprintf返回格式化所需的字符数,因此可以利用此功能进行追加:

char buf[20] = "";
char *cur = buf, * const end = buf + sizeof buf;
cur += snprintf(cur, end-cur, "%s", "foo");
printf("%s\n", buf);
if (cur < end) {
    cur += snprintf(cur, end-cur, "%s", " bar");
}
printf("%s\n", buf);
Run Code Online (Sandbox Code Playgroud)


R..*_*R.. 5

虽然接受的答案是好的,但更好的(在我看来)答案是连接字符串是错误的。您应该在一次调用中构建整个输出snprintf。这就是使用格式化输出函数的全部意义,它比进行指针算术和多次调用更高效、更安全。例如:

snprintf(buf, sizeof buf, "%s%s%s", str_a, str_b, str_c);
Run Code Online (Sandbox Code Playgroud)

  • 这个想法与循环和条件完全不兼容。所以我认为它实际上并不是很有帮助,除非在非常有限的情况下。 (5认同)
  • @R ..:我很确定真正的代码不包含“foo”和“bar”。闻起来很像最小的复制品。 (2认同)