Чтение онлайн

ЖАНРЫ

Системное программирование в среде Windows

Харт Джонсон М.

Шрифт:

Вступление: стандартные символы и символы Unicode

Прежде чем двигаться дальше, необходимо кратко объяснить, как Windows обрабатывает символы и различает 8-битовые, 16-битовые и обобщенные символы. Эта тема весьма обширна и выходит за рамки данной книги, поэтому мы не будем выделять ее обсуждение в отдельную главу и ограничимся приведением лишь самых необходимых сведений в минимальном объеме.

Windows поддерживает стандартные 8-битовые символы (типы char или CHAR) и (исключая Windows 9x) 16-битовые символы расширенной формы (тип WCHAR, определенный в библиотеке С как wchar_t). В документации Microsoft 8-битовый набор фигурирует как символьный набор ASCII, хотя фактически он является символьным набором Latin-1, однако в целях удобства изложения название "ASCII" будет использоваться и в нашем обсуждении. Обеспечиваемая Windows с использованием кодировки Unicode UTF-16 поддержка обобщенных символов расширенной формы

позволяет представлять в стандарте Unicode символы и буквы, встречающиеся во всех основных языках, включая английский, французский, испанский, немецкий, русский, японский и китайский. 

Ниже описаны шаги, которые обычно предпринимаются при написании обобщенных (generic) Windows-приложений, то есть приложений, предусматривающих использование как символов Unicode (UTF-16, а не, например, UCS-4), так и 8-битовых ASCII-символов.

1. Определите все символы и строки с использованием обобщенных типов TCHAR, LPTSTR и LPCTSTR.

2. Чтобы иметь возможность работать с символами в расширенной форме Unicode (wchar_t в ANSI С), включите во все модули исходного кода определения #define UNICODE и #define _UNICODE; если этого не сделать, то тип TCHAR будет эквивалентен типу CHAR (char в ANSI С). Это определение должно помещаться перед директивой #include <windows.h>, и его часто задают в командной строке компилятора. Первая из указанных переменных препроцессора управляет определениями функций Windows, вторая — библиотекой С.

3. Размеры буферов для хранения символов, указываемые, например, при вызове функций ReadFile, могут определяться с использованием функции sizeof(TCHAR).

4. Используйте входящие в состав библиотеки С функции ввода/вывода обобщенных символов и строк, описанные в файле <tchar.h>. В качестве наиболее характерных из доступных функций можно назвать такие функции, как _fgettc, _itot (вместо itoa), _stprintf (вместо sprintf), _tstcpy (вместо strcpy), _ttoi, _totupper, _totlower и _tprintf. [12] Полный и исчерпывающий список таких функций можно найти в оперативной справочной системе. Все перечисленные определения зависят от определения символьной константы _UNICODE. Описанная коллекция функций не является полной. Примером функции, для которой еще не реализован аналог, позволяющий работать с символами расширенной формы, может служить функция memchr. Новые версии предоставляются по мере возникновения необходимости в них.

12

Символ подчеркивания (_) указывает на то, что данная функция или ключевое слово предоставляются компилятором Microsoft С, тогда как буквы t и Т указывают на то, что данная функция предназначена для работы с обобщенными символами, имеющими расширенную форму. Аналогичные возможности предлагаются и другими средами разработки приложений, хотя используемые в них имена функций и ключевые слова могут отличаться от приведенных выше.

5. Строковые константы могут принимать одну из трех допустимых форм. Эти же соглашения следует применять и к одиночным символам. Первые две формы предоставляются стандартом ANSI С, третья — макрос _Т (эквиваленты — TEXT и _ТЕХТ) — поставляется вместе с компилятором Microsoft С.

"В этой строке используются 8-битовые символы"

L"B этой строке используются 16-битовые символы"

_Т("В этой строке используются обобщенные символы")

6. Чтобы получить доступ к необходимым определениям текстовых макросов и обобщенным функциям библиотеки С, в модуль следует включить заголовочный файл <tchar.h>, объявление которого должно предшествовать объявлению файла <windows.h>.

16-битовые символы Unicode (кодировка UTF-16) используются в Windows повсеместно; для внутреннего представления имен файлов и путей доступа в файловой системе NTFS также используется Unicode. Если определена символьная константа _UNICODE, то все вызовы функций Windows требуют использования строк, состоящих из расширенных символов; в противном случае строки 8-битовых символов преобразуются в расширенные строки. В случае программ, которые должны выполняться под управлением систем Windows 9x, не являющихся Unicode-системами, определять символические константы UNICODE и _UNICODE не следует. В средах NT или СЕ решение об использовании указанных определений вы принимаете по своему усмотрению, если только для программы не должна быть одновременно сохранена возможность выполнения под управлением Windows 9x.

Во всех последующих примерах вместо обычного типа char для символов и символьных строк будет использоваться тип TCHAR, если только по каким-то вполне обоснованным причинам не возникнет необходимости в обработке отдельных 8-битовых символов. Точно так же, тип LPTSTR соответствует указателю на обобщенную строковую переменную,

а тип LPCTSTR — указателю на обобщенную строковую константу. В результате принятия этих мер программа может стать более громоздкой, однако лишь своевременный учет различных возможных вариантов обеспечивает гибкость, необходимую для разработки и тестирования приложений, допускающих как кодировку Unicode, так и 8-битовую кодировку символов, что позволит легко преобразовать программу к использованию символов Unicode, если впоследствии в этом возникнет необходимость. Более того, предоставление возможности выбора между обеими разновидностями кодировок соответствует общепринятой, если не универсальной, практике, которая сложилась к настоящему времени.

Немалую пользу может принести просмотр системных заголовочных файлов, изучив которые вы поймете, как определяются тип TCHAR и интерфейсы системных функций и как они зависят от того, определены или не определены символьные константы UNICODE и _UNICODE. Соответствующие строки обычно выглядят так:

#ifdef UNICODE

#define TCHAR WCHAR

#else

#define TCHAR CHAR

#endif

Альтернативные функции для работы с обобщенными строками 

В тех случаях, когда при сравнении строк необходим учет специфики языковых и региональных, или локальных, особенностей на стадии выполнения, или же когда требуется сравнивать не строки, а слова, [13] то вместо функций _tcscmp и _tcscmpi вам могут понадобиться функции lstrcmp и lstrcmpi. Сравнение строк осуществляется путем простого сравнения числовых значений символов, тогда как при сравнении слов принимаются во внимание специфические для конкретного языка особенности словообразования. Если применить указанные два метода сравнения к таким парам строк, как coop/co-op и were/we're, то они приведут к противоположным результатам.

13

В соответствии со сложившейся практикой для обозначения длинных указателей на параметры, представленные строками символов, используется префикс l.

В Windows также существует группа функций, предназначенных для работы с символами и строками в представлении Unicode. Эти функции обеспечивают прозрачную обработку региональных особенностей. Типичными функциями этой группы являются функция CharUpper, которую можно применять как к строкам, так и к отдельным символам, и функция IsCharAlphaNumeric. К числу других функций для работы со строками принадлежат функция CompareString (учитывающая особенности локализации) и функция MultiByteToWideChar. Многобайтовые символы Windows 3.1 и 9х расширяют наборы 8-битовых символов, позволяя применять для представления наборов символов, используемых в языках дальневосточных стран, сдвоенные байты. Чтобы продемонстрировать использование функций обоих типов, будут рассмотрены примеры программ, в которых используются как обобщенные функции библиотеки С (_tprintf и подобные ей), так и функции Windows (CharUpper и подобные ей). Примеры в последующих главах в основном опираются на обобщенную библиотеку С.

Обобщенная функция Main

Обозначение С-функции main с ее списком аргументов (argv[]) следует заменить макросом _tmain. В зависимости от определения символической константы _UNICODE макрос разворачивается либо до main, либо до wmain. _tmain определяется в заголовочном файле <tchar.h>, который следует включать после файла <windows.h>. Тогда типичный заголовок основной программы будет иметь следующий вид:

#include <windows.h>

#include <tchar.h>

int _tmain(int argc, LPTSTR argv[]) {

 …

}

В Microsoft С функция _tmain поддерживает дополнительный третий параметр, используемый для строк окружения. Такое нестандартное расширение является обычным в UNIX.

Определения функций

В качестве примера рассмотрим функцию CreateFile. Если символьная переменная UNICODE определена, то эта функция определяется как CreateFileA, а если не определена — то как CreateFileW. Строковые параметры в объявлениях также описываются как строки 8-битовых символов или символов в расширенной форме. Следовательно, если в исходном коде присутствуют такие, например, ошибки, как использование неподходящих параметров в функции CreateFile, то в сообщениях компилятора об этих ошибках будут указываться функции CreateFileA или CreateFileW.

Поделиться с друзьями: