[問題] VC++ 字元集"Unicode"下使用MySQL

作者: chingyue (ChingYue)   2017-06-16 18:05:55
開發平台(Platform): (Ex: Win10, Linux, ...)
win7(win10)
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
VC++(2013)
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
MySQL API
問題(Question):
各位前輩大家好
之前小弟寫了一支程式
使用的字元集為"多位元組"
程式碼 http://codepad.org/aUdBuWV3
今天我想把字元集改為"Unicode"
結果發生了錯誤
無法將引數char轉換為'LPCWSTR'
我Google後發現
LPCWSTR = const wchar_t *
所以做了幾點修正
1:char改為wchar_t,雙引號前面加L
2:sprintf_s改為swprintf_s
3:strlen()改為wcslen()
4:增加 mysql_options(&myCont, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_set_character_set(&myCont, "utf8");
修改後程式碼:http://codepad.org/IhFEG7RM
但是在使用mysql_real_connect()時發生了錯誤
函式說明:http://i.imgur.com/GY72hjm.jpg
錯誤圖:http://i.imgur.com/LWLkqD1.jpg
請問這樣是不是要修改標頭檔?
(有稍微修改一下 結果問題好像越來越大洞...)
還是有其他方法能在Unicode下使用MySQL API ?
懇請各位前輩賜教
謝謝!
程式碼(Code):(請善用置底文網頁, 記得排版)
多位元組:http://codepad.org/aUdBuWV3
Unicode :http://codepad.org/IhFEG7RM
作者: pttuser (pttuser)   2017-06-17 23:11:00
你應該在unicode用tchar,然後要用char時候只要sprintf到char buffer就好了如果更菜鳥一點,用multibytetowidebyte也可以multibytetowidebyte API應該沒拼錯吧?很久沒寫vc了啊應該是widebytetomultibyte啦果然老了,windowsAPI記不住了良好的習慣用tchar不要用wchar or char
作者: LPH66 (-6.2598534e+18f)   2017-06-18 06:33:00
這裡其實不是 TCHAR/wchar_t/char 的問題而是 MySQL API 只收 const char * 的關係雖然我沒用過, 但根據我在 PHP 的經驗, 這個 const char *字串的編碼應該是先前 set names 所設定的編碼那麼當原 PO 手上有的是 wchar_t 時, 就必須要先轉碼成對應編碼的 const char * 字串再送進去如果是 set names utf8; 的話, 用上面推文講的 windows APIWideCharToMultiByte() 函數就可以轉了, 詳情可查 MSDN這裡反而當使用 TCHAR 會搞亂, 因為如果 TCHAR 是 char 時要先把這個 char* 字串轉成 wchar_t* 的 Unicode 字串(使用的是上面那個函式的反向版 MultiByteToWideChar() )再轉成 UTF-8 字串才能送進去比 TCHAR 是 wchar_t 時多了一個步驟如果原 PO 沒有想要維護兩個版本的程式那建議不要 TCHAR而就直接使用 wchar_t 就行了
作者: pttuser (pttuser)   2017-06-18 14:10:00
就說在unicode環境只要把tchar sprintf到char buffer就可以餵給sql api了,widebytetomultibyte也可以啦,不過這種情況用widebytetomultibyte是菜逼巴的人用的樓上那個菜逼巴是聽不懂人話喔
作者: firose (guest也是也是也是也是也)   2017-06-18 14:26:00
這麼厲害? TCHAR 可以直接 sprintf 到 char buffer ?
作者: pttuser (pttuser)   2017-06-18 16:16:00
廢話,windows 環境wide string 可以直接sprintf到char buffer,一堆菜逼巴還在用widebytetomultibyte不過只限ascii code
作者: firose (guest也是也是也是也是也)   2017-06-18 17:12:00
那它還定義 _stprintf 跟 swprintf 幹嘛?
作者: LPH66 (-6.2598534e+18f)   2017-06-18 21:03:00
...要不要來做個實驗? 就印個 "一" 字就好......等等我看到了你的但書: 只限 ASCII Code = =不過就算這樣還是不行的...除非你的 char buffer 別有用途再不然就是你以為是 _UNICODE 其實是 _MBCS所以 TCHAR 還是 char, 那自然可以 sprintf 到 char這似乎也能解釋為什麼你會有只限 ASCII 的但書在
作者: pttuser (pttuser)   2017-06-19 12:17:00
樓上的菜逼巴,這只是windows的小技巧之一,另外他的charbuffer是要餵給sql api的,又不是要處理拉丁字母,阿拉伯字母,中文等等,另外TCHAR就是widebyte沒錯,只是format不是%s而是%?自己Google吧看到兩個菜逼巴一直在回文,原po對multibyte或是widebyte不熟的話用widebyte <-> multibyte先頂著吧
作者: LPH66 (-6.2598534e+18f)   2017-06-19 14:38:00
不好意思, TCHAR 是 Visual Studio 獨有的東西就是為了一支程式能藉給定 _UNICODE 或 _MBCS 編出不同版本所以不會有 printf 的 %? 語法, 只會有 _stprintf 的 %s用 printf 印一個 TCHAR 一定是搞錯了什麼然後, sql 敘述並不只會有拉丁字母, 指定欄位名和給值時都會需要給定實際字串內容, 這正是 MYSQL_SET_CHARSET_NAME的用途; 我不相信一個有一定規模的資料庫會沒有字串資料甚至在開一個表格時對字串欄位都需要給定編碼了雖然我只能猜測, 但它 API 設計只吃 char* 的理由很有可能就是為了相容各種編碼, 因此只能以最原始的 char*進行傳送, 再使用所設定的編碼進行解釋 / 填入資料庫那為了要給定正確的編碼給這些欄位, 這樣子的轉碼是必須的_s 的函數需要傳入目標空間的最大大小, 位置在空間後面所以你需要 swprintf_s(szDir, MAX_PATH, L"%s%s*", ...)關於 wcstombs, 它需要配合 C 語言的 locale 介面來使用問題是 setlocale 的設定方式是跟系統相關的那這樣倒不如直接使用所在系統的 API 來做轉換以你的狀況就是 Windows API

Links booklink

Contact Us: admin [ a t ] ucptt.com