Pergunta

Eu quero converter QStrings em nomes de arquivos.Desde que eu gostaria que o nome do arquivo para uma aparência limpa, eu quero substituir todos os não-letras e não números por um carácter de sublinhado.O código a seguir deve fazer isso.

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

No entanto, no meu computador, isso não funciona, eu vejo como uma saída:

�_

Procurando um explentation, depuração me diz que QString("§").size() = 2 > 1 = QString("a").size().

Minhas perguntas:

  • Por que QString usar 2 QChars para "§"?(resolvido)
  • Você tem uma solução para makeFilename?Seria também trabalhar para o povo Chinês?
Foi útil?

Solução

Além disso, para o que os outros disseram, tenha em mente que um QString é um UTF-16 codificado de seqüência de caracteres.Um caractere Unicode que está fora da BMP requer 2 QChar valores trabalho em conjunto, chamado de um par substituto, a fim de codificar caracteres.O QString documentação diz muito:

Caracteres Unicode com código de valores acima de 65535 são armazenados usando pares substitutos, por exemplo, por duas vezes consecutivas QChars.

Você não está levando isso em conta quando um loop através de QString.Você está olhando para cada um QChar individualmente, sem verificar se ele pertence a um par substituto ou não.

Tente isso:

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

Outras dicas

Ok, aqui vai a minha teoria:quando você alimenta o "§" literal para uma QString, Qt usa algum padrão de codificação porque você não definido.Se o seu compilador usa UTF-8 para armazenar literais de seqüência de caracteres, você pode estar alimentando-2 bytes que são convertidos em 2 de caracteres em vez de um.Da mesma forma, o seu "toAscii" a saída mais provável faz a coisa errada também.

A partir do que parece, você vai ter que descobrir o que o compilador usa para armazenar a seqüência de caracteres literais e chamada de setCodecForCStrings com o valor correto.

EDITAR:dada a sua descrição, se eu não sabia que a codificação para o meu compilador, eu provavelmente iria tentar QTextCodec::codecForName("UTF-8") como parâmetro para o setCodec primeiro :-)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top