首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QChar::isLetterOrNumber()失败

QChar::isLetterOrNumber()失败
EN

Stack Overflow用户
提问于 2012-10-03 14:22:36
回答 2查看 739关注 0票数 0

我想把QStrings转换成文件名。因为我希望文件名看起来很干净,所以我想用下划线替换所有的非字母和非数字。下面的代码应该这样做。

代码语言:javascript
复制
#include <iostream>
#include <QString>

QString makeFilename(const QString& title)
{
    QString result;
    for(QString::const_iterator itr = title.begin(); itr != title.end(); itr++)
     result.push_back(itr->isLetterOrNumber()?itr->toLower():'_');
    return result;
}

int main()
{
    QString str = "§";
    std::cout << makeFilename(str).toAscii().data() << std::endl;
}

但是,在我的计算机上,这是不工作的,我得到了一个输出:

代码语言:javascript
复制
�_

为了找到解释,调试告诉我QString("§").size() =2>1= QString("a").size()

我的问题:

  • 为什么QString在"§“中使用2 QChars?(解决了)
  • 您有makeFilename的解决方案吗?这对中国人也有好处吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-03 21:24:33

除了其他人所说的,请记住QString是一个UTF-16编码字符串。在BMP之外的Unicode字符需要两个QChar值一起工作,称为代理项对,以便对该字符进行编码。QString文档也这么说:

代码值大于65535的Unicode字符使用代理项对存储,即两个连续的QChars。

在循环遍历QString时,没有考虑到这一点。您正在单独查看每个QChar,而不检查它是否属于代理项对。

试一试:

代码语言:javascript
复制
QString makeFilename(const QString& title) 
{ 
    QString result; 

    QString::const_iterator itr = title.begin();
    QString::const_iterator end = title.end();

    while (itr != end)
    {
        if (!itr->isHighSurrogate())
        {
            if (itr->isLetterOrNumber())
            {
                result.push_back(itr->toLower()); 
                ++itr;
                continue;
            }
        }
        else
        {
            ++itr;
            if (itr == end)
                break; // error - missing low surrogate

            if (!itr->isLowSurrogate())
                break; // error - not a low surrogate

            /*
            letters/numbers should not need to be surrogated,
            but if you want to check for that then you can use
            QChar::surrogateToUcs4() and QChar::category() to
            check if the surrogate pair represents a Unicode
            letter/number codepoint...

            uint ch = QChar::surrogateToUcs4(*(itr-1), *itr);
            QChar::Category cat = QChar::category(ch);
            if (
                ((cat >= QChar::Number_DecimalDigit) && (cat <= QChar::Number_Other)) ||
                ((cat >= QChar::Letter_Uppercase) && (cat <= QChar::Letter_Other))
                )
            {
                result.push_back(QChar(ch).toLower()); 
                ++itr;
                continue;
            }
            */
        }

        result.push_back('_');
        ++itr; 
    }

    return result; 
} 
票数 1
EN

Stack Overflow用户

发布于 2012-10-03 15:35:17

好的,下面是我的理论:当您将"§“文本提供给QString时,Qt使用一些默认编码,因为您没有设置它。如果您的编译器使用UTF-8来存储字符串文本,那么您可能要给它添加2个字节,这些字节被转换成2个字符,而不是一个字符。同样,您的"toAscii“输出也很可能做错了事情。

从它的外观来看,您必须找出编译器用于存储字符串文本的内容,并使用正确的值调用setCodecForCStrings

编辑:给定您的描述,如果我不知道编译器的编码,我可能会尝试使用QTextCodec::codecForName("UTF-8")作为setCodec的参数(首先:-)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12710528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档