CSV解析和插入数据库-空值和分段错误
Im使用以下代码解析CSV并将值插入表中CSV解析和插入数据库-空值和分段错误,c,csv,sqlite,C,Csv,Sqlite,Im使用以下代码解析CSV并将值插入表中 void readcsv() { FILE* stream = fopen("input.csv", "r"); char line[1024]; while (fgets(line, 1024, stream)) { char* tmp = strdup(line); char a1[20]= ""; char b1[20]= ""; char c1[20]= "";
void readcsv()
{
FILE* stream = fopen("input.csv", "r");
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
char a1[20]= "";
char b1[20]= "";
char c1[20]= "";
char d1[20]= "";
char e1[20]= "";
char f1[20]= "";
strcat(a1, getcsvfield(tmp, 1));
strcat(b1, getcsvfield(tmp, 2));
strcat(c1, getcsvfield(tmp, 3));
strcat(d1, getcsvfield(tmp, 4));
strcat(e1, getcsvfield(tmp, 5));
strcat(f1, getcsvfield(tmp, 6));
strcat(a1, '\0');
strcat(b1, '\0');
strcat(c1, '\0');
strcat(d1, '\0');
strcat(e1, '\0');
strcat(f1, '\0');
// printf("Field 1 would be %s\n", a1);
// printf("Field 2 would be %s\n", getcsvfield(tmp, 2));
// printf("Field 2 would be %s\n", getcsvfield(tmp, 3));
// printf("Field 2 would be %s\n", getcsvfield(tmp, 4));
// printf("Field 2 would be %s\n", getcsvfield(tmp, 5));
// printf("Field 2 would be %s\n", getcsvfield(tmp, 6));
//--- // execute("INSERT INTO sdata(sid,name,area,type,stbamount,pkgamount) VALUES('%s','%s','%s','%s','%s','%s');",a1,b1,c1,d1,e1,f1);
// NOTE strtok clobbers tmp
free(tmp);
}
}
//Used for parsing CSV
const char* getcsvfield(char* line, int num)
{
char buffer[1024]= {0};
strcpy(buffer, line);
const char* tok;
for (tok = strtok(buffer, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
这是CSV
me;val1;val2;val3;val4;val5;
me;val1;val2;val3;val4;val5;
错误:
分段故障(堆芯转储)
更新:
数据库.c
#include“./include/header.h”
int Open_数据库()
{
int rc=0;
rc=初始化_db();
如果(rc==0)
{
printf(“\n未能初始化数据库”);
返回失败;
}
printf(“\n数据库初始化成功”);
rc=open_sqlite(“/mnt/jffs2/db2.db”);
如果(rc==0)
{
printf(“\n打开数据库失败”);
返回失败;
}
其他的
printf(“数据库已存在\n”);
printf(“\n数据库已打开\n”);
回归成功;
}
int初始化_db()
{
char*database=“/mnt/jffs2/db2.db”;
int rc=0,i=0;
结构统计buf;
i=统计(数据库和buf);
如果((i0&&(c=getc(fd))!=EOF)
{
如果(c=='\n')
打破
*cstring++=c;
}
*cstring++='\0';
if(c==EOF&&cstring==line)//ie文件中没有任何内容!
行=空;
如果(c==EOF)
行=空;
回流线;
}
结果集获取结果(常量字符*fmt,…)
{
int成功=0;
int nrow=0,ncol=0,i=0,j=0,count=0;
字符*错误消息;
字符**结果;
字符***记录集;
结果集结果集表格;
char sql_string[1500];//老实说,这需要更加优雅;现在就可以了
va_列表参数;
va_启动(参数、fmt);
sql_字符串[0]='\0';
ret=vsprintf(sql_字符串、fmt、args);
va_端(args);
fprintf(标准输出,“\n%s\n”,sql\u字符串);
SQLITE=1;
//初始化resultset_表;
resultset_table.rows=0;
结果集_table.cols=0;
resultset_table.recordset=NULL;
ret=sqlite3\u get\u表(
德布康,
sql_字符串,
&结果,,
&哦,
&士官,
&错误消息
);
fprintf(标准输出,“nrow=%d ncol=%d\n”,nrow,ncol);
记录集=(字符***)malloc(nrow*sizeof(字符**));
对于(count=ncol;countJust使用调试标志编译代码(gcc或clang时为-g3)然后在调试器中运行,例如gdb./a.out。分段错误后,您可以使用gdb的bt命令看到backtrace。您还可以使用gdb分析现有的核心转储。@pikkewyn请查看更新。。您可能应该创建一个新问题,并准备完整的问题代码示例。即使是大型项目,也尝试只提取必要的位然后将它们放在一起重现问题并寻求帮助。或者,如果有进一步的问题,您可以通过研究[dot]导师[at]gmail[dot]com与我联系。关于这一行:return tok;
,这是将指针返回到位于getcsvfield()堆栈上的字符数组中
当该函数退出时,字符数组将超出范围
,因此调用者将收到指向垃圾桶的指针。建议调用字符数组的malloc()
,或者将字符数组放置在文件全局空间中(前缀为static
修饰符)@user3629249我让它工作了…问题是我在调用此方法之前忘记打开数据库。非常感谢您的建议:)
#include "../include/header.h"
int Open_Database()
{
int rc=0;
rc = Initialize_db();
if(rc == 0)
{
printf("\nFailed to initialize db");
return FAILED;
}
printf("\n Database initialization success");
rc = open_sqlite("/mnt/jffs2/db2.db");
if(rc == 0)
{
printf("\n Failed to open db");
return FAILED;
}
else
printf("Database already exists\n");
printf("\n database opened\n");
return SUCCESS;
}
int Initialize_db()
{
char *database = "/mnt/jffs2/db2.db";
int rc=0, i=0;
struct stat buf;
i = stat(database, &buf );
if((i<0) || (buf.st_size == 0))
{
printf("Initializing database...\n");
lk_dispclr();
lk_disptext(2,0,(unsigned char *)" Initializing DB...",0);
rc = open_sqlite(database);
if(rc == 0)
{
printf("Create database failure!\n");
lk_dispclr();
//DispText(2,0," Failed to Create",0);
//DispText(4,4," Database",0);
lk_getkey();
return FAILED;
}
else
{
rc = execute("CREATE TABLE if not exists sdata(sid VARCHAR(10),name VARCHAR(20),area VARCHAR(10),type VARCHAR(10),stbamount VARCHAR(10),pkgamount VARCHAR(10))");
if(rc==0)
{
return error_handler(rc);
}
else
{
printf("\n Master table created\n");
}
rc = execute("CREATE TABLE if not exists tdata(sid VARCHAR(10),stbamount VARCHAR(10),pkgamount VARCHAR(10))");
if(rc==0)
{
return error_handler(rc);
}
else
{
printf("\n Transaction table created\n");
}
}
close_sqlite();
}
else
{
printf("database already existed\n");
rc=1;
}
return rc;
}
int error_handler(int rc)
{
if(rc == 0)
{
printf("\n SQL Error while initializing!!!\n");
/*lk_dispclr();
DispText(2,0," SQL ERROR",0);
lk_getkey();
*/
return FAILED;
}
else
{
printf("SQL Successfull\n");
/*lk_dispclr();
DispText(2,0," SQL Successfull",0);
lk_getkey();*/
}
return SUCCESS;
}
#include "../include/sqlite3.h"
#include "../include/header.h"
#define ELEMENT_NUM(_array) ( sizeof(_array)/sizeof(_array[0]) )
sqlite3 *db_conn;
int ret = 0;
char OPEN_FLAG = 0;
int open_sqlite(char *db_name)
{
if(OPEN_FLAG == 0)
{
if(sqlite3_open(db_name, &db_conn) == SQLITE_OK)
{
OPEN_FLAG = 1;
printf("\nOPEN_FALG = %d\n",OPEN_FLAG);
printf("database opened\n");
return 1;
}
else
{
printf("database opening failed\n");
return 0;
}
}
else
{
printf("\ndatabase already opened\n");
return 1;
}
return 1;
}
int close_sqlite()
{
if(OPEN_FLAG == 1)
{
if(sqlite3_close(db_conn) == SQLITE_OK)
{
printf("database closed\n");
OPEN_FLAG = 0;
printf("OPEN_FLAG = %d\n",OPEN_FLAG);
return 1;
}
else
{
printf("database closing failed\n");
return 0;
}
}
else
{
printf("database not yet opened\n");
return 1;
}
}
//only type s and d are allowed as arguments
int execute(const char* fmt, ...)
{
char *err_messg;
int ret=0, result = 0;
char sql_string[2000]="";//this honestly needs to be more elegant; will do for now
//char sql_string[1024]="";//this honestly needs to be more elegant; will do for now
va_list args;
va_start(args, fmt);
SQLITE = 1;
memset(sql_string,0,sizeof(sql_string));
sql_string[0] = '\0';
ret = vsprintf(sql_string, fmt, args);
va_end(args);
err_printf(sql_string);//
if(!ret)
result = 0;
else
result = 1;
if(result != -1)
{
if(sqlite3_exec(db_conn, sql_string, NULL, 0, &err_messg) == SQLITE_OK)
{
result = 1;
}
else
{
fprintf(stdout,"SQL error: %s\n", err_messg);
result = 0;
}
}
SQLITE = 0;
return result;
}
//you must open_sqlite first before using execute_file
int execute_file(char *filename)
{
char *err_messg;
FILE *read_fd = (FILE *) 0;
char sql_string[1024];
ret = 0;
read_fd = fopen (filename, "r");//open file for read
if (read_fd != NULL)
{
rewind(read_fd);
while(!feof (read_fd))
{
m_fgets(sql_string, 1024, read_fd);
//ie if string is not empty, then execute - ha no more newline errors!
if(strcmp(sql_string, "") != 0)
{
//err_printf("SQL_STRING: %s\n", sql_string);
if(sqlite3_exec(db_conn, sql_string, NULL, 0, &err_messg) == SQLITE_OK)
{
ret = 1;
continue;
}
else
{
fprintf(stdout,"SQL error: %s\n", err_messg);
ret = 0;
break;
}
}
}
}
fclose(read_fd);
return ret;
}
char *m_fgets(char *line, int n, FILE *fd)
{
int c = 0;
char *cstring;
cstring = line;
while(--n>0 && ( c = getc(fd) ) != EOF)
{
if (c == '\n')
break;
*cstring++ = c;
}
*cstring++ = '\0';
if (c == EOF && cstring == line)//ie nothing in file!
line = NULL;
if (c == EOF)
line = NULL;
return line;
}
resultset get_result(const char* fmt, ...)
{
int success = 0;
int nrow=0, ncol=0, i=0, j=0, count=0;
char *err_messg;
char **result;
char ***recordset;
resultset resultset_table;
char sql_string[1500];//this honestly needs to be more elegant; will do for now
va_list args;
va_start(args, fmt);
sql_string[0] = '\0';
ret = vsprintf(sql_string, fmt, args);
va_end(args);
fprintf(stdout,"\n%s\n", sql_string);
SQLITE = 1;
//initialize resultset_table;
resultset_table.rows = 0;
resultset_table.cols = 0;
resultset_table.recordset = NULL;
ret = sqlite3_get_table(
db_conn,
sql_string,
&result,
&nrow,
&ncol,
&err_messg
);
fprintf(stdout,"nrow=%d ncol=%d\n",nrow,ncol);
recordset = (char ***)malloc(nrow * sizeof(char **));
for(count=ncol; count<((nrow + 1)*ncol); count++)
{
recordset[i] = (char **)malloc(ncol * sizeof(char *));
for(j=0; j<ncol; j++)
{
err_printf("%s ",result[count]);//
recordset[i][j] = (char *) malloc( (strlen(result[count]) + 1) );
strcpy(recordset[i][j], result[count]);
if(j != (ncol - 1))
count++;
}
i++;
err_printf("\n");//
}
sqlite3_free_table(result);
if( ret != SQLITE_OK )
{
fprintf(stdout,"SQL error: %s\n", err_messg);
success = 0;
}
else
{
resultset_table.rows = nrow;
resultset_table.cols = ncol;
resultset_table.recordset = recordset;
success = 1;
}
SQLITE = 0;
return resultset_table;
}
//will free all allocd memory ie only recordset memory (since only that allocd)
void free_result(resultset resultset_table)
{
int i=0,j=0;
if(resultset_table.recordset != NULL)
{
for(i=0;i<resultset_table.rows;i++)
{
for(j=0;j<resultset_table.cols;j++)
{
free(resultset_table.recordset[i][j]);
}
free(resultset_table.recordset[i]);
}
free(resultset_table.recordset);
}
}
//if DEBUG is on then print message to stderr using fprintf function
/*int err_printf(const char *fmt, ...)
{
int i;
va_list ap;
va_start(ap, fmt);
i = vfprintf(stderr, fmt, ap);
va_end(ap);
return i;
}*/
//returns the row index in the resultset that was selected
//column is the column of the resultset that you want to display
int err_printf(const char *fmt, ...)
{
int i;
// #ifdef DEBUG
va_list ap;
va_start(ap, fmt);
i = vfprintf(stderr, fmt, ap);
va_end(ap);
// #endif
return i;
}