Урок 6. Функции
Привет! После прохождения Урока 5 у тебя должен был получиться следующий код:
#include <iostream>
int main()
{
int a = 1;
int b = 2;
int c = 0;
c = a + b;
std::cout << a << " + " << b << " = " << c << '\n';
c = a - b;
std::cout << a << " - " << b << " = " << c << '\n';
c = a * b;
std::cout << a << " * " << b << " = " << c << '\n';
if (b != 0)
{
c = a / b;
std::cout << a << " / " << b << " = " << c << '\n';
}
else
{
std::cout << "Error! Division by zero is not allowed";
}
c = 1;
for (int i = 0; i < b; ++i)
{
c = c * a;
}
std::cout << a << " ^ " << b << " = " << c << '\n';
}
Обращаю твоё внимание, что при выводе сообщений в консоль необходимо использовать именно английский язык. Не трать своё драгоценное время и даже не пытайся разобраться с выводом русских букв в консоль - в разработке на С++ это абсолютно бесполезный навык.
Я думаю, настало время подумать над архитектурой нашего приложения. Термин архитектуры был позаимствован разработчиками из… архитектуры строений. В контексте разработки архитектурой называется “описание того, из каких частей построено программное приложение, и как эти части взаимодействуют между собой и другими приложениями”. Из каких же частей состоит наше простое приложение? Чтобы ответить на этот вопрос, выполним декомпозицию нашего приложения, т.е. разобьем его на части:
- Ввод данных
int a = 1;
int b = 2;
- Математические вычисления
c = a + b;
c = a - b;
c = a * b;
c = a / b;
for (int i = 0; i < b; ++i)
{
c = c * a;
}
- Вывод в консоль. Представление результата вычислений
std::cout << a << " + " << b << " = " << c << '\n';
std::cout << a << " - " << b << " = " << c << '\n';
std::cout << a << " * " << b << " = " << c << '\n';
std::cout << a << " / " << b << " = " << c << '\n';
std::cout << a << " ^ " << b << " = " << c << '\n';
или ошибок работы программы
std::cout << "Error! Division by zero is not allowed";
В итоге схему работы нашего приложения можно представить в следующем виде:
Ввод данных
Выполнение вычислений
Вывод результатов работы в консоль
Так намного понятнее!
Начнем работу по приведению архитектуры нашего приложения в порядок. А в этом нам помогут функции.
Функции С функциями мы уже бегло познакомились на Уроке 2. Рекомендую тебе освежить его в памяти. Эх, это одна из сложностей изучения С++ - постоянно нужно забегать вперед и знакомиться с конструкциями, до которых ты “еще не дорос”, а потом возвращаться назад, чтобы вспомнить то, что ты забыл.
Попробуем применить уже имеющиеся у нас знания и написать собственные функции для выполнения математических операций. Я буду объяснять принцип создания функции на примере функции сложения.
Итак. Что мы знаем о функциях на текущий момент.
Функция — это именованный блок кода, который мы можем вызвать. При вызове можно передать функции некоторую информацию с помощью аргументов функции, а в ответ получить результат выполнения функции.
Применим эту информацию к операции сложения c = a + b и запишем ТЗ к нашей функции
Имя нашей функции: addition Аргументы функции: a (имеет тип int) и b (имеет тип int) Функция возвращает c (имеет тип int) - результат сложения двух чисел
Напомню, что объявление и определение функции записывается следующим образом:
тип_возврата имя_функции(аргументы_функции)
{
тело функции
}
Запишем код для функции сложения:
int addition(int a, int b)
{
int c = 0;
c = a + b;
return c;
}
Вместо типа возврата я подставил тип переменной c. Дал функции имя addition. В круглых скобках я через запятую перечислил аргументы функции; перед именем каждого аргумента указал его тип. В фигурных скобках я поместил код, который выполняет функция. Функция возвращает результат сложения аргументов функции.
Код функции можно написать проще:
int addition(int a, int b)
{
return a + b;
}
Сначала будет выполнена операция сложения, а затем будет возвращен результат выполненной операции.
По аналогии можно записать код для функций вычитания, умножения, деления и возведения в степень.
Добавим функции в наш проект:
#include <iostream>
int addition(int a, int b)
{
return a + b;
}
int subtraction(int a, int b)
{
return a - b;
}
int multiplication(int a, int b)
{
return a * b;
}
int division(int a, int b)
{
return a / b;
}
int power(int a, int b)
{
int c = 1;
for (int i = 0; i < b; ++i)
{
c = c * a;
}
return c;
}
int main()
{
int a = 1;
int b = 2;
int c = 0;
c = addition(a, b);
std::cout << a << " + " << b << " = " << c << '\n';
c = subtraction(a, b);
std::cout << a << " - " << b << " = " << c << '\n';
c = multiplication(a, b);
std::cout << a << " * " << b << " = " << c << '\n';
if (b != 0)
{
c = division(a, b);
std::cout << a << " / " << b << " = " << c << '\n';
}
else
{
std::cout << "Error! Division by zero is not allowed";
}
c = power(a, b);
std::cout << a << " ^ " << b << " = " << c << '\n';
}
С одной стороны, количество строчек кода возросло, с другой стороны - логика работы программы стала более прозрачной.
Знакомство с типом данных char Обратим внимание на вывод в консоль
std::cout << a << " + " << b << " = " << c << '\n';
std::cout << a << " - " << b << " = " << c << '\n';
std::cout << a << " * " << b << " = " << c << '\n';
std::cout << a << " / " << b << " = " << c << '\n';
std::cout << a << " ^ " << b << " = " << c << '\n';
Эти пять строчек практически идентичны, исключение составляет лишь символ операции. Еще одно из предназначений функций: использование функций помогает уменьшить количество дублирования кода в программе. Давай попытаемся заменить вывод результата расчета в консоль одной функцией. Для этого нам понадобится познакомиться с типом char
char - символьный тип данных С++. char позволяет работать с символами из таблицы ASCII https://www.industrialnets.ru/files/misc/ascii.pdf Сейчас тебе достаточно знать, что, используя тип char, можно хранить символ математической операции: +, -, *, /, ^. Например:
char operation = '+';
Для того, чтобы присвоить переменной char значение, необходимо записать символ в одинарных кавычках.
Напишем функцию вывода в консоль, используя полученные знания:
void printResult(int a, int b, int c, char operation)
{
std::cout << a << ' ' << operation << ' ' << b << " = " << c << '\n';
}
Функция printResult не возвращает никакого значения. В таких случаях необходимо использовать особый тип void - с английского переводится как “пустота”, но в контексте С++ будет правильнее перевести как “отсутствие данных о типе”.
Используем написанную функцию в коде нашего приложения:
#include <iostream>
int addition(int a, int b)
{
return a + b;
}
int subtraction(int a, int b)
{
return a - b;
}
int multiplication(int a, int b)
{
return a * b;
}
int division(int a, int b)
{
return a / b;
}
int power(int a, int b)
{
int c = 1;
for (int i = 0; i < b; ++i)
{
c = c * a;
}
return c;
}
void printResult(int a, int b, int c, char operation)
{
std::cout << a << ' ' << operation << ' ' << b << " = " << c << '\n';
}
int main()
{
int a = 1;
int b = 2;
int c = 0;
c = addition(a, b);
printResult(a, b, c, '+');
c = subtraction(a, b);
printResult(a, b, c, '-');
c = multiplication(a, b);
printResult(a, b, c, '*');
if (b != 0)
{
c = division(a, b);
printResult(a, b, c, '/');
}
else
{
std::cout << "Error! Division by zero is not allowed";
}
c = power(a, b);
printResult(a, b, c, '^');
}
Отлично! Код main стало намного проще читать! Единственный момент, который меня смущает, это следующий код:
if (b != 0)
{
c = division(a, b);
printResult(a, b, c, '/');
}
else
{
std::cout << "Error! Division by zero is not allowed";
}
Проблема этого кода заключается в том, что пользователь функции division должен следить за правильностью работы функции division. Если пользователь забудет проверить b на равенство нулю, произойдет аварийное завершение работы программы. Было бы здорово перенести проверку внутрь функции division. Но как тогда сообщать пользователю о произошедшей проблеме? В этой истории не все так просто, как кажется на первый взгляд. Подробности ты узнаешь в следующем уроке.
На этом на сегодня всё. До встречи на следующем уроке!