basic-c/main.tex

173 lines
14 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\documentclass[a5paper,twoside]{article}
\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}
\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}}). Операционная система ищет именно эту функцию, когда получает команду на выполнение программы.
\frm{Названия функций в рамках одной программы не должны повторяться и не должны начинаться с цифр или спецсимволов, также, как и названия переменных (\hyperref[text:naming]{\ref{text:naming}}) никаких других ограничений на название функций не накладывается.}
Конструкция в круглых скобках \code{(int argc, char *argv[])} - это \textit{аргументы функции}. Аргументы функции - это такие переменные, которые создаются при вызове функции и существуют только внутри неё. С их помощью можно передать в функцию какие-то параметры и исходные данные для работы. Аргументы пишутся в круглых скобках сразу после названия функции. В случае если функция не принимает аргументов необходимо поставить после названия пустые круглые скобки. Весь код, содержащийся в фигурных скобках после аргументов функции называется \textit{телом функции}. Это те операторы и команды, которые будут последовательно выполнены при вызове функции. В теле функции мы можем \textbf{вызывать} другие функции, но никогда не можем создавать в теле функции другие функции. Никаких других ограничений на написание тела функции язык не накладывает.
\begin{verbatim}
ТипВозвращаемогоЗначения Имя (СписокАргументов)
{
ТелоФункции
return ВозвращаемоеЗначение;
}
\end{verbatim}
% \begin{lstlisting}[language=C,style=CCodeStyle]
% void somefunction() { // <-- это функция
% // полезные действия
% }
% int main (int argc, const char* argv[]) {
% // больше полезных действий
% somefunction(); // <-- это вызов функции
% return 0;
% }
% \end{lstlisting}
Функции принято разделять на проверяющие, считающие и выводящие, и каждая из вышеописанных функций не должна нести дополнительной нагрузки. То есть, функция не должна знать откуда в программе появились её аргументы, и где будет использован результат её работы. Для примера опишем функцию суммирующую два числа. в качестве аргументов она будет принимать целые числа и возвращать целочисленный результат. Обратите внимание что функция не знает откуда взялись эти числа, мы можем их считать с консоли, можем задать в виде констант или получить в результате работы какой то другой функции.
Внутри функции main мы вызываем нашу функцию sum суммирующую два числа и передаем в качестве аргументов эти числа.
% int sum(int x, int y) {
% int result = x + y;
% return result;
% }
% 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.
% printf(“HelloWorld!”);
% printf(“%d”, sum(50, a));
% Теперь мы без проблем можем оформить уже существующие у нас программы в виде функций. Например, оформим в виде функций программу проверки простоты числа.
% Для этого опишем функцию которая возвращает целое число, назовем ее isPrime, в качестве аргумента она принимает целое число, назовем его number. Найдем из предыдущих занятий программу определения простоты числа и скопируем в тело функции.
% Внесем небольшие правки, уберем вывод т.к. это проверяющая функция, вывод оставим для основной части. И допишем если делителей 2 то число простое, возвращаем 1. Если же делителей больше число не простое, возвращаем 0.
% Такой вывод можно записать и другим способом, return (d == 2) это выражение в случае истины вернет 1 в случае лжи 0.
% Можно воспользоваться тернарным оператором, т.е. написать
% return (d == 2) ? 1 : 0 если условие в скобках истинно вернется 1, ложно 0.;
% Выйти из функции мы можем на любом этапе ее выполнения, например если делителей уже 3, то мы можем вернуть 0.
% 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;
% return (d == 2)
% //return (d == 2) ? 1 : 0;
% }
% if (d == 3) return 0;
% Немного подправим вывод, внесем в него вызов функции isPrime и объявим переменную int num, которую будем передавать в качестве аргумента в функцию isPrime.
% Запустим нашу программу и убедимся что все работает число 71 действительно является простым.
% Теперь мы можем написать программы любой сложности, содержащие функции isPrime. sum. О том, что мы работаем с консолью, в нашем случае должна знать только функция main, поэтому ввод значений и вывод на экран мы оставим в ней, а подсчёты значений положим в функции.
% int main (int argc, const char* argv[]) {
% int a;
% scanf(“%d, &a”);
% printf(“%d”, sum(50, a));
% int num = 71;
% printf(“Введенное число %d %s является простым \n”, number, isPrime(num) ? “” : “не”);
% return 0;
% }
% Пришло время поговорить про прототипы.
% Зачастую возникают ситуации, когда функция не описана до точки входа в программу, или вовсе лежит в другом файле. В этом случае мы должны сообщить компилятору, что такую функцию придётся дополнительно поискать. Для этого необходимо указать всю информацию о функции, кроме её тела. Такой оператор называется прототип функции.
% Опишем прототип функции isPrime, описав сигнатуру этой функции.
% int isPrime(int number);
% И пара слов о заголовочных файлах. Заголовочные файлы это мощный инструмент модульной разработки. Мы уже неоднократно видели подключение заголовочного файла stdio.h, давайте посмотрим, что же скрывает и как именно работает эта строка. Обнаружив данный файл на диске мы видим, что в нём содержатся другие подключения библиотек, директивы препроцессора (о которых более подробно мы будем говорить на следующих занятиях) и прототипы функций (например, так часто используемой нами
% printf()). (Где-то вот здесь… на 259 строке)
% // Здесь показ содержимого stdio.h
\end{document}