将sqlite_exec响应的行组合到C中sqlite回调的单个字符串中
我试图漂亮地打印从SELECT调用返回的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
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.