basic-c/main.tex

173 lines
14 KiB
TeX
Raw Normal View History

\documentclass[a5paper,twoside]{article}
2021-08-20 15:57:50 +03:00
\include{formatting}
\title{Очередное введение в\\язык программирования C}
\begin{document}
\maketitle
\thispagestyle{empty}
\newpage
\tableofcontents
\newpage
% 01 intro
\include{sections/01-intro}
% 02 basics
\include{sections/02-basics}
% 03 io
\include{sections/03-io}
% 04 variables
\include{sections/04-variables}
% 05 conditions
\include{sections/05-conditions}
% 06 cycles
\include{sections/06-cycles}
2021-08-20 15:57:50 +03:00
\section{Функции}
Функция - это такая обособленная часть кода, которую можно выполнять любое количество раз. У функций обязательно в таком порядке должны быть описаны: тип возвращаемого значения, название, аргументы и так называемое тело, то есть собственно исполняемый код. Рассмотрим более детально функцию \code{int main (int argc, char *argv[])}: \code{int} - это \textit{тип возвращаемого значения}, то есть на том месте, откуда будет вызвана эта функция, в результате её работы по выполнении оператора \code{return;}, появится некое целое число. Возвращаемые значения могут быть любых типов. В случае же когда функция не должна возвращать результат своей работы, или никакого возвращаемого результата не предполагается, указывается ключевое слово \code{void} (англ. - пустота). То есть на месте вызова функции в результате её выполнения ничего не появится. Оператор \code{return;} обязателен для не-void функций, а в \code{void} функциях может присутствовать или нет, но никогда не содержит возвращаемого значения. \code{main} - это \textit{название функции}. Функция именно с таким названием, написанным с маленькой буквы, всегда является точкой входа в программу (\hyperref[text:main]{\ref{text:main}}). Операционная система ищет именно эту функцию, когда получает команду на выполнение программы.
2021-08-20 18:26:33 +03:00
\frm{Названия функций в рамках одной программы не должны повторяться и не должны начинаться с цифр или спецсимволов, также, как и названия переменных (\hyperref[text:naming]{\ref{text:naming}}) никаких других ограничений на название функций не накладывается.}
2021-08-20 15:57:50 +03:00
Конструкция в круглых скобках \code{(int argc, char *argv[])} - это \textit{аргументы функции}. Аргументы функции - это такие переменные, которые создаются при вызове функции и существуют только внутри неё. С их помощью можно передать в функцию какие-то параметры и исходные данные для работы. Аргументы пишутся в круглых скобках сразу после названия функции. В случае если функция не принимает аргументов необходимо поставить после названия пустые круглые скобки. Весь код, содержащийся в фигурных скобках после аргументов функции называется \textit{телом функции}. Это те операторы и команды, которые будут последовательно выполнены при вызове функции. В теле функции мы можем \textbf{вызывать} другие функции, но никогда не можем создавать в теле функции другие функции. Никаких других ограничений на написание тела функции язык не накладывает.
\begin{verbatim}
ТипВозвращаемогоЗначения Имя (СписокАргументов)
{
ТелоФункции
return ВозвращаемоеЗначение;
}
\end{verbatim}
% \begin{lstlisting}[language=C,style=CCodeStyle]
% void somefunction() { // <-- это функция
% // полезные действия
% }
2021-08-20 15:57:50 +03:00
% int main (int argc, const char* argv[]) {
% // больше полезных действий
% somefunction(); // <-- это вызов функции
% return 0;
% }
% \end{lstlisting}
2021-08-20 15:57:50 +03:00
Функции принято разделять на проверяющие, считающие и выводящие, и каждая из вышеописанных функций не должна нести дополнительной нагрузки. То есть, функция не должна знать откуда в программе появились её аргументы, и где будет использован результат её работы. Для примера опишем функцию суммирующую два числа. в качестве аргументов она будет принимать целые числа и возвращать целочисленный результат. Обратите внимание что функция не знает откуда взялись эти числа, мы можем их считать с консоли, можем задать в виде констант или получить в результате работы какой то другой функции.
Внутри функции main мы вызываем нашу функцию sum суммирующую два числа и передаем в качестве аргументов эти числа.
% int sum(int x, int y) {
% int result = x + y;
% return result;
% }
2021-08-20 15:57:50 +03:00
% int main (int argc, const char* argv[]) {
% sum(50, 60);
% return 0;
% }
% Обратите внимание, что в качестве аргументов мы можем передавать константные значения, а также переменные. Значения переменных мы можем получить например из консоли, либо в результате выполнения какой-нибудь другой функции.
% int main (int argc, const char* argv[]) {
% int a;
% scanf(“%d, &a”);
% sum(50, a);
% return 0;
% }
% Как уже было сказано - аргументы - это переменные, которые хранят в себе некоторые параметры вызова функции. Аргументы позволяют использовать одни и те же функции с разными исходными данными. Приглядимся повнимательнее к хорошо знакомой нам функции printf(). Строка, которую мы пишем в круглых скобках в двойных кавычках это и есть аргумент функции. То есть мы знаем, что функция умеет выводить на экран строки. Как именно - нам нет дела, а какие именно строки - мы указываем в качестве аргумента.
% Функция printf() примечательна еще и тем, что она может принимать в себя нефиксированное количество аргументов. Описание работы таких функций, а также их написание выходит далеко за пределы основ языка, нам важно помнить что мы можем это использовать. В аргументе функции printf() мы можем написать заполнитель соответствующего типа и вызвать нашу функцию sum.
2021-08-20 15:57:50 +03:00
% printf(“HelloWorld!”);
2021-08-20 15:57:50 +03:00
% printf(“%d”, sum(50, a));
2021-08-20 15:57:50 +03:00
% Теперь мы без проблем можем оформить уже существующие у нас программы в виде функций. Например, оформим в виде функций программу проверки простоты числа.
% Для этого опишем функцию которая возвращает целое число, назовем ее isPrime, в качестве аргумента она принимает целое число, назовем его number. Найдем из предыдущих занятий программу определения простоты числа и скопируем в тело функции.
% Внесем небольшие правки, уберем вывод т.к. это проверяющая функция, вывод оставим для основной части. И допишем если делителей 2 то число простое, возвращаем 1. Если же делителей больше число не простое, возвращаем 0.
% Такой вывод можно записать и другим способом, return (d == 2) это выражение в случае истины вернет 1 в случае лжи 0.
% Можно воспользоваться тернарным оператором, т.е. написать
% return (d == 2) ? 1 : 0 если условие в скобках истинно вернется 1, ложно 0.;
% Выйти из функции мы можем на любом этапе ее выполнения, например если делителей уже 3, то мы можем вернуть 0.
2021-08-20 15:57:50 +03:00
% int isPrime(int number){
% int d = 0, i = 1;
% while(i <= number){
% if(number % i++ ==0)
% d++;
% else
% continue;
% if (d == 3) break;
% }
% //if (d == 2) return 1;
% //else return 0;
2021-08-20 15:57:50 +03:00
% return (d == 2)
2021-08-20 15:57:50 +03:00
% //return (d == 2) ? 1 : 0;
2021-08-20 15:57:50 +03:00
% }
2021-08-20 15:57:50 +03:00
% if (d == 3) return 0;
2021-08-20 15:57:50 +03:00
% Немного подправим вывод, внесем в него вызов функции isPrime и объявим переменную int num, которую будем передавать в качестве аргумента в функцию isPrime.
% Запустим нашу программу и убедимся что все работает число 71 действительно является простым.
2021-08-20 15:57:50 +03:00
% Теперь мы можем написать программы любой сложности, содержащие функции isPrime. sum. О том, что мы работаем с консолью, в нашем случае должна знать только функция main, поэтому ввод значений и вывод на экран мы оставим в ней, а подсчёты значений положим в функции.
% int main (int argc, const char* argv[]) {
% int a;
% scanf(“%d, &a”);
% printf(“%d”, sum(50, a));
2021-08-20 15:57:50 +03:00
% int num = 71;
% printf(“Введенное число %d %s является простым \n”, number, isPrime(num) ? “” : “не”);
% return 0;
% }
2021-08-20 15:57:50 +03:00
% Пришло время поговорить про прототипы.
% Зачастую возникают ситуации, когда функция не описана до точки входа в программу, или вовсе лежит в другом файле. В этом случае мы должны сообщить компилятору, что такую функцию придётся дополнительно поискать. Для этого необходимо указать всю информацию о функции, кроме её тела. Такой оператор называется прототип функции.
% Опишем прототип функции isPrime, описав сигнатуру этой функции.
2021-08-20 15:57:50 +03:00
% int isPrime(int number);
% И пара слов о заголовочных файлах. Заголовочные файлы это мощный инструмент модульной разработки. Мы уже неоднократно видели подключение заголовочного файла stdio.h, давайте посмотрим, что же скрывает и как именно работает эта строка. Обнаружив данный файл на диске мы видим, что в нём содержатся другие подключения библиотек, директивы препроцессора (о которых более подробно мы будем говорить на следующих занятиях) и прототипы функций (например, так часто используемой нами
% printf()). (Где-то вот здесь… на 259 строке)
2021-08-20 15:57:50 +03:00
% // Здесь показ содержимого stdio.h
2021-08-20 15:57:50 +03:00
\end{document}