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
を2回使用します。1回目は使用するサイズを確認し、2回目は実際に使用します。これは、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
の必要性)を回避します。それらを使用して、「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またはBSDlibcを使用している場合は、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);
私は実際にsprintfを介して生成する代わりに、sqlite3_bind_textを使用してワイルドカードを入力しています。
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コードは適切ですが、何度もコピーして貼り付ける必要があります。このコードを1つの関数で使用します
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では、MichaelEが言っていたようにバッファオーバーフロー保護を追加するsprintf_sを使用できます。
http://msdn.Microsoft.com/en-us/library/ce3zzk1k(VS.80).aspx