1. 程式人生 > >C++中istream和stringstream的使用

C++中istream和stringstream的使用

   上個專案完成第一個版本開發,寫的部分由於是底層SDK。測試的時候沒有BUG可改,於是又回到本部門開始做資料庫維護的工作。資料庫表設計已基本成型,主要是新增或刪除一些欄位。麻煩的是要為資料庫表建立觸發器,而且這些觸發器功能都一樣,就是在資料更新的時候寫歷史記錄。一百多個表,一個一個寫不知道寫到什麼時候,甚至有些表字段就差不多有一百個欄位。於是下載一個MySQL的C++聯結器,不知道為什麼,下原始碼居然編譯通不過,裡面甚至還有一些基本的識別符號不識別的錯誤。真不知道Oracle想把MySQL怎麼樣了,上傳程式碼不用檢查嗎?下了一個編譯好非安裝的庫,加入工程使用,居然連基本的getString函式都報錯。恩,不是我一個人遇見,其他人的解決方法是使用getBlob代替。於是就是我標題中的istream流了,使用方法如:

string svalue;

std::istream* id = result->getBlob(sfield.c_str());//從結果集中取回欄位sfield.c_str()的值

*id >> (svalue);//把該值輸出給svalue;以前還真沒如此使用過istream。

下面還是使用MySQL聯結器引出的問題,該問題導致我化了一天的時間,恩。有如下幾個問題:

1、MySQL聯結器庫對string進行封裝成SQLString,並重載了該類的建構函式接收string,char[]及char*等型別作為引數來構造SQLString物件,於是導致在呼叫excute函式的時候傳遞給string字串時,編譯器不會報告型別不匹配,因為會構造臨時SQLString物件,但是在執行時由於記憶體結構不一樣會導致崩掉。至於為什麼string給SQLString中的string不行,我也還不清楚。最後改成string的data()或c_str()函式返回char[]後傳給excute函式解決。有一點變態的是封裝後的SQLString再我直接構造一個字串的時候編譯器總是提示指標錯誤,其實是沒問題的,只是在SQLString的前幾個字元為被使用吧。

2、我一直認為DELIMITER命令式MySQL伺服器提供的命令,所以我在程式設計的時候在前面加了一個DELIMITER $$命令,由於該命令後第1點同時存在,導致我未搞清楚什麼原因。其實DELIMITER是告訴客戶端什麼時候可以提交一個SQL語句,由於我是在程式中處理,所以是不需要改命令的。在使用者手動輸入的時候,由於預設情況下回車會提交,導致多行的命令不能完整提交而出現該命令。正因為這,我找不到原因,於是加了聯結器提供的異常處理機制。是網上一個老兄提供的程式碼,如下:


cout<< "# ERR: SQLException in " << __FILE__;
cout<< "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
cout<< "# ERR: " << e.what();
cout<< " (MySQL error code: " << e.getErrorCode();
cout<< ", SQLState: " << e.getSQLState().data() << " )" << endl;

可我是在MFC下,cout的東西看不到,而且我不想去改寫這些程式碼,印象中找到了stringstream類。

處理如下,需要包含sstream標頭檔案。

stringstream sException;

sException << "# ERR: SQLException in " << __FILE__;
sException << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
sException << "# ERR: " << e.what();
sException << " (MySQL error code: " << e.getErrorCode();
//sException << ", SQLState: " << e.getSQLState().data() << " )" << endl;//這句不知道為什麼會崩掉
string str = sException.str();//這樣就先輸出到stringstream物件中,在從中提取出字串就OK了。
AfxMessageBox(str.data());

總的來說,感覺上MySQL提供的這些聯結器不太專業,感覺做為C++程式設計師的我也不太專業,連C++基本的輸入輸出流都使用不熟。不過問題解決了就行