Domanda

Voglio convertire QStrings in filenames.Dal momento che vorrei che il nome del file fosse pulito, voglio sostituire tutte le non lettere e i non numeri da un sottolineatura.Il seguente codice dovrebbe farlo.

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

Tuttavia, sul mio computer, questo non funziona, ottengo come output:

�_
.

Alla ricerca di un'esplice, il debugging mi dice che QString("§").size()= 2> 1= QString("a").size().

Le mie domande:

    .
  • Perché QString utilizza 2 Qchars per "§"?( Risolto )
  • Hai una soluzione per makeFilename?Lavorerebbe anche per il popolo cinese?
È stato utile?

Soluzione

Oltre a ciò che gli altri hanno detto, tieni presente che un QString è una stringa codificata UTF-16.Un carattere Unicode esterno del BMP richiede 2 valori QChar che lavorano insieme, chiamato una coppia surrogata, per codificare quel carattere. Documentazione QString dice tanto:

.

I caratteri Unicode con valori di codice sopra 65535 sono memorizzati utilizzando coppie surrogate, I.e., due qchar consecutivi.

Non stai prendendo in considerazione quando looping attraverso il QString.Stai guardando ogni QChar singolarmente senza controllare se appartiene a una coppia surrogata o no.

prova questo invece:

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

Altri suggerimenti

OK, ecco la mia teoria: quando si alimenta il "§" Letterale per un QString, QT utilizza una codifica predefinita perché non ne hai impostato uno.Se il compilatore utilizza UTF-8 per memorizzare i letterali delle stringhe, potresti alimentare 2 byte che vengono convertiti in 2 caratteri anziché uno.Allo stesso modo, la tua output "Tascii" molto probabilmente fa la cosa sbagliata anche.

Dall'aspetto di esso, dovrai scoprire cosa usa il tuo compilatore per memorizzare le stringa letterali e chiamare setcodecforcstrings con il valore corretto.

Modifica: Data la descrizione, se non conoscessi la codifica per il mio compilatore, probabilmente proverò a qtextcodec :: codecforname ("utf-8") come parametro sul setcodec prima: -)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top