Символьные константы. Символьные и строковые константы

  • 28.06.2019

До этого момента, все переменные, которые мы рассматривали, были не константами. Их значения можно было изменить в любое время. Например:

int x { 4 }; // инициализация переменной x значением 4 x = 5; // изменяем значение x на 5

Тем не менее, иногда полезно использовать переменные, значения которых нельзя изменить – константы . Вот например, сила тяжести на Земле: 9.8м/с^2. Оно вряд ли поменяется в ближайшее время. Использовать константу для этого случая — наилучший вариант, так как таким способом мы предотвратим любое (даже случайное) изменение значения.

Чтобы сделать переменную константой – используйте ключевое слово const перед типом переменной или после. Например:

const double gravity { 9.8 }; // предпочтительнее использовать const перед типом данных int const sidesInSquare { 4 }; // ок, но не предпочтительно

Несмотря на то, C++ примет const как до, так и после типа, мы рекомендуем использовать именно перед типом.

Константы должны быть инициализированы при объявлении . Их значения с помощью операции присваивания изменить не получится.

const double gravity { 9.8 }; gravity = 9.9; // не допускается - ошибка компиляции

Объявление константы без инициализации также вызовет ошибку компиляции:

const double gravity; // ошибка компиляции, константа должна быть инициализирована

Обратите внимание, константы могут быть инициализированы и с помощью неконстантных значений:

std::cout << "Enter your age: "; int age; std::cin >> age; const int usersAge (age); // в дальнейшем переменная usersAge не может быть изменена

const является наиболее полезным (и наиболее часто используемым) с параметрами функций:

void printInteger(const int myValue) { std::cout << myValue; }

void printInteger (const int myValue )

std :: cout << myValue ;

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

Compile time и runtime

Когда вы находитесь в процессе компиляции программы – это compile time (время компиляции ) . Компилятор проверяет вашу программу на синтаксические ошибки, затем конвертирует код в объектные файлы.

Когда вы находитесь в процессе запуска вашей программы или когда программа уже выполняется — это runtime (время выполнения) . Код выполняется строка за строкой.

Constexpr

В C++ есть два вида констант.

Константы r untime . Их значения определяются только во время выполнения (когда программа запущена). Переменные типа usersAge и myValue (в коде выше) — это константы runtime, так как компилятор не может определить их значения во время компиляции. usersAge зависит от пользовательского ввода (который можно получить только во время выполнения программы), а myValue зависит от значения, переданного в функцию (которое станет известным также во время выполнения программы).

Константы c ompile-time . Их значения определяются во время компиляции. Например, сила тяжести Земли – это константа compile-time, мы её определили сами в ходе написания программы.

В большинстве случаев, неважно какой тип константы: compile-time или runtime. Однако, есть все же несколько ситуаций, когда C++ может требовать константу compile-time вместо runtime (например, при определении длины массива фиксированного размера — мы рассмотрим это позже). Так как типов есть два, то компилятору нужно постоянно отслеживать, к какому из них относится какая переменная. Чтобы упростить это задание, в C++ 11 появляется ключевое слово constexpr , которое гарантирует, что тип константы — compile-time:

constexpr double gravity (9.8); // ок, значение определяется во время компиляции constexpr int sum = 4 + 5; // ок, значение 4 + 5 определяется во время компиляции std::cout << "Enter your age: "; int age; std::cin >> age; constexpr int myAge = age; // не ок, переменная age не определяется во время компиляции

Использовать вы его, скорее всего, не будете, но знать о нем не помешает.

Правило: Любая переменная, которая не должна изменять свое значение после инициализации — должна быть объявлена, как const (или как constexpr).

Имена констант

Некоторые программисты пишут имена констант заглавными буквами. Другие используют обычные имена, только с префиксом ‘k’. Мы же не будем их как-то выделять, так как константы – это те же обычные переменные, просто с фиксированными значениями, вот и всё. Особой причины, чтобы их выделять нет. Однако, это дело каждого лично.

Символьные константы

В предыдущем уроке , мы обсуждали «магические числа» – литералы, которые используются в программе как константы. Поскольку их использование является плохой практикой, тогда что использовать вместо них? Ответ: символьные константы. Символьная (или еще символическая ) константа – это тот же литерал (магическое число), только с идентификатором. Есть два способа объявления символических констант в C++. Один из них хороший, а один не очень. Рассмотрим оба.

Плохой способ: Использование макросов-объектов с текстом-заменой в качестве символьных констант

Раньше этот метод широко использовался, так что вы все еще можете увидеть его в старых кодах.

В уроке 22 о препроцессорах и директивах , мы говорили, что макросы-объекты имеют две формы – с текстом-заменой и без. Рассмотрим первый случай (с текстом-заменой). Он выглядит так:

#define identifier substitution_text

Как только препроцессор встретит эту директиву, все дальнейшие появления ‘identifier’ будет заменяться на ‘substitution_text’. Идентификатор обычно пишется заглавными буквами с нижним подчеркиванием вместо пробелов.

Например:

int max_students = numClassrooms * MAX_STUDENTS_PER_CLASS;

#define MAX_STUDENTS_PER_CLASS 30

Во время компиляции, препроцессор заменит все идентификаторы MAX_STUDENTS_PER_CLASS на литерал 30.

Согласитесь, это гораздо лучший вариант, чем использование магических чисел, как минимум по нескольким причинам. MAX_STUDENTS_PER_CLASS обеспечивает контекст того, что это за значение и зачем оно надо, даже без комментариев. Во-вторых, если число нужно будет изменить — достаточно будет сделать правки только в директиве #define, все остальные идентификаторы MAX_STUDENTS_PER_CLASS в программе будут автоматически заменены новым значением при повторной компиляции.

Рассмотрим еще один пример:

#define MAX_STUDENTS_PER_CLASS 30 #define MAX_NAME_LENGTH 30 int max_students = numClassrooms * MAX_STUDENTS_PER_CLASS; setMax(MAX_NAME_LENGTH);

#define MAX_STUDENTS_PER_CLASS 30

#define MAX_NAME_LENGTH 30

int max_students = numClassrooms * MAX_STUDENTS_PER_CLASS ;

setMax (MAX_NAME_LENGTH ) ;

Здесь ясно, что MAX_STUDENTS_PER_CLASS и MAX_NAME_LENGTH имеются в виду как разные объекты, даже если у них одни и те же значения (30).

Так почему же этот способ плохой? Есть две причины.

Во-первых, макросы обрабатываются препроцессором, который заменяет идентификаторы на определенные значения. Эти значения не будут отображаться в отладчике (который показывает ваш фактический код). При компиляции int max_students = numClassrooms * 30; в отладчике вы увидите int max_students = numClassrooms * MAX_STUDENTS_PER_CLASS; . А если нужно будет узнать значение MAX_STUDENTS_PER_CLASS? Вам придется самостоятельно найти его в коде. А это может занять некоторое время, в зависимости от размеров программы.

Во-вторых, эти директивы всегда имеют глобальную область видимости (о ней мы поговорим позже). Это означает, что значения #define в одной части кода могут конфликтовать со значениями #define в другой части кода.

Правило: Не используйте #define для создания символьных констант.

Хороший способ: Переменные const

Лучший способ создать символьную константу — использовать const:

const int maxStudentsPerClass { 30 }; const int maxNameLength { 30 };

const int maxStudentsPerClass { 30 } ;

const int maxNameLength { 30 } ;

Такие значения будут отображаться в отладчике, также они следуют всем правилам обычных переменных (в том числе и насчет области видимости).

Правило: Используйте const для создания символьных констант.

Использование символьных констант в программе

Во многих программах символьная константа должна быть использована на протяжении всего кода (а не только в одном месте). Они могут быть физическими или математическими константами, которые не меняются (например, число Пи или число Авогадро) или специфическими значения вашей программы. Чтобы не писать их каждый раз, когда они необходимы — определите их в одном месте и используйте везде, где будет нужно. Таким образом, если вам придется их изменить – достаточно будет зайти в один файл и там внести правки, а не рыскать по всей программе.

Как это осуществить? Очень просто:

  1. Создайте заголовочный файл для хранения констант.
  2. В заголовочном файле объявите пространство имен (

Константы вещественного типа

Целочисленные константы

Константы в программах

Константы - объекты, не подлежащие использованию в левой части оператора присваивания, т.к. константа - является неадресуемой величиной и, хотя она хранится в памяти ЭВМ, обычно нет никакого способа узнать ее адрес. В языке Си константами являются:

Самоопределенные арифметические, символьные и строковые данные;

Идентификаторы массивов и функций;

Элементы перечислений.

Арифметические константы могут быть целого или вещественного типов.

Общий формат: ±n (+ обычно не ставится).

Десятичные константы - последовательность цифр 0...9, первая из которых не должна быть 0. Например, 22 и 273 - обычные целые константы, если нужно ввести длинную целую константу, то указывается признак L (l ) - 273L (273l ). Для такой константы будет отведено – 4 байта. Обычная целая константа, которая слишком длинна для типа int , рассматривается как более длинный тип (long или long long ).

Существует система обозначений для восьмеричных и шестнадца­те­­ри­чных констант.

Восьмеричные константы - последовательность цифр от 0 до 7, первая из которых должна быть 0, например: 020 = 16-десятичное.

Шестнадцатеричные константы - последовательность цифр от 0 до 9 и букв от A до F (a...f), начинающаяся символами 0Х (0х), например: 0X1F (0х1f) = 31-десятичное.

Восьмеричные и шестнадца­те­ричные константы могут также заканчиваться буквой L(l) - long, например, 020L или 0X20L.

Примеры целочисленных констант:

1992 13 1000L - десятичные;

0777 00033 01l - восьмеричные;

0x123 0X00ff 0xb8000l - шестнадцатеричные.

Данные константы размещаются в памяти по формату double, а во внешнем представлении могут иметь две формы:

1) с фиксированной десятичной точкой, формат записи: ±n .m , где n , m - целая и дробная части числа;

2) с плавающей десятичной точкой (экспоненциальная форма): ±n .m p , где n , m - целая и дробная части числа, р - порядок, например, 1,25×10 -8 записывается как 1.25E-8.

Примеры констант с фиксированной и плавающей точками:

1.0 -3.125100е-10 0.12537е+13

Символьная константа - это символ, заключенный в одинарные кавычки: "A", "х" (занимает 1 байт).

В языке Си используются и. специальные (управляющие ) символы, не отображаемые на экране; их назначение - влиять на порядок изображения других символов.. Поскольку они не отображаются на экране, для их обозначения в тексте программы используется пара символов, первый из которых всегда - обратная косая черта (обратный слеш ) ("\"). Основные их них:

С помощью обратного слеша в символьных и строковых (см. ниже) константах представляются и некоторые обычные символы, чье написание там могло бы привести к двусмысленности:

При присваивании символьной переменной эти последователь­ности должны быть заключены в апострофы. Символьная константа "\0" (не путать с символом - цифрой "0" !) часто записывается вместо целой константы 0, чтобы подчеркнуть символьную природу некоторого выражения (см. тему "Строки").

Примеры символьных констант: "А", "9", "$", "\n", "\"".

Константа - это ограниченная последовательность символов алфавита языка, представляющая собой изображение фиксированного (неизменяемого) объекта.

Константы бывают числовые, символьные и строковые. Числовые константы делятся на целочисленные и вещественные.

Целочисленные константы

Целочисленные данные в языке Си могут быть представлены в одной из следующих систем счисления :


Двоичная система представления данных непосредственно в языке Си не поддерживается. Однако можно воспользоваться файлом binary.h , в котором определены двоичные константы в пределах байта.

Пример использования двоичной системы счисления в языке Си:

1
2
3
4
5
6
7
8
9

#include
#include "binary.h"
int main()
{
unsigned char p = b10001001 | b00001010; // p=b10001011=139
printf("p = %dd = %xh" , p, p);
getchar(); getchar();
return 0;
}

Результат выполнения

В зависимости от значения целой константы компилятор присваивает ей тот или иной тип (char , int , long int ).

С помощью суффикса U (или u ) можно представить целую константу в виде беззнакового целого.

Например, Константе 200U выделяется 1 байт, и старший бит используется для представления одного из разрядов кода числа и диапазон значений становится от 0 до 255 . Суффикс L (или l ) позволяет выделить целой константе 8 байт (long int ).

Совместное использование в любом порядке суффиксов U (или u ) и L (или l ) позволяет приписать целой константе тип unsigned long int , и она займет в памяти 64 разряда, причем знаковый разряд будет использоваться для представления разряда кода (а не знака).

Вещественные константы

Константа с плавающей точкой (вещественная константа) всегда представляется числом с плавающей точкой двойной точности, т. е. как имеющая тип double , и состоит из следующих частей:

  • целой части - последовательности цифр;
  • точки — разделителя целой и дробной части;
  • дробной части - последовательности цифр;
  • символа экспоненты е или E ;
  • экспоненты в виде целой константы (может быть со знаком).

Любая часть (но не обе сразу) из нижеследующих пар может быть опущена:

  • целая или дробная часть;
  • точка или символ е (Е ) и экспонента в виде целой константы.

Примеры вещественных констант

  • 3.14159
  • 2.1Е5
  • .123ЕЗ
  • 4037е-5

По умолчанию компилятор присваивает вещественному числу тип double . Если программиста не устраивает тип, который компилятор приписывает константе, то тип можно явно указать в записи константы с помощью следующих суффиксов:

  • F (или f ) - float для простых вещественных констант,
  • L (или l ) - long double для вещественных констант двойной расширенной точности.

Примеры:

  • 3.14159F - константа типа float , занимающая 4 байта;
  • 3.14L - константа типа long double , занимающая 10 байт.

Символьные константы

Символьная константа - это один символ, например: ‘z’ . В качестве символьных констант также могут использоваться управляющие коды, не имеющие графического представления. При этом код управляющего символа начинается с символа ‘\’ (обратный слеш).

Как правило, нажатие клавиши Enter генерирует сразу два управляющих символа — перевод строки (0x0A ) и возврат каретки (0x0D ).

Все символьные константы имеют тип char и занимают в памяти 1 байт. Значением символьной константы является числовое значение её внутреннего кода.

Строковые константы

Строковая константа - это последовательность символов, заключенная в кавычки, например:

«Это строковая константа»

Кавычки не входят в строку, а лишь ограничивают её. Технически строковая константа представляет собой массив символов, и по этому признаку может быть отнесена к разряду сложных объектов языка Си.

В конце каждой строковой константы компилятор помещает ‘\0’ (нуль-символ), чтобы программе было возможно определить конец строки. Такое представление означает, что размер строковой константы не ограничен каким-либо пределом, но для определения длины строковой константы её нужно полностью просмотреть.

Поскольку строковая константа состоит из символов, то она имеет тип char . Количество ячеек памяти, необходимое для хранения строковой константы на 1 больше количества символов в ней (1 байт используется для хранения нуль-символа).

Символьная константа ‘x’ и строка из одного символа «x» — не одно и то же. Символьная константа — это символ, используемый для числового представления буквы x, а строковая константа «x» содержит символ ‘x’ и нуль-символ ‘\0’ и занимает в памяти 2 байта. Если в программе строковые константы записаны одна за другой через разделители, то при выполнении программы они будут размещаться в последовательных ячейках памяти.

Константы

Константами называют неизменяемые величины. Различаются целые, вещественные, символьные и строковые константы. Компилятор, выделив константу в качестве лексемы, относит ее к одному из типов по ее внешнему виду.

Форматы констант, соответствующие каждому типу, приведены в табл. 7.1.

Таблица 7.1.

Константы в языке С++

Константа Формат Примеры
Целая Десятичный: последовательность десятичных цифр, начинающаяся не с нуля, если это не число нуль 8, 0, 199226
Восьмеричный: нуль, за которым следуют восьмеричные цифры (0,1,2,3,4,5,6,7) 01, 020, 07155
Шестнадцатеричный: Ох или ОХ, за которым следуют шестнадцатеричные цифры (0,1,2,3,4,5,6,7,8,9,А,В,С,D,Е,F) 0хА, 0x1 В8, 0Х00FF
Вещественная Десятичный: [цифры], [цифры] 5.7, .001, 35.
Экспоненциальный: [цифры][.][цифры]{Е|е}[+|-[цифры] 0.2Е6, .11е-3, 5Е10
Символьная Один или два символа, заключенных в апострофы "А", ‘ю’, "*", ‘db’ ‘\0’ ‘\n’, ‘\012’ "\x07\x07"
Строковая Последовательность символов, заключенная в кавычки "Здесь был Vasia", "\tЗначение r=\0хF5\"

Если требуется сформировать отрицательную целую или вещественную константу, то перед константой ставится знак унарной операции изменения знака (-), например: -218, -022, -0х3С, -4.8, -0.1е4.

Вещественная константа в экспоненциальном формате представляется в виде мантиссы и порядка. Мантисса записывается слева от знака экспоненты (Е или е), порядок – справа от знака. Значение константы определяется как произведение мантиссы и возведенного в указанную в порядке степень числа 10. Обратите внимание, что пробелы внутри числа не допускаются, а для отделения целой части от дробной используется не запятая, а точка.

Программист может задать тип константы самостоятельно. Могут быть опущены либо целая часть, либо дробная, но не обе сразу. Если указаны обе части, символ точки обязателен.

Символьные константы, состоящие из одного символа, занимают в памяти один байт и имеют стандартный тип char. Двухсимвольные константы занимают два байта и имеют тип int, при этом первый символ размещается в байте с меньшим адресом.

Символ обратной косой черты используется для представления:

· кодов, не имеющих графического изображения (например,
\а – звуковой сигнал, \n – перевод курсора в начало следующей строки);

· символов апострофа ("), обратной косой черты (\), знака вопроса (?) и кавычки (");

· любого символа с помощью его шестнадцатеричного или восьмеричного кода, например, \073, \0xF5. Числовое значение должно находиться в диапазоне от 0 до 255.

Последовательности символов, начинающиеся с обратной косой черты, называют управляющими, или escape-последовательностями. В таблице 7.2. приведены их допустимые значения. Управляющая последовательность интерпретируется как одиночный символ. Если непосредственно за обратной косой чертой следует символ, не предусмотренный табл. 7.2, результат интерпретации не определен. Если в последовательности цифр встречается недопустимая, она считается концом цифрового кода.


Таблица 7.2.

Управляющие последовательности в языке С++

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

"Издательский дом \"Питер\""

Все строковые литералы рассматриваются компилятором как различные объекты.

Строковые константы, отделенные в программе только пробельными символами, при компиляции объединяются в одну. Длинную строковую константу можно разместить на нескольких строках, используя в качестве знака переноса обратную косую черту, за которой следует перевод строки. Эти символы игнорируются компилятором, при этом следующая строка воспринимается как продолжение предыдущей. Например, строка

Символьная константа – это некоторый символ алфавита, заключенный в одиночные кавычки: "<символ_алфавита>" .

Примеры символьных констант: " a " " B " "=" "+" " F " "[" " d ".

Значением символьной константы является целое число, равное (American Standard Code for Information Interchange, Американский стандартный код обмена информацией) данного символа. Символьная константа имеет тип int(char) и представляется 16(8)-битной величиной.

В имеются коды, которые не отображаются при печати, а производят некоторые действия, например, перевод на новую строку (LF), подача звукового сигнала, гудка – BELL) и т. д. Для таких кодов на клавиатуре не предусмотрено отдельных клавиш, и при вводе с клавиатуры они набираются сочетанием определенных клавиш: например, нажатие клавиши Ctrl и G влечет за собой поступление в память кода "гудок", а при выводе символа, имеющего значение кода "гудок", компьютер подает звуковой сигнал.

Возникает вопрос: каким образом использовать подобные коды в программе? Для этого Си предоставляет два способа, имеющих непосредственное отношение к символьным константам.

Первый способ . Любой символ в можно определить в виде символьной константы следующим образом:

"\ddd" или "\xHHH",

где ddd – восьмеричный, а HHH шестнадцатеричный код символа. Ведущие нули в представлении кода символа можно не записывать. Таким образом, в соответствии с этим вышеуказанные примеры символьных констант можно записать

" a "

" B "

" F "

" d "

Символ, вызывающий подачу звукового сигнала, записывается в виде "\07", а символ, вызывающий перевод печати на новую строку – "\x0A".

Второй способ заключается в том, что часто используемые неотображаемые символы не нужно записывать их кодами, а можно использовать для них зарезервированные обозначения. Эти символы в Си выделены в класс управляющих символов, представленных в таблице 3.3.

Таблица 3.3. Управляющие символы

Символ Си Символ ASCII Название символа
Новая строка
Горизонтальная табуляция
Вертикальная табуляция
Шаг назад
Возврат каретки
Подача бланка
Гудок
Одинарная кавычка
Двойная кавычка
Обратная дробная черта
Вопрос

Если управляющие символы встречаются, например, в строке вывода, то они вызывают соответствующее действие. Первые шесть управляющих символов являются символами управления работой печатающего устройства: символ "новая строка " переводит печать на начало следующей строки; символ "горизонтальная табуляция " продвигает печать в текущей строке в очередную фиксированную позицию строки. По умолчанию позиции в строке фиксируются через каждые 8 символов. Фиксированные позиции можно изменять, используя так называемые ESC-последовательности, формат которых описывается в документации по принтеру.

Символ "вертикальная табуляция " продвигает печать на начало очередных фиксированных номеров строк, которые также определяются ESC-последовательностью принтера.

Символ "шаг назад " производит сдвиг печати в текущей строке на одну позицию назад, т.е. позволяет на одном и том же знакоместе напечатать некоторое количество символов.

Символ "подача бланка " производит пропуск оставшейся части текущего текста и начинает печать со следующего нового листа.

Седьмой символ таблицы "гудок " инициирует подачу звукового сигнала. Оставшиеся четыре символа не относятся, по сути, к управляющим, но они включены в таблицу, так как имеют аналогичные зарезервированные обозначения. Их обычное использование в строковых константах (см. следующий раздел 3.1.4.) в качестве символов могло бы привести к ошибке, а использование именно в таком виде позволяет печатать их в строке вывода.

Сказанное не относится к символу "вопрос ". По всей вероятности, символ "вопрос" попал в число зарезервированных символов в связи с тем, что в Си имеется операция, обозначаемая знаком "?", и в некоторых ситуациях это могло бы привести к неоднозначному толкованию конструкций языка. Знак "вопрос", как символьную константу, можно записать любым рассмотренным способом: "?" "\77" "x3F" "\?" .

В заключение раздела обращаем внимание на то, что символьные константы являются целыми константами. Следовательно, допустима запись и двухсимвольных констант, например, таких: "ab" "ta" "ma" "do". Однако в этом случае их необходимо обрабатывать как данные типа int. Если двухсимвольную константу попытаться присвоить переменной типа char, то произойдет потеря второго символа.

Двухсимвольную константу можно записать в виде "\ddC" или в виде "\xHHc", где С – символ алфавита отличный от восьмеричной цифры, с – символ, отличный от шестнадцатеричной цифры. Например, "\538" все равно что "+8", ибо компилятор воспринимает \53 как восьмеричный код символа +, за которым стоит символ 8. Аналогично "\x6DQ"воспринимается как "mQ", т.е. \x6D – шестнадцатеричный код символа m, за которым записан символ Q. Мы не советуем применять такие "хитроумные штучки", хотя Си предоставляет в этом плане широчайшие возможности.

Таблица символьного типа

Для работы с расширенным набором символов используется, таких как Unicode, тип wchar _ t (широкий символ, 16 бит в Windows, 32 ,бита в GNU/Linux , но может представляться и 8 битовым значением.

В стандарте С и С++ от 2011 года введены фиксированные символьные типы char16_t and char32_t для обеспечения недвусмысленного представления 16-битового и 32 битового преобразования Unicode форматов.