QCHAR :: isletterOnumber()は失敗しました
質問
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 documentation
65535を超えるコード値を持つUnicode文字は、代理ペア、すなわち2つの連続するQCHARSを使用して保存されます。
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;
}
. 他のヒント
OK、私の理論: "←"リテラルをqstringにフィードすると、qtは一つを設定しなかったため、デフォルトのエンコーディングを使用します。CompilerがUTF-8を使用して文字列リテラルを保存している場合は、1文字ではなく2文字に変換される2バイトに給紙している可能性があります。同様に、あなたの「Toascii」の出力も最も間違ったことをする可能性があります。
その外観から、コンパイラが文字列リテラルを保存するために使用するものを見つけて、 setCodecForcStrings 正しい値です。
編集:あなたの説明を考えると、私が私のコンパイラのエンコーディングがわからなかった場合、私はおそらくqtextcodec :: codecforname( "UTF-8")をsetcodec first: - )