Як писати програму з використанням Unicode
Microsoft розробила Windows API так, щоб якнайменше впливати на Ваш код. Справді, у Вас з'явилася можливість створити єдиний файл з вихідним кодом, який компілюється як із застосуванням Unicode, так і без нього, — достатньо визначити два макроси (UNICODE та _UNICODE), які відповідають за потрібні зміни.
Unicode та бібліотека С
Для використання було введено деякі нові типи даних. Стандартний заголовковий файл String.h модифікований у ньому визначено wchar_t - тип даних для
typedef unsigned short wchar_t
Якщо Ви хочете створити буфер для зберігання довжиною до 99 символів з нульовим символом в кінці, поставте оператор:
Він створює масив зі ста значень. Звичайно, стандартні функції бібліотеки для роботи з рядками на кшталт strcpy, strchr і strcat оперують тільки з
- Вони не здатні коректно обробляти Поет
му в ANSI є додатковий набір функцій. На рис. наведено список рядкових функцій ANSI C та еквівалентних їм
wchar_t * wcschr (const wchar_t *,
int strcmp(const char *,
int wcscmp(const wchar_t
Мал. Рядкові функції ANSI C та їх
Зверніть увагу, що імена всіх нових функцій починаються з wcs - це абревіатура wide character set (набір широких символів) Таким чином, імена утворюються простою заміною префікса str відповідних wcs.
Один дуже важливий момент, про який багато хто забуває, полягає в тому, що бібліотека С, що надається Microsoft, відповідає стандарту ANSI. A він вимагає, щоб бібліотека С підтримувала символи та рядки в Unicode Це означає, що Ви можете викликати функції С для роботи з рядками навіть при роботі в Windows 98. Іншими словами, функції wcscat, wcslen, wcstok і т.д.
чудово працюють іу Windows 98; турбуватися треба за функції операційної системи.
Код, що містить явні виклики, просто так компілювати з використанням і ANSI, і Unicode не можна. Щоб реалізувати можливість компіляції "подвійного призначення", замініть у своїй програмі заголовний файл String.h на TChar.h. Він допомагає створювати універсальний вихідний код, здатний задіяти як ANSI, так і Unicode, - і це єдине, для чого потрібен файл TChar.h . Він складається з макросів, що замінюють явні виклики strилиЯкщо при компіляції вихідного коду Ви визначаєте _UNICODE, макроси посилаються на його відсутність - на
Наприклад, у TChar.h є макрос _tcscpy. Якщо Ви увімкнули цей заголовковий файл, але UNlCODE не визначено, _tcscpy розкривається в strcpy, а якщо _UNICODE визначено — вwcscpy, У файлі TChar.h визначено універсальні макроси для всіх стандартних рядкових функцій С. При використанні цих макросів замість конкретних імен ANSI або Ваш код можна буде компілювати для як Unicode, і ANSI.
Але, на жаль, це ще не все. Файл TChar.h має додаткові макроси.
Щоб оголосити символьний масив універсального призначення" (ANSI/Unicode), застосовується тип даних TCHAR. Якщо _UNICODE визначено, TCHAR оголошується так:
typedef wchar_L TCHAR;
А якщо UNICODE не визначено, то:
typedef char TCHAR
Використовуючи цей тип даних, можна оголосити рядок символів як:
Можна також визначати вказівники на рядки:
TCHAR * szError = "Error";
Щоправда, у цьому операторі є одна проблема. За замовчуванням компілятор Microsoft С++ транслює рядки як символи ANSI, а не Unicode. У результаті цей оператор нормально компілюється, якщо UNICODE не визначено, але в іншому випадку дає помилку. Щобкомпілятор згенерував a неоператор треба переписати так
TCHAR * szFrror = L "Error";
Велика буква L перед рядковим літералом вказує компілятору, що його треба обробляти як тоді, розміщуючи рядок в області даних програми,
компілятор вставить між усіма символами нульові байти. Але виникає інша проблема — програма компілюється, тільки якщо _UNICODE визначено. Отже, потрібен макрос, здатний вибірково ставити L перед рядковим літералом. Цю роботу виконує макрос _TEXT, що також міститься в Tchar.h. Якщо _UNICODE визначено, _TEXT визначається як
#define _TEXT(x) L ## x
В іншому випадку _TEXT визначається таким чином:
#define _TEXT(x) x
Використовуючи цей макрос, перепишемо злощасний оператор так, щоб його можна було коректно компілювати незалежно від того, чи визначено _UNICODE чи ні:
TCHAR * szError = _TEXT("Error");
Макрос _TEXT застосовується і символьних літералів. Наприклад, щоб перевірити, чи перший символ рядка є великою літерою J:
if (szError[0] == _TEXT('J'))
/ / Перший символ - J & gt; else
// перший символ – не J
Типи даних, визначені у Windows для Unicode
У заголовних файлах Windows визначено такі типи даних.