我想将QStrings转换为文件名。由于我希望文件名看起来干净,我想用下划线替换所有非字母和非数字。下面的代码应该做到这一点。

#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;
}

但是,在我的电脑上,这不起作用,我得到作为输出:

�_

寻找一个解释,调试告诉我, QString("§").size() = 2 > 1 = QString("a").size().

我的问题:

  • 为什么QString为"§"使用2个QChars?(解决了)
  • 你有解决方案吗? makeFilename?这对中国人也有效吗?
有帮助吗?

解决方案

除了别人所说的,请记住,一个 QString 是UTF-16编码的字符串。BMP之外的Unicode字符需要2 QChar 值一起工作,称为代理对,以便对该字符进行编码。该 QString文档 说的一样多:

代码值超过65535的Unicode字符使用代理项对存储,即两个连续的Qchar。

当你循环浏览时,你没有考虑到这一点。 QString.你正在看着每一个 QChar 单独不检查它是否属于代理对。

试试这个吧:

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; 
} 

其他提示

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

从它的外观来看,你必须找出你的编译器用来存储字符串文字的东西,并调用 n.线束,线束 用正确的值。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top