3

Основы программирования на C++: функции, шаблоны

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

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

Здравствуйте, мои маленькие любители программирования!

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

Основные концепции функций

  1. Что такое функция? Функция — это блок кода, который выполняет определенную задачу. Она может принимать входные данные (аргументы), обрабатывать их и возвращать результат. В языке C++ каждая программа начинается с выполнения функции main(), которая является точкой входа в программу.

    int main() {

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

    return 0;

    }

    • int перед main() указывает, что функция возвращает целое число.

    • return 0; означает успешное завершение программы.

  2. Создание простой функции

    Рассмотрим пример функции, которая складывает два числа:

    int Sum(int a, int b) {

    return a + b;

    }

    • int перед именем функции указывает, что функция возвращает значение типа int.

    • Sum — это имя функции.

    • (int a, int b) — это параметры функции, то есть значения, которые передаются в функцию при её вызове.

    Пример использования функции Sum:

    int main() {

    int x = 17, y = 42;

    int z = Sum(x, y); // Вызов функции Sum

    std::cout << "Сумма: " << z << "\n"; // Выведет 59

    }

  3. Функции без возвращаемого значения

    Если функция не должна возвращать результат, её можно объявить как void. Это означает, что функция просто выполняет какие-то действия, но не возвращает никаких данных.

    void DoSomething(double d, char c) {

    std::cout << "Число: " << d << ", Символ: " << c << "\n";

    }

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

    int main() {

    DoSomething(3.14, '@'); // Выведет: Число: 3.14, Символ: @

    }

  4. Рекурсивные функции

    Рекурсия — это когда функция вызывает саму себя. Это полезно для решения задач, которые могут быть разделены на подзадачи того же типа. Например, вычисление факториала числа:

    #include <cstdint> // Для uint64_t

    std::uint64_t Factorial(std::uint64_t n) {

    if (n == 0) {

    return 1; // Базовый случай

    }

    return n * Factorial(n - 1); // Рекурсивный вызов

    }

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

    int main() {

    std::cout << "Факториал 5: " << Factorial(5) << "\n"; // Выведет 120

    }

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


Аргументы функций

  1. Передача аргументов по значению

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

    void f(int x, int y) {

    x = 10; // Изменение x не повлияет на внешнюю переменную

    y = 20; // Изменение y не повлияет на внешнюю переменную

    }

    int main() {

    int a = 1, b = 2;

    f(a, b);

    std::cout << "a: " << a << ", b: " << b << "\n"; // Выведет: a: 1, b: 2

    }

  2. Передача аргументов по ссылке

    Чтобы изменять исходные переменные внутри функции, используются ссылки (&). Это позволяет функции работать с оригинальными переменными, а не с их копиями.

    void Swap(int& x, int& y) { // Передача по ссылке

    int temp = x;

    x = y;

    y = temp;

    }

    int main() {

    int a = 1, b = 2;

    Swap(a, b);

    std::cout << "a: " << a << ", b: " << b << "\n"; // Выведет: a: 2, b: 1

    }

  3. Константные ссылки

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

    void PrintVector(const std::vector<int>& vec) {

    for (int num : vec) {

    std::cout << num << " ";

    }

    std::cout << "\n";

    }

    int main() {

    std::vector<int> numbers = {1, 2, 3, 4, 5};

    PrintVector(numbers); // Выведет: 1 2 3 4 5

    }


Возвращаемые значения функций

  1. Возврат простых типов

    Функция может возвращать любые типы данных, такие как int, double, char и т.д. Например:

    double Divide(double a, double b) {

    return a / b;

    }

    int main() {

    double result = Divide(10.0, 2.0);

    std::cout << "Результат деления: " << result << "\n"; // Выведет: 5.0

    }

  2. Возврат сложных типов

    Возврат сложных типов данных (например, векторов или строк) также возможен. Компилятор автоматически оптимизирует процесс копирования таких объектов.

    std::string Concatenate(const std::vector<std::string>& parts) {

    std::string result;

    for (const auto& part : parts) {

    result += part;

    }

    return result;

    }

    int main() {

    std::vector<std::string> words = {"Hello", " ", "World", "!"};

    std::cout << Concatenate(words) << "\n"; // Выведет: Hello World!

    }

  3. Опасность возврата ссылок на локальные переменные

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

    int& GetLocalVariable() {

    int x = 10;

    return x; // Ошибка! x будет уничтожен после завершения функции

    }


Лямбда-функции

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

#include <algorithm>

#include <vector>

int main() {

std::vector<int> numbers = {5, 2, 8, 1, 9};

// Сортировка в обратном порядке с помощью лямбда-функции

std::sort(numbers.begin(), numbers.end(), [](int a, int b) {

return a > b; // Сравнение в обратном порядке

});

for (int num : numbers) {

std::cout << num << " "; // Выведет: 9 8 5 2 1

}

}


Шаблоны

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

  1. Шаблонные функции

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

    template<typename T>

    T Max(T a, T b) {

    return (a > b) ? a : b;

    }

    int main() {

    std::cout << "Максимум: " << Max(10, 20) << "\n"; // Выведет: 20

    std::cout << "Максимум: " << Max(3.14, 2.71) << "\n"; // Выведет: 3.14

    std::cout << "Максимум: " << Max("apple", "banana") << "\n"; // Выведет: banana

    }

  2. Шаблонные структуры

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

    template<typename T1, typename T2, typename T3>

    struct Triple {

    T1 first;

    T2 second;

    T3 third;

    };

    int main() {

    Triple<int, double, std::string> data = {1, 3.14, "Hello"};

    std::cout << "First: " << data.first << ", Second: " << data.second

    << ", Third: " << data.third << "\n";

    }


Это основные концепции работы с функциями и шаблонами в C++. Теперь вы знаете, как создавать и использовать функции, передавать аргументы, возвращать значения и работать с шаблонами.

Задачи на функции

1. Простые функции

  1. Функция "Приветствие"
    Напишите функцию void Greet(const std::string& name), которая выводит приветствие в формате:
    "Привет, [имя]!".
    Пример:

    Greet("Анна"); // Вывод: Привет, Анна!

  2. Вычисление площади прямоугольника
    Напишите функцию double CalculateRectangleArea(double width, double height), которая принимает ширину и высоту прямоугольника и возвращает его площадь.
    Пример:

    double area = CalculateRectangleArea(5.0, 3.0); // Результат: 15.0

  3. Проверка числа на четность
    Напишите функцию bool IsEven(int number), которая возвращает true, если число четное, и false — если нечетное.
    Пример:

    bool result = IsEven(4); // Результат: true


2. Функции с передачей по ссылке

  1. Увеличение значения на 1
    Напишите функцию void Increment(int& value), которая увеличивает переданное значение на 1.
    Пример:

    int x = 5;

    Increment(x);

    std::cout << x; // Вывод: 6

  2. Обмен значений двух переменных
    Реализуйте функцию void Swap(int& a, int& b), которая меняет значения двух переменных местами.
    Пример:

    int x = 10, y = 20;

    Swap(x, y);

    std::cout << x << " " << y; // Вывод: 20 10


3. Рекурсивные функции

  1. Числа Фибоначчи
    Напишите рекурсивную функцию int Fibonacci(int n), которая возвращает n-е число Фибоначчи.
    Пример:

    int result = Fibonacci(7); // Результат: 13

  2. Степень числа
    Напишите рекурсивную функцию int Power(int base, int exponent), которая возводит число base в степень exponent.
    Пример:

    int result = Power(2, 3); // Результат: 8


Задачи на шаблоны

4. Шаблонные функции

  1. Минимум двух чисел
    Напишите шаблонную функцию T Min(T a, T b), которая возвращает минимальное из двух значений.
    Пример:

    int result1 = Min(10, 20); // Результат: 10

    double result2 = Min(3.14, 2.71); // Результат: 2.71

  2. Сравнение строк
    Напишите шаблонную функцию bool AreEqual(T a, T b), которая возвращает true, если два значения равны, и false — если нет.
    Пример:

    bool result1 = AreEqual(5, 5); // Результат: true

    bool result2 = AreEqual("hello", "world"); // Результат: false

  3. Сумма элементов массива
    Напишите шаблонную функцию T SumArray(const std::vector<T>& arr), которая вычисляет сумму всех элементов вектора.
    Пример:

    std::vector<int> numbers = {1, 2, 3, 4};

    int result = SumArray(numbers); // Результат: 10


5. Шаблонные структуры

  1. Шаблонная структура "Точка"
    Создайте шаблонную структуру Point<T>, которая хранит координаты точки в двумерном пространстве. Добавьте метод void Print(), который выводит координаты точки.
    Пример:

    Point<int> p1 = {3, 4};

    p1.Print(); // Вывод: (3, 4)

  2. Шаблонная структура "Пара"
    Создайте шаблонную структуру Pair<T1, T2>, которая хранит два значения разных типов. Добавьте метод void Print(), который выводит значения пары.
    Пример:

    Pair<int, std::string> pair = {42, "Ответ"};

    pair.Print(); // Вывод: (42, Ответ)


Задачи на лямбда-функции

6. Лямбда-выражения

  1. Фильтрация чисел
    Используя лямбда-функцию, напишите программу, которая фильтрует числа из вектора, оставляя только четные.
    Пример:

    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

    std::vector<int> evenNumbers;

    std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evenNumbers), [](int x) {

    return x % 2 == 0;

    });

    // Результат: evenNumbers = {2, 4, 6}

  2. Сортировка строк по длине
    Используя лямбда-функцию, отсортируйте вектор строк по их длине.
    Пример:

    std::vector<std::string> words = {"apple", "banana", "kiwi"};

    std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) {

    return a.size() < b.size();

    });

    // Результат: words = {"kiwi", "apple", "banana"}


Дополнительные задачи

7. Комбинированные задачи

  1. Калькулятор
    Напишите шаблонную функцию T Calculator(T a, T b, char operation), которая выполняет одну из операций (+, -, *, /) над двумя числами.
    Пример:

    int result = Calculator(10, 5, '+'); // Результат: 15

    double result2 = Calculator(10.0, 2.0, '/'); // Результат: 5.0

  2. Поиск максимального элемента в массиве
    Напишите шаблонную функцию T FindMax(const std::vector<T>& arr), которая возвращает максимальный элемент вектора.
    Пример:

    std::vector<int> numbers = {3, 1, 4, 1, 5, 9};

    int max = FindMax(numbers); // Результат: 9

  3. Подсчет слов в строке
    Напишите функцию int CountWords(const std::string& text), которая подсчитывает количество слов в строке. Слова разделены пробелами.
    Пример:

    int count = CountWords("Hello world!"); // Результат: 2


Эти задачи помогут вам закрепить основные концепции работы с функциями, шаблонами и лямбда-выражениями в C++. Вы можете начать с простых задач и постепенно переходить к более сложным. Удачи!

Лига программистов

2.1K постов11.9K подписчиков

Правила сообщества

- Будьте взаимовежливы, аргументируйте критику

- Приветствуются любые посты по тематике программирования

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