Шаблонний клас std::ctype являється facet-аспектом локалі (похідний від класу locale::facet) і призначений для класифікування і перетворення символів, адаптуючи функціональність файлу ctype стандартної бібліотеки мови C до системи локалей C++. Оголошення класу приблизно виглядає наступним чином:
template <class charT> class ctype ;
Параметр шаблону charT вказує на тип комірок, які зберігають символи у певному кодування, з якими клас повинен мати справу.
Клас std::ctype має захищений деструктор - програми повинні створювати примірники класів, які похідні від класу std::ctype, або використовувати примірники прив’язані до об’єктів локалі.
Усі стандартні локалі повинні підтримувати наступну мінімальну кількість примірників даного класу:
- ctype<char> - для звичайного типу символів;
- ctype<wchar_t> - для розширеного типу символів.
Нутрощі класу
Вбудовані типи
ctype_base::mask
Тип успадкований від класу ctype_base. Використовується методами класу ctype в якості поверненого значення.
Константи
ctype_base::mask space ;
Константа позначає пропуски у тексті (пробіл, '\t', '\n').
ctype_base::mask print ;
Позначає символи, які можуть бути надрукованими.
ctype_base::mask cntrl ;
Константа позначає контролюючі символи.
ctype_base::mask upper ;
Константа позначає символи у верхньому регістрі.
ctype_base::mask lower ;
Позначає символи у нижньому регістрі.
ctype_base::mask alpha ;
Позначає символ, який представляє букву абетки.
ctype_base::mask digit ;
Константа позначає символ, який представляє букву.
ctype_base::mask punct ;
Позначає символи пунктуації.
ctype_base::mask xdigit ;
Константа позначає символи, які можуть представляти шістнадцяткові цифри.
ctype_base::mask alnum ;
Константа позначає буквенно-цифрові символи.
ctype_base::mask graph ;
Позначає символи, які мають графічне представлення.
locale::id id ;
Унікальний ідентифікатор facet-об’єкта.
Методи
// загальний конструктор
explicit ctype (size_t refs = 0) ;
// конструктор для ctype<char>
explicit ctype (const mask* tab = 0,
bool del = false,
size_t refs = 0) ;
Конструктори класу ctype. Параметр refs призначений для управління знищення об’єктів класу: для значення 0 (нуль) - об’єкт автоматично видаляється, коли видаляється останній об’єкт локалі, який містив даний facet-об’єкт; і значення 1 - коли об’єкт не повинен автоматично видалятися. Параметр tab призначений для вказування усіх класифікованих символамів кодування (на подобі поверненого методом ctype::is).
bool is (mask m, char_type c) const ;
const char_type* is (const char_type* low,
const char_type* high,
mask* vec)
const ;
Класифікування символів. Варіант методу з двома параметрами призначений для тестування одного символу c на приналежність до будь-якого класу, вказаного у бітовій масці m. Варіант з трьома параметрами призначений для класифікування послідовності символів у проміжку [low, high), заповнюючи масив vec значеннями бітових констант.
Даний метод являється делегатом - він викликає віртуальний захищений метод do_is, який реалізовують потомки даного класу.
char narrow (char_type c, char dfault) const ;
const char_type* narrow (const char_type* low,
const char_type* high,
char dfault,
char* to) const ;
Версія методу з двома параметрами, перетворює символ c (який найчастіше має тип wchar_t) у його відповідник типу char. Функція з чотирма параметрами виконує перетворення послідовності [low, high) і повертає масив перетворених значень; параметр to вказує на буфер типу char, який повинен вмістити усі перетворені символи з послідовності [low, high). Параметр dfault вказує на значення, яке функція повинна повертати, коли у розширеного символу немає відповідника у типі char.
Даний метод являється делегатом - він викликає захищений метод do_narrow, який реалізовують потомки даного класу.
const char_type* scan_is (mask m,
const char_type* low,
const char_type* high) const ;
Даний метод повертає вказівник на перший елемент, який відповідає одному з константних бітових значень маски m, з проміжку [low, high).
Даний метод являється делегатом - він викликає захищений віртуальний метод do_scan_is, який реалізовують потомки класу std::ctype.
const char_type* scan_not (mask m,
const char_type* low,
const char_type* high) const ;
Повертає вказівник на символ, який не належить жодній з категорії вказаній у параметрі m, з проміжку символів [low, high).
Даний метод являється делегатом - він викликає метод do_scan_not, який реалізовують потомки класу std::ctype.
char_type tolower (char_type c) const ;
const char_type* tolower (char_type* low,
const char_type* high) const ;
Версія методу з одним параметром перетворює вказаний символ c у нижній регістр і повертає його. Версія методу з двома параметрами перетворює усі символи з верхнього регістру у нижній з проміжку [low, high) і повертає high.
Даний метод являється делегатом - він викликає віртуальний захищений метод do_tolower, який реалізовують потомки даного класу.
char_type toupper (char_type c) const ;
const char_type* toupper (char_type* low,
const char_type* high) const ;
Метод з одним параметром, перетворює символ c з верхнього регістру у нижній і повертає нове значення. Метод з двома параметрами перетворює усі символи проміжку [low, high) з верхнього регістру у нижній і повертає вказівник high.
Даний метод являється делегатом - він викликає захищений віртуальний метод do_toupper, який реалізовують потомки даного класу.
char_type widen (char c) const ;
const char* widen (const char* low,
const char* high,
char_type* to) const ;
Метод з одним параметром, перетворює символ c з типу char у тип символів, який вказаний при створені примірника даного класу (параметр шаблону charT). Метод з трьома параметрами перетворює символи з послідовності [low, high) у пам’ять, на яку вказує to і повертає вказівник high.
Приклади
Приклад #1
Розглянемо простий приклад використання класу ctype, а точніше його метод is для одного символу.
#include <locale> /* все корисне включно з ctype */
#include <iostream> /* об'єкт cout */
using namespace std ; /* друкуємо усе без std */
/* головна фукнція програми */
int main (int argc, char** argv)
{
/* створюємо піддослідну локаль
** пусте ім'я вказує на викристання
** локалі, яку вказав користувач, наприклад
** через змінну середовища LANG */
locale preferred ("") ;
/* перевіряємо, чи існує у локалі об'єкт класу
** ctype<wchar_t>, ми ж не бажаємо виключень в програмі */
if (!has_facet < ctype<wchar_t> > (preferred))
{
/* якщо даний facet-об'єкт не присутній у локалі,
** виводимо відповідне повідомлення і завершуємо роботу
** програми
** Символи на кирилиці, можуть неправильно відображатись
** у терміналі. */
cout << "Локаль немає facet-об'єкту ctype<wchar_t>." << endl ;
return 0 ;
}
/* отримуємо facet-об'єкт класу ctype через функцію use_facet */
const ctype<wchar_t>& lcfacet = use_facet < ctype<wchar_t> > (preferred) ;
/* тестуємо різні символи і виводимо результат на екран*/
cout << "Символ 'А', буква? - "
<< lcfacet.is (lcfacet.alpha, L'А') << endl
<< "Символ 'А', буква в верхньому регістрі? - "
<< lcfacet.is (lcfacet.alpha | lcfacet.alpha, L'А') << endl
<< "Символ 'Ф', буква? - "
<< lcfacet.is (lcfacet.alpha, L'Ф') << endl
<< "Символ 'F', буква в нижньому регістрі? - "
<< lcfacet.is (lcfacet.lower, L'F') << endl
<< "Символ '1', буква в верхньому регістрі? - "
<< lcfacet.is (lcfacet.lower | lcfacet.alpha, L'1') << endl
<< "Символ ';', символ пунктуації або пропуск? - "
<< lcfacet.is (lcfacet.punct | lcfacet.space, L';') << endl ;
return 0 ;
}
Вивід програми наступний:
Приклад #2
Переглянемо приклад використання методу ctype::toupper.
#include <locale> /* все корисне включно з ctype */
#include <string.h>
#include <iostream> /* об'єкт cout */
using namespace std ; /* друкуємо усе без std */
/* головна фукнція програми */
int main (int argc, char** argv)
{
/* створюємо піддослідну локаль
** пусте ім'я вказує на викристання
** локалі, яку вказав користувач, наприклад
** через змінну середовища LANG */
locale preferred ("") ;
/* перевіряємо, чи існує у локалі об'єкти класів
** ctype<wchar_t> і codecvt<wchar_t, char, mbstring_t>,
** ми ж не бажаємо виключень в програмі */
if ( !has_facet < ctype<wchar_t> > (preferred)
|| !has_facet < codecvt<wchar_t, char, mbstate_t> > (preferred))
{
/* якщо даний facet-об'єкт не присутній у локалі,
** виводимо відповідне повідомлення і завершуємо роботу
** програми
** Символи на кирилиці, можуть неправильно відображатись
** у терміналі. */
cout << "Локаль немає потрібних facet-об'єктів." << endl ;
return 0 ;
}
/* отримуємо facet-об'єкт класу ctype через функцію use_facet */
const ctype<wchar_t>& lcfacet = use_facet < ctype<wchar_t> > (preferred) ;
/* отримуємо facet-об'єкт класу codecvt через функцію use_facet,
** щоб вивести оригінальний рядок з перетвореним у термінал
** (термінал не вміє працювати з UTF-16 символами) */
const codecvt<wchar_t,char,mbstate_t>& lcvtfacet
= use_facet < codecvt<wchar_t,char,mbstate_t> > (preferred) ;
/* створюємо піддослідний рядок символів, елементи якого,
** будемо перетворювати у верхній регістр */
wchar_t low_str[] = L"не той козак, що за водою пливе, а той, що проти." ;
/* також визначаємо довжину рядка і створюємо відповідний вказівник */
unsigned int lslen = sizeof(low_str)/sizeof(low_str[0]) ;
const wchar_t* wptr = NULL ;
/* творюємо буфери, куди будемо
** запиувати перетворені у UTF-8 символи
** з константою довжини і вказівником на елемент типу */
const unsigned int deflen = 256 ;
char byte_low_str [deflen] ;
char byte_converted_str [deflen] ;
char* bptr = NULL ;
/* створюємо стан перетворення */
mbstate_t state ;
/* встановлюємо стан перетворення в початкове значення*/
memset (&state, 0, sizeof(state)) ;
/* виконуємо перетворення символів нижнього решістру
** з UTF-16 у UTF-8 у буфер byte_low_str */
lcvtfacet.out (state, low_str, low_str+lslen, wptr,
byte_low_str, byte_low_str+deflen, bptr) ;
/* перетворюємо симоли нижнього регістру у верхній */
lcfacet.toupper (low_str, low_str+lslen) ;
/* тепер рядок low_str містить усі символи у верхньому регістрі */
/* встановлюємо стан перетворення в початкове значення*/
memset (&state, 0, sizeof(state)) ;
/* виконуємо перетворення символів верхнього регістру
** з розширеного UTF-16 у байтовий UTF-8 буферу byte_converted_str */
lcvtfacet.out (state, low_str, low_str+lslen, wptr,
byte_converted_str, byte_converted_str+deflen, bptr) ;
/* повідомлення на UTF-8 кирилиці
** може некоректно відображатись у терміналі */
cout << "Оригінал : " << byte_low_str << endl
<< "У верхньому: " << byte_converted_str << endl ;
return 0 ;
}
Вивід програми наступний: