Compare commits

..

1 Commits

Author SHA1 Message Date
Maria_Grebenyuk 352de43505 02-basics.tex changed 2022-11-10 17:30:16 +01:00
4 changed files with 45 additions and 45 deletions

View File

@ -1,10 +1,10 @@
\section{Введение} %раздел
\subsection{От автора} %подраздел
Приветствую, коллеги! Начиная работу над этим документом, я не ставил целью написать очередной учебник по языку С или поспорить с трудами Кернигана, Ритчи и Страуструпа. Я думаю, что понял, почему программирование кажется таким сложным: не нашлось ни одного материала, написанного понятным и простым языком. В этом документе я постараюсь не повторить этой досадной ошибки именитых авторов.
Приветствую, коллеги! Начиная работу над этим документом я не ставил целью написать очередной учебник по языку С или поспорить с трудами Кернигана, Ритчи и Страуструпа. Я думаю, что понял, почему программирование кажется таким сложным: не нашлось ни одного материала, написанного понятным и простым языком. В этом документе я постараюсь не повторить этой досадной ошибки именитых авторов.
\frm{Брайан Керниган: <<\textbf{Язык C} — инструмент, острый, как бритва: с его помощью можно создать и элегантную программу, и кровавое месиво.>>}
Да, спасибо классикам за предупреждения, постараемся также этой работой не создать кровавое месиво.
Да, спасибо классикам за предупреждения, постараемся, также, этой работой не создать кровавое месиво.
\subsection{Инструментарий}
В этом документе сознательно пропускается подраздел, посвящённый выбору и настройке инструментария, потому что целью документа не является начало очередного раунда борьбы за право какого бы то ни было компилятора и/или среды разработки называться единственно верным даже с точки зрения отдельно взятого автора отдельно взятой книги. Обозначим лишь популярные варианты для основной тройки операционных систем (Windows, Linux, Mac OS X). Компиляторы:
В этом документе сознательно пропускается подраздел, посвящённый выбору и настройке инструментария, потому что целью документа не является начало очередного раунда борьбы за право какого бы то ни было компилятора и/или среды разработки называться единственно верным, даже с точки зрения отдельно взятого автора отдельно взятой книги. Обозначим лишь популярные варианты для основной тройки операционных систем (Windows, Linux, Mac OS X). Компиляторы:
\begin{itemize}
\item clang;
\item GCC/MinGW;
@ -24,4 +24,4 @@
%https://docs.google.com/document/d/15b226AsztngEhyzP6ZPAYnSzSlGkLHVj
%https://docs.google.com/document/d/11PmQYyQIPHl84Fh9dpJ3fwKP_h5f2veu
\subsection{Немного истории}
Первая версия языка С была разработана в 1972 году Деннисом Ритчи для программирования в недавно созданной на тот момент среде UNIX. Язык разрабатывался не государством, а обычными практикующими программистами. В нём сразу были учтены и исправлены все неудобства существовавших на тот момент FORTRAN и PASCAL. Поскольку интерес к языку со временем не пропадал, а технологии развивались, появились редакции языка, такие как С99 (1999 год) С11(2011 год). В языке С есть возможность работать с указателями на физические ячейки оперативной памяти компьютера. Конечно, это небезопасно, но при должной квалификации программиста позволяет получить максимально эффективный код, близкий к языку ассемблера и даже машинным кодам конкретного процессора. С является компилируемым процедурным языком со строгой статической типизацией, что позволяет писать максимально безопасный код и отсеять бОльшую часть ошибок ещё на этапе компиляции проекта. На языке С написано огромное количество программ, библиотек, и даже операционных систем. Какая бы у Вас ни была установлена операционная система, очень вероятно, что она написана на С. На языке С пишут драйверы для периферийного оборудования, программируют контроллеры для космической аппаратуры, пишут высокоскоростные приложения. Помимо этого, сейчас стремительно набирает популярность такое направление, как <<умная техника>> и <<интернет вещей>>. Именно из-за этих трендов язык С за последние пару лет снова поднялся в рейтинге TIOBE на лидирующие места. Какой бы язык программирования вы ни изучали, знание языка С нужно, потому что языки высокого уровня делают много вещей одной командой, а если Вы хотите не просто стать программистом, а быть хорошим программистом - вы должны понимать, что там, внутри, происходит на самом деле. Знание языка С можно сравнить с умением ездить на автомобиле с механической коробкой передач: коробка-автомат резко снижает порог вхождения в участники дорожного движения, но зачастую настолько ухудшает качество управления автомобилем, что это приводит к самым печальным последствиям.
Первая версия языка С была разработана в 1972м году Деннисом Ритчи для программирования в недавно созданной на тот момент среде UNIX. Язык разрабатывался не государством, а обычными практикующими программистами. В нём сразу были учтены и исправлены все неудобства существовавших на тот момент FORTRAN и PASCAL. Поскольку интерес к языку со временем не пропадал, а технологии развивались, появились редакции языка, такие как С99 (1999 год) С11(2011 год). В языке С есть возможность работать с указателями на физические ячейки оперативной памяти компьютера. Конечно, это небезопасно, но при должной квалификации программиста позволяет получить максимально эффективный код, близкий к языку ассемблера и даже машинным кодам конкретного процессора. С является компилируемым процедурным языком со строгой статической типизацией, что позволяет писать максимально безопасный код, и отсеять бОльшую часть ошибок ещё на этапе компиляции проекта. На языке С написано огромное количество программ, библиотек, и даже операционных систем. Какая-бы у Вас ни была установлена операционная система, очень вероятно, что она написана на С. На языке С пишут драйверы для периферийного оборудования, программируют контроллеры для космической аппаратуры, пишут высокоскоростные приложения. Помимо этого, сейчас стремительно набирает популярность такое направление, как <<умная техника>> и <<интернет вещей>>. Именно из-за этих трендов язык С за последние пару лет снова поднялся в рейтинге TIOBE на лидирующие места. Какой бы язык программирования вы ни изучали, знание языка С нужно потому что языки высокого уровня делают много вещей одной командой, а если Вы хотите не просто стать программистом, а быть хорошим программистом - вы должны понимать, что там, внутри, происходит на самом деле. Знание языка С можно сравнить с умением ездить на автомобиле с механической коробкой передач: коробка-автомат резко снижает порог вхождения в участники дорожного движения, но, зачастую настолько ухудшает качество управления автомобилем, что это приводит к самым печальным последствиям.

View File

@ -1,15 +1,15 @@
\section{Основные понятия}
\subsection{Компиляция}
\label{text:naming}
Прежде, чем говорить о языках программирования и о том, что такое компиляция, как она работает и прочих интересных вещах, нам необходимо познакомиться с понятием, которое будет сопровождать весь курс и в целом всю программистскую жизнь - это понятие имени. Имя - это некий символьный идентификатор (переменная, контейнер) для некоторого числа (числом в свою очередь является адрес ячейки памяти, куда записывается значение). Именовать можно как переменные, так и функции. Простейший пример - запись равенства: \code{name = 123456}. Различие между именем и числом задает признак числа, в программах для компьютеров признаком числа является первый символ, имя (идентификатор) не должно начинаться с цифры. Таким образом компиляторы однозначно могут определить, что является именем, а что числом. Это отличие накладывает на программиста очевидное ограничение: невозможность создать идентификаторы, начинающиеся с цифр. Также, чтобы не создавать неоднозначности в поведении программы нельзя, чтобы имена в рамках одной программы повторялись. Общий алгоритм работы со всеми компилируемыми языками, в том числе С++ выглядит следующим образом:
Прежде, чем говорить о языках программирования и о том, что такое компиляция, как она работает и прочих интересных вещах, нам необходимо познакомиться с понятием, которое будет сопровождать весь курс и в целом всю программистскую жизнь - это понятие имени. Имя - это некий символьный идентификатор (переменная, контейнер) для некоторого числа (числом в свою очередь является адрес ячейки памяти, куда записывается значение). Именовать можно как переменные, так и функции. Простейший пример - запись равенства: \code{name = 123456}. Различие между именем и числом задает признак числа: в программах для компьютеров признаком числа является первый символ, так как имя (идентификатор) не должно начинаться с цифры. Таким образом, компиляторы однозначно могут определить, что является именем, а что числом. Это отличие накладывает на программиста очевидное ограничение: невозможность создать идентификаторы, начинающиеся с цифр. Также, чтобы не создавать неоднозначности в поведении программы, нельзя, чтобы имена в рамках одной программы повторялись. Общий алгоритм работы со всеми компилируемыми языками, в том числе С++, выглядит следующим образом:
\begin{enumerate}
\item программист пишет текст программы на каком-либо языке программирования, в нашем случае это С;
\item при помощи программы-транслятора и, зачастую, ассемблера этот текст преобразуется в исполняемые машинные коды, этот процесс, обычно, состоит из нескольких этапов и называется общим словом <<компиляция>>;
\item исполняемые коды запускаются на целевом компьютере (чаще всего, это сервер или персональный компьютер пользователя).
\item при помощи программы-транслятора и зачастую ассемблера этот текст преобразуется в исполняемые машинные коды: этот процесс обычно состоит из нескольких этапов и называется общим словом <<компиляция>>;
\item исполняемые коды запускаются на целевом компьютере (чаще всего это сервер или персональный компьютер пользователя).
\end{enumerate}
Применим этот общий алгоритм для написания первой программы. Предполагается, что на данный момент у Вас установлена либо среда разработки, либо текстовый редактор и компилятор по отдельности, чтобы иметь возможность повторить этот и все последующие примеры самостоятельно.
\paragraph{Первая программа, файл \code{program.c}}
Для написания программы, откроем выбранный текстовый редактор или среду программирования, и напишем следующие строки (важно отличать заглавные и строчные буквы, то есть, например \code{Int} и \code{int} - это разные слова, и первое, написанное с заглавной буквы, будет не понято компилятором):
Для написания программы откроем выбранный текстовый редактор или среду программирования и напишем следующие строки (важно отличать заглавные и строчные буквы, то есть, например \code{Int} и \code{int} - это разные слова, и первое, написанное с заглавной буквы, будет не понято компилятором):
\begin{figure}[h!]
\lstinputlisting[language=C,style=CCodeStyle]{../sources/helloworld.c}
@ -24,7 +24,7 @@
(или) gcc -o program program.c
\end{verbatim}
\end{figure}
Запуск будет отличаться только для Windows (символами доллара и угловой скобки обозначены приглашения unix-терминала и командной строки windows, соответственно):
Запуск будет отличаться только для Windows (символами доллара и угловой скобки обозначены приглашения unix-терминала и командной строки windows соответственно):
\begin{figure}[h!]
\begin{verbatim}
@ -32,21 +32,21 @@ non-windows $ ./program
windows > .\program.exe
\end{verbatim}
\end{figure}
Далее в тексте в целях демонстрации будет использоваться запуск в стиле non-windows, а также, будет опускаться демонстрация этапа компиляции (кроме случаев, когда сам процесс компиляции отличается).
Далее в тексте в целях демонстрации будет использоваться запуск в стиле non-windows, а также будет опускаться демонстрация этапа компиляции (кроме случаев, когда сам процесс компиляции отличается).
\subsection{Шаблон программы}
Как и программы на любом другом языке, программы на языке С имеют ряд обязательных элементов, также называемых шаблоном программы. Рассмотрим эти элементы подробнее на примере только что написанной первой программы (\hyperref[code:firstprogram]{\ref{code:firstprogram}}). Некоторые, незначительные аспекты, будут рассмотрены сразу и полностью, комментарии, например, но некоторые будут рассмотрены поверхностно, поскольку являются масштабными, сложными для понимания фундаментальными механизмами языка, которым будут посвящены целые специальные разделы.
\paragraph{Комментарии} Некоторые среды разработки оставляют в шапке файла комментарии об авторе и дате создания файла. Некоторые команды разработки регламентируют такие комментарии и рекомендуют их написание каждым участником. Комментарий это любой текст, написанный для удобства программиста и игнорируемый компилятором. Комментарии бывают как однострочные, так и многострочные. В редких случаях можно встретить внутристрочные комментарии, но их лучше стараться не использовать, они считаются дурным тоном, поскольку резко снижают читаемость кода.
Как и программы на любом другом языке, программы на языке С имеют ряд обязательных элементов, также называемых шаблоном программы. Рассмотрим эти элементы подробнее на примере только что написанной первой программы (\hyperref[code:firstprogram]{\ref{code:firstprogram}}). Некоторые незначительные аспекты будут рассмотрены сразу и полностью, комментарии, например, но некоторые будут рассмотрены поверхностно, поскольку являются масштабными, сложными для понимания фундаментальными механизмами языка, которым будут посвящены целые специальные разделы.
\paragraph{Комментарии} Некоторые среды разработки оставляют в шапке файла комментарии об авторе и дате создания файла. Некоторые команды разработки регламентируют такие комментарии и рекомендуют их написание каждым участником. Комментарий это любой текст, написанный для удобства программиста и игнорируемый компилятором. Комментарии бывают как однострочные, так и многострочные. В редких случаях можно встретить внутристрочные комментарии, но их лучше стараться не использовать, они считаются дурным тоном, поскольку резко снижают читаемость кода.
\frm{\textbf{Комментарий} - это фрагмент текста программы, который будет проигнорирован компилятором языка.}
Очень старые компиляторы допускали только комментарии в стиле \code{/* xxx */}, сейчас допустим также стиль \code{// xxx}, завершается такой комментарий концом строки (то есть вся оставшаяся строка, после символов \code{//} будет проигнорирована компилятором). Комментарии в коде важны, особенно для описания и пояснения неочевидных моментов, но важно соблюсти баланс и не превратить программу в один сплошной комментарий, иногда прерывающийся на работающий код.
Очень старые компиляторы допускали только комментарии в стиле \code{/* xxx */}, сейчас допустим также стиль \code{// xxx}, завершается такой комментарий концом строки (то есть вся оставшаяся строка после символов \code{//} будет проигнорирована компилятором). Комментарии в коде важны, особенно для описания и пояснения неочевидных моментов, но важно соблюсти баланс и не превратить программу в один сплошной комментарий, иногда прерывающийся на работающий код.
\label{text:directive}
\paragraph{Директивы препроцессора} это такие команды, которые будут выполняться не просто до запуска программы, но даже до компиляции.
\frm{Есть мнение, что С/С++ программисты - это не программисты на языке С/С++, а программисты на языке препроцессора используемых ими компиляторов.}
В директивах препроцессора подключаются внешние заголовочные файлы, и определяются некоторые абсолютные значения проекта. Обратите внимание, что директивы препроцессора это достаточно сложный инструмент, и использовать его, например, только для определения константных значений - не лучшее архитектурное решение. Для нашего проекта нам понадобится директива \code{\#include <stdio.h>} - эта директива подключит библиотеку стандартного ввода вывода в наш проект, что позволит нам "общаться" с пользователем нашей программы, используя терминал операционной системы (командную строку в терминах Windows)
В директивах препроцессора подключаются внешние заголовочные файлы и определяются некоторые абсолютные значения проекта. Обратите внимание, что директивы препроцессора это достаточно сложный инструмент, и использовать его, например, только для определения константных значений - не лучшее архитектурное решение. Для нашего проекта нам понадобится директива \code{\#include <stdio.h>} - эта директива подключит библиотеку стандартного ввода-вывода в наш проект, что позволит нам "общаться" с пользователем нашей программы, используя терминал операционной системы (командную строку в терминах Windows).
\label{text:main}
\paragraph{Функция \code{main()\{\}}} это точка входа в программу. Программа может состоять из огромного числа файлов и функций, но операционная система как-то должна понять, откуда ей начинать исполнение программы. Такой точкой начала исполнения является функция \code{main} которая должна быть написана именно так:
\paragraph{Функция \code{main()\{\}}} это точка входа в программу. Программа может состоять из огромного числа файлов и функций, но операционная система как-то должна понять, откуда ей начинать исполнение программы. Такой точкой начала исполнения является функция \code{main}, которая должна быть написана именно так:
\frm{\centering\code{int main(int argc, char** args)}}
более подробно о функциях, их синтаксисе и аргументах мы поговорим позднее, на данном этапе можно просто запомнить такое (или же упрощённое \code{int main()} описание главной функции любой программы на языке С. Далее в фигурных скобках пишется так называемое <<тело>> программы, то есть именно те операторы, функции и алгоритмы, которые являются программой. По сути, всё наше программирование будет происходить либо в этой функции, либо будет довольно тесно с ней связано.
\paragraph{Возврат из функции \code{return;}} это оператор явно завершающий выполнение функции \code{main} и, соответственно, программы. Все операторы, кроме директив препроцессора, комментариев и описаний тел функций должны заканчиваться точкой с запятой.
более подробно о функциях, их синтаксисе и аргументах мы поговорим позднее, на данном этапе можно просто запомнить такое (или же упрощённое \code{int main()}) описание главной функции любой программы на языке С. Далее в фигурных скобках пишется так называемое <<тело>> программы, то есть именно те операторы, функции и алгоритмы, которые являются программой. По сути, всё наше программирование будет происходить либо в этой функции, либо будет довольно тесно с ней связано.
\paragraph{Возврат из функции \code{return;}} это оператор явно завершающий выполнение функции \code{main} и, соответственно, программы. Все операторы, кроме директив препроцессора, комментариев и описаний тел функций, должны заканчиваться точкой с запятой.
\label{text:simplify}
\frm{\textbf{Внимание!} Далее Вы прочитаете тезис, который является значительным упрощением реальной ситуации. Автор пошёл на такое упрощение по двум причинам: во-первых, поскольку в классическом С дела обстояли именно так, а в современных компьютерах ситуация меняется настолько быстро, что никакой текст не сможет оставаться актуальным, и во-вторых, поскольку целью данного документа не является детальное описание архитектур современных операционных систем.}
Поскольку программа написанная на языке С работает на одном уровне с операционной системой, а не в средах виртуализации, как это происходит в Java, например, она должна сообщить операционной системе, что она отработала нормально. Это делается посредством возврата в качестве результата работы программы кода ноль. В нашем случае, оператор \code{return} сообщает код \code{0}, говорящий об успешности завершения работы программы. Такой возвратный код - исторически сложившаяся договорённость между программистами: ненулевой код означает аварийное завершение программы и сообщает системе, что программа завершена некорректно и необходимо дополнительно и явно освобождать занятые ею ресурсы.
Поскольку программа, написанная на языке С, работает на одном уровне с операционной системой, а не в средах виртуализации, как это происходит в Java, например, она должна сообщить операционной системе, что она отработала нормально. Это делается посредством возврата в качестве результата работы программы кода ноль. В нашем случае, оператор \code{return} сообщает код \code{0}, говорящий об успешности завершения работы программы. Такой возвратный код - исторически сложившаяся договорённость между программистами: ненулевой код означает аварийное завершение программы и сообщает системе, что программа завершена некорректно и необходимо дополнительно и явно освобождать занятые ею ресурсы.

View File

@ -1,7 +1,7 @@
\section{Базовый ввод-вывод}
\subsection{Форматированный вывод}
Общение с пользователем на чистом С происходит через консоль. Для того, чтобы выводить какую-либо информацию для чтения пользователем - используется функция \code{printf();} предназначенная для форматированного вывода некоторого текста в консоль. Функция описана в заголовке \code{stdio.h}, поэтому мы и включили данный заголовок в нашу программу. Какого рода форматирование применяется при выводе строк в консоль? Существуют два основных инструмента придания выводу необходимого вида: экранированные последовательности (escape sequences) и заполнители (placeholders).
\paragraph{Экранированная последовательность} - это буква или символ, написанные после знака обратного слэша (\code{\char`\\}), которые при выполнении программы будут на что-то заменены. Самые часто используемые это:
\paragraph{Экранированная последовательность} это буква или символ, написанные после знака обратного слэша (\code{\char`\\}), которые при выполнении программы будут на что-то заменены. Самые часто используемые это:
\begin{itemize}
\item \code{\char`\\'} - одинарная кавычка;
\item \code{\char`\\"} - двойная кавычка;
@ -18,7 +18,7 @@
\item \code{\char`\\xnn} - произвольное шестнадцатеричное значение;
\item \code{\char`\\unnnn} - произвольное Юникод-значение.
\end{itemize}
Чтобы убедиться, что это правильно работает, выведем еще одну строку (в дополнение к коду со страницы \hyperref[code:firstprogram]{\pageref{code:firstprogram}}) с надписью <<Это новая строка>> на следующую строку нашей консоли. Также добавим к ещё одной строке символ табуляции чтобы увидеть как он работает. И сразу рассмотрим экранированную последовательность \code{\char`\\\char`\\} она делает не что иное, как добавляет символ обратного слэша в наш текст. Аналогичным образом работают и другие символьные экранирования. Это нужно, чтобы компилятор мог отличить, например, символ двойных кавычек в строке, написанной программистом, от символа двойных кавычек, завершающего строку в коде программы. Обратите внимание, что, не поставив в конец строки последовательность \code{\char`\\n}, мы заставим компилятор постоянно писать текст на одной строке, не переходя на новую. И наконец, \code{\char`\\0} сообщает компилятору, что строка закончилась. Даже если у нас есть еще какие-то символы до закрывающих кавычек, компилятор их просто проигнорирует. Добавим в код программы ещё пару строк, таким образом тело функции \code{main} должно принять следующий вид:
Чтобы убедится что это правильно работает выведем еще одну строку (в дополнение к коду со страницы \hyperref[code:firstprogram]{\pageref{code:firstprogram}}) с надписью <<Это новая строка>> на следующую строку нашей консоли. Также добавим к ещё одной строке символ табуляции чтобы увидеть как он работает. И сразу рассмотрим экранированную последовательность \code{\char`\\\char`\\} она делает ни что иное как добавляет символ обратного слэша в наш текст. Аналогичным образом работают и другие символьные экранирования. Это нужно, чтобы компилятор мог отличить, например, символ двойных кавычек в строке, написанной программистом, от символа двойных кавычек, завершающего строку в коде программы. Обратите внимание что не поставив в конец строки последовательность \code{\char`\\n} мы заставим компилятор постоянно писать текст на одной строке, не переходя на новую. И наконец \code{\char`\\0} сообщает компилятору что строка закончилась. Даже если у нас есть еще какие-то символы до закрывающих кавычек компилятор их просто проигнорирует. Добавим в код программы ещё пару строк, таким образом тело функции \code{main} должно принять следующий вид:
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -29,7 +29,7 @@
printf("This is a terminant \0 it ends a string");
\end{lstlisting}
\end{figure}
Запустив программу, мы можем убедиться, что всё работает так, как мы описали в тексте: сначала идёт приветствие миру, на новой строке сообщение о том, что это новая строка, далее на той же строке (ведь мы не переходили на новую) демонстрация пробела и символа табуляции. На последних двух строках происходит демонстрация обратного слэша и терминанта, видно, что остаток строки не был выведен на экран.
Запустив программу мы можем убедиться, что всё работает так, как мы описали в тексте: сначала идёт приветствие миру, на новой строке сообщение о том, что это новая строка, далее на той же строке (ведь мы не переходили на новую) демонстрация пробела и символа табуляции. На последних двух строках происходит демонстрация обратного слэша и терминанта, видно, что остаток строки не был выведен на экран.
\begin{figure}[h!]
\begin{verbatim}
@ -41,7 +41,7 @@ This is terminant
$
\end{verbatim}
\end{figure}
\paragraph{Заполнитель} - это также специальная последовательность, но она говорит компилятору, что на место этой последовательности необходимо вставить некий аргумент, который будет передан после строки, через запятую, при вызове данной функции \code{printf();}. Заполнитель начинается со знака процента и обозначает тип вставляемой переменной.
\paragraph{Заполнитель} это также специальная последовательность, но она говорит компилятору, что на место этой последовательности необходимо вставить некий аргумент, который будет передан после строки, через запятую, при вызове данной функции \code{printf();}. Заполнитель начинается со знака процента и обозначает тип вставляемой переменной.
\begin{itemize}
\item \code{\%\%} - символ процента;
\item \code{\%i (\%d)} - целые числа (integer, decimal);
@ -65,7 +65,7 @@ $
printf("Placeholders are \"%5d%%\" of formatting\n", a);
\end{lstlisting}
\end{figure}
Так первый оператор выведет просто число. Второй это же число, но оставив для его отображения пять пробельных символов (два окажутся заняты разрядами числа 50, и ещё три останутся свободными слева от числа). Третий оператор форматированного вывода впишет число в пять отображаемых символов, но заполнит пустоту нулями (запись с лидирующими нулями, leading zeroes). Четвёртый осуществит вывод числа с плавающей точкой, ограничив дробную часть двумя отображаемыми символами, при этом важно, что не произойдёт математического округления, символы просто не отобразятся, такое отображение часто используется для демонстрации денежных значений в долларах и центах, рублях и копейках, и пр. Последний же оператор выведет на экран надпись, информирующую о том, что заполнители - это 50\% форматирования:
Так первый оператор выведет просто число. Второй это же число, но оставив для его отображения пять пробельных символов (два окажутся заняты разрядами числа 50, и ещё три останутся свободными, слева от числа). Третий оператор форматированного вывода впишет число в пять отображаемых символов, но заполнит пустоту нулями (запись с лидирующими нулями, leading zeroes). Четвёртый осуществит вывод числа с плавающей точкой, ограничив дробную часть двумя отображаемыми символами, при этом важно, что не произойдёт математического округления, символы просто не отобразятся, такое отображение часто используется для демонстрации денежных значений в долларах и центах, рублях и копейках, и пр. Последний же оператор выведет на экран надпись, информирующую о том, что заполнители - это 50\% форматирования:
\begin{figure}[h!]
\begin{verbatim}
@ -80,7 +80,7 @@ $
\end{figure}
Для заполнителей \code{\%d}, \code{\%i}, \code{\%f} часто используются дополнительные параметры, такие как количество знаков после запятой, например, \code{\%.2f} или минимальное количество знаков для отображения целого числа \code{\%5d}. Также в пользу оператора форматированного вывода говорит тот факт, что, например, в С++ стандартный вывод в консоль осуществляется с помощью команды \code{std::cout}, которая не поддерживала форматирование строк вплоть до принятия стандарта С++20.
\subsection{Форматированный ввод}
Поговорив о выводе в консоль, нельзя не сказать о пользовательском вводе данных. Один из способов пользовательского ввода данных в программу - это использование функции \code{scanf();}. Предложим пользователю ввести некоторое число:
Поговорив о выводе в консоль нельзя не сказать о пользовательском вводе данных. Один из способов пользовательского ввода данных в программу - это использование функции \code{scanf();}. Предложим пользователю ввести некоторое число:
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]

View File

@ -2,7 +2,7 @@
\subsection{Условный оператор}
\paragraph{\code{if()}} пожалуй, самый часто используемый в любом языке программирования, в том числе и в языке С оператор. Оператор \code{if()} позволяет программе принять решение о выполнении или невыполнении того или иного действия в зависимости от текущего состояния. В случае, если условие в круглых скобках выполнится, выполнится и последующий код, который чаще всего пишется в фигурных скобках. Если условие в круглых скобках не выполнится, то все операторы внутри идущих следом фигурных скобок будут проигнорированы.
Например, зададим пользователю вопрос, хочет ли он, чтобы его поприветствовали. Для этого опишем переменную \code{char answer}, которая будет хранить ответ пользователя в виде символа, и спросим у пользователя в терминале, хочет ли он, чтобы мы его поприветствовали, выведем на экран строку с приглашением. Далее, при помощи уже знакомой нам функции \code{scanf();} считаем ответ пользователя в переменную, и, в зависимости от пользовательского ввода, программа либо поприветствует пользователя, либо нет, это решение будет принято с помощью оператора \code{if()}.
Например, зададим пользователю вопрос, хочет ли он, чтобы его поприветствовали, для этого опишем переменную \code{char answer}, которая будет хранить ответ пользователя в виде символа и спросим у пользователя в терминале, хочет ли он, чтобы мы его поприветствовали, выведем на экран строку с приглашением. Далее при помощи уже знакомой нам функции \code{scanf();} считаем ответ пользователя в переменную, и, в зависимости от пользовательского ввода, программа либо поприветствует пользователя, либо нет, это решение будет принято с помощью оператора \code{if()}.
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -15,7 +15,7 @@
}
\end{lstlisting}
\end{figure}
\paragraph{\code{else}} Зачастую складываются ситуации, когда нужно выполнить разные наборы действий, в зависимости от результата проверки условия. Для таких случаев используется дополнение к оператору \code{if()} - оператор \code{else}, в котором описывается последовательность действий, выполняемая в случае, если условие в круглых скобках дало ложный результат. Код немного изменится, не будем приводить повторяющиеся части взаимодействия с пользователем, сконцентрируемся на условном операторе:
\paragraph{\code{else}} Зачастую складываются ситуации, когда нужно выполнить разные наборы действий, в зависимости от результата проверки условия. Для таких случаев используется дополнение к оператору \code{if()} - оператор \code{else}, в котором описывается последовательность действий выполняемая в случае если условие в круглых скобках дало ложный результат. Код немного изменится, не будем приводить повторяющиеся части, взаимодействия с пользователем, сконцентрируемся на условном операторе:
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -26,9 +26,9 @@
}
\end{lstlisting}
\end{figure}
Как вы видите, в зависимости от того, что ввел пользователь, мы реализуем ту или иную ветку оператора \code{if}-\code{else}. Конструкция \code{if}-\code{else} является единым оператором выбора, то есть, выполнив код в фигурных скобках после \code{if}, программа не станет выполнять код в \code{else}, и наоборот.
Как вы видите, в зависимости от того что ввел пользователь мы реализуем ту или иную ветку оператора \code{if}-\code{else}. Конструкция \code{if}-\code{else} является единым оператором выбора, то есть выполнив код в фигурных скобках после \code{if} программа не станет выполнять код в \code{else}, и наоборот.
\paragraph{\code{else if()}} Множественный выбор при помощи оператора \code{if} можно осуществить используя конструкцию \code{if}-\code{else if}-\code{else}. Данное усложнение также будет являться единым оператором выбора. Добавим в нашу конструкцию еще одно условие и опишем поведение для ответа <<да>> и ответа <<нет>>. В этом примере оператором \code{else} будет непонимание программы того, что ввел пользователь. Выведем в консоль надпись <<Я не могу понять Ваш ввод>>.
\paragraph{\code{else if()}} Множественный выбор при помощи оператора \code{if} можно осуществить используя конструкцию \code{if}-\code{else if}-\code{else}. Данное усложнение также будет являться единым оператором выбора. Добавим в нашу конструкцию еще одно условие и опишем поведение для ответа <<да>> и ответа <<нет>>. В этом примере оператором \code{else} будет непонимание программы того что ввел пользователь. Выведем в консоль надпись <<Я не могу понять Ваш ввод>>.
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -41,7 +41,7 @@
}
\end{lstlisting}
\end{figure}
Операторов \code{else if} в одном операторе выбора может быть сколько угодно, в отличие от оператора \code{if} и оператора \code{else}, которых не может быть больше одного.
Операторов \code{else if} в одном операторе выбора может быть сколько угодно, в отличие от оператора \code{if} и оператора \code{else} которых не может быть больше одного.
\begin{figure}[h!]
\begin{verbatim}
@ -57,7 +57,7 @@ I can't understand your input
$
\end{verbatim}
\end{figure}
\paragraph{Тернарный оператор.} Для короткой или внутристрочной записи условного оператора, а также для присваивания переменных по условию можно использовать \textbf{тернарный оператор}, также называемый оператором условного перехода и записываемый с помощью следующего синтаксиса: \code{(условие) ? истина : ложь}. Например, создадим три целочисленные переменные \code{а}, \code{b}, \code{c} и зададим двум из них какие-нибудь начальные значения, допустим \code{а = 10} и \code{b = 15}. Поставим себе задачу: присвоить переменной \code{c} наименьшее из значений \code{а} и \code{b}. Если мы будем использовать только что изученный нами оператор \code{if}-\code{else}, у нас должен получиться такой код:
\paragraph{Тернарный оператор.} Для короткой или внутристрочной записи условного оператора, а также для присваивания переменных по условию можно использовать \textbf{тернарный оператор}, также называемый оператором условного перехода и записываемый с помощью следующего синтаксиса: \code{(условие) ? истина : ложь}. Например, создадим три целочисленные переменные \code{а}, \code{b}, \code{c} и зададим двум из них какие-нибудь начальные значения, допустим \code{а = 10} и \code{b = 15}. Поставим себе задачу: присвоить переменной \code{c} наименьшее из значений \code{а} или \code{b}. Если мы будем использовать только что изученный нами оператор \code{if}-\code{else} у нас должен получиться такой код:
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -80,12 +80,12 @@ $
int c = (a > b) ? b : a;
\end{lstlisting}
\end{figure}
которая будет обозначать, что в случае если \code{a > b}, в переменную \code{c} запишется значение {b}, и наоборот, если \code{b > a}, то в переменную \code{c} запишется значение \code{а}. Также тернарный оператор можно использовать для удобного форматированного вывода, например опишем функцию \code{printf();}, которая будет печатать нам строку, и в зависимости от условия, это будет \code{"true"} либо \code{"false"}:
которая будет обозначать, что в случае если \code{a > b}, в переменную \code{c} запишется значение {b}, и наоборот если \code{b > a}, то в переменную \code{c} запишется значение \code{а}. Также тернарный оператор можно использовать для удобного форматированного вывода, например опишем функцию \code{printf();} которая будет печатать нам строку, и в зависимости от условия, это будет \code{"true"} либо \code{"false"}:
\begin{lstlisting}[language=C,style=CCodeStyle]
printf("%s", (1 > 0) ? "true" : "false");
\end{lstlisting}
Проверим, как это работает, и в результате видим true, потому что единица действительно больше нуля.
Проверим как это работает, и в результате видим true, потому что единица действительно больше нуля.
\begin{figure}[h!]
\begin{verbatim}
@ -95,7 +95,7 @@ $
\end{verbatim}
\end{figure}
\paragraph{Вложенные условия и сокращения}
Внутри фигурных скобок конструкций \code{if()} находится код программы, поэтому там могут находиться и другие условные операторы. Условия, расположенные таким образом, называются вложенными. Никаких ограничений на использование вложенных условий в языке С нет. В примере ниже показано, что условия всегда выполняются (единица в круглых скобках будет означать, что условие всегда истинно), а комментариями с многоточием показано, где может располагаться код программы.
Внутри фигурных скобок конструкций \code{if()} находится код программы, поэтому там могут находиться и другие условные операторы. Условия, расположенные таким образом называются вложенными. Никаких ограничений на использование вложенных условий в языке С нет. В примере ниже показано, что условия всегда выполняются (единица в круглых скобках будет означать, что условие всегда истинно), а комментариями с многоточием показано, где может располагаться код программы.
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -128,16 +128,16 @@ $
// single operator
\end{lstlisting}
\end{figure}
При использовании такой записи можно легко допустить ошибку: забыть о необходимости объединения кода фигурными скобками и предполагать, что несколько операторов могут выполниться по условию без фигурных скобок.
При использовании такой записи можно легко допустить ошибку: забыть о необходимости объединения кода фигурными скобками, и предполагать, что несколько операторов могут выполниться по условию без фигурных скобок.
\frm{Часто это заблуждение приводит к трудноуловимым ошибкам в коде, когда программа компилируется, запускается, но работает не так, как следует.}
\subsection{Операции сравнения}
\paragraph{Арифметическое сравнение} это знакомые и привычные нам со школы операторы <<больше>> (\code{>}), <<меньше>> (\code{<}), <<больше или равно>> (\code{>=}), <<меньше или равно>> (\code{<=}), а также в языке С присутствуют в виде отдельных операторов <<проверка на равенство>>, которая записывается в виде двух знаков равенства (\code{==}), и <<проверка на неравенство>>, которая записывается в виде восклицательного знака и символа равенства (\code{!=}). Возвращают истину, когда выполняются соответствующие названиям условия, и ложь, когда условия не выполняются, что очевидно. Единственное исключение, которое было оговорено ранее (\hyperref[text:floats]{\ref{text:floats}}), сравнение разнотипных нецелочисленных значений должно осуществляться через сравнение допустимой дельты этих значений, например:
\paragraph{Арифметическое сравнение} это знакомые и привычные нам со школы операторы <<больше>> (\code{>}), <<меньше>> (\code{<}), <<больше или равно>> (\code{>=}), <<меньше или равно>> (\code{<=}), а также в языке С присутствуют в виде отдельных операторов <<проверка на равенство>>, которая записывается в виде двух знаков равенства (\code{==}), и <<проверка на неравенство>>, которая записывается в виде восклицательного знака и символа равенства (\code{!=}). Возвращают истину, когда выполняются соответствующие названиям условия и ложь, когда условия не выполняются, что очевидно. Единственное исключение, которое было оговорено ранее (\hyperref[text:floats]{\ref{text:floats}}), сравнение разнотипных нецелочисленных значений должно осуществляться через сравнение допустимой дельты этих значений, например:
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
float f = 0.5f;
double d = 0.5;
double diff = (f > d) ? f - d : d - f;
fouble diff = (f > d) ? f - d : d - f;
if (diff < 0.00001) {
// useful code here
}
@ -151,7 +151,7 @@ $
\end{lstlisting}
Некоторые компиляторы выдают ошибку на этапе компиляции, некоторые компилируют такой код, но программа не сможет выполниться и выдаст ошибку \textbf{Segmentation fault}, то есть ошибку доступа к памяти (попытка обратиться к недоступной памяти или попытка обратиться к памяти неподобающим образом). В этой конкретной ситуации, мы попытаемся интерпретировать как строку часть памяти, которая находится по адресу 1, что находится далеко за пределами доступа программы. Это поведение (ошибка компиляции или ошибка времени выполнения) зависит от большого количества факторов, таких как тип операционной системы, тип и версия компилятора, версия используемого стандарта языка.
Отдельного внимания заслуживает применение оператора поразрядного (арифметического) \code{ИСКЛЮЧАЮЩЕГО ИЛИ} в качестве логического. В случае такого применения оператор \code{ИСКЛЮЧАЮЩЕГО ИЛИ} фактически дублирует сравнение на неравенство, это легко объяснить, проведя анализ происходящего с числами при таком сравнении:
Отдельного внимания заслуживает применение оператора поразрядного (арифметического) \code{ИСКЛЮЧАЮЩЕГО ИЛИ} в качестве логического. В случае такого применения оператор \code{ИСКЛЮЧАЮЩЕГО ИЛИ}, фактически, дублирует сравнение на неравенство, это легко объяснить, проведя анализ происходящего с числами при таком сравнении:
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -163,9 +163,9 @@ $
}
\end{lstlisting}
\end{figure}
Данный код внутри фигурных скобок оператора \code{if()} никогда не выполнится, поскольку в С оператор сравнения работает с числами, интерпретируя ноль как ложь, а любое ненулевое значение - как истину, мы наблюдаем, что побитовое \code{ИСКЛЮЧАЮЩЕЕ ИЛИ} - это тоже самое, что проверка на неравенство.
Данный код внутри фигурных скобок оператора \code{if()} никогда не выполнится, поскольку в С оператор сравнения работает с числами, интерпретируя ноль как ложь, а любое ненулевое значение как истину, мы наблюдаем, что побитовое \code{ИСКЛЮЧАЮЩЕЕ ИЛИ} - это тоже самое, что проверка на неравенство.
\begin{itemize}
\item оператор \code{И (\&\&)} возвращает истину, только когда оба операнда истинны;
\item оператор \code{И (\&\&)} возвращает истину только когда оба операнда истинны;
\begin{tabular}{|c|c|c|}
\hline
@ -180,7 +180,7 @@ $
1 & 1 & 1 \\
\hline
\end{tabular}
\item оператор \code{ИЛИ (||)} возвращает истину, когда хотя бы один из операндов истинный;
\item оператор \code{ИЛИ (||)} возвращает истину когда хотя бы один из операндов истинный;
\begin{tabular}{|c|c|c|}
\hline
@ -195,7 +195,7 @@ $
1 & 1 & 1 \\
\hline
\end{tabular}
\item оператор \code{НЕ (!)} возвращает истину, когда операнд ложный;
\item оператор \code{НЕ (!)} возвращает истину когда операнд ложный;
\begin{tabular}{|c|c|}
\hline
@ -208,7 +208,7 @@ $
\end{tabular}
\end{itemize}
Используя логические операторы в программе, мы можем написать логику практически любой сложности. В языке С нет ограничений на использование сложных условий. Сложные условия это такие, где в круглых скобках выполняется более одного сравнения. Сравнения производятся в порядке заранее оговорённого приоритета. В списке ниже указаны операторы в порядке уменьшения их приоритета:
Используя логические операторы в программе мы можем написать логику практически любой сложности. В языке С нет ограничений на использование сложных условий. Сложные условия это такие, где в круглых скобках выполняется более одного сравнения. Сравнения производятся в порядке заранее оговоренного приоритета. В списке ниже указаны операторы в порядке уменьшения их приоритета:
\begin{enumerate}
\item $!$
\item $<, <=, >, >=$
@ -216,7 +216,7 @@ $
\item $\&\&$
\item $||$
\end{enumerate}
Приведём короткий пример: дана некоторая целочисленная переменная, и нужно выяснить, не выходит ли эта переменная за рамки заданных значений, например от нуля до десяти. Условие можно будет скомбинировать так: \code{x >= 0 \&\& x <= 10}. В случае его истинности - выдадим сообщение о том, что \code{х} подходит.
Приведём короткий пример: дана некоторая целочисленная переменная и нужно выяснить, не выходит ли эта переменная за рамки заданных значений, например от нуля до десяти. Условие можно будет скомбинировать так: \code{x >= 0 \&\& x <= 10}. В случае его истинности - выдадим сообщение о том, что \code{х} подходит.
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
@ -235,9 +235,9 @@ X Fits!
$
\end{verbatim}
\end{figure}
Самый не приоритетный оператор - тернарный, внимательный читатель мог заметить, что он даже не вошёл в список выше, это сделано, поскольку использование тернарного оператора внутри условий нежелательно. Тернарный оператор внутри условий резко снижает читаемость кода и усложняет его интерпретацию. Если Вы сомневаетесь в приоритете сравнений или Вам необходимо описать какое-то очень сложное условие, всегда можно воспользоваться простыми математическими круглыми скобками, задав приоритет операций явно. В таком случае в первую очередь будут выполнены операции в скобках.
Самый не приоритетный оператор тернарный, внимательный читатель мог заметить, что он даже не вошёл в список выше, это сделано, поскольку использование тернарного оператора внутри условий нежелательно. Тернарный оператор внутри условий резко снижает читаемость кода и усложняет его интерпретацию. Если Вы сомневаетесь в приоритете сравнений или Вам необходимо описать какое-то очень сложное условие, всегда можно воспользоваться простыми математическими круглыми скобками, задав приоритет операций явно. В таком случае в первую очередь будут выполнены операции в скобках.
\subsection{Блоки кода и область видимости}
Говоря об операторах языка С и управляющих конструкциях, нельзя не сказать о <<блоках кода>> и <<областях видимости>>. Как видно, условные операторы содержат записи в фигурных скобках. В такие же скобки заключён код функции \code{main}. Эти скобки называются <<операторными>>, а то, что в них содержится, называется <<блоком кода>> или <<телом>> оператора или функции. Все переменные, которые инициализируются внутри блока кода, существуют и <<видны>> только внутри кодового блока. Поэтому пространство между операторными скобками также называют <<областью видимости>>.
Говоря об операторах языка С и управляющих конструкциях нельзя не сказать о <<блоках кода>> и <<областях видимости>>. Как видно, условные операторы содержат записи в фигурных скобках. В такие же скобки заключён код функции \code{main}. Эти скобки называются <<операторными>>, а то что в них содержится, называется <<блоком кода>> или <<телом>> оператора или функции. Все переменные, которые инициализируются внутри блока кода, существуют и <<видны>> только внутри кодового блока. Поэтому пространство между операторными скобками также называют <<областью видимости>>.
\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]