像 printf 一样连接一个字符串

Concatenate a string like in printf

printf 是一个漂亮的函数,因为它可以帮助您以非常干净的方式格式化字符串。

printf("Player %s has lost %d hitpoints", victim.name, damage);

是否有类似的方法在 "normal string" 中连接和执行强制转换,如下所示:

uint8_t myString = ("Player %s has lost %d hitpoints", victim.name, damage); //SOMETHING LIKE THIS

您可以使用 sprintf()。像这样

char* myString = malloc(50);

sprintf(myString, "Player %s has lost %d hitpoints", victim.name, damage);

如你所料,它代表string printf


请注意 sprintf() 需要 char*,而不是 uint8_t


当然您也可以使用 snprintf()。额外的好处是您可以指定要复制到字符串中的字符数。这样可以防止缓冲区溢出。

char* myString = malloc(50);

snprintf(myString, 50, "Player %s has lost %d hitpoints", victim.name, damage);

这样试试

   char str[MAX_LEN];
   sprintf(str,"Player %s has lost %d hitpoints", victim.name, damage);

但我不确定将 uint8_t* 传递给 sprintf 而不是 char * 是否安全。 (这可能违反约束,有关类似情况的更多详细信息,请参阅 here)。

确实为了更安全,您也可以使用 snprintf

printf("Player %s has lost %d hitpoints", victim.name, damage);

如果您想将结果保存在字符串中而不是打印它,可以使用同一系列中的另一个函数,称为 sprintf。在你的情况下,像这样使用它:

sprintf(myString,"Player %s has lost %d hitpoints", victim.name, damage);

Further info on sprintf

正如 user694733 所指出的,通常使用 snprintf 而不是 sprintf 更安全。两者之间的区别在于,对于 snprintf,您可以在第二个参数中指定要写入字符串的最大字符数(这包括终止符字符 [=16=]!")。More info on snprintf

每个人都在建议 sprintf,但我认为始终使用 snprintf 会更好。函数原型如下:

int snprintf ( char * s, size_t n, const char * format, ... );

第一个参数是您的字符串缓冲区,第二个参数是它的最大容量,后跟格式说明符字符串和参数。用法示例:

char str[STR_LEN];
snprintf(str, sizeof(str), "Player %s has lost %d hitpoints", victim.name, damage);

请注意,虽然这永远不会做任何非法的事情(使用 sprintf 你可能会产生未定义的行为),但如果你的缓冲区不够长,字符串将被截断,这可能会导致一些令人惊讶的输出。最好检查 snprintf 的结果以查看实际写入了多少个字符(感谢 chux 指出这一点)。

如果您有兴趣编写您问题中的代码,其中字符串从格式化函数 返回 给您,您可能会发现 Carmack 的 va 来自他有趣的 idTech3 引擎:https://github.com/id-Software/Quake-III-Arena/blob/master/code/splines/q_shared.cpp (第 700 行)。请注意,您应该了解它的工作原理及其对嵌套调用的可能影响,更不用说在多线程环境中使用它时可能出现的问题了。

C99 的 snprintf 打印到一个字符串并保证不会溢出缓冲区:

char msg[48];

snprintf(msg, sizeof(msg),
    "Player %s has lost %d hitpoints", victim.name, damage);

snprintf returns 如果字符串足够大,可以写入的字符数。因此,如果返回值等于或大于缓冲区大小,则字符串被截断。

传递零缓冲区大小和空指针是合法的,这样您就可以通过先进行探测调用来进行自己的分配:

char *msg;
int n;

n = snprintf(NULL, 0,
    "Player %s has lost %d hitpoints", victim.name, damage);

msg = malloc(n + 1);
n = snprintf(msg, n + 1,
    "Player %s has lost %d hitpoints", victim.name, damage);

// do stuff with msg

free(msg);

在 GNU 编译器上,非标准函数 asprintf 将为您完成:

char *msg = asprintf("Player %s has lost %d hitpoints",
    victim.name, damage);

// do stuff with msg

free(msg);