Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将sqlite_exec响应的行组合到C中sqlite回调的单个字符串中_C_Sqlite_Pointers - Fatal编程技术网

将sqlite_exec响应的行组合到C中sqlite回调的单个字符串中

将sqlite_exec响应的行组合到C中sqlite回调的单个字符串中,c,sqlite,pointers,C,Sqlite,Pointers,我试图漂亮地打印从SELECT调用返回的sqlite表,但我无法使指针正常工作 到目前为止,我有以下几点: char *full_response = ""; sqlite3_exec(db, select_query, callback, (void *)full_response, &zErrMsg); printf(full_response); // This is where I'd like the entire table 以及以下回调函数: sta

我试图漂亮地打印从SELECT调用返回的sqlite表,但我无法使指针正常工作

到目前为止,我有以下几点:

char *full_response = "";
sqlite3_exec(db, select_query, callback, (void *)full_response, &zErrMsg);
printf(full_response);  // This is where I'd like the entire table
以及以下回调函数:

static int callback(void *full_response, int argc, char **argv, char **azColName){
   int i;
   int response_header_length = 0;
   int response_body_length = 0;
   
   // This is to get the length of the header and body strings.
   for (i=0;i<argc;i++){
    response_header_length+=strlen(azColName[i])+1;
    response_body_length+=strlen(argv[i])+1;
   }
   //This is to turn the headers and field values of the returned table into a single string
   char response_header[response_header_length-1];strcpy(response_header,azColName[0]);
   char response_body[response_body_length-1];strcpy(response_body,argv[0]);
   for (i=1;i<argc;i++){
       strcat(response_header,"|"); strcat(response_header,azColName[i]);
       strcat(response_body,"|"); strcat(response_body,argv[i]);
   }


   if (strlen((char *)full_response)==0){ // full_response is empty so we need the header
    char temp_response[strlen(response_header) + strlen(response_body)+1];
    strcpy(temp_response, response_header);
    strcat(temp_response, "\n");
    strcat(temp_response, response_body);
    full_response = &temp_response;
   }
   else{ // full_response has stuff in it so we just need the field values for this row
   char temp_response[strlen((char *)full_response) + strlen(response_body)+1];
   strcpy(temp_response, (char *)full_response);
   strcat(temp_response, "\n");
   strcat(temp_response, response_body);
   full_response = &temp_response;
   }
   return 0;
}
在回调函数中,会将完整的_响应地址重新分配给temp_响应的地址,该地址应包含到目前为止的表以及回调函数正在处理的当前行,但它似乎不是这样工作的

-


或者,如果C中有一个漂亮的print函数或代码片段或git repo,可以在主体(即调用sqlite_exec的地方)中以字符串的形式获取整个返回表,那将非常棒。

您需要动态分配字符串免责声明-未经测试:

struct Buffer {
    size_t n;
    // todo: may want to add capacity and over-allocate to avoid worst-case quadratic performance.
    char *p;
};
void bufcat(struct Buffer *buf, const char *s) {
    size_t m = strlen(s), n = buf->n+m;
    char *p = realloc(buf->p, n+1);
    /* note: realloc may fail */
    memcpy(p+buf->n, s, m+1);
    buf->p = p;
    buf->n = n;
}

static int callback(void *full_response, int argc, char **argv, char **azColName){
    struct Buffer *buf = full_response;
    if(buf->n == 0) {
        for(int i=0;i<argc;i++){
            if(i) bufcat(buf, "|");
            bufcat(buf, azColName[i]);
        }
        bufcat(buf, "\n");
    }
    for(int i=0;i<argc;i++){
        if(i) bufcat(buf, "|");
        bufcat(buf, argv[i]);
    }
    bufcat(buf, "\n");
    return 0;
}
或者,您可以在以下平台上使用open_memstream:

static int callback(void *full_response, int argc, char **argv, char **azColName){
    FILE *file = full_response;
    if(ftell(file) == 0) {
        for(int i=0;i<argc;i++){
            if(i) fputc('|',file);
            fputs(azColName[i],file);
        }
        fputc('\n',file);
    }
    for(int i=0;i<argc;i++){
        if(i) fputc('|',file);
        fputs(argv[i],file);
    }
    fputc('\n',file);
    return 0;
}

您需要动态分配字符串免责声明-未测试:

struct Buffer {
    size_t n;
    // todo: may want to add capacity and over-allocate to avoid worst-case quadratic performance.
    char *p;
};
void bufcat(struct Buffer *buf, const char *s) {
    size_t m = strlen(s), n = buf->n+m;
    char *p = realloc(buf->p, n+1);
    /* note: realloc may fail */
    memcpy(p+buf->n, s, m+1);
    buf->p = p;
    buf->n = n;
}

static int callback(void *full_response, int argc, char **argv, char **azColName){
    struct Buffer *buf = full_response;
    if(buf->n == 0) {
        for(int i=0;i<argc;i++){
            if(i) bufcat(buf, "|");
            bufcat(buf, azColName[i]);
        }
        bufcat(buf, "\n");
    }
    for(int i=0;i<argc;i++){
        if(i) bufcat(buf, "|");
        bufcat(buf, argv[i]);
    }
    bufcat(buf, "\n");
    return 0;
}
或者,您可以在以下平台上使用open_memstream:

static int callback(void *full_response, int argc, char **argv, char **azColName){
    FILE *file = full_response;
    if(ftell(file) == 0) {
        for(int i=0;i<argc;i++){
            if(i) fputc('|',file);
            fputs(azColName[i],file);
        }
        fputc('\n',file);
    }
    for(int i=0;i<argc;i++){
        if(i) fputc('|',file);
        fputs(argv[i],file);
    }
    fputc('\n',file);
    return 0;
}

这是使用sqlite3_exec而不是普通工作流来使用查询结果的少数几种情况之一。但是,不要使用您自己的可增长字符串,而是使用sqlite3的API:


这是使用sqlite3_exec而不是普通工作流来使用查询结果的少数几种情况之一。但是,不要使用您自己的可增长字符串,而是使用sqlite3的API:


为什么您需要它以字符串形式出现,而不是直接从回调中打印出来?您知道exec可以从不同的表中运行多个SELECT,从而给出不同的头吗?你能使用fmemopen吗?我需要用字符串做其他事情,即通过套接字发送整个响应,而不是单独发送每一行,并且需要整个字符串。我确实尝试了从回调打印,但这对我的目的是无用的。其他地方正在进行验证,因此假设它对单个表运行单个SELECT查询。为什么需要字符串形式的验证,而不是直接从回调中打印?您知道exec可以从不同的表中运行多个SELECT,从而给出不同的头吗?你能使用fmemopen吗?我需要用字符串做其他事情,即通过套接字发送整个响应,而不是单独发送每一行,并且需要整个字符串。我确实尝试了从回调打印,但这对我的目的是无用的。其他地方正在进行验证,所以假设它对一个表运行一个SELECT查询。太棒了-谢谢。另外,Struct buffer和bufcat是一个共同的模式吗?@asuprem:pattern与否,您已经有三个答案用不同的名称做相同的事情。太棒了-谢谢。此外,Struct buffer和bufcat是否是一个共同的模式?@asuprem:pattern与否,您已经有三个答案以不同的名称执行相同的操作。
char *full_response = 0;
size_t n = 0;
FILE *file = open_memstream(&full_response, &n);
sqlite3_exec(db, select_query, callback, (void *)file, &zErrMsg);
fclose(file);
puts(full_response);
free(full_response);
static int callback(void *data, int ncols, char **cols, char **headers) {
    sqlite3_str *str = data;
    for (int n = 0; n < ncols; n++) {
      sqlite3_str_apendall(str, cols[n]);
      if (n + 1 < ncols) 
        sqlite3_str_appendchar(str, 1, '|');
    }
    sqlite3_str_appendchar(str, 1, '\n');
    return 0;
}

//...

    sqlite3_str *str = sqlite3_str_new();
    sqlite3_exec(db, select_query, callback, str, &zErrMsg);
    char *s = sqlite3_str_finish(str); // Get the string you just built
    fputs(s, stdout); // Or do whatever with the string
    sqlite3_free(s); // Just remember to free it when done.