C++ Курс

C++: функции

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

Введение: Зачем нужны функции?

Представь, что ты строишь робота. У робота есть разные части: руки, ноги, голова, датчики. Каждая часть делает свою работу. Рука может поднимать предметы, ноги — ходить, датчики — видеть препятствия. Если бы тебе пришлось каждый раз заново объяснять роботу, как поднимать руку, это было бы очень долго и неудобно. Вместо этого ты один раз программируешь команду "поднять руку" и потом просто говоришь: "Сделай это".

В программировании функции работают точно так же. Это готовые блоки кода, которые можно вызывать по имени, когда они нужны. Они помогают:

  • Не повторять код — написал один раз, используй сколько хочешь.
  • Упростить чтение — программа становится как книга с главами.
  • Легко исправлять ошибки — если что-то не так, меняешь только в одном месте.

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

Что такое функция? Аналогия с кухней

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

В C++ функция — это именованный блок кода, который выполняет конкретную задачу. У неё есть:

  • Имя — как название рецепта.
  • Параметры (аргументы) — ингредиенты, которые мы передаём.
  • Возвращаемое значение — готовое блюдо, которое функция отдаёт.

Вот как выглядит простейшая функция:

#include <iostream>
using namespace std;

// Объявляем функцию с именем "sayHello"
void sayHello() {
    cout << "Привет, мир!" << endl;
}

int main() {
    // Вызываем функцию
    sayHello();
    return 0;
}

Здесь void означает, что функция ничего не возвращает (как инструкция "нарезать помидоры" — она просто делает дело). А sayHello() — это вызов.

Синтаксис функции: разбор по косточкам

Чтобы написать свою функцию, нужно знать её структуру. Вот шаблон:

тип_возвращаемого_значения имя_функции(параметры) {
    // тело функции
    return значение; // если тип не void
}

Разберём каждый элемент:

  1. Тип возвращаемого значения — что функция отдаёт: int, double, string, или void (ничего).
  2. Имя функции — как её вызывать. Имена должны быть понятными: calculateSum, printMessage.
  3. Параметры — переменные в скобках, которые функция принимает на вход. Может быть несколько или ни одного.
  4. Тело функции — код в фигурных скобках.
  5. return — возвращает результат (если тип не void).

Пример с возвратом значения:

#include <iostream>
using namespace std;

// Функция складывает два числа и возвращает результат
int add(int a, int b) {
    int sum = a + b;
    return sum; // возвращаем сумму
}

int main() {
    int result = add(5, 3); // вызываем функцию, сохраняем результат
    cout << "Сумма: " << result << endl;
    return 0;
}

Вывод: Сумма: 8

Почему функции — это суперсила? Примеры из жизни

Представь, что ты пишешь игру. В игре нужно много раз проверять, столкнулись ли два объекта. Без функций ты бы писал один и тот же код 100 раз. С функцией — один раз:

bool checkCollision(int x1, int y1, int x2, int y2) {
    // Проверяем, находятся ли объекты рядом
    if (abs(x1 - x2) < 10 && abs(y1 - y2) < 10) {
        return true;
    }
    return false;
}

int main() {
    // Теперь можно вызывать много раз
    if (checkCollision(10, 20, 15, 25)) {
        cout << "Столкновение!" << endl;
    }
    return 0;
}

Или представь калькулятор. Каждая операция — функция:

double multiply(double a, double b) {
    return a * b;
}

double divide(double a, double b) {
    if (b != 0) {
        return a / b;
    } else {
        cout << "Ошибка: деление на ноль!" << endl;
        return 0;
    }
}

Функции делают код модульным — как LEGO: собираешь из маленьких кирпичиков большую программу.

Параметры и аргументы: разница

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

// a и b — это параметры
void printSum(int a, int b) {
    cout << a + b << endl;
}

int main() {
    // 5 и 10 — это аргументы
    printSum(5, 10);
    return 0;
}

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

Возвращаемые значения: как функция отдаёт результат

Функция может не только что-то делать, но и возвращать данные. Например, функция, которая вычисляет площадь прямоугольника:

double rectangleArea(double width, double height) {
    return width * height;
}

int main() {
    double area = rectangleArea(5.0, 3.0);
    cout << "Площадь: " << area << endl;
    return 0;
}

Если функция ничего не возвращает, используем void. Но даже void может использовать return для досрочного выхода:

void checkAge(int age) {
    if (age < 18) {
        cout << "Доступ запрещён" << endl;
        return; // выходим из функции
    }
    cout << "Доступ разрешён" << endl;
}

Область видимости: где живут переменные?

У каждой переменной есть своя "территория" — область видимости. Переменные, объявленные внутри функции, видны только там. Это как комната: вещи в комнате — только для этой комнаты.

void myFunction() {
    int x = 10; // x существует только здесь
    cout << x << endl;
}

int main() {
    // cout << x; // Ошибка! x не видна
    myFunction();
    return 0;
}

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

Перегрузка функций: одно имя, разные задачи

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

// Функция для сложения целых чисел
int add(int a, int b) {
    return a + b;
}

// Функция для сложения вещественных чисел
double add(double a, double b) {
    return a + b;
}

// Функция для сложения трёх чисел
int add(int a, int b, int c) {
    return a + b + c;
}

int main() {
    cout << add(2, 3) << endl;       // вызовет первую
    cout << add(2.5, 3.7) << endl;   // вызовет вторую
    cout << add(1, 2, 3) << endl;    // вызовет третью
    return 0;
}

Это как швейцарский нож: один инструмент, много лезвий.

Практические советы для начинающих

  1. Давай функциям осмысленные имена. calc() — плохо, calculateAverage() — хорошо.
  2. Не делай функции слишком длинными. Если функция занимает больше 20 строк, разбей её на несколько.
  3. Одна функция — одна задача. Функция не должна и печатать, и считать, и сохранять в файл.
  4. Используй комментарии. Даже если код кажется очевидным, через месяц ты можешь забыть, что он делает.
  5. Тестируй каждую функцию отдельно. Напиши маленькую программу, которая вызывает функцию с разными аргументами.

Продвинутый пример: игра "Угадай число" с функциями

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

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

// Функция генерирует случайное число от 1 до 100
int generateRandomNumber() {
    return rand() % 100 + 1;
}

// Функция проверяет догадку пользователя
bool checkGuess(int guess, int secret) {
    if (guess == secret) {
        cout << "Поздравляю! Ты угадал!" << endl;
        return true;
    } else if (guess < secret) {
        cout << "Загаданное число больше." << endl;
    } else {
        cout << "Загаданное число меньше." << endl;
    }
    return false;
}

// Функция запускает игру
void playGame() {
    int secretNumber = generateRandomNumber();
    int guess;
    int attempts = 0;

    cout << "Я загадал число от 1 до 100. Попробуй угадать!" << endl;

    while (true) {
        cout << "Твой вариант: ";
        cin >> guess;
        attempts++;

        if (checkGuess(guess, secretNumber)) {
            cout << "Количество попыток: " << attempts << endl;
            break;
        }
    }
}

int main() {
    srand(time(0)); // инициализируем генератор случайных чисел
    playGame();
    return 0;
}

Видишь, как код стал аккуратным? Каждая функция отвечает за своё, и если нужно что-то поменять (например, диапазон чисел), мы меняем только одну функцию.

Типичные ошибки новичков

  • Забыть вызвать функцию. Если ты её объявил, но не вызвал, код не выполнится.
  • Несоответствие типов. Если функция ожидает int, а ты передаёшь string, будет ошибка.
  • Забыть return. Если функция не void, она обязана вернуть значение. Иначе — неопределённое поведение.
  • Путать параметры и аргументы. Помни: параметры — это "коробки" в определении, аргументы — "вещи", которые кладёшь.
  • Слишком много глобальных переменных. Они делают код запутанным. Лучше передавать данные через параметры.

Как отлаживать функции?

Когда функция не работает, используй cout внутри неё, чтобы увидеть, что происходит:

int mysteryFunction(int x) {
    cout << "Входное значение x: " << x << endl;
    int result = x * 2 + 5;
    cout << "Результат: " << result << endl;
    return result;
}

Или используй пошаговую отладку в среде разработки (IDE) — это как замедленная съёмка: ты видишь каждую строчку.

Заключение: почему функции — это важно?

Функции — это основа любой серьёзной программы. Они помогают:

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

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

Теперь твоя очередь попрактиковаться!

Практические задания

Задание 1: Калькулятор с функциями

Напиши программу, которая запрашивает у пользователя два числа и операцию (+, -, *, /). Используй отдельные функции для каждой операции. Функция должна возвращать результат. Если операция деления на ноль — выведи сообщение об ошибке.

Подсказка: используй switch или if-else в main для выбора функции.

// Пример начала:
double add(double a, double b) { return a + b; }
double subtract(double a, double b) { return a - b; }
// ... остальные функции

Задание 2: Проверка пароля

Напиши функцию bool checkPassword(string password), которая проверяет, что пароль:

  • Не короче 8 символов.
  • Содержит хотя бы одну цифру.
  • Содержит хотя бы одну заглавную букву.

В main дай пользователю 3 попытки ввести правильный пароль. Если все попытки исчерпаны — выведи "Доступ заблокирован".

Подсказка: используй isdigit() и isupper() из <cctype>.

Задание 3: Генератор таблицы умножения

Напиши функцию void printMultiplicationTable(int n), которая выводит таблицу умножения для числа n от 1 до 10. Например, для n=5:

5 x 1 = 5
5 x 2 = 10
...
5 x 10 = 50

В main запроси у пользователя число и вызови функцию. Добавь проверку: если число меньше 1 или больше 100, выведи сообщение об ошибке и заверши программу.

Подсказка: используй цикл for внутри функции.

Удачи! Помни: программирование — это как спорт. Чем больше тренируешься, тем лучше получается. Не бойся ошибаться — на ошибках учатся!