Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Использование класса CString




Работа со строками

 

Примеры преобразования строк символов в различные форматы представления см. в MSDN:

Ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vcmcpp/html/e7e4f741-3c82-45f0-b8c0-1e1e343b0e77.htm

Эту ссылку надо поместить в элемент ввода URL в окне MSDN.

Очень хорошо различные кодировки символов и обработка символов с строк в целом изложены в работе Д.Рихтера и Назара [«Работа с символами и строками» 8а].

Кодировки и кодовые страницы

Обработка строк (символов) в языке С++ является, как на мой взгляд, одной из самых сложных или, скорее, запутанных задач. Это связано с наличием следующих, как говорят юристы, «отягчающих обстоятельств».

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

Во-вторых, слабая поддержка кодировки символов кириллицы (здесь имеются ввиду кодировки символов кириллицы в MS DOS и Windows) в инструментальных средствах.

В-третьих, наличие многочисленных кодировок: ASCII (7 или 8 бит), ANSI (8 бит), Multibyte Character Sets (MBCSs – 16 бит), Unicode (UTF-7, UTF-8,UTF-16,UTF-32, UTF-32 Big-Endian).

Терминология. Ucs Transformation Format (UTF) – формат преобразования UCS. Universal Character Set (UCS) – универсальный набор символов ISO 10646, надмножество Unicode, имеет 31-битовое кодовое пространство.

Для справки.  Найти кодовые страницы (CP – code page) и их краткую характеристику можно в MSDN (MVS-2005) по индексу Encoding class→About encoding class. Некоторые кодовые страницы приведены в табл. 2. Символ * в столбце «Примечание» означает, что кодовая страница непосредственным образом поддерживается инфраструктурой .NET вне зависимости от базовой платформы.

Таблица 2

Краткая характеристика некоторых кодовых страниц

 

Code Page (кодовая страница) Name (имя) Display Name (полное имя) Примечание
850 ibm850 Western European (DOS)  
852 ibm852 Central European (DOS)  
855 IBM855 OEM Cyrillic  
866 cp866 Cyrillic (DOS)  
1149 IBM01149 IBM EBCDIC (Icelandic-Euro)  
1250 windows-1250 Central European (Windows)  
1251 windows-1251 Cyrillic (Windows)  
1252 Windows-1252 Western European (Windows) *
10017 x-mac-ukrainian Ukrainian (Mac)  
20127 us-ascii US-ASCII *
20866 koi8-r Cyrillic (KOI8-R)  
21866 koi8-u Cyrillic (KOI8-U)  
28591 iso-8859-1 Western European (ISO) *
28592 iso-8859-2 Central European (ISO)  
28595 iso-8859-5 Cyrillic (ISO)  
65000 utf-7 Unicode (UTF-7) *
65001 utf-8 Unicode (UTF-8) *
65005 utf-32 Unicode (UTF-32)  

 

Если Вы хотите в своем программном коде разобраться с тем, какое число байт занимает символ или переменная какого-либо символьного типа, воспользуйтесь операцией sizeof.Например, в консольном приложении (среда MVS-2005) это можно сделать так:

cout<<sizeof (char) <<endl; //выводит 1

cout<<sizeof (TCHAR) <<endl; /*выводит 2 или 1 в зависимости от

выбранной кодировки */

cout<<sizeof (wchar_t)<<endl; //выводит 2

cout<<sizeof ('a') <<endl; //выводит 1

 

О кодировке 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-файла».

 

Использование класса 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 - Выполняет преобразование символов кириллицы из кодировки

   1251 (Cyrillic (Windows) ) в кодировку 866 (Cyrillic DOS).

       Поддерживает символы как русского, так и украинского языков*/

char * Ukr(char Str[])

{

static char Buf[1024];

strcpy_s(Buf,strlen(Str)+1,Str);

/*в следующем цикле заменяем коды русских букв на коды украинских,

не изменяя кодов остальных символов*/

for(int i=0;i<strlen(Buf);i++)

switch (Buf[i])

{

case -78 : Buf[i]=73; break; // І

case -77 : Buf[i]=105; break; // і

case -86 : Buf[i]=242; break; // Є

case -70 : Buf[i]=243; break; // є

case -81 : Buf[i]=244; break; // Ї

case -65 : Buf[i]=245; break; // ї

case -88 : Buf[i]=240; break; // Ё

case -72 : Buf[i]=241; break; // ё

default :

       {

       if((Buf[i]<=-17)&&(Buf[i]>=-64)) Buf[i]-=64; //А..Я,а..п

       else

       if((Buf[i]<=-1)&&(Buf[i]>=-16)) Buf[i]-=16; //р..я

       }

}

return Buf;

}










Последнее изменение этой страницы: 2018-04-12; просмотров: 358.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...