Функции в языке C
Привет! Сегодня мы погрузимся в мир функций — мощного инструмента, который делает код понятным, удобным и профессиональным. Представь: ты пишешь программу для игры, и один и тот же код повторяется раз пять. Копировать? Неудобно! Вот для этого и нужны функции. Готов? Поехали!
Зачем нужны функции?
Когда ты работаешь над большим проектом (будь то программа для обработки фото, бот для Discord или игра), код быстро разрастается. Функции — это как отдельные "мини-программы" внутри основной программы.
✨ Что дают нам функции
- Не повторяться: написал один раз — используй хоть сто раз
- Легче находить ошибки: проблема в одном месте, а не размазана по всему коду
- Делиться кодом: твою функцию может использовать друг в своём проекте
- Думать проще: разбиваешь большую задачу на маленькие понятные кусочки
💡 Важно знать
В языке C все подпрограммы называются функциями. Даже главная программа — это функция main()! Но функции бывают разные: одни возвращают результат, другие просто выполняют действия.
Функции с возвращаемым значением
Функция с возвращаемым значением — это функция, которая вычисляет и возвращает конкретный результат. Это самый распространённый и понятный тип функций в C.
Функция с return — это математическая машина: засунул значения, получил ответ
📐 Общая структура функции
<тип_результата> <имя_функции>(<параметры>) {
// объявление локальных переменных
// вычисления
return <результат>;
}
Разбираем по частям:
- Тип результата — какое значение вернёт функция:
int,double,charи т.д. - Имя — даёшь функции понятное имя (например,
max,sumDigits,isPrime) - Параметры — данные, которые функция получает для работы
return— оператор, который возвращает результат- Фигурные скобки
{}— внутри них все действия функции
Пример 1: Функция максимума
Давай напишем функцию, которая находит максимум из двух чисел. Это классика программирования!
🔢 Функция max
int max(int x, int y) {
if (x > y)
return x;
else
return y;
}
Как использовать?
#include <stdio.h>
int max(int x, int y) {
if (x > y)
return x;
else
return y;
}
int main() {
int a, b, c, d;
scanf("%d %d %d %d", &a, &b, &c, &d);
printf("MAX = %d\n", max(max(a, b), max(c, d)));
return 0;
}
✨ Магия вложенных вызовов
Смотри, как удобно: функцию max можно вкладывать друг в друга! Сначала находим максимум из a и b, потом из c и d, а затем максимум из этих двух результатов. Три строчки кода вместо кучи if-ов!
Пример 2: НОД — алгоритм Евклида
Помнишь алгоритм Евклида из математики? Давай запишем его как функцию для нахождения наибольшего общего делителя двух чисел.
Функция принимает данные, обрабатывает их и возвращает результат
📝 Код функции
int nod(int a, int b) {
while (a != b) {
if (a > b)
a = a - b;
else
b = b - a;
}
return a;
}
🎯 Что здесь происходит?
aиb— числа для НОД- Цикл
whileработает, пока числа не равны - Уменьшаем большее число на меньшее
- Возвращаем результат через
return
🚀 Как вызвать функцию?
int result = nod(36, 15); // result = 3
printf("НОД = %d\n", result);
// или короче:
printf("НОД = %d\n", nod(36, 15));
Пример 3: Последовательность чисел
Задача: пользователь вводит число k, а программа выводит НОД для каждой пары соседних чисел из последовательности от 1 до k.
💻 Полная программа
#include <stdio.h>
int nod(int a, int b) {
while (a != b) {
if (a > b)
a = a - b;
else
b = b - a;
}
return a;
}
int main() {
int i, k, x, y;
printf("Введите k: ");
scanf("%d", &k);
scanf("%d", &x);
for (i = 2; i <= k; i++) {
scanf("%d", &y);
x = nod(x, y); // записываем результат обратно в x
}
printf("НОД = %d\n", x);
return 0;
}
🔑 Ключевая мысль
Функцию nod мы написали один раз, а используем внутри цикла много раз! Вот в чём сила функций — не нужно повторять один и тот же код.
Пример 4: Простые делители
Эта программа выводит все простые делители числа. Функция ppd находит наименьший простой делитель.
📝 Код программы
#include <stdio.h>
int ppd(int n) {
int d = 2;
while (n % d > 0)
d = d + 1;
return d;
}
int main() {
int a, p;
printf("a = ");
scanf("%d", &a);
while (a > 1) {
p = ppd(a);
printf("%d ", p);
a = a / p;
}
printf("\n");
return 0;
}
🔍 Как это работает?
- Вводим число
a(например, 120) - Функция находит наименьший делитель (2)
- Выводим его и делим
aна него - Повторяем, пока число не станет 1
Результат для 120: 2 2 2 3 5
(потому что 120 = 2³ × 3 × 5)
Функции типа void
Иногда нам не нужен результат — мы просто хотим, чтобы функция что-то сделала: вывела текст, нарисовала фигуру, проверила условие. Для таких случаев используется тип void (пустота).
Функции void выполняют действия, но не возвращают результат — как кнопка, которая что-то делает
💡 Определение
Функция типа void — это функция, которая выполняет действия, но не возвращает значение.
📊 Пример: Таблица умножения
void printTable(int n) {
int i;
printf("\nТаблица для %d:\n", n);
for (i = 1; i <= 10; i++) {
printf("%d x %d = %d\n",
n, i, n * i);
}
}
int main() {
int num;
printf("Введите число: ");
scanf("%d", &num);
printTable(num);
return 0;
}
📋 Пример: Меню программы
void showMenu() {
printf("\n===== МЕНЮ =====\n");
printf("1. Найти НОД\n");
printf("2. Найти максимум\n");
printf("3. Простые делители\n");
printf("0. Выход\n");
printf("================\n");
printf("Ваш выбор: ");
}
int main() {
int choice;
showMenu();
scanf("%d", &choice);
// обработка выбора...
return 0;
}
🎯 Обрати внимание
Функция printTable имеет тип void — она ничего не возвращает, просто выводит таблицу на экран. Внутри неё НЕТ оператора return (или он пустой: return;).
Рекурсия — функция вызывает саму себя!
Приготовься к самому интересному! Рекурсия — это когда функция вызывает саму себя. Звучит странно, но работает идеально для задач, где большая проблема разбивается на такие же, но поменьше.
Рекурсия — функция, которая решает задачу, вызывая сама себя для более простых случаев
🐰 История о кроликах Фибоначчи
Помнишь задачу про кроликов из математики? В январе пара новорождённых крольчат, через два месяца они дают потомство, и так каждый месяц. Сколько пар будет в декабре?
Правило последовательности:
f(1) = 1(январь — одна пара)f(2) = 1(февраль — они ещё маленькие)f(3) = 2(март — появился первый приплод)f(n) = f(n-1) + f(n-2)для всех остальных
💻 Рекурсивная функция Фибоначчи
int fib(int n) {
if (n == 1 || n == 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
Полная программа:
#include <stdio.h>
int fib(int n) {
if (n == 1 || n == 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main() {
int i;
printf("Последовательность Фибоначчи:\n");
for (i = 1; i <= 12; i++) {
printf("f(%d) = %d\n", i, fib(i));
}
return 0;
}
🤔 Как это работает?
Ключевая идея рекурсии: функция решает большую задачу, разбивая её на более простые версии этой же задачи, пока не дойдёт до самого простого случая (базового).
Факториал через рекурсию
Факториал числа n (обозначается n!) — это произведение всех чисел от 1 до n. Например: 5! = 1 · 2 · 3 · 4 · 5 = 120
📐 Рекурсивное определение
1! = 1(базовый случай)n! = n · (n-1)!(рекурсивный случай)
Код функции:
long long factorial(int n) {
if (n <= 1)
return 1;
else
return n * factorial(n - 1);
}
🔄 Как работает factorial(5)?
factorial(5)
= 5 * factorial(4)
= 5 * 4 * factorial(3)
= 5 * 4 * 3 * factorial(2)
= 5 * 4 * 3 * 2 * factorial(1)
= 5 * 4 * 3 * 2 * 1
= 120
Функция "спускается" до базового случая (1), а потом "поднимается" обратно, перемножая числа!
Прототипы функций
В C есть одна особенность: компилятор читает код сверху вниз. Если ты вызываешь функцию раньше, чем она определена, компилятор не знает, что это такое!
❌ Проблема
#include <stdio.h>
int main() {
printf("MAX = %d\n", max(5, 8)); // Ошибка!
return 0;
}
int max(int x, int y) {
return (x > y) ? x : y;
}
Компилятор не знает про функцию max в момент её вызова!
✅ Решение 1: Функция ДО main()
#include <stdio.h>
int max(int x, int y) {
return (x > y) ? x : y;
}
int main() {
printf("MAX = %d\n", max(5, 8));
return 0;
}
✅ Решение 2: Прототип
#include <stdio.h>
// Прототип функции
int max(int x, int y);
int main() {
printf("MAX = %d\n", max(5, 8));
return 0;
}
// Определение функции
int max(int x, int y) {
return (x > y) ? x : y;
}
💡 Что такое прототип?
Прототип функции — это как анонс "скоро будет такая функция". Прототипы обычно пишут в начале файла. Это позволяет располагать функции в любом порядке!
Возведение в степень — практика
Напишем функцию для возведения числа в степень — полезный инструмент для многих задач!
🔢 Функция power
double power(double x, int n) {
int i;
double result = 1.0;
for (i = 0; i < n; i++) {
result = result * x;
}
return result;
}
🚀 Пример использования
#include <stdio.h>
double power(double x, int n) {
int i;
double result = 1.0;
for (i = 0; i < n; i++) {
result = result * x;
}
return result;
}
int main() {
double x;
int n;
printf("Введите x и n: ");
scanf("%lf %d", &x, &n);
// Вычисляем s = x^3 + x^5 + x^n
double s = power(x, 3) + power(x, 5) + power(x, n);
printf("Результат: %.2f\n", s);
return 0;
}
📌 Самое главное
Давайте подведём итоги нашего путешествия в мир функций на языке C:
🤔 Проверь себя
Проверьте, как хорошо вы усвоили материал о функциях в C!
1. Зачем вообще нужны функции? Как они упрощают разработку программ?
Представь, что ты пишешь калькулятор с множеством операций — как функции упростят твою жизнь? Подумай о повторяющемся коде, об исправлении ошибок и о читаемости программы.
2. В чём разница между функцией типа void и функцией с return?
Подумай:
- Когда нужна каждая из них?
- Можно ли использовать результат функции void в выражении?
- Приведи примеры из жизни
3. Задачка на смекалку: функция countDigits
Напиши функцию countDigits, которая считает количество цифр в целом числе. Например, для числа 2025 она должна вернуть 4.
int countDigits(int n) {
// твой код здесь
}
Подсказка: используй цикл и деление на 10.
4. Усложняем: функция sumDigits
Напиши функцию sumDigits, которая вычисляет сумму цифр числа. Например, для 2025 результат: 2 + 0 + 2 + 5 = 9.
int sumDigits(int n) {
// твой код здесь
}
5. НОК и НОД: связь двух понятий
Как связаны НОК (наименьшее общее кратное) и НОД (наибольший общий делитель) двух чисел?
Формула: НОК(a, b) = (a · b) / НОД(a, b)
Напиши функцию для вычисления НОК, используя функцию nod:
int nok(int a, int b) {
return (a * b) / nod(a, b);
}
Протестируй её на числах: 36, 54, 18 и 15.
6. Проверка на простоту
Напиши функцию isPrime, которая проверяет, является ли число простым (делится только на 1 и на себя).
Функция должна возвращать 1 (истина), если число простое, и 0 (ложь) — если нет.
int isPrime(int n) {
// твой код здесь
// проверь делители от 2 до n-1
}
7. Факториалы: суммирование
Напиши программу для вычисления выражения:
s = 1! + 2! + 3! + ... + n!
где n! (факториал) = 1 · 2 · 3 · ... · n
Используй функцию factorial из примеров.
8. Степени: вычисление суммы
Напиши программу для вычисления выражения s = x³ + x⁵ + xⁿ, где x и n вводятся с клавиатуры.
Используй функцию power для возведения в степень.
9. Геометрия в коде: расстояние между точками
Напиши функцию, которая вычисляет длину отрезка по координатам его концов (x1, y1) и (x2, y2).
Формула: d = √((x2-x1)² + (y2-y1)²)
#include <math.h>
double distance(double x1, double y1,
double x2, double y2) {
// твой код здесь
// используй функцию sqrt()
}
Затем напиши программу, которая использует эту функцию для вычисления периметра треугольника по координатам его вершин.
10. Задача со звёздочкой ⭐: минимум из трёх
Напиши функцию minOfThree, которая находит минимум из трёх чисел.
Можешь использовать вложенные вызовы функции min (которая находит минимум из двух чисел), по аналогии с примером максимума из четырёх чисел.
int min(int x, int y) {
return (x < y) ? x : y;
}
int minOfThree(int a, int b, int c) {
// используй функцию min
}
11. Что такое прототип функции и зачем он нужен?
Объясни своими словами:
- Почему компилятор C может не знать о функции?
- Как прототип решает эту проблему?
- Где обычно размещают прототипы?
12. Объясни рекурсию простыми словами
Представь, что ты объясняешь младшему брату, что такое рекурсия. Используй пример с числами Фибоначчи или факториалом.
Обязательно упомяни:
- Что такое базовый случай?
- Почему рекурсия не работает бесконечно?
- В чём преимущество рекурсивного подхода?
13. Чем отличаются параметры-значения от параметров-переменных?
Подумай: В нашем материале мы использовали только передачу по значению. Как ты думаешь, почему?
Подсказка: Это проще для понимания на начальном этапе. Позже ты узнаешь об указателях!
🎯 Практические задания
Попробуй применить полученные знания на практике! Эти задания помогут закрепить материал.
✍️ Задание 1: Простая функция
Напиши функцию isEven, которая проверяет, является ли число чётным.
int isEven(int n) {
// вернуть 1, если чётное
// вернуть 0, если нечётное
}
Подсказка: используй оператор остатка от деления %
🔢 Задание 2: Возведение в квадрат
Напиши функцию square, которая возводит число в квадрат.
int square(int x) {
// твой код
}
Используй её для вычисления суммы квадратов чисел от 1 до 10.
📊 Задание 3: Таблица степеней
Напиши программу, которая выводит таблицу степеней числа 2 от 2⁰ до 2¹⁰.
Используй функцию power из примеров или напиши свою.
Ожидаемый вывод:
2^0 = 1
2^1 = 2
2^2 = 4
...
2^10 = 1024
🎲 Задание 4: НОД трёх чисел
Напиши программу для нахождения НОД трёх чисел.
Подсказка: НОД(a, b, c) = НОД(НОД(a, b), c)
Используй функцию nod из примеров.
🔄 Задание 5: Переворот числа
Напиши функцию reverse, которая переворачивает цифры числа.
Пример: reverse(1234) должна вернуть 4321
int reverse(int n) {
// используй цикл и операции % и /
}
⭐ Задание 6: Числа Фибоначчи без рекурсии
Напиши функцию для вычисления n-го числа Фибоначчи БЕЗ использования рекурсии (через цикл).
int fibLoop(int n) {
// используй цикл for
// храни два предыдущих значения
}
Сравни скорость работы с рекурсивной версией для больших n (например, n=40).
💡 Творческое задание
Придумай свой пример! Какую функцию ты бы написал для своего проекта?
🎮 Идеи для вдохновения
Для игры:
- Функция проверки столкновения объектов
- Функция подсчёта очков
- Функция генерации случайного числа в диапазоне
- Функция проверки победы
Для калькулятора:
- Функция вычисления процента от числа
- Функция конвертации температур
- Функция вычисления площади фигур
- Функция решения квадратного уравнения
📝 План описания твоей функции:
- Название: как ты назовёшь свою функцию?
- Что делает: опиши своими словами
- Параметры: какие данные принимает?
- Возвращаемое значение: что она возвращает? (или это void?)
- Пример использования: как бы ты её вызвал?
🔍 Дополнительно: интересные факты
Несколько любопытных фактов о функциях в программировании!
📚 История
Концепция функций (или подпрограмм) появилась ещё в 1940-х годах! Это одна из самых старых и важных идей в программировании.
🚀 Оптимизация
Современные компиляторы могут "встраивать" маленькие функции прямо в код, чтобы программа работала быстрее. Это называется inline-оптимизация.
🌐 Универсальность
Концепция функций есть почти во всех языках программирования: C, Python, JavaScript, Java и многих других!
🎯 Совет профессионала
Хорошее правило: если ты копируешь код больше двух раз — пора сделать из него функцию! Это сэкономит время и упростит поддержку программы.