我想用類似於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