Compare commits
No commits in common. "master" and "master" have entirely different histories.
|
@ -1,10 +1,10 @@
|
||||||
\section{Введение} %раздел
|
\section{Введение} %раздел
|
||||||
\subsection{От автора} %подраздел
|
\subsection{От автора} %подраздел
|
||||||
Приветствую, коллеги! Начиная работу над этим документом, я не ставил целью написать очередной учебник по языку С или поспорить с трудами Кернигана, Ритчи и Страуструпа. Я думаю, что понял, почему программирование кажется таким сложным: не нашлось ни одного материала, написанного понятным и простым языком. В этом документе я постараюсь не повторить этой досадной ошибки именитых авторов.
|
Приветствую, коллеги! Начиная работу над этим документом я не ставил целью написать очередной учебник по языку С или поспорить с трудами Кернигана, Ритчи и Страуструпа. Я думаю, что понял, почему программирование кажется таким сложным: не нашлось ни одного материала, написанного понятным и простым языком. В этом документе я постараюсь не повторить этой досадной ошибки именитых авторов.
|
||||||
\frm{Брайан Керниган: <<\textbf{Язык C} — инструмент, острый, как бритва: с его помощью можно создать и элегантную программу, и кровавое месиво.>>}
|
\frm{Брайан Керниган: <<\textbf{Язык C} — инструмент, острый, как бритва: с его помощью можно создать и элегантную программу, и кровавое месиво.>>}
|
||||||
Да, спасибо классикам за предупреждения, постараемся также этой работой не создать кровавое месиво.
|
Да, спасибо классикам за предупреждения, постараемся, также, этой работой не создать кровавое месиво.
|
||||||
\subsection{Инструментарий}
|
\subsection{Инструментарий}
|
||||||
В этом документе сознательно пропускается подраздел, посвящённый выбору и настройке инструментария, потому что целью документа не является начало очередного раунда борьбы за право какого бы то ни было компилятора и/или среды разработки называться единственно верным даже с точки зрения отдельно взятого автора отдельно взятой книги. Обозначим лишь популярные варианты для основной тройки операционных систем (Windows, Linux, Mac OS X). Компиляторы:
|
В этом документе сознательно пропускается подраздел, посвящённый выбору и настройке инструментария, потому что целью документа не является начало очередного раунда борьбы за право какого бы то ни было компилятора и/или среды разработки называться единственно верным, даже с точки зрения отдельно взятого автора отдельно взятой книги. Обозначим лишь популярные варианты для основной тройки операционных систем (Windows, Linux, Mac OS X). Компиляторы:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item clang;
|
\item clang;
|
||||||
\item GCC/MinGW;
|
\item GCC/MinGW;
|
||||||
|
@ -24,4 +24,4 @@
|
||||||
%https://docs.google.com/document/d/15b226AsztngEhyzP6ZPAYnSzSlGkLHVj
|
%https://docs.google.com/document/d/15b226AsztngEhyzP6ZPAYnSzSlGkLHVj
|
||||||
%https://docs.google.com/document/d/11PmQYyQIPHl84Fh9dpJ3fwKP_h5f2veu
|
%https://docs.google.com/document/d/11PmQYyQIPHl84Fh9dpJ3fwKP_h5f2veu
|
||||||
\subsection{Немного истории}
|
\subsection{Немного истории}
|
||||||
Первая версия языка С была разработана в 1972 году Деннисом Ритчи для программирования в недавно созданной на тот момент среде UNIX. Язык разрабатывался не государством, а обычными практикующими программистами. В нём сразу были учтены и исправлены все неудобства существовавших на тот момент FORTRAN и PASCAL. Поскольку интерес к языку со временем не пропадал, а технологии развивались, появились редакции языка, такие как С99 (1999 год) С11(2011 год). В языке С есть возможность работать с указателями на физические ячейки оперативной памяти компьютера. Конечно, это небезопасно, но при должной квалификации программиста позволяет получить максимально эффективный код, близкий к языку ассемблера и даже машинным кодам конкретного процессора. С является компилируемым процедурным языком со строгой статической типизацией, что позволяет писать максимально безопасный код и отсеять бОльшую часть ошибок ещё на этапе компиляции проекта. На языке С написано огромное количество программ, библиотек, и даже операционных систем. Какая бы у Вас ни была установлена операционная система, очень вероятно, что она написана на С. На языке С пишут драйверы для периферийного оборудования, программируют контроллеры для космической аппаратуры, пишут высокоскоростные приложения. Помимо этого, сейчас стремительно набирает популярность такое направление, как <<умная техника>> и <<интернет вещей>>. Именно из-за этих трендов язык С за последние пару лет снова поднялся в рейтинге TIOBE на лидирующие места. Какой бы язык программирования вы ни изучали, знание языка С нужно, потому что языки высокого уровня делают много вещей одной командой, а если Вы хотите не просто стать программистом, а быть хорошим программистом - вы должны понимать, что там, внутри, происходит на самом деле. Знание языка С можно сравнить с умением ездить на автомобиле с механической коробкой передач: коробка-автомат резко снижает порог вхождения в участники дорожного движения, но зачастую настолько ухудшает качество управления автомобилем, что это приводит к самым печальным последствиям.
|
Первая версия языка С была разработана в 1972м году Деннисом Ритчи для программирования в недавно созданной на тот момент среде UNIX. Язык разрабатывался не государством, а обычными практикующими программистами. В нём сразу были учтены и исправлены все неудобства существовавших на тот момент FORTRAN и PASCAL. Поскольку интерес к языку со временем не пропадал, а технологии развивались, появились редакции языка, такие как С99 (1999 год) С11(2011 год). В языке С есть возможность работать с указателями на физические ячейки оперативной памяти компьютера. Конечно, это небезопасно, но при должной квалификации программиста позволяет получить максимально эффективный код, близкий к языку ассемблера и даже машинным кодам конкретного процессора. С является компилируемым процедурным языком со строгой статической типизацией, что позволяет писать максимально безопасный код, и отсеять бОльшую часть ошибок ещё на этапе компиляции проекта. На языке С написано огромное количество программ, библиотек, и даже операционных систем. Какая-бы у Вас ни была установлена операционная система, очень вероятно, что она написана на С. На языке С пишут драйверы для периферийного оборудования, программируют контроллеры для космической аппаратуры, пишут высокоскоростные приложения. Помимо этого, сейчас стремительно набирает популярность такое направление, как <<умная техника>> и <<интернет вещей>>. Именно из-за этих трендов язык С за последние пару лет снова поднялся в рейтинге TIOBE на лидирующие места. Какой бы язык программирования вы ни изучали, знание языка С нужно потому что языки высокого уровня делают много вещей одной командой, а если Вы хотите не просто стать программистом, а быть хорошим программистом - вы должны понимать, что там, внутри, происходит на самом деле. Знание языка С можно сравнить с умением ездить на автомобиле с механической коробкой передач: коробка-автомат резко снижает порог вхождения в участники дорожного движения, но, зачастую настолько ухудшает качество управления автомобилем, что это приводит к самым печальным последствиям.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
\section{Базовый ввод-вывод}
|
\section{Базовый ввод-вывод}
|
||||||
\subsection{Форматированный вывод}
|
\subsection{Форматированный вывод}
|
||||||
Общение с пользователем на чистом С происходит через консоль. Для того, чтобы выводить какую-либо информацию для чтения пользователем - используется функция \code{printf();} предназначенная для форматированного вывода некоторого текста в консоль. Функция описана в заголовке \code{stdio.h}, поэтому мы и включили данный заголовок в нашу программу. Какого рода форматирование применяется при выводе строк в консоль? Существуют два основных инструмента придания выводу необходимого вида: экранированные последовательности (escape sequences) и заполнители (placeholders).
|
Общение с пользователем на чистом С происходит через консоль. Для того, чтобы выводить какую-либо информацию для чтения пользователем - используется функция \code{printf();} предназначенная для форматированного вывода некоторого текста в консоль. Функция описана в заголовке \code{stdio.h}, поэтому мы и включили данный заголовок в нашу программу. Какого рода форматирование применяется при выводе строк в консоль? Существуют два основных инструмента придания выводу необходимого вида: экранированные последовательности (escape sequences) и заполнители (placeholders).
|
||||||
\paragraph{Экранированная последовательность} - это буква или символ, написанные после знака обратного слэша (\code{\char`\\}), которые при выполнении программы будут на что-то заменены. Самые часто используемые это:
|
\paragraph{Экранированная последовательность} это буква или символ, написанные после знака обратного слэша (\code{\char`\\}), которые при выполнении программы будут на что-то заменены. Самые часто используемые это:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item \code{\char`\\'} - одинарная кавычка;
|
\item \code{\char`\\'} - одинарная кавычка;
|
||||||
\item \code{\char`\\"} - двойная кавычка;
|
\item \code{\char`\\"} - двойная кавычка;
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
\item \code{\char`\\xnn} - произвольное шестнадцатеричное значение;
|
\item \code{\char`\\xnn} - произвольное шестнадцатеричное значение;
|
||||||
\item \code{\char`\\unnnn} - произвольное Юникод-значение.
|
\item \code{\char`\\unnnn} - произвольное Юникод-значение.
|
||||||
\end{itemize}
|
\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{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
printf("This is a terminant \0 it ends a string");
|
printf("This is a terminant \0 it ends a string");
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Запустив программу, мы можем убедиться, что всё работает так, как мы описали в тексте: сначала идёт приветствие миру, на новой строке сообщение о том, что это новая строка, далее на той же строке (ведь мы не переходили на новую) демонстрация пробела и символа табуляции. На последних двух строках происходит демонстрация обратного слэша и терминанта, видно, что остаток строки не был выведен на экран.
|
Запустив программу мы можем убедиться, что всё работает так, как мы описали в тексте: сначала идёт приветствие миру, на новой строке сообщение о том, что это новая строка, далее на той же строке (ведь мы не переходили на новую) демонстрация пробела и символа табуляции. На последних двух строках происходит демонстрация обратного слэша и терминанта, видно, что остаток строки не был выведен на экран.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
|
@ -41,7 +41,7 @@ This is terminant
|
||||||
$
|
$
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\paragraph{Заполнитель} - это также специальная последовательность, но она говорит компилятору, что на место этой последовательности необходимо вставить некий аргумент, который будет передан после строки, через запятую, при вызове данной функции \code{printf();}. Заполнитель начинается со знака процента и обозначает тип вставляемой переменной.
|
\paragraph{Заполнитель} это также специальная последовательность, но она говорит компилятору, что на место этой последовательности необходимо вставить некий аргумент, который будет передан после строки, через запятую, при вызове данной функции \code{printf();}. Заполнитель начинается со знака процента и обозначает тип вставляемой переменной.
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item \code{\%\%} - символ процента;
|
\item \code{\%\%} - символ процента;
|
||||||
\item \code{\%i (\%d)} - целые числа (integer, decimal);
|
\item \code{\%i (\%d)} - целые числа (integer, decimal);
|
||||||
|
@ -65,7 +65,7 @@ $
|
||||||
printf("Placeholders are \"%5d%%\" of formatting\n", a);
|
printf("Placeholders are \"%5d%%\" of formatting\n", a);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Так первый оператор выведет просто число. Второй – это же число, но оставив для его отображения пять пробельных символов (два окажутся заняты разрядами числа 50, и ещё три останутся свободными слева от числа). Третий оператор форматированного вывода впишет число в пять отображаемых символов, но заполнит пустоту нулями (запись с лидирующими нулями, leading zeroes). Четвёртый осуществит вывод числа с плавающей точкой, ограничив дробную часть двумя отображаемыми символами, при этом важно, что не произойдёт математического округления, символы просто не отобразятся, такое отображение часто используется для демонстрации денежных значений в долларах и центах, рублях и копейках, и пр. Последний же оператор выведет на экран надпись, информирующую о том, что заполнители - это 50\% форматирования:
|
Так первый оператор выведет просто число. Второй это же число, но оставив для его отображения пять пробельных символов (два окажутся заняты разрядами числа 50, и ещё три останутся свободными, слева от числа). Третий оператор форматированного вывода впишет число в пять отображаемых символов, но заполнит пустоту нулями (запись с лидирующими нулями, leading zeroes). Четвёртый осуществит вывод числа с плавающей точкой, ограничив дробную часть двумя отображаемыми символами, при этом важно, что не произойдёт математического округления, символы просто не отобразятся, такое отображение часто используется для демонстрации денежных значений в долларах и центах, рублях и копейках, и пр. Последний же оператор выведет на экран надпись, информирующую о том, что заполнители - это 50\% форматирования:
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
|
@ -80,7 +80,7 @@ $
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Для заполнителей \code{\%d}, \code{\%i}, \code{\%f} часто используются дополнительные параметры, такие как количество знаков после запятой, например, \code{\%.2f} или минимальное количество знаков для отображения целого числа \code{\%5d}. Также в пользу оператора форматированного вывода говорит тот факт, что, например, в С++ стандартный вывод в консоль осуществляется с помощью команды \code{std::cout}, которая не поддерживала форматирование строк вплоть до принятия стандарта С++20.
|
Для заполнителей \code{\%d}, \code{\%i}, \code{\%f} часто используются дополнительные параметры, такие как количество знаков после запятой, например, \code{\%.2f} или минимальное количество знаков для отображения целого числа \code{\%5d}. Также в пользу оператора форматированного вывода говорит тот факт, что, например, в С++ стандартный вывод в консоль осуществляется с помощью команды \code{std::cout}, которая не поддерживала форматирование строк вплоть до принятия стандарта С++20.
|
||||||
\subsection{Форматированный ввод}
|
\subsection{Форматированный ввод}
|
||||||
Поговорив о выводе в консоль, нельзя не сказать о пользовательском вводе данных. Один из способов пользовательского ввода данных в программу - это использование функции \code{scanf();}. Предложим пользователю ввести некоторое число:
|
Поговорив о выводе в консоль нельзя не сказать о пользовательском вводе данных. Один из способов пользовательского ввода данных в программу - это использование функции \code{scanf();}. Предложим пользователю ввести некоторое число:
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
\subsection{Условный оператор}
|
\subsection{Условный оператор}
|
||||||
\paragraph{\code{if()}} пожалуй, самый часто используемый в любом языке программирования, в том числе и в языке С оператор. Оператор \code{if()} позволяет программе принять решение о выполнении или невыполнении того или иного действия в зависимости от текущего состояния. В случае, если условие в круглых скобках выполнится, выполнится и последующий код, который чаще всего пишется в фигурных скобках. Если условие в круглых скобках не выполнится, то все операторы внутри идущих следом фигурных скобок будут проигнорированы.
|
\paragraph{\code{if()}} пожалуй, самый часто используемый в любом языке программирования, в том числе и в языке С оператор. Оператор \code{if()} позволяет программе принять решение о выполнении или невыполнении того или иного действия в зависимости от текущего состояния. В случае, если условие в круглых скобках выполнится, выполнится и последующий код, который чаще всего пишется в фигурных скобках. Если условие в круглых скобках не выполнится, то все операторы внутри идущих следом фигурных скобок будут проигнорированы.
|
||||||
|
|
||||||
Например, зададим пользователю вопрос, хочет ли он, чтобы его поприветствовали. Для этого опишем переменную \code{char answer}, которая будет хранить ответ пользователя в виде символа, и спросим у пользователя в терминале, хочет ли он, чтобы мы его поприветствовали, выведем на экран строку с приглашением. Далее, при помощи уже знакомой нам функции \code{scanf();} считаем ответ пользователя в переменную, и, в зависимости от пользовательского ввода, программа либо поприветствует пользователя, либо нет, это решение будет принято с помощью оператора \code{if()}.
|
Например, зададим пользователю вопрос, хочет ли он, чтобы его поприветствовали, для этого опишем переменную \code{char answer}, которая будет хранить ответ пользователя в виде символа и спросим у пользователя в терминале, хочет ли он, чтобы мы его поприветствовали, выведем на экран строку с приглашением. Далее при помощи уже знакомой нам функции \code{scanf();} считаем ответ пользователя в переменную, и, в зависимости от пользовательского ввода, программа либо поприветствует пользователя, либо нет, это решение будет принято с помощью оператора \code{if()}.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\paragraph{\code{else}} Зачастую складываются ситуации, когда нужно выполнить разные наборы действий, в зависимости от результата проверки условия. Для таких случаев используется дополнение к оператору \code{if()} - оператор \code{else}, в котором описывается последовательность действий, выполняемая в случае, если условие в круглых скобках дало ложный результат. Код немного изменится, не будем приводить повторяющиеся части взаимодействия с пользователем, сконцентрируемся на условном операторе:
|
\paragraph{\code{else}} Зачастую складываются ситуации, когда нужно выполнить разные наборы действий, в зависимости от результата проверки условия. Для таких случаев используется дополнение к оператору \code{if()} - оператор \code{else}, в котором описывается последовательность действий выполняемая в случае если условие в круглых скобках дало ложный результат. Код немного изменится, не будем приводить повторяющиеся части, взаимодействия с пользователем, сконцентрируемся на условном операторе:
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\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{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Операторов \code{else if} в одном операторе выбора может быть сколько угодно, в отличие от оператора \code{if} и оператора \code{else}, которых не может быть больше одного.
|
Операторов \code{else if} в одном операторе выбора может быть сколько угодно, в отличие от оператора \code{if} и оператора \code{else} которых не может быть больше одного.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
|
@ -57,7 +57,7 @@ I can't understand your input
|
||||||
$
|
$
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
\end{figure}
|
\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{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -80,12 +80,12 @@ $
|
||||||
int c = (a > b) ? b : a;
|
int c = (a > b) ? b : a;
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\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]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
printf("%s", (1 > 0) ? "true" : "false");
|
printf("%s", (1 > 0) ? "true" : "false");
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Проверим, как это работает, и в результате видим true, потому что единица действительно больше нуля.
|
Проверим как это работает, и в результате видим true, потому что единица действительно больше нуля.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
|
@ -95,7 +95,7 @@ $
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\paragraph{Вложенные условия и сокращения}
|
\paragraph{Вложенные условия и сокращения}
|
||||||
Внутри фигурных скобок конструкций \code{if()} находится код программы, поэтому там могут находиться и другие условные операторы. Условия, расположенные таким образом, называются вложенными. Никаких ограничений на использование вложенных условий в языке С нет. В примере ниже показано, что условия всегда выполняются (единица в круглых скобках будет означать, что условие всегда истинно), а комментариями с многоточием показано, где может располагаться код программы.
|
Внутри фигурных скобок конструкций \code{if()} находится код программы, поэтому там могут находиться и другие условные операторы. Условия, расположенные таким образом называются вложенными. Никаких ограничений на использование вложенных условий в языке С нет. В примере ниже показано, что условия всегда выполняются (единица в круглых скобках будет означать, что условие всегда истинно), а комментариями с многоточием показано, где может располагаться код программы.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -128,16 +128,16 @@ $
|
||||||
// single operator
|
// single operator
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
При использовании такой записи можно легко допустить ошибку: забыть о необходимости объединения кода фигурными скобками и предполагать, что несколько операторов могут выполниться по условию без фигурных скобок.
|
При использовании такой записи можно легко допустить ошибку: забыть о необходимости объединения кода фигурными скобками, и предполагать, что несколько операторов могут выполниться по условию без фигурных скобок.
|
||||||
\frm{Часто это заблуждение приводит к трудноуловимым ошибкам в коде, когда программа компилируется, запускается, но работает не так, как следует.}
|
\frm{Часто это заблуждение приводит к трудноуловимым ошибкам в коде, когда программа компилируется, запускается, но работает не так, как следует.}
|
||||||
\subsection{Операции сравнения}
|
\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{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
float f = 0.5f;
|
float f = 0.5f;
|
||||||
double d = 0.5;
|
double d = 0.5;
|
||||||
double diff = (f > d) ? f - d : d - f;
|
fouble diff = (f > d) ? f - d : d - f;
|
||||||
if (diff < 0.00001) {
|
if (diff < 0.00001) {
|
||||||
// useful code here
|
// useful code here
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ $
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Некоторые компиляторы выдают ошибку на этапе компиляции, некоторые компилируют такой код, но программа не сможет выполниться и выдаст ошибку \textbf{Segmentation fault}, то есть ошибку доступа к памяти (попытка обратиться к недоступной памяти или попытка обратиться к памяти неподобающим образом). В этой конкретной ситуации, мы попытаемся интерпретировать как строку часть памяти, которая находится по адресу 1, что находится далеко за пределами доступа программы. Это поведение (ошибка компиляции или ошибка времени выполнения) зависит от большого количества факторов, таких как тип операционной системы, тип и версия компилятора, версия используемого стандарта языка.
|
Некоторые компиляторы выдают ошибку на этапе компиляции, некоторые компилируют такой код, но программа не сможет выполниться и выдаст ошибку \textbf{Segmentation fault}, то есть ошибку доступа к памяти (попытка обратиться к недоступной памяти или попытка обратиться к памяти неподобающим образом). В этой конкретной ситуации, мы попытаемся интерпретировать как строку часть памяти, которая находится по адресу 1, что находится далеко за пределами доступа программы. Это поведение (ошибка компиляции или ошибка времени выполнения) зависит от большого количества факторов, таких как тип операционной системы, тип и версия компилятора, версия используемого стандарта языка.
|
||||||
|
|
||||||
Отдельного внимания заслуживает применение оператора поразрядного (арифметического) \code{ИСКЛЮЧАЮЩЕГО ИЛИ} в качестве логического. В случае такого применения оператор \code{ИСКЛЮЧАЮЩЕГО ИЛИ} фактически дублирует сравнение на неравенство, это легко объяснить, проведя анализ происходящего с числами при таком сравнении:
|
Отдельного внимания заслуживает применение оператора поразрядного (арифметического) \code{ИСКЛЮЧАЮЩЕГО ИЛИ} в качестве логического. В случае такого применения оператор \code{ИСКЛЮЧАЮЩЕГО ИЛИ}, фактически, дублирует сравнение на неравенство, это легко объяснить, проведя анализ происходящего с числами при таком сравнении:
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -163,9 +163,9 @@ $
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Данный код внутри фигурных скобок оператора \code{if()} никогда не выполнится, поскольку в С оператор сравнения работает с числами, интерпретируя ноль как ложь, а любое ненулевое значение - как истину, мы наблюдаем, что побитовое \code{ИСКЛЮЧАЮЩЕЕ ИЛИ} - это тоже самое, что проверка на неравенство.
|
Данный код внутри фигурных скобок оператора \code{if()} никогда не выполнится, поскольку в С оператор сравнения работает с числами, интерпретируя ноль как ложь, а любое ненулевое значение как истину, мы наблюдаем, что побитовое \code{ИСКЛЮЧАЮЩЕЕ ИЛИ} - это тоже самое, что проверка на неравенство.
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item оператор \code{И (\&\&)} возвращает истину, только когда оба операнда истинны;
|
\item оператор \code{И (\&\&)} возвращает истину только когда оба операнда истинны;
|
||||||
|
|
||||||
\begin{tabular}{|c|c|c|}
|
\begin{tabular}{|c|c|c|}
|
||||||
\hline
|
\hline
|
||||||
|
@ -180,7 +180,7 @@ $
|
||||||
1 & 1 & 1 \\
|
1 & 1 & 1 \\
|
||||||
\hline
|
\hline
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
\item оператор \code{ИЛИ (||)} возвращает истину, когда хотя бы один из операндов истинный;
|
\item оператор \code{ИЛИ (||)} возвращает истину когда хотя бы один из операндов истинный;
|
||||||
|
|
||||||
\begin{tabular}{|c|c|c|}
|
\begin{tabular}{|c|c|c|}
|
||||||
\hline
|
\hline
|
||||||
|
@ -195,7 +195,7 @@ $
|
||||||
1 & 1 & 1 \\
|
1 & 1 & 1 \\
|
||||||
\hline
|
\hline
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
\item оператор \code{НЕ (!)} возвращает истину, когда операнд ложный;
|
\item оператор \code{НЕ (!)} возвращает истину когда операнд ложный;
|
||||||
|
|
||||||
\begin{tabular}{|c|c|}
|
\begin{tabular}{|c|c|}
|
||||||
\hline
|
\hline
|
||||||
|
@ -208,7 +208,7 @@ $
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Используя логические операторы в программе, мы можем написать логику практически любой сложности. В языке С нет ограничений на использование сложных условий. Сложные условия это такие, где в круглых скобках выполняется более одного сравнения. Сравнения производятся в порядке заранее оговорённого приоритета. В списке ниже указаны операторы в порядке уменьшения их приоритета:
|
Используя логические операторы в программе мы можем написать логику практически любой сложности. В языке С нет ограничений на использование сложных условий. Сложные условия это такие, где в круглых скобках выполняется более одного сравнения. Сравнения производятся в порядке заранее оговоренного приоритета. В списке ниже указаны операторы в порядке уменьшения их приоритета:
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item $!$
|
\item $!$
|
||||||
\item $<, <=, >, >=$
|
\item $<, <=, >, >=$
|
||||||
|
@ -216,7 +216,7 @@ $
|
||||||
\item $\&\&$
|
\item $\&\&$
|
||||||
\item $||$
|
\item $||$
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
Приведём короткий пример: дана некоторая целочисленная переменная, и нужно выяснить, не выходит ли эта переменная за рамки заданных значений, например от нуля до десяти. Условие можно будет скомбинировать так: \code{x >= 0 \&\& x <= 10}. В случае его истинности - выдадим сообщение о том, что \code{х} подходит.
|
Приведём короткий пример: дана некоторая целочисленная переменная и нужно выяснить, не выходит ли эта переменная за рамки заданных значений, например от нуля до десяти. Условие можно будет скомбинировать так: \code{x >= 0 \&\& x <= 10}. В случае его истинности - выдадим сообщение о том, что \code{х} подходит.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
@ -235,9 +235,9 @@ X Fits!
|
||||||
$
|
$
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
Самый не приоритетный оператор - тернарный, внимательный читатель мог заметить, что он даже не вошёл в список выше, это сделано, поскольку использование тернарного оператора внутри условий нежелательно. Тернарный оператор внутри условий резко снижает читаемость кода и усложняет его интерпретацию. Если Вы сомневаетесь в приоритете сравнений или Вам необходимо описать какое-то очень сложное условие, всегда можно воспользоваться простыми математическими круглыми скобками, задав приоритет операций явно. В таком случае в первую очередь будут выполнены операции в скобках.
|
Самый не приоритетный оператор тернарный, внимательный читатель мог заметить, что он даже не вошёл в список выше, это сделано, поскольку использование тернарного оператора внутри условий нежелательно. Тернарный оператор внутри условий резко снижает читаемость кода и усложняет его интерпретацию. Если Вы сомневаетесь в приоритете сравнений или Вам необходимо описать какое-то очень сложное условие, всегда можно воспользоваться простыми математическими круглыми скобками, задав приоритет операций явно. В таком случае в первую очередь будут выполнены операции в скобках.
|
||||||
\subsection{Блоки кода и область видимости}
|
\subsection{Блоки кода и область видимости}
|
||||||
Говоря об операторах языка С и управляющих конструкциях, нельзя не сказать о <<блоках кода>> и <<областях видимости>>. Как видно, условные операторы содержат записи в фигурных скобках. В такие же скобки заключён код функции \code{main}. Эти скобки называются <<операторными>>, а то, что в них содержится, называется <<блоком кода>> или <<телом>> оператора или функции. Все переменные, которые инициализируются внутри блока кода, существуют и <<видны>> только внутри кодового блока. Поэтому пространство между операторными скобками также называют <<областью видимости>>.
|
Говоря об операторах языка С и управляющих конструкциях нельзя не сказать о <<блоках кода>> и <<областях видимости>>. Как видно, условные операторы содержат записи в фигурных скобках. В такие же скобки заключён код функции \code{main}. Эти скобки называются <<операторными>>, а то что в них содержится, называется <<блоком кода>> или <<телом>> оператора или функции. Все переменные, которые инициализируются внутри блока кода, существуют и <<видны>> только внутри кодового блока. Поэтому пространство между операторными скобками также называют <<областью видимости>>.
|
||||||
|
|
||||||
\begin{figure}[h!]
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||||
|
|
Loading…
Reference in New Issue