Слайд 2Массивы
Инициализация массивов.
Размерность массива.
Динамические массивы.
Многомерные массивы.
Слайд 3МАССИВЫ.
Массивы представляют собой ограниченную упорядоченную совокупность однотипных величин.
Каждая отдельная величина
называется компонентой массива.
Вся совокупность компонент определяется одним именем.
Слайд 4МАССИВЫ.
Элементы массива нумеруются с нуля.
При описании массива используются те же
модификаторы, что и для простых переменных:
класс памяти, const и инициализатор.
Описание
массива отличается от описания простой переменной наличием после имени квадратных скобок, в которых задается количество элементов массива (размерность):
float a [10];
// описание массива из 10 вещественных чисел
Слайд 5Инициализация массивов
Инициализирующие значения для массивов записываются в фигурных скобках.
Значения элементам
присваиваются по порядку.
Слайд 6Инициализация массивов
Если элементов в массиве больше, чем инициализаторов, элементы, для
которых значения не указаны, обнуляются.
Пример:
int b[5] = {3,2,1};
// b[0]=3,
b[1]=2, b[2]=1, b[3]=0, b[4]=0
Слайд 7Размерность массива
Размерность массива может быть задана только целой положительной константой
или константным выражением
Последний элемент массива имеет номер, на единицу меньший
заданной при его описании размерности.
Слайд 8Размерность массива
Если при описании массива не указана размерность, должен присутствовать
инициализатор.
в этом случае компилятор выделит память по количеству инициализирующих
значений.
Размерность может быть опущена также в списке формальных параметров.
Слайд 9Размерность массива
Для доступа к элементу массива после его имени указывается
номер элемента (индекс)
в квадратных скобках.
Слайд 10При обращении к элементам массива автоматический контроль выхода индекса за
границу массива не производится.
Слайд 11Размерность массива
// подсчитывается сумма элементов массива
#include
int main(){
const int
n = 10;
int i, sum;
int mas[n] = {3, 4,
5, 4, 4};
for (i = 0, sum = 0; i
cout << "Сумма элементов: " << sum;
return 0; }
Пример:
Слайд 12Размерность массива
Идентификатор массива является константным указателем на его нулевой элемент
для
массива из предыдущего листинга имя mas — это то же
самое, что &mas[0], а к i-му элементу массива можно обратиться, используя выражение *(mas+i).
Слайд 13Размерность массива
// программа копирует все элементы массива a в массив
b
int а[100], b[100];
int *pa = а; // или int *p =
&а[0];
int *pb = b;
for(int i=0; i<100; i++)
*pb++ = *pa++; // или pb[i] = pa[i];
Можно описать указатель,
присвоить ему адрес начала массива
и работать с массивом через указатель
Пример:
Слайд 14Динамические массивы
Динамические массивы создают с помощью операции new, при этом
необходимо указать тип и размерность.
Слайд 15Динамические массивы нельзя инициализировать при создании, и они не обнуляются!!!
Слайд 16Динамические массивы
int n = 100;
float *р = new float [n];
создается
указатель на float,
в динамической памяти отводится непрерывная область, для размещения
100 элементов вещественного типа,
адрес ее начала записывается в указатель р.
Пример:
Слайд 17Динамические массивы
например, к элементу номер 5 приведенного выше массива можно
обратиться как
р[5] или *(р+5).
Доступ к элементам динамического массива осуществляется
точно так же, как к статическим.
Слайд 18Динамические массивы
int n = 100;
float *q = (float *) malloc(n
* sizeof(float));
Операция преобразования типа, записанная перед обращением к функции malloc,
требуется потому, что функция возвращает значение указателя тина void*, а инициализируется указатель на float.
Альтернативный способ создания динамического массива — использование функции malloc библиотеки С.
Слайд 19Динамические массивы
Память, зарезервированная под динамический массив с помощью new [],
должна освобождаться оператором delete[],
а память, выделенная функцией malloc —
посредством функции free
delete [] p; free (q);
При несоответствии способов выделения и освобождения памяти результат не определен
Размерность массива в операции delete не указывается, но квадратные скобки обязательны
Слайд 20Многомерные массивы
Многомерные массивы задаются указанием каждого измерения в квадратных скобках.
Слайд 21Многомерные массивы
Пример:
int matr [6][8];
В памяти такой массив располагается в последовательных
ячейках построчно.
Многомерные массивы размещаются так, что при переходе к следующему
элементу быстрее всего изменяется последний индекс.
Слайд 22Многомерные массивы
Для доступа к элементу многомерного массива указываются все его
индексы.
например, matr[i][j]
или более экзотическим способом: *(matr[i]+j)
или *(*(matr +i)+j)
Это возможно, поскольку
matr[i] является адресом начала i-й строки массива.
Слайд 23М А С С И В Ы
При инициализации многомерного массива
он представляется :
либо как массив из массивов, при этом каждый
массив заключается в свои фигурные скобки
в этом случае левую размерность при описании можно не указывать
либо задается общий список элементов в том порядке, в котором элементы располагаются в памяти
Примеры:
int mass2[][2] ={{1, 1},{0. 2},{1, 0}};
int mass2[3][2] = {1, 1, 0, 2, 1, 0};
Слайд 24Динамические многомерные массивы
Динамические многомерные массивы
Для создания динамического многомерного массива необходимо
указать в операции new все его размерности
самая левая размерность может
быть переменной
Пример:
int nstr = 5;
int ** m = (int **) new int [nstr][10];
Слайд 25Динамические многомерные массивы
Более универсальный и безопасный способ выделения памяти под
двумерный массив, когда обе его размерности задаются на этапе выполнения
программы, приведен ниже:
int nstr; nstb;
cout << " Введите количество строк и столбцов :";
cin >> nstr >> nstb;
int **a = new int *[nstr]; // 1
for(int i = 0; ia[i] = new int [nstb]; // 3
1
объявляется переменная типа «указатель на указатель на int» и выделяется память под массив указателей на строки массива
2
организуется цикл для выделения памяти под каждую строку массива
3
каждому элементу массива указателей на строки присваивается адрес начала участка памяти, выделенного под строку двумерного массива
Слайд 26Динамические многомерные массивы
Процессы, происходящие в памяти при выполнении предыдущего фрагмента
программы можно проиллюстрировать следующей схемой:
Слайд 27Динамические многомерные массивы
Освобождение памяти из-под массива с любым количеством измерений
выполняется с помощью операции delete [].
Слайд 28Указатель на константу удалить нельзя!!!
Слайд 29Обратите внимание
Если при описании переменной используются одновременно префикс * (указатель)
и суффикс [] (массив), то переменная интерпретируется как массив указателей,
а не указатель на массив:
int *p[10]; — массив из 10 указателей на int
Для правильной интерпретации объявлений полезно запомнить мнемоническое правило:
«суффикс привязан крепче префикса».
Слайд 31СТРОКИ.
Строка представляет собой массив символов, заканчивающийся нуль-символом.
Нуль-символ — это символ
с кодом, равным 0, что записывается в виде управляющей последовательности
'\0'.
По положению нуль-символа определяется фактическая длина строки.
Слайд 32С Т Р О К И
Строку можно инициализировать строковым литералом:
char
str[10] = "Vasia";
// выделено 10 элементов с номерами от 0
до 9
// первые элементы - 'V','а','s','i','а','\0'
Слайд 33С Т Р О К И
Если строка при определении инициализируется,
ее размерность можно опускать
компилятор сам выделит соответствующее количество байт
char str[]
= "Vasia";
// выделено и заполнено 6 байт
Слайд 34С Т Р О К И
Оператор
char *str = "Vasia"
создает не строковую переменную,
а указатель на строковую константу,
изменить
которую невозможно
к примеру, оператор str[1]='o' не допускается
Слайд 35Знак равенства перед строковым литералом означает инициализацию,
а не присваивание!!!
Слайд 36С Т Р О К И
Операция присваивания одной строки другой
не определена и может выполняться с помощью цикла или функций
стандартной библиотеки
поскольку строка является массивом
Библиотека (<сstring.h>) предоставляет возможности копирования, сравнения, объединения строк, поиска подстроки, определения длины строки и т. д., а также содержит специальные функции ввода строк и отдельных символов с клавиатуры и из файла
Слайд 37С Т Р О К И
Пример :
// Программа запрашивает пароль
не более трех раз.
#include
#include
int main(){
char s[80],
passw[] = "kuku"; // passw - эталонный пароль.
// Можно описать как *passw = "kuku";
int i, k = 0;
for (i=0; !k && i<3; i++){
printf("\nвведите пароль:\n");
gets(s); // функция ввода строки
if (strstr(s,passw))k = 1; // функция сравнения строк
}
if (k) printf("\nпароль принят");
else printf("\nпароль не принят");
return 0;
}
Слайд 38С Т Р О К И
При работе со строками часто
используются указатели
Очевидный алгоритм имеет вид:
Рассмотрим процесс копирования строки src в
строку dest.
char src[10], dest[10];
for (int i = 0; i<=strlen(src); i++) dest[i] = src[i];
Таким образом, строка фактически просматривается дважды.
Длина строки определяется с помощью функции strlen, которая вычисляет длину, выполняя поиск нуль-символа.
Слайд 39С Т Р О К И
Более эффективным будет использовать проверку
на нуль-символ непосредственно в программе:
#include
int main(){
char *src =
new char [10];
char *dest = new char [10], *d = dest;
cin >> src;
while ( *src != 0) *d++ = *src++;
*d = 0; // завершающий нуль
cout << dest;
return 0;
}
Слайд 40Обратите внимание
В приведенном примере, результат операции присваивания — передаваемое значение,
которое, собственно, и проверяется в условии цикла, поэтому можно поставить
присваивание на место условия, а проверку на неравенство нулю опустить
(при этом завершающий нуль копируется в цикле, и отдельного оператора для его присваивания не требуется).
В результате цикл копирования строки принимает вид:
while ( *d++ = *src++);
Слайд 41С Т Р О К И
Оба способа работы со строками
(через массивы или указатели) приемлемы и имеют свои плюсы и
минусы, но в общем случае лучше не изобретать велосипед, а пользоваться функциями библиотеки или определенным в стандартной библиотеке C++ классом string, который обеспечивает индексацию, присваивание, сравнение, добавление, объединение строк и поиск подстрок, а также преобразование из С-строк, то есть массивов типа char, в string, и наоборот.
Слайд 42С Т Р О К И
Распространенные ошибки при работе со
строками:
отсутствие нуль-символа
выход указателя при просмотре строки за ее пределы
Слайд 43С Т Р О К И
Строки string не обязательно должны
состоять из символов типа char.
Это позволяет использовать любой набор
символов (не только ASCII), но для произвольного набора следует определить собственную операцию копирования, что может снизить эффективность работы.