operator char() или operator int()
Здорова госпдо!
Снова ничо не ясно как всегда.
Разбираю программку из книги Страуструпа, там он описывает класс String в нем есть
вложенный класс Cref как бы имитирующий char.
И от надыбал я там строчку:
operator char() const //выдает значение
ну и не понял, что это он тут перегрузил, и кода этот оператор вызывается.
И еще смотрел на перед задачку, так там нужно сымитировать полностью класс int свой INT и там подсказка
перегрузите INT::operator int()
ну и чо это за фигня?
Када читал, то вроде как бы вспоминаю это перегрузка new или чото хз, искал не нашол, где объяснялось про эту фигню.
Да и вообще эти две задачки, разобрать класс String и создать свой INT, с оценкой *2, как бы за 1 час делаются, а я уже 4 дня разбираю, что такое перегрука. Кумарят такие задачи.
п.с. ну и книга не учебник, а гамно.
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Class & operator’s |Error: undefined reference to operator
Компилирует нормально, но когда хочу использовать оператор выдает ошибку:undefined reference to.
Вызов operator[] через operator[] const
Перелистывал Майерса, наткнулся на код, подскажите пожалуйста почему он советует закомментированный.
Перегрузка operator>> и operator
Здрасьте! Есть необходимость перегрузить потоки, Я знаю как это сделать через friend, но вот.
Ошибка Operator= char []
Пробую написать свой строковый тип (wStr) с нуля Такой код работает: wStr path_prj_2;.
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Сообщение было отмечено ninja2 как решение
Решение
Сообщение от ninja2
ну и чо это за фигня?
оператор преобразования типа
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include class Test { char mChar; int mInt; double mDouble; public: Test(char c, int i, double d) : mChar(c) , mInt(i) , mDouble(d) { } operator char() const { return mChar; } operator int() const { return mInt; } operator double() const { return mDouble; } }; int main() { Test t('c', 10, 100.500); char c = t; // с == 'c' int i = t; // i == 10 double d = t; //d == 100.500 }
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь
Зачем нужен operator++(int)
Очень тупой вопрос — для чего нужен operator++(int)? Ну, то есть, понятно что он делает.
operator int() что за зверь?
Несколько раз видел в интернетах такую запись: operator int()<>; По контексту так и не понял, что.
Operator int() в классе Строка
Приведите пример, пожалуйста, как воспользоваться данной перегрузкой операции в main. String.h.
Реализация operator + через operator +=
внутри следующей темы возник вопрос, ответ на который так и не был получен.
Char operation c что это
Стандартная библиотека языка С++ предоставляет программистам строковый тип данных (избавляет от использования массивов символов char[ ]).
Мы будем использовать тип данных string наряду со стандартными встроенными типами данных. И вы на первый взгляд не будете замечать никаких различий, хотя на самом деле это абстрактный тип данных, созданный на основе объектно-ориентированных возможностей языка С++. Надеюсь со временем вы тоже сможете создавать АТД, которыми можно будет пользоваться так же удобно и свободно, как и классом string.
Строковый тип данных позволяет хранить строки переменной длины, причем длину можно менять в процессе выполнения программы. Строковый тип представляет операторы, выполняющие такие операции над строками, как контеканация, присваивание, замещение и др.
Для того, чтобы можно было создавать строковую переменную, необходимо подключить описание этого типа данных из стандартной библиотеки.
void main()
string name=»Vitaly»; // объявление, определение, инициализация
string lastname=»Domnenko»;
name+=»M.»+lastname; // конкатенация с присваиванием (накапливающее присваивание)
cout >
Используя [ ] можно получить символ из любой позиции
char ch=name[5]; // символы нумеруются с нуля
Лексикографическое сравнение осуществляется с использованием операторов == < >= !=. При лексикографическом сравнении последовательно сравниваются коды символов строки. Те символы считаются «больше», чьи коды «больше»и наоборот.
Кодировка (кодовая таблица) — это однозначное соответствие между целым число (кодом) и символом. При этом символ — это буква, цифра и другие графические знаки. Кодировки обычно составляют так, что символы следуют в алфавитном порядке и символ ‘а’ имеет наименьший код, а символ ‘z’ наибольший. Таким образом, выполняя лексикографическое сравнение можно разместить слова (строки) в алфавитном порядке. Это справедливо и для символов кириллического алфавита. Но не всегда, т.к. существует кодировки, в которой кириллические символы располагаются не в алфавитном порядке. Это кодировка КОИ8, которая обычно используется в операционных системах UNIX. Если вы пишете программу для UNIX, то нужно помнить, что простое лексикографическое сравнение не даст ожидаемого результата и нужно усложнять программу.
В нашем случае (при программировании для DOS или Windows) используются кодировки CP866 и СP1251 лексикографическое сравнение справедливо и дает нужный результат.
Ну и операторы для ввода/вывода строковых переменных >>
Функция | Описание |
---|---|
Конструкторы | |
string() | конструктор по умолчанию, создает пустую строку |
string(const char* p) | преобразующий конструктор |
string(const string& str, size t pos=0, size t n=npos) | копирующий конструктор (npos обычно равен -1 и указывает, что память не была выделена) |
string(const char* p, size_t n) | копирует n символов, р является базовым адресом |
string(char c, size t n=l) | создает строку из n символов с |
Перегруженные операторы | |
string& operator= (const string& s) | оператор присваивания |
string& operator+= (const string& s) | добавляет строку |
char operator[] (size t pos) const | возвращает символ из позиции pos |
char& operator[] (size t pos) | возвращает ссылку на символ из позиции pos |
Функции-члены | |
string& append(const string& s, size_t pos=0, size t n=npos); | Добавляет n символов начиная от позиции pos |
string& assign(const string& s, size_t pos=0, size_t n=npos); | строковому объекту присваивается n символов, начиная от позиции pos |
string& insert(size_t posl, const string& str, size_t pos2=0 , size_t n=npos); | вставляет n символов, полученных из str, начиная с позиции pos2, в строку с позиции posl |
string& remove(size_t pos=0 , size_t n=npos); | Удаляются n символов из строки начиная с позиции pos |
string& replace(posl, nl, str, pos2=0, n2=npos); | в неявной строке начиная с позиции posl заменяет nl символов n2 символами из подстроки str с позиции pos2 |
string& replace(pos, n, p, n2); | заменяет n символов в позиции pos используя char* p из n2 символов или char* p до завершающего нуля, или повторяя символ с rep раз |
char get_at (pos) const; | возвращает символ из позиции pos |
void put_at (pos, c); | помещает символ с в позицию pos |
size_t length() const; | возвращает длину строки |
const char* c_str() const; | преобразует строку в традиционное char* представление |
const char* data() const; | возвращает базовый адрес строкового представления |
void resize(n, c); void resize(n); | изменяет строку, делая ее длину равной п; в первой функции в качестве заполняющего символа выступает с, а во второй — символ eos () (end-of-string, конец строки) |
void reserve(size_t res_arg);size_t reserve() const; | выделяет память под строку; первая функция переустанавливает this; вторая возвращает закрытый член res — размер выделенного фрагмента |
size_t copy(p, n, pos=0) const; | п симолов строки, начиная с позиции pos, копируются в char* p |
string substr(pos=0, n=pos) const; | возвращается подстрока из п символов строки |
int compare(const string& str, size_t pos=0, size_t n=npos) const; | сравнивает п символов строки, начиная с позиции pos, со строкой str. Возвращается ноль, если строки равны; в противном случае возвращается положительное или отрицательное целое значение, показывающее, что неявная строка лексикографически больше или меньше чем строка str. |
size_t find (const string& str, size_t pos=0) const; | в строке начиная с позиции pos производится поиск строки str. Если она найдена, возвращается позиция, в которой она начинается; в противном случае возвращается позиция npos |
size_t rfind(str, pos=npos) const; | похоже на find (), но при поиске первого совпадения строка сканируется в обратном направлении |
size_t find_first_of(str, pos=0) const; | производится поиск первого вхождения str начиная с позиции pos |
size_t find_last_of(str, pos=npos) const; | аналогично, но в обратном направлении |
size_t find_first_not_of(str, pos=0) const; | производится поиск первого символа, который не соответствует ни одному из символов str начиная с позиции pos |
size_t find_last_not_of(str, pos=npos) const; | аналогично, но в обратном направлении |
Пример работы со строками
///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 2.1. Пример работы со сроками // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include // подключение библиотеки ввода-вывода #include // подключение библиотеки ввода-вывода в файл #include // подключение описания string using namespace std; // подключение стандартного пространства имен для использования библиотек ///////////////////////////////////////////////////////////////////////////// void main() < ifstream ifile("test.html"); // создание потока ввода из файла по его имени string data; // строка куда будут записаны данные // цикл будет выполняться до тех пор, пока не встретиться конец файла while(!ifile.eof()) < string sLine; getline(ifile, sLine, '\n'); // читаем строку из файла до символа конца строки data+=sLine; // записываем прочитанную строку в конец итоговой > size_t num_first=0; // номер символа, с которого будет происходить поиск // бесконечный цикл, выход из цикла - по оператору break while(true) < // находим номер символа, с которого начинается подстрока "// если такого текста не нашли - выход из цикла num_first=data.find("
, num_first); if(num_first==string::npos) break; // находим номер символа, с которого начинается подстрока ">", начиная с символа под номером num_first+1 // если такого текста не нашли - выход из цикла size_t num_last=data.find(">", num_first+1); if(num_last==string::npos) break; // выделяем подстроку от "" string image_data=data.substr(num_first+1, num_last-num_first-1); // запоминаем символ, начиная с которого будем искать в следующий раз num_first=num_last+1; // ищем номер символа, с которого начинается подстрока "src="" // (для задания подстроки используем экранирующий символ) size_t num_first2=image_data.find("src=\""); // если такая подстрока была найдена if(num_first2!=string::npos) < // ищем закрывающую кавычку size_t num_last2=image_data.find("\"", num_first2+6); // если такая подстрока была найдена - выделяем в отдельную строку имя файла и выводим на экран if(num_last2!=string::npos) < string image_name=image_data.substr(num_first2+5, num_last2-num_first2-5); cout> >; > /////////////////////////////////////////////////////////////////////////////
Указатель на тип char
Я как-то давно спрашивал по поводу указателей, разобрался, всем ответившим спасибо. Но сейчас мне пришлось столкнутся с типом char :
int *a; char *b; a = new int(10); b = "bla bla bla"; // Странно ведь мы записываем в адрес, а не в разыменованный указатель cout
Хотелось бы понять, как работает указатель на тип char (хотелось бы увидеть аргументированные ответы, почему так различается, и что-то от себя как рекомендации). Шерстил интернет — по теме указателей в C++ ничего не нашел P. S.: Прошу прощения, если эта тема всех достала или мое сообщение является дубликатом (есть темы похожие, но, вроде, это не то, что мне надо).
Отслеживать
11.5k 8 8 золотых знаков 42 42 серебряных знака 69 69 бронзовых знаков
задан 12 ноя 2015 в 10:00
3,913 7 7 золотых знаков 45 45 серебряных знаков 85 85 бронзовых знаков
4 ответа 4
Сортировка: Сброс на вариант по умолчанию
Давайте рассмотрим предложения из вашего примера шаг за шагом.
В этом предложении
int *a;
вы объявили переменную a как указатель на объект с типом int
В этом предложении
char *b;
вы объявили переменную b как указатель на объект с типом char
В этом предложении
a = new int(10);
был создан объект в динамической памяти типа int , который был инициализирован значением 10.
В этом предложении
b = "bla bla bla";
в левой части выражения с оператором присваивания стоит переменна с типом char * . В правой части этого выражения используется строковый литерал "bla bla bla" . Строковые литералы в C++ имеют типы константных символьных массивов.
(C++ Стандарт, 2.14.5 String literals)
8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).
Строковый литерал "bla bla bla" имеет тип const char [12] . В выражениях массивы неявно преобразуются к указателям на свой первый элемент.
Согласно стандарту C++ (4.2 Array-to-pointer conversion)
1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.
Таким образом в приведенном предложении в правой части выражения с оператором присваивания используется значение типа const char * , которое указывает на первый символ строкового литерала "bla bla bla" . То есть имеет место попытка указателю типа char * присвоить значение указателя типа const char * . Так как не существует неявного преобразования из типа указателя на константный объект в тип указателя на неконстантный объект, то компилятор должен выдать диагностическое сообщение.
Правильно было бы объявить переменную b следующим образом
const char *b;
Тогда вышеприведенное предложение с присваиванием было бы корректно, и переменной b был бы присвоен адрес первого символа строкового литерала, стоящего в правой части выражения от знака присваивания.
b = "bla bla bla";
фактически, эквивалентно следующему предложению
В этом предложении
cout
целочисленное значение, адресуемое указателем a выводится на консоль.
Было бы более корректно записать
cout
В этом предложении
cout
при условии, что компилятор каким-то образом сгенерировал объектный модуль, несмотря на ошибку, о которой я сказал выше, выведет на консоль строковый литерал, так как для указателей типа char * оператор operator
Если вы хотите вывести на консоль именно значение самого указателя, то вам в таком случае следует написать либо
cout
cout ( b )
А если переменная b была объявлена с квалификатором const , то
Char operation c что это
Каждая переменная имеет определенный тип. И этот тип определяет, какие значения может иметь переменная, какие операции с ней можно производить и сколько байт в памяти она будет занимать. В языке C++ определены следующие базовые типы данных: логический тип bool , целочисленные типы, типа чисел с плавающей точкой, символьные типы. Рассмотрим эти группы по отдельности.
Логический тип
Логический тип bool может хранить одно из двух значений: true (истинно, верно) и false (неверно, ложно). Например, определим пару переменных данного типа и выведем их значения на консоль:
#include int main() < bool isAlive ; bool isDead ; std::cout
При выводе значения типа bool преобразуются в 1 (если true) и 0 (если false). Как правило, данный тип применяется преимущество в условных выражениях, которые будут далее рассмотрены.
Значение по умолчанию для переменных этого типа - false .
Целочисленные типы
Целые числа в языке C++ представлены следующими типами:
- signed char : представляет один символ. Занимает в памяти 1 байт (8 бит). Может хранить любой значение из диапазона от -128 до 127
- unsigned char : представляет один символ. Занимает в памяти 1 байт (8 бит). Может хранить любой значение из диапазона от 0 до 255
- char : представляет один символ в кодировке ASCII. Занимает в памяти 1 байт (8 бит). Может хранить любое значение из диапазона от -128 до 127, либо от 0 до 255 Несмотря на то, что данный тип представляет тот же диапазон значений, что и вышеописанный тип signed char , но они не эквивалентны. Тип char предназначен для хранения числового кода символа и в реальности может представлять как signed byte , так и unsigned byte в зависимости от конкретного компилятора.
- short : представляет целое число в диапазоне от –32768 до 32767. Занимает в памяти 2 байта (16 бит). Данный тип также имеет псевдонимы short int , signed short int , signed short .
- unsigned short : представляет целое число в диапазоне от 0 до 65535. Занимает в памяти 2 байта (16 бит). Данный тип также имеет синоним unsigned short int .
- int : представляет целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита). Диапазон предельных значений соответственно также может варьироваться от –32768 до 32767 (при 2 байтах) или от −2 147 483 648 до 2 147 483 647 (при 4 байтах). Но в любом случае размер должен быть больше или равен размеру типа short и меньше или равен размеру типа long Данный тип имеет псевдонимы signed int и signed .
- unsigned int : представляет положительное целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита), и из-за этого диапазон предельных значений может меняться: от 0 до 65535 (для 2 байт), либо от 0 до 4 294 967 295 (для 4 байт). Имеет псевдоним unsigned
- long : в зависимости от архитектуры может занимать 4 или 8 байт и представляет целое число в диапазоне от −2 147 483 648 до 2 147 483 647 (при 4 байтах) или от −9 223 372 036 854 775 808 до +9 223 372 036 854 775 807 (при 8 байтах). Занимает в памяти 4 байта (32 бита) или. Имеет псевдонимы long int , signed long int и signed long
- unsigned long : представляет целое число в диапазоне от 0 до 4 294 967 295. Занимает в памяти 4 байта (32 бита). Имеет синоним unsigned long int .
- long long : представляет целое число в диапазоне от −9 223 372 036 854 775 808 до +9 223 372 036 854 775 807. Занимает в памяти 8 байт (64 бита). Имеет псевдонимы long long int , signed long long int и signed long long .
- unsigned long long : представляет целое число в диапазоне от 0 до 18 446 744 073 709 551 615. Занимает в памяти, как правило, 8 байт (64 бита). Имеет псевдоним unsigned long long int .
Для представления чисел в С++ применятся целочисленные литералы со знаком или без, типа -10 или 10. Например, определим ряд переменных целочисленных типов и выведем их значения на консоль:
#include int main() < signed char num1< -64 >; unsigned char num2< 64 >; short num3< -88 >; unsigned short num4< 88 >; int num5< -1024 >; unsigned int num6< 1024 >; long num7< -2048 >; unsigned long num8< 2048 >; long long num9< -4096 >; unsigned long long num10< 4096 >; std::cout u или U. Литералы типовlong
иlong long
имеют суффиксы L/l и LL/ll соответственно:#include int main() < unsigned int num6< 1024U >; // U - unsigned int long num7< -2048L >; // L - long unsigned long num8< 2048UL >; // UL - unsigned long long long num9< -4096LL >; // LL - long long unsigned long long num10< 4096ULL >;// ULL - unsigned long long std::cout #include int main() < int num< 1'234'567'890 >; std::coutРазличные системы исчисления
По умолчанию все стандартные целочисленные литералы представляют числа в привычной нам десятичной системе. Однако C++ также позволяет использовать и числа в других системах исчисления.
Чтобы указать, что число - шестнадцатеричное, перед числом указывается префикс 0x или 0X . Например:
int num1< 0x1A>; // 26 - в десятичной int num2< 0xFF >; // 255 - в десятичной int num3< 0xFFFFFF >; //16777215 - в десятичнойЧтобы указать, что число - восьмеричное, перед числом указывается ноль 0 . Например:
int num1< 034>; // 26 - в десятичной int num2< 0377 >; // 255 - в десятичнойБинарные литералы предваряются префиксом 0b или 0B :
int num1< 0b11010>; // 26 - в десятичной int num2< 0b11111111 >; // 255 - в десятичнойВсе эти типы литералов также поддерживают суффиксы U/L/LL :
unsigned int num1< 0b11010U>; // 26 - в десятичной long num2< 0377L >; // 255 - в десятичной unsigned long num3< 0xFFFFFFULL >; //16777215 - в десятичнойЧисла с плавающей точкой
Для хранения дробных чисел в C++ применяются числа с плавающей точкой. Число с плавающей точкой состоит из двух частей: мантиссы и показателя степени . Оба могут быть как положительными, так и отрицательными. Величина числа – это мантисса, умноженная на десять в степени экспоненты.
Например, число 365 может быть записано в виде числа с плавающей точкой следующим образом:
3.650000E02В качестве разделителя целой и дробной частей используется символ точки. Мантисса здесь имеет семь десятичных цифр - 3.650000 , показатель степени - две цифры 02 . Буква E означает экспоненту, после нее указывается показатель степени (степени десяти), на которую умножается часть 3.650000 (мантисса), чтобы получить требуемое значение. То есть, чтобы вернуться к обычному десятичному представлению, нужно выполнить следующую операцию:
3.650000 × 102 = 365Другой пример - возьмем небольшое число:
-3.650000E-03В данном случае мы имеем дело с числом –3.65 × 10 -3 , что равно –0.00365 . Здесь мы видим, что в зависимости от значения показателя степени десятичная точка "плавает". Собственно поэтому их и называют числами с плавающей точкой.
Однако хотя такая запись позволяет определить очень большой диапазон чисел, не все эти числа могут быть представлены с полной точностью; числа с плавающей запятой в целом являются приблизительными представления точного числа. Например, число 1254311179 выглядело бы так: 1.254311E09 . Однако если перейти к десятичной записи, то это будет 1254311000 . А это не то же самое, что и 1254311179 , поскольку мы потеряли три младших разряда.
В языке C++ есть три типа для представления чисел с плавающей точкой:
- float : представляет вещественное число одинарной точности с плавающей точкой в диапазоне +/- 3.4E-38 до 3.4E+38. В памяти занимает 4 байта (32 бита)
- double : представляет вещественное число двойной точности с плавающей точкой в диапазоне +/- 1.7E-308 до 1.7E+308. В памяти занимает 8 байт (64 бита)
- long double : представляет вещественное число двойной точности с плавающей точкой не менее 8 байт (64 бит). В зависимости от размера занимаемой памяти может отличаться диапазон допустимых значений.
В своем внутреннем бинарном представлении каждое число с плавающей запятой состоит из одного бита знака, за которым следует фиксированное количество битов для показателя степени и набор битов для хранения мантиссы. В числах float 1 бит предназначен для хранения знака, 8 бит для экспоненты и 23 для мантиссы, что в сумме дает 32 бита. Мантисса позволяет определить точность числа в виде 7 десятичных знаков.
В числах double : 1 знаковый бит, 11 бит для экспоненты и 52 бит для мантиссы, то есть в сумме 64 бита. 52-разрядная мантисса позволяет определить точность до 16 десятичных знаков.
Для типа long double расклад зависит от конкретного компилятора и реализации этого типа данных. Большинство компиляторов предоставляют точность до 18 - 19 десятичных знаков (64-битная мантисса), в других же (как например, в Microsoft Visual C++) long double аналогичен типу double .
В C++ литералы чисел с плавающими точками представлены дробными числами, которые в качестве разделителя целой и дробной частей применяют точку:
double num ;
Даже если переменной присваивается целое число, чтобы показать, что мы присваиваем число с плавающей точкой, применяется точка:
double num1< 1 >; // 1 - целочисленный литерал double num2< 1. >; //1. - литерал числа с плавающей точкой
Так, здесь число 1. представляет литерал числа с плавающей точкой, и в принципе аналогичен 1.0 .
По умолчанию все такие числа с точкой расцениваются как числа типа double. Чтобы показать, что число представляет другой тип, для float применяется суффикс f / F , а для long double - l / L :
float num1< 10.56f >; // float long double num2< 10.56l >; // long double
В качестве альтернативы также можно применять экспоненциальную запись:
double num1< 5E3 >; // 5E3 = 5000.0 double num2< 2.5e-3 >; // 2.5e-3 = 0.0025
Размеры типов данных
При перечислении типов данных указывался размер, который он занимает в памяти. Но стандарт языка устанавливает лишь минимальные значения, которые должны быть. Например, для типов int и short минимальное значение - 16 бит, для типа long - 32 бита, для типа long double - 64 разряда. При этом размер типа long должен быть не меньше размера типа int, а размер типа int - не меньше размера типа short, а размер типа long double должен быть не меньше double . А разработчики компиляторов могут выбирать предельные размеры для типов самостоятельно, исходя из аппаратных возможностей компьютера.
К примеру, компилятор g++ Windows для long double использует 16 байт. А компилятор в Visual Studio, который также работает под Windows, и clang++ под Windows для long double используют 8 байт. То есть даже в рамках одной платформы разные компиляторы могут по разному подходить к размерам некоторых типов данных. Но в целом используются те размеры, которые указаны выше при описании типов данных.
Однако бывают ситуации, когда необходимо точно знать размер определенного типа. И для этого в С++ есть оператор sizeof() , который возвращает размер памяти в байтах, которую занимает переменная:
#include int main() < long double number ; std::coutsizeof(number) = 16Символьные типы
В C++ есть следующие символьные типы данных:
- char : представляет один символ в кодировке ASCII. Занимает в памяти 1 байт (8 бит). Может хранить любое значение из диапазона от -128 до 127, либо от 0 до 255
- wchar_t : представляет расширенный символ. На Windows занимает в памяти 2 байта (16 бит), на Linux - 4 байта (32 бита). Может хранить любой значение из диапазона от 0 до 65 535 (при 2 байтах), либо от 0 до 4 294 967 295 (для 4 байт)
- char8_t : представляет один символ в кодировке Unicode. Занимает в памяти 1 байт. Может хранить любой значение из диапазона от 0 до 256
- char16_t : представляет один символ в кодировке Unicode. Занимает в памяти 2 байта (16 бит). Может хранить любой значение из диапазона от 0 до 65 535
- char32_t : представляет один символ в кодировке Unicode. Занимает в памяти 4 байта (32 бита). Может хранить любой значение из диапазона от 0 до 4 294 967 295
char
Переменная типа char хранит числовой код одного символа и занимает один байт. Стандарт языка С++ не определяет кодировку символов, которая будет использоваться для символов char, поэтому производители компиляторов могут выбирать любую кодировку, но обычно это ASCII.
В качестве значения переменная типа char может принимать один символ в одинарных кавычках, либо числовой код символа:
#include int main() < char a1 ; char a2 ; std::cout
В данном случае переменные a1 и a2 будут иметь одно и то же значение, так как 65 - это числовой код символа "A" в таблице ASCII. При выводе на консоль с помощью cout по умолчанию отображается символ.
Кроме того, в C++ можно использовать специальные управляющие последовательности, которые предваряются слешем и которые интерпретируются особым образом. Например, "\n" представляет перевод строки, а "\t" - табуляцию.
Однако ASCII обычно подходит для наборов символов языков, которые используют латиницу. Но если необходимо работать с символами для нескольких языков одновременно или с символами языков, отличных от английского, 256-символьных кодов может быть недостаточно. И в этом случае применяется Unicode .
Unicode (Юникод) — это стандарт, который определяет набор символов и их кодовых точек, а также несколько различных кодировок для этих кодовых точек. Наиболее часто используемые кодировки: UTF-8, UTF-16 и UTF-32. Разница между ними заключается в том, как представлена кодовая точка символа; числовое же значение кода для любого символа остается одним и тем же в любой из кодировок. Основные отличия:
- UTF-8 представляет символ как последовательность переменной длины от одного до четырех байт. Набор символов ASCII появляется в UTF-8 как однобайтовые коды, которые имеют те же значения кодов, что и в ASCII. UTF-8 на сегодняшний день является самой популярной кодировкой Unicode.
- UTF-16 представляет символы как одно или два 16-битных значения.
- UTF-32 представляет все символы как 32-битные значения
В C++ есть четыре типа для хранения символов Unicode: wchar_t , char8_t , char16_t и char32_t ( char16_t и char32_t были добавлены в C+11, а char8_t - в C++20).
wchar_t
Тип wchar_t — это основной тип, предназначенный для наборов символов, размер которых выходит за пределы одного байта. Собственно отсюда и его название: wchar_t - wide (широкий) char. происходит от широкого символа, потому что этот символ «шире», чем обычный однобайтовый символ. Значения wchar_t определяются также как и символы char за тем исключением, что они предваряются символов "L":
wchar_t a1 ;
Также можно передать код символа
wchar_t a1 ;
Значение, заключенное в одинарные кавычки, представляет собой шестнадцатеричный код символа. Обратная косая черта указывает на начало управляющей последовательности, а x после обратной косой черты означает, что код шестнадцатеричный.
Стоит учитывать, что для вывода на консоль символов wchar_t следует использовать не std::cout , а поток std::wcout :
#include int main() < char h = 'H'; wchar_t i ; std::wcout
При этом поток std::wcout может работать как с char, так и с wchar_t. А поток std::cout для переменной wchar_t вместо символа будет выводить его числовой код.
Проблема с типом wchar_t заключается в том, что его размер сильно зависит от реализации и применяемой кодировки. Кодировка обычно соответствует предпочтительной кодировке целевой платформы. Так, для Windows wchar_t обычно имеет ширину 16 бит и кодируется с помощью UTF-16. Большинство других платформ устанавливают размер в 32 бита, а в качестве кодировки применяют UTF-32. С одной стороны, это позволяет больше соответствовать конкретной платформе. Но с другой стороны, затрудняет написание кода, переносимого на разные платформы. Поэтому в общем случае часто рекомендуется использовать типы char8_t , char16_t и char32_t . Значения этих типов предназначены для хранения символов в кодировке UTF-8, UTF-16 или UTF-32 соответственно, а их размеры одинаковы на всех распространенных платформах.
Для определения символов типов char8_t , char16_t и char32_t применяются соответственно префиксы u8, u и U:
char8_t c< u8'l' >; char16_t d< u'l' >; char32_t e< U'o' >;
Стоит отметить, что для вывода на консоль значений char8_t/char16_t/char32_t пока нет встроенных инструментов типа std:cout/std:wcout .
Спецификатор auto
Иногда бывает трудно определить тип выражения. В этом случае можно предоставить компилятору самому выводить тип объекта. И для этого применяется спецификатор auto . При этом если мы определяем переменную со спецификатором auto, эта переменная должна быть обязательно инициализирована каким-либо значением:
auto number = 5; // number имеет тип int auto sum ; // sum имеет тип double auto distance ; // distance имеет тип unsigned long
На основании присвоенного значения компилятор выведет тип переменной. Неинициализированные переменные со спецификатором auto не допускаются: