web-dev-qa-db-ja.com

printfを変数に格納する方法は?

PrintfがCで行うのと同様の方法を使用して、フォーマットされた文字列を格納したいと思います。

char *tmp = (char *)sqlite3_column_text(selectstmt, 2);
const char *sqlAnswers = printf("select key from answer WHERE key = %s LIMIT 5;", tmp);

後者は明らかにエラーです。

17
Frank

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エンジンは文字列を入力し、最初に適切にエスケープされていることを確認する必要をなくします。

36

sprintf()が必要です。

char *sqlAnswers = malloc(SIZE_TO_HOLD_FINAL_STRING);
sprintf(sqlAnswers, "select key from answer WHERE key = %s LIMIT 5;", tmp);
9
Carl Norum

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);
8
Scott Wales

私は実際に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);
2
Frank

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を使用しているため、問題が発生します。メモリを使用し、ドロップしないので、使用後に削除する必要があります。

1
Rodrigo

Windowsでは、MichaelEが言っていたようにバッファオーバーフロー保護を追加するsprintf_sを使用できます。

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

0
rerun