
- •Вопрос 5 Скалярные типы и выражения. Приведите пример простой программы.
- •Вопрос 6 Типы операций: операции присвоения и отношения. Примеры. Операция присваивания.
- •Вопрос7 Типы операций: логические, битовые и условные операции.
- •10) Условные операторы. Варианты условных операторов. Пример: Даны целые числа X, y. Вычислить max(X, y).
- •11) Условные конструкции. Оператор switch. Приведите примеры
- •12. Условные и циклические конструкции. Виды конструкций, что общего у них.
- •13.Циклические конструкции. Виды конструкций.
- •14Циклические констрккции.Цикл while
- •Вопрос15 Циклические конструкции. Цикл do...While. Приведите примеры.
- •Вопрос16 Циклические конструкции. Цикл for. Приведите примеры. Циклические конструкции. Цикл for
- •Вопрос17 Цикл for. Использование операции "запятая". Приведите примеры.
- •Вопрос18 Укажите особенности операторов go to, break, continue, return.
- •20Этапы решения задач на компьютере
- •21 Назначение препроцессора .Примеры использования директив препроцессора
- •1. Замена идентификаторов заранее подготовленными последовательностями символов;
- •2. Включение в программу текстов из указанных файлов;
- •3. Исключение из программы отдельных частей ее текста, условная компиляция;
- •4. Макроподстановка, то есть замена обозначения параметризованным текстом, формируемым препроцессором с учетом конкретных аргументов.
- •23Основные возможности функции scanf(). Приведите примеры
- •25Арифметические операции. Приведите примеры.
- •27 Указатели и адреса
- •28 Общие сведения о массивах
- •29Многомерные массивы. Работа с массивами с помощью указателей
- •30Общие сведения о функциях. Определение функции
- •31 Класс памяти (auto)
- •32Внешний класс памяти (extern)
- •33 Внешние глобальные объекты (extern)
- •33Внешние статические объекты (static).
- •34 Строки
- •35 Функция для работы со строками
28 Общие сведения о массивах
Массив представляет собой последовательность элементов одного типа. Каждому элементу массива соответствует индекс - целое неотрицательное число, определяющее его номер в последовательности. Первому элементу массива соответствует индекс 0. Элементы массива размещаются в памяти последовательно, друг за другом, как показано на следующем рисунке:
Рис.1.
Схема размещения в памяти элементов
массива b
При определении массива ему выделяется память так же, как массивам других алгоритмических языков. Но как только память для массива выделена, имя массива воспринимается как константный указатель того типа, к которому отнесены элементы массива. Однако это справедливо не всегда. Например, при использовании имени массива в операции sizeof, ее результатом является размер в байтах участка памяти, выделенного не для указателя, а для массива в целом. Исключением является и применение операции & (получение адреса) к имени массива. Результат операции - адрес начального (с нулевым индексом) элемента массива. В остальных случаях значением имени является адрес первого элемента массива, которое нельзя изменить.
Для создания массива компилятору необходимо знать тип данных и требуемый класс памяти, т.е. то же самое, что и для простой переменной (называемой скалярной). Кроме того, должно быть известно, сколько элементов имеет массив. Определение одномерного массива имеет вид:
<тип элементов массива> <имя массива> [<количество элементов в массиве>];.
Нумерация элементов в массиве начинается с нуля!
Массивы могут иметь те же типы и классы памяти, что и простые переменные. В некоторых случаях допустимо описание массива без указания количества его элементов, то есть без константного выражения в квадратных скобках. Например: extern unsigned long UL[]; является описанием внешнего массива, который определен в другой части программы, где ему выделена память и (возможно) присвоены начальные значения его элементам. Приведем еще несколько примеров описания массивов:
char alpha[26]; //Внешний массив, содержащий 26 символов.
main ()
{
static int nan[22]; //Статический массив, содержащий 22 целых числа.
extern char alpha[]; //Внешний массив, размер его указан выше.
float a[15]; //Автоматический массив, содержащий 15
//вещественных чисел.
}
29Многомерные массивы. Работа с массивами с помощью указателей
Многомерный массив представляет собой массив массивов, то есть массив, элементами которого служат массивы. Определение многомерного массива в общем случае должно содержать сведения о типе, размерности и количествах элементов каждой размерности, например описание: int ARRAY[4][3][6]; определяет массив, состоящий из четырех элементов, каждый из которых - двухмерный массив с размерами 3 на 6. В памяти массив ARRAY размещается в порядке возрастания самого правого индекса, то есть самый младший адрес имеет элемент ARRAY[0][0][0], затем идет элемент ARRAY[0][0][1] и т.д.
С учетом порядка расположения в памяти элементов многомерного массива нужно размещать начальные значения его элементов в списке инициализации. Например, конструкция:
int ARRAY [4][3][6] = {0,1,2,3,4,5,6,7}
инициализирует только первые 8 элементов этого массива:
ARRAY[0][0][0]=0, ARRAY[0][0][1]=1, ARRAY[0][0][2]=2, ARRAY[0][0][3]=3,
ARRAY[0][0][4]=4, ARRAY[0][0][5]=5, ARRAY[0][1][0]=6, ARRAY[0][1][1]=7.
При необходимости инициализировать только часть элементов многомерного массива, но они размещены не в его начале или не подряд, то можно вводить дополнительные фигурные скобки, каждая пара которых выделяет последовательность значений, относящихся к одной размерности. (Нельзя использовать скобки без информации внутри них.)
Следующее определение с инициализацией трехмерного массива:
int А[4][5][6] = { { {0} /*Нулевой элемент.*/ },/*Нулевой массив.*/
{ {100},/*Нулевой элемент.*/
{110, 111} /*Первый элемент.*/
}, /*Первый массив.*/
{ {200),/*Нулевой элемент.*/
{210},/*Первый элемент.*/
{220, 221, 222}/*Второй элемент.*/
}; /*Второй массив.*/
так задает некоторые значения его элементов:
А[0][0][0]=0,
А[1][0][0]=100, A[1][1][0]=110, A[1][1][1]=111,
А[2][0][0]=200, A[2][1][0]=210, A[2][2][0]=220,
A[2][2][1]=221, A[2][2][2]=222.
Если многомерный массив при определении инициализируется, то его самая левая размерность может в скобках не указываться. Количество элементов компилятор определяет по числу членов в инициализирующем списке. Например, определение:
float matrix [ ][5] = { {1}, {2}, {3} };
формирует массив matrix с размерами 3 на 5, но не определяет явно начальных значений всех его элементов.
Как и в случае одномерных массивов, доступ к элементам многомерных массивов возможен с помощью индексированных переменных и с помощью указателей. Следующая программа иллюстрирует оба подхода к организации доступа к элементам массива.
#include <iostream.h>
void main()
{
int b[3][2][4] = { 0, 1, 2, 3,
4, 5, 6, 7,
10, 11, 12, 13,
14, 15, 16, 17,
100, 101, 102, 103,
104, 105, 106, 107 };
//Адрес массива b[ ][ ][ ].
cout<< "\n b= " << b;
// Адрес массива b[0][ ][ ].
cout<< "\n *b= " << *b;
// Адрес массива b[0][0][].
cout<< "\n **b= " << **b;
// Элемент b[0][0][0].
cout<< "\n ***b= " << ***b;
// Адрес массива b[1][ ][ ].
cout<< "\n *(b+1) = " << *(b+1);
// Адрес массива b[2][][].
cout<< "\n *(b+2) = " << *(b+2);
// Адрес массива b[0][1][ ].
cout<< "\n *(*b+1)= " << *(*b+1);
//Вывод элемента b[1][1][1] двумя способами.
cout<< "\n *(*(*(b+1)+1)+1)= " << *(*(*(b+1)+1)+1);
cout<< "\n b[1][1][1]= " << b[1][1][1];
}
В общем случае для трехмерного массива индексированный элемент b[i][j][k] соответствует выражению *(*(*(b + i) + j) + k).
Компилятор всегда реализует доступ к элементам массива с помощью указателя и операции разыменования. Если в программе использована, например, такая индексированная переменная: AR[i][j][k], принадлежащая массиву type AR[N][М][L], где N, M, L - целые положительные константы, то последовательность действий компилятора такова:
выбирается адрес начала массива, то есть целочисленное значение указателя AR, равное (unsigned long)AR;
добавляется смещение i * (M * L) * sizeof(type) для вычисления начального адреса i-го массива с размерами M на L, входящего в исходный трехмерный массив;
добавляется смещение для вычисления начального адреса j-й строки (одномерный массив), включающей L элементов. Теперь смещение равно (i * (M * L) + j * L) * sizeof(type);
добавляется смещение для получения адреса k-го элемента в строке, то есть получается адрес (unsigned long) (i * (M * L) +j * L + k) * sizeof(type);
применяется разыменование, то есть обеспечивается доступ к содержимому элемента по его адресу: * ((unsigned long) (i * (M * L) +j * L + k)).