سؤال

أنا أكتب غلاف صغير لتطبيق يستخدم الملفات كوسائط.

يجب أن يكون Wrapper في Unicode، لذلك أنا أستخدم Wchar_T للحصول على الشخصيات والسلاسل لدي. الآن أجد نفسي في مشكلة، أحتاج إلى حجج البرنامج في مجموعة من wchar_t's وفي سلسلة wchar_t.

هل هو ممكن؟ أنا أعرف main وظيفة

int main(int argc, char *argv[])

يجب أن أستخدم wchar_t ل argv?

شكرا جزيلا لك، لا يبدو لي أن أجد معلومات مفيدة حول كيفية استخدام Unicode بشكل صحيح في C.

هل كانت مفيدة؟

المحلول

بشكل عام، لا. سيعتمد على O / S، لكن المعيار C يقول أن الحجج إلى "الرئيسية ()" يجب أن تكون "الرئيسية (int argc، archv)" أو ما يعادلها، لذلك ما لم تكن شار و wchar_t هي نفس النوع الأساسي ، لا يمكنك أن تفعل ذلك.

بعد القول أنه يمكنك الحصول على سلاسل وسيطة UTF-8 في البرنامج، وتحويلها إلى UTF-16 أو UTF-32، ثم استمر في الحياة.

على جهاز Mac (10.5.8، ليوبارد)، حصلت على:

Osiris JL: echo "ï€" | odx
0x0000: C3 AF E2 82 AC 0A                                 ......
0x0006:
Osiris JL: 

هذا كل شيء UTF-8 المشفرة. (odx هو برنامج تفريغ عرافة).

أنظر أيضا: لماذا يتم استخدام ترميز UTF-8 عند التفاعل مع بيئة UNIX / Linux

نصائح أخرى

رمز المحمولة لا يدعم ذلك. يدعم Windows (على سبيل المثال) باستخدام wmain بدلا من main, في هذه الحالة يتم تمرير Argv كحرف واسعة.

على ويندوز، يمكنك استخدام GetCommandLineW() و CommandLineToArgvW() لإنتاج نمط Argv wchar_t[] صفيف، حتى إذا لم يتم تجميع التطبيق ل Unicode.

على ويندوز على أي حال، يمكنك الحصول على wmain() بالنسبة لبناء Unicode. غير محمول رغم ذلك. أنا dunno إذا توفر منصات دول مجلس التعاون الخليجي أو يونيكس / لينكس أي شيء مماثل.

على افتراض أن بيئة Linux الخاصة بك تستخدم ترميز UTF-8 ثم تعد التعليمات البرمجية التالية برنامجك لسهولة علاج Unicode في C ++:

    int main(int argc, char * argv[]) {
      std::setlocale(LC_CTYPE, "");
      // ...
    }

التالي، نوع wchar_t هو 32 بت في لينكس، مما يعني أنه يمكن أن يحمل نقاط رمز Unicode الفردية ويمكنك استخدام نوع WSTRING بأمان لمعالجة السلسلة الكلاسيكية في C ++ (حرف حسب الحرف). مع مكالمة SetLocale أعلاه، سيقوم إدراج WCOUT تلقائيا بترجمة الإخراج الخاص بك إلى UTF-8 واستخراج من WCIN تلقائيا إشراف إدخال UTF-8 في UTF-32 (حرف واحد = 1 رمز رمز). المشكلة الوحيدة التي تظل هي أن سلاسل Argv [i] لا تزال تشفير UTF-8.

يمكنك استخدام الوظيفة التالية لتشغيل UTF-8 في UTF-32. إذا كانت سلسلة الإدخال تالفة، فسوف تعيد الأحرف المحولة بشكل صحيح حتى يتم كسر المكان الذي تم فيه كسر قواعد UTF-8. يمكنك تحسينه إذا كنت بحاجة إلى المزيد من التقارير الأخطاء. ولكن بالنسبة لبيانات Argv، يمكن للمرء أن يفترض بأمان أنه صحيح UTF-8:

#define ARR_LEN(x) (sizeof(x)/sizeof(x[0]))

    wstring Convert(const char * s) {
        typedef unsigned char byte;
        struct Level { 
            byte Head, Data, Null; 
            Level(byte h, byte d) {
                Head = h; // the head shifted to the right
                Data = d; // number of data bits
                Null = h << d; // encoded byte with zero data bits
            }
            bool encoded(byte b) { return b>>Data == Head; }
        }; // struct Level
        Level lev[] = { 
            Level(2, 6),
            Level(6, 5), 
            Level(14, 4), 
            Level(30, 3), 
            Level(62, 2), 
            Level(126, 1)
        };

        wchar_t wc = 0;
        const char * p = s;
        wstring result;
        while (*p != 0) {
            byte b = *p++;
            if (b>>7 == 0) { // deal with ASCII
                wc = b;
                result.push_back(wc);
                continue;
            } // ASCII
            bool found = false;
            for (int i = 1; i < ARR_LEN(lev); ++i) {
                if (lev[i].encoded(b)) {
                    wc = b ^ lev[i].Null; // remove the head
                    wc <<= lev[0].Data * i;
                    for (int j = i; j > 0; --j) { // trailing bytes
                        if (*p == 0) return result; // unexpected
                        b = *p++;   
                        if (!lev[0].encoded(b)) // encoding corrupted
                            return result;
                        wchar_t tmp = b ^ lev[0].Null;
                        wc |= tmp << lev[0].Data*(j-1);
                    } // trailing bytes
                    result.push_back(wc);
                    found = true;
                    break;
                } // lev[i]
            }   // for lev
            if (!found) return result; // encoding incorrect
        }   // while
        return result;
    }   // wstring Convert

على Windows، يمكنك استخدام Tchar.h و _tmain، والتي سيتم تحويلها إلى WMAIN إذا تم تعريف رمز _unicode في وقت ترجمة، أو غير ذلك. سيتم توسيع Thar * Argv [] بالمثل وفقا لشركة Wchr * Argv [] إذا تم تعريف Unicode، والشار * Argv [] إن لم يكن.

إذا كنت ترغب في الحصول على منصة عرض أسلوبك الرئيسي، فيمكنك تحديد وحدات الماكرو الخاصة بك بنفس التأثير.

يحتوي Tchar.H على عدد من وحدات ماكرو للتحويل بين Wchar و Char.

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