Каква е най-добрата практика за създаване на библиотеки, които поддържат Unicode и ASCII в C++?

Работя върху писането на някои библиотеки, които ще се използват както вътрешно, така и от клиенти, и се чудех кой е най-добрият метод за поддръжка на Unicode и ASCII. Изглежда, че Microsoft (в MFC библиотеките) записва както Unicode, така и ASCII класовете и прави нещо подобно в заглавните файлове, използвайки макроси:

#ifdef _UNICODE
#define CString CStringW
#else
#define CString CStringA
#endif

Въпреки че не съм голям фен на макросите, той върши работа. Ако пиша библиотеки, използвайки STL, има ли смисъл да пиша заглавки, които съдържат неща като това:

#ifdef _UNICODE
#define GetLastErrorString GetLastErrorStringW
#else
#define GetLastErrorString GetLastErrorStringA
#endif

std::string GetLastErrorStringA();
std::wstring GetLastErrorStringW();

Или трябва просто да пусна отделни библиотеки, една за ASCII и една за Unicode?

Просто се чудя какво мислят хората, че е най-доброто нещо, което да направите в тази ситуация.

АКТУАЛИЗАЦИЯ: Разглеждане на някои коментари и въпроси:

  • Това ще бъдат C++ класови библиотеки.
  • Вярвам, че ще трябва да използвам UTF-16 кодиране, тъй като бих искал да поддържам азиатски набори от знаци.
  • Моите причини да внедря Unicode са две: 1) Всички нови SDK поддържат Unicode и не съм сигурен, че бъдещите SDK или библиотеки на трети страни ще поддържат отделни ASCII версии в бъдеще. 2) Въпреки че няма да интернационализираме напълно нашето приложение, би било хубаво, ако можем да обработваме потребителски вход (като имена) и зареждане на файлове от пътища, които съдържат азиатски знаци.

person bsruth    schedule 30.09.2009    source източник
comment
Разработвате ли плосък API в стил C или набор от C++ класове?   -  person Michael    schedule 30.09.2009
comment
Има проблем с вашия пример: трябва също така да зададете псевдоним на връщания тип на метода, ако искате да имате някакъв шанс той да компилира не самия метод (въпреки че може да се наложи да използвате #define в изпълнението на метода) .   -  person Matthieu M.    schedule 30.09.2009
comment
Според моя опит не е необходимо да използвате UTF-16 за азиатски (CJK) знаци. Моята програма ги обработва добре с многобайтов UTF-8 без всякакъв вид магьосничество.   -  person akaltar    schedule 07.07.2013


Отговори (4)


Бих направил библиотеката изцяло Unicode вътрешно. След това ще съществува набор от C++ адаптерни класове за ASCII, които се свързват с изпълнението на Unicode.

person Michael    schedule 30.09.2009
comment
Въпросът е: необходимо ли е това за вътрешно използване на "Unicode", тъй като в зависимост от кодирането обикновен std::string може да свърши работа. - person Matthieu M.; 30.09.2009

Можете да съхранявате Unicode низове в std::string, ако първо ги конвертирате в UTF-8.

Имате нужда само от wstring, когато взаимодействате с UTF-16 извиквания, като Windows API. Ако случаят е такъв, можете да конвертирате вашите низове в wstrings локално, където е необходимо. Това може да е малко натоварващо, но не е толкова лошо.

person StackedCrooked    schedule 30.09.2009

Въпросът е малко неточен, но...

Първо трябва да прецизирате кодирането. Unicode е просто представяне на знаците (всеки е свързан с кодова точка), когато става въпрос за работа с Unicode в приложение, трябва да изберете как ще бъдат представени кодовите точки. Ако можете да използвате Utf-8, няма да се притеснявате за широки знаци, можете да съхранявате данните в обикновен std::string :)

След това трябва да прецизирате проблема си:

  • искате ли да поддържате записи в Unicode и Ascii?
  • или говориш за изхода?
  • има ли все пак, че можете да използвате std::locale, за да знаете в кое кодиране трябва да изведете?

Работя върху интернационализирано приложение (уебсайт, с C++ бекенд...) и ние просто използваме std::string вътрешно. Резултатът в Ascii или Utf-8 зависи от файл за превод, но представянето на данните не се различава с йота (с изключение на броенето на знаци, вижте моята публикация по тази тема).

Наистина, определено не съм фен на макросите, тъй като utf-8 трябваше да бъде съвместим с Ascii, ако можете да изберете свое собствено кодиране, вие сте спасени!

person Matthieu M.    schedule 30.09.2009

Аз t-h-i-n-k питате за "разбираемостта" на кода, а не за използването на ASCII, UTF-8, 16 или 32-битови символи.

Ако е така, предпочитам да направя блоковете от код възможно най-големи: това би накарало човек да използва "портата" (символната константа _UNICODE), за да избира или отделни файлове, или поне големи парчета код. Кодът, който променя петната си на всеки следващ ред, или така, или, не дай боже, в рамките на изявление, е труден за разбиране.

Бих посъветвал да не използвате портала за избор на включвания на отделни файлове

#ifdef _UNICODE
#include "myUniLib.h"
#else
#include "myASCIILib.h"
#endif

като такъв ще включва два и може би дори три файла (файлът Unicode, файлът 646US (ASCII) и може би вашият nexus файл с горния код). Това е три пъти по-голяма от възможността нещо да бъде загубено и произтичаща от това компилация да се провали.

Вместо това използвайте вратата във файл, за да изберете големи блокове код:

#ifdef _UNICODE
   ...lotsa code...
#else
   ...lotsa code...
#endif

Добре, кажете, че правите обратното: чудите се за char срещу char (UTF-8) срещу W срещу A. Колко универсален искате да бъдете? CStrings, които споменавате, са само за света на Windows. Ако искате да сте съвместими с Mac и UNIX (OK, Linux), ви предстои трудна работа.

BtW- ASCII вече не е... признат стандарт. Има ASCII и след това има ... ASCII. Ако имате предвид седем битовия "стандарт" от старите дни на UNIX, най-близкият, който намерих, е ISO-646US. Еквивалентът на Unicode е ISO-10646.

Някои хора са имали късмет с кодирането на знаците като URL адреси: само ASCII букви и цифри и знака за процент. Докато трябва да кодирате и декодирате през цялото време, съхранението е наистина предвидимо. Малко странно, да, но определено иновативно.

Има някои езикови капани. Например, не зависи от регистъра, за да бъде двупосочен (тук не знам точната дума). На немски, малките букви ß стават SS, когато се превеждат на главни букви. SS обаче, когато е с малки букви, се превръща в ss, а не в ß. Турският има нещо подобно. Когато проектирате вашето приложение, не приемайте, че преводите на малки и големи букви могат да ви помогнат.

Освен това не забравяйте, че граматическото подреждане е различно в различните езици. Просто „Здравей, Джим! Как върви понеделникът ти?“ може да завърши с "Здравей! Твоят понеделник, върви добре, Джим?"

И накрая, предупреждение: избягвайте поток IO (std::cin ‹‹ и std::cout >>). Той ви хваща в капан да вграждате вашите генератори на съобщения по такъв начин, че локализирането им става много трудно.

Задаваш правилните въпроси. Предстои ви приключение! Най-доброто!

person Community    schedule 30.09.2009