- •Аннотация
- •Предисловие
- •Г л а в а 1. Введение в указатели
- •§1. Понятие указателя. Операции разыменования и разадресации
- •§2. Инициализация и присваивание указателей
- •§3. Передача параметров функций с помощью указателей.
- •§4. Распределение динамической памяти.
- •4.1. Операция new
- •4.2. Операция delete
- •Упражнения, тесты.
- •Указатели и массивы
- •§1. Связь указателей и массивов
- •1.1. Указатели и одномерные массивы
- •1.2. Указатели и матрицы
- •Int MyFun (int *X, int n)
- •§3. Операции над указателями при работе с массивами.
- •3.1. Арифметические операции
- •3.2. Операции сравнения.
- •§4. Использование операций над указателями при работе с одномерными массивами
- •4.1. Использование индексов
- •4.2. Указатель в качестве параметра цикла
- •4.3. Использование указателя и индекса
- •§5. Строки.
- •5.1. Общая характеристика строк.
- •5.2. Примеры алгоритмов работы со строками.
- •5.3. Анализ строковых функций.
- •§6. Использование операций над указателями при работе со статической матрицей.
- •Упражнения, тесты.
- •Массивы указателей
- •§1. Статический массив указателей
- •§2. Частично динамическая матрица.
- •Int arr_of_size[n];
- •§3. Статический массив строк
- •§4. Динамический массив указателей
- •4.1. Указатель на указатель
- •4.2. Динамические “матрицы”.
- •Int *arr_of_size;
- •4.3. Передача матрицы в функцию
- •Int a[10]; FunArr1(a, 10,…);
- •Упражнения, тесты.
- •Задачи второго среднего уровня.
- •Структуры и другие типы, определяемые пользователем
- •§1. Структуры
- •Объявление структуры
- •1.2. Работа со структурой.
- •1.3. Вложенные структуры и статические массивы в структурах
- •1.4. Статический массив структур
- •§2. Cтруктуры и указатели
- •2.1. Указатели в структуре.
- •2.2. Указатели на структуру
- •2.3. Динамический массив структур
- •2.4. Ссылка на структуру.
- •2.5. Указатели и вложенные структуры
- •§3. Cтруктуры и функции
- •3.1. Передача полей структуры в функцию.
- •Void MyFun1 (int X, float &y, int *u1, float *u2, char *s);
- •3.2. Передача всей структуры в функцию
- •Void Fun1 (tst s,…);
- •Void Fun2 (tst & s,…);
- •Void Fun3 (tst* s,…);
- •§4. Cтруктуры и классы.
- •§5. Объединения.
- •Представление вещественных чисел в памяти компьютера.
- •§6. Поля битов (битовые поля)
- •Ввод в ы в о д
- •Symbol Code16 Code10 Code2
- •§7. Перечисления
- •Какие из строк (//1 – //9) правильные?
Int arr_of_size[n];
2) Определяем значения этого массива, например, вводим их с экрана или другим способом:
for (int i=0; i<n; i++) cin>>arr_of_size[i];
3) Аналогично резервируем память для каждой строки матрицы, размер которой берём из массива arr_of_size:
for (int i=0; i<n; i++)
M[i]= new int[arr_of_size[i]];
Работа с такой “матрицей” выполняется аналогично, только надо учитывать, что тело цикла для анализа, например, всех элементов строки выполняется не одинаковое для всех строк m раз, а разное количество, то есть arr_of_size[i] раз, где i — номер строки матрицы.
Кроме этого, количество элементов в строках “матрицы” может меняться по некоторому правилу. Например, рассмотрим следующий фрагмент:
for (int i=0; i<n; i++) M[i]=new int[i+1];
В первой по порядку строке (i=0) резервируем память для одного элемента, во второй строке – для двух и т. д., в i-й строке резервируем память для (i+1) элемента Другими словами, создаём в памяти нижний треугольник квадратной “матрицы” относительно главной диагонали.
§3. Статический массив строк
Статический массив указателей можно использовать также для работы с массивом строк, количество которых определено в виде константы. Пусть нам надо представить в виде массива список студентов группы (фамилия, инициалы).
Это можно сделать без использования массива указателей, обычным образом объявив матрицу символов:
char FIO[40][20];
Здесь 40 — максимальное количество студентов в группе, а длина каждой фамилии с именем и отчеством не превышает 19 символов (букв). Напомним, что один байт будет использоваться для хранения символа конца строки. При таком определении массива его размеры всегда фиксированы: 40*20= 850 байт. Как для фамилии “Шилдт Г.”, так и для фамилии “Страуструп Б.”, то есть независимо от длины строки, всегда выделяется одно и то же количество байтов (20), указанное в качестве предельного значения второго индекса матрицы FIO.
При определении матрицы один из его предельных размеров (самого левого индекса) можно не указывать:
char FIO2[][20] ={“Петров П. И.”, “Иванов И. С.”, “Сидоров С. К.”};
В этом случае количество элементов массива строк (количество фамилий) определяется инициализацией. Но и в этом случае каждая из трёх строк по-прежнему занимает максимальный объём памяти, равный 20 байтам.
При использовании массива указателей память распределяется гораздо рациональнее. Объявляем статический массив указателей фиксированной размерности n, где n – константа и определяет количество фамилий:
const n=30; char * S[n];
Память под каждую строку резервируем на этапе выполнения в зависимости от её длины. Для этого объявляем дополнительную строку и резервируем для неё (для одной строки, а не для массива!) память максимального размера:
char *t= new char [20];
Затем в цикле вводим строку, для каждой строки массива S динамически выделяем память, размер которой равен длине введённой строки и введённую строку копируем в i–ю строку массива S:
for(int i=0;i<n;i++)
{ gets(t);
S[i]=new char (strlen(t));
strcpy( S[i],t);
}
После этого с S[i] работаем как с обычной строкой. Более того, аналогично, как и в 5.1, можно переставлять две строки (фамилии), не меняя их физически в памяти.
Одномерный массив указателей на строки можно проинициализировать при объявлении:
char *S2[]={“Петровский П. И.”, “Иванов И. С.”, “Сидоров С. К.”};
При таком объявлении компилятор размещает в памяти три строковые константы длиной 17, 13 и 14 байт соответственно, а их адреса становятся значениями элементов массива указателей S2[0], S2[1], S2[2].
Пример 1. (+). Работа со статическим массивом строк как со статическим массивом указателей на строки. В каждой строке массива строк удалить введённый символ.
int main() { const n=5;
/* Объявляем статический массив указателей фиксированной размерности n, где n – константа.*/
char *S[n]; char C,*p, t[40]; cout<<"Symbol"; C=getch();
unsigned K=0; cout << endl<<endl;
for(int i=0;i<n;i++)
{ gets(t);
/* Для каждой строки динамически выделяем память, размер которой равен длине строки */
S[i]=new char [strlen(t)];
strcpy( S[i],t); // Введённую строку копируем в i–ю строку массива S
}
for(int i=0;i<n;i++)
{ p=S[i]; // В p засылаем адрес строки S[i]
do
{ /* Начиная с p, находим адрес символа C и засылаем его в эту же переменную указатель p */
p=strchr(p,C);
if (!p) /* это тоже самое, что if (p == NULL), т.е. если не нашли символ C, то заканчиваем анализ строки */
break;
K++;
strcpy(p,p+1); /* Удаляем найденный символ, т. е. всю строку сдвигаем на один символ влево */
}
while(1);
}
for(int i=0;i<n;i++) puts (S[i]); // Вывод массива слов
cout <<"\n Number"<< K<<" ";
getch(); return 0; }