Question

Je veux convertir QStrings dans les noms de fichiers.Depuis que j'aimerais le nom de fichier à l'air propre, je veux remplacer tous les non-lettres et non des nombres par un trait de soulignement.Le code suivant devrait le faire.

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

Cependant, sur mon ordinateur, cela ne fonctionne pas, j'obtiens en sortie:

�_

Vous cherchez un explentation, le débogage me dit que QString("§").size() = 2 > 1 = QString("a").size().

Mes questions:

  • Pourquoi ne QString utiliser 2 QChars pour "§"?(résolu)
  • Avez-vous une solution pour makeFilename?Serait-il aussi travailler pour le peuple Chinois?
Était-ce utile?

La solution

En plus de ce que les autres ont dit, gardez à l'esprit qu'un QString est codé en UTF-16 de la chaîne.Un caractère Unicode qui est à l'extérieur de la BMP nécessite 2 QChar les valeurs de travailler ensemble, appelé une paire de substitution, afin de coder les caractères.L' QString documentation comme le dit bien:

Caractères Unicode avec des valeurs de code ci-dessus 65535 sont stockées à l'aide de paires de substitution, c'est à dire, deux fois de suite QChars.

Vous n'êtes pas prendre en compte lors de la boucle par le QString.Vous êtes à la recherche à chaque QChar individuellement, sans vérifier s'il appartient à une paire de substitution ou pas.

Essayez plutôt ceci:

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

Autres conseils

Ok, voici ma théorie:si vous nourrissez le "§" littérale d'un QString, Qt utilise le codage par défaut parce que vous n'avez pas défini une.Si votre compilateur utilise UTF-8 pour stocker les littéraux de chaîne, vous pourriez être de le nourrir 2 octets qui sont converties en 2 caractères au lieu d'un.De même, votre "toAscii" sortie le plus probable n'est pas une bonne chose aussi.

Apparemment, vous aurez à trouver ce que votre compilateur utilise pour stocker les littéraux de chaîne, et d'appeler setCodecForCStrings avec la valeur correcte.

EDIT:compte tenu de votre description, si je ne connaissais pas l'encodage de mon compilateur, je serais probablement essayer QTextCodec::codecForName("UTF-8") en tant que paramètre à la setCodec premier :-)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top