最近在帮公司一个小孩看一个很奇怪的bug,是MFC 的一个小GUI,在客户环境上一个输入框中的数据总是有乱码,导致从数据库中查不出数据。但是奇怪的是在我们环境上重现不了,因为我们的测试环境用的是Win XP, 客户环境上用的是Win7(我们一开始就没想到过跟不同的操作系统有关)。最开始我们都是怀疑是code在转换UTF8的时候出的错,可是根据给客户的debug版本否定了我们这种猜测,因为我们发现在转换之前debug打印出来的字符串就已经是错误的了。如下图所示:
奇怪的这个字符串就是直接从界面的输入框中得到。先看一下code吧:
TCHAR szAccountNo[GAL_TICKLER_ACCT_LEVEL_EXTERNAL_ID_LEN];
m_eAccountNo.GetLine(0,szAccountNo, GAL_TICKLER_ACCT_LEVEL_EXTERNAL_ID_LEN );
CString szAcctno= szAccountNo;
szAcctno =ArbI18N::translateToUTF8(szAcctno);
我们在调用translateToUTF8之前加了一处debug信息,就是上图显示的account_no的字符串,这时它已经是有乱码的了,也就是说字符串从GetLine()这个函数获得结果就是含有乱码的。这个问题困住了我们一时,百思不得其解。但是强大的stackoverflow又帮助我们解决了这个问题。
分析如下:
因为Getline()return value is the number of bytes actually copied. But the copied line doesnot contain a null-termination character.
See : https://msdn.microsoft.com/en-us/library/7775836w.aspx
解决方案:(我们所采用的)
因为没有null-terminationcharacter 导致乱码的生成,但是返回值却又明确了字节的个数,所以我们可以用这个返回值来确定我们赋值给字符串的时候拷贝几个字节。修改如下:
TCHAR szAccountNo[GAL_TICKLER_ACCT_LEVEL_EXTERNAL_ID_LEN];
int AccountLen = m_eAccountNo.GetLine(0,szAccountNo, GAL_TICKLER_ACCT_LEVEL_EXTERNAL_ID_LEN );
CString szAcctno= CString (szAccountNo,AccountLen);
szAcctno =ArbI18N::translateToUTF8(szAcctno);
当然,这只是其中一种办法,其他解决方案和详细的分析相关链接:
http://stackoverflow.com/questions/5637153/ceditgetline-windows-7
http://stackoverflow.com/questions/10645171/ceditgetline-mfc-vc6-returns-extra-characters-in-windows-7