Як писати програму з використанням 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 визначено такі типи даних.