用CString::Left()时,有时最后的汉字是一半,怎么办? 用CString::Left()时,有时最后的汉字是一半,怎么办? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 对于CString 来说一个汉字对应的字符的个数为2个所以你取的时候一定要注意:比如:CString str="中国";你要取中字必须str.Left(2);当取一般的时候你只要把你的left的参数加1就可以了 这个方法不行的,因为我不到字符串里到底是怎么,假如CString str="A中国";,那我取str.Left(2)不是中又成一半吗? 看那个字符的ascii码,如果大于128就是汉字一部分,小于就不是汉字,这样就能区分了吧 foxmail(萧遥)的方法是不行的,这样只能得到读取得字符是汉字还是Ascii码,不能判断是否是汉字的一半。 先全部转化为unicode的._T("")然后再按2倍数找. 在一个英文字母和汉字混合的字符串中区分汉字和英文字符只能从字符串头开始判断,大致可以如下:BYTE *p = string;while(*p = 0){ if (*p == '\r' || *p == '\n'){ //回车符,换行符 } if (*p > 0x80){ p+=2;//汉字 } else{ p++;//英文字符 }} 英文属于单子节编码, 汉字属于多字节编码,国际标准多字结为UNICODE编码,标准之中定义了世界上大部分国家的代码页,一般代码为双字节,第一字节为前导字节表明语种,第二字节为代码页中对应的字符. 我国用的是自己定义的GB码,有些是双字节,有些是多字节,于UNICODE很不一样,其实光凭HEX值,是可以显示任何代码页中的字符的,关键是要和代码页对应上,两个Hex值就可以显示一个汉字. 英文中每一个字符值(大小写)必小于128, 如果你的CString只有两种情况(全英文或全汉字)判断起来比较容易,汉字编码的第一个字节的最高位为1(>128无论是几个字节编码),若是英汉混合的情况,要检出其中一种,稍微麻烦一点,若要处理多国语言,好像有多国语言API函数,可以通过统计的方法检出一直对应的代码页. http://expert.csdn.net/Expert/topic/1251/1251404.xml?temp=.7669794判断所有的值,标准看上面那个帖子。 其实转化为unicode再取也不失为一条捷径 如何转换成Unicode码?CString strText = _T( strChar );//注意:不能 _T("dsd");这样不行的。!! if( (BYTE)str.Left(2) < 0xa1 ){ //半角 .......}else{ //全角 .......} 希望有所帮助将ANSI转换到Unicode(1)通过L这个宏来实现,例如: CLSIDFromProgID( L"MAPI.Folder",&clsid);(2)通过MultiByteToWideChar函数实现转换,例如:char *szProgID = "MAPI.Folder";WCHAR szWideProgID[128];CLSID clsid;long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));szWideProgID[lLen] = '\0'; (3)通过A2W宏来实现,例如: USES_CONVERSION; CLSIDFromProgID( A2W(szProgID),&clsid); 将Unicode转换到ANSI(1)使用WideCharToMultiByte,例如:// 假设已经有了一个Unicode 串 wszSomeString... char szANSIString [MAX_PATH]; WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL ); (2)使用W2A宏来实现,例如:USES_CONVERSION;pTemp=W2A(wszSomeString); 在程序的最开头:#define _UNICODE这样CString是按whar_t来装数据的.同时所有_T()回被解释成L. 这样就是双字节版本了. 好像在codeguru上有这个问题的答案,你自己去找 //记录当前行中汉字字节数,以防止将一半汉字分为两行 unsigned short halfChinese=0; for(int i=0; i<=szString.GetLength()-1; i++){ if(((unsigned char)szString.GetAt(i) == 0x0d) && ((unsigned char)szString.GetAt(i+1) == 0x0a)) theLineLength=0; //大于0xa1的字节为汉字字节 if((unsigned char)szString.GetAt(i) >= 0xA1) halfChinese++; theLineLength++; //如果行宽大于每行最大宽度,进行特殊处理 if(theLineLength > nMaxLineChar) { //防止将一个汉字分为两行,回溯 if(halfChinese%2) { szString.Insert(i,(unsigned char)0x0a); szString.Insert(i,(unsigned char)0x0d); } else { szString.Insert(i-1,(unsigned char)0x0a); szString.Insert(i-1,(unsigned char)0x0d); } theLineLength = 0; } } CString str="中国K美国"; LPCTSTR lpsz=str; CString sLeft; const int nLeft=4; int nIndex=nLeft; LPSTR lp=(LPSTR)lpsz; int nSize=lstrlen(str); while(nIndex--!=0) { lp=::CharNext(lp); } lstrcpyn(sLeft.GetBuffer(lp-lpsz+1) ,lpsz,lp-lpsz+1); sLeft.ReleaseBuffer(); //sLeft="中国K美" 设当前的位置为pos,对应的字符为chif(ch>128)//是汉字的一部分chNext=(pos+1)位置的字符;if(chNext>128)说明pos是汉字的后一个字节,调整pos为pos+1;否则,位置就是pos-----------------------------以上可以用CString 得成员函数find()很容易实现! 我自己写的,效果还不错//检查当前字符串最后一位是否半个汉字BOOL GIsHalfHZ(const CString &str){ int len=str.GetLength(); BOOL IsHalf=FALSE; for(int i=0;i<len;i++) { if(str.GetAt(i) < 0) IsHalf=!IsHalf; } return IsHalf;} : oracle3(kk)我看不大懂,if(str.GetAt(i) < 0) IsHalf=!IsHalf;作何用意? str.GetAt(i)取字符串的一个字符如果一个汉字的话,它的高字节字符和低字节字符都是<0的,如果出现半汉字的情况IsHalf=!IsHalf;必然为FALSE 转换成char * ,然后使用普通的函数如strcpy等 str.GetAt(i)取字符串的一个字符如果一个汉字的话,它的高字节字符和低字节字符都是<0的,如果出现半汉字的情况IsHalf;必然为FALSE-----------不对吧?出现半个汉字的情况应该是IsHalf=TRUE才对阿! 刚才说错了,如果出现半汉字的情况IsHalf;必然为TRUE 先转换成用UNICODE编码后再取。 各位大虾,请问一下,在vc下有没有和vb的AscW函数功能相同或类似的函数或解决方案? oracle3(kk)的方法是不行的,只是在GB2312时基本可以,但是在其他GB编码时,就未必是两个字节都是<0的,据我测试,一个汉字的右面一边的数值未必小于0,但是左面一边的数值的确实小于0的(即最高位为1) 使用 BOOL IsDBCSLeadByte(ch);试试; for(int I=0 ;I < count;I++) { if IsDBCSLeadByte(lpstr[count]) I++;//说明该字节和后面的字节共同组成一个双字节字(如汉字) //因为上面还有一个I++,所以这里I只加1 //注意,必须要从行的开始判断,不然会出现判断错误 } 在GB2312下函数返回真表示含有半个汉字其它判断请参考简体中文:字符集:GB 2312-80代码页:CP 936Lead byte:0xA1 - 0xFETrail byte:0xA1 - 0xFE繁体中文:字符集:BIG-5代码页:CP 950Lead byte:0x81 - 0xFETrail byte:0x40 - 0x7E, 0xA1 - 0xFE日文:字符集:Shift-JIS(Japan Industry Standard)代码页:CP 932Lead byte:0x81 - 0x9E, 0xE0 - 0xFCTrail byte:0x40 - 0xfc (except 0x7F)韩文(Wansung):字符集:KS C-5601-1987代码页:CP 949Lead byte:0x81 - 0xFETrail byte:0x41 - 0x5A, 0x61 - 0x7A, 0x81 - 0xFE 其实用Unicode字符很好的,你Left()时全取偶数,自然就避免半个汉字的问题了。中国人常英汉夹杂,用Unicode字符好像是受鼓励的吧。 DELETEFILE求助 【新手求助】有什么办法能解决定时器消息丢失问题。。 学习VC看完了深入浅出MFC跟着孙鑫的视频学了一遍现在干嘛啊 (非MFC)文本框控件里em_setsel选中的文本 怎么让它有背景颜色! ATL activex中timer如何使用? 如何硬拷贝屏幕上的图形,要什么软件吗?谢谢各位解答,在线等你 为什么我的DrawItem不被调用??? $$$$$$《深入浅出MFC》中对于动态创建对象的解释$$$$$$ 是否可以这样使用数组 一个问题,谢谢 activeSkin问题,有整容经验者请进 如何使窗口的客户区变为非客户区?
比如:
CString str="中国";
你要取中字必须str.Left(2);当取一般的时候你只要把你的left的参数加1就可以了
在一个英文字母和汉字混合的字符串中区分汉字和英文字符只能从字符串头开始判断,大致可以如下:
BYTE *p = string;
while(*p = 0){
if (*p == '\r' || *p == '\n'){
//回车符,换行符
}
if (*p > 0x80){
p+=2;//汉字
}
else{
p++;//英文字符
}
}
我国用的是自己定义的GB码,有些是双字节,有些是多字节,于UNICODE很不一样,
其实光凭HEX值,是可以显示任何代码页中的字符的,关键是要和代码页对应上,两个Hex值就可以显示一个汉字.
英文中每一个字符值(大小写)必小于128, 如果你的CString只有两种情况(全英文或全汉字)判断起来比较容易,汉字编码的第一个字节的最高位为1(>128无论是几个字节编码),若是英汉混合的情况,要检出其中一种,稍微麻烦一点,若要处理多国语言,好像有多国语言API函数,可以通过统计的方法检出一直对应的代码页.
判断所有的值,标准看上面那个帖子。
CString strText = _T( strChar );//注意:不能 _T("dsd");
这样不行的。!!
{
//半角
.......
}
else
{
//全角
.......
}
(1)通过L这个宏来实现,例如: CLSIDFromProgID( L"MAPI.Folder",&clsid);
(2)通过MultiByteToWideChar函数实现转换,例如:
char *szProgID = "MAPI.Folder";
WCHAR szWideProgID[128];
CLSID clsid;
long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));
szWideProgID[lLen] = '\0';
(3)通过A2W宏来实现,例如:
USES_CONVERSION;
CLSIDFromProgID( A2W(szProgID),&clsid); 将Unicode转换到ANSI
(1)使用WideCharToMultiByte,例如:
// 假设已经有了一个Unicode 串 wszSomeString...
char szANSIString [MAX_PATH];
WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL );
(2)使用W2A宏来实现,例如:
USES_CONVERSION;
pTemp=W2A(wszSomeString);
#define _UNICODE
这样CString是按whar_t来装数据的.同时所有_T()回被解释成L. 这样就是双字节版本了.
{
if(((unsigned char)szString.GetAt(i) == 0x0d) &&
((unsigned char)szString.GetAt(i+1) == 0x0a))
theLineLength=0; //大于0xa1的字节为汉字字节
if((unsigned char)szString.GetAt(i) >= 0xA1)
halfChinese++;
theLineLength++; //如果行宽大于每行最大宽度,进行特殊处理
if(theLineLength > nMaxLineChar)
{
//防止将一个汉字分为两行,回溯
if(halfChinese%2)
{
szString.Insert(i,(unsigned char)0x0a);
szString.Insert(i,(unsigned char)0x0d);
}
else
{
szString.Insert(i-1,(unsigned char)0x0a);
szString.Insert(i-1,(unsigned char)0x0d); }
theLineLength = 0;
} }
LPCTSTR lpsz=str;
CString sLeft;
const int nLeft=4;
int nIndex=nLeft;
LPSTR lp=(LPSTR)lpsz;
int nSize=lstrlen(str);
while(nIndex--!=0)
{
lp=::CharNext(lp);
}
lstrcpyn(sLeft.GetBuffer(lp-lpsz+1) ,lpsz,lp-lpsz+1);
sLeft.ReleaseBuffer();
//sLeft="中国K美"
设当前的位置为
pos,对应的字符为ch
if(ch>128)//是汉字的一部分
chNext=(pos+1)位置的字符;
if(chNext>128)
说明pos是汉字的后一个字节,调整pos为pos+1;
否则,位置就是pos
-----------------------------
以上可以用CString 得成员函数find()很容易实现!
//检查当前字符串最后一位是否半个汉字
BOOL GIsHalfHZ(const CString &str)
{
int len=str.GetLength();
BOOL IsHalf=FALSE;
for(int i=0;i<len;i++)
{
if(str.GetAt(i) < 0) IsHalf=!IsHalf;
} return IsHalf;
}
作何用意?
不对吧?出现半个汉字的情况应该是IsHalf=TRUE才对阿!
{
if IsDBCSLeadByte(lpstr[count])
I++;//说明该字节和后面的字节共同组成一个双字节字(如汉字)
//因为上面还有一个I++,所以这里I只加1
//注意,必须要从行的开始判断,不然会出现判断错误
}
其它判断请参考
简体中文:
字符集:GB 2312-80
代码页:CP 936
Lead byte:0xA1 - 0xFE
Trail byte:0xA1 - 0xFE繁体中文:
字符集:BIG-5
代码页:CP 950
Lead byte:0x81 - 0xFE
Trail byte:0x40 - 0x7E, 0xA1 - 0xFE日文:
字符集:Shift-JIS(Japan Industry Standard)
代码页:CP 932
Lead byte:0x81 - 0x9E, 0xE0 - 0xFC
Trail byte:0x40 - 0xfc (except 0x7F)韩文(Wansung):
字符集:KS C-5601-1987
代码页:CP 949
Lead byte:0x81 - 0xFE
Trail byte:0x41 - 0x5A, 0x61 - 0x7A, 0x81 - 0xFE