C ++与sqlite:"库程序不按顺序调用

时间:2014-04-15 17:25:43

标签: c++ sqlite

如果我运行以下代码(仅显示相关部分),我将收到错误消息:"库程序不按顺序调用"。

// Open database
char *lang = "Spanish";
char *DBName = "Spanish.db";
sqlite3 *db;
int sqlret;

sqlret = sqlite3_open(DBName, &db);

if (sqlret != SQLITE_OK) {
    printf("Can't open database: %s \n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return 1;
}

// Create Table

sqlite3_stmt *stmt;
char *sqlcommand;
sqlcommand = new char;

Start(sqlcommand, lang);

printf(sqlcommand);

sqlret = sqlite3_prepare_v2(db, sqlcommand, -1, &stmt, NULL);

if (sqlret != SQLITE_OK) {
    printf("Error: %s \n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return 2;
}

开始(a,b)是以下功能:

void Start(char *command, char *language) {

sprintf(command,"CREATE TABLE IF NOT EXISTS 'Vocabulary' ( "\
                "'%s' TEXT NOT NULL, ", language);
strcat(command, "'Native Language' TEXT NOT NULL, " \
                "'Times Asked' INT NOT NULL, " \
                "'Times Correct' INT NOT NULL, " \
                "'Times Wrong' INT NOT NULL );");
}

但是,如果我没有动态定义sqlcommand但是静态(我的意思是:char * sqlcommand =" CREATE ...&#34 ;;),它可以工作。如果你帮助了我,我将不胜感激!

1 个答案:

答案 0 :(得分:1)

sqlcommand = new char;

这为一个字符分配内存。顺便说一下,你永远不会删除。

你不想要一个字符,而是整个字符串。从技术上讲,这意味着您需要一对new[]delete[]来电。但是,在C ++中,如果不必要,则不要使用原始字符串。你当然不必在这里使用它们。

改为使用std::string

这也允许您摆脱低级sprintfstrcat函数。结果如下:

std::string Start(std::string const &language)
{
    return "CREATE TABLE IF NOT EXISTS 'Vocabulary' ( "\
        "'" + language + "' TEXT NOT NULL, "
        "'Native Language' TEXT NOT NULL, "
        "'Times Asked' INT NOT NULL, "
        "'Times Correct' INT NOT NULL, "
        "'Times Wrong' INT NOT NULL );"
}

为了与C函数(例如SQLite API中的函数)兼容,std::string提供c_str()成员函数:

std::string sqlcommand = Start(lang);
sqlret = sqlite3_prepare_v2(db, sqlcommand.c_str(), -1, &stmt, NULL);

简而言之,您确实需要学习在C ++中使用字符串。你的生活将变得相当容易:)


编辑:只是提到这一点......您遇到的错误消息显然源于SQLite内部的未定义行为,因为您向它传递了一个无效的char指针(一个不是null-terminated - 你可以在C ++中忘记的另一个C事件。)