日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

VC2005字符集设置容易出错的问题!

發(fā)布時(shí)間:2024/8/1 c/c++ 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VC2005字符集设置容易出错的问题! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

微軟托管環(huán)境已經(jīng)出來好多年了,作為非托管環(huán)境下運(yùn)行的VC,雖然它的編程效率比托管編程低多了,但是它能生存到今天,也足見它的強(qiáng)大

但是VC使用比起.net Framework來確實(shí)比較難,常常令有經(jīng)驗(yàn)的軟件工程師也耗費(fèi)大量的時(shí)間。最近由于一個(gè)小小的環(huán)境設(shè)置設(shè)置問題花了很多時(shí)間,這跟用慣了VC6突然轉(zhuǎn)到VC2005有關(guān),寫出來讓大家參考參考

一。字符集設(shè)置不同系統(tǒng)調(diào)用的函數(shù)也不同

我不知道VC.net2005默認(rèn)工程默認(rèn)設(shè)置是采用“Unicode字符集”(Unicode Character Set)的,以前用VC6工程的時(shí)候默認(rèn)是“多字符集”(Multi-Byte Character Set)的。

我聲明了一個(gè)CString,按計(jì)劃給它賦值,就像下面:

CString s;

s.Format(“count = %d”,count);

如果是采用Multi-Byte Character Set不會有錯(cuò)誤的,因?yàn)檫@是我的環(huán)境采用的Unicode字符集的,而我給CStringFormat函數(shù)是“多字符集”(Multi-Byte)所以編譯不通過,要知道在這種設(shè)置下使用MessageBox(“ddd”);編譯是不會通過的,因?yàn)橄到y(tǒng)調(diào)用的是MessageBoxW,即Unicode寬字符集的那個(gè)函數(shù)。

根據(jù)編譯器的提示把s.Format(“count = %d”,count);改成s.Format(_T(“count = %d”,count);就搞定了,_T代表一個(gè)宏,宏的意思就是把字符串轉(zhuǎn)成寬字符表示。同樣的,MessageBox(“ddd”);可以為MessageBox(_T(“ddd”));

但是還有個(gè)問題就是,所有窗體顯示的東西都是寬字符的,例如a在內(nèi)存里就是a/0兩個(gè)字節(jié),前面一個(gè)字節(jié)a后面是/0,當(dāng)從窗體取下數(shù)據(jù)(例如用戶輸入)要跟其他平臺交互時(shí),例如網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)端機(jī)器。如果那邊使用的不是Unicode字符集,就會出問題,為了使界面和后臺傳輸一致,只好使用把寬字符轉(zhuǎn)換成多字符集表示:

CString strWideChar;

strWideChar.Format(_T(“這是寬字節(jié)哦”));

char buf[20];

???? memset(buf,0,20);

???? WideCharToMultiByte(? //轉(zhuǎn)換UnicodeAnsi

????????? CP_ACP,

????????? WC_COMPOSITECHECK | WC_DEFAULTCHAR,

????????? strWideChar,

????????? strWideChar.GetLength(),

????????? (char *)buf,? //轉(zhuǎn)換到緩沖區(qū)中

????????? 20,? //最多個(gè)字節(jié)

????????? 0,

????????? 0

???? );

同樣的,你接收到的字符串想要在界面正常顯示,還必須把它轉(zhuǎn)換成寬字節(jié)表示:

char chBytes[8];

memcpy(chBytes,aaaaaaa/ 0,8);

WCHAR wch[9];

n = MultiByteToWideChar( //轉(zhuǎn)換UnicodeAnsi

???? CP_ACP,

???? 0,

???? chBytes,

???? 8,

???? wch,? //轉(zhuǎn)換到緩沖區(qū)中

???? 8? //最多個(gè)字節(jié)

);

wch[n] = '/0';

這樣每次從界面取數(shù)據(jù)和把數(shù)據(jù)顯示到界面上都要先做處理,但是也可以把編譯環(huán)境設(shè)置成“多字符集”(Multi-Byte Character Set),就可以避免這樣轉(zhuǎn)換來轉(zhuǎn)換去。就是在Project->Configuration Properties->General->Character Set,選擇“Use Unicode Character Set”就是使用Uncode字符集,選擇 Use Multi-Byte Character Set就是多字節(jié)字符集。

二。字符集設(shè)置造成函數(shù)調(diào)用的失敗

我在CodeProject上找了一個(gè)很厚道的老外寫的一個(gè)繼承了CDialog窗體類CResizableDialog的源碼,這個(gè)類的作用是使MFC的窗體放大縮小時(shí),窗體上的控件可以定位(Auchor),不要小看這個(gè)小小的每天都要用到的功能,用MFC實(shí)現(xiàn)真的很麻煩。很佩服那個(gè)老外寫了那么多代碼。

我拿了那個(gè)現(xiàn)成的工程,直接在我的工程里引用他的工程。Everything works perfect。直到我把項(xiàng)目發(fā)布成Release的,雙擊運(yùn)行后沒有任何反應(yīng),Very weird!后來我用MessageBox打印消息,發(fā)現(xiàn)運(yùn)行到DoModal函數(shù)里面就沒有出來,程序直接退出了!使用trycatch都得不到錯(cuò)誤!因?yàn)槲业拇绑w是繼承老外寫的窗體類來的,原先繼承CDialog是好好的,問題肯定在他的工程里面,可是他給的示例程序沒有任何問題啊。

我又拿一個(gè)前的測試程序,讓它從CResizableDialog繼承,也沒有任何問題。

一時(shí)間不知道哪里出現(xiàn)了問題,Release又不能像Debug那樣調(diào)試,打了一堆MessageBox后還是不知道問題出現(xiàn)在哪里。憑著經(jīng)驗(yàn),可以知道程序中可能出現(xiàn)了內(nèi)存的越界訪問什么的致命錯(cuò)誤,才會導(dǎo)致程序“一聲不吭”地退出,但是究竟哪里出了問題呢?

就在束手無策的時(shí)候,我發(fā)現(xiàn)調(diào)用CResizableDialog的成員函數(shù)EnableSaveRestore會引發(fā)鏈接錯(cuò)誤:“未定義的外部符號”,不引用它不會出錯(cuò),測試程序引用它沒有任何錯(cuò)誤。通常這個(gè)錯(cuò)誤造成是因?yàn)橐煤瘮?shù)在.h文件里聲明了,但是在.cpp里面沒有定義,或者.cpp文件里的定義和.h上的函數(shù)簽名不一樣。但是此時(shí)不可能是這個(gè)錯(cuò)誤,因?yàn)闇y試程序沒有錯(cuò)誤啊。直覺告訴我這是解決“Release后程序直接退出的關(guān)鍵”,說不定這個(gè)函數(shù)調(diào)用的問題解決了Release的問題也解決了。

既然調(diào)用EnableSaveRestore出現(xiàn)了不該出現(xiàn)的錯(cuò)誤,那么就從這個(gè)函數(shù)開始找。這個(gè)函數(shù)是這樣的:

.h文件聲明

void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE);

.cpp文件定義

void CResizableDialog::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly/* = FALSE */)

{

?????? m_sSection = pszSection;

?????? m_bEnableSaveRestore = TRUE;

?????? m_bRectOnly = bRectOnly;

?????? // restore immediately

?????? LoadWindowRect(pszSection, bRectOnly);

}

上面的代碼沒有任何錯(cuò)誤,既然沒有錯(cuò)誤,就要用使用以下方法來找:

1.重新為CResizableDialog寫一個(gè)函數(shù),它沒有參數(shù)的,調(diào)用它,發(fā)現(xiàn)沒有錯(cuò)誤,看來參數(shù)有問題。

2.既然沒有參數(shù)的函數(shù)沒有錯(cuò)誤,就把出問題的函數(shù)參數(shù)去掉吧,竟然也沒有錯(cuò)誤!那問題就肯定是出在參數(shù)上。

3.去掉其中一個(gè)參數(shù),測試發(fā)現(xiàn)是LPCTSTR pszSection的問題,而不是BOOL bRectOnly的問題。

4.既然這樣,那就換一種表示吧,把LPCTSTR pszSection換成WCHAR* pszSection,運(yùn)行它,竟然不出錯(cuò)了!翻開MFC宏定義,就會發(fā)現(xiàn)其實(shí)LPCTSTRWCHAR*是一樣的

5.但是這個(gè)函數(shù)功能還是不正常,斷點(diǎn)進(jìn)入那個(gè)函數(shù)里面發(fā)現(xiàn)傳進(jìn)去的字符串只有一個(gè)字符了,這種情況就是寬字符當(dāng)成短字符時(shí),第二個(gè)字節(jié)的/0當(dāng)成了字符串的截止字符了,也就是說,這個(gè)函數(shù)里采用的是短字符(多字符集Multi Byte)處理的。

6.我的工程采用的是寬字符集(Unicode Char)的,檢查設(shè)置,原來那個(gè)老外是用VC6編的,默認(rèn)是使用多字符集(Multi Byte)的,VC真是笨啊,兩個(gè)Project在一個(gè)Solution里面完全不同的設(shè)置竟然沒有任何提示,簡直把我弄死了!

7.把引用工程也改成使用Unicode字符集,并且把函數(shù)EnableSaveRestore WCHAR* pszSection恢復(fù)原樣,搞定!果然不出我所料,Release也沒有問題了!

看來VC排錯(cuò)需要 一點(diǎn)技巧啊。

總結(jié)

以上是生活随笔為你收集整理的VC2005字符集设置容易出错的问题!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。