• 15220阅读
  • 25回复

[讨论]QString的Bug。length、size、count均错误。 [复制链接]

上一主题 下一主题
离线qdxianxing
 
只看楼主 倒序阅读 楼主  发表于: 2012-04-30
QString s="我𠇾你吗";
你们猜猜s.length()是多少?

答案上5。
离线jdwx

只看该作者 1楼 发表于: 2012-04-30
设置QTextCodec了吗?
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线qdxianxing
只看该作者 2楼 发表于: 2012-04-30
引用第1楼jdwx于2012-04-30 08:33发表的  :
设置QTextCodec了吗?

设置了,我代码用的是UTF8。
离线qdxianxing
只看该作者 3楼 发表于: 2012-04-30
引用第1楼jdwx于2012-04-30 08:33发表的  :
设置QTextCodec了吗?

我把这个中文字符串“我𠇾你吗”,最终在我的QToolButton里显示,能正确显示。

所以,QTextCodec已经正确设置。



“𠇾”是生僻字,在UTF16编码中,是占4字节的字符,因此,需要把QT的代码编写器的字体格式,设置为"SimSun-Extb",才能正确显示。

当然,代码中也要加入:
  QFont f("SimSun-Extb");
    app.setFont(f);

这段字符,才能在QToolButton上正确显示。

离线qdxianxing
只看该作者 4楼 发表于: 2012-04-30
没有人遇到这种问题?
离线jdwx

只看该作者 5楼 发表于: 2012-04-30
确实没遇到,估计是水土不服的原因。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线qdxianxing
只看该作者 6楼 发表于: 2012-04-30
引用第5楼jdwx于2012-04-30 10:01发表的  :
确实没遇到,估计是水土不服的原因。



你能否按照下面的步骤,帮我试试看?



首先,把QT-Creator的代码编写器的字体,设置为"SimSun-Extb",然后,创建一个utf8编码的qt工程(即那些cpp和h的编码都是utf8的)。

(注:上面两步,要先做)

最后,来看看下面例子:

int main(int argc,char*argv[])
{
QApplication app(argc,argv);
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf-8"));
QFont f("SimSun-Extb");
app.setFont(f);

QString s="他𡆮";

QWidget w;
QPushButton pb(&w);
pb.setText(s);
w.setWindowTitle(QString::number(s.length()));      //最终显示是3个,正确应该是2个。

w.resize(300,300);
w.show();

return app.exec();
}

如何才能正确统计,一个QString里到底有多少个unicode字符?
离线qdxianxing
只看该作者 7楼 发表于: 2012-04-30
我的意思是:
qstring.length(),返回的,根本不是qstring里的字符个数。

它返回的是“字节数/2”。
离线qdxianxing
只看该作者 8楼 发表于: 2012-04-30
6楼的例子,够详细了吧?
离线roywillow

只看该作者 9楼 发表于: 2012-04-30
回 7楼(qdxianxing) 的帖子
QString的length应该与字节数无关
因为QString不是以char为单位,而是QChar,可以当做QChar的一个容器
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线qdxianxing
只看该作者 10楼 发表于: 2012-04-30
Re:回 7楼(qdxianxing) 的帖子
引用第9楼roywillow于2012-04-30 12:46发表的 回 7楼(qdxianxing) 的帖子 :
QString的length应该与字节数无关
因为QString不是以char为单位,而是QChar,可以当做QChar的一个容器

要知道,QChar是2个字节,

所以,length==QChar数==字节数/2

也就是与字节数相关了。
离线dbzhang800

只看该作者 11楼 发表于: 2012-04-30
引用第7楼qdxianxing于2012-04-30 10:55发表的  :
我的意思是:
qstring.length(),返回的,根本不是qstring里的字符个数。
它返回的是“字节数/2”。

嗯,只能说明Manual中说的不够清楚,不过个人不觉得这是个大问题。

QString中存放的是utf16字符串,即

char16_t * (如果编译器支持C++11)

wchar_t * (如果wchar_t是16位,比如MSVC)

unsigned short *

而 length 返回是这种字符流中的“字符”数目。

进一步说,如果QString真的提供的是unicode字符数,反而会使大家非常郁闷。比如说,你要接受或者拷贝一个 wchar_t* 的字符数组,此时大小?。比如:我们都知道Windows系统内部都是UTF16,你如何把那四个字符传递给它呢,不还是要 5 个 wchar_t 么?
离线qdxianxing
只看该作者 12楼 发表于: 2012-04-30
引用第11楼dbzhang800于2012-04-30 13:11发表的  :
嗯,只能说明Manual中说的不够清楚,不过个人不觉得这是个大问题。
QString中存放的是utf16字符串,即
.......

但是,有一个细节你没有注意到:

UTF-16是变长编码,虽然大部分字符都是2个字节,但,有些字符是4个字节的。

例如:
QString s="𠇾";

按常理,s.length()应该是1。
但是,你可以试试看,输出s.length()却是2。




离线qdxianxing
只看该作者 13楼 发表于: 2012-04-30
引用第11楼dbzhang800于2012-04-30 13:11发表的  :
嗯,只能说明Manual中说的不够清楚,不过个人不觉得这是个大问题。
QString中存放的是utf16字符串,即
.......

我觉得你有一点说得不对,你说:“ length 返回是这种字符流中的“字符”数目”。

其实不是。
离线dbzhang800

只看该作者 14楼 发表于: 2012-04-30
引用第12楼qdxianxing于2012-04-30 13:21发表的  :
但是,有一个细节你没有注意到:
UTF-16是变长编码,虽然大部分字符都是2个字节,但,有些字符是4个字节的。
.......

我前面说的就是这个 ;-) ,如果真是1的话,会让人非常郁闷。
离线dbzhang800

只看该作者 15楼 发表于: 2012-04-30
引用第13楼qdxianxing于2012-04-30 13:24发表的  :
我觉得你有一点说得不对,你说:“ length 返回是这种字符流中的“字符”数目”。
其实不是。


所以我加了引号,代码 char16_t 或 wchar_t "字符"的个数。
离线qdxianxing
只看该作者 16楼 发表于: 2012-04-30
引用第14楼dbzhang800于2012-04-30 13:24发表的  :
我前面说的就是这个 ;-) ,如果真是1的话,会让人非常郁闷。



为什么会让人非常郁闷呢?

那么,有没有办法,获知QString里到底有多少个真实的“unicode字符”?

离线qdxianxing
只看该作者 17楼 发表于: 2012-04-30
引用第15楼dbzhang800于2012-04-30 13:26发表的  :
所以我加了引号,代码 char16_t 或 wchar_t "字符"的个数。


现在我的最终问题就是,

QString s="𠇾";那么,s.length()==2。
QString s="我";那么,s.length()==1。

那我到底怎么才能知道,qstring里,到底有多少个真实的“unicode字符”?

离线roywillow

只看该作者 18楼 发表于: 2012-04-30
总感觉讨论一个类有多少个字节很奇怪呢……为什么说QChar是“2个字节”呢?
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线qdxianxing
只看该作者 19楼 发表于: 2012-04-30
引用第18楼roywillow于2012-04-30 13:35发表的  :
总感觉讨论一个类有多少个字节很奇怪呢……为什么说QChar是“2个字节”呢?

不是说一个类有多少个字节,而是说,QString里的编码内容,有多少个字节。

sizeof(QChar)==2。
离线roywillow

只看该作者 20楼 发表于: 2012-04-30
你所说的那些字符是不是也需要用两个QChar来编码呢?
如果是这样的话,不就跟过去经常纠结的char*里中英文混排后该怎么获得字符数一样的问题了么
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线qdxianxing
只看该作者 21楼 发表于: 2012-04-30
引用第20楼roywillow于2012-04-30 14:00发表的  :
你所说的那些字符是不是也需要用两个QChar来编码呢?
如果是这样的话,不就跟过去经常纠结的char*里中英文混排后该怎么获得字符数一样的问题了么

是啊,那些是要用两个QCchar来编码的,而有些,则只需要一个QChar。

那有什么办法吗?
离线qdxianxing
只看该作者 22楼 发表于: 2012-04-30
引用第11楼dbzhang800于2012-04-30 13:11发表的  :
嗯,只能说明Manual中说的不够清楚,不过个人不觉得这是个大问题。
QString中存放的是utf16字符串,即
.......

我明白你的意思了。

QString.length()返回wchar_t的数目,当然在很多场合是有用的。

但,我希望知道unicode字符数目,也是有用的。

我现在,希望能统计,到底有多少个unicode字符在QString里。有没有办法做到?





离线roywillow

只看该作者 23楼 发表于: 2012-04-30
回 21楼(qdxianxing) 的帖子
我觉得应该参考c串获取实际字符数的方法,如果实际上存在的话
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线dbzhang800

只看该作者 24楼 发表于: 2012-05-01
引用第22楼qdxianxing于2012-04-30 18:06发表的  :
我明白你的意思了。
QString.length()返回wchar_t的数目,当然在很多场合是有用的。
但,我希望知道unicode字符数目,也是有用的。
我现在,希望能统计,到底有多少个unicode字符在QString里。有没有办法做到?
.......


当然,你直接 QString::toUcs4 () ,然后得到 char32_t 数组,此时的大小就不会有歧义了。
离线qdxianxing
只看该作者 25楼 发表于: 2012-05-01
引用第24楼dbzhang800于2012-05-01 04:06发表的  :
当然,你直接 QString::toUcs4 () ,然后得到 char32_t 数组,此时的大小就不会有歧义了。




我后来找到了一个很好的方法:

QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme,str);
int c=0;
while(tbf.toNextBoundary()!=-1)
{
    c++;
}

c就是真实的QString里的“unicode字符”的数目。(即使里面字符编码,有些占4字节,有些站2字节,都是能正确统计的。)
快速回复
限100 字节
 
上一个 下一个