سؤال

النظر في التعليمات البرمجية التالية:

#include <string>
#include <fstream>
#include <iomanip>

int main() {
    std::string s = "\xe2\x82\xac\u20ac";
    std::ofstream out("test.txt");
    out << s.length() << ":" << s << std::endl;
    out << std::endl;
    out.close();
}

تحت دول مجلس التعاون الخليجي 4.8 على لينكس (أوبونتو 14.04) ، الملف test.txt يحتوي على هذا:

6:€€

تحت البصرية ج 2 2013 على ويندوز ، فإنه يحتوي على هذا:

4:€\x80

(بواسطة '\ س 80 ' أعني حرف 8 بت واحد 0 80).

لقد كنت غير قادر تماما على الحصول على أي مترجم لإخراج الحرف باستخدام std::wstring.

سؤالان:

  • ماذا بالضبط مترجم مايكروسوفت يعتقدون انها تفعل مع char* حرفي?من الواضح أنه يفعل شيئا لتشفيره ، ولكن ما هو غير واضح.
  • ما هي الطريقة الصحيحة لإعادة كتابة التعليمات البرمجية أعلاه باستخدام std::wstring و std::wofstream بحيث مخرجات اثنين الشخصيات?
هل كانت مفيدة؟

المحلول

هذا لأنك تستخدم \u20ac وهو حرف يونيكود الحرفي في سلسلة أسي.

مسفك ترميز "\xe2\x82\xac\u20ac" كما 0xe2, 0x82, 0xac, 0x80, وهو 4 أحرف ضيقة.إنه يشفر بشكل أساسي \u20ac كما 0 * 80 لأنه تعيين حرف اليورو إلى المعيار 1252 كوديباج

دول مجلس التعاون الخليجي هو تحويل يونيكود الحرفي /u20ac إلى تسلسل أوتف-8 3 بايت 0xe2, 0x82, 0xac وبالتالي فإن السلسلة الناتجة ينتهي كما 0xe2, 0x82, 0xac, 0xe2, 0x82, 0xac.

إذا كنت تستخدم std::wstring = L"\xe2\x82\xac\u20ac" يحصل المشفرة بواسطة مسفك كما 0xe2, 0x00, 0x82, 0x00, 0xac, 0x00, 0xac, 0x20 وهو 4 أحرف واسعة ، ولكن منذ كنت خلط أوتف-8 التي تم إنشاؤها يدويا مع أوتف-16 ، سلسلة الناتجة لا معنى له.إذا كنت تستخدم std::wstring = L"\u20ac\u20ac" يمكنك الحصول على 2 أحرف يونيكود في سلسلة واسعة كما كنت تتوقع.

المشكلة التالية هي أن مسفك أوفستريم و وفستريم الكتابة دائما في أنسي / أسي.للحصول عليه للكتابة في أوتف-8 يجب عليك استخدام <codecvt> (مقابل 2010 أو في وقت لاحق):

#include <string>
#include <fstream>
#include <iomanip>
#include <codecvt>

int main()
{
    std::wstring s = L"\u20ac\u20ac";

    std::wofstream out("test.txt");
    std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
    out.imbue(loc);

    out << s.length() << L":" << s << std::endl;
    out << std::endl;
    out.close();
}

وكتابة أوتف-16 (أو بشكل أكثر تحديدا أوتف-16 لي):

#include <string>
#include <fstream>
#include <iomanip>
#include <codecvt>

int main()
{
    std::wstring s = L"\u20ac\u20ac";

    std::wofstream out("test.txt", std::ios::binary );
    std::locale loc(std::locale::classic(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>);
    out.imbue(loc);

    out << s.length() << L":" << s << L"\r\n";
    out << L"\r\n";
    out.close();
}

ملاحظة:مع أوتف-16 لديك لاستخدام وضع ثنائي بدلا من وضع النص لتجنب الفساد ، لذلك لا يمكننا استخدام std::endl ويجب أن تستخدم L"\r\n" للحصول على سلوك الملف النصي الصحيح في نهاية السطر.

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