我想用类似于C如何将printf存储到变量中?
确实char *tmp = (char *)sqlite3_column_text(selectstmt, 2);
const char *sqlAnswers = printf("select key from answer WHERE key = %s LIMIT 5;", tmp);
什么的printf后者是一个错误显然某物存储的格式化字符串。
我想用类似于C如何将printf存储到变量中?
确实char *tmp = (char *)sqlite3_column_text(selectstmt, 2);
const char *sqlAnswers = printf("select key from answer WHERE key = %s LIMIT 5;", tmp);
什么的printf后者是一个错误显然某物存储的格式化字符串。
您可以使用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);
然而,为构建SQL,它远远更好地使用prepared statements。他们避免了SQL注入漏洞(并且经常需要sprintf
)。有了它们,您就可以准备好“回答where key =?limit 5;”中的选择键,然后使用参数tmp
执行它。 SQL引擎放入字符串,并删除确保首先正确转义的需求。
你想要sprintf()
。
char *sqlAnswers = malloc(SIZE_TO_HOLD_FINAL_STRING);
sprintf(sqlAnswers, "select key from answer WHERE key = %s LIMIT 5;", tmp);
为安全起见,请始终使用snprintf()。 – 2009-11-17 00:10:45
我可以同意这一点; +1。 – 2009-11-17 01:36:02
如果您使用的是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);
'asprintf'对于'sprintf的方便快捷(的malloc(的snprintf(...)))'绝招 - 我投用它提供了一个备用'asprintf'定义,如果你需要处理一个缺乏它的可悲的,过时的平台。 – ephemient 2009-11-17 15:52:27
在windows上,你可以使用sprintf_s,它增加了像Michael E所说的缓冲区溢出保护。
http://msdn.microsoft.com/en-us/library/ce3zzk1k(VS.80).aspx
看来如果缓冲区太小,'sprintf_s'不会返回所需的字节数; GNU和BSD'snprintf'都可以。这是我所依赖的关键行为。 – 2009-11-17 04:20:04
我实际使用sqlite3_bind_text输入我的通配符,而不是通过sprintf的产生:
const char *sql1 = "select id, repA, key from iphone_reponse WHERE question_id = ?;";
sqlite3_stmt *selectstmt1;
if(sqlite3_prepare_v2(database, sql1, -1, &selectstmt1, NULL) == SQLITE_OK) {
sqlite3_bind_text(selectstmt1, 1, [questionObj.key UTF8String], -1, SQLITE_TRANSIENT);
的迈克尔·埃克斯特兰德代码是好的,但你将需要复制并粘贴各种倍。我用这个代码在一个函数
char *storePrintf (const char *fmt, ...)
{
va_list arg;
va_start(arg, fmt);
size_t sz = snprintf(NULL, 0, fmt, arg);
char *buf = (char *)malloc(sz + 1);
vsprintf(buf, fmt, arg);
va_end (arg);
return buf;
}
是否有问题,缓冲区溢出?到现在为止我没有问题。
编辑。
好吧,我有一个问题,因为我正在与Arduino合作。它使用内存,不要删除它,所以你需要在使用后删除它。
绑定参数更好的原因之一 – eckes 2017-12-08 17:33:49