Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VC_Lect.doc
Скачиваний:
6
Добавлен:
01.07.2025
Размер:
15 Мб
Скачать
☆

1.3.2.О кодировке Unicode

Символы, используемые в европейских языках, можно закодировать восемью битами, даже символы с диакритическими знаками. Большинство азиатских языков для своих символов требуют 16 разрядов. Многие программы используют стандарт «набор двухбайтовых символов» (double-byte character set, DBCS), в котором некоторые символы кодируются 8, другие — 16 разрядами, в зависимости от значения первых 8 разрядов. DBCS сейчас (эти строки были написаны в 1998г.) заменяется Unicode, в которой все символы кодируются 16 разрядами. Для отдельных языков не выделяются отдельные наборы символов: например, если символ используется в японском и китайском, то этот символ лишь однократно входит в Unicode.

Если посмотреть на исходный код MFC и на код, сгенерированный IDE, то можно видеть типы TCHAR, LPTSTR и LPCTSTR, а также строковые константы вида _T(“строка символов”). Перед нами макросы. Если собирать проект без определения символа препроцессора _UNICODE, компилятор сгенерирует код для обычных 8-разрядных символов ANSI (CHAR) и указателей на массивы 8-разрядных символов (LPTSTR и LPCTSTR).

Если же определить _UNICODE, компилятор сгенерирует код для 16-разрядных символов Unicode (WCHAR), соответствующих указателей (LPWSTR и LPCWSTR) и строковых констант (L”wide string”).

Символ препроцессора _UNICODE определяет также, какие функции вызываются приложением, так как многие функции Win32 существуют в двух версиях. Когда программа вызывает, например, CreateWindowEx(), компилятор генерирует код для вызова либо CreateWindowExA() (с параметрами ANSI) либо CreateWindowExW() (с параметрами Unicode). В Microsoft Windows NT, в которой используется Unicode, CreateWindowExW() передаст все параметры напрямую, тогда как CreateWindowExA() преобразует строковые (ANSI) и символьные параметры в Unicode.

Если Вы хотите создать Unicode-приложение, его следует создавать для Windows NT и везде использовать макросы. Вызовы СОМ (за исключением DAO) всегда используют «широкие» (wide) символы (тип BSTR). Хотя и существуют функции Win32 для преобразования между ANSI и Unicode, но, используя класс CString, для этого можно прибегнуть к помощи Unicode-конструктора и функции-члена AllocSysString.

Некоторые рекомендации и основные приемы по работе с символами кириллицы см. в конце следующего подраздела и в подразделах «Русификация приложений» и «Использование ini-файла».

1.3.3.Использование класса cString

Этот MFC-класс значительно расширяет язык C++. Как указано в разделе “Microsoft Foundation Classes and Templates” интерактивной справки MSDN у класса CString много полезных операторов и функций-членов, но, по-видимому, главное его достоинство — способность динамически выделять память. Благодаря этому не надо заботиться о размере строки, выделении и освобождениии памяти и т.п. Вот несколько типичных примеров использования объектов CString:

CString strFirstName("Elvis");

CString strLastName("Presley");

CString strTruth = strFirstName + _T(" ") + strLastName; // конкатенация

strTruth += " is alive";

ASSERT(strTruth == "Elvis Presley is alive");

ASSERT(strTruth.Left(5) == strFirstName); /* функция Left возвращает

подстроку, начинающуюся с начала строки заданной длины*/

ASSERT(strTruth[2] == 'v'); // операция индексирования

В совершенном мире программы на C++ всегда использовали бы объекты CString и никогда — обычные массивы символов с нулем в конце. Увы, многие функции стандартной библиотеки по-прежнему полагаются на эти массивы, поэтому программы должны уметь работать с обоими представлениями строк. К счастью, в классе CString есть оператор const char * (), преобразующий объект CString в указатель на символы. Многие функции библиотеки MFC требуют параметров типа const char *. Возьмем, к примеру, глобальную функцию AfxMessageBox() библиотеки MFC. Вот один из ее прототипов:

int AFXAPI AfxMessageBox(LPCTSTR lpszText, UINT nType = MB_OK,

UINT nIDHelp = 0);

Обратите внимание: LPCTSTR — это не указатель на объект CString, а заменитель для const char *, совместимый с Unicode.

В программе, компилируемой для набора символов ANSI, можно использовать функцию AfxMessageBox так:

char szMessageText[] = "Unknown error";

AfxMessageBox(szMessageText);

или так:

CString strMessageText("Unknown error");

AfxMessageBox(strMessageText);

Теперь предположим, что надо создать строку в соответствии с определенным форматом. Эта задача решается при использовании функции Format:

int nError = 23;

CString strMessageText;

strMessageText.Format("Error number %d", nError);

AfxMessageBox(strMessageText);

Допустим, Вам понадобился прямой доступ к символам в объекте CString. Если Вы напишите примерно такой код:

CString strTest("test");

strncpy(strTest, "T", 1);

то компилятор сообщит об ошибке, так как первый параметр функции strncpy() объявлен как char*, а не const char *. Функция CString::GetBuffer() фиксирует заданный размер буфера строки и возвращает char *. Чтобы потом вновь сделать строку динамической, вызовите функцию-член CString::ReleaseBuffer(). Вот как правильно заменить строчную букву t прописной:

CString strTest("test");

strncpy(strTest.GetBuffer(5), "T", 1);

strTest.ReleaseBuffer();

ASSERT(strTest == "Test");

То же самое в программе, компилируемой для набора символов Unicode, должно выглядеть таким образом:

wchar_t szMessageText[] = _T("Unknown error");

AfxMessageBox(szMessageText);

CString strMessageText("Unknown error CString");

AfxMessageBox(strMessageText);

int nError = 23;

CString strMessageText;

strMessageText.Format(_T("Error number %d"), nError);

AfxMessageBox(strMessageText);

CString strTest("test");

wcsncpy(strTest.GetBuffer(5),_T("T"),1);

strTest.ReleaseBuffer();

ASSERT(strTest == "Test");

Примечание. Если Вы компилируете приложение с использованием Unicode, то оператор strncpy(strTest.GetBuffer(5),"T",1) вызовет сообщение об ошибке, так как GetBuffer() возвращает указатель на строку Unicode, и его можно заменить также одним из следующих двух:

strncpy_s((char *)(strTest.GetBuffer(5)), 5, "T", 1);

strncpy((char *)(strTest.GetBuffer(5)), "T", 1);

Оператор const char * преобразует объект CString в указатель на константу; но как быть с обратным преобразованием? У класса CString есть конструктор, преобразующий указатель на символьную константу в объект CString, и, кроме того, набор переопределенных операторов для таких указателей. Вот почему допустимы такие выражения, как:

truth += "is alive";

Специальный конструктор работает с функциями, принимающими ссылку на CString, например с CDC::TextOut(). В следующем примере в стеке вызывающей программы создается временный объект CString, а его адрес передается в TextOut():

pDC-> TextOut(0,0,”Hello world!”);

Если Вы пишете функцию, принимающую строковый параметр, учтите несколько правил:

  • если функция не изменяет содержимое строки и Вы собираетесь работать со стандартными библиотечными функциями, такими как strcpy(), используйте параметр const char *;

  • если функция не изменяет содержимое строки, но Вы хотите вызывать в ней функции-члены CString, используйте параметр типа const CString &;

  • если функция изменяет содержимое строки, но Вы хотите вызывать в ней функции-члены CString, используйте параметр типа CString &.

Перечисленные преобразования работают с английскими символами, но не работают с символами кириллицы. Для преобразования символов кириллицы в кодировку MS DOS воспользуйтесь таким приемом:

char Buf[300];

char * GetANSI(CString str)

{

WideCharToMultiByte(866,WC_NO_BEST_FIT_CHARS,str,-1,Buf,sizeof(Buf),0,0);

return Buf;

}

Если требуется получить символы в кодировке Windows, замените 866 на 1251.

Еще одна функция:

/*Ukr - Выполняет преобразование символов кириллицы из кодировки

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]