连接像printf一样的字符串

时间:2015-11-16 13:47:44

标签: c concatenation coercion

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

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

是否有类似的方法来连接和执行正常字符串"如下所示:

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

5 个答案:

答案 0 :(得分:5)

您可以使用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);

答案 1 :(得分:5)

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

char msg[48];

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

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

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

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

答案 2 :(得分:4)

每个人都在建议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行)。请注意,您应该了解它的工作原理及其对嵌套调用的可能影响,更不用说在多线程环境中使用它时可能出现的问题。

答案 3 :(得分:2)

试试这个

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

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

为了更安全,你也可以使用snprintf

答案 4 :(得分:2)

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,您可以指定要写入字符串的最大字符数(这包括终结符char \0!"在第二个参数中。{{ 3}}