我想使用类似于 printf 在 C 中所做的事情来存储格式化的字符串。
char *tmp = (char *)sqlite3_column_text(selectstmt, 2);
const char *sqlAnswers = printf("select key from answer WHERE key = %s LIMIT 5;", tmp);
后者显然是一个错误。
我想使用类似于 printf 在 C 中所做的事情来存储格式化的字符串。
char *tmp = (char *)sqlite3_column_text(selectstmt, 2);
const char *sqlAnswers = printf("select key from answer WHERE key = %s LIMIT 5;", tmp);
后者显然是一个错误。
你可以用 来做 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,使用准备好的语句要好得多。它们避免了 SQL 注入漏洞(并且经常需要sprintf
. 使用它们,您将准备语句“select key from answer 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);
如果您使用的是 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);
我实际上是使用 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);
Michael Ekstrand代码很好,但您需要多次复制和粘贴。我在一个函数中使用此代码
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。它使用内存并且不会丢弃它,因此您需要在使用后将其删除。
在 Windows 上,您可以使用 sprintf_s 来添加缓冲区溢出保护,就像 Michael E 所说的那样。
http://msdn.microsoft.com/en-us/library/ce3zzk1k(VS.80).aspx