2014-04-15 31 views
0

如果我運行下面的代碼(只有相關部分所示),我會得到錯誤信息:‘庫程序的呼叫順序’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的動態,但靜態的(我的意思是:字符*的SqlCommand = 「創建...」; ),它的工作原理。如果你幫助我,我將不勝感激!

+0

只是挑剔:沒有任何C++代碼在那裏,只是C. –

+0

@JoachimPileborg:錯了,有一個'new'(它甚至似乎是罪魁禍首):) –

回答

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結尾的 - 另一個你可以在C++中忘記的C)。

+0

鑑於該過程顯然做了不會崩潰,'char *'正在被('sprintf'和'strcat')取得NUL終止 - 但是它會拋棄堆中的任何東西。 –

+0

@AndrewMedico:我認爲這裏最精確的是sprintf調用已經產生了UB。 –