Примечание: Ух ты ... Похоже, КТО-то решил, что ПОЧТИ все ответы заслуживают снижения, даже когда они правильные ... Я взял на себя обязательство изменить их, чтобы сбалансировать снижение ...
Давайте посмотрим, есть ли у меня собственный downmod ...: - /
Редактировать: РАДОСТЬ !!!
Девять часов назад, кто-то (вероятно, тот, кто отрицал все ответы, кроме ответа Павла Радзивиловского) отклонил этот ответ. Конечно, без каких-либо комментариев, указывающих на то, что не так с моим ответом.
\ о /
1 - Как выполнить миграцию в Windows Unicode?
Какие изменения необходимо внести для переноса этого кода, чтобы он работал в экосистеме библиотек Visual Studio Unicode и Unicode? (У меня нет реальной необходимости работать с ASCII и Unicode, это может быть чистый Unicode.)
1.a - Моя кодовая база большая, я не могу сделать это за один шаг!
Давайте представим, что вы хотите сделать это постепенно (потому что ваше приложение не маленькое).
У меня была такая же проблема в моей команде: я хотел создать код, готовый к Unicode, сосуществующий с кодом, который не был готов к Unicode.
Для этого вы должны использовать заголовок MS tchar.h
и использовать его возможности. Используя ваши собственные примеры:
"Hello World"
----> _T("Hello World")
char
тип ----> TCHAR
тип
char *
указатели на выделенные строки C ----> TCHAR *
указатели
std::string
type ---> Это сложно, потому что вы должны создать свой собственный std::tstring
- помните, что sizeof (char) может отличаться от sizeof (TCHAR), поэтому обновите ваши malloc и новые [] тоже
1.b - Ваш собственный tstring.hpp
заголовок
Для обработки STL с моим компилятором (в то время я работал над Visual C ++ 2003, поэтому ваш пробег мог варьироваться), я должен предоставить заголовок tstring.hpp
, который является кроссплатформенным и позволяет пользователю используйте tstring, tiostream и т. д. Я не могу поместить полный исходный код здесь, но я приведу выдержку, которая позволит вам создавать свои собственные:
namespace std
{
#ifdef _MSC_VER
#ifdef UNICODE
typedef wstring tstring ;
typedef wistream tistream ;
// etc.
#else // Not UNICODE
typedef string tstring ;
typedef istream tistream ;
// etc.
#endif
#endif
} // namespace std
Обычно, это не разрешено загрязнять пространство имен std
, но я думаю, что это нормально (и это было проверено хорошо).
Таким образом, вы можете использовать префикс большинства конструкций STL / C ++ iostreams с t
и иметь его готовым к Unicode (в Windows).
1.c - Готово !!!
Теперь вы можете переключиться из режима ANSI в режим UNICODE, определив UNICODE
и _UNICODE
, которые обычно определяются в настройках проекта (я помню, что в Visual C ++ 2008 на первых страницах настроек есть записи именно для этого ).
Мой совет таков: у вас, вероятно, есть режимы «Debug» и «Release» в вашем проекте Visual C ++, чтобы создавать производные от них режимы «Debug Unicode» и «Release Unicode», где описаны макросы, описанные выше. определены.
Таким образом, вы сможете создавать двоичные файлы ANSI и UNICODE.
1.d - Теперь все является (или должно быть) Unicode!
Если вы хотите, чтобы ваше приложение было кроссплатформенным, игнорируйте этот раздел.
Теперь, либо вы можете изменить всю свою кодовую базу за один шаг, либо вы уже преобразовали всю свою кодовую базу для использования описанных выше функций tchar.h
, теперь вы можете удалить все макросы из своего кода:
_T("Hello World")
----> L"Hello World"
TCHAR
тип ----> wchar_t
тип
TCHAR *
указатели на выделенные строки C ----> wchar_t *
указатели
std::tstring
тип ---> std::wstring
тип и т. Д.
1.e - Помните, что глифы UTF-16 могут иметь ширину 1 или 2 wchar_t в Windows!
Одно распространенное заблуждение в Windows - полагать, что символ wchar_t - это один символ Unicode. Это неправильно, так как некоторые символы Unicode представлены двумя wchar_t.
Таким образом, любой код, который полагается на один char
, являющийся одним глифом, потенциально сломается, если вы используете глифы Unicode не из BMP.
2 - Кросс-платформенность?
Возможно ли сделать это независимо от платформы? (т.е. не используя типы Microsoft.)
Так вот, это была сложная часть.
Linux (я не знаю, для других ОС, но это должно быть легко сделать вывод из решения Linux или Windows), теперь готов к Unicode, тип char
должен содержать значение UTF-8.
Это означает, что ваше приложение, когда-то скомпилированное, например, на моем Ubuntu 10.04, по умолчанию является Unicode.
2.a - Помните, что глифы UTF-8 могут иметь ширину 1, 2, 3 или 4 символа в Linux!
Конечно, совет выше относительно UTF-16 и широких символов здесь еще более важен:
Символу Юникода может потребоваться от 1 до 4 char
символов для представления. Таким образом, любой используемый вами код, основанный на предположении, что каждый char
является целым символом Unicode, сломается.
2.b - В Linux нет tchar.h
! 1127 *
Мое решение: напиши.
Вам нужно только определить префиксные символы 't' для отображения на нормальные символы, как показано в этом фрагменте:
#ifdef __GNUC__
#ifdef __cplusplus
extern "C" {
#endif
#define _TEOF EOF
#define __T(x) x
// etc.
#define _tmain main
// etc.
#define _tprintf printf
#define _ftprintf fprintf
// etc.
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
#ifdef __cplusplus
}
#endif
#endif // __GNUC__
... и включить его в Linux вместо tchar.h
из Windows.
2.c - в Linux нет tstring
! 1138 *
Конечно, приведенное выше сопоставление STL для Windows должно быть завершено для обработки случая Linux:
namespace std
{
#ifdef _MSC_VER
#ifdef UNICODE
typedef wstring tstring ;
typedef wistream tistream ;
// etc.
#else // Not UNICODE
typedef string tstring ;
typedef istream tistream ;
// etc.
#endif
#elif defined(__GNUC__)
typedef string tstring ;
typedef istream tistream ;
// etc.
#endif
} // namespace std
Теперь вы можете использовать _T("Hello World")
и std::tstring
в Linux и Windows.
3 - Должен быть подвох!
И есть.
Во-первых, существует проблема загрязнения пространства имен std
вашими собственными префиксными символами t
, что должно быть запрещено. Затем не забудьте добавить макросы, которые будут загрязнять ваш код. В текущем случае, я думаю, это нормально.
Во-вторых, я предположил, что вы используете MSVC в Windows (таким образом, макрос _MSC_VER
) и GCC в Linux (таким образом, макрос __GNUC__
). Измените определения, если ваш случай отличается.
В-третьих, ваш код должен быть нейтральным Unicode, то есть вы не должны полагаться на то, что ваши строки являются UTF-8 или UTF-16. Фактически, ваш источник должен быть пустым от чего угодно, кроме символов ASCII, чтобы оставаться кросс-платформенным.
Это означает, что некоторые функции, такие как поиск ОДНОГО Unicode Glyph, должны выполняться отдельным фрагментом кода, который будет иметь все #define
, необходимое для его исправления.
Например, поиск символа é
(Unicode Glyph 233) потребует от вас поиска первого символа 233 при использовании UTF-16 wchar_t в Windows и первой последовательности из двух символов 195 и 169 в UTF-8 char
. Это означает, что вы должны либо использовать некоторую библиотеку Unicode, либо написать ее самостоятельно.
Но это больше проблема самого Unicode, чем Unicode в Windows или в Linux.
3.a - Но предполагается, что Windows неправильно обрабатывает UTF-16
И что?
«Каноническим» примером, который я видел, описан был элемент управления EDIT Win32, который, как предполагается, не может корректно возвращать символ не-BMP UTF-16 в Windows. достаточно осторожно).
Это проблема Microsoft. Ничто из того, что вы решите в своем коде, не изменит факт наличия этой ошибки или ее отсутствия в Win32 API Поэтому использование символов UTF-8 в Windows не исправит ошибку в элементе управления EDIT. Единственное, на что вы можете надеяться - это создать свой собственный элемент управления EDIT (сделать его подклассом и правильно обрабатывать событие BACKSPACE?) Или свои собственные функции преобразования.
Не смешивайте две разные проблемы, а именно: предполагаемая ошибка в Windows API и ваш собственный код . Ничто в вашем собственном коде не поможет избежать ошибки в Windows API, если вы НЕ используете предполагаемый ошибочный Windows API.
3.b - Но UTF-16 в Windows, UTF-8 в Linux, не так ли сложно?
Да, это может привести к ошибкам на некоторых платформах, которые не произойдут на других, если вы слишком много думаете о символах.
Я предположил, что вашей основной платформой была Windows (или вы хотели предоставить библиотеку для wchar_t
и char
пользователей).
Но если это не так, если Windows не является вашей основной платформой, то есть решение, что все ваши символы char и std :: string будут содержать символы UTF-8, если не указано иное. Затем вам нужно будет обернуть API, чтобы убедиться, что ваша строка char UTF-8 не будет ошибочно принята за строковую строку ANSI (или другую кодовую страницу) в Windows. Например, имя файлов для библиотек stdio.h
и iostream
будет считаться кодированной страницей, а также версия ANSI API Win32 (например, CreateWindowA).
Это подход GTK +, который использует символы UTF-8, но не удивительно, что QT (на котором построен Linux KDE), который использует UTF-16.
Источник:
Тем не менее, это не защитит вас от "Эй, но средства управления Win32 не обрабатывают мои символы Юникода!" проблема, поэтому вам все равно придется создать подкласс для этого элемента управления, чтобы иметь желаемое поведение (если ошибка все еще существует) ...
Приложение
См. Мой ответ в std :: wstring VS std :: string для полной разницы между std::string
и std::wstring
.