如何将printf存储到变量中?

Fra*_*ank 17 c string string-formatting

我想使用类似于C中printf所做的事情来存储格式化的字符串.

char *tmp = (char *)sqlite3_column_text(selectstmt, 2);
const char *sqlAnswers = printf("select key from answer WHERE key = %s LIMIT 5;", tmp);
Run Code Online (Sandbox Code Playgroud)

后者显然是一个错误.

Mic*_*and 36

您可以使用 sprintf,但不是单独(安全).在一个理智的系统上,使用snprintf两次,一次找出要使用的大小,第二次实际使用它.这取决于snprintf返回房间用完时所需的字符数.Linux,BSD和C99兼容系统可以做到这一点; Windows通常不会.在后一种情况下,您需要分配一个初始缓冲区并在snprintf失败时分配一个更大的缓冲区(在循环中直到snprintf成功).但在C99上,以下内容将起作用:

char *buf;
size_t sz;
sz = snprintf(NULL, 0, "select key from answer WHERE key = %s LIMIT 5;", tmp);
buf = (char *)malloc(sz + 1); /* make sure you check for != NULL in real code */
snprintf(buf, sz+1, "select key from answer WHERE key = %s LIMIT 5;", tmp);
Run Code Online (Sandbox Code Playgroud)

但是,对于构建SQL,使用预准备语句要好得多.它们避免了SQL注入漏洞(并且经常需要sprintf).使用它们,您将准备语句"select key from key where??limit 5;",然后使用参数执行它tmp.SQL引擎放入字符串并删除了确保首先正确转义的需要.


Car*_*rum 9

你想要的sprintf().

char *sqlAnswers = malloc(SIZE_TO_HOLD_FINAL_STRING);
sprintf(sqlAnswers, "select key from answer WHERE key = %s LIMIT 5;", tmp);
Run Code Online (Sandbox Code Playgroud)

  • 始终使用`snprintf()`来保证安全. (16认同)

Sco*_*les 8

如果你正在使用gnu或BSD libc,你可以使用它asprintf,它会自动分配一个正确大小的缓冲区.

#define _GNU_SOURCE
#include <stdio.h>
// ...
char *sqlAnswers = NULL;
int length = asprintf(&sqlAnswers,"select key from answer WHERE key = %s LIMIT 5;", tmp);
free(sqlAnswers);
Run Code Online (Sandbox Code Playgroud)

  • `asprintf`是一个方便的快捷方式`sprintf(malloc(snprintf(...)))技巧 - 我投票使用它并提供一个回退`asprintf`定义,如果你不得不处理一个悲伤,过时平台缺乏它. (5认同)