- •Тема 5. Функции Зачем нужны функции?
- •Определение и вызов функции
- •Void say_hello() {
- •Int main() {
- •Int main() {
- •Void drawStars(int n) {
- •Int main() {
- •Int main() {
- •Void printNumbers(int numbers[], int size) {
- •Int main()
- •Int summa(int y) {
- •Int summa_version2(int y) {
- •Int summa(int a, int b) {
- •Int factorial(int n) {
- •Int factorial(int n) {
- •Int factorial(int n) {
- •Int main() {
- •Реализация функций в компактном виде
- •Int indexOf(int element) {
- •Правильное проектирование функций
- •Int main() {
- •Примеры решения задач
- •Void printMark(int mark) {
- •Int main() {
- •Int main() {
- •Int main() {
- •Int main() {
- •Int main() {
Void printNumbers(int numbers[], int size) {
for (int i=0; i<size; i++) {
cout << numbers[i];
}
}
Если же при определении функция тип возвращаемого значения указан отличным от void, то хотя бы один оператор return должен присутствовать; более, все ветки логических конструкций должны содержать оператор return. Например, функция
int max(int m, int n) {
if (m>n) {
return m;
} else {
printf("%d\n", n);
}
}
определена неправильно, поскольку ветка else не возвращает никакого значения, в то время как функция должна возвращать значение типа int.
Вызов логических функций
Некоторые трудности часто бывают связаны с вызовом функций, возвращающих тип логический тип bool, хотя ничего сложного здесь нет. Пример проверки, является ли число простым:
bool isPrime(int n) {
for (int i=2; i<=n-1; i++) {
if (n%i==0) {
return false;
}
}
return true;
}
Int main()
{
//Можно так
isPrime(17) ? cout << "Yes" : cout << "No";
//Или так
for (int i=2; i<100; i++) {
if (isPrime(i)) {
cout << i << endl;
}
}
return 0;
}
Глобальные и локальные переменные
Посмотрите на следующий пример:
int x = 10;
Int summa(int y) {
result = x+y;
return x + y;
}
А теперь еще один:
Int summa_version2(int y) {
int x = 10;
result = x+y;
return result;
}
В чем отличие этих двух фрагментов кода? Нетрудно заметить, что отличие заключается в объявлении переменной x: в первом случает она объявлена до функции, а во втором – после. Во что выльется такая разница?
В первом случае переменная является глобальной, т.е. доступной во всех функциях программы, а во втором – локальной, т.е. доступной только внутри функции, где она объявлена. Константы, заданные при помощи директивы #define являются глобальными.
Как Вы думаете, какой вариант правильный? С точки зрения языка программирования правильны оба варианта, поскольку обе программы успешно откомпилируются и при запуске приведут к одному результату. Но с точки зрения хорошего стиля программирования, который, в конечном счете, приводит к более понятным и легко отлаживаемым программам.
Обратите внимание, что данная запись является неправильной:
summa_version2(4,7);
cout << result;
Функция, как и любая другая конструкция языка Си, делит переменные на глобальные и локальные. Локальными являются те переменные, которые описаны внутри функции и, значит, доступны только внутри этой функции. Например, в следующем фрагменте кода переменная result – локальная:
Int summa(int a, int b) {
int result = a+b;
return result;
}
Понятие локальной переменной относится не только к функциям, но и к другим конструкциям языка. Например, в следующем фрагменте переменная i является локальной для цикла:
for (int i=0; i<10; i++) {
…
}
Переменная, описанная внутри некоторого блока, ограниченного фигурными скобками, является локальной для этого блока:
if (…) {
…
int x;
…
}
Обращение к локальной переменной за пределами блока, где она описана, приведет к ошибке компиляции, однако можно описать переменную с таким же именем за пределами этого блока, и это будет уже другая переменная.
Внимание – частая ошибка!
Определять или объявлять функции внутри других функций нельзя! Вызывать можно, но определять или объявлять – нет. Например, следующая программа ошибочна:
int main() {
//Локальное определение недопустимо!
void say_hello() {
cout << "Hello!" << endl;
cout << "Bonjour!" << endl;
cout << "Привет!" << endl;
}
}
int main() {
//Локальное объявление недопустимо!
void say_hello();
}
Рекурсивные и нерекурсивные функции
Существует важный класс функций, называемых рекурсивными. Функция называется рекурсивной, если она вызывает сама себя. Хотя любую рекурсивную программу можно переписать без использования рекурсии, в ряде случаев рекурсивная версия функции имеет более простой вид, особенно в тех случаях, когда вычисляемое значение или объект, используемый в функции, определяется рекурсивно.
Рассмотрим функцию, вычисляющую факториал. Факториал числа N обозначается через N! и равен произведению 1*2*3*4*…*N; по определению также полагается 0!=1. Очевидная реализация такой функции следующая: