
- •Экзамен 374 Предварительные рассуждения Вступительное слово
- •Исторические факты
- •Начнем!
- •Проба пера
- •Открытие сохраненного проекта
- •Вывод данных
- •Типы данных
- •Хороший стиль программирования
- •Переменные и константы
- •Практический пример
- •Ввод данных
- •Например:
- •Пример:
- •Арифметические операции с числами
- •Литералы
- •Некоторые примеры
- •Домашнее задание
- •Напишите программу, которая вводит число из трех цифр, разделяет число на отдельные цифры и печатает их отдельно друг от друга с тремя пробелами между ними. Преобразование типов
- •Перечисляемые типы
- •Типичная ошибка
- •Хороший стиль программирования
- •Типичная ошибка
- •Выражения
- •Оператор if
- •Структура программы
- •Логические операции
- •Структура множественного выбора switch
- •Практический пример
- •Цикл for
- •Практический пример
- •Цикл do-while
- •Домашнее задание
- •Вызов функции
- •Прототипы функций
- •Разбор программы
- •Область видимости
- •Аргументы по умолчанию
- •Встраивание
- •Перегрузка функций
- •Учебный пример перегруженных функций. Иллюстрация перегрузки
- •Результат работы программы
- •Практические примеры
- •Домашнее задание
- •Примеры домашней работы урока 1 Пример №1
- •Как работает программа
- •Пример №2
- •Как работает программа
- •Примеры домашних работ на создание функций Пример №1
- •Как работает программа
- •Пример №2
- •Как работает программа
- •Массивы
- •Объявление массивов
- •Примеры использования массивов
- •Программа 1
- •Программа 2
- •Обратите внимание!
- •Типичная ошибка программирования
- •Типичная ошибка программирования
- •Программа 3
- •Типичная ошибка программирования
- •Замечание по технике программирования
- •Программа 4
- •Программа 5
- •Программа нахождения минимального и максимального элементов массива
- •Сортировка массивов
- •Домашнее задание
- •Что такое указатели?
- •За кулисами...
- •Как работать с указателями?..
- •Зачем нужны указатели?
- •Указатели и Массивы.
- •Примеры задач
- •Пример 1
- •Пример 2
- •Пример 3
- •Указатели - аргументы функций.
- •Ссылочные параметры
- •Примеры решения задач
- •Домашнее задание
- •Операторы свободной памяти new и delete
- •Функции работы со строками из библиотеки обработки строк
- •Пример 1.
- •Пример2
- •Пример 3
- •Пример задачи на новый материал
- •Домашнее задание
- •Двухмерные массивы, как частный случай многомерных массивов
- •Программа.
- •Результаты работы программы.
- •Многомерные динамические массивы
- •Пример на многомерные динамические массивы
- •Домашнее задание
- •Рекурсия
- •Рекурсии или итерации
- •Указатели на функции
- •Пример №1
- •Результат выполнения программы:
- •Пример №2
- •Результат выполнения программы
- •Пример №3
- •Результаты выполнения программы
- •Определения структур
- •Пример #1 на использование структур
- •Пример #2 на использование структур
- •Оператор указателя на структуру
- •Домашнее задание
- •Тест по c Группа ___________________ф. И. О. ______________________
- •Объектно-ориентированное программирование.
- •Наследование (Inheritance).
- •Инкапсуляция (Encapsulation).
- •Определение класса
- •Конструкторы и деструкторы Инициализация объектов класса: конструкторы
- •Основное назначение конструкторов - инициализация объектов.
- •Использование конструкторов с аргументами по умолчанию
- •Если параметры не передаются конструктору, в определении объекта не нужно включать пустые круглые скобки.
- •Использование деструкторов
- •Когда вызываются конструкторы и деструкторы.
- •Домашнее задание
- •Конструктор копирования
- •Синтаксис конструктора копирования
- •Памятка
- •Пример использования конструктора копирования.
- •Перегруженные конструкторы
- •Экскурс в историю
- •Послесловие к примеру
- •Маленькое замечание
- •Домашнее задание
- •Создание класса ''строка''
- •Перегрузка операций.
- •Общие принципы перегрузки операторов.
- •Преобразования, определяемые классом
- •Пример строкового класса с перегруженными операторами
- •Домашнее задание
- •Дружественные функции (Friend Functions)
- •Пример строкового класса с перегруженными операторами и дружественными функциями
- •Перегрузка операторов new и delete
- •Перегрузка оператора индексирования
- •Класс вектор. Часть1.
- •Класс вектор. Часть 2.
- •Класс вектор. Часть 3.
- •Домашнее задание
- •Наследование (Inheritance). Часть 1.
- •Наследование (Inheritance). Часть 2.
- •Множественное наследование (multiple inheritance)
- •Пример множественного наследования
- •Домашнее задание
- •Статические члены данных
- •Раннее и позднее связывание
- •Виртуальные функции
- •Пример.
- •Абстрактные классы
- •Виртуальный базовый класс
- •Практический пример
- •Домашнее задание
- •Потоки ввода-вывода.
- •Iostream.H: stream - поток, "I" - сокр. Input - ввод, "o" - сокр. Output - вывод.
- •Предопределенные потоки.
- •Операции помещения в поток и извлечения из потока.
- •Файловый ввод-вывод с применением потоков.
- •Конструкторы файловых потоков.
- •Функции для открытия и закрытия файлов.
- •Функции для обмена с потоками.
- •Часто применяемые функции потока.
- •Ввод/вывод массива в/из файл(-а).
- •Практический пример: перекодировка файла.
- •Домашнее задание
- •Немного о файлах...
- •И снова файлы...
- •Пример "Телефонная книга"
- •Файл abonent.H
- •Форматирование данных при обменах с потоками.
- •Состояние потока.
- •Использование аргументов командной строки.
- •Ввод/вывод в с.
- •Домашнее задание
- •Определение шаблонов функций
- •Переопределение шаблонов функций
- •Шаблоны классов
- •Шаблонный класс вектор
- •Шаблонный класс вектор
- •Шаблонный класс вектор
- •Введение
- •Обработка исключительных ситуаций
- •Практический пример
- •Программа
- •Домашнее задание
- •Экзамен
Домашнее задание
Задания первого уровня:
Дана строка символов. Верно ли, что в ней встречаются все буквы из слова step?
Дана строка символов. Сколько раз в ней встречается слово step?
Дана строка символов. Заменить в ней все восклицательные знаки точками.
Пользователь вводит с клавиатуры арифметическое выражение (используемые операции только сложение и вычитание). Посчитать его значение. Если в выражении встречаются другие символы, выдать сообщение, что выражение введено не корректно.
В разделе Пример задачи на новый материал добавьте в программу функцию вставки элемента в заданную позицию.
Двухмерные массивы, как частный случай многомерных массивов
Массивы в C++ могут иметь много индексов. Обычным представлением многомерных массивов являются таблицы значений, содержащие информацию в строках и столбцах. Чтобы определить отдельный табличный элемент, нужно указать два индекса: первый (по соглашению) указывает номер строки, а второй (по соглашению) указывает номер столбца.
Примеры двухмерных массивов. Ведомость по зарплате: в первой колонке указана
сумма оклада, во второй - премия, в третьей - отчисления в пенсионный фонд,
в четвертой - сумма подоходного налога и т.д. Строки - номера сотрудников,
на пересечении строка-столбец - соответствующая сумма.
Или журнал посещений и успеваемости студентов: строка - номер студента,
столбец - номер занятия и на пересечении - был/не был, или оценка по
предмету.
Таблицы или массивы, которые требуют двух индексов для указания отдельного элемента, называются двухмерными массивами. Заметим, что многомерный массив может иметь более двух индексов.
Пример многомерного массива. Смотрите КВН? Как правило в игре принимают
участие несколько команд, и соревнуются они по нескольким конкурсам.
Каждый конкурс оценивает группа жюри. В каком пространстве мы очутились?
Верно, трехмерном и хранить данные естественно в трехмерной структуре,
элементы которой - это балл i-ой команды за j-ый конкурс у k-ого
члена жюри.
Компиляторы C++ поддерживают по меньшей мере 12-мерные массивы.
Рисунок иллюстрирует двухмерный массив а. Массив содержит три строки и четыре столбца, так что, как говорят, - это массив три на четыре.
Вообще, массивы с m строками и n столбцами называют массивами m на n.
Каждый элемент в массиве а определяется именем элемента в форме а[i][j]; а - это имя массива, a i и j - индексы, которые однозначно определяют каждый элемент в а. Заметим, что нумерация строк и столбцов элементов массива начинается с нуля.
Типичная ошибка программирования. Неправильное обращение к элементу двухмерного массива a[x][y] как a[x,y]. На самом деле, a[x,y] воспринимается как a[y], т.к. С++ оценивает выражение (содержащее операцию последования - запятую) x, y просто как y (последнее из разделенных запятыми выражений).
Многомерные массивы могут получать начальные значения в своих объявлениях точно так же, как массивы с единственным индексом. Например, двухмерный массив b[2][2] можно объявить и дать ему начальные значения таким образом:
int b[2][2] = {{1, 2}, {3, 4}};
Значения группируются в строки, заключенные в фигурные скобки. Таким образом, элементы b[0][0] и b[0][1] получают начальные значения 1 и 2, а элементы b[1][0] и b[1][1] получают начальные значения 3 и 4. Если начальных значений в данной строке не хватает для их присвоения всем элементам строки, то остающимся элементам строки присваиваются нулевые начальные значения. Таким образом, объявление
int b[2][2] = {{1}, { 3, 4}};
будет означать что b[0][0] получает начальное значение 1, b[0][1] получает начальное значение 0, b[1][0] получает начальное значение 3 и b[1][1] получает начальное значение 4.
Следующая программа демонстрирует присваивание начальных значений двухмерным массивам в объявлениях. Программа объявляет три массива, каждый с тремя строками и тремя столбцами. Объявление array1 имеет шесть начальных значений в двух подсписках. Первый подсписок присваивает начальные значения 1, 2 и 3 элементам первой строки массива; второй подсписок присваивает начальные значения 4, 5 и 6 элементам второй строки массива. Если фигурные скобки вокруг каждого подписка удалить из списка начальных значений array1, то компилятор автоматически присвоит первые начальные значения элементам первой строки, а следующие - элементам второй строки.
Объявление array2 содержит пять начальных значений. Начальные значения присваиваются первой строке, затем второй строке. Любые элементы, которые не имеют явно заданных начальных значений, автоматически получают нулевые начальные значения, так что элемент array[1][2] получит нулевое начальное значение.
Объявление array3 имеет три начальные значения в двух подсписках. Подсписок для первой строки явно присваивает начальные значения 1 и 2 первым двум элементам первой строки. Третий элемент автоматически получает нулевое начальное значение. Подсписок для второй строки явно присваивает начальное значение 4 первому элементу. Остальные два элемента автоматически получают нулевые начальные значения.
// Присвоение начальных значений в многомерных массивах
#include <iostream.h>
void printArray( int [][3]);
void main()
{
int array1[2][3] = {{1,2,3},{4,5,6}},
array2[2][3] = {1, 2, 3, 4, 5},
array3[2][3] = { {1,2}, {4}};
cout << "Значения массива array1 по строкам:" << endl;
printArray(array1);
cout << "Значения массива array2 по строкам:" << endl;
printArray(array2);
cout << "Значения массива array3 по строкам:" << endl;
printArray(array3);
}
void printArray(int a[][3])
{
for (int i = 0; i <= 1; i++)
{
for(int j = 0; j <= 2; j++)
cout << a[i][j] << ' ';
cout << endl;
}
}
Программа вызывает функцию printArray для вывода элементов каждого массива. Заметим, что описание функции указывает параметр - массив как int а[ ][3]. Когда мы задаем как аргумент функции одномерный массив, скобки в списке параметров функции пустые. Размерность первого индекса многомерного массива также не требуется, но все последующие размерности индексов необходимы. Компилятор использует размерности этих индексов, чтобы правильно обращаться к элементам многомерных массивов. В памяти все элементы массива хранятся последовательно, независимо от количества индексов. В двухмерном массиве первая строка хранится в памяти перед второй строкой. Наличие размерностей индексов в объявлении параметра дает возможность компилятору сообщить функции о том, как расположены элементы в массиве. В двухмерном массиве каждая строка по существу является одномерным массивом. Чтобы определить местоположение элемента в некоторой строке, функция должна точно знать, сколько элементов находится в каждой строке, чтобы она смогла пропустить соответствующее количество ячеек памяти при обращении к массиву. Таким образом, при обращении к a[1][2] функция знает, что для доступа ко второй строке (строка 1) нужно пропустить в памяти три элемента первой строки, а затем обратиться к третьему элементу этой строки (элементу 2).
Многие типовые операции с массивами используют структуру повторения for. Например, следующая структура for обнуляет все элементы третьей строки массива a:
for (column = 0; column < 4; column ++)
а[2][column] = 0;
Поскольку мы знаем, что будем работать с третьей строкой, то первый индекс указали константой, а именно 2 (0 - это первая строка, а 1 - это вторая строка). Цикл for варьирует только второй индекс (т.е. индекс столбца). Предыдущая структура for эквивалентна операторам присваивания:
а[2][0] = 0;
а[2][1] = 0;
а[2][2] = 0;
а[2][3] = 0;
С помощью следующих вложенных циклов for определяется сумма всех элементов массива а:
total = 0;
for (row = 0; row < 3; row++)
for (column = 0; column < 3; colunm++)
total += a[row][column];
Внутренняя структура for суммирует элементы одной строки массива. Внешняя структура for начинает работу с установки row (т.е. индекса строки) в нуль, так что во внутренней структуре for могут быть просуммированы элементы первой строки. Затем внешняя структура for увеличивает row на 1, так что могут быть просуммированы элементы второй строки. Далее внешняя структура for увеличивает row до значения 2, так что могут быть просуммированы элементы третьей строки.
В следующем разделе рассматривается пример программы, которая в двухмерном массиве находит максимальный элемент каждой строки и минимальный элемент каждого столбца.
Пример
Задача. Написать программу, которая в двумерном массиве находит максимальный элемент каждой строки и минимальный элемент каждого столбца.
Разбор задачи. Из постановки условия задачи сразу можем выделить следующие четыре подзадачи:
ввод данных;
для каждой строки поиск ее максимального элемента;
для каждого столбца поиск его минимального элемента;
вывод результатов.
Очевидно, что максимальных элементов у нас будет столько, сколько строк в массиве. Таким образом, выводить их мы можем сразу по мере нахождения (т.е. после просмотра строки, сразу вывести ее максимальный элемент), либо после просмотра всего массива (т.е. всех строк) для каждой строки вывести найденные во время просмотра максимальные элементы. Но во втором случае нам придется ввести дополнительный одномерный массив, который будет содержать для каждой строки двумерного массива ее максимальный элемент. Аналагочно, для столбцов.
Поскольку данная задача не требует особой обработки результатов (например, ответа на вопрос, есть ли среди найденных элементов одинаковые), а нужно только вывести их на экран, то воспользуемся первым подходом, т.е. результаты будем выводить сразу. Таким образом, можем разбить работу на три этапа:
ввод данных и вывод массива в виде таблицы (в целях наглядности);
для каждой строки поиск ее максимального элемента с выводом результатов на экран;
для каждого столбца поиск его минимального элемента с выводом результатов на экран.
Ввод данных. Данные вводятся в массив в цикле по строкам, т.е. сначала вводятся элементы первой строки, затем второй и т.д. Переменная i отвечает за изменение индекса строки, j - столбца.
Для вывода массива на экран также используем вложенные циклы. Внутренний цикл по j выводит i-ую строку массива на экран.
for (int j=0; j<n; j++) // изменение индекса столбца
cout << setw(5) << A[i][j] << " ";
Внешний цикл по i позволяет вывести все строки.
Поиск максимального элемента строки. Предполагаем, что первый элемент строки и есть максимальный, присваиваем его значение переменной max. Дальше перебираем все элементы строки и сравниваем их со значением max. Если находим элемент больше max, то присваеваем переменной max новое значение, а именно значение этого элемента. После просмотра всей строки результат выводим на экран. Теперь эти же действия нужно повторить для следующей строки и т.д., пока не просмотрим все строки массива. Итак, внешний цикл по i отвечает за изменение индекса строки, внутренний по j - за поиск максимального элемента в строке.
// поиск в строках максимального элемента
for (i=0; i<m; i++) // изменение индекса строки
{
int max = A[i][0]; /* предполагаем, что максимальный -
первый элемент строки */
// поиск максимального элемента в i-ой строке
for (int j=0; j<n; j++) // изменение индекса столбца
{
if (A[i][j] > max) max = A[i][j];
}
// вывод резутльтата
cout << "Максимальный элемент " << i
<< "-ой строки = " << max << endl;
}
Аналогично ищем минимальный элемент в столбце, с той только разницей, что здесь просмотр массива осуществляется по столбцам, т.е. индекс i внешнего цикла отвечатает теперь за изменение индекса столбца, а внутренний по j - за поиск минимального значения в столбце.