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]= "";

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]= "";
    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;
}