1

私は本当に基本的なことをしようとしています-SQLiteのC/C++インターフェイスをSELECT使用してステートメントの結果を返します。私のデータテーブルには、キー(varchar)と値(text)の2つのフィールドしかありません。

キーが与えられた場合、私の目標はSQLiteデータベースにクエリを実行して値を返すことです。* sqlite3_exec *-* select_callback *関数とparam(char *)に渡します。パラメータは、*select_callback*内で正しい値に正常に設定されています。ただし、* sqlite3_exec *を呼び出した後、paramは空の文字列を指します(同じメモリを指しているにもかかわらず)。

何がうまくいかず、これを修正する方法はありますか?* sqlite3_exec *はバックグラウンドでparamのメモリの割り当てを解除しますか?

前もって感謝します!

// given the key tid returns the value
void getTypeByID(sqlite3 * db, string tid)
{
    string sql_exp_base = "select value from Data where key=''";
    int len = (int)sql_exp_base.size() + (int)tid.size() + 10;
    char * sql_exp = new char[len];
    sprintf(sql_exp, "select value from Data where key='%s'", tid.data());
    sql_exec(db, sql_exp);
}

// This is the callback function to set the param to the value
static int select_callback(void * param, int argc, char **argv, char **azColName)
{
    if(argc == 0) return 0;
    char * res = (char *)param;
    res = (char *) realloc(res, sizeof(*res));
    res = (char *) malloc(strlen(argv[0]) + 1);
    strcpy(res, argv[0]);
    printf("%s\n", res); // {"name": "Instagram Photo", url: "http://instagram.com"}
    return 0;
}

// execute the SQL statement specified by sql_statement
void sql_exec(sqlite3 * db, const char * sql_statement)
{
    char * zErrMsg = 0;
    char * param = (char *)calloc(1, sizeof(*param));
    int rc = sqlite3_exec(db, sql_statement, select_callback, param, &zErrMsg);
     printf("%s\n", param);

paramは{"name": "Instagram Photo"、url: "http://instagram.com"}である必要がありますが、何らかの理由で空の文字列です。

    if(rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
}
4

2 に答える 2

3

新しく割り当てられたメモリへのポインタをに書き込んでいますresが、その変数は内部のローカル変数select_callbackであるため、それsql_execについてはわかりません。同じことがパラメータにも当てはまりparamます。これは、の4番目のパラメータのコピーにすぎませsqlite3_execん。

string文字列への変更が確実に表示されるようにするには、エラーメッセージと同様に、文字列自体へのポインタ(Cの場合はポインタ、C ++の場合はオブジェクト)を渡す必要があります。Cの場合:

char *result_str = ...;
rc = sqlite3_exec(..., &result_str, ...);
...
int callback(void *param, ...)
{
    char **result_str = (char **)param;
    *result_str = (char *)realloc(*result_str, ...);
    strcpy(*result_str, ...);
}

注:文字列に引用符やその他の制御文字が含まれている場合、またはBobby Tablestidを検索しようとすると、問題が発生します。SQL文字列をフォーマットして割り当てるために使用するか、パラメータをより適切に使用しますsqlite3_mprintf

于 2012-10-20T08:10:59.140 に答える
0

私は最後の答えを試しましたが、うまくいきました:char値としてポインターへのポインターを作成し、void変数からポインターのポインターを挿入しました

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sqlite3.h>


int callback(void *data,int argc,char *argv[],char **azcolname) {
int i=0;

char **result_str = (char **)data;
*result_str = (char *)calloc(strlen(argv[0]),sizeof(char));
strcpy(*result_str,argv[0]);
return 0;
}

    int main(int argc,char *argv[]) {

sqlite3 *conn;
int c=0;
char *ofile=NULL;
char *tsql_stmt=NULL;
int res=0;
char *zErrMsg = 0;
char *data=NULL;


while((c = getopt(argc , argv ,"f:")) != -1) 
{
    switch (c) {

        case 'f':
            ofile = optarg;
        break;

        default:
            fprintf(stderr,"worng argument provided\n");
        break;

    }
}

if (!ofile) {
    fprintf(stderr,"no output file (-f) given\n");
    exit(1);
}
sqlite3_open(ofile,&conn);
tsql_stmt = calloc(80,sizeof(char));
strcpy(tsql_stmt,"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='");
    strcat(tsql_stmt,"mytest");
    strcat(tsql_stmt,"\'");

    //running the query
//printf("%s\n",tsql_stmt);
res = sqlite3_exec(conn,tsql_stmt,callback,&data, &zErrMsg);

if ( res != SQLITE_OK ) {
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
}
else{
    if ( atoi(data) != 1)
        fprintf(stderr, "unable to find the requested table\n");
    else
        printf("the Operation found the requested table in the database\n");
}

free(data);
sqlite3_close(conn);
return 0;
}
于 2013-09-30T17:54:31.763 に答える