سؤال

أريد تحويل 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;
}

ومع ذلك، على جهاز الكمبيوتر الخاص بي، لا يعمل هذا، أحصل على النتيجة:

�_

أبحث عن Explentation، وتصحيح الأخطاء يقول لي ذلك QString("§").size() = 2 > 1 = QString("a").size().

أسئلتي:

  • لماذا يستخدم QString 2 QChars لـ "§"؟(تم حلها)
  • هل لديك حل ل makeFilename؟هل سينجح الأمر أيضًا مع الشعب الصيني؟
هل كانت مفيدة؟

المحلول

بالإضافة إلى ما قاله الآخرون، ضع في اعتبارك أن أ QString هي سلسلة مشفرة UTF-16.يتطلب حرف Unicode الموجود خارج BMP 2 QChar القيم التي تعمل معًا، تسمى الزوج البديل، من أجل تشفير هذا الحرف.ال وثائق QString يقول بقدر:

يتم تخزين أحرف Unicode ذات قيم رمزية أعلى من 65535 باستخدام أزواج بديلة، أي اثنين من 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; 
} 

نصائح أخرى

حسنًا، هذه هي نظريتي:عند تغذية "§" حرفيًا إلى QString، يستخدم Qt بعض الترميز الافتراضي لأنك لم تقم بتعيينه.إذا كان المترجم الخاص بك يستخدم UTF-8 لتخزين سلسلة حرفية، فربما تقوم بتغذيته ببايتين يتم تحويلهما إلى حرفين بدلاً من حرف واحد.وبالمثل، من المرجح أن يؤدي إخراج "toAscii" إلى حدوث خطأ أيضًا.

من مظهره، سيتعين عليك معرفة ما يستخدمه برنامج التحويل البرمجي الخاص بك لتخزين سلسلة حرفية، واستدعاء setCodecForCStrings بالقيمة الصحيحة.

يحرر:نظرًا لوصفك، إذا لم أكن أعرف ترميز برنامج التحويل البرمجي الخاص بي، فمن المحتمل أن أحاول QTextCodec::codecForName("UTF-8") كمعلمة لـ setCodec أولاً :-)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top