Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры по ямп.docx
Скачиваний:
4
Добавлен:
01.04.2025
Размер:
161.76 Кб
Скачать

1.Типы данных языка С++.

имя

размер

Представляемые значения

диапазон

bool

1 байт

логические

false, true

(signed) char

1

символы  целые числа

от –128 до 127

wchar_t

2

символы Unicode

от 0 до 65535

(signed) short int

2

целые числа

от -32768 до 32767

(signed) int

зависит от реализации  (в последних компиляторах обычно 4 байта)

целые числа

(signed) long int

4

целые числа

от -2147483648 до 2147483647

(signed) long long int  (signed) __int64 (MS)

8

целые числа

От –много до много

float

4

вещественные числа

от 1.175494351e–38  до 3.402823466e+38

double

8

вещественные числа

от 2.2250738585072014e–308  до 1.7976931348623158e+308

long double

зависит от реализации

вещественные числа

В языке C++ также существуют перечислимый тип – enum, который является подмножеством целого типа, и пустой тип – void, который имеет специальное назначение. Он используется для объявления функций, которые не возвращают никакого значения, а также для объявления указателей на значение типа void. Такие указатели могут быть преобразованы к указателям на любой другой тип.

В языке С++ можно объявлять структуры и так называемые объединения.

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

Приставка unsigned необходима для того, чтобы диапазон начинался от 0 до какого-то числа (int, long int, long long int).

2.Операции языка С++. Приоритет операций.

Знак операции

наименование

ассоциативность

::

Разрешение области видимости

Слева направо

( )    [ ]    .    ->  ++    --  static_cast  dynamic_cast  reinterpret_cast  const_cast 

Первичные  Постфиксный инкремент и декремент  Преобразование с проверкой во время компиляции  Преобразование с проверкой во время выполенения  Преобразование без проверки  Константное преобразование 

Слева направо

-    ~    !    *    &  ++    --  sizeof  (<тип>)<выражение> 

Унарные  Префиксный инкремент и декремент  Вычисление размера  Приведение типа 

Справа налево

.*    ->*

Выбор члена класса

Слева направо

*    /    %

Мультипликативные

Слева направо

+    -

Аддитивные

Слева направо

<<    >>

Сдвиг

Слева направо

<    >    <=    >=

Отношение

Слева направо

==    !=

Отношение

Слева направо

&

Поразрядное И

Слева направо

^

Поразрядное исключающее ИЛИ

Слева направо

|

Поразрядное ИЛИ

Слева направо

&&

Логическое И

Слева направо

||

Логическое ИЛИ

Слева направо

? :

Условная операция

Справа налево

=    *=    /=    %=    +=    -=    <<=    >>=    &=    ^=    |=

Простое и составное присваивания

Справа налево

throw

Генерация исключения

Слева направо

,

Операция последовательного вычисления

Слева направо

:: – операция разрешения области видимости. При повторном объявлении имени во вложенном блоке или классе предыдущие объявления оказываются скрытыми. Однако скрытое имя члена класса можно использовать, квалифицировать его именем класса при помощи операции разрешения области видимости. Скрытое глобальное имя можно использовать, если квалифицировать его унарной операцией разрешения области видимости.

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

[ ] – индексное выражение, используется для работы с массивами.

. и -> – выбор элемента, используются при работе с классами, структурами и объединениями.

- – унарный минус.

~ – обратный код (см. лекцию 8).

! – логическое отрицание.

* – косвенная адресация (см. лекцию 5).

& – адресация (см. лекцию 5).

Операции ++ и -- инкрементируют (увеличивают на 1) и декрементируют (уменьшают на 1) свой операнд. Операнд должен иметь целый, вещественный тип или быть указателем. Операции инкремента и декремента могут записываться как перед своим операндом (префиксная форма записи), так и после него (постфиксная форма записи). При префиксной форме записи операнд сначала инкрементируется или декрементируется, а затем его новое значение участвует в дальнейшем вычислении выражения, содержащего данную операцию. При постфиксной форме записи операнд инкрементируется или декрементируется лишь после того, как его старое значение участвует в вычислении выражения. Таким образом, результатом операций инкремента и декремента является либо новое, либо старое значение операнда. Например, если переменная i = 0, то выражение a[++i] = 1 меняет элемент a[1], а выражениеa[i++] = 1 меняет элемент a[0]. В обоих случая переменная i получает новое значение, равное 1.

sizeof – вычисление размера в байтах переменной или типа.

Операция приведения типа записывается следующим образом: (<новый тип>)<выражение>. Например,(long int)n приводит переменную n к типу long int. При преобразовании типов надо помнить, что при преобразовании между знаковыми/беззнаковыми значениями и при преобразовании от типа с большей размерностью к типу с меньшей размерностью могут возникнуть ошибки. Более безопасным способом преобразования типов является использование операций static_cast, dynamic_cast, reinterpret_cast иconst_cast.

% – остаток от деления.

3.Структура программы на языке С++.

Операторы управляют процессом выполнения программы. Набор операторов языка С++ содержит все управляющие конструкции структурного программирования.

Составной оператор ограничивается фигурными скобками. Все другие операторы заканчиваются точкой с запятой.

Пустой оператор –  ;

Пустой оператор – это оператор, состоящий только из точки с запятой. Он может появиться в любом месте программы, где по синтаксису требуется оператор. Выполнение пустого оператора не меняет состояния программы.

Составной оператор –  {...}

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

Оператор-переключатель

Оператор-переключатель предназначен для выбора одного из нескольких альтернативных путей выполнения программы. Вычисление оператора-переключателя начинается с вычисления выражения, после чего управление передается оператору, помеченному константным выражением, равным вычисленному значению выражения. Выход из оператора-переключателя осуществляется оператором break. Если значение выражения не равно ни одному константному выражению, то управление передается оператору, помеченному ключевым словом default, если он есть.

Оператор цикла с предусловием while (<выражение>) <оператор>

Оператор цикла с постусловием do <оператор> while <выражение>;

В языке C++ этот оператор отличается от классической реализации цикла с постусловием тем, что при истинности выражения происходит продолжение работы цикла, а не выход из цикла.

Оператор пошагового цикла for ([<начальное выражение>];

[<условное выражение>];

[<выражение приращения>])

<оператор>

Оператор разрыва  break;

Оператор разрыва прерывает выполнение операторов while, do, for и switch. Он может содержаться только в теле этих операторов. Управление передается оператору программы, следующему за прерванным. Если оператор разрыва записан внутри вложенных операторов while, do, for, switch, то он завершает только непосредственно охватывающий его оператор.

Оператор продолжения  continue;

Оператор продолжения передает управление на следующую итерацию в операторах цикла while, do,for. Он может содержаться только в теле этих операторов. В операторах do и while следующая итерация начинается с вычисления условного выражения. В операторе for следующая итерация начинается с вычисления выражения приращения, а затем происходит вычисление условного выражения.

Оператор возврата return [<выражение>];

Оператора возврата заканчивает выполнение функции, в которой он содержится, и возвращает управление в вызывающую функцию. Управление передается в точку вызывающей функции, непосредственно следующую за оператором вызова. Значение выражения, если она задано, вычисляется, приводится к типу, объявленному для функции, содержащей оператор возврата, и возвращается в вызывающую функцию. Если выражение опущено, то возвращаемое функцией значение не определено.

С формальной точки зрения операторы break, continue и return не являются операторами структурного программирования. Однако их использование в ограниченных количествах оправдано, когда они упрощают понимание программы и позволяют избегать больших вложенных структур. Например, мы проверяем входные данные на аномалии. Если не использовать эти операторы, то всю обработку придется вложить в условный блок, что ухудшает читабельность программы. Вместо этого можно написать небольшой условный блок, который организует выход из функции при неверных исходных данных.

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

5. Препроцессор. Директивы препроцессора.

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

включение в программу текстов из указанных файлов;

замена идентификаторов последовательностями символов;

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

2.3.1. Включение файлов

Включение файлов производиться с помощью директивы #include, которая имеет следующий синтаксис: 

#include <путь>

#include "путь"

Угловые скобки здесь являются элементом синтаксиса.

Директива #include включает содержимое файла, путь к которому задан, в компилируемый файл вместо строки с директивой. Если путь заключен в угловые скобки, то поиск файла осуществляется в стандартных директориях. Если путь заключен в кавычки и задан полностью, то поиск файла осуществляется в заданной директории, а если путь полностью не задан – в текущей директории. С помощью это директивы Вы можете включать в текст программы как стандартные, так и свои файлы.

Во включаемый файл можно поместить, например, общие для нескольких исходных файлов определения именованных констант и макроопределения. Включаемые файлы используются также для хранения объявлений внешних переменных и абстрактных типов данных, разделяемых несколькими исходными файлами. Более подробную информацию об использовании заголовочных файлов см. в лекции 9.

Кроме того, как было указано выше, в языке С++ ряд функций, такие как функции ввода/вывода, динамического распределения памяти и т.д., не являются элементом языка, а входят в стандартные библиотеки. Для того чтобы пользоваться функциями стандартных библиотек, необходимо в текст программы включать так называемые заголовочные файлы (в описании каждой функции указывается, какой заголовочный файл необходим для неё). Это также делается с помощью директивы препроцессора #include.

Директива #include может быть вложенной. Это значит, что она может встретиться в файле, включенном другой директивой #include. Допустимый уровень вложенности директив #include зависит от реализации компилятора.

2.3.2. Макроподстановки

Макроподстановки реализуются директивой #define, которая имеет следующий синтаксис: 

#define <идентификатор> <текст>

#define <идентификатор>(<список параметров>) <текст>

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

Текст представляет собой набор лексем, таких как ключевые слова, константы, идентификаторы или выражение. Один или более пробельных символов должны отделять текст от идентификатора (или от заключённых в скобки параметров). Если текст не умещается на строке, то он может быть продолжен на следующей строке, для этого следует набрать в конце строки символ «обратный слэш» и сразу за ним нажать клавишу «ВВОД».

Текст может быть опущен. В этом случае все экземпляры идентификатора будут удалены из исходного текста программы. Тем не менее, сам идентификатор рассматривается как определённый.

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

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

После того как выполнена макроподстановка, полученная строка вновь просматривается для поиска других имен макроопределений. При повторном просмотре не принимается к рассмотрению имя ранее произведенной макроподстановки. Поэтому директива #define x x не приведет к зацикливанию препроцессора.

Вызов MULT(x + y, z) будет заменен на ((x + y) * (z)). При отсутствии внутренних скобок получилось бы(x + y * z), что неверно.

Макровызов MAX(i, a[i++]) заменится на ((i) > (a[i++])) ? (i) : (a[i++])). Результат вычисления непредсказуем.

В директиве #define две лексемы могут быть «склеены» вместе. Для этого их нужно объединить знаками ## (слева и справа допустимы пробельные символы). Препроцессор объединяет такие лексемы в одну. Например, макроопределение #define VAR(i, j) i ## j  при макровызове VAR(x, 6) образует идентификатор x6.

Символ #, помещаемый перед аргументом макроопределения, указывает на необходимость преобразования его в символьную строку. При макровызове конструкция #<формальный параметр>заменяется на "<фактический параметр>".

Замены в тексте можно отменить директивой #undef, которая имеет следующий синтаксис: 

#undef <идентификатор>

Директива #undef отменяет действие текущего определения #define для идентификатора. Чтобы отменить макроопределение, достаточно задать его идентификатор. Задание списка параметров не требуется. Не является ошибкой применение директивы #undef к идентификатору, который ранее не был определён или действие которого уже отменено.

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

6.Массивы в языке С++.

Массив – это совокупность данных, которая обладает следующими свойствами:

все элементы массива имеют один и тот же тип;

массив имеет одно имя для всех элементов;

доступ к конкретному элементу массива осуществляется по индексу (индексам).

1. Объявление массива

Объявление массива имеет следующий синтаксис:

<спецификация типа> <имя> [<константное выражение>];

<спецификация типа> <имя> [ ];

Здесь квадратные скобки являются элементом синтаксиса, а не признаком необязательности конструкции.

Объявление массива может иметь одну из двух синтаксических форм, указанных выше. Квадратные скобки, следующие за именем, – признак того, что переменная является массивом. Константное выражение, заключенное в квадратные скобки определяет число элементов в массиве. Индексация элементов массива в языке C++ начинается с нуля. Таким образом, последний элемент массива имеет индекс на единицу меньше, чем число элементов массива.

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

Многомерный массив, или массив массивов, объявляется путем задания последовательности константных выражений в квадратных скобках, следующей за именем: <спецификация типа> <имя> [<константное выражение>][<константное выражение>] ... ;

Каждое константное выражение определяет количество элементов в данном измерении массива, поэтому объявление двумерного массива содержит два константных выражение, трехмерного – три и т.д.

Массив может состоять из элементов любого типа, кроме типа void и функций, т.е. элементы массива могут иметь базовый, перечислимый, структурный тип, быть объединением, указателем или массивом.

2. Инициализация массивов

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

Наличие списка инициализаторов в объявлении массива позволяет не указывать число элементов по его первой размерности. В этом случае количество элементов в списке инициализаторов и определяет число элементов по первой размерности массива. Тем самым определяется размер памяти, необходимой для хранения массива. Число элементов по остальным размерностям массива, кроме первой, указывать обязательно.

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

Примеры инициализации массивов

Обратите внимание, что не существует присваивания массиву, соответствующего описанному выше способу инициализации.

3. Работа с массивами

3.1. Доступ к элементу массива

Для доступа к конкретному элементу массива используются так называемые индексные выражения:

<имя массива>[<целочисленное выражение>]

Здесь квадратные скобки являются требованием синтаксисам языка, а не признаком необязательности конструкции.

Индекс массива может быть не только константой, но и выражением, которое имеет целочисленный тип, например, a[i + 1] (здесь a должно быть именем ранее объявленного массива, а i – переменной целого типа).

Объявление массива и индексное выражение, используемое для доступа к элементу массива, имеют схожий синтаксис. Различаются они по месту в программе. Это особенно важно, когда мы определяем индекс последнего элемента массива. Как было сказано ранее, индексы элементов массива в языке C начинаются с 0, и номер последнего элемента на 1 меньше количества элементов массива. Поэтому если Вы объявили массив xиз 10 элементов, Вы не можете написать индексное выражение x[10], т.к. в этом случае Вы пытаетесь обратиться к элементу с индексом 10, которого нет в Вашем массиве. Компилятор не выдаст сообщения об ошибке, но результаты работы такой программы будут непредсказуемы.

Имя массива является адресом его начала! Оно имеет тип константный указатель на <тип элементов массива>. Конструкция a[i] эквивалентна *(a + i) (см. лекцию 5).

Для многомерного массива надо указать соответствующее количество индексов в квадратных скобках.

3.2. Обработка массивов

Для обработки элементов массива обычно используется оператор пошагового цикла for.

Для обработки многомерного массива используется соответствующее количество циклов.

Массивы не самодостаточны в том смысле, что не гарантируется хранение информации о количестве элементов вместе с самим массивом. В большинстве реализаций С++ отсутствует проверка диапазона индексов для массивов. Таков традиционный низкоуровневый подход к массивам. Более совершенное понятие массива можно реализовать при помощи классов.

В С++ массивы тесно связаны с указателями. Имя массива можно использовать в качестве указателя на его первый элемент. Гарантируется осмысленность значения указателя на элемент, следующий за последним элементом массива. Это важно для многих алгоритмов. Но ввиду того, что такой указатель на самом деле не указывает ни на какой элемент массива, его нельзя использовать ни для чтения, ни для записи. Результат получения адреса элемента массива, предшествующего первому, не определён, и такой операции следует избегать.

Неявное преобразование имени массива в указатель на его первый элемент широко используется в вызовах функций.

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

При объявлении многомерного массива как параметра функции можно опустить только первую размерность.

Это ограничение при желании можно обойти. Правда, при этом возникают другие проблемы (см. пример 3 в конце лекции).

3.3. Ввод/вывод массивов

В языке C нет возможности вводить и выводить весь массив одним оператором ввода/вывода. Можно вводить и выводить только один элемент массива. Следовательно, для того чтобы ввести весь массив, надо использовать цикл.

Вывод также осуществляется в цикле.