Алгоритмизация. Введение в язык программирования С++
Белоцерковская Ирина Ефимовна, Галина Наталья Владимировна, Катаева Лилия Юрьевна

Содержание


Лекция 1. Понятие алгоритма. Виды алгоритмов

Алгоритм является базовым понятием для тех, кто хочет начать программировать на любом языке программирования. Любая задача может быть формализована алгоритмически. Чтобы понять, с чего начать, рассмотрим основные виды алгоритмов.

Цель данной лекции – ознакомить студентов с понятием алгоритма; показать, что такая абстрактная вещь как алгоритм окружает нас в повседневной жизни.

Существует несколько определений понятия алгоритма. Приведем два самых распространенных.

Алгоритм – последовательность чётко определенных действий, выполнение которых ведёт к решению задачи. Алгоритм, записанный на языке машины, есть программа решения задачи.

Алгоритм – это совокупность действий, приводящих к достижению результата за конечное число шагов.

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

Свойства алгоритмов:

  1. Дискретность (от лат. discretus — разделенный, прерывистый) – это разбиение алгоритма на ряд отдельных законченных действий (шагов).
  2. Детерминированность (от лат. determinate — определенность, точность) - любое действие алгоритма должно быть строго и недвусмысленно определено в каждом случае. Например, алгоритм проезда к другу, если к остановке подходят автобусы разных маршрутов, то в алгоритме должен быть указан конкретный номер маршрута 5. Кроме того, необходимо указать точное количество остановок, которое надо проехать, скажем, три.
  3. Конечность – каждое действие в отдельности и алгоритм в целом должны иметь возможность завершения.
  4. Массовость – один и тот же алгоритм можно использовать с разными исходными данными.
  5. Результативность – алгоритм должен приводить к достоверному решению.

Основная цель алгоритмизации – составление алгоритмов для ЭВМ с дальнейшим решением задачи на ЭВМ.

Примеры алгоритма:

  1. Любой прибор, купленный в магазине, снабжается инструкцией по его использованию. Данная инструкция и является алгоритмом для правильной эксплуатации прибора.
  2. Каждый шофер должен знать правила дорожного движения. Правила дорожного движения однозначно регламентируют поведение каждого участника движения. Зная эти правила, шофер должен действовать по определенному алгоритму.
  3. Массовый выпуск автомобилей стал возможен только тогда, когда был придуман порядок сборки машины на конвейере. Определенный порядок сборки автомобилей – это набор действий, в результате которых получается автомобиль.

Существует несколько способов записи алгоритмов. На практике наиболее распространены следующие формы представления алгоритмов:

  1. словесная (запись на естественном языке);
  2. псевдокоды (полуформализованные описания алгоритмов на условном алгоритмическом языке, включающие в себя как элементы языка программирования, так и фразы естественного языка, общепринятые математические обозначения и др.);
  3. графическая (изображения из графических символов – блок-схема);
  4. программная (тексты на языках программирования – код программы).

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

Словесный способ записи алгоритмов представляет собой описание последовательных этапов обработки данных. Алгоритм задается в произвольном изложении на естественном языке. Ответ при этом получает человек, который выполняет команды согласно словесной записи.

Пример словесной записи:

  1. задать два числа, являющиеся делимым и делителем;
  2. проверить, равняется ли делитель нулю;
  3. если делитель не равен нулю, то найти частное, записать его в ответ;
  4. если делитель равен нулю, то в ответ записать "нет решения".

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

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

Приведем основные управляющие структуры псевдокода в табл. 1.1.

Таблица 1.1. Базовые управляющие структуры псевдокода
Название структурыПсевдокод
Присваивание
переменная = число
Ввод
ввод(переменная)
Вывод
вывод(переменная)
вывод("фраза")
Ветвление
если условие 
	то действие1 
иначе действие2
Повторение
пока условие
начало пока
	действие
конец пока

Пример псевдокода:

алг Нахождение частного двух чисел
начало
вывод ("задайте делимое и делитель")
ввод (делимое, делитель)
если делитель ≠ 0
то частное = делимое / делитель
	вывод(частное)
иначе вывод("нет решения")
кон алг Нахождение частного двух чисел

В данном примере используется три переменные: делимое, делитель и частное. Делимое и делитель задаются исполнителем произвольными числами. Частное считается лишь в том случае, если делитель не равен нулю.

Графическая реализация алгоритма представляет собой блок-схему. Блок-схема состоит из блоков определенной формы, соединенных стрелками. Ответ при этом получает человек, который выполняет команды согласно блок-схеме. Более подробно о блок-схемах будет рассказано в Лекции 2.

Программная реализация алгоритма – это компьютерная программа, написанная на каком-либо алгоритмическом языке программирования, например: С++, Pascal, Basic и т.д. Программа состоит из команд определенного языка программирования. Отметим, что одна и та же блок-схема может быть реализована на разных языках программирования. Ответ при этом получает ЭВМ, а не человек. Более подробно о составлении программ на языке программирования С++ смотреть Лекцию 3.

Различают три основных вида алгоритмов:

  1. линейный алгоритм,
  2. разветвляющийся алгоритм,
  3. циклический алгоритм.

Линейный алгоритм – это алгоритм, в котором действия выполняются однократно и строго последовательно.

Самый простой пример реализации линейного алгоритма – путь из университета домой.

Словесный способ записи данного алгоритма:

  1. выйти из университета на остановку;
  2. подождать нужный автобус;
  3. сесть на нужный автобус;
  4. оплатить проезд;
  5. выйти на требуемой остановке;
  6. дойти до дома.

Очевидно, что данный пример относится к линейному алгоритму, т.к. все действия следуют одно за другим, без условий и повторений.

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

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

Приведенный выше пример псевдокода по нахождению частного двух чисел также относится к разветвляющемуся алгоритму.

Циклический алгоритм – это алгоритм, команды которого повторяются некое количество раз подряд.

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

Более подробно о линейном, разветвляющемся и циклическом алгоритмах смотреть Лекцию 2.

Краткие итоги

Любая задача может быть разбита на элементарные действия. Для любой математической задачи или ситуации из жизни можно составить алгоритм решения. Алгоритм может быть описан словесно, псевдокодом, графически или программно. Задача всегда решается с помощью базовых типов алгоритма – линейного, разветвляющегося или циклического.

Вопросы

  1. Что такое алгоритм?
  2. В чем состоит задача алгоритмизации?
  3. Какими свойствами обладает алгоритм?
  4. Какие виды алгоритма бывают?

Упражнения

  1. Составьте алгоритмы по походу в магазин за яблоками. Используйте линейный и разветвляющийся алгоритмы. Реализуйте их словесно.
  2. Составьте алгоритм по нахождению корней квадратного уравнения через дискриминант. Используйте разветвляющийся алгоритм. Реализуйте его псевдокодом.

Лекция 2. Блок-схемы. Графическая реализация алгоритмов

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

Цель данной лекции – ознакомить студентов с понятием блок-схемы; показать основные конструкции реализации разных видов алгоритма; показать принципы проверки блок-схем и получения по ним ответа.

Занятие 1. Понятие блок-схемы. Основные виды блоков

Блок-схема – это графическая реализация алгоритма.

Блок-схема представляет собой удобный и наглядный способ записи алгоритма.

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

Таблица 2.1. Виды блоков
Форма блокаНазначение блока
начало и конец блок-схемы
блок ввода данных
блок выполнения действия
блок условия
блок вывода данных

Любая команда алгоритма записывается в блок-схеме в виде графического элемента – блока, и дополняется словесным описанием. Блоки в блок-схемах соединяются линиями потока информации. Направление потока информации указывается стрелкой. В случае потока информации сверху вниз и слева направо стрелку ставить не обязательно. Блоки в блок-схеме имеют только один вход и один выход (за исключением логического блока – блока с условием).

Блок начала блок-схемы имеет один выход и не имеет входов, блок конца блок-схемы имеет один вход и не имеет выходов. Блок условия – единственный блок, имеющий два выхода, т.к. соответствует разветвляющемуся алгоритму. На одном выходе указывается "да", на другом – "нет". Все остальные блоки имеют один вход и один выход. Блок выполнения действия может содержать присвоение значения переменной (например "") или вычисление (например "").

Математические выражения и логические высказывания должны быть описаны математическим языком, т.к. блок-схема не должна иметь привязки к какому-то определенному языку программирования. Одна и таже блок-схема может быть реализована в программах на разных языках программирования. К примеру, функция в блок-схеме будет выглядеть таким образом: , а не таким образом: .

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

Занятие 2. Графическая реализация линейного алгоритма

Приведем простейшие примеры, соответствующие линейному алгоритму.

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

Решение. Чтобы позвонить по городскому телефону, нужно знать номер Пети. Значит, сначала надо найти номер телефона Пети, набрать его и поговорить с Петей. На этом цель Васи (поговорить с Петей по телефону) будет достигнута. Результат блок схемы представлен на рис. 2.1.

Блок-схема для примера 1


Рис. 2.1.  Блок-схема для примера 1

Пример 2. Ученику требуется купить учебник. Составить блок-схему, описывающую порядок действий ученика.

Решение. Сначала ученику нужно взять деньги, потом прийти в книжный магазин и заплатить за учебник. На этом цель (покупка учебника) будет достигнута. Результат блок схемы представлен на рис. 2.2.

Блок-схема для примера 2


Рис. 2.2.  Блок-схема для примера 2

Пример 3. Даны числа . Вычислить сумму и разность чисел и .

Решение. Сначала следует задать значения для чисел и , согласно условиям задачи. После этого их уже можно будет использовать в расчетах для получения суммы и разности по формулам: . Полученные значения суммы и разности нужно будет показать на экране, и мы используем блок вывода данных. Если не выводить данные на экран, то пользователь нашего алгоритма не узнает, какие получились значения суммы и разности. Результат блок схемы представлен на рис. 2.3.

Блок-схема для примера 3: а) в каждом блоке по одному действию, б) действия объединены по смыслу операции


увеличить изображение

Рис. 2.3.  Блок-схема для примера 3: а) в каждом блоке по одному действию, б) действия объединены по смыслу операции

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

Занятие 3. Графическая реализация разветвляющегося алгоритма

В разветвляющемся алгоритме обязательным блоком является блок условия, который представлен на рис. 2.4.

Использование блока условия в общем виде


Рис. 2.4.  Использование блока условия в общем виде

Внутри блока условия записывается условие. Если данное условие верно, то выполняются блоки, идущие по стрелке "да", т.е. "Набор действий 1". Если условие оказывается неверным, т.е. ложным, то выполняются блоки, идущие по стрелке "нет", а именно "Набор действий 2". Разветвление заканчивается, когда обе стрелки ("да" и "нет") соединяются. На рис. 2.5 представлен еще один вариант использования блока условия. Бывают задачи, в которых, исходя из условия, необходимо либо выполнить действие, либо пропустить его. Если условие верно выполняется, то следуют блоки, соответствующие стрелке "да", т.е. "Набор действий 1". Если же условие оказывается ложным, то следует перейти по стрелке "нет". Т.к. стрелке "нет" не соответствует ни одного блока с действием, то ни одного действия не будет выполнено. Т.е. получается, что мы пропустили и не выполнили "Набор действий 1".

Вариант использования блока условия


Рис. 2.5.  Вариант использования блока условия

В разветвляющемся алгоритме возможна запись сразу нескольких условий, которые могут объединяться союзом "ИЛИ" или пересекаться союзом "И". Рассмотрим случай двух условий: "условие 1" и "условие 2".

Если необходимо, чтобы оба условия были верными одновременно, то следует использовать логическое пересечение "И":

"условие 1 и условие 2".

Если достаточно, чтобы только одно условие выполнялось – либо первое, либо второе, то следует использовать логическое объединение "ИЛИ":

"условие 1 ИЛИ условие 2".

Приведем простейшие примеры, соответствующие разветвляющемуся алгоритму.

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

Решение. В отличие от примера 1, здесь присутствует условие – Пол ли взял трубку телефона. На данное условие можно однозначно ответить: "да", Пол, или "нет", кто-то другой. Если трубку взял Пол, то Джону нужно с ним поговорить, и цель будет достигнута. Если трубку взял кто-то другой, то необходимо позвать Пола к телефону, поговорить с ним, и цель также будет достигнута. Третьего варианта, например, "не туда попали" или "его нет дома" мы не рассматриваем. Результат блок-схемы представлен на рис. 2.6.

Блок-схема для примера 4


Рис. 2.6.  Блок-схема для примера 4

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

Решение. В данном примере присутствует условие: "Нужна жесткая обложка".

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

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

И в том, и в другом случае, цель будет достигнута и задача будет выполнена, т.к. ученик купит учебник.

Результат блок схемы представлен на рис. 2.7.

Блок-схема для примера 5


Рис. 2.7.  Блок-схема для примера 5

Пример 6. Даны числа . Вычислить сумму и разность чисел и . Сравнить полученные значения и и указать большее из них.

Решение. Как и в примере 3, сначала необходимо задать значения и . Затем рассчитать сумму и разность по формулам: , и вывести полученные числа на экран (блок вывода данных). Когда значения и будут получены, следует сравнить их между собой. Условие запишется в виде: . Если полученная сумма будет больше разности , то мы пойдем по стрелке "да" и выведем фразу "". Если же условие окажется ложным (т.е. ), то пойдем по стрелке "нет" и выведем фразу "". Результат блок схемы представлен на рис. 2.8.

Блок-схема для примера 6


Рис. 2.8.  Блок-схема для примера 6

Занятие 4. Графическая реализация циклического алгоритма

В рассмотрении циклического алгоритма следует выделить несколько понятий.

Тело цикла – это набор инструкций, предназначенный для многократного выполнения.

Итерация – это единичное выполнение тела цикла.

Переменная цикла – это величина, изменяющаяся на каждой итерации цикла.

Каждый цикл должен содержать следующие необходимые элементы:

  1. первоначальное задание переменной цикла,
  2. проверку условия,
  3. выполнение тела цикла,
  4. изменение переменной цикла.

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

Циклический алгоритм с предусловием в общем виде


Рис. 2.9.  Циклический алгоритм с предусловием в общем виде

В цикле с постусловием сначала выполняется тело цикла, а потом проверяется условие. Циклический алгоритм с постусловием представлен на рис. 2.10.

Циклический алгоритм с постусловием в общем виде


Рис. 2.10.  Циклический алгоритм с постусловием в общем виде

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

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

Приведем простейшие примеры, соответствующие циклическому алгоритму.

Пример 7. Вася звонит Пете, но у Пети может быть занята линия. Составить блок-схему действий Васи в этом случае.

Решение. Когда телефонная линия занята, то необходимо снова и снова набирать номер, пока Петя не закончит предыдущий разговор, и телефонная линия не окажется вновь свободной. Блок-схема представлена на рис. 2.11.

Блок-схема для примера 7


Рис. 2.11.  Блок-схема для примера 7

Здесь тело цикла состоит из одного действия "Набрать номер Пети", т.к. именно это действие следует повторять, пока линия будет занята. Под итерацией цикла понимается очередная попытка дозвониться до Пети. Как таковой переменной цикла здесь нет, т.к. ситуация взята из жизни. Выход из цикла происходит в тот момент, когда условие "У Пети занято" стало неверным, т.е. телефонная линия свободна – действительно, нет необходимости больше набирать номер Пети. В данном примере применен цикл с постусловием, т.к. сначала необходимо набрать номер Пети, ведь иначе мы не можем ответить на вопрос – занята ли линия у Пети.

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

Решение. Действия ученика в данном примере очевидны: когда он приходит в первый и любой последующий магазины, то возможны два варианта – учебник имеется в наличии или учебника нет в продаже. Если учебника нет в продаже, то ученику следует пойти в другой книжный магазин и спросить данный учебник, и т.д. пока учебник не будет куплен, т.к. перед учеником стоит конечная цель – купить учебник. Мы будем использовать цикл с предусловием, т.к. сначала требуется найти магазин, имеющий в наличии данный учебник. Цикл будет выполняться, пока условие "В данном магазине нет учебника" будет верным, а выход из цикла осуществится, когда условие станет ложным, т.е. когда ученик придет в магазин, в котором есть данный учебник. Действительно, в этом случае ученик купит нужный ему учебник и не будет больше искать книжные магазины. Результат блок-схемы представлен на рис. 2.12.

Блок-схема для примера 8


Рис. 2.12.  Блок-схема для примера 8

Здесь тело цикла состоит из одного действия "Найти другой книжный магазин". Переменной цикла в явном виде нет, но можно подразумевать номер магазина, в который пришел ученик в очередной раз. Как любой другой цикл с предусловием, данный цикл может ни разу не выполниться (не иметь итераций), если в первом же магазине окажется нужный учебник.

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

Пример 9. Даны числа . Известно, что число меняется от -10 до 10 с шагом 5, и не изменяется. Вычислить сумму и разность чисел и для всех значений и .

Решение. В отличие от примеров 3 и 6 здесь число меняется от -10 до 10 с шагом 5. Это означает, что число является переменной цикла. Сначала равно -10 – это первоначальное задание переменной цикла. Далее будет изменяться с шагом 5, и т.д. пока не будет достигнуто значение 10 – это соответствует изменению переменной цикла. Итерации надо повторять, пока выполняется условие "". Итак, будет принимать следующие значения: -10, -5, 0, 5, 10. Число не будет являться переменной цикла, т.к. и не изменяется по условию задачи. Результат блок-схемы (с предусловием) представлен на рис. 2.13.

Блок-схема для примера 9 (с предусловием)


Рис. 2.13.  Блок-схема для примера 9 (с предусловием)

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

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

Приведем блок-схему, использующую цикл с постусловием, на рис. 2.14.

Блок-схема для примера 9 (с постусловием)


Рис. 2.14.  Блок-схема для примера 9 (с постусловием)

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

Блок-схема с ветвлением для примера 9: а) с предусловием,    б) с постусловием


Рис. 2.15.  Блок-схема с ветвлением для примера 9: а) с предусловием, б) с постусловием

Занятие 5. Выполнение блок-схем

Блок-схема сама по себе не содержит ответа. Чтобы получить результат, нужно выполнить блок-схему.

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

Если блок-схема составлена корректно, то, выполнив ее, человек получит ответ к своей задаче. Если же при составлении блок-схемы были допущены ошибки, то исполнитель либо вообще не дойдет до блока Конец, либо получит неверный ответ.

Для выполнения нам понадобится поле для расчетов (аналог "оперативной памяти") и поле для вывода результата (аналог экрана для вывода данных). Экран будем показывать несколько раз в зависимости от вывода новых данных на экране.

Выполнение блок-схемы для примера 3. Даны числа . Вычислить сумму и разность чисел и .

Выполнение блок-схемы приведем в табл. 2.2.

Таблица 2.2. Выполнение блок-схемы для примера 3
Расчеты:
Начало
a=2
b=7
S=a+b={подставляем значения a и b}=2+7=9
R=a-b={подставляем значения a и b}=2-7=-5
Выводим на экран S=9, R=-5:
					
Вывод данных (экран)
S=9
R=-5
							
Конец.

Выполнение блок-схемы для примера 6. Даны числа . Вычислить сумму и разность чисел и . Сравнить полученные значения и и указать большее из них.

Выполнение блок-схемы приведем в табл. 2.3.

Таблица 2.3. Выполнение блок-схемы для примера 6
Расчеты:
Начало
a=2
b=7
S=a+b=2+7=9
R=a-b=2-7=-5
Выводим на экран S=9, R=-5:
				
Вывод данных (экран)
S=9
R=-5
						
S>R   9>-5   да, верно
Выводим на экран "Max S":
				
Вывод данных (экран)
S=9
R=-5
Max S
						
Конец.

Выполнение блок-схемы для примера 9. Даны числа . Известно, что число меняется от -10 до 10 с шагом 5, и не изменяется. Вычислить сумму и разность чисел и для всех значений и .

Выполнение блок-схемы с предусловием приведем в табл. 2.4.

Таблица 2.4. Выполнение блок-схемы с предусловием для примера 9
Расчеты:
Начало
b=7
a=-10
a≤10   -10≤10   да, верно
S=a+b=-10+7=-3
R=a-b=-10-7=-17
Вывод S, R
					
Экран
S=-3   R=-17
a=a+5=-10+5=-5
{Идем по стрелке вверх}
a≤10   -5≤10   да, верно
S=a+b=-5+7=2
R=a-b=-5-7=-12
Вывод S, R
				
Экран
S=-3   R=-17
S=2   R=-12
						
a=a+5=-5+5=0
{Идем по стрелке вверх}
a≤10   0≤10   да, верно
S=a+b=0+7=7
R=a-b=0-7=-7
Вывод S, R
Экран
S=-3   R=-17
S=2   R=-12
S=7   R=-7
						
a=a+5=0+5=5
{Идем по стрелке вверх}
a≤10   5≤10   да, верно
S=a+b=5+7=12
R=a-b=5-7=-2
Вывод S, R
				
Экран
S=-3   R=-17
S=2   R=-12
S=7   R=-7
S=12   R=-2
						
a=a+5=5+5=10
{Идем по стрелке вверх}
a≤10   10≤10   да, верно
S=a+b=10+7=17
R=a-b=10-7=3
Вывод S, R
				
Экран
S=-3   R=-17
S=2   R=-12
S=7   R=-7
S=12   R=-2
S=17   R=3
						
a=a+5=10+5=15
{Идем по стрелке вверх}
a≤10   15≤10   нет, ложно {выходим из цикла}
Конец.
				

Виполнение блок-схемы с постусловием приведем в табл. 2.5.

Таблица 2.5. Выполнение блок-схемы с постусловием для примера 9
Расчеты:
Начало
b=7
a=-10
S=a+b=-10+7=-3
R=a-b=-10-7=-17
Вывод S, R
					
Экран
S=-3   R=-17
a=a+5=-10+5=-5
a≤10   -5≤10   да, верно
{Идем по стрелке вверх}
S=a+b=-5+7=2
R=a-b=-5-7=-12
Вывод S, R
				
Экран
S=-3   R=-17
S=2   R=-12
						
a=a+5=-5+5=0 
a≤10   0≤10   да, верно
{Идем по стрелке вверх}
S=a+b=0+7=7
R=a-b=0-7=-7
Вывод S, R
Экран
S=-3   R=-17
S=2   R=-12
S=7   R=-7
						
a=a+5=0+5=5 
a≤10   5≤10   да, верно
{Идем по стрелке вверх}
S=a+b=5+7=12
R=a-b=5-7=-2
Вывод S, R
				
Экран
S=-3   R=-17
S=2   R=-12
S=7   R=-7
S=12   R=-2
						
a=a+5=5+5=10
a≤10   10≤10   да, верно
{Идем по стрелке вверх}
S=a+b=10+7=17
R=a-b=10-7=3
Вывод S, R
				
Экран
S=-3   R=-17
S=2   R=-12
S=7   R=-7
S=12   R=-2
S=17   R=3
						
a=a+5=10+5=15
a≤10   15≤10   нет, ложно {выходим из цикла}
Конец.
				

Пример 10. Даны числа . Известно, что число меняется от -10 до 10 с шагом 5, и не изменяется. Вычислить сумму и разность и сравнить полученные значения суммы и разности для всех значений и .

Выполнение блок-схемы с предусловием приведем в табл. 2.6.

Таблица 2.6. Выполнение блок-схемы с предусловием для примера 10
Расчеты:
Начало
b=7
a=-10
a≤10   -10≤10   да, верно
S=a+b=-10+7=-3
R=a-b=-10-7=-17
Вывод S, R
S>R   -3>-17   да, верно
Вывод "Max S"
					
Вывод данных (экран)
S=-3   R=-17   Max S
a=a+5=-10+5=-5
{Идем по стрелке вверх}
a≤10   -5≤10   да, верно
S=a+b=-5+7=2
R=a-b=-5-7=-12
Вывод S, R
S>R   2>-12   да, верно
Вывод "Max S"
				
Вывод данных (экран)
S=-3   R=-17   Max S
S=2   R=-12   Max S
						
a=a+5=-5+5=0
{Идем по стрелке вверх}
a≤10   0≤10   да, верно
S=a+b=0+7=7
R=a-b=0-7=-7
Вывод S, R
S>R   7>-7   да, верно
Вывод "Max S"
Вывод данных (экран)
S=-3   R=-17   Max S
S=2   R=-12   Max S
S=7   R=-7   Max S
						
a=a+5=0+5=5 
a≤10   5≤10   да, верно
{Идем по стрелке вверх}
S=a+b=5+7=12
R=a-b=5-7=-2
Вывод S, R
S>R   12>-2   да, верно
Вывод "Max S"
				
Вывод данных (экран)
S=-3   R=-17   Max S
S=2   R=-12   Max S
S=7   R=-7   Max S
S=12   R=-2   Max S
						
a=a+5=5+5=10
{Идем по стрелке вверх}
a≤10   10≤10   да, верно
S=a+b=10+7=17
R=a-b=10-7=3
Вывод S, R
S>R   17>3   да, верно
Вывод "Max S"
				
Вывод данных (экран)
S=-3   R=-17   Max S
S=2   R=-12   Max S
S=7   R=-7   Max S
S=12   R=-2   Max S
S=17   R=3   Max S
						
a=a+5=10+5=15
{Идем по стрелке вверх}
a≤10   15≤10   нет, ложно {выходим из цикла}
Конец.
				

В процессе составления блок-схемы важно "ходить" по стрелкам из блока в блок, следить, чтобы не получалось "тупиковых ситуаций". Такая ситуация возникает, если составитель блок-схемы не нарисовал стрелку из блока. Также частой ошибкой является замыкание стрелки не в тот блок, например при реализации циклического алгоритма.

Краткие итоги

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

Вопросы

  1. Что такое блок-схема?
  2. Какие типы блоков бывают?
  3. Какие блоки используются при реализации линейного, разветвляющегося, циклического алгоритмов?
  4. Можно ли составить разные варианты блок-схем для одной и той же задачи?
  5. Какие виды циклического алгоритма бывают?
  6. Какие пункты должны присутствовать в любом цикле?
  7. Что такое выполнение блок-схемы?
  8. Для чего следует выполнять блок-схему?

Упражнения

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

Лекция 3. Основы программирования на языке С++

Подступаемся к языку программирования С++. Будем делать это уверенными шагами. Сначала посмотрим, как и где он работает.

Цель данной лекции – ознакомить студентов необходимыми элементами языка программирования С++; показать, в каких программах можно работать и как это правильно делать.

Занятие 1. Базовые знания о языке программирования С++

Программа – это реализация алгоритма для выполнения задачи компьютером (ЭВМ).

С помощью программы мы формулируем алгоритм на языке, понятном компьютеру. Таким языком служит язык программирования.

На сегодняшний день распространенными языками программирования являются: С, С++, Pascal, Basic, Fortran и т.д.

Язык программирования С++ является одним из самых востребованных на сегодняшний день.

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

Существует несколько приложений для написания программ на языке С++. Мы будем рассматривать Microsoft Visual Studio и Borland C++.

В языке программирования С++ определены некоторые стандартные типы данных, которые представлены в табл. 3.1.

Таблица 3.1. Стандартные типы данных С++
Тип данныхЗначение
intцелый тип, размер типа int не определяется стандартом, а зависит от компьютера и компилятора, для 16-разрядного процессора под величины этого типа отводится 2 байта, для 32-разрядного — 4 байта.Примеры значений типа int: 5, 0, -1, 100.
doubleвещественный тип с двойной точностью. Типы данных с плавающей точкой хранятся в памяти компьютера иначе, чем целочисленные. Внутреннее представление вещественного числа состоит из двух частей — мантиссы и порядка. Мантисса — это число, большее 1.0, но меньшее 2.0. Для величин типа double, занимающих 8 байт, под порядок и мантиссу отводится 11 и 52 разряда соответственно. Длина мантиссы определяет точность числа, а длина порядка — его диапазон.Примеры значений типа double: 5.0, -0.00001, 2.9987.
floatвещественный тип. В компьютерах величины типа float занимают 4 байта, из которых один двоичный разряд отводится под знак мантиссы, 8 разрядов под порядок и 23 под мантиссу. Тип float имеет меньшую точность, чем double. В большинстве случаев лучше использовать double.
charсимвольный тип, под величину символьного типа отводится количество байт, достаточное для размещения любого символа из набора символов для данного компьютера, что и обусловило название типа. Как правило, это 1 байт. Каждый символ имеет свой собственный целочисленный код, согласно таблице ASCII (англ. American Standard Code for Information Interchange).Примеры значений типа char: "A" (код 65), "7" (код 55), "-" (код 189), "/" (код 191).
fstream, ifstream, ofstreamфайловый поток. Используется для вывода данных в файл и считывания данных из файла.

Программа на языке С++ имеет определенную структуру.

Существует определенная последовательность заранее определенных строк кода, которая приведена в табл. 3.2.

Таблица 3.2. Структура программы С++
#include "stdafx.h"подключение заголовочного файла для сборки проекта. Обязательный пункт в Visual Studio, в среде Borland C++ не используется.
#include <название_библиотеки>подключение библиотек. Необязательный пункт. Подробно о библиотеках смотреть ниже.
using namespace std;использование пространства имен. Обязательный пункт в Visual Studio, в среде Borland C++ не используется.
int main(){ или void main(){главная функция программы. Именно она начинает выполняться, когда запускается программа. Обязательный пункт.
Тело_функции_mainв теле функции main записываются действия и операции, предусмотренные алгоритмом. Обязательный пункт.
return 0;} или }конец программы. Самый последний оператор. Обязательный пункт.

Библиотека – это файл, в котором описаны функции и операторы. Для каждой смысловой группы функций своя библиотека. Библиотек в языке C++ предусмотрено много, мы будем рассматривать только самые необходимые. Нам понадобятся функции для работы с экраном, математические функции.

Основные библиотеки и их основные функции и операторы:

  1. <iostream> для Visual Studio, <iostream.h> для Borland C++. Библиотека для работы с консолью (экраном).

    cout – оператор вывода данных на экран.

    Пример использования:

    cout<<"fraza"; //выведет на экран слово fraza. Может вывести любой текст.

    cout<<x; //выведет на экран число, хранящееся в переменной х.

    cin – оператор считывания с экрана.

    Когда у пользователя запрашивают число, программа ждет, пока пользователь не напечатает число и нажмет ENTER. Тогда оператор cin записывает это значение в переменную х.

    Пример использования:

    cin>>x; //присваивает переменной х значение, введенное с клавиатуры.

    cin>>x>>y; //присваивает переменной х первое введенное с клавиатуры значение, переменной у – второе.

    endl – оператор перевода каретки на экране на следующую строку.

    Самостоятельно не используется.

    Пример использования:

    cout<<endl; //курсор перейдет на новую строку.

    cout<<x<<endl;//сначала на экране появится число, хранящееся в переменной , потом перейдет на новую строку. Выводимые далее данные будут печататься с новой строки.

    cout<<endl<<"fraza"; // курсор перейдет на новую строку, и на новой строке появится надпись fraza.

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

    Пример использования:

    cout.precision(3); //число 7.897426 выведется на экран в виде 7.897.

  2. <math.h> одинаково для Visual Studio, Borland C++. Библиотека математических функций. Основные математические функции представлены в табл. 3.3.
    Таблица 3.3. Основные математические функции С++
    Математическая функцияПрограммная записьОписание
    fabs(x)Модуль числа.
    sin(x)Синус числа, аргумент в радианах.
    cos(x)Косинус числа, аргумент в радианах.
    tan(x)Тангенс числа, аргумент в радианах.
    exp(x)Экспонента числа.
    log(x)Натуральный логарифм числа.
    log10(x)Десятичный логарифм числа.
    pow(x, y)х в степени y.
    pow10(x)Степень десяти.
    sqrt(x)Квадратный корень из числа.
    asin(x)Арксинус числа, в радианах.
    acos(x)Арккосинус числа, в радианах.
    atan(x)Арктангенс числа, в радианах.
    M_PIЧисло =3.141593
  3. <iomanip> для Visual Studio, <iomanip.h> для Borland C++.

    setw(n) – для вывода на экран отводится ячеек.

    Используется при построении ровной таблицы значений функции.

    Пример использования:

    cout<<setw(5)<<x<<setw(5)<<y<<endl;

    На экране выведутся два числа: первое (1.5) в первых пяти ячейках, второе (-73) во вторых пяти ячейках. _ _ 1 . 5 _ _ - 7 3 .

В программах используются переменные. Имя переменной выбирает составитель программы; имя переменной должно начинаться с буквы латинского алфавита и может содержать буквы латинского алфавита, цифры и символы подчеркивания. Заглавные и строчные буквы считаются разными. Примеры имен переменных: х, y, summa, s1, srednee_ar и т.д. Имена переменных не должны совпадать с ключевыми словами языка С++.

Чтобы использовать в программе переменную, необходимо:

  1. объявить переменную в начале программы, явно указав тип данных для переменной. Пример:

    double x; //вещественная переменная .

    int m; //целочисленная переменная .

    Если переменная не будет объявлена, но будет использоваться далее в программе, то программа не запустится, компилятор выдаст ошибку.

  2. проинициализировать переменную, т.е. задать переменной значение. Пример:

    x=7.81;
    m=4; z=x+m;

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

  3. использовать далее в программе в расчетах или при выводе на экран.

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

Таблица 3.4. Основные арифметические операции С++
Операция в С++ОписаниеПример в программе
=присвоение
х=0.4;
+сложение
х=8+3;
y=x+7.9;
				
-вычитание
x=8-3;
y=x-7.9;
				
*умножение
x=4*2.5;
y=x*4;
				
/деление. Результатом деления целых чисел является целое число.
x=7.5/3.2;
y=x/2.6;
z=1/3; //z=0 (округление до целого, т.к. делятся целые числа)
z=1.0/3.0; //z=0.333(3)
				

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

Таблица 3.5. Логические операции С++
Сравнение в С++ОписаниеПример в программе
>больше чем
x>0
<меньше чем
y<z
>=больше или равно
y>=x
<=меньше или равно
z<=8.56
==проверка на равенство
x==0.7
!=не равно
x!=y
&&логическое И
x>0 && x<1 // двойное неравенство 0<x<1
||логическое ИЛИ
s<8 || s>10

Для реализации разветвляющегося алгоритма в С++ используется условный оператор if. Приведем общий вид блок-схем и общий вид записи оператора if:



if (условие) {
	Набор_действий_1;
}
else {
	Набор_действий_2;
}



if (условие) {
	Набор_действий_1;
}

Примечание. Если необходимо выполнить не набор действий, а всего одно действие, то фигурные скобки можно опустить.

Для реализации циклического алгоритма с предусловием в С++ предусмотрено два оператора цикла while и for. По одной и той же блок-схеме с предусловием можно написать две программы, одну – с оператором while, другую – с оператором for. Оператор while удобно использовать, если неопределенно, сколько итераций нужно сделать, или это трудно сделать. Оператор for удобно использовать, когда мы заранее знаем количество итераций.

Приведем общий вид блок-схем и общий вид записи операторов while и for:



Оператор while:
x=xn;
while(x<=xk){
	Тело_цикла;
	x=x+hx;
}
Оператор for:
for(x=xn; x<=xk; x=x+hx){
	Тело_цикла;
}
				

Для реализации циклического алгоритма с постусловием в С++ предусмотрен оператор do while. Блок-схема и запись оператора do while в общем виде:



Оператор do while:
x=xn;
do{
	Тело_цикла;
	x=x+hx;
} while(x<=xk);
				

Существует ряд задач, где изменяется сразу две переменные. Тогда используют вложенные циклы. Внутри одного цикла (внешнего) организуют другой цикл (внутренний).

Для ясности будем делать внешний цикл по переменной , а внутренний – по переменной . Обозначим переменные: – начальное значение – конечное значение – шаг по переменной – начальное значение – конечное значение – шаг по переменной . Приведем блок-схему и вид записи операторов цикла с предусловием:



Оператор while:
x=xn;
while (x<=xk){
	y=yn;
	while (y<=yk){
		Тело_цикла;
		y=y+hy;
	}
	x=x+hx;
}
Оператор for:
for (x=xn; x<=xk; x=x+hx){
	for(y=yn; y<=yk; y=y+hy){
		Тело_цикла;
}
}
				

Общий вид записи циклов с постусловием и блок-схема с постусловием:



Оператор do while:
x=xn;
do {
	y=yn;
	do {
		Тело_цикла;
		y=y+hy;
	} while (y<=yk);
	x=x+hx;
} while (x<=xk);
				

Занятие 2. Начало работы в приложении Microsoft Visual Studio

Microsoft Visual Studio — это набор инструментов разработки, основанных на использовании компонентов и других технологий для создания мощных, производительных приложений.

Кроме того, среда Visual Studio оптимизирована для совместного проектирования, разработки и развертывания корпоративных решений.

Также Visual Studio позволяет создавать проекты, имеющие пользовательский интерфейс (GUI), работая с разными компонентами, такими как формы, кнопки, списки, меню и т.д.

В рамках данного курса мы будем рассматривать лишь программы, работающие в режиме DOS.

Рассмотрим версию Visual Studio 2010.

При загрузке приложения из меню Пуск/Программы/Microsoft Visual Studio 2010 появляется главное окно c начальной страницей программы, которое представлено на рис. 3.1.

Начальная страница Visual Studio 2010


увеличить изображение

Рис. 3.1.  Начальная страница Visual Studio 2010

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

Для создания программы необходимо нажать Файл/Создать/Проект или нажать на стартовой странице Visual Studio2010 быструю ссылку Создать проект, выделенную синим цветом. После выбора создания нового проекта появится другое диалоговое окно Создать проект, где необходимо выбрать требуемые опции, а именно: в левом столбце необходимо выбрать Visual C++/Win32, справа наверху – Консольное приложение Win32, справа внизу вписать имя проекта (например, proga1), в графе расположение выбрать вашу папку, где будут храниться все программы, оставить галочку Создать каталог для решения. Диалоговое окно Создать проект представлено на рис. 3.2.

Диалоговое окно Создать проект


увеличить изображение

Рис. 3.2.  Диалоговое окно Создать проект

После этого нужно нажать ОК. Откроется мастер настройки нашего будущего консольного приложения, который представлен на рис. 3.3.

Окно Мастер приложений Win32


увеличить изображение

Рис. 3.3.  Окно Мастер приложений Win32

Заготовка нового проекта в Visual Studio 2010


увеличить изображение

Рис. 3.4.  Заготовка нового проекта в Visual Studio 2010

Требуется нажать кнопку Готово. Тогда в главном окне Visual Studio 2010 закроется начальная страница, и откроется файл proga1.cpp (правое верхнее поле), окно вывода ошибок и предупреждений Вывод (правое нижнее поле), Командный обозреватель (левое вертикальное поле). Данный вид представлен на рис. 3.4.

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

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

Просмотр Обозревателя решений


увеличить изображение

Рис. 3.5.  Просмотр Обозревателя решений

Вместо командного обозревателя можно включить Обозреватель решений, в котором видно все файлы и папки, созданные для нашего нового проекта. Для этого необходимо под Командным обозревателем нажать кнопку Обозреватель решений. Далее в появившемся списке раскрыть папки Файлы исходного кода и Заголовочные файлы. Окно Visual Studio с Обозревателем решений представлено на рис. 3.5.

Когда мы составляем программу в Visual Studio, получается целый проект, который автоматически создается средой Visual Studio. Задача начинающего программиста состоит в том, чтобы напечатать код своей программы в файле *.cpp и запустить программу на выполнение.

Рассмотрим заготовку кода, которую нам предлагает Visual Studio.

Первые две строчки начинаются двумя символами "//". Данные символы означают, что далее на этой строчке следует комментарий, он не воспринимается компилятором как код программы и не будет выдавать ошибку. Удалять эти две строчки не рекомендуется.

Далее следует строчка #unclude "stdafx.h". Данная строка необходима для сборки нашего проекта. Файл stdafx.h – это один из файлов, автоматически создаваемых для нашей программы, и его можно увидеть в левом столбце Обозревателя решений. Эту строчку также нельзя удалять.

Успешное построение проекта


увеличить изображение

Рис. 3.6.  Успешное построение проекта

Далее начинается функция int main(). Автоматически Visual Studio называет ее _tmain и вписывает аргументы int argc, _TCHAR* argv[]. У нас будут самые простые программы для начинающих программистов, поэтому мы изменяем эту строчку и приводим ее к виду: int main() и оставляем return 0, или void main() и стираем return 0. После проведенной нами подготовки необходимо собрать проект, нажав в меню Построение/Построить решение. Тогда в поле Вывод начинается проверка нашего кода. Сейчас проверка прошла успешно и проект построился. Окно Visual Studio после сборки проекта представлено на рис. 3.6.

Попробуем теперь запустить нашу пустую программу. Для этого на клавиатуре необходимо нажать Ctrl+F5. Тогда появится консоль со стандартной надписью после выполнения программы "Для продолжения нажмите любую клавишу…". Консоль представлена на рис. 3.7.

Консоль выполнения программы


Рис. 3.7.  Консоль выполнения программы

После просмотра консоли закройте ее, нажав на крестик.

Теперь можно составить простейшую программу, которая напишет на экране фразу "PRIVET, STUDENT!!!". В код нашей заготовки нужно добавить несколько строк:

#include <iostream>   // т.к. нужно будет использовать оператор вывода на экран cout
using namespace std;   // подключение пространства имен
cout<<"PRIVET, STUDENT!!!"<<endl;   // вывод фразу на экран и перевод курсора на новую строку, 
// чтобы стандартная фраза "Для продолжения нажмите любую клавишу…" не "налипла" на нашу фразу.

Итак, итоговый код программы представлен на рис. 3.8.

Файл с кодом программы


Рис. 3.8.  Файл с кодом программы

После этого опять строим решение, т.к. код программы был изменен. Если построение выполнилось успешно, то можно запускать программу, нажав Ctrl+F5. Если же построение выдало ошибки, то нужно еще раз все проверить, исправить код, после этого построить проект еще раз. Консоль представлена на рис. 3.9.

Консоль выполнения программы


Рис. 3.9.  Консоль выполнения программы

Конечно, в процессе работы с приложением Visual Studio может возникнуть множество вопросов. В меню программы предусмотрена справка и стандартные примеры, которые можно посмотреть. Чтобы включить справку, необходимо нажать Справка/Просмотр справки или воспользоваться горячими клавишами Ctrl+F1. Чтобы посмотреть примеры кодов, в меню нужно выбрать Справка/Примеры.

Занятие 3. Начало работы в приложении Borland С++

Borland C++ - это консольное приложение для составления и запуска программ на языке С++. Данное приложение гораздо проще, чем Microsoft Visual Studio, требует меньшей памяти у компьютера для своей работы.

Допустим, мы установили Borland C++ в папку F:/BC. После установки в папке F:/BC создаем папку OUTPUT.

При запуске программы Borland C++ (запускаем файл BC.exe) появляется консольное окно приложения Borland C++, которое представлено на рис. 3.10.

Приложение Borland C++ после запуска


Рис. 3.10.  Приложение Borland C++ после запуска

При самом первом запуске Borland C++ нужно зайти в настройки, выбрав в меню Options/Directories, как показано на рис. 3.11.

Выбор настроек


Рис. 3.11.  Выбор настроек

В появившемся диалоге необходимо вписать стандартные папки, как показано на рис. 3.12. После этого нужно нажать ОК.

Настройки Borland C++


Рис. 3.12.  Настройки Borland C++

Чтобы печатать код программы, необходимо в меню выбрать File/New, тогда появится поле синего цвета с мигающим курсором, как на рис. 3.13.

Создание нового файла


Рис. 3.13.  Создание нового файла

Наверху в центре можно увидеть надпись "NONAME00.CPP". Эта надпись показывает название файла с кодом программы. Ниже расположено поле с названием Message, где будут отображаться ошибки при проверке программы.

В отличие от Visual Studio, приложению Borland C++ достаточно одного файла с кодом программы, чтобы выполнить ее. Здесь не будет проекта, как в Visual Studio.

Итак, сохраним наш пустой файл для программы под именем proga1.cpp. Для этого нужно нажать в меню File/Save as… Появится диалоговое окно Save File As, которое представлено на рис. 3.14.

Диалоговое окно для сохранения программы


Рис. 3.14.  Диалоговое окно для сохранения программы

На рис. 3.15 показано уже заполненное диалоговое окно.

Сохранение файла с кодом программы


Рис. 3.15.  Сохранение файла с кодом программы

Здесь необходимо выбрать папку, где будут сохраняться все программы. Папка выбирается в поле Files. Какая именно папка предлагается для сохранения, можно увидеть внизу на синем поле. Чтобы выйти из предлагаемой папки, щелкните два раза мышью по двум точкам в списке файлов и папок. В выпавшем списке выберите нужную папку, щелкнув по ней два раза. Название папки должно вписаться в верхнюю строку. Если название папки слишком длинное, то Borland C++ сокращает название и в конце приписывает ˜1. В данном примере название папки было BCprogs, а в приложении Borland C++ она отображается как BCPROG˜1. Хочется также обратить внимание на то, что в нижнем синем поле сменилось название текущей папки для сохранения на следующее: F:\BCPROG˜1\*.CPP. После того, как нужная папка выбрана, необходимо вписать название файла с кодом программы. Для этого в верхней строке нужно стереть значок "*" и вписать название программы proga1. После этого можно нажать кнопку ОК. Если вы все сделали верно, то теперь на синем поле для кода программы будет название \BCPROG˜1\PROGA1.CPP.

Создадим простую программу, которая будет печатать на экране фразу "PRIVET, STUDENT!!!". Набираем код программы, как показано на рис. 3.16.

Код программы


Рис. 3.16.  Код программы

Чтобы проверить, есть ли ошибки, в меню необходимо выбрать Compile/Compile или нажать Alt+F9. На рис. 3.17 показано сообщение о том, что ошибок нет.

Сообщение об успешной компиляции программы


Рис. 3.17.  Сообщение об успешной компиляции программы

Чтобы запустить программу, нужно нажать в меню Run/Run или клавиши Ctrl+F9. После этого внизу в поле Message появится надпись Linking PROGA1.EXE:. Это служебная информация. Если она появилась, значит программа запустилась и выполнилась. Чтобы посмотреть на экран с надписью "PRIVET, STUDENT!!!", необходимо в меню выбрать Window/Output или нажать клавиши Alt+F5. Окно вывода данных представлено на рис. 3.18.

Окно вывода данных


Рис. 3.18.  Окно вывода данных

Краткие итоги

В языке С++ существуют определенные правила оформления программы. Запустить программу можно в разных средах, например Microsoft Visual Studio или Borland C++.

Вопросы

  1. Что такое программа?
  2. Какие ключевые слова придусмотрены для типов данных?
  3. Какова структура программы С++?
  4. Что такое библиотека?
  5. Перечислите арифметические операции С++.
  6. Как записать двойное неравенство в программе С++?

Упражнения

  1. В программе Microsoft Visual Studio создайте новый проект.
  2. Запустите пустую программу.
  3. Запустите программу, печатающую на экране фразу.
  4. То же самое выполните в приложении Borland C++.

Лекция 4. Реализация линейного и разветвляющегося алгоритмов

Умение писать программы начинается с понимания реализации простейших алгоритмов. Разбор линейного и разветвляющегося алгоритмов на примерах с результатами выполнений программ нам в этом поможет.

Цель данной лекции – сформировать однозначное понимание принципов построения программ.

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

Занятие 1. Программная реализация линейного алгоритма

Пример 1. Даны числа . Вычислить сумму и разность чисел и .

Приведем блок-схему на рис. 4.1.

Блок-схема для примера 1


Рис. 4.1.  Блок-схема для примера 1

Код программы (Visual Studio):

// proga10.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
	double a, b, S, R;
	a=2;
	b=7;
	S=a+b;
	R=a-b;
	cout<<"S="<<S<<endl;
	cout<<"R="<<R<<endl;
	return 0;
}

Результат выполнения программы(Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double a, b, S, R;
	a=2;
	b=7;
	S=a+b;
	R=a-b;
	cout<<"S="<<S<<endl;
	cout<<"R="<<R<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



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

Приведем блок-схему на рис. 4.2.

Блок-схема для примера 2


Рис. 4.2.  Блок-схема для примера 2

Код программы (Visual Studio):

// proga11.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main(){
	double x, y, z;
	cout<<"vvedi x=";
	cin>>x;
	y=sin(x); z=log(x);
	cout<<"pri x="<<x<<" y="<<y<<" z="<<z<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Ручной счет:

x=1.5
y=sin(1.5)=0.997495 
z=ln(1.5)=0.405465

Результат выполнения программы (Visual Studio):



Ручной счет:

x=0.2
y=sin(0.2)=0.198669
z=ln(0.2)=-1.609438

Результат выполнения программы(Visual Studio):



Ручной счет:

x=-2
y=sin(-2)=-0.909297
z=ln(-2)=не существует, что соответствует результату на экране.

Код программы (Borland C++):

#include <iostream.h>
#include <math.h>
int main(){
	double x, y, z;
	cout<<"vvedi x=";
	cin>>x;
	y=sin(x);
	z=log(x);
	cout<<"pri x="<<x<<" y="<<y<<" z="<<z<<endl;
	return 0;
}

Результат выполнения программы(Borland C++):



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

Когда требуется записать программно сложную математическую функцию, ее мысленно разбивают на внутреннюю и внешнюю. Например, если дано выражение , то внешней функцией будет возведение в квадрат, а внутренней – тангенс от . Поэтому сначала начинают писать функцию возведения в степень: pow( , 2.0), а потом вписывают на первое место тангенс: pow( tan(x), 2.0).

Когда требуется записать дробь, то ее мысленно разбивают на числитель и знаменатель. если в числителе или знаменателе стоит выражение, а не одно число или одна переменная, то все выражение берут в скобки: будет выглядеть в программе как . Но дробь будет записана в виде .

Пример 3. Составить блок-схему и программу для вычисления значений функций и при различных значениях аргументов . Переменные считать с клавиатуры.

Блок-схема представлена на рис. 4.3.

Блок-схема для примера 3


Рис. 4.3.  Блок-схема для примера 3

Код программы (Visual Studio):

// proga12.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main(){
	double x, y, U, V;
	cout<<"vvedi x=";
	cin>>x;
	cout<<"vvedi y=";
	cin>>y;
	U=pow(x, 2.0)+(y+3.0)/(x-1.0);
	V=1.0/pow(y, exp(1.0))*pow(sin(sqrt(x)+1.5), 2.0);
	cout<<"pri x="<<x<<" y="<<y<<endl;
	cout<<"U="<<U<<" V="<<V<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
#include <math.h>
int main(){
	double x, y, U, V;
	cout<<"vvedi x=";
	cin>>x;
	cout<<"vvedi y=";
	cin>>y;
	U=pow(x,2.0)+(y+3.0)/(x-1.0);
	V=1.0/pow(y,exp(1.0))*pow(sin(sqrt(x)+1.5),2.0);
	cout<<"pri x="<<x<<" y="<<y<<endl;
	cout<<"U="<<U<<" V="<<V<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



Пример 4. Найти длину окружности и площадь круга, если известен радиус.

Решение. Введем обозначения: – радиус, который будет считываться с клавиатуры (т.к. он не задан конкретным числом); – длина окружности, вычисляемая по формуле – площадь круга, вычисляемая по формуле .

Приведем блок-схему на рис. 4.4.

Блок-схема для примера 4


Рис. 4.4.  Блок-схема для примера 4

Код программы (Visual Studio):

// proga13.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main(){
	double r, C, S;
	cout<<"vvedi r=";
	cin>>r;
	C=2.0*3.141593*r;
	S=3.141593*pow(r, 2.0);
	cout<<"r="<<r<<" C="<<C<<" S="<<S<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
#include <math.h>
int main(){
	double r, C, S;
	cout<<"vvedi r=";
	cin>>r;
	C=2.0*M_PI*r;
	S=M_PI*pow(r, 2.0);
	cout<<"r="<<r<<" C="<<C<<" S="<<S<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



Занятие 2. Программная реализация разветвляющегося алгоритма

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

Будут приведены примеры вычисления функций, заданных на разных промежутках кусочно. Также приведены принцип и примеры расчетов для кусочных функций, заданных на двух промежутках и на трех промежутках.

Пример 5. Даны числа . Вычислить сумму и разность чисел и . Сравнить полученные значения и и указать большее из них.

Блок-схема представлена на рис. 4.5.

Блок-схема для примера 5


Рис. 4.5.  Блок-схема для примера 5

Код программы (Visual Studio):

// proga14.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
	double a, b, S, R;
	a=2;
	b=7;
	S=a+b;
	R=a-b;
	cout<<"S="<<S<<" R="<<R<<endl;
	if(S>R) cout<<"Max S"<<endl;
	else cout<<"Max R"<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double a, b, S, R;
	a=2;
	b=7;
	S=a+b;
	R=a-b;
	cout<<"S="<<S<<" R="<<R<<endl;
	if(S>R) cout<<"Max S"<<endl;
	else cout<<"Max R"<<endl;
	return 0;
}

Результат выполнения программы:



Пример 6. Составить блок-схему и программу для вычисления значений функций и при различных значениях аргумента. Учесть область определения функций.

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

Блок-схема представила на рис. 4.6.

Блок-схема для примера 6


Рис. 4.6.  Блок-схема для примера 6

Код программы (Visual Studio):

// proga15.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
	double x, y, z;
	cout<<"vvedi x=";
	cin>>x;
	y=sin(x);
	cout<<"y="<<y;
	if(x>0){
		z=log(x);
		cout<<" z="<<z<<endl;
	}
	else cout<<" z net"<<endl;
	return 0;
}

Результат выполнения программы:



Код программы (Borland C++):

#include <iostream.h>
#include <math.h>
int main(){
	double x, y, z;
	cout<<"vvedi x=";
	cin>>x;
	y=sin(x);
	cout<<"y="<<y;
	if(x>0){
		z=log(x);
		cout<<" z="<<z<<endl;
	}
	else cout<<" z net"<<endl;
	return 0;
}

Результат выполнения программы:



Пример 7. Вычислить значение функции при различных значениях аргумента (аргумент считать с клавиатуры).

Решение: Функция задана как кусочная функция, т.е. при разных значениях она считается по-разному. Следует отметить, что при одном значении аргумента функция будет иметь лишь одно значение, т.е. функция однозначная. График функции представлен на рис. 4.7.

График кусочной функции


Рис. 4.7.  График кусочной функции

Посчитаем значение функции при . Прежде всего необходимо проверить, какое условие верно: "" или "". Условие для первой ветки функции верно, значит считаем .

Посчитаем значение функции при . Прежде всего необходимо проверить, какое условие верно: "" или "". Условие для второй ветки функции верно, значит считаем .

При расчете кусочной функции так или иначе сначала проводится проверка условия, поэтому вычисление таких функций реализуется через разветвляющийся алгоритм. В данном примере будет один блок разветвления (соответственно один оператор if в программе). Условием будет служить проверка "". Если условие верно, то функция считается по первой ветке, если ложно, то по второй ветке. Второе условие "" будет лишним, т.к. оно соответствует стрелке "нет" от первого условия "".

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

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

Блок-схема для примера 7 представлена на рис. 4.8.

Блок-схема для примера 7


Рис. 4.8.  Блок-схема для примера 7

Код программы (Visual Studio):

// proga16.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(){
	double x, Z;
	cout<<"x=";
	cin>>x;
	if(x<1){
		Z=x+3;
	}
	else {
		Z=4*x;
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы:



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double x, Z;
	cout<<"x=";
	cin>>x;
	if(x<1){
		Z=x+3;
	}
	else { Z=4*x;
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы:



Пример 8. Вычислить значение функции при различных значениях аргумента (аргумент считать с клавиатуры).

Решение: Функция задана как кусочная функция, определенная на трех промежутках. График функции представлен на рис. 4.9.

График кусочной функции


Рис. 4.9.  График кусочной функции

В данной задаче будем использовать два условия для определения нужной ветви функции. Первое условие "" определяет, следует ли рассчитывать по первой ветви функции. Второе условие "" определяет, следует ли рассчитывать по второй ветви. Если и первое, и второе условия оказались ложными (не выполнились), то следует рассчитывать по третьей ветви. Следовательно, в блок-схеме будем использовать два блока разветвления, а в программе два оператора условия if.

Например, нужно вычислить при . Первое условие "" выполняется верно, т.к. . Следовательно, считать следует по первой ветви, а именно: .

Например, нужно вычислить при . Первое условие "" выполняется неверно, т.к. 2,5>0. Проверяем второе условие "": 2,5≤5 – верно. Следовательно, считать следует по второй ветви, а именно: .

Например, нужно вычислить при . Первое условие "" выполняется неверно, т.к. 10>0. Проверяем второе условие "": 10≤5 – неверно. Следовательно, ни первое, ни второе условия не выполнились, и считать следует по третьей ветви, а именно: .

Блок-схема представлена на рис. 4.10.

Блок-схема для примера 8


Рис. 4.10.  Блок-схема для примера 8

Код программы (Visual Studio):

// proga17.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main(){
	double x,Z;
	cout<<"x=";
	cin>>x;
	if(x<0){ Z=pow(x, 2.0);
	}
	else {if(x<=5){
			Z=fabs(x);}
		else {
			Z=5.0;}
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
#include <math.h>
int main(){
	double x, Z;
	cout<<"x=";
	cin>>x;
	if(x<0){
		Z=pow(x, 2.0);
	}
	else {
		if(x<=5){
			Z=fabs(x);
	}
	else {
		Z=5.0;
		}
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



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

Пример 9. Вычислить значение функции при различных значениях аргументов и (аргументы и считать с клавиатуры).

Решение: Данный Пример аналогичен Примеру 7. Отличие состоит в том, что сейчас функция зависит от двух переменных и . Для реализации алгоритма разницы нет, поэтому за основу возьмем блок-схему и программу из Примера 7.

Блок-схема представлена на рис. 4.11.

Блок-схема для примера 9


Рис. 4.11.  Блок-схема для примера 9

Код программы (Visual Studio):

// proga18.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(){
	double x, y, Z;
	cout<<"x=";
	cin>>x;
	cout<<"y=";
	cin>>y;
	if(x*y<1){ Z=x+y;
	}
	else {Z=x-y;
	}
	cout<<"Z="<<Z<<endl;
	return 0;}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double x, y, Z;
	cout<<"x=";
	cin>>x;
	cout<<"y=";
	cin>>y;
	if(x*y<1){
		Z=x+y;
	}
	else {
		Z=x-y;
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



Ручной счет.

при х=-3; у=0,5 ху=-3·0,5=-1,5 <1 Z=x+y=-3+0,5=-2,5.
при x=0,8; y=2 xy=0,8·2=1,6≥1 Z=x-y=0,8-2=-1,2.

Пример 10. Вычислить значение функции при различных значениях аргументов и (аргументы и считать с клавиатуры).

Решение. В данном примере функция определена на трех промежутках, как в Примере 8. Отличие состоит в том, что зависит от двух переменных и . Для реализации алгоритма разницы нет, поэтому за основу возьмем блок-схему и программу из Примера 8.

Блок-схема представлена на рис. 4.12.

Блок-схема для примера 10


Рис. 4.12.  Блок-схема для примера 10

Код программы (Visual Studio):

// proga19.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(){
	double x, y, Z;
	cout<<"x=";
	cin>>x;
	cout<<"y=";
	cin>>y;
	if(x*y<0){ Z=x+y;}
	else {
		if(x*y<=5){
			Z=x-y;
		}
		else {
			Z=y;
		}
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double x, y, Z;
	cout<<"x=";
	cin>>x;
	cout<<"y=";
	cin>>y;
	if(x*y<0){
		Z=x+y;
	}
	else {
		if(x*y<=5){
			Z=x-y;
	}
	else {
		Z=y;
		}
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



Ручной счет:

при х=-1,5; у=2   ху=-1,5·2=-3 <0   Z={по первой ветви}=x+y=-1,5+2=0,5.
при x=1,2; y=2   xy=1,2·2=2,4≤5   Z={по второй ветви}=x-y=1,2-2=-0,8.
при x=3; y=7   xy=3·7=21 >5   Z={по третьей ветви}=y=7.

Пример 11. Найти наибольшее (максимальное) из трех чисел.

Решение. Обозначим три числа буквами . Числа будем считывать с клавиатуры. Для нахождения наибольшего из трех чисел введем еще одну переменную , которая будет хранить наибольшее значение. Принцип нахождения наибольшего значения заключается в следующем. Сначала принимаем как первое число . Потом поочередно сравниваем с оставшимися числами и . Если окажется, что больше уже запомненного , то следует перезаписать , изменив его значение на значение . Если же , то изменять не нужно, поэтому ветвь "нет" будет пустой. Аналогично сравниваем и . После двух сравнений в переменной будет лежать наибольшее из трех чисел.

Примечание. Если чисел будет больше трех, например, пять чисел, то следует сделать четыре сравнения.

Примечание. Если нужно определить наименьшее из трех чисел, то вводят переменную , приравнивают к первому числу. Затем поочередно сравнивают оставшиеся числа: "", "".

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

Блок-схема представлена на рис. 4.13.

Блок-схема для примера 11


Рис. 4.13.  Блок-схема для примера 11

Выполнение блок-схемы (при вводимых значениях чисел 23,7; -0,4; 34,28)

Начало
ввод данных a=23,7; b=-0,4; c=34,28
Экран
a=23,7
b=-0,4
c=34,28
max=a=23,7
b>max   -0,4>23,7  нет
c>max   34,28>23,7  да
max=c=34,28
вывод max
Экран
a=23,7
b=-0,4
c=34,28
max=34,28
Конец.

Код программы (Visual Studio):

// proga20.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
	double a, b, c, max;
	cout<<"a=";
	cin>>a;
	cout<<"b=";
	cin>>b;
	cout<<"c=";
	cin>>c;
	max=a;
	if(b>max){
		max=b;
	}
	if(c>max){
		max=c;
	}
	cout<<"max="<<max<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double a, b, c, max;
	cout<<"a=";
	cin>>a;
	cout<<"b=";
	cin>>b;
	cout<<"c=";
	cin>>c;
	max=a;
	if(b>max){
		max=b;
	}
	if(c>max){
		max=c;
	}
	cout<<"max="<<max<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



Пример 12. Найти значение функции при различных значениях аргумента (аргумент считать с клавиатуры).

Решение. Функция считается как наибольшее из трех выражений. Задача схожа с Примером 11. Введем обозначения: . Тогда наша задача максимально будет похожа на Пример 11.

Блок-схема представлена на рис. 4.14.

Блок-схема для примера 12


Рис. 4.14.  Блок-схема для примера 12

Выполнение блок-схемы (при вводимом x=1)

Начало
ввод x=1
Экран
x=1
a=3x=3·1=3
b=10-x=10-1=9
c=|x|=|1|=1
Z=a=3
b>Z   9>3  да
Z=b=9
c>Z   1>9  нет
вывод Z
Экран
x=1
Z=9
Конец.

Код программы (Visual Studio):

// proga21.cpp: определяет точку входа для консольного приложения.
//	
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int main(){
	double x, a, b, c, Z;
	cout<<"x=";
	cin>>x;
	a=3.0*x;
	b=10.0-x;
	c=fabs(x);
	Z=a;
	if(b>Z){Z=b;}
	if(c>Z){Z=c;}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
#include <math.h>
int main(){
	double x, a, b, c, Z;
	cout<<"x=";
	cin>>x;
	a=3.0*x;
	b=10.0-x;
	c=fabs(x);
	Z=a;
	if(b>Z){
		Z=b;
	}
	if(c>Z){
		Z=c;
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



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

Блок-схема представлена на рис. 4.15.

Блок-схема для примера 13


Рис. 4.15.  Блок-схема для примера 13

Код программы (Visual Studio):

// proga22.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
	double x, y, a, b, c, Z;
	cout<<"x=";
	cin>>x;
	cout<<"y=";
	cin>>y;
	a=x+y;
	b=x-y;
	c=x*y;
	Z=a;
	if(b>Z){
		Z=b;
	}
	if(c>Z){
		Z=c;
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Visual Studio):



Код программы (Borland C++):

#include <iostream.h>
int main(){
	double x, y, a, b, c, Z;
	cout<<"x=";
	cin>>x;
	cout<<"y=";
	cin>>y;
	a=x+y;
	b=x-y;
	c=x*y;
	Z=a;
	if(b>Z){
		Z=b;
	}
	if(c>Z){
		Z=c;
	}
	cout<<"Z="<<Z<<endl;
	return 0;
}

Результат выполнения программы (Borland C++):



Краткие итоги

Одна и та же блок-схема может быть использована при написании разных программ С++. Результат выполнения программы из-за этого не должен меняться.

Упражнения

  1. Составьте блок-схему и программу для вычисления значений функций при различных значениях аргументов и .
  2. Составьте блок-схему и программу по нахождению корней квадратного уравнения через дискриминант. Коэффициенты квадратного уравнения считывайте с клавиатуры.
  3. Составьте блок-схему и программу, которая спрашивает у пользователя возраст и в соответствии с возрастной группой ("дошкольник", "школьник", "взрослый", "пожилой") выдает соответствующую фразу на экран.
  4. Составьте блок-схему и программу для вычисления значения функции при разных значениях аргументов и .
  5. Составьте блок-схему и программу для вычисления значений функции при разных значениях аргументов и .

Лекция 5. Реализация циклического алгоритма

Продолжаем изучать применение стандартных элементов алгоритма в простейших задачах. Циклический алгоритм – это мощное средство при решении разных примеров.

Цель данной лекции – научиться правильно реализовывать циклический алгоритм в разных задачах.

В данной лекции мы рассмотрим множество задач, соответствующих циклическому алгоритму. В каждой задаче будут представлены блок-схемы, коды программ для Microsoft Visual Studio, а также результаты выполнения программ (консоли).

Занятие 1. Программная реализация циклического алгоритма

Пример 1. Вычислить таблицу "" значений функции при с шагом 2,5.

Решение. Т.к. переменная х имеет не одно, а несколько значений (а именно 0; 2,5), то следует использовать циклический алгоритм. Решим данную задачу несколькими способами: блок-схема с предусловием, блок-схема с постусловием, программа с оператором while (соответствует блок-схеме с предусловием), программа с оператором for (соответствует блок-схеме с предусловием), программа с оператором do while (соответствует блок-схеме с постусловием).

В данной задаче мы имеем:

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

В программе мы будем использовать функцию setw(10) из библиотеки <iomanip>, чтобы таблица значений строилась ровно.

Блок-схема с предусловием представлена на рис. 5.1.

Блок-схема с предусловием для примера 1


Рис. 5.1.  Блок-схема с предусловием для примера 1

Выполнение блок-схемы:

Начало
вывод заголовка таблицы "x, f"
x=0
x≤4   0≤4   да
f=2x+1=280+1=1
вывод x, f
Экран
x	f
0	1
x=x+2,5=0+2,5=2,5
наверх
x≤4   2,5≤4   да
f=2x+1=2*2,5+1=6
вывод x, f
Экран
x	f
0	1
2,5	6
x=x+2,5=2,5+2,5=5
наверх
x≤4   5≤4   нет
выход из цикла по х
Конец.

Код программы с оператором while:

// proga23while.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	double x, f;
	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
	x=0;
	while(x<=4){
		f=2.0*x+1.0;
		cout<<setw(10)<<x<<setw(10)<<f<<endl;
		x=x+2.5;
	}
	return 0;}

Код программы с оператором for:

// proga23for.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{	
	double x, f;
	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
	for(x=0; x<=4; x=x+2.5){
		f=2.0*x+1.0;
		cout<<setw(10)<<x<<setw(10)<<f<<endl;
	}
	return 0;}

Блок-схема с постусловием представлена на рис. 5.2.

Блок-схема с постусловием для примера 1


Рис. 5.2.  Блок-схема с постусловием для примера 1

Выполнение блок-схемы:

Начало
x=0
f=2x+1=2*0+1=1
вывод x, f
Экран
x	f
0	1
x=x+2,5=0+2,5=2,5
x≤4   2,5≤4   да
наверх
f=2x+1=2*2,5+1=6
вывод x, f
Экран
x	f
0	1
2,5	6
x=x+2,5=2,5+2,5=5
x≤4   5≤4   нет
выход из цикла по х
Конец.

Код программы с оператором do while:

// proga23dowhile.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{	
	double x, f;
	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
	x=0;
	do{
		f=2.0*x+1.0;
		cout<<setw(10)<<x<<setw(10)<<f<<endl;
		x=x+2.5;
	}while(x<=4);
	return 0;
}

Результат выполнения программ с операторами while, for, do while:



Ручной счет:

Диапазон значений х: 0; 2,5.
при x=0		f=2x+1=2*0+1=1
при x=2,5	f=2x+1=2*2,5+1=6

Пример 2. Вычислить таблицу "" значений функции при с шагом 1.

Решение. Функция является кусочной, поэтому для ее расчета используем разветвляющийся алгоритм.

Необходимо добавить реализацию одномерного цикла по переменной .

В данной задаче:

В теле цикла следует рассчитать значение функции и вывести очередную строку значений таблицы на экран.

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

Приведем две блок-схемы: с предусловием и с постусловием.

К блок-схеме с предусловием относятся две программы – с оператором while и for.

К блок-схеме с постусловием относится одна программа с оператором do while.

Блок-схема с предусловием приведена на рис. 5.3.

Блок-схема с предусловием для примера 2


Рис. 5.3.  Блок-схема с предусловием для примера 2

Код программы с оператором while:

// proga24while.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double x, Z;
	cout<<setw(10)<<"x"<<setw(10)<<"Z"<<endl;
	x=-1.0;
	while(x<=2.0){
		if(x<1){
			Z=x+3;
		}
		else {
			Z=4*x;
		}
		cout<<setw(10)<<x<<setw(10)<<Z<<endl;
		x=x+1.0;
	}
	return 0;}

Код программы с оператором for:

// proga24for.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double x, Z;
	cout<<setw(10)<<"x"<<setw(10)<<"Z"<<endl;
	for(x=-1; x<=2; x=x+1){
		if(x<1){
			Z=x+3;
		}
		else {
			Z=4*x;
		}
		cout<<setw(10)<<x<<setw(10)<<Z<<endl;
	}
	return 0;}

Блок-схема с постусловием представлена на рис. 5.4.

Блок-схема с постусловием для примера 2


Рис. 5.4.  Блок-схема с постусловием для примера 2

Код программы с оператором do while:

// proga24dowhile.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double x, Z;
	cout<<setw(10)<<"x"<<setw(10)<<"Z"<<endl;
	x=-1;
	do{
		if(x<1){
			Z=x+3;
		}
		else {
			Z=4*x;
		}
		cout<<setw(10)<<x<<setw(10)<<Z<<endl;
		x=x+1;
	}while(x<=2);
	return 0;}

Результат выполнения программ с операторами while, for, do while:



Ручной счет:

Диапазон значений х: -1; 0; 1; 2.
при x=-1	Z={по первой ветви}=x+3=-1+3=2;
при x=0		Z={по первой ветви}=x+3=0+3=3;
при x=1		Z={по первой ветви}=4x=4*1=4;
при x=2		Z={по первой ветви}=4x=4*2=8.

Пример 3. Вычислить таблицу "" значений функции при с шагом 1, с шагом 5 .

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

В данной задаче имеем:

Блок-схема с предусловием приведена на рис. 5.5.

Блок-схема с предусловием для примера 3


Рис. 5.5.  Блок-схема с предусловием для примера 3

Код программы с оператором while:

// proga25while.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double x, y, Z;
	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"Z"<<endl;
	x=-1;
	while(x<=0.5){
		y=5;
		while(y<=15){
			if(x*y<1){
				Z=x+y;
			}
			else{
				Z=x-y;
			}
			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<Z<<endl;
			y=y+5;
		}
		x=x+1;
	}
	return 0;}

Код программы с оператором for:

// proga25for.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double x, y, Z;
	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"Z"<<endl;
	for(x=-1; x<=0.5; x=x+1){
		for(y=5; y<=15; y=y+5){
			if(x*y<1){
				Z=x+y;
			}
			else{
				Z=x-y;
			}
			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<Z<<endl;
		}
	}
	return 0;}

Блок-схема с постусловием приведена на рис. 5.6.

Блок-схема с постусловием для примера 3


Рис. 5.6.  Блок-схема с постусловием для примера 3

Код программы (Visual Studio) с оператором do while (постусловие):

// proga25dowhile.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double x, y, Z;
	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"Z"<<endl;
	x=-1;
	do{
		y=5;
		do{
			if(x*y<1){
				Z=x+y;
			}
			else{
				Z=x-y;
			}
			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<Z<<endl;
			y=y+5;
		}while(y<=15);
		x=x+1;
	}while(x<=0.5);
	return 0;}

Результат выполнения программ с операторами while, for, do while:



Ручной счет:

Диапазон значений х: -1; 0.
Диапазон значений у: 5, 10, 15.
при x=-1	y=5	Z={по первой ветви}=x+y=-1+5=4;
при x=-1	y=10	Z={по первой ветви}=x+y=-1+10=9;
при x=-1	y=15	Z={по первой ветви}=x+y=-1+15=14;
при x=0		y=5	Z={по первой ветви}=x+y=0+5=5;
при x=0		y=10	Z={по первой ветви}=x+y=0+10=10;
при x=0		y=15	Z={по первой ветви}=x+y=0+15=15.

Примечание. В данном примере операторы вложенного и внешнего циклов совпадают. Например, в одной программе задействован один оператор while два раза. Можно сочетать операторы цикла как угодно: оператор do while может быть вложен в оператор for, оператор for в оператор while и т.д. Результат выполнения программы не должен зависеть от выбранного оператора цикла.

Занятие 2. Исследование таблицы значений функции

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

  1. Нахождение наибольшего (наименьшего ) значения функции.



    max=-10E10;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	if(f>max){
    		max=f;
    }
    }
    Примечание. Если нужно найти наименьшее значение функции, то следует сделать следующие замены: "" поменять на "", "" поменять на "", "" поменять на "".
  2. Нахождение суммы значений функции



    S=0;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	S=S+f;
    }
    cout<<"S="<<S<<endl;
  3. Нахождение произведения значений функции



    P=1;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	P=P*f;
    }
    cout<<"P="<<S<<endl;
  4. Нахождение среднего арифметического значения и количества значений функции



    S=0;
    k=0;
    for(x=xn; x<=xk; x=x+h){
    	f=…;
    	S=S+f;
    	k=k+1;
    }
    S=S/k;
    cout<<"S="<<S<<endl;
    cout<<"k="<<k<<endl;

Пример 4. Вычислить таблицу "" значений функции при с шагом 1. Найти сумму всех значений функции; произведение значений, меньших 6; минимальное значение функции.

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

Введем обозначения:

Т.к. нужно найти произведение значений, меньших 6, то следует добавить условие "" при вычислении произведения.

Будем реализовывать цикл с предусловием, используя оператор for.

Блок-схема с предусловием:Код программы с оператором for:



// proga26.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	double x,f,S,P,min;
	cout<<setw(10)<<"x"<<setw(10)<<"f"<<endl;
	S=0;
	P=1;
	min=10E10;
	for(x=0; x<=4; x=x+1){
		f=2*x+1;
		cout<<setw(10)<<x<<setw(10)<<f<<endl;
		S=S+f;
		if(f<6){
			P=P*f;
		}
		if(f<min){
			min=f;
		}
	}
	cout<<"S="<<S<<endl;
	cout<<"P="<<P<<endl;
	cout<<"min="<<min<<endl;
	return 0;
}

Результат выполнения программы:



Ручной счет:

Диапазон значений х: 0, 1, 2, 3, 4.
при x=0	f=2x+1=2*0+1=1;
при x=1	f=2x+1=2*1+1=3;
при x=2	f=2x+1=2*2+1=5;
при x=3	f=2x+1=2*3+1=7;
при x=4	f=2x+1=2*4+1=9;
сумма всех значений:S=1+3+5+7+9=25;
произведение значений, меньших 6: P=1*3*5=15;
наименьшее значение функции: min=1.

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

Пример 5. Нарисовать на экране бесконечную "змейку" символами "*".

Решение. Определим сначала внешний вид "змейки":

*
 *
  *
   *
  *
 *
*
 *
  *

Т.к. "змейка" должна быть бесконечной, то необходимо организовать бесконечный цикл. В этом случае будем использовать оператор while с всегда выполняемым условием true: while(true). Внутри этого бесконечного цикла будем рисовать один период "змейки", т.е. один холм. За счет бесконечного цикла на экране будет бесконечное число раз рисоваться наш холм.

Теперь стоит решить, какой ширины будет наша "змейка". Будем запрашивать ширину "змейки" у пользователя, т.е. с клавиатуры. Обозначим ширину переменной . Холм состоит из двух частей – расширяющейся и сужающейся. Чтобы нарисовать расширяющуюся часть, будем использовать цикл for по переменной от 1 до и функцию setw(i). Чтобы нарисовать сужающуюся часть, будем использовать цикл for по переменной от до 1 и функцию setw(i).

Таким образом, внутри бесконечного цикла while вложены последовательно два цикла for – первый с увеличением переменной цикла, второй с уменьшением.

Код программы:

// snake.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	int i, n;
	cout<<"vvedi n=";
	cin>>n;
	while (true){
		for(i=1; i<=n; i=i+1){
			cout<<setw(i)<<"*"<<endl;
		}
		for(i=n; i>=1; i=i-1){
			cout<<setw(i)<<"*"<<endl;
		}
		}
	return 0;
}

Результат выполнения программы: при :



Краткие итоги

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

Упражнения

  1. Составьте блок-схему и программу для вычисления суммы всех целых чисел от 1 до 100 включительно.
  2. Постройте таблицу значений функции при с шагом 0,5. Определите наименьшее значение функции и значение , при котором оно достигается.
  3. Составьте блок-схему и программу для вычисления таблицы значений функций при c шагом 1. Найдите сумму всех значений , количество значений , меньших 10, наимешьшее значение , наибольшее значение .
  4. Составьте блок-схему и программу для вычисления таблицы значений функции при c шагом 0,05; y задать с клавиатуры.
  5. Составьте блок-схему и программу для вычисления таблицы значений функции при c шагом 9,3; c шагом 0,75. Определите наибольшее отрицательное значение функции, наименьшее положительное значение функции, произведение ненулевых значений функции, количество значений функции, больших 1 или меньших -1.
  6. Составьте программу, которая нарисует на экране геометрическую фигуру. Попробуйте разные варианты:
    • квадрат,
    • треугольник,
    • прямоугольник.
    Модифицируйте программу таким образом, чтобы на экране появлялась фигура заданное число раз.

Лекция 6. Массивы

Существует ряд задач, в которых одни и те же действия нужно совершить над набором данных, массивом. Массивы применяются в разных задачах, начиная от математики (вектора, матрицы), заканчивая оконными приложениями (набор строк, параметры приложения и т.д.).

Цель данной лекции – ознакомить студентов с понятием массива, его видами; показать основные принципы работы с массивами.

Массив – это пронумерованный набор однотипных элементов.

Массивы бывают статическими и динамическими. У статического массива количество элементов известно заранее и не может быть изменено. У динамического массива количество элементов заранее неизвестно и определяется в процессе выполнения программы.

Также массивы различаются по размерности: одномерные, двумерные, трехмерные и т.д. Примером одномерного массива может послужить вектор . Примером двумерно массива может послужить матрица. Примером трехмерного массива может послужить набор высот местности.

Массивы различают по типу элементов. Бывают целочисленные, вещественные (состоящие из дробных чисел), символьные массивы.

Примеры массивов:

  1. вектор – одномерный вещественный массив из трех элементов;
  2. матрица – двумерный целочисленный массив из шести элементов;
  3. – одномерный символьный массив;
  4. – не является массивом, т.к. часть элементов символы, часть элементов числа.

Мы будем рассматривать только статические одномерные и двумерные численные массивы.

Занятие 1. Одномерные массивы

Индекс – это номер элемента в массиве.

У одномерного массива один индекс, обычно он обозначается .

Чтобы использовать одномерный массив в программе, необходимо:

  1. объявить массив в функции main():
    тип_данных имя_массива[количество элементов];
    double a[3];   //статический массив а из трех дробных чисел
    int b[7];   //статический массив b из семи целых чисел
  2. проинициализировать массив, т.е. задать каждому элементу конкретное числовое значение;
  3. провести вычисления, исследования.

Примечание. Индексация в массиве начинается с 0, т.е. индекс у самого первого элемента в массиве . Индексация в массиве указана на рис. 6.1.

Индексация одномерного массива


Рис. 6.1.  Индексация одномерного массива

Способы инициализации одномерного массива представлены в табл. 6.1. Обратим внимание на то, что число известно заранее и в программе фигурировать не будет.

Таблица 6.1. Способы инициализации одномерного массива a[n]
Часть блок-схемы Часть программы
1. инициализация числами



double a[4]={0.5, -2,856, 1};
2. с клавиатуры:



double a[n];
int i;
for(i=0; i<n; i=i+1){
	cout<<"a["<<i<<"]=";
	cin>>a[i];
}
3. из файла:



double a[n];
int i;
fstream file;
file.open("1.txt", ios::in);
for(i=0; i<n; i=i+1){
	file>>a[i];
}
file.close();
4. по заданной формуле a[i]=f(i):



double a[n];
int i;
for(i=0; i<n; i=i+1){
	a[i]=f(i);
}

Примечание. Более подробно работа с файлами будет рассмотрена позже.

Вывод одномерного массива на экран представлен в табл. 6.2.

Таблица 6.2. Вывод одномерного массива на экран
Часть блок-схемыЧасть программы



for(i=0; i<n; i=i+1){
	cout<<"a["<<i<<"]="<<a[i]<<endl;
}
				

Принципы нахождения таких величин, как сумма, произведение, минимальное, максимальное значение, представлены в табл. 6.3.

Таблица 6.3. Принципы исследования одномерного массива
Часть блок-схемыЧасть программы
1. нахождение суммы:



s=0;
for(i=0; i<n; i=i+1){
	s=s+a[i];
}
cout<<"s="<<s<<endl;
2. нахождение произведения:



p=1;
for(i=0; i<n; i=i+1){
	p=p*a[i];
}
cout<<"p="<<p<<endl;
3. нахождение среднего арифметического и количества элементов:



s=0, k=0;
for(i=0; i<n; i=i+1){
	s=s+a[i];
	k=k+1;
}
s=s/k;
cout<<"s="<<s<<endl;
cout<<"k="<<k<<endl;
4. нахождение максимального элемента:



max=-10E10;
imax=0;
for(i=0; i<n; i=i+1){
	if(a[i]>max){
		max=a[i];
		imax=i;
	}
}
cout<<"max="<<max<<" imax="<<imax<<endl;
5. нахождение минимального элемента:



min=10E10;
imin=0;
for(i=0; i<n; i=i+1){
	if(a[i]<min){
		min=a[i];
		imin=i;
		}
	}
cout<<"min="<<min<<" imin="<<imin<<endl;
6. поменять местами элементы с индексами i1 и i2:



tmp=a[i1];
a[i1]=a[i2];
a[i2]=tmp;
7. вычисление формулы :



s=0;
for(i=0; i<n; i=i+1){
	s=s+f(a[i],i);
}
cout<<"s="<<s<<endl;

Пример 1. Даны четыре одномерных массива: вводится с клавиатуры, вычисляется по формуле вычисляется по формуле . Построить таблицу значений массивов.

Решение. Сначала необходимо проинициализировать массивы согласно условию задачи.

Массив задан числами (первый способ инициализации), поэтому он будет проинициализирован при объявлении.

В цикле по переменной введем с клавиатуры (второй способ инициализации), массивы и рассчитаем по формулам (четвертый способ инициализации).

Далее организуем еще один цикл по переменной , в котором выведем все проинициализированные массивы на экран.

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

Блок-схема представлена на рис. 6.2.

Блок-схема для примера 1


Рис. 6.2.  Блок-схема для примера 1

Код программы (Visual Studio) с оператором for:

// proga27.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	double a[8]={1,2,3,4,5,6,7,8};
	double b[8], c[8], d[8];
	int i;
	for(i=0; i<8; i=i+1){
		cout<<"b["<<i<<"]=";
		cin>>b[i];
		c[i]=2.0*i;
		d[i]=a[i]+b[i]+c[i];
	}
	cout<<setw(2)<<"i"<<setw(5)<<"a"<<setw(5)<<"b"<<setw(5)<<"c"<<setw(5)<<"d"<<endl;
	for(i=0; i<8; i=i+1){
		cout<<setw(2)<<i<<setw(5)<<a[i]<<setw(5)<<b[i]<<setw(5)<<c[i]<< setw(5)<<d[i]<<endl;
	}
	return 0;
}

Результат выполнения программы:



Пример 2. Массив задан формулой . Вычислить сумму положительных элементов массива и поменять местами первый и последний элементы.

Решение.

Обозначим за сумму положительных элементов массива. При расчете требуется дополнительное условие: "". Первый элемент массива имеет индекс 0, последний элемент имеет индекс 9, поэтому будем менять местами и . Из-за перемены мест элементов массив изменится, поэтому выведем его еще раз.

Блок-схема представлена на рис. 6.3.

Блок-схема для примера 2


Рис. 6.3.  Блок-схема для примера 2

Код программы (Visual Studio) с оператором for:

// proga28.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
	double S, tmp, a[10];
	int i;
	S=0;
	for(i=0; i<10; i=i+1){
		a[i]=3.0*i-5.0;
		cout<<setw(3)<<a[i];
		if(a[i]>0){
			S=S+a[i];
		}
	}
	cout<<endl;
	cout<<"S="<<S<<endl;
	tmp=a[0];
	a[0]=a[9];
	a[9]=tmp;
	for(i=0; i<10; i=i+1){ cout<<setw(3)<<a[i]; }
	cout<<endl;
	return 0;}

Результат выполнения программы:



Ручной счет:

при i=0	a(0)=3i-5=3·0-5=-5;
при i=1	a(1)=3i-5=3·1-5=-2;
при i=2	a(2)=3i-5=3·2-5=1;
при i=3	a(3)=3i-5=3·3-5=4;
при i=4	a(4)=3i-5=3·4-5=7;
при i=5	a(5)=3i-5=3·5-5=10;
при i=6	a(6)=3i-5=3·6-5=13;
при i=7	a(7)=3i-5=3·7-5=16;
при i=8	a(8)=3i-5=3·8-5=19;
при i=9	a(9)=3i-5=3·9-5=22;
сумма положительных элементов S=1+4+7+10+13+16+19+22=92.·

Занятие 2. Двумерные массивы

У двумерного массива имеется два индекса: – номер строки, – номер столбца.

Индексация двумерного массива представлена на рис. 6.4.

Индексация двумерного массива


Рис. 6.4.  Индексация двумерного массива

Для использования двумерного массива в программе необходимо:

  1. Объявить массив в функции main():
    тип_данных имя_массива [количество строк][количество столбцов];
    double a[5][9];   // двумерный массив из 5 строк, 9 столбцов
  2. Проинициализировать массив;
  3. Провести вычисления, исследования.

Способы инициализации двумерного массива представлены в таблице 6.4. Обратим внимание на то, что числа и известны заранее и в программе фигурировать не будут.

Таблица 6.4. Способы инициализации двумерного массива a[n][m]
Часть блок-схемыЧасть программы
1. из файла:



double a[n][m];
int i,j;
fstream file;
file.open("1.txt", ios::in);
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		file>>a[i][j];
	}
}
file.close();
2. по заданной формуле :



double a[n][m];
int i,j;
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		a[i][j]=f(i,j);
}
}

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

Вывод двумерного массива на экран представлен в табл. 6.5.

Таблица 6.5. Вывод двумерного массива на экран
Часть блок-схемыЧасть программы



for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		cout<<setw(6)<<a[i][j];
	}
	cout<<endl;
}

Принципы нахождения таких величин, как сумма, произведение, минимальное, максимальное значение, представлены в табл. 6.6.

Таблица 6.6. Принципы исследования двумерного массива
Часть блок-схемыЧасть программы
1. нахождение суммы:



s=0;
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		s=s+a[i][j];
	}
}
cout<<"s="<<s<<endl;
2. нахождение произведения:



p=1;
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		p=p*a[i][j];
	}
}
cout<<"p="<<p<<endl;
3. нахождение среднего арифметического и количества элементов:



s=0, k=0;
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		s=s+a[i][j];
		k=k+1;
	}
}
s=s/k;
cout<<"s="<<s<<endl;
cout<<"k="<<k<<endl;
4. нахождение максимального элемента:



max=-10E10;
imax=0; jmax=0;
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		if(a[i]>max){
			max=a[i][j];
			imax=i;
			jmax=j;
		}
	}
}
cout<<"max="<<max<<endl;
cout<<"imax="<<imax<<endl;
cout<<"jmax="<<jmax<<endl;
5. нахождение минимального элемента:



min=10E10;
imin=0; jmin=0;
for(i=0; i<n; i=i+1){
	for(j=0; j<m; j=j+1){
		if(a[i][j]<min){
			min=a[i][j];
			imin=i;
			jmin=j;
		}
	}
}
cout<<"min="<<min<<endl;
cout<<"imin="<<imin<<endl;
cout<<"jmin="<<jmin<<endl;
				
6. поменять элементы и местами:



tmp=a[i1][j1];
a[i1][j1]=a[i2][j2];
a[i2][j2]=tmp;
7. поменять местами строки и :



for(j=0; j<m; j=j+1){
	tmp=a[i1][j];
	a[i1][j]=a[i2][j];
	a[i2][j]=tmp;
}
8. поменять местами столбцы и :



for(i=0; i<n; i=i+1){
	tmp=a[i][j1];
	a[i][j1]=a[i][j2];
	a[i][j2]=tmp;
}
9. вычисление формулы :



s=0;
for(i=0; i<n; i=i+1){
	s=s+f(a[i][j],i,j);
}
cout<<"s="<<s<<endl;

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

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

Пример 3. Массив задан формулой . Найти сумму элементов во второй строке, поменять местами первую и третью строки, найти произведение по формуле .

Решение. Данную задачу можно разбить на несколько этапов:

  1. задать массив по формуле и вывести его на экран;
  2. найти сумму элементов во второй строке и вывести ее на экран;
  3. поменять местами первую и третью строки;
  4. вывести на экран измененный массив;
  5. найти произведение по формуле и вывести его на экран.

Каждый указанный этап решается с помощью циклов. Все циклы целесообразно использовать с предусловием (в программе – оператор for). На первом этапе следует организовать двумерный цикл по , по , т.к. необходимо задать значениями и вывести на экран весь массив. На втором этапе перед циклом необходимо задать , а в теле цикла по насчитывать значение . Индекс задаем как 1, что соответствует второй строке. Следует отметить, что нельзя считать сумму по какой-то определенной строке (столбце, диагонали) внутри двумерного цикла, т.к. в этом случае будет больше в разы (зависит от количества строк/столбцов).На третьем этапе индексы строк берем – для первой строки, – для третьей строки. Замена строк организуется в одномерном цикле по . На четвертом этапе матрица а должна быть отображена на экране. Нам требуется показать, что замена строк выполнена верно.На пятом этапе перед циклом следует задать , а в теле цикла насчитывать произведение. Цикл организуем одномерный по от 0 до 2 включительно, т.к. согласно формуле изменяется только .

Блок-схема для примера 3 приведена на рис. 6.5.

Блок-схема для примера 3


Рис. 6.5.  Блок-схема для примера 3

Код программы (Visual Studio) с оператором for:

// proga29.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	double a[6][8];
	double S, tmp, P;
	int i, j;
	cout<<"Massiv a:"<<endl;
	for(i=0; i<6; i=i+1){
		for(j=0; j<8; j=j+1){
			a[i][j]=3.0*i-5.0*j;
			cout<<setw(5)<<a[i][j];
		}
		cout<<endl;
	}
	S=0;
	for(j=0; j<8; j=j+1){
		S=S+a[1][j];
	}
	cout<<"S="<<S<<endl;
	for(j=0; j<8; j=j+1){
		tmp=a[0][j];
		a[0][j]=a[2][j];
		a[2][j]=tmp;
	}
	for(i=0; i<6; i=i+1){
		for(j=0; j<8; j=j+1){
			cout<<setw(5)<<a[i][j];
		}
		cout<<endl;
	}
	P=1;
	for(i=0; i<2; i=i+1){
		P=P*(a[i][1]-a[i][0]);
	}
	cout<<"P="<<P<<endl;
	return 0;
}
Результат выполнения программы:



Краткие итоги

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

Вопросы

  1. Что такое массив?
  2. Перечислите виды массивов.
  3. Что такое индекс?
  4. Как добиться отображения массива на экране в виде ровной таблицы?

Упражнения

  1. Одномерный массив задать в программе. Найти максимальный из отрицательных элементов и поменять его местами с последним.
  2. Одномерный массив задать с клавиатуры. Найти сумму отрицательных, количество положительных и произведение ненулевых элементов.
  3. Одномерный массив задать числами. Найти среднее арифметическое элементов, удовлетворяющих условию .
  4. Одномерный массив задать по формуле . Найти количество элементов, удовлетворяющих условию , минимальный элемент.
  5. Матрицу задать по формуле . Найти новый одномерный массив из произведений элементов каждой строки матрицы . Найти максимальный элемент среди положительных элементов матрицы . Заменить третий элемент в первой строке матрицы на найденный максимальный элемент.
  6. Матрицу задать по формуле . Найти сумму положительных элементов над главной диагональю матрицы. Найти максимальный элемент среди отрицательных элементов 4-ой строки. Заменить найденный максимальный элемент значением суммы.
  7. Матрицу задать по формуле . Поменять местами первую и последнюю строки матрицы. Подсчитать для элементов каждой строки матрицы по формуле: , где – номер строки.

Лекция 7. Работа с файловыми потоками. Пользовательские функции

Очень часто бывают задачи, в которых неоходимо производить запись в файл или чтение из файла. Например, если программа производит много вычислений, по результатам которых нужно постороить график в MS Excel. Другой пример, когда программа работает с большим набором данных, которые хранятся в файлах.

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

Цель данной лекции – ознакомить студентов с понятиями файлового потока и пользовательской функции; показать, как работать с файлами и создавать свои пользовательские функции.

Занятие 1. Работа с файловыми потоками

Программа С++ может взаимодействовать не только с экраном DOS, но и с файлами. Мы будем рассматривать работу с текстовыми файлами (*.txt) и таблицами MS Excel (*.xls).

К примеру, требуется составить программу для решения дифференциального уравнения. Программа выдаст в качестве ответа набор чисел. Количество чисел может быть любым числом – и 10, и 200. Поэтому разумно в этом случае печатать эти данные не столько на экран DOS, сколько в файл *.xls, а затем в MS Excel строить график. При этом говорят, что программа выводит в файл данные.

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

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

Для работы с файловым потоком необходимо:

  1. подключить библиотеку fstream:
    #include <fstream>
  2. объявить переменную типа файловый поток:
    fstream f;
  3. открыть файл:
    • для записи в файл:
      f.open("1.txt", ios::out);
    • для чтения из файла:
      f.open("1.txt", ios::in);
  4. произвести запись в файл или чтение из файла:
    • для записи в файл:
      f<<"x="<<x;
    • для чтения из файла:
      f>>x;
  5. закрыть файл: f.close();

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

f.open("1.txt", ios::app);

Пример 1. Считать из файла число и показать его на экране.

Решение. Сначала рассмотрим, как выполнить эту задачу в Visual Studio, затем – в Borland C++.

Создадим проект в Visual Studio, назовем его "8.1". При этом генерируется папка с нашим проектом. Открываем папку 8.1\8.1 и создаем текстовый документ, называем его 1.txt, как показано на рис. 7.1.

Создание текстового файла в папке с проектом


Рис. 7.1.  Создание текстового файла в папке с проектом

Открываем файл 1.txt и записываем одно число, например, -3.27, как показано на рис. 7.2.

Исходный текстовый файл для примера 1


Рис. 7.2.  Исходный текстовый файл для примера 1

Сохраняем и закрываем файл. Теперь переходим в приложение Visual Studio и в нашем проекте прописываем код программы.

Код программы для примера 1:

// 8.1.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{ 
	double x;
	fstream f;
	f.open("1.txt", ios::in);
	f>>x;
	f.close();
	cout<<"x="<<x<<endl;
	return 0;
}

Результат выполнения программы:



Чтобы работать с файлами в Borland C++, создадим папку F:/BC/FILES. Эта папка предназначена для хранения файлов, с которыми будет взаимодействовать наша программа. Создаем файл 1.txt в папке F:/BC/FILES, записываем в него число -3.27.

При открытии файла необходимо записать имя файла как FILES/1.txt, чтобы наша программа искала текстовый файл именно в этой папке.

Код программы:

#include <iostream.h>
#include <fstream.h>
int main()
{ 
	double x;
	fstream f;
	f.open("FILES/1.txt", ios::in);
	f>>x;
	f.close();
	cout<<"x="<<x<<endl;
	return 0;
}

Результат выполнения программы:



Пример 2. Составить программу, которая производит запись двух чисел в файлы *.txt и *.xls.

Решение. Обозначим числа как и , зададим . Файлы не будем предварительно создавать, т.к. они возникнут автоматически при запуске нашей программы. Создаем новый проект 8.2 в Visual Studio.

Объявим два файловых потока ftxt – для записи в текстовый файл 1.txt, fxls – для записи в табличный файл 2.xls.

Сделаем так, чтобы в файле 1.txt появилась надпись:

a=7.2 b=-10.89

В файле 2.xls выведем каждый кусочек сообщения в разные ячейки. Для этого следует использовать символ табуляции "\t".

Код программы для примера 2:

// 8.2.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
	double a, b;
	fstream ftxt, fxls;
	a=7.2;
	b=-10.89;
	cout<<"a="<<a<<" b="<<b<<endl;
	ftxt.open("1.txt", ios::out);
	fxls.open("2.xls", ios::out);
	ftxt<<"a="<<a<<" b="<<b;
	fxls<<"a=\t"<<a<<"\tb=\t"<<b;
	ftxt.close();
	fxls.close();
	return 0;
}

Результат выполнения программы:

экран DOS:



текстовый файл 1.txt:



табличный файл 2.xls:



Примечание. Файлы 1.txt и 2.xls создаются в папке с проектом 8.2\8.2, как показано на рис. 7.3.

Созданные программой файлы в папке с проектом


Рис. 7.6.  Созданные программой файлы в папке с проектом

Решим данную задачу в Borland C++.

Код программы:

#include <iostream.h>
#include <fstream.h>
int main()
{
	double a, b;
	fstream ftxt, fxls;
	a=7.2;
	b=-10.89;
	cout<<"a="<<a<<" b="<<b<<endl;
	ftxt.open("FILES/1.txt", ios::out);
	fxls.open("FILES/2.xls", ios::out);
	ftxt<<"a="<<a<<" b="<<b;
	fxls<<"a=\t"<<a<<"\tb=\t"<<b;
	ftxt.close();
	fxls.close();
	return 0;
}

Результат выполнения программы:

экран DOS:



текстовый файл 1.txt:



табличный файл 2.xls:



Примечание. Т.к. в примере 2 мы задали имя текстового файла 1.txt так же, как в примере 1, то после выполнения программы примера 2 в папке FILES будет находиться два файла. Файл 1.txt запишется заново. При этом потеряется число -3.27, которое мы печатали для примера 1.

В следующих примерах будем приводить коды программ в среде Visual Studio.

Пример 3. Построить таблицу значений функции при с шагом 0,1.

Решение. Данный пример решается с помощью циклического алгоритма. Будем использовать цикл for. Построим таблицу значений функции на экране, а также в файле 1.xls и построим график в MS Excel.

Блок-схема:



Код программы:

// 8.3.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
	double x, y;
	fstream f;
	f.open("1.xls", ios::out);
	cout<<setw(10)<<"x"<<setw(10)<<"y"<<endl;
	f<<"x"<<"\t"<<"y"<<endl;
	for(x=0; x<=2; x=x+0.1){
		y=sin(x);
		cout<<setw(10)<<x<<setw(10)<<y<<endl;
		f<<x<<"\t"<<y<<endl;
	}
	f.close();
	return 0;
}

Результат выполнения программы:

экран DOS:



табличный файл 1.xls:



Файл 1.xls с построенным графиком:



Пример 4. В матрице вычислить сумму положительных элементов, произведение элементов на главной диагонали, количество элементов, больших 2.

Решение. Матрица а является двумерным массивом, состоящим из пяти строк и пяти столбцов. Проинициализируем массив по формуле . Массив и все результаты вычислений будем выводить в файл 1.xls.

Блок-схема:



Код программы:

// 8.4.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
	double a[5][5], s, p;
	int i, j, k;
	fstream f;
	f.open("1.xls", ios::out);
	cout<<"matrix:"<<endl;
	f<<"матрица:"<<endl;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			a[i][j]=7.0*sin(2.3*i*j);
			cout<<setw(10)<<a[i][j];
			f<<'\t'<<a[i][j];
		}
		cout<<endl;
		f<<endl;	
	}
	s=0;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			if(a[i][j]>0){
				s=s+a[i][j];
			}
		}
	}
	cout<<"s="<<s<<endl;
	f<<"Сумма положительных=\t"<<s<<endl;
	p=1;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			if(i==j){
				p=p*a[i][j];
			}
		}
	}
	cout<<"p="<<p<<endl;
	f<<"Произв. на гл. диаг.=\t"<<p<<endl;
	k=0;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			if(a[i][j]>2){
				k=k+1;
			}
		}
	}
	cout<<"k="<<k<<endl;
	f<<"Количество элем.>2 =\t"<<k<<endl;
	f.close();
	return 0;
}

Результат выполнения программы:

экран DOS:



табличный файл 1.xls:



Примечание. Если данный код запустить в программе Borland C++, то русский текст следует заменить латиницей.

Занятие 2. Пользовательские функции

Ранее в программах мы использовали функции из разных библиотек, например, из библиотеки <math.h> или setw(10) из библиотеки <iomanip>. Что общего во всех функциях? Все функции представляют собой некий шаблон, по которому вычисляется значение какой-то функции или выполняется набор каких-то действий. В языке С++ есть возможность создавать свои функции, не относящиеся к библиотекам. Такие функции называются пользовательскими функциями.

Для того, чтобы создать и использовать свою пользовательскую функцию в программе, необходимо:

  1. объявить пользовательскую функцию:
    тип_данных имя_функции (список параметров);
    здесь тип_данных – это возвращаемый тип данных функции, который определяется ответом функции (выходные данные), имя функции – любое имя (по аналогии с именем переменной), список параметров – это то, с чем наша функция будет работать (входные данные);
  2. описать пользовательскую функцию;
  3. вызвать пользовательскую функцию.

Объявление пользовательской фукнции должно быть обязательно до функции main(), описание может быть вместе с объявлением, а может быть после функции main(). Вызов пользовательской функции может быть внутри функции main() или внутри другой пользовательской функции.

Первый вариант описания пользовательской функции – до функции main() представлен на рис. 7.4.

Описание пользовательской функции до функции main()


Рис. 7.4.  Описание пользовательской функции до функции main()

Второй вариант описания пользовательской функции – после функции main() представлен на рис. 7.5.

Описание пользовательской функции после функции main()


Рис. 7.5.  Описание пользовательской функции после функции main()

Конечно, приведенные выше варианты не заработают, т.к. они показывают общую структуру записи программ. В наших примерах всегда будем использовать первый вариант.

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

Принцип работы пользовательской функции


Рис. 7.6.  Принцип работы пользовательской функции

Например, для известной нам функции из библиотеки <math.h>, входными данными является один параметр – вещественное число , сам аппарат представляет собой процесс вычисления синуса от , результатом является полученное значение синуса. Результат является вещественным числом, которое задается ключевым словом double. Поэтому можно было бы представить объявление и описание функции следующим образом:

double sin(double x){
double res;
res=...; // вычисление синуса по сложной математической формуле
return res;  // ответ, результат
}

Здесь внутри функции объявлена локальная переменная double res, в которую будет насчитываться ответ (res – result – результат). Данная переменная будет видна только внутри пользовательской функции. Переменная res – это, своего рода, временная переменная для расчета синуса. Строка return res; выдает в ответ вычисленное значение синуса.

Вызов функции внутри функции main() выглядит следующим образом:

z=sin(1.5);

Примечание. Хотелось бы обратить внимание на разницу между списком параметров при объявлении функции и список аргументов при вызове функции. Объявление, описание и список формальных параметров составляют весь шаблон. Здесь параметры представляют собой некие абстрактные параметры, которые пока нельзя "пощупать". А вот когда идет вызов функции, абстрактные параметры приобретают вполне реальные формы и становятся аргументами функции, конкретными числами. В программе это отражается следущим образом. Объявление и описание функции делается один раз:

double function(double a, double b){...}

Вызовов функции может быть сколько угодно:

int main(){
double x, y, z1, z2, z3;
x=10;
y=-0.3;
z1=function(x,y); // первый вариант вызова
z2=function(1.8, y); // второй вариант вызова
z3=function(1.8, 0); // третий вариант вызова
return 0;
}

Рассмотрим несколько примеров по созданию пользовательских функций.

Пример 1. Требуется создать пользовательскую функцию для вычисления квадрата вещественного числа.

Решение. Составим схему работы нашей пользовательской функции в общем виде на рис. 7.7.

Схема в общем виде для примера 1


Рис. 7.7.  Схема в общем виде для примера 1

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

Объявление и описание функции kv:

double kv(double x){
double res;
res=x*x;
return res;
}

Код программы и результат выполнения программы:



Пример 2. Вычислить таблицу "" значений функции при с шагом 1.

Решение. Сделаем пользовательскую функцию для вычисления значения функции . Возвращаемый тип – double, т.к. ответом является вещественное число. Параметр один, double x. В описании пользовательской функции будет вычисление функции по разветвляющемуся алгоритму. В функции main() реализуем циклический алгоритм для вывода таблицы значений функции.

Код программы:

// test.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
double fz(double x){
	double res;
	if(x<1){
		res=x+3.0;
	}
	else {
		res=4.0*x;
	}
	return res;
}
int main(){
	double x, z;
	cout<<setw(10)<<"x"<<setw(10)<<"z"<<endl;
	for(x=-1; x<=2; x=x+1){
		z=fz(x);
		cout<<setw(10)<<x<<setw(10)<<z<<endl;
	}
return 0;
}

Результат выполнения программы:



Пример 3. Вычислить таблицу "" значений функции при с шагом 1, с шагом 5 .

Решение. Сделаем пользовательскую функцию для вычисления значения функции . Возвращаемый тип – double, т.к. ответом является вещественное число. Параметров два, double x, double y. В описании пользовательской функции будет вычисление функции по разветвляющемуся алгоритму. В функции main() реализуем вложенные циклы для вывода таблицы значений функции.

Код программы:

// test.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
double fz(double x, double y){
	double res;
	if(x*y<1){
		res=x+y;
	}
	else {
		res=x-y;
	}
	return res;
}
int main(){
	double x, y, z;
	cout<<setw(10)<<"x"<<setw(10)<<"y"<<setw(10)<<"z"<<endl;
	for(x=-1; x<=0.5; x=x+1){
		for(y=5; y<=15; y=y+5){
			z=fz(x, y);
			cout<<setw(10)<<x<<setw(10)<<y<<setw(10)<<z<<endl;
		}
	}
	return 0;
}

Результат выполнения программы:



Пример 4. Вычислить таблицу значений функции при с шагом 1.

Решение. Сделаем пользовательскую функцию для вычисления значения функции . Возвращаемый тип – double, т.к. ответом является вещественное число. Параметр один, int n. В описании пользовательской функции будет вычисление функции по циклическому алгоритму. В функции main() реализуем цикл по для вывода таблицы значений функции.

Код программы:

// test.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
double fz(int n){
	double res;
	int i;
	res=0;
	for(i=1; i<=n; i=i+1){
		res=res+1.0/i;
	}
	return res;
}
int main(){
	int n;
	double z;
	cout<<setw(10)<<"n"<<setw(10)<<"z"<<endl;
	for(n=1; n<=10; n=n+1){
		z=fz(n);
		cout<<setw(10)<<n<<setw(10)<<z<<endl;
	}
	return 0;
}

Результат выполнения программы:



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

Решение. Пользовательскую функцию назовем print_mass. В качестве параметра будет сам массив, например, double х[5][5]. Результатом пользовательской функции является вывод массива на экран, поэтому никакого числа в ответе не будет. Следовательно, возвращаемый тип на этот раз будет void, что означает "пустой". В описании пользовательской функции организуем вывод двумерного массива во вложенном цикле. В функции main() инициализируем два массива и вызовем функцию print_mass два раза.

Код программы:

// test.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
void print_mass(double x[5][5]){
	int i, j;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			cout<<setw(10)<<x[i][j];
		}
	cout<<endl;
	}
}
int main(){
	double A[5][5], B[5][5];
	int i,j;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			A[i][j]=2.3*i+j;
			B[i][j]=i-1.5*j;
		}
	}
	cout<<"massiv A:"<<endl;
	print_mass(A);
	cout<<"massiv B:"<<endl;
	print_mass(B);
	return 0;
}

Результат выполнения программы:



Пример 6. Массив задан по формуле , массив по формуле . Вычислить сумму положительных элементов массивов.

Решение. Создадим пользовательскую функцию для вычисления суммы положительных элементов массива, назовем ее sum_pol. В качестве параметра будет формальный массив . В функции main() проинициализируем массивы и , затем два раза вызовем функцию sum_pol.

Код программы:

// test.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
double sum_pol(double x[5][5]){
	int i, j;
	double s;
	s=0;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			if(x[i][j]>0){ s=s+x[i][j];}
		}
	}
	return s;
}
int main(){
	double A[5][5], B[5][5], sa, sb;
	int i,j;
	for(i=0; i<5; i=i+1){
		for(j=0; j<5; j=j+1){
			A[i][j]=0.3*i+j;
			B[i][j]=i-1.5*j;
		}
	}
	sa=sum_pol(A);
	cout<<"s A>0 = "<<sa<<endl;
	sb=sum_pol(B);
	cout<<"s B>0 = "<<sb<<endl;
	return 0;
}

Результат выполнения программы:



Краткие итоги

Чтобы работать с файлами, необходимо использовать переменную типа fstream. Рассмотрены случаи вывода в файл и чтения из файла.

Вопросы

  1. Что такое файловый поток?
  2. Что необходимо сделать, чтобы использовать в программе файловый поток?
  3. Как сделать разделение по ячейкам при записи в файл *.xls?
  4. Что такое пользовательская функция?
  5. Что такое объявление, описание, вызов пользовательской функции?

Упражнения

  1. Составьте программу, которая создаст следующие файлы:



  2. Составьте блок-схему и программу для построения таблицы значений функции при с шагом 0 с шагом 0,8. Таблицы вывести на экран, в файлы *.txt, *.xls.
  3. Для массива найти минимальный элемент, максимальный элемент; найденные минимальный и максимальный элементы поменять местами. Исходный массив считать из файла. Исходный массив, результаты вычислений и измененный массив вывести на экран и в файл *.xls.
  4. Составить блок-схему и программу для вычисления суммы 20 чисел из файла. Указание: использовать циклический алгоритм, не использовать массивы.
  5. В программе для задачи 3 создать пользовательские функции для вычисления минимального и максимального элементов.
  6. Массив считать из файла. Вывести массив на экран. Поменять местами первый и последний элементы. Измененный массив вывести на экран. Указание: для вывода массива на экран создать пользовательскую функцию.

Дополнения


Литература