如何将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); 

后者显然是一个错误。

你可以用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 key where??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  // ... 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); 

在Windows上你可以使用sprintf_s,它增加了像Michael E所说的缓冲区溢出保护。

http://msdn.microsoft.com/en-us/library/ce3zzk1k(VS.80).aspx

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。 它使用内存而不删除它,因此您需要在使用后删除它。