문제

QString을 파일 이름으로 변환하고 싶습니다.파일 이름이 깔끔하게 보이길 바라기 때문에 문자나 숫자가 아닌 모든 문자를 밑줄로 바꾸고 싶습니다.다음 코드는 이를 수행해야 합니다.

#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개의 QChar를 사용하는 이유는 무엇입니까?(해결됨)
  • 당신은에 대한 솔루션이 있습니까? makeFilename?중국 사람들에게도 효과가 있을까요?
도움이 되었습니까?

해결책

다른 사람들이 말한 것 외에도 다음 사항을 명심하십시오. QString UTF-16으로 인코딩된 문자열입니다.BMP 외부의 유니코드 문자에는 2가 필요합니다. QChar 해당 문자를 인코딩하기 위해 대리 쌍이라고 하는 값이 함께 작동합니다.그만큼 QString 문서 다음과 같이 말합니다.

65535 이상의 코드 값을 가진 유니코드 문자는 서로게이트 쌍, 즉 두 개의 연속 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을 사용하여 문자열 리터럴을 저장하는 경우 1자가 아닌 2자로 변환되는 2바이트를 제공할 수 있습니다.마찬가지로 "toAscii" 출력도 잘못된 작업을 수행할 가능성이 높습니다.

겉으로 보기에는 컴파일러가 문자열 리터럴을 저장하기 위해 무엇을 사용하는지 알아내고 호출해야 합니다. setCodecForCStrings 올바른 값으로.

편집하다:설명을 들었을 때 내 컴파일러의 인코딩을 모른다면 먼저 setCodec에 대한 매개변수로 QTextCodec::codecForName("UTF-8")을 시도해 볼 것입니다. :-)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top