forked from ivan-igorevich/basic-c
refactored preambles
This commit is contained in:
parent
6f639f55cd
commit
50b4bbbdfa
|
@ -0,0 +1,29 @@
|
|||
% \usepackage[printwatermark]{xwatermark}
|
||||
|
||||
\usepackage{ascii}
|
||||
\usepackage{textcomp}
|
||||
\usepackage{eurosym}
|
||||
\usepackage{cclicenses}
|
||||
|
||||
\input{fancy-listings-preamble}
|
||||
|
||||
\usetikzlibrary{positioning}
|
||||
|
||||
\geometry{
|
||||
paperheight=24cm,
|
||||
paperwidth=17cm,
|
||||
lmargin=1.5cm,
|
||||
rmargin=2.5cm,
|
||||
tmargin=2.5cm,
|
||||
bmargin=2.5cm,
|
||||
}
|
||||
|
||||
\author{Иван Овчинников}
|
||||
\date{\today}
|
||||
\title{Очередное введение в\\язык программирования C}
|
||||
|
||||
% \newwatermark[allpages,color=red!50,angle=70,scale=7,xpos=-36,ypos=14]{DRAFT}
|
||||
|
||||
\addto{\captionsrussian}{\renewcommand{\figurename}{}}
|
||||
|
||||
\newcommand{\sectionbreak}{\clearpage}
|
BIN
build/main.pdf
BIN
build/main.pdf
Binary file not shown.
|
@ -0,0 +1,85 @@
|
|||
\usepackage{tikz}
|
||||
\usepackage{import}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{bookmark}
|
||||
\usepackage{multicol,multirow,colortbl}
|
||||
\usepackage{longtable}
|
||||
\usepackage{setspace}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{indentfirst}
|
||||
\usepackage{amsmath,amsfonts,amssymb,amsthm,mathtools}
|
||||
\usepackage{layout,lscape}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{geometry}
|
||||
\usepackage[russian]{babel}
|
||||
\usepackage{nomencl}
|
||||
\usepackage{makeidx}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{tabularx,adjustbox}
|
||||
\usepackage{float,makecell}
|
||||
\usepackage{anyfontsize,tabto}
|
||||
\usepackage{tocloft}
|
||||
|
||||
\makeindex
|
||||
\makenomenclature
|
||||
\babelfont{rm}{Times New Roman}
|
||||
\babelfont{sf}{Liberation Serif}
|
||||
\babelfont{tt}{Courier New}
|
||||
\onehalfspacing
|
||||
|
||||
\hypersetup{
|
||||
colorlinks=false,
|
||||
linktoc=all
|
||||
}
|
||||
|
||||
\fancypagestyle{plain}{ % для автосгенерированых
|
||||
\fancyhf{}
|
||||
\renewcommand{\headrulewidth}{0pt}
|
||||
}
|
||||
\fancypagestyle{titlepage}{
|
||||
\fancyhf{}
|
||||
\cfoot{\small{\textbf{Москва, \the\year{}г.}}}
|
||||
}
|
||||
\fancyhf{}
|
||||
\renewcommand{\headrulewidth}{0pt}
|
||||
|
||||
\newcommand{\numerationTop}{
|
||||
\fancyhead[C]{\thepage}
|
||||
}
|
||||
\newcommand{\numerationBottom}{
|
||||
\fancyfoot[C]{\thepage}
|
||||
}
|
||||
|
||||
\newcommand{\code}[1]{\texttt{#1}}
|
||||
\renewcommand{\nomname}{ }
|
||||
\newcommand*{\nom}[2]{#1\nomenclature{#1}{#2}}
|
||||
|
||||
\newcommand\blankpage{%
|
||||
\null
|
||||
\thispagestyle{empty}%
|
||||
\addtocounter{page}{-1}%
|
||||
\newpage
|
||||
}
|
||||
|
||||
\newcommand{\frm}[1]{\newline%
|
||||
\newline%
|
||||
\indent\fbox{%
|
||||
\parbox{0.9\textwidth}{%
|
||||
#1}%
|
||||
}%
|
||||
\newline%
|
||||
\newline%
|
||||
}%
|
||||
|
||||
\makeatletter
|
||||
\newcommand{\setword}[2]{%
|
||||
\phantomsection
|
||||
#1\def\@currentlabel{\unexpanded{#1}}\label{#2}%
|
||||
}
|
||||
\makeatother
|
||||
|
||||
\newcommand\lh[2]{\texttt{\textcolor{#1}{#2}}}
|
||||
\newcommand\hrf[1]{\hyperref[#1]{\ref{#1}}}
|
||||
\newcommand*\circled[1]{\tikz[baseline=(char.base)]{\node[shape=circle,draw,inner sep=2pt] (char) {#1};}}
|
||||
|
||||
\renewcommand{\cftsecleader}{\cftdotfill{\cftdotsep}}
|
|
@ -0,0 +1,104 @@
|
|||
\usepackage{listings}
|
||||
|
||||
\definecolor{codekeywords}{rgb}{0.1,0.4,0.4}
|
||||
\definecolor{codecomments}{rgb}{0,0.6,0}
|
||||
\definecolor{codenumbers}{rgb}{0.4,0.4,0.4}
|
||||
\definecolor{codestring}{rgb}{0.85,0.2,0.1}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codefine}{rgb}{0.7,0.5,0.3}
|
||||
\definecolor{dkgreen}{rgb}{0,0.6,0}
|
||||
\definecolor{gray}{rgb}{0.5,0.5,0.5}
|
||||
\definecolor{mauve}{rgb}{0.58,0,0.82}
|
||||
|
||||
\lstdefinestyle{JCodeStyle}{
|
||||
frame=single,
|
||||
language=Java,
|
||||
aboveskip=3mm,
|
||||
belowskip=3mm,
|
||||
showstringspaces=false,
|
||||
columns=flexible,
|
||||
basicstyle=\footnotesize\ttfamily,
|
||||
numbers=left,
|
||||
numberstyle=\tiny\color{gray},
|
||||
keywordstyle=\color{blue},
|
||||
commentstyle=\color{dkgreen},
|
||||
stringstyle=\color{mauve},
|
||||
breaklines=true,
|
||||
breakatwhitespace=true,
|
||||
tabsize=4,
|
||||
escapeinside={<@}{@>}
|
||||
}
|
||||
|
||||
\lstdefinestyle{PyCodeStyle}{
|
||||
frame=single,
|
||||
commentstyle=\color{codecomments},
|
||||
numberstyle=\tiny\color{codenumbers},
|
||||
stringstyle=\color{codestring},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
keywordstyle=\color{codekeywords},
|
||||
breakatwhitespace=false,
|
||||
breaklines=true,
|
||||
captionpos=b,
|
||||
keepspaces=true,
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
showtabs=false,
|
||||
tabsize=4,
|
||||
escapeinside={<@}{@>}
|
||||
}
|
||||
|
||||
\lstdefinestyle{CCodeStyle}{
|
||||
frame=single,
|
||||
commentstyle=\color{codecomments},
|
||||
morecomment=[l][\color{codefine}]{\#},
|
||||
numberstyle=\tiny\color{codenumbers},
|
||||
stringstyle=\color{codestring},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
keywordstyle=\color{codekeywords},
|
||||
emph={int,char,double,float,unsigned,void,bool},
|
||||
emphstyle={\color{blue}},
|
||||
breakatwhitespace=false,
|
||||
breaklines=true,
|
||||
captionpos=b,
|
||||
keepspaces=true,
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
showtabs=false,
|
||||
tabsize=4,
|
||||
escapeinside={<@}{@>}
|
||||
}
|
||||
|
||||
\lstdefinestyle{ASMStyle}{
|
||||
frame=single,
|
||||
numberstyle=\tiny\color{codenumbers},
|
||||
commentstyle=\color{codecomments},
|
||||
keywordstyle=\color{codekeywords},
|
||||
morecomment=[l]{//}, % l is for line comment
|
||||
morecomment=[s]{/*}{*/}, % s is for start and end delimiter
|
||||
basicstyle={\ttfamily\footnotesize},
|
||||
morekeywords={
|
||||
add,addi,and,andi,
|
||||
bge,beq,bne,br,
|
||||
cmpeqi,cmpgei,cmplti,cmpnei,
|
||||
ldhu,ldw,ldwio,
|
||||
mov,movi,movhi,muli,
|
||||
nop,nor,
|
||||
ret,
|
||||
slli,srai,srli,stw,stwio},
|
||||
breakatwhitespace=false,
|
||||
breaklines=true,
|
||||
captionpos=b,
|
||||
keepspaces=true,
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
showspaces=false,
|
||||
showtabs=false,
|
||||
tabsize=4,
|
||||
escapeinside={<@}{@>}
|
||||
}
|
||||
|
||||
\lstset{escapeinside={<@}{@>}}
|
|
@ -1,75 +0,0 @@
|
|||
% \usepackage[printwatermark]{xwatermark}
|
||||
\usepackage{import}
|
||||
\usepackage{listings}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{bookmark}
|
||||
\usepackage{multicol}
|
||||
\usepackage{setspace}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{indentfirst}
|
||||
\usepackage{amsmath,amsfonts,amssymb,amsthm,mathtools}
|
||||
\usepackage{icomma}
|
||||
\usepackage{layout}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{tikz}
|
||||
|
||||
\usepackage{ascii}
|
||||
\usepackage{textcomp}
|
||||
\usepackage{eurosym}
|
||||
\usepackage{cclicenses}
|
||||
|
||||
\usetikzlibrary{positioning}
|
||||
\usepackage[lmargin=1.5cm,rmargin=2.5cm,tmargin=2.5cm,bmargin=2.5cm,paperheight=240mm,paperwidth=170mm]{geometry}
|
||||
|
||||
\definecolor{codekeywords}{rgb}{0.1,0.3,0.3}
|
||||
\definecolor{codecomments}{rgb}{0,0.4,0}
|
||||
\definecolor{codenumbers}{rgb}{0.4,0.4,0.4}
|
||||
\definecolor{codestring}{rgb}{0.85,0.2,0.1}
|
||||
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
|
||||
\definecolor{codefine}{rgb}{0.7,0.5,0.3}
|
||||
\lstdefinestyle{CCodeStyle}{
|
||||
commentstyle=\color{codecomments},
|
||||
morecomment=[l][\color{codefine}]{\#},
|
||||
numberstyle=\tiny\color{codenumbers},
|
||||
stringstyle=\color{codestring},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
keywordstyle=\color{codekeywords},
|
||||
emph={int,char,double,float,unsigned,void,bool},
|
||||
emphstyle={\color{blue}},
|
||||
breakatwhitespace=false,
|
||||
breaklines=true,
|
||||
captionpos=b,
|
||||
keepspaces=true,
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
showtabs=false,
|
||||
tabsize=4
|
||||
}
|
||||
\author{Иван Овчинников}
|
||||
\date{\today}
|
||||
\title{Очередное введение в\\язык программирования C}
|
||||
\babelfont{rm}{Times New Roman}
|
||||
\babelfont{sf}{Microsoft Sans Serif}
|
||||
\babelfont{tt}{Courier New}
|
||||
% \newwatermark[allpages,color=red!50,angle=70,scale=7,xpos=-36,ypos=14]{DRAFT}
|
||||
\onehalfspacing
|
||||
\addto{\captionsrussian}{\renewcommand{\figurename}{}}
|
||||
\hypersetup{
|
||||
colorlinks=false,
|
||||
linktoc=all
|
||||
}
|
||||
|
||||
\newcommand{\code}[1]{\texttt{#1}}
|
||||
\newcommand{\sectionbreak}{\clearpage}
|
||||
\newcommand{\frm}[1]{\newline%
|
||||
\newline%
|
||||
\indent\fbox{%
|
||||
\parbox{0.9\textwidth}{%
|
||||
#1}%
|
||||
}%
|
||||
\newline%
|
||||
\newline%
|
||||
}%
|
8
main.tex
8
main.tex
|
@ -1,6 +1,6 @@
|
|||
\documentclass[a4paper]{article}
|
||||
\usepackage[russian]{babel}
|
||||
\include{formatting}
|
||||
\documentclass[fontsize=14bp]{article}
|
||||
\input{common-preamble}
|
||||
\input{book-preamble}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
@ -35,7 +35,7 @@
|
|||
\import{sections/}{12-files}
|
||||
|
||||
\section{Распределение памяти}
|
||||
Этот раздел находится в конце книги, но не по важности. Сильная сторона языка С (и, как следствие, С++) не только в возможности работать с указателями, но и в возможности самостоятельно управлять выделяемой памятью внутри программы. В языках высокого уровня данная возможность зачастую скрыта от программиста, чтобы по случайности программа не привела к зависанию среды виртуализации, по неосторожности не попыталась воспользоваться всей возможной оперативной памятью или не сломала операционную систему. Итак, как мы уже знаем, все переменные всех типов как-то хранятся в памяти, и до этого момента нас устраивало, как операционная система нам эту память выделяет. Но, пришло время взять бразды правления в свои руки. Процесс \textbf{выделения памяти} для программы называется \textbf{memory allocation}, отсюда и название функции, которая выделяет память и пишет в предложенный идентификатор указатель на начало этой области.
|
||||
Этот раздел находится в конце документа, но не по важности. Сильная сторона языка С (и, как следствие, С++) не только в возможности работать с указателями, но и в возможности самостоятельно управлять выделяемой памятью внутри программы. В языках высокого уровня данная возможность зачастую скрыта от программиста, чтобы по случайности программа не привела к зависанию среды виртуализации, по неосторожности не попыталась воспользоваться всей возможной оперативной памятью или не сломала операционную систему. Итак, как мы уже знаем, все переменные всех типов как-то хранятся в памяти, и до этого момента нас устраивало, как операционная система нам эту память выделяет. Но, пришло время взять бразды правления в свои руки. Процесс \textbf{выделения памяти} для программы называется \textbf{memory allocation}, отсюда и название функции, которая выделяет память и пишет в предложенный идентификатор указатель на начало этой области.
|
||||
|
||||
\subsection{\code{void* malloc(size);}}
|
||||
Функция \code{void* malloc(size);} принимает в качестве аргумента размер выделяемой памяти. Как видим, функция возвращает довольно необычный на первый взгляд тип: \code{void*}, то есть область памяти будет зафиксирована, но не размечена. То есть это будет просто некоторая пустая область из \code{size} байт.
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
Переменные делятся на целочисленные, символьные, указатели и числа с плавающей точкой (англ. floating point, дробное число). Все, кроме указателей и символьных переменных бывают как знаковыми так и беззнаковыми. То есть в знаковых самый старший бит в двоичной записи этих переменных отводится под определение, является ли число отрицательным, или положительным, в беззнаковых все биты используются для записи числа, что увеличивает его диапазон возможных значений, но позволяет записать только положительные числа. В классическом С нет булевого типа, вместо него используется целое число и значения нуля для \textbf{лжи} и \textit{любое} другое число для \textbf{истины}, обычно это единица. Об указателях и булевой алгебре мы будем подробно говорить в одном из последующих разделов.
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\begin{tabular}{|p{1.5cm}|p{6.6cm}|p{2.4cm}|}
|
||||
\begin{tabular}{|p{15mm}|p{65mm}|p{25mm}|}
|
||||
\hline
|
||||
Тип & Пояснение & Спецификатор формата \\
|
||||
\hline
|
||||
char & Целочисленный, самый маленький из адресуемых типов, диапазон: [\textminus128, +127] & \%c \\
|
||||
\hline
|
||||
short\newline short int & Тип короткого целого числа со знаком, диапазон: [\textminus32 768, +32 767] & \%hi \\
|
||||
short\newline short int & Тип короткого целого числа со знаком, диапазон:\newline[\textminus32 768, +32 767] & \%hi \\
|
||||
\hline
|
||||
int & Основной тип целого числа со знаком, диапазон: [\textminus2 147 483 648, +2 147 483 647] & \%i или \%d \\
|
||||
int & Основной тип целого числа со знаком, диапазон:\newline[\textminus2 147 483 648, +2 147 483 647] & \%i или \%d \\
|
||||
\hline
|
||||
long\newline long int & Тип длинного целого числа со знаком, диапазон: [\textminus2 147 483 648, +2 147 483 647] & \%li или \%ld \\
|
||||
long\newline long int & Тип длинного целого числа со знаком, диапазон:\newline[\textminus2 147 483 648, +2 147 483 647] & \%li или \%ld \\
|
||||
\hline
|
||||
long long\newline long long int & Тип двойного длинного целого числа со знаком, диапазон: [\textminus9 223 372 036 854 775 808, +9 223 372 036 854 775 807] & \%lli \\
|
||||
long long\newline long long int & Тип двойного длинного целого числа со знаком, диапазон:\newline[\textminus9 223 372 036 854 775 808, +9 223 372 036 854 775 807] & \%lli \\
|
||||
\hline
|
||||
float & Тип вещественного числа с плавающей запятой (одинарной точности) & \%f (автоматически преобразуется в double для printf()) \\
|
||||
\hline
|
||||
|
@ -363,7 +363,7 @@ a = a ^ b; //00001111
|
|||
\end{figure}
|
||||
Применять бинарную алгебру можно и в больших проектах, работающих со сложными высокоуровневыми абстракциями. Помимо этого важно помнить, что поддержка бинарных операций есть в подавляющем числе языков программирования. Используя бинарную алгебру можно создавать оптимальные протоколы передачи данных и/или алгоритмы хранения и обработки.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\begin{figure}[H]
|
||||
\begin{verbatim}
|
||||
$ ./program
|
||||
a = 15
|
||||
|
|
|
@ -84,10 +84,13 @@ $
|
|||
Теперь мы без проблем можем оформить уже существующие у нас программы в виде функций. Например, оформим в виде функции программу проверки простоты числа. Для этого опишем функцию которая возвращает целое число, назовем ее \code{isPrime()}, в качестве параметра она будет принимать целое число, назовем его \code{number}. Найдем в предыдущих разделах (стр. \hyperref[code:isPrime]{\pageref{code:isPrime}}) программу определения простоты числа и скопируем в тело функции. Внесем небольшие правки, уберем вывод так как это будет, можно сказать, классическая проверяющая функция, вывод оставим для функции \code{int main (int argc, char *argv[])}, пусть о наличии у нас терминала <<знает>> только она.
|
||||
\frm{Такой процесс, перенос участков кода между функциями, выделение участков кода в функции, синтаксические, стилистические и другие улучшения, называетя \textbf{рефакторингом}. Обычно, рефакторингом занимаются сами разработчики в свободное от основной деятельности времени, в периоды код ревью или по необходимости улучшить читаемость/повторяемость собственного кода.}
|
||||
Следовательно, допишем условия: если делителей два, то число простое, возвращаем \code{ИСТИНУ}, то есть любое ненулевое значение, в нашем примере - единицу. Если же делителей больше – число не простое, возвращаем \code{ЛОЖЬ}, в нашем случае, это ноль. Такой вывод можно записать и другим способом, \code{return (dividers == 2)} – это выражение в случае истины вернет единицу в случае лжи ноль. Или можно воспользоваться тернарным оператором, то есть, написать \code{return (dividers == 2) ? 1 : 0}: если условие в скобках истинно вернется единица, ложно – ноль. Также важно, что выйти из функции мы можем на любом этапе ее выполнения, например если делителей уже три, то нам нужно не завершать цикл, а вернуть \code{ЛОЖЬ} из функции.
|
||||
|
||||
\begin{figure}[H]
|
||||
\setlength{\columnsep}{22pt}
|
||||
\begin{multicols}{2}
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
|
||||
int isPrime(int number){
|
||||
|
||||
int dividers = 0, i = 1;
|
||||
|
||||
|
||||
|
@ -126,6 +129,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
\end{lstlisting}
|
||||
\end{multicols}
|
||||
\end{figure}
|
||||
%\setlength{\columnsep}{10pt}
|
||||
Немного подправив вывод, внесем в него вызов функции \code{isPrime()} и объявим переменную \code{int num}, которую будем передавать в качестве аргумента в функцию \code{isPrime()}. Запустим нашу программу и убедимся что все работает – число 71 действительно является простым.
|
||||
|
||||
\begin{figure}[h!]
|
||||
|
|
|
@ -52,9 +52,13 @@ value of 'pointer' is 000000000061FE1C
|
|||
\frm{Для языка С также справедливо выражение <<передача по ссылке>>, поскольку в языке С нет отдельной операции передачи по ссылке. Так, например, в языке С++ передача по ссылке и передача по указателю - это разные операции.}
|
||||
То есть функция будет ссылаться на переменные, на которые мы укажем и оперировать их значениями. Давайте немного модифицируем нашу программу обмена значениями внутри двух переменных (\hyperref[code:programswap]{\ref{code:programswap}}): опишем её в виде функции, принимающей в качестве параметров два указателя на целые числа типа \code{char}, и передадим адреса созданных в \code{int main (int argc, char *argv[])} переменных. Внутри функции, при её вызове, у нас будут создаваться не переменные, а указатели на переменные, то есть мы будем ссылаться на те самые переменные, созданные вне функции, и будем менять именно их (тех переменных) значения. Таким образом, нам не нужно ничего возвращать, потому что в функции ничего не создавалось, и типом возвращаемого значения функции должен быть \code{void}.
|
||||
|
||||
|
||||
\begin{figure}[H]
|
||||
\setlength{\columnsep}{30pt}
|
||||
\begin{multicols}{2}
|
||||
\lstinputlisting[language=C,style=CCodeStyle]{../sources/swapfunc.c}
|
||||
\columnbreak
|
||||
\lstinputlisting[language=C,style=CCodeStyle]{../sources/swapprog.c}
|
||||
\end{multicols}
|
||||
\end{figure}
|
||||
Применение такого подхода открывает перед нами широкие возможности. Важно, на схеме со стр. \pageref{fig:dereference}, что указатель - это тоже переменная, поэтому мы можем создавать указатели на указатели, и так далее, указатели любой сложности, тем самым увеличивая уровень абстракции программы.
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
Помимо уже хорошо знакомой вам директивы \code{\#include}, частично описанной в разделе \hyperref[text:directive]{\ref{text:directive}}, естественно, существуют и другие. Некоторые из них ограничивают импорт описанных в заголовочном файле функций, некоторые <<\textbf{описывают}>> какие-то константы и даже действия. Вот, директиву \textbf{описать} мы и рассмотрим подробнее. Она не зря называется директивой препроцессора, поскольку даёт указание не процессору во время выполнения программы выделить память, присвоить значения, а непосредственно компилятору: заменить в тексте программы одни слова на другие. Таким образом можно задавать константы проекта, и даже делать сокращённые записи целых действий. Например, написав \code{\#define ARRAY\_LENGTH 50} мы предпишем компилятору, перед запуском трансляции нашего кода заменить все слова \code{ARRAY\_LENGTH} на цифру 50. В такой записи, слово \code{ARRAY\_LENGTH} будет называться \textit{макроконстантой}.
|
||||
\frm{Обратите внимание, что директива пишется немного не так, как обычный оператор языка, хоть и может находиться в любом месте кода. В конце директивы не ставится точка с запятой. Это важно именно потому что директивы работают с текстом программы, то есть если точка с запятой всё же будет поставлена, текст программы будет всегда содержать вместо макроконстанты число и точку с запятой, что может в корне изменить смысл программы.}
|
||||
Весьма удобно, но этим можно не ограничиваться, мы можем попросить компилятор заменить вызовы функций и операторы на короткие, удобные нам слова. Важно помнить, что директивы препроцессора работают с текстом программы, поэтому не осуществляют никаких дополнительных проверок. Это сложный и мощный инструмент, который чаще всего используется для решения нетривиальных задач, например, выбор кода, который попадёт в компиляцию в зависимости от операционной системы. Иногда в программах можно встретить описание недостающего, но такого привычного булева типа при помощи директив препроцессора:
|
||||
|
||||
\begin{figure}[H]
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
#define bool int
|
||||
#define true 1
|
||||
#define false 0
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
Но нам пока что достаточно умения создать глобальную именованную константу. Код ниже демонстрирует, что директивы не обязательно группировать именно в начале файла, а можно использовать там, где это удобно и уместно, так мы можем объявить константу с длиной массива в начале файла, а можем прямо внутри функции \code{int main (int argc, char *argv[])}.
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
int main(int argc, char* argv[]) {
|
||||
|
@ -261,7 +264,7 @@ float average(int* array, int length) {
|
|||
|
||||
Попробуем визуализировать двумерный массив. Создадим двумерный массив в коде, например, 5х5 элементов. Массив 5х5 – это 5 столбцов и 5 строчек. Соответственно, \textit{каждая строчка – это будет у нас младший индекс, а каждый столбец – старший индекс}. Трехмерный массив может быть, например, 3х3х3 – его можно визулизировать как всем известный кубик Рубика то есть, это три стоящих друг за другом таблицы 3х3. Также опишем его в коде ниже. Получается, что мы к таблице (ширине и высоте) добавили третье \textbf{измерение}, поэтому и массив получается \textbf{многомерным}, в данном случае, \textbf{трёхмерным}. Массивы б\'{о}льших размерностей тоже можно встретить в программах, но значительно реже, только лишь потому, что их действительно немного сложнее представить себе.
|
||||
\begin{figure}[h!]
|
||||
|
||||
\setlength{\columnsep}{30pt}
|
||||
\begin{multicols}{2}
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
int twoDimensional[5][5];
|
||||
|
@ -288,7 +291,7 @@ int twoDimensional[5][5];
|
|||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
int threeDimensional[3][3][3];
|
||||
\end{lstlisting}
|
||||
|
||||
\centering
|
||||
\begin{tikzpicture}[every node/.style={minimum size=1cm},on grid]
|
||||
\begin{scope}[every node/.append style={yslant=-0.5},yslant=-0.5]
|
||||
\node at (0.5,2.5) {2,0,0};
|
||||
|
@ -321,9 +324,9 @@ int threeDimensional[3][3][3];
|
|||
\node at (4.5,2.5) {2,0,1};
|
||||
\node at (4.5,1.5) {1,0,1};
|
||||
\node at (4.5,0.5) {0,0,1};
|
||||
\node at (5.5,2.5) {2,1,2};
|
||||
\node at (5.5,1.5) {1,1,2};
|
||||
\node at (5.5,0.5) {0,1,2};
|
||||
\node at (5.5,2.5) {2,0,2};
|
||||
\node at (5.5,1.5) {1,0,2};
|
||||
\node at (5.5,0.5) {0,0,2};
|
||||
\draw (3,0) grid (6,3);
|
||||
\end{scope}
|
||||
\end{tikzpicture}
|
||||
|
@ -367,10 +370,13 @@ for (r = 0; r < rows; r++) {
|
|||
Запустив нашу программу с формированием таблицы умножения увидим, что все отлично работает. Полный листинг программы приводить не целесообразно, поскольку это цикл с заполнением и цикл с выводом, полностью привед§нные выше. К тому же, такой код носит исключительно академический характер, и в случае действительной необходимости формирования таблицы Пифагора на экране промежуточное заполнение массива будет излишним, результат умножения целесообразнее сразу выводить на экран.
|
||||
|
||||
Как уже говорилось, все массивы могут содержать данные любых типов, в том числе и указатели. Именно это позволяет массиву хранить другие массивы, строки и прочие ссылочные типы данных. Используя массивы указателей, мы можем создать, например, массив строк.
|
||||
|
||||
\begin{figure}[H]
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
char* stringArray[3] = {"Hello", "C", "World"};
|
||||
int r;
|
||||
for (r = 0; r < 3; r++)
|
||||
printf("%s ", stringArray[r]);
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
Это указатели на строки, а точнее, на строковые литералы. Такой тип данных (строковый литерал) является указателем. И мы можем создать из этих указателей массив. Используя массивы указателей, мы можем создать, например, двумерный массив, где каждый элемент не обязан быть того же размера, что и остальные (но обязан быть того же типа, как мы помним). Но строки и сложно составленные указатели - это темы, которые очень сильно выходят за рамки Основ языка, хотя, конечно, это не помешает нам немного подробнее разобраться со строками в следующем разделе.
|
||||
|
|
|
@ -153,6 +153,8 @@ int main(int argc, const char* argv[]) {
|
|||
\frm{В некоторых случаях может показаться, что никакой проблемы нет, поскольку написанная таким образом программа благополучно поприветствует пользователя, но такое поведение не гарантируется ни одним компилятором и ни одной операционной системой, поскольку возвращаемый таким образом указатель может быть переписан абсолютно любой следующей инструкцией кода. Такое \textit{исчезающее} значение называется \textbf{xvalue}.}
|
||||
Выход очень простой: раз указатель не идёт в \code{int main (int argc, char *argv[])}, надо чтобы \code{int main (int argc, char *argv[])} дал нам указатель. Добавим в параметры функции указатель на выходную строку, и напишем что для начала сложить строки и положить в локальный массив \code{strcat(welcome, name)}. Добавим в основную функцию массив \code{char result[]}, который будет хранить результат и передадим в функцию \code{helloFunction} аргументы \code{name} и \code{result}. А раз функция больше ничего не возвращает, вполне легально сделать её \code{void}.
|
||||
|
||||
|
||||
\begin{figure}[H]
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
void helloFunction(char* name, char* out) {
|
||||
char welcome[255] = "Hello, ";
|
||||
|
@ -170,6 +172,7 @@ int main(int argc, const char* argv[]) {
|
|||
return 0;
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
Запускаем, и \textbf{снова не работает}, да ещё и как интересно, смотрите! Предупреждение, ладно, понятно, мы о нём говорили, но дальше, когда мы вводим имя на выходе получается какая-то совсем уж непонятная строчка, совсем не похожая на приветствие.
|
||||
\begin{verbatim}
|
||||
|
|
|
@ -24,6 +24,8 @@ struct fraction {
|
|||
};
|
||||
\end{lstlisting}
|
||||
Для сокращения записи опишем новый тип данных, назовём его \textbf{дробь}. Далее будут приведены два равнозначных способа сокращения записи структур: первый способ создаёт псевдоним для уже существующей структуры, а второй создаёт псевдоним для структуры прямо в момент её описания, поэтому и саму структуру можно не называть, а обращаться к ней только через псевдоним:
|
||||
|
||||
\begin{figure}[H]
|
||||
\begin{lstlisting}[language=C,style=CCodeStyle]
|
||||
// alias for existing struct
|
||||
typedef struct fraction Fraction;
|
||||
|
@ -35,6 +37,7 @@ typedef struct {
|
|||
int den; // denominator
|
||||
} Fraction;
|
||||
\end{lstlisting}
|
||||
\end{figure}
|
||||
|
||||
Обычно доступ к переменным внутри структуры осуществляется привычным для высокоуровневых языков способом - через точку. Есть одно исключение, но об этом чуть позже. Создадим три переменных для хранения двух дробей, с которыми будем совершать операции, и одну для хранения результата. Инициализируем переменные какими-нибудь значениями. Опишем целочисленные значения, опишем делимое для обеих дробей и опишем делитель для обеих дробей. Для простоты будем использовать простые дроби: \( 1\frac{1}{5} \) и \( -1\frac{1}{5} \).
|
||||
|
||||
|
|
Loading…
Reference in New Issue