initial commit
This commit is contained in:
commit
2369f801af
76 changed files with 4273 additions and 0 deletions
53
.gitignore
vendored
Normal file
53
.gitignore
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# ---> C
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
BIN
seminar01_overload/classroom_tasks/classroom_tasks_overload.pdf
Normal file
BIN
seminar01_overload/classroom_tasks/classroom_tasks_overload.pdf
Normal file
Binary file not shown.
180
seminar01_overload/classroom_tasks/classroom_tasks_overload.tex
Normal file
180
seminar01_overload/classroom_tasks/classroom_tasks_overload.tex
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
\documentclass{article}
|
||||||
|
\usepackage[utf8x]{inputenc}
|
||||||
|
\usepackage{ucs}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amsfonts}
|
||||||
|
\usepackage{marvosym}
|
||||||
|
\usepackage{wasysym}
|
||||||
|
\usepackage{upgreek}
|
||||||
|
\usepackage[english,russian]{babel}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{float}
|
||||||
|
\usepackage{textcomp}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{geometry}
|
||||||
|
\geometry{left=2cm}
|
||||||
|
\geometry{right=1.5cm}
|
||||||
|
\geometry{top=1cm}
|
||||||
|
\geometry{bottom=2cm}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{ccaption}
|
||||||
|
\usepackage{multicol}
|
||||||
|
\usepackage{fancyvrb}
|
||||||
|
|
||||||
|
\usepackage{listings}
|
||||||
|
%\setlength{\columnsep}{1.5cm}
|
||||||
|
%\setlength{\columnseprule}{0.2pt}
|
||||||
|
|
||||||
|
\usepackage{colortbl,graphicx,tikz}
|
||||||
|
\definecolor{X}{rgb}{.5,.5,.5}
|
||||||
|
|
||||||
|
\title{ДЗ. Работа с изображениями в формате \texttt{.ppm}}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
|
||||||
|
\lstset{
|
||||||
|
language=C++, % choose the language of the code
|
||||||
|
basicstyle=\linespread{1.1}\ttfamily,
|
||||||
|
columns=fixed,
|
||||||
|
fontadjust=true,
|
||||||
|
basewidth=0.5em,
|
||||||
|
keywordstyle=\color{blue}\bfseries,
|
||||||
|
commentstyle=\color{gray},
|
||||||
|
stringstyle=\ttfamily\color{orange!50!black},
|
||||||
|
showstringspaces=false,
|
||||||
|
%numbers=false, % where to put the line-numbers
|
||||||
|
numbersep=5pt,
|
||||||
|
numberstyle=\tiny\color{black},
|
||||||
|
numberfirstline=true,
|
||||||
|
stepnumber=1, % the step between two line-numbers.
|
||||||
|
numbersep=10pt, % how far the line-numbers are from the code
|
||||||
|
backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
|
||||||
|
showstringspaces=false, % underline spaces within strings
|
||||||
|
captionpos=b, % sets the caption-position to bottom
|
||||||
|
breaklines=true, % sets automatic line breaking
|
||||||
|
breakatwhitespace=true, % sets if automatic breaks should only happen at whitespace
|
||||||
|
xleftmargin=.2in,
|
||||||
|
extendedchars=\true,
|
||||||
|
keepspaces = true,
|
||||||
|
}
|
||||||
|
\lstset{literate=%
|
||||||
|
*{0}{{{\color{red!20!violet}0}}}1
|
||||||
|
{1}{{{\color{red!20!violet}1}}}1
|
||||||
|
{2}{{{\color{red!20!violet}2}}}1
|
||||||
|
{3}{{{\color{red!20!violet}3}}}1
|
||||||
|
{4}{{{\color{red!20!violet}4}}}1
|
||||||
|
{5}{{{\color{red!20!violet}5}}}1
|
||||||
|
{6}{{{\color{red!20!violet}6}}}1
|
||||||
|
{7}{{{\color{red!20!violet}7}}}1
|
||||||
|
{8}{{{\color{red!20!violet}8}}}1
|
||||||
|
{9}{{{\color{red!20!violet}9}}}1
|
||||||
|
}
|
||||||
|
|
||||||
|
\title{Семинар \#1: Введение в язык C++ (для тех, кто знает C). Классные задачи.\vspace{-5ex}}\date{}\maketitle
|
||||||
|
|
||||||
|
\section*{Hello world++}
|
||||||
|
Пишем первую программу на \texttt{C++}
|
||||||
|
\begin{lstlisting}
|
||||||
|
#include <cstdio>
|
||||||
|
int main() {
|
||||||
|
printf("Hello World++\n");
|
||||||
|
}
|
||||||
|
\end{lstlisting}
|
||||||
|
Все библиотеки из языка \texttt{C} можно использовать и в языке \texttt{C++}. Только название библиотеки без \texttt{.h} на конце и с символом \texttt{c} в начале:
|
||||||
|
\begin{verbatim}
|
||||||
|
<stdio.h> -------> <cstdio>
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
Для компиляции используйте компилятор \texttt{g++}. Вот так:
|
||||||
|
\begin{verbatim}
|
||||||
|
g++ helloworld.cpp
|
||||||
|
./a.out
|
||||||
|
\end{verbatim}
|
||||||
|
Или, если вы хотите установить у исполняемого файла своё имя за место \texttt{a.out}:
|
||||||
|
\begin{verbatim}
|
||||||
|
g++ -o hello helloworld.cpp
|
||||||
|
./hello
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Задача 1:} Скомпилируйте и запустите простейшую программу \texttt{00helloworld.cpp}.
|
||||||
|
\item \textbf{Задача 2:} Разберитесь в программе \texttt{01structnaming.cpp}. Скомпилируйте и запустите.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\section*{Тип bool}
|
||||||
|
В прошлом семестре, для хранения результатов логических операций, мы использовали целочисленные типы.\\
|
||||||
|
В языке \texttt{C++} есть встроенный тип \texttt{bool}, который может принимать 2 значения (\texttt{true} и \texttt{false}).
|
||||||
|
\begin{lstlisting}
|
||||||
|
#include <cstdio>
|
||||||
|
int main() {
|
||||||
|
bool a = true;
|
||||||
|
bool b = false;
|
||||||
|
bool c = a || b;
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
printf("Yes\n");
|
||||||
|
else
|
||||||
|
printf("No\n");
|
||||||
|
}
|
||||||
|
\end{lstlisting}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Задача 3:} Что напечатает эта программа? Скомпилируйте её и запустите (\texttt{02bool.cpp})
|
||||||
|
\item \textbf{Задача 4:} Напишите функцию, которая будет принимать на вход целое число и возвращать \texttt{true}, если число оканчивается на \texttt{0} и \texttt{false} иначе. Вызовите эту функцию из \texttt{main}.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\section*{Пространство имён}
|
||||||
|
\begin{lstlisting}
|
||||||
|
#include <cstdio>
|
||||||
|
// Определяем переменные, структуры, функции внутри пространства имён foo
|
||||||
|
namespace foo {
|
||||||
|
int a = 5;
|
||||||
|
int square(int x) {
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Чтобы получить доступ к ним вне пространства имён, нужно добавить к именам foo::
|
||||||
|
int main() {
|
||||||
|
printf("%d\n", foo::a);
|
||||||
|
}
|
||||||
|
\end{lstlisting}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Задача 5:} Возведите \texttt{foo::a} в квадрат с помощью функции \texttt{foo::square}.
|
||||||
|
\item \textbf{Задача 6:} Создайте своё пространство имён по имени \texttt{bar} и определите в нём переменную \texttt{a = 7}. Напечатайте значение этой переменной в \texttt{main}.
|
||||||
|
\item \textbf{Задача 7:} Сделайте задание в программе \texttt{03namespace.cpp}.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\section*{Ссылки}
|
||||||
|
Ссылка -- это переменная, которая является новым именем для существующего участка памяти.
|
||||||
|
\begin{lstlisting}
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int a = 10;
|
||||||
|
// Создадим ссылку r на переменную a
|
||||||
|
int& r = a;
|
||||||
|
// Теперь, если изменить r, то поменяется и a
|
||||||
|
r += 5;
|
||||||
|
printf("%d\n", a);
|
||||||
|
}
|
||||||
|
\end{lstlisting}
|
||||||
|
Ссылки часто используются для тех же целей, что и указатели (только со ссылкам работать удобнее).
|
||||||
|
В отличии от указателей, ссылки:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Должны всегда инициализироваться при создании
|
||||||
|
\item Не могут никуда не ссылаться (т.е. не могут равняться \texttt{NULL})
|
||||||
|
\item Их нельзя переприсвоить. При использовании оператора \texttt{=} со ссылками изменяется та переменная, на которую ссылка ссылается, а не сама ссылка.
|
||||||
|
\end{enumerate}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Задача 8:} Сделайте задание в файлах \texttt{04ref.cpp}, \texttt{05ref.cpp} и \texttt{06ref.cpp}.
|
||||||
|
\end{itemize}
|
||||||
|
\section*{Перегрузка функций}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Задача 9:} Сделайте задание в файлах \texttt{07function\_overload.cpp}, \texttt{08nulptr.cpp} и \texttt{09default\_arguments.cpp}.
|
||||||
|
\end{itemize}
|
||||||
|
\section*{Перегрузка операторов}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Задача 10:} Сделайте задание в файлах \texttt{10operator\_overload.cpp}, \texttt{11iostream.cpp} и \texttt{12iostream\_overload.cpp}.
|
||||||
|
\end{itemize}
|
||||||
|
\end{document}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Здравствуйте, это первый файл семестра по языку C++ (для тех, кто знаком с языком C)
|
||||||
|
|
||||||
|
Язык C++ создан на основе языка C и одним из приоритетов C++ является обратная совместимость с C
|
||||||
|
Поэтому почти любая программа на языке C будет работать и на языке C++
|
||||||
|
|
||||||
|
Однако, нужно помнить, что это разные языки. В C++ было добавлено огромное количество новых возможностей,
|
||||||
|
что сделало C++ возможно самым объёмным и мощным языком программирования.
|
||||||
|
|
||||||
|
C++ содержит в себе во много раз больше всего, чем язык C и пройти его за один семестр не представляется возможным,
|
||||||
|
но мы пройдём ключевые части этого языка.
|
||||||
|
|
||||||
|
|
||||||
|
Для компиляции программ на C++ будем использовать компилятор g++.
|
||||||
|
Скомпилируйте эту программу вот так:
|
||||||
|
g++ 00hello.cpp
|
||||||
|
|
||||||
|
И запустите вот так (для Windows):
|
||||||
|
a.exe
|
||||||
|
|
||||||
|
И запустите вот так (для Linux):
|
||||||
|
./a.out
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("Hello World of C++\n");
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Пространства имён - namespace
|
||||||
|
|
||||||
|
Определяем переменные/структуры/функции внутри пространства имён.
|
||||||
|
Давайте назовём его mipt
|
||||||
|
|
||||||
|
Чтобы получить доступ к этим переменным/структурам/функциям
|
||||||
|
вне пространства имён, нужно добавить к имени название пространства имён и оператор ::
|
||||||
|
В данном случае нужно добавить mipt::
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
int a = 5;
|
||||||
|
float b = 1.2;
|
||||||
|
|
||||||
|
int square(int x)
|
||||||
|
{
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%i\n", mipt::square(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Скомпилируйте программу и запустите, что она напечатает?
|
||||||
|
|
||||||
|
2) Что будет, если забыть написать mipt:: у названия функции square?
|
||||||
|
|
||||||
|
3) Передайте в функцию mipt::square переменную a из пространства имён mipt
|
||||||
|
|
||||||
|
4) Напишите функцию float average(float x, float y), которая будет принимать 2 числа
|
||||||
|
и возвращать их среднее арифметическое.
|
||||||
|
Поместите эту функцию в пространство имён mipt и вызовите эту функцию из main
|
||||||
|
|
||||||
|
5) Напечатайте среднее арифметическое от a и b, используя функцию average
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
int a = 5;
|
||||||
|
float b = 1.2;
|
||||||
|
|
||||||
|
int square(int x)
|
||||||
|
{
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float average(float x, float y)
|
||||||
|
{
|
||||||
|
return (x + y) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%i\n", mipt::square(mipt::a));
|
||||||
|
printf("%f\n", mipt::average(mipt::a, mipt::b));
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
В языке C при объявлении структуры struct Book создаётся тип по имени struct Book.
|
||||||
|
|
||||||
|
В языке C++ при объявлении структуры struct Book создаётся тип к которому
|
||||||
|
можно обращаться как по имени struct Book так и по имени Book
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[50];
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct Book a = {"Tom Sawyer", 280, 500};
|
||||||
|
|
||||||
|
Book b = {"War and Peace", 1200, 900};
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Определяем переменные/структуры/функции внутри пространства имён mipt
|
||||||
|
Затем к ним можно будет доступиться используя префикс mipt::
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[50];
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
void printBook(Book b)
|
||||||
|
{
|
||||||
|
printf("%s, pages: %d, price: %.2f\n", b.title, b.pages, b.price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
Структура Book и функция printBook определены в пространстве имён mipt
|
||||||
|
|
||||||
|
1) Создайте переменную типа структура Book и иницилизируйте
|
||||||
|
её значениями: "War and Peace", 1200, 900
|
||||||
|
|
||||||
|
2) Напечатайте созданную переменную с помощью функции printBook
|
||||||
|
*/
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[50];
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
void printBook(Book b)
|
||||||
|
{
|
||||||
|
printf("%s, pages: %d, price: %.2f\n", b.title, b.pages, b.price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
mipt::Book b = {"War and Peace", 1200, 900};
|
||||||
|
mipt::printBook(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
Структура Book и функция printBook определены в пространстве имён mipt
|
||||||
|
|
||||||
|
1) Создайте переменную типа структура Book и иницилизируйте
|
||||||
|
её значениями: "War and Peace", 1200, 900
|
||||||
|
|
||||||
|
2) Напечатайте созданную переменную с помощью функции printBook
|
||||||
|
*/
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Зачем вообще нужны пространства имён?
|
||||||
|
|
||||||
|
Представьте, что вы создаёте большую программу, исходный код который
|
||||||
|
содержит миллионы строк кода. Конечно, большая часть кода написана не вами,
|
||||||
|
так как вы используете библиотеки, написанные другими программистами.
|
||||||
|
|
||||||
|
Библиотекой можно назвать совокупность файлов исходного кода, нацеленных
|
||||||
|
на решение какой-либо задачи. Например, есть библиотека для работы с графикой
|
||||||
|
в которой содержатся функции/структуры/классы для работы с графикой.
|
||||||
|
|
||||||
|
Если вы подключаете несколько библиотек, то существует высокая вероятность,
|
||||||
|
что название чего-либо из одной библиотеки совпадёт с названием чего-то из другой библиотеки.
|
||||||
|
Это, конечно, приведёт к ошибке.
|
||||||
|
|
||||||
|
Чтобы этого избежать и используются пространства имён.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
int calculate(int x)
|
||||||
|
{
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace graphics
|
||||||
|
{
|
||||||
|
int a = 20;
|
||||||
|
|
||||||
|
int calculate(int x)
|
||||||
|
{
|
||||||
|
return x * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%i\n", audio::a);
|
||||||
|
printf("%i\n", graphics::a);
|
||||||
|
|
||||||
|
|
||||||
|
printf("%i\n", graphics::calculate(audio::calculate(graphics::a)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа?
|
||||||
|
*/
|
|
@ -0,0 +1,78 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Если вам очень не хочется постоянно писать названия пространства имён,
|
||||||
|
то вы можете использовать ключевое слово using
|
||||||
|
|
||||||
|
using namespace audio;
|
||||||
|
|
||||||
|
Это говорит о том, что начиная с этой строки audio:: перед именами писать больше не нужно
|
||||||
|
|
||||||
|
Это, конечно, полностью уничтожают всю пользу, которую приносят пространства имён.
|
||||||
|
То есть в больших проектах могут возникнуть ошибки, связанные с одинаковыми именами.
|
||||||
|
|
||||||
|
Так что так лучше не делать, а если и делать, то только в маленьких программах.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
int calculate(int x)
|
||||||
|
{
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace graphics
|
||||||
|
{
|
||||||
|
int a = 20;
|
||||||
|
|
||||||
|
int calculate(int x)
|
||||||
|
{
|
||||||
|
return x * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace network
|
||||||
|
{
|
||||||
|
int b = 20;
|
||||||
|
|
||||||
|
int solve(int x)
|
||||||
|
{
|
||||||
|
return x * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace audio;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%i\n", calculate(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа?
|
||||||
|
|
||||||
|
2) Если заменить using namespace audio на using namespace graphics, то что напечатает программа?
|
||||||
|
|
||||||
|
3) Что если одновременно использовать пространство имён audio и пространство имён graphics?
|
||||||
|
|
||||||
|
using namespace audio;
|
||||||
|
using namespace graphics;
|
||||||
|
|
||||||
|
Приведёт ли это к ошибке и, если да, то почему?
|
||||||
|
|
||||||
|
|
||||||
|
4) Что если одновременно использовать пространство имён audio и пространство имён network?
|
||||||
|
|
||||||
|
using namespace audio;
|
||||||
|
using namespace network;
|
||||||
|
|
||||||
|
Приведёт ли это к ошибке и, если да, то почему?
|
||||||
|
*/
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Все переменные/функции/структуры/классы стандартной библиотеки языка C++ содержатся в пространстве имён std
|
||||||
|
Рассмотрим, например, глобальную переменную cout, определённую в библиотеке iostream в пространстве имён std.
|
||||||
|
|
||||||
|
К этой переменной можно применять оператор <<
|
||||||
|
cout << объект
|
||||||
|
В результате этой операции объект напечатается на экран (если он может напечататься)
|
||||||
|
Результат оператора << также является cout, поэтому можно применять << несколько раз:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Например это выражение: cout << "Hello " << "World" << "\n";
|
||||||
|
|
||||||
|
1) Сначала напечатается "Hello " и на место cout << "Hello " подставится cout
|
||||||
|
Получтся cout << "World" << "\n";
|
||||||
|
|
||||||
|
2) Потом напечатется "World" и на место cout << "World" подставится cout
|
||||||
|
Получтся cout << "\n";
|
||||||
|
|
||||||
|
3) В конце напечатается перенос строки
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::cout << "Hello World\n";
|
||||||
|
std::cout << 5 << "\n";
|
||||||
|
|
||||||
|
int x = 10;
|
||||||
|
std::cout << 5 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Напечатайте на экран число 1.4, используя cout (количество печатаемых знаков после запятой неважно)
|
||||||
|
Обратите внимание, что при печати с cout не нужно указывать спецификатор типа как в printf.
|
||||||
|
cout сам понимает объект какого типа ему передаётся
|
||||||
|
|
||||||
|
2) Напечатайте фразу "I am x years old", только за место x нужно подставить значение
|
||||||
|
переменной x. В данной задаче получится "I am 10 years old". Используйте cout.
|
||||||
|
|
||||||
|
3) Напечатайте на экран числа от 1 до 20, разделённые пробелом. Используйте cout
|
||||||
|
|
||||||
|
4) Вместо \n для переноса строки можно использовать endl - специальный объект из
|
||||||
|
пространства имён std.
|
||||||
|
Если мы передаём его объекту cout через оператор << то печатается перенос строки
|
||||||
|
|
||||||
|
Замените все переносы строк с \n на endl
|
||||||
|
std::cout << 5 << "\n"; --> std::cout << 5 << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
На самом деле std::endl работает медленней, чем \n, так как он помимо печати делает flush
|
||||||
|
Поэтому, если важна скорость печати в буфер, то лучше использовать \n
|
||||||
|
|
||||||
|
|
||||||
|
5) Что будет если не написать std:: перед одним из cout?
|
||||||
|
|
||||||
|
6) Используйте using namespace std; и избавьтесь от надоедливых std:: перед cout и endl
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << 1.4 << endl;
|
||||||
|
|
||||||
|
int x = 10;
|
||||||
|
cout << "I am " << x << " years old" << endl;
|
||||||
|
|
||||||
|
for (int i = 1; i <= 20; ++i)
|
||||||
|
cout << i << " ";
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
/*
|
||||||
|
В пространстве имён std очень много разных имён. Если мы добавим их всех, используя
|
||||||
|
using namespace std;
|
||||||
|
то это может привести к проблеме.
|
||||||
|
Одно из имён из std может совпасть с названием нашего объекта и это может привести к ошибке.
|
||||||
|
|
||||||
|
Так что лучше такую возможность не использовать.
|
||||||
|
|
||||||
|
Но можно добавить только одно имя так:
|
||||||
|
using std::cout;
|
||||||
|
Начиная с этого момента можно писать просто cout.
|
||||||
|
Но для всех остальных объектов из std вы должны продолжать писать std::
|
||||||
|
*/
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << "Hello World" << std::endl;
|
||||||
|
cout << 5 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Добавить endl в нашу область видимости, также как и cout
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Счтиывание из стандартного входа
|
||||||
|
|
||||||
|
Рассмотрим глобальную переменную cin, определённую в библиотеке iostream в пространстве имён std.
|
||||||
|
|
||||||
|
К этой переменной можно применять оператор >>
|
||||||
|
cin >> объект
|
||||||
|
В результате этой операции объект считается с экрана (если он может быть считан)
|
||||||
|
Результат оператора >> также является cin, поэтому можно применять >> несколько раз:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Например это выражение: cin >> a >> b;
|
||||||
|
|
||||||
|
1) Сначала считается переменная a и на место cin >> a подставится cin
|
||||||
|
Получтся cin >> b;
|
||||||
|
|
||||||
|
2) Потом считается переменная b
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a, b;
|
||||||
|
std::cin >> a >> b;
|
||||||
|
std::cout << a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа, если на вход передать числа 10 и 20?
|
||||||
|
|
||||||
|
2) Напишите программу, которая будет считывать два вещественных числа и печатать их среднее геометрическое
|
||||||
|
Функция корня sqrt есть в библиотеке <cmath>
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
float a, b;
|
||||||
|
std::cin >> a >> b;
|
||||||
|
std::cout << sqrt(a * b);
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Язык C++ обратно совместим с языком C. То есть почти любая программа на C будет работать на C++
|
||||||
|
Эта программа будет работать.
|
||||||
|
|
||||||
|
Обратите внимания, для имён, пришедших из языка C использовать std:: не обязательно
|
||||||
|
|
||||||
|
Программа работает, несмотря на то, что мы используем библиотечные
|
||||||
|
функции printf и sqrt без указания пространства имён std.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%f", sqrt(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Задача:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа?
|
||||||
|
|
||||||
|
2) Использование библиотечных функций без std опасно, так как может привести к ошибкам,
|
||||||
|
связанных с совпадением имён. Помните, что большая программа может иметь миллионы
|
||||||
|
строк кода и совпадение ваших имен и библиотечных имён очень вероятно.
|
||||||
|
|
||||||
|
|
||||||
|
Напишите следующую функцию перед функцией main
|
||||||
|
|
||||||
|
int sqrt(int x)
|
||||||
|
{
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Что теперь напечатает программа? Объясните результат.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Желательно всё равно использовать std даже для имён пришедших из языка C
|
||||||
|
|
||||||
|
Также были изменены названия библиотек:
|
||||||
|
stdio.h --> cstdio
|
||||||
|
math.h --> cmath
|
||||||
|
cmath означает, что это библиотека языка C под названием math, поэтому и cmath
|
||||||
|
|
||||||
|
Они почти не отличаются от предыдущих, но при программировании на C++
|
||||||
|
желательно использовать именно эти библиотеки.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::printf("%f", std::sqrt(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Задача:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа?
|
||||||
|
|
||||||
|
2) Напишите следующую функцию перед функцией main
|
||||||
|
|
||||||
|
int sqrt(int x)
|
||||||
|
{
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Что теперь напечатает программа? Объясните результат.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
60
seminar01_overload/classroom_tasks/code/01ref/00ref.cpp
Normal file
60
seminar01_overload/classroom_tasks/code/01ref/00ref.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
В C++ вводится понятие нового типа под названием Ссылка
|
||||||
|
|
||||||
|
Ссылку можно рассматривать как новое имя для объекта.
|
||||||
|
Ссылку также можно рассматривать как удобный указатель, который автоматически разыменовывается
|
||||||
|
(На самом деле под капотом ссылка и является указателем)
|
||||||
|
|
||||||
|
Ссылка объявляется с помощью значка & после имени типа.
|
||||||
|
Не стоит путать & используемый при объявлении ссылки с & используемым для нахождения адреса переменной.
|
||||||
|
Это разные &
|
||||||
|
|
||||||
|
|
||||||
|
Пусть есть переменная a
|
||||||
|
int a = 10;
|
||||||
|
Давайте создадим указатель и ссылку на эту переменную и увеличим её на 1 с помощью указателя/ссылки
|
||||||
|
|
||||||
|
Используем указатель: Используем ссылку:
|
||||||
|
int* p = &a; int& r = a;
|
||||||
|
*p += 1; r += 1;
|
||||||
|
|
||||||
|
|
||||||
|
Ссылкой пользоваться удобно, так как:
|
||||||
|
|
||||||
|
1) При создании ссылки нам не нужно передавать ей адрес
|
||||||
|
Просто передаём ей саму переменную, а ссылка уже сама находит её адрес
|
||||||
|
|
||||||
|
2) Не нужно её разыменовывать, она всегда разыменовывается сама
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
int& r = a;
|
||||||
|
r += 1;
|
||||||
|
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Используйте ссылку r, чтобы увеличить a в 2 раза
|
||||||
|
Проверьте, как изменилась a, напечатав её
|
||||||
|
|
||||||
|
|
||||||
|
2) Используйте ссылку r, чтобы присвоить a число 100
|
||||||
|
Проверьте, как изменилась a, напечатав её
|
||||||
|
|
||||||
|
|
||||||
|
3) Создайте переменную b типа float, равную 1.5
|
||||||
|
Создайте ссылку на b и используйте эту ссылку, чтобы возвести b в квадрат
|
||||||
|
|
||||||
|
*/
|
39
seminar01_overload/classroom_tasks/code/01ref/01ref.cpp
Normal file
39
seminar01_overload/classroom_tasks/code/01ref/01ref.cpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Пусть у нас есть некоторый объект, например
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
После того как мы создали ссылку на этот объект
|
||||||
|
int& r = a;
|
||||||
|
|
||||||
|
Все (почти) операции применяемые к ссылке r применяются на самом деле к объекту a
|
||||||
|
Как будто у одного объекта теперь два имени a и r
|
||||||
|
Поэтому можно сказать, что ссылка это новое имя для объекта
|
||||||
|
|
||||||
|
При этом изменить саму ссылку (например, чтобы она начала указывать на другое имя) нельзя
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
int& r = a;
|
||||||
|
|
||||||
|
|
||||||
|
r += 5; // Прибавим к a число 5
|
||||||
|
r *= 2; // Умножим a на 2
|
||||||
|
cout << r << endl; // Напечатаем a
|
||||||
|
cout << sizeof(r) << endl; // Напечатаем размер a
|
||||||
|
cout << &r << endl; // Напечатаем адрес a
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Чему будет равно значение a в конце этой программы
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
43
seminar01_overload/classroom_tasks/code/01ref/02ref.cpp
Normal file
43
seminar01_overload/classroom_tasks/code/01ref/02ref.cpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Пусть у нас есть некоторый объект, например
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
После того как мы создали ссылку на этот объект
|
||||||
|
int& r = a;
|
||||||
|
|
||||||
|
Все (почти) операции применяемые к ссылке r применяются на самом деле к объекту a
|
||||||
|
Как будто у одного объекта теперь два имени a и r
|
||||||
|
Поэтому можно сказать, что ссылка это новое имя для объекта
|
||||||
|
|
||||||
|
При этом изменить саму ссылку (например, чтобы она начала указывать на другое имя) нельзя
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a[5] = {10, 20, 30, 40, 50};
|
||||||
|
|
||||||
|
int& b = a[1];
|
||||||
|
b += 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
cout << a[i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Что будет содержать массив a в конце данной программы?
|
||||||
|
|
||||||
|
2) Создайте ссылку, которая будет указывать на последний элемент массива a
|
||||||
|
Используйте эту ссылку, чтобы умножить последний элемент массива на 2
|
||||||
|
Напечатайте этот массив
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Несмотря на то, что ссылки и указатели во многом похожи, у них есть и много больших отличий.
|
||||||
|
(помимо разной инициализации и того, что ссылку не нужно постоянно разыменовывать)
|
||||||
|
|
||||||
|
|
||||||
|
Различие 1)
|
||||||
|
Указатель можно создать без инициализации вот так:
|
||||||
|
int* p;
|
||||||
|
В этом случае в p будет храниться произвольный адрес.
|
||||||
|
Разыменовывать такой указатель, не задав его значение адресом какого-либо объекта,
|
||||||
|
очень опасно, это может привести к сложновыявляемым ошибкам.
|
||||||
|
|
||||||
|
Ссылку нельзя создать без инициализации, то есть так нельзя:
|
||||||
|
int& r;
|
||||||
|
При создании ссылки нужно указать на что она будет указывать
|
||||||
|
|
||||||
|
|
||||||
|
Различие 2)
|
||||||
|
Указатель можно приравнять нулевому значению
|
||||||
|
В C++ вводится специальное нулевое значение для указателя nullptr
|
||||||
|
Вместо NULL, который был просто равен числу 0. В C++ лучше использовать nullptr
|
||||||
|
Разыменование нулевого указателя также приведёт к ошибке.
|
||||||
|
|
||||||
|
Ссылку нельзя присвоить никакому нулевому значению
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Попробуйте создать:
|
||||||
|
a) Указатель без инициализации
|
||||||
|
б) Ссылку без инициализации
|
||||||
|
|
||||||
|
в) Указатель, равнуй нулевому значению nullptr
|
||||||
|
г) Ссылку, равную нулю
|
||||||
|
|
||||||
|
Скомпилируется ли программа в этих 4-х случаях?
|
||||||
|
*/
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Несмотря на то, что ссылки и указатели во многом похожи, у них есть и много больших отличий.
|
||||||
|
(помимо разной инициализации и того, что ссылку не нужно постоянно разыменовывать)
|
||||||
|
|
||||||
|
|
||||||
|
Различие 3) Указатель можно переприсвоить. Если указатель сначала указывал в одно место,
|
||||||
|
например, на переменную a, то можно просто написать
|
||||||
|
p = &b;
|
||||||
|
и указатель станет указывать на переменную b.
|
||||||
|
|
||||||
|
Со ссылками такое не пройдёт, они всегда указывают на тот объект, который был указан при создании ссылки
|
||||||
|
При попытке изменить это и написать что-то вроде
|
||||||
|
r = b;
|
||||||
|
ссылка автоматически разыменуется и присваивание произойдёт к тому, на что указывала ссылка
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
int b = 20;
|
||||||
|
|
||||||
|
int* p = &a;
|
||||||
|
*p += 1;
|
||||||
|
p = &b;
|
||||||
|
*p += 1;
|
||||||
|
|
||||||
|
cout << a << " " << b << endl;
|
||||||
|
|
||||||
|
|
||||||
|
int& r = a;
|
||||||
|
r += 1;
|
||||||
|
r = b;
|
||||||
|
r += 1;
|
||||||
|
|
||||||
|
cout << a << " " << b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Попробуйте понять, что напечатает программа без её запуска
|
||||||
|
|
||||||
|
2) Запустите программу, проверьте ваши догадки и объясните результат
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Несмотря на то, что ссылки и указатели во многом похожи, у них есть и много больших отличий.
|
||||||
|
(помимо разной инициализации и того, что ссылку не нужно постоянно разыменовывать)
|
||||||
|
|
||||||
|
Различие 4)
|
||||||
|
Арифметика указателей.
|
||||||
|
К указателю можно прибавлять/отнимать целые числа. Можно вычесть 2 указателя.
|
||||||
|
Можно применить [] к указателю. При всём этом, желательно, чтобы указатель указывал на элемент массива.
|
||||||
|
Неаккуратное использование арифметики указателей может привести к ошибкам.
|
||||||
|
Например, можно прибавить к указателю не то число и выйти за пределы массива.
|
||||||
|
|
||||||
|
|
||||||
|
Ничего такого со ссылками сделать нельзя.
|
||||||
|
При попытке прибавить к ссылке число, оно прибавится к той переменной, на которую указывает ссылка.
|
||||||
|
Так как ссылка автоматически разыменуется.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a[5] = {10, 20, 30, 40, 50};
|
||||||
|
|
||||||
|
int* p = &a[0];
|
||||||
|
|
||||||
|
p += 1; // Увеличиваем указатель
|
||||||
|
*p += 1; // Увеличиваем то, на что указывает указатель
|
||||||
|
|
||||||
|
|
||||||
|
int& r = a[0];
|
||||||
|
|
||||||
|
r += 1; // Увеличиваем то, на что указывает ссылка (она автоматически разыменовывается)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Чему будет равен массив a в конце данной программы
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Несмотря на то, что ссылки и указатели во многом похожи, у них есть и много больших отличий.
|
||||||
|
|
||||||
|
Различие 5)
|
||||||
|
Ссылки это не совсем обычный объект, некоторые операции с ними запрещены:
|
||||||
|
|
||||||
|
Ссылку нельзя сделать элементом массива
|
||||||
|
|
||||||
|
Нельзя получить адрес ссылки (если применим & то вернётся адрес того объекта на который указывет ссылка)
|
||||||
|
Нельзя создать укатель на ссылку
|
||||||
|
Нельзя создать ссылку на ссылку
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
int x = 1;
|
||||||
|
int y = 2;
|
||||||
|
int z = 2;
|
||||||
|
|
||||||
|
int& a[3] = {x, y, z}; // Ошибка, создать массив из ссылок не получится
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Можно ли инициализировать ссылку на int простым числом вот так:
|
||||||
|
int& r = 5;
|
||||||
|
|
||||||
|
|
||||||
|
2) Ссылку на ссылку создать нельзя, но код ниже почему-то работает.
|
||||||
|
Объясните почему этот код работает
|
||||||
|
|
||||||
|
int a = 10;
|
||||||
|
int& r1 = a;
|
||||||
|
int& r2 = r1;
|
||||||
|
|
||||||
|
r2 += 1;
|
||||||
|
|
||||||
|
*/
|
69
seminar01_overload/classroom_tasks/code/01ref/07func_ref.cpp
Normal file
69
seminar01_overload/classroom_tasks/code/01ref/07func_ref.cpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
В 90% случаях ссылки используются для того чтобы передать что либо в функцию
|
||||||
|
Часто нам хочется передать переменную в функцию и изменить её там (внутри функции)
|
||||||
|
Это можно делать и с помощью указателей, но с помощью ссылок это делать гораздо удобней
|
||||||
|
Рассмотрим два эквивалентных участка кода:
|
||||||
|
|
||||||
|
Передаём по указателю: Передаём по ссылке:
|
||||||
|
|
||||||
|
void sqr(int* p) void sqr(int& r)
|
||||||
|
{ {
|
||||||
|
*p = *p * *p; r = r * r;
|
||||||
|
} }
|
||||||
|
|
||||||
|
int main() int main()
|
||||||
|
{ {
|
||||||
|
int a = 5; int a = 5;
|
||||||
|
sqr(&a); sqr(a);
|
||||||
|
cout << a << endl; cout << a << endl;
|
||||||
|
} }
|
||||||
|
|
||||||
|
|
||||||
|
Обратите внимание на 2 вещи:
|
||||||
|
1) Ссылку не нужно разыменовывать внутри функции, это происходит автоматически
|
||||||
|
|
||||||
|
2) При передаче в функцию, не нужно передавать адрес переменной
|
||||||
|
Нужно передать саму переменную, компилятор сам вычислит её адрес
|
||||||
|
|
||||||
|
При этом копирования объекта a в функцию не происходит,
|
||||||
|
ссылки работают также быстро как и указатели
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sqr(int& r)
|
||||||
|
{
|
||||||
|
r = r * r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 5;
|
||||||
|
sqr(a);
|
||||||
|
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Напишите функцию void inc(int& x), которая должна принимать объект типа int
|
||||||
|
и увеличивать его на 1
|
||||||
|
Вызовите эту функцию из main и протестируйте её работу
|
||||||
|
|
||||||
|
2) Напишите функцию void normalize(float& x, float& y), которая должна принимать
|
||||||
|
2 объекта типа float и нормализировать их. То есть делить их на некоторое число,
|
||||||
|
так чтобы было x*x + y*y == 1
|
||||||
|
|
||||||
|
Для этого x и y нужно разделить на sqrt(x*x + y*y)
|
||||||
|
|
||||||
|
|
||||||
|
3) Можно ли передать в функцию sqr не переменную, а число?
|
||||||
|
То есть, можно ли написать так:
|
||||||
|
sqr(5)
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
void inc(int& x)
|
||||||
|
{
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize(float& x, float& y)
|
||||||
|
{
|
||||||
|
float norm = std::sqrt(x * x + y * y);
|
||||||
|
x /= norm;
|
||||||
|
y /= norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 5;
|
||||||
|
inc(a);
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
float x = 9, y = 6;
|
||||||
|
normalize(x, y);
|
||||||
|
cout << x << " " << y << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Напишите функцию void inc(int& x), которая должна принимать объект типа int
|
||||||
|
и увеличивать его на 1
|
||||||
|
Вызовите эту функцию из main и протестируйте её работу
|
||||||
|
|
||||||
|
2) Напишите функцию void normalize(float& x, float& y), которая должна принимать
|
||||||
|
2 объекта типа float и нормализировать их. То есть делить их на некоторое число,
|
||||||
|
так чтобы было x*x + y*y == 1
|
||||||
|
|
||||||
|
Для этого x и y нужно разделить на sqrt(x*x + y*y)
|
||||||
|
|
||||||
|
|
||||||
|
3) Можно ли передать в функцию sqr не переменную, а число?
|
||||||
|
То есть, можно ли написать так:
|
||||||
|
sqr(5)
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,81 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Чаще всего по ссылке в функцию передаются объекты структур и классов
|
||||||
|
|
||||||
|
Даже если мы не хотим менять объект внутри функции, мы всё-равно можем
|
||||||
|
захотеть передать его по ссылке, так как передача по ссылке не копирует объект,
|
||||||
|
следовательно это гораздо более эффективно
|
||||||
|
|
||||||
|
В этом случае передаём по константной ссылке (по аналогии с константным указателем)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void increasePrice(Book& b, float value)
|
||||||
|
{
|
||||||
|
b.price += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBook(Book& b)
|
||||||
|
{
|
||||||
|
cout << b.title << ", pages = " << b.pages << ", price = " << b.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book b = {"War and Peace", 1200, 900};
|
||||||
|
|
||||||
|
printBook(b);
|
||||||
|
increasePrice(b, 100);
|
||||||
|
printBook(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Тот же самый код с использованием указателей выглядел бы так:
|
||||||
|
|
||||||
|
void increasePrice(Book* b, float value)
|
||||||
|
{
|
||||||
|
b->price += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBook(const Book* b)
|
||||||
|
{
|
||||||
|
cout << b->title << ", pages = " << b->pages << ", price = " << b->price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book b = {"War and Peace", 1200, 900};
|
||||||
|
|
||||||
|
printBook(&b);
|
||||||
|
increasePrice(b, 100);
|
||||||
|
printBook(&b);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Напишите функцию addPage, которая бы принимала структуру Book по ссылке
|
||||||
|
и увеличивала количество страниц на 1
|
||||||
|
Протестируйте эту функцию в main
|
||||||
|
|
||||||
|
2) Напишите функцию changeFirstLetter, которая бы принимала структуру Book по ссылке
|
||||||
|
и изменяла первую букву в названии на букву A
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
void addPage(Book& b)
|
||||||
|
{
|
||||||
|
b.pages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeFirstLetter(Book& b)
|
||||||
|
{
|
||||||
|
b.title[0] = 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBook(const Book& b)
|
||||||
|
{
|
||||||
|
cout << b.title << ", pages = " << b.pages << ", price = " << b.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book b = {"War and Peace", 1200, 900};
|
||||||
|
|
||||||
|
printBook(b);
|
||||||
|
|
||||||
|
addPage(b);
|
||||||
|
printBook(b);
|
||||||
|
|
||||||
|
changeFirstLetter(b);
|
||||||
|
printBook(b);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ссылки, как и указатели используются для передачи объектов в функции
|
||||||
|
|
||||||
|
Рассмотрим три функции
|
||||||
|
|
||||||
|
incByValue - принимаем объект по значению
|
||||||
|
В этом случае объект копируется и функция работает с копией
|
||||||
|
|
||||||
|
incByPointer - принимаем объект по адресу
|
||||||
|
В этом случае внутри функции создаётся указатель, и в этот указатель
|
||||||
|
мы передаём адрес нашего объекта
|
||||||
|
|
||||||
|
incByReference - принимаем объект по ссылке
|
||||||
|
В этом случае происходит всё примерно то же самое, что и в случае incByPointer
|
||||||
|
Только с гораздо более приятным синтаксисом
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void incByValue(int a)
|
||||||
|
{
|
||||||
|
a += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void incByPointer(int* p)
|
||||||
|
{
|
||||||
|
*p += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void incByReference(int& a)
|
||||||
|
{
|
||||||
|
a += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
cout << "1) Initial a = " << a << endl
|
||||||
|
|
||||||
|
incByValue(a);
|
||||||
|
cout << "2) After incByValue a = " << a << endl;
|
||||||
|
|
||||||
|
incByPointer(&a);
|
||||||
|
cout << "3) After incByPointer a = " << a << endl
|
||||||
|
|
||||||
|
incByReference(a);
|
||||||
|
cout << "4) After incByReference a = " << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Напишите функции:
|
||||||
|
|
||||||
|
cubeByPointer(int* p) - принимет число по указателю и возводит это число в куб
|
||||||
|
cubeByReference(int& a) - принимет число по ссылке и возводит это число в куб
|
||||||
|
|
||||||
|
Протестируйте эти функции в main
|
||||||
|
|
||||||
|
|
||||||
|
2) Написать функции:
|
||||||
|
|
||||||
|
swapByPointer(int* pa, int* pb) - принимает 2 числа по указателю и обменивает их значения
|
||||||
|
swap(int& pa, int& pb) - принимает 2 числа по ссылке и обменивает их значения
|
||||||
|
|
||||||
|
Протестируйте эти функции в main
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,54 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
void cubeByPointer(int* p)
|
||||||
|
{
|
||||||
|
*p = *p * *p * *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cubeByReference(int& a)
|
||||||
|
{
|
||||||
|
a = a * a * a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void swapByPointer(int* pa, int* pb)
|
||||||
|
{
|
||||||
|
int temp = *pa;
|
||||||
|
*pa = *pb;
|
||||||
|
*pb = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swapByReference(int& a, int& b)
|
||||||
|
{
|
||||||
|
int temp = a;
|
||||||
|
a = b;
|
||||||
|
b = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 5;
|
||||||
|
cubeByPointer(&a);
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
a = 5;
|
||||||
|
cubeByReference(a);
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int x = 10, y = 20;
|
||||||
|
swapByPointer(&x, &y);
|
||||||
|
cout << x << " " << y << endl;
|
||||||
|
|
||||||
|
|
||||||
|
x = 10;
|
||||||
|
y = 20;
|
||||||
|
swapByReference(x, y);
|
||||||
|
cout << x << " " << y << endl;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Константные ссылки можно создать, используя ключевое слово const
|
||||||
|
|
||||||
|
int a = 10;
|
||||||
|
const int& r = a;
|
||||||
|
|
||||||
|
Это означает, что a нельзя будет изменить по этой ссылке
|
||||||
|
То есть поменять a, используя ссылку r будет нельзя:
|
||||||
|
r += 1; // Ошибка!
|
||||||
|
a += 1; // OK
|
||||||
|
|
||||||
|
|
||||||
|
Важным неочевидным отличием константных ссылок от обычных ссылок является то, что обычные ссылки
|
||||||
|
можно инициализировать только объектами, которые уже храняться в памяти (например, переменными).
|
||||||
|
|
||||||
|
int& r1 = a; // OK
|
||||||
|
int& r2 = 5; // Ошибка
|
||||||
|
|
||||||
|
Константные ссылки можно инициализировать чем угодно (нужно только чтобы тип совпадал)
|
||||||
|
|
||||||
|
const int& cr1 = a; // OK
|
||||||
|
const int& cr2 = 5; // OK
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
const int& r = a;
|
||||||
|
|
||||||
|
|
||||||
|
int& r1 = 20; // Это не будет компилироваться
|
||||||
|
const int& r2 = 20 // Тут всё ОК
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Можно ли инициализировать ссылку таким образом?
|
||||||
|
float& r = std::sqrt(2);
|
||||||
|
|
||||||
|
Можно ли инициализировать константную ссылку таким образом?
|
||||||
|
const float& r = std::sqrt(2);
|
||||||
|
|
||||||
|
|
||||||
|
2) Пусть есть функция:
|
||||||
|
|
||||||
|
void printAgeV(int x)
|
||||||
|
{
|
||||||
|
cout << "My age is " << x << " years" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Можно ли вызвать её так?
|
||||||
|
int a = 10;
|
||||||
|
printAgeV(a)
|
||||||
|
|
||||||
|
Можно ли вызвать её так?
|
||||||
|
printAgeV(20)
|
||||||
|
|
||||||
|
|
||||||
|
3) Пусть есть функция:
|
||||||
|
|
||||||
|
void printAgeR(int& x)
|
||||||
|
{
|
||||||
|
cout << "My age is " << x << " years" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Можно ли вызвать её так?
|
||||||
|
int a = 10;
|
||||||
|
printAgeR(a)
|
||||||
|
|
||||||
|
Можно ли вызвать её так?
|
||||||
|
printAgeR(20)
|
||||||
|
|
||||||
|
|
||||||
|
4) Пусть есть функция:
|
||||||
|
|
||||||
|
void printAgeCR(const int& x)
|
||||||
|
{
|
||||||
|
cout << "My age is " << x << " years" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Можно ли вызвать её так?
|
||||||
|
int a = 10;
|
||||||
|
printAgeCR(a)
|
||||||
|
|
||||||
|
Можно ли вызвать её так?
|
||||||
|
printAgeCR(20)
|
||||||
|
*/
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Константные ссылки нужны прежде всего, чтобы передавать большие объекты в функции, внутри которых они не должны меняться
|
||||||
|
|
||||||
|
Рассмотрим структуру Book, чей размер более 100 байт
|
||||||
|
|
||||||
|
|
||||||
|
1) При передаче такой структуры в функцию по значению, как это происходит в функции printBookV,
|
||||||
|
вся структура будет копироваться внутрь функции и это очень медленно. Так делать не стоит.
|
||||||
|
|
||||||
|
|
||||||
|
2) При передаче такой структуры в функцию по обычной ссылке, как это происходит в функции printBookR, структура не копируется
|
||||||
|
На самом деле, под капотом внутрь функции копируется адрес структуры.
|
||||||
|
Адрес намного меньше самой структуры, поэтому это копирование работает намного быстрее.
|
||||||
|
|
||||||
|
Но возникает проблема с тем, что структура внутри такой функции может поменяться.
|
||||||
|
В реальной ситуации, если функций много и они большие, уследить за тем меняется ли аргументы внутри функций становится проблематично.
|
||||||
|
|
||||||
|
|
||||||
|
3) При передаче такой структуры в функцию по константной ссылке, как это происходит в функции printBookCR, структура не копируется.
|
||||||
|
Плюс к этому мы можем быть уверены, что внутри функции наша структура не поменяется и это сильно упрощает понимание программы.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void printBookV(Book b)
|
||||||
|
{
|
||||||
|
cout << b.title << ", pages = " << b.pages << ", price = " << b.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printBookR(Book& b)
|
||||||
|
{
|
||||||
|
cout << b.title << ", pages = " << b.pages << ", price = " << b.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printBookCR(const Book& b)
|
||||||
|
{
|
||||||
|
cout << b.title << ", pages = " << b.pages << ", price = " << b.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book b = {"War and Peace", 1200, 900};
|
||||||
|
|
||||||
|
printBookV(b);
|
||||||
|
printBookR(b);
|
||||||
|
printBookCR(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ссылки можно и возвращать из функции
|
||||||
|
Например, функция get возвращает ссылку на глобальную переменную x
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int x = 10;
|
||||||
|
|
||||||
|
|
||||||
|
int& get()
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << x << endl;
|
||||||
|
cout << get() << endl;
|
||||||
|
|
||||||
|
get() += 1;
|
||||||
|
cout << x << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
С указателями аналогичный код выглядел бы так:
|
||||||
|
|
||||||
|
|
||||||
|
int x = 10;
|
||||||
|
|
||||||
|
int* get()
|
||||||
|
{
|
||||||
|
return &x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << x << endl;
|
||||||
|
cout << *get() << endl;
|
||||||
|
|
||||||
|
*get() += 1;
|
||||||
|
cout << x << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ссылки можно и возвращать из функции
|
||||||
|
|
||||||
|
Но при этом нужно следить за тем, чтобы функция не вернула ссылку на локальную переменную, как это происходит в данном примере.
|
||||||
|
После завершения функции, переменная x удалится, так как она была определена внутри функции.
|
||||||
|
|
||||||
|
В результате, внутри функции main мы попробуем доступиться к области памяти, в которой раньше лежала переменная x.
|
||||||
|
Это приведёт к ошибке
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int& get()
|
||||||
|
{
|
||||||
|
int x = 10;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << get() << endl;
|
||||||
|
|
||||||
|
get() += 1;
|
||||||
|
cout << get() << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Аналогичная ошибка может произойти и при работе с обычными указателями:
|
||||||
|
|
||||||
|
int* get()
|
||||||
|
{
|
||||||
|
int x = 10;
|
||||||
|
return &x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << *get() << endl;
|
||||||
|
|
||||||
|
*get() += 1;
|
||||||
|
cout << *get() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ссылки можно и возвращать из функции
|
||||||
|
Например, функция increase принимает ссылку, увеличивет то, на что указывает эта ссылка на 1
|
||||||
|
и возвращает эту ссылку
|
||||||
|
|
||||||
|
При этом никакого копирование самой переменной a в функцию и из функции не происходит
|
||||||
|
*/
|
||||||
|
|
||||||
|
int& increase(int& r)
|
||||||
|
{
|
||||||
|
r += 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
|
||||||
|
cout << "1) a = " << a << endl;
|
||||||
|
|
||||||
|
increase(a);
|
||||||
|
cout << "2) a = " << a << endl;
|
||||||
|
|
||||||
|
increase(a) += 7;
|
||||||
|
cout << "3) a = " << a << endl;
|
||||||
|
|
||||||
|
increase(increase(increase(a)));
|
||||||
|
cout << "4) a = " << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Что напечатает данная программа?
|
||||||
|
*/
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите функцию multiplyBy2, которая принимает число по ссылке и увеличивает его в 2 раза
|
||||||
|
Вызовите эту функцию из функции main
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
void multiplyBy2(int& a)
|
||||||
|
{
|
||||||
|
a *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int x = 10;
|
||||||
|
multiplyBy2(x);
|
||||||
|
cout << x << endl;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите функцию sumAndSave, которая должна принимать 3 аргумента
|
||||||
|
Первые два аргумента по значению
|
||||||
|
Третий аргумент по ссылке
|
||||||
|
|
||||||
|
Функция должна складывать первые 2 аргумента и сохранять результат по третей ссылке
|
||||||
|
|
||||||
|
Вызовите эту функцию из функции main
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите функцию sumAndSave, которая должна принимать 3 аргумента
|
||||||
|
Первые два аргумента по значению
|
||||||
|
Третий аргумент по ссылке
|
||||||
|
|
||||||
|
Функция должна складывать первые 2 аргумента и сохранять результат по третей ссылке
|
||||||
|
|
||||||
|
Вызовите эту функцию из функции main
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sumAndSave(int a, int b, int& c)
|
||||||
|
{
|
||||||
|
c = a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int x = 10, y = 20;
|
||||||
|
int z;
|
||||||
|
|
||||||
|
sumAndSave(x, y, z);
|
||||||
|
cout << z << endl;
|
||||||
|
|
||||||
|
|
||||||
|
sumAndSave(70, 80, z);
|
||||||
|
cout << z << endl;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите функцию
|
||||||
|
|
||||||
|
void calculateLetters(char str[], int& numLetters)
|
||||||
|
|
||||||
|
Которая будет принимать на вход строку и считать количество строчных букв в этой строке
|
||||||
|
Строчные буквы - это символы от 'a' и до 'z'
|
||||||
|
|
||||||
|
Например, вызов calculateLetters("ab54AB,gd1:e", x) должен сохранить число 5 в переменную x
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
int x;
|
||||||
|
calculateLetters("ab54AB,gd1:e", x);
|
||||||
|
cout << x << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void calculateLetters(char str[], int& numLetters)
|
||||||
|
{
|
||||||
|
numLetters = 0;
|
||||||
|
for (int i = 0; str[i] != '\0'; ++i)
|
||||||
|
{
|
||||||
|
if (str[i] >= 'a' && str[i] <= 'z')
|
||||||
|
numLetters += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
calculateLetters("ab54AB,gd1:e", x);
|
||||||
|
cout << x << endl;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Это программа на языке C и компилировать её надо так:
|
||||||
|
gcc 00cfunctions.c
|
||||||
|
|
||||||
|
|
||||||
|
Известно, что в языке C нельзя создать две функции с одинаковым названием
|
||||||
|
Но часто требуется написать функции, которые будут делать похожие вещи, но для разных типов данных.
|
||||||
|
Простейший пример -- математические функции для разных численных типов данных
|
||||||
|
|
||||||
|
В языке C эта проблема решается так, что функциям даются немного различающиеся имена
|
||||||
|
|
||||||
|
|
||||||
|
В данном примере мы создали функции для вычисления абсолютного значения для типов int и double
|
||||||
|
Всё работает хорошо, пока мы соблюдаем типы данных и функции
|
||||||
|
|
||||||
|
Но стоит ошибиться и произойдёт сложно выявляемая ошибка
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int abs(int a)
|
||||||
|
{
|
||||||
|
if (a < 0)
|
||||||
|
return -a;
|
||||||
|
else
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
double fabs(double a)
|
||||||
|
{
|
||||||
|
if (a < 0)
|
||||||
|
return -a;
|
||||||
|
else
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%i\n", abs(-5));
|
||||||
|
printf("%lf\n", fabs(-5.9));
|
||||||
|
|
||||||
|
|
||||||
|
double x = abs(-5.9);
|
||||||
|
printf("%lf\n", x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) В данном примере переменная x равна ровно 5. Почему так происходит?
|
||||||
|
|
||||||
|
2) Что будет, если всё-таки назвать 2 функции одинаковым именем и скомпилировать программу с помощью gcc?
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Это программа на языке C++ и компилировать её надо так:
|
||||||
|
g++ 01cppfunctions.c
|
||||||
|
|
||||||
|
|
||||||
|
В отличии от языка C в языке C++ есть возможность создать 2 и больше разных функции с одним и тем же названием,
|
||||||
|
но с разным количеством и/или типами аргументов.
|
||||||
|
|
||||||
|
Компилятор сам догадается, какую функцию следует вызвать в зависимости от типа аргумента.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int abs(int a)
|
||||||
|
{
|
||||||
|
if (a < 0)
|
||||||
|
return -a;
|
||||||
|
else
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
double abs(double a)
|
||||||
|
{
|
||||||
|
if (a < 0)
|
||||||
|
return -a;
|
||||||
|
else
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << abs(-5) << endl;
|
||||||
|
cout << abs(-5.9) << endl;
|
||||||
|
|
||||||
|
|
||||||
|
double x = abs(-5.9);
|
||||||
|
cout << x << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Протестируйте, что компилятор действительно вызывает нужные функции
|
||||||
|
Для этого просто сделайте так, чтобы функция, которая принимает int печатала на экран слово int,
|
||||||
|
а функция, которая принимает double, печатала бы на экран слово double
|
||||||
|
|
||||||
|
|
||||||
|
2) Что если на вход функции abs передать тип float?
|
||||||
|
Например, вот так:
|
||||||
|
abs(1.5f)
|
||||||
|
|
||||||
|
Какая из функций вызовется?
|
||||||
|
|
||||||
|
|
||||||
|
3) Напишите ещё одну перегрузку функции abs для типа float
|
||||||
|
Протестируйте её в функции main
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите несколько перегруженных функций под названием max
|
||||||
|
|
||||||
|
1) max, который вычисляет максимум от двух чисел типа int
|
||||||
|
2) max, который вычисляет максимум от двух чисел типа double
|
||||||
|
3) max, который вычисляет максимум от трёх чисел типа int
|
||||||
|
4) max, который вычисляет максимум от трёх чисел типа double
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int max(int a, int b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << max(4.2, 2.8) << endl; // Выводит число 4 -- неправильно
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
int max(int a, int b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
double max(double a, double b)
|
||||||
|
{
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max(int a, int b, int c)
|
||||||
|
{
|
||||||
|
int result = a;
|
||||||
|
if (b > result)
|
||||||
|
result = b;
|
||||||
|
if (c > result)
|
||||||
|
result = c;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double max(double a, double b, double c)
|
||||||
|
{
|
||||||
|
double result = a;
|
||||||
|
if (b > result)
|
||||||
|
result = b;
|
||||||
|
if (c > result)
|
||||||
|
result = c;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << max(4.2, 2.8) << endl;
|
||||||
|
|
||||||
|
cout << max(1, 2) << endl;
|
||||||
|
|
||||||
|
cout << max(4, 2, 5) << endl;
|
||||||
|
|
||||||
|
cout << max(1.2, 2.1, 0.5) << endl;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите несколько перегруженных функций под названием printType
|
||||||
|
|
||||||
|
Эти функции должны печатать тип переменной, которая поступает на вход
|
||||||
|
|
||||||
|
|
||||||
|
printType(15) должен напечатать int
|
||||||
|
printType(1.5) должен напечатать double
|
||||||
|
printType(1.5f); должен напечатать float
|
||||||
|
printType("Hello"); должен напечатать char[]
|
||||||
|
|
||||||
|
book b = {"War and Peace", 900, 1200};
|
||||||
|
printType(b); должен напечатать book
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct book
|
||||||
|
{
|
||||||
|
char title[50];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printType(15);
|
||||||
|
printType(1.5);
|
||||||
|
printType(1.5f);
|
||||||
|
printType("Hello");
|
||||||
|
|
||||||
|
book b = {"War and Peace", 900, 1200};
|
||||||
|
printType(b);
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Напишите несколько перегруженных функций под названием printType
|
||||||
|
|
||||||
|
Эти функции должны печатать тип переменной, которая поступает на вход
|
||||||
|
|
||||||
|
|
||||||
|
printType(15) должен напечатать int
|
||||||
|
printType(1.5) должен напечатать double
|
||||||
|
printType(1.5f); должен напечатать float
|
||||||
|
printType("Hello"); должен напечатать char[]
|
||||||
|
|
||||||
|
book b = {"War and Peace", 900, 1200};
|
||||||
|
printType(b); должен напечатать book
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct book
|
||||||
|
{
|
||||||
|
char title[50];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void printType(int a)
|
||||||
|
{
|
||||||
|
cout << "int" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printType(double a)
|
||||||
|
{
|
||||||
|
cout << "double" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printType(float a)
|
||||||
|
{
|
||||||
|
cout << "float" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printType(const char a[])
|
||||||
|
{
|
||||||
|
cout << "char[]" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printType(const book& a)
|
||||||
|
{
|
||||||
|
cout << "book" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printType(15);
|
||||||
|
printType(1.5);
|
||||||
|
printType(1.5f);
|
||||||
|
printType("Hello");
|
||||||
|
|
||||||
|
book b = {"War and Peace", 900, 1200};
|
||||||
|
printType(b);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
В отличии от языка C в языке C++ стандартные математические функции уже перегружены и могут
|
||||||
|
работать с разными типами данных
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << std::abs(-4) << endl;
|
||||||
|
cout << std::abs(-4.2) << endl;
|
||||||
|
cout << std::abs(-4.2f) << endl;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Функции можно перегружать и по указателю и ссылке
|
||||||
|
|
||||||
|
Но в случае с перегрузкой по ссылке могут возникнуть ситуации при которых невозможно выбрать правильный
|
||||||
|
|
||||||
|
Например, при вызове
|
||||||
|
|
||||||
|
int a = 10;
|
||||||
|
func(a);
|
||||||
|
|
||||||
|
Можно выбрать функцию void func(int x) или void func(int& x)
|
||||||
|
Определить более правильную функцию в этом случае невозможно, это приведёт к ошибке
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void func(int x)
|
||||||
|
{
|
||||||
|
cout << "int x" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void func(int* x)
|
||||||
|
{
|
||||||
|
cout << "int* x" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void func(int& x)
|
||||||
|
{
|
||||||
|
cout << "int& x" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
int* p = &a;
|
||||||
|
int& r = a;
|
||||||
|
|
||||||
|
func(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Определите какая функция вызовется при следующих вызовах функции func или произойдёт ошибка
|
||||||
|
|
||||||
|
1) func(a)
|
||||||
|
2) func(p)
|
||||||
|
3) func(&a)
|
||||||
|
4) func(20)
|
||||||
|
5) func(r)
|
||||||
|
6) func(&r)
|
||||||
|
|
||||||
|
|
||||||
|
2) Если добавить перегрузку, принимающую по константной ссылке, то что изменится
|
||||||
|
|
||||||
|
void func(const int& x)
|
||||||
|
{
|
||||||
|
cout << "const int& x" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
struct Cat {};
|
||||||
|
struct Dog {};
|
||||||
|
struct Cow {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void say(Cat a)
|
||||||
|
{
|
||||||
|
cout << "Meow" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void say(Dog a)
|
||||||
|
{
|
||||||
|
cout << "Woof" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void say(Cow a)
|
||||||
|
{
|
||||||
|
cout << "Mooo" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Cow x;
|
||||||
|
say(x);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Предположим, что мы захотели создать структуру, который будет хранить время (для простоты, только минуты и секунды)
|
||||||
|
|
||||||
|
Нам может понадобиться функция, которая будет добавлять ко времени, некоторое количество секунд
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time add(Time t, int x)
|
||||||
|
{
|
||||||
|
Time result = t;
|
||||||
|
result.seconds += x;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {20, 10};
|
||||||
|
Time b = add(a, 90);
|
||||||
|
|
||||||
|
cout << b.minutes << " " << b.seconds << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Напишите функцию, которая будет складывать не время и число, а два времени
|
||||||
|
|
||||||
|
Time add(Time ta, Time tb)
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time add(Time t, int x)
|
||||||
|
{
|
||||||
|
Time result = t;
|
||||||
|
result.seconds += x;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Time add(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {20, 10};
|
||||||
|
Time b = add(a, 90);
|
||||||
|
Time c = add(a, b);
|
||||||
|
|
||||||
|
cout << b.minutes << " " << b.seconds << endl;
|
||||||
|
cout << c.minutes << " " << c.seconds << endl;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Использовать функции может быть не так удобно как операторы.
|
||||||
|
Возможно было бы удобней для добавления времени использовать не функцию add, а оператор +
|
||||||
|
|
||||||
|
Можно перегрузить оператор функцией, для этого нужно назвать функцию так: operator@
|
||||||
|
где за место @ нужно подставить оператор, который вы хотите перегрузить
|
||||||
|
|
||||||
|
Например, функция Time operator+(Time t, int x) перегружает оператор + для типов Time и int соответственно (обязательно в таком порядке)
|
||||||
|
Теперь, когда компилятор встретит в коде сложение с таким операндами он вызовет эту функцию
|
||||||
|
|
||||||
|
В этом примере a + 90 при компиляции преобразуется в вызов функции operator+(a, 90)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time operator+(Time t, int x)
|
||||||
|
{
|
||||||
|
Time result = t;
|
||||||
|
result.seconds += x;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {20, 10};
|
||||||
|
Time b = a + 90;
|
||||||
|
|
||||||
|
cout << b.minutes << " " << b.seconds << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Что если операторы сложения поменяются местами
|
||||||
|
Time b = 90 + a;
|
||||||
|
Сработает ли в этом случае наша функция operator+ и, если нет, что нужно добавить, чтобы такое сложение сработало?
|
||||||
|
|
||||||
|
|
||||||
|
2) Напишите перегруженный оператор, который будет складывать не время и число, а два времени
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time operator+(Time t, int x)
|
||||||
|
{
|
||||||
|
Time result = t;
|
||||||
|
result.seconds += x;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time operator+(int x, Time t)
|
||||||
|
{
|
||||||
|
return t + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {20, 10};
|
||||||
|
Time b = a + 90;
|
||||||
|
Time c = 90 + a;
|
||||||
|
Time d = a + b;
|
||||||
|
|
||||||
|
cout << b.minutes << " " << b.seconds << endl;
|
||||||
|
cout << c.minutes << " " << c.seconds << endl;
|
||||||
|
cout << d.minutes << " " << d.seconds << endl;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Помимо перегрузки операторов, принимающих 2 аргумента (бинарных)
|
||||||
|
можно перегружать и унарные операторы - принимающие один аргумент
|
||||||
|
|
||||||
|
При этом, так как operator+ это функция, то работает перегрузка функций
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
cout << "binary operator +" << endl;
|
||||||
|
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time operator+(Time t)
|
||||||
|
{
|
||||||
|
cout << "unary operator +" << endl;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {20, 10};
|
||||||
|
Time b = {40, 30};
|
||||||
|
|
||||||
|
Time c = a + b;
|
||||||
|
Time d = +a;
|
||||||
|
|
||||||
|
cout << c.minutes << " " << c.seconds << endl;
|
||||||
|
cout << d.minutes << " " << d.seconds << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Что если операторы сложения поменяются местами
|
||||||
|
Time b = 90 + a;
|
||||||
|
Сработает ли в этом случае наша функция operator+ и, если нет, что нужно добавить, чтобы такое сложение сработало?
|
||||||
|
|
||||||
|
|
||||||
|
2) Напишите перегруженный оператор, который будет складывать не время и число, а два времени
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
В прошлом семестре, для хранения результатов логических операций, мы использовали целочисленные типы (например int).
|
||||||
|
|
||||||
|
В языке C++ есть встроенный тип bool, который может принимать 2 значения (true и false).
|
||||||
|
Для хранения значения логических переменных желательно использовать этот тип
|
||||||
|
|
||||||
|
|
||||||
|
При печати на экран с помощью std::cout переменных типа bool печатается либо 0 либо 1
|
||||||
|
Чтобы на экран печаталось false или true нужно в std::cout передать специальный объект std::boolalpha
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
bool isEven(int a)
|
||||||
|
{
|
||||||
|
return a % 2 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
bool a = isEven(10);
|
||||||
|
bool b = isEven(15);
|
||||||
|
bool c = a || b;
|
||||||
|
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
cout << c << endl;
|
||||||
|
cout << std::boolalpha << c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Помимо арифметических операторов можно перегружать и операторы сравнения (и многие другие операторы)
|
||||||
|
Желательно, чтобы операторы сравнения возвращали bool
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator>(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (ta.minutes > tb.minutes)
|
||||||
|
result = true;
|
||||||
|
else if (ta.minutes == tb.minutes && ta.seconds > tb.seconds)
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {10, 20};
|
||||||
|
Time b = {10, 40};
|
||||||
|
Time c = {0, 20};
|
||||||
|
|
||||||
|
cout << std::boolalpha;
|
||||||
|
cout << (a > b) << endl;
|
||||||
|
cout << (b > a) << endl;
|
||||||
|
cout << (a + c > b) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Заметьте, что при выводе на экран сравнение было взято в скобки
|
||||||
|
cout << (a > b) << endl;
|
||||||
|
|
||||||
|
Что будет, если эти скобки не писать и почему
|
||||||
|
cout << a > b << endl;
|
||||||
|
|
||||||
|
|
||||||
|
2) Напишите перегруженные операторы < >= <= == != для сравнения объектов структур типа Time друг с другом
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Помимо арифметических операторов можно перегружать и операторы сравнения (и многие другие операторы)
|
||||||
|
Желательно, чтобы операторы сравнения возвращали bool
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator>(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (ta.minutes > tb.minutes)
|
||||||
|
result = true;
|
||||||
|
else if (ta.minutes == tb.minutes && ta.seconds > tb.seconds)
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator==(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (ta.minutes == tb.minutes && ta.seconds == tb.seconds)
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
return !(ta == tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator>=(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
return ta > tb || ta == tb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator<(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
return !(ta >= tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator<=(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
return !(ta > tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {10, 20};
|
||||||
|
Time b = {10, 40};
|
||||||
|
Time c = {0, 20};
|
||||||
|
|
||||||
|
cout << std::boolalpha;
|
||||||
|
cout << (a == b) << endl;
|
||||||
|
cout << (a != b) << endl;
|
||||||
|
|
||||||
|
cout << (a < b) << endl;
|
||||||
|
cout << (a <= b) << endl;
|
||||||
|
cout << (a > b) << endl;
|
||||||
|
cout << (a >= b) << endl;
|
||||||
|
cout << (a + c >= b) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Заметьте, что при выводе на экран сравнение было взято в скобки
|
||||||
|
cout << (a > b) << endl;
|
||||||
|
|
||||||
|
Что будет, если эти скобки не писать и почему
|
||||||
|
cout << a > b << endl;
|
||||||
|
|
||||||
|
Ошибка происходит из-за того, что приоритет операции << выше, чем у операций сравнения
|
||||||
|
В результате сначала проводится
|
||||||
|
cout << a
|
||||||
|
затем получившийся объект сравнивается с b. Это и приводит к ошибке.
|
||||||
|
*/
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Перегрузка оператора << для вывода на экран
|
||||||
|
|
||||||
|
Напомним, что объект под названием cout имеет тип ostream (сокращение от output stream - выходной поток)
|
||||||
|
и хранится в библиотеке iostream в пространстве имён std
|
||||||
|
|
||||||
|
То есть где-то внутри библиотеки iostream объявлена глобальная переменная по имени cout типа ostream
|
||||||
|
ostream cout;
|
||||||
|
|
||||||
|
|
||||||
|
Мы можем перегрузить оператор << с первым аргументом типа std::ostream, а вторым аргументом - нашим типом,
|
||||||
|
чтобы удобно выводить на экран объекты нашего типа.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void operator<<(std::ostream& out, Time t)
|
||||||
|
{
|
||||||
|
out << t.minutes << ":" << t.seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {10, 20};
|
||||||
|
cout << a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
cout << a; работает, но
|
||||||
|
cout << a << endl; выдаёт ошибку в данной программе.
|
||||||
|
|
||||||
|
Из-за чего это происходит и как исправить эту ошибку?
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Time t)
|
||||||
|
{
|
||||||
|
out << t.minutes << ":" << t.seconds;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {10, 20};
|
||||||
|
Time b = {15, 50};
|
||||||
|
|
||||||
|
cout << a << endl << b << endl;
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
cout << a; работает, но
|
||||||
|
cout << a << endl; выдаёт ошибку в данной программе.
|
||||||
|
|
||||||
|
Из-за чего это происходит и как исправить эту ошибку?
|
||||||
|
|
||||||
|
|
||||||
|
Решение:
|
||||||
|
|
||||||
|
Ошибка происходила из-за того, что оператор << ничего не возвращал.
|
||||||
|
|
||||||
|
В строке cout << a << endl;
|
||||||
|
результат cout << a был void и к нему нельзя применить оператор << ещё раз.
|
||||||
|
|
||||||
|
|
||||||
|
Результат cout << a должен быть тоже быть равен cout
|
||||||
|
Но, поскольку глобальный объект cout копировать мы не можем, у нас остаётся единственный выход:
|
||||||
|
принимать и возвращать объект cout по ссылке.
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
struct Complex
|
||||||
|
{
|
||||||
|
float re, im;
|
||||||
|
};
|
||||||
|
|
||||||
|
Complex operator+(Complex first, Complex second)
|
||||||
|
{
|
||||||
|
Complex result = {first.re + second.re, first.im + second.im};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Complex z1 = {3, 7};
|
||||||
|
Complex z2 = {2, -4};
|
||||||
|
|
||||||
|
Complex z = z1 + z2;
|
||||||
|
cout << z.re << " + " << z.im << "i" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Перегрузите следующие операторы:
|
||||||
|
- Вычитание
|
||||||
|
- Умножение
|
||||||
|
- Деление
|
||||||
|
- Унарный минус
|
||||||
|
- Унарный плюс
|
||||||
|
- Сравнение ==
|
||||||
|
- Сопряжение - это операция, которая меняет знак мнимой части комплексного числа
|
||||||
|
Для сопряжения используйте оператор унарная звёздочка *
|
||||||
|
|
||||||
|
2) Перегрузите оператор вывода <<
|
||||||
|
|
||||||
|
3) Напишите функцию exp(z)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
cout << z1 - z2 << endl;
|
||||||
|
cout << z1 * z2 << endl;
|
||||||
|
cout << z1 / z2 << endl;
|
||||||
|
cout << -z1 << endl;
|
||||||
|
cout << *z1 << endl; // (Комплексно-сопряжённое)
|
||||||
|
|
||||||
|
z = exp(z1 + z2)/(z1 * z2);
|
||||||
|
cout << z << endl;
|
||||||
|
*/
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
В библиотеки iomanip содержатся специальные функции, для работы с потоками ostream
|
||||||
|
|
||||||
|
setw - установить минимальный размер в символах для печати следующего объекта
|
||||||
|
setfill - если размер печати меньше минимального, то замостить оставшееся соответствующим символом
|
||||||
|
|
||||||
|
setprecision - установить точность (для вещественных чисел)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct Time
|
||||||
|
{
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Time operator+(Time ta, Time tb)
|
||||||
|
{
|
||||||
|
Time result = ta;
|
||||||
|
result.seconds += 60 * tb.minutes + tb.seconds;
|
||||||
|
|
||||||
|
result.minutes += (result.seconds / 60);
|
||||||
|
result.seconds %= 60;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Time t)
|
||||||
|
{
|
||||||
|
out << std::setfill('0') << std::setw(2) << t.minutes << ":" <<
|
||||||
|
std::setfill('0') << std::setw(2) << t.seconds;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Time a = {1, 5};
|
||||||
|
Time b = {4, 20};
|
||||||
|
|
||||||
|
cout << a << endl << b << endl;
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
В отличии от языка C, язык C++ не делает неявное преобразование типов указателей.
|
||||||
|
|
||||||
|
Рассмотрим, например, код:
|
||||||
|
|
||||||
|
int a = 10;
|
||||||
|
char* p = &a;
|
||||||
|
|
||||||
|
В языке C такой код сработает, несмотря на то, что в строке char* p = &a; слева стоит указатель типа char*
|
||||||
|
а справа объект типа int*. Будет произведено неявное преобразование типов указателей.
|
||||||
|
|
||||||
|
В языке C++ такой код приведёт к ошибке, так как C++ не преобразует указатели неявно.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Рассмотрим, например, код:
|
||||||
|
|
||||||
|
int* q = malloc(10 * sizeof(int));
|
||||||
|
|
||||||
|
В языке C такой код сработает, несмотря на то, что слева стоит указатель типа int*
|
||||||
|
а справа объект типа void* (malloc возвращает указатель типа void*).
|
||||||
|
Будет произведено неявное преобразование типов указателей.
|
||||||
|
|
||||||
|
В языке C++ такой код приведёт к ошибке, так как C++ не преобразует указатели неявно.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
char* p = &a;
|
||||||
|
|
||||||
|
|
||||||
|
int* q = malloc(10 * sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Исправьте ошибки компиляции, явно приведя указатель к правильным типам.
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
char* p = (char*)&a;
|
||||||
|
|
||||||
|
|
||||||
|
int* q = (int*)malloc(10 * sizeof(int));
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
В языке C++ желательно использовать более безопасное приведение типов static_cast
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a = 10;
|
||||||
|
char* p = static_cast<char*>(&a);
|
||||||
|
|
||||||
|
|
||||||
|
int* q = static_cast<int*>(malloc(10 * sizeof(int)));
|
||||||
|
}
|
50
seminar01_overload/classroom_tasks/code/04other/01nulptr.cpp
Normal file
50
seminar01_overload/classroom_tasks/code/04other/01nulptr.cpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Новое специальное нулевое значение для указателя: nullptr
|
||||||
|
В языке C для этой цели использовался NULL, который был просто числом 0
|
||||||
|
|
||||||
|
Если определить NULL так:
|
||||||
|
|
||||||
|
#define NULL (void*)0
|
||||||
|
|
||||||
|
То, в отличии от языка C, в языке C++ простая строка вида:
|
||||||
|
|
||||||
|
int* p = NULL;
|
||||||
|
|
||||||
|
не сработает, так как слева стоит int* а справа void*
|
||||||
|
|
||||||
|
|
||||||
|
Если определить NULL так:
|
||||||
|
|
||||||
|
#define NULL 0
|
||||||
|
|
||||||
|
то в C++ могут возникнуть проблемы с перегрузкой, как это показано ниже.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void print(int value)
|
||||||
|
{
|
||||||
|
printf("Int: %d\n", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(void* pointer)
|
||||||
|
{
|
||||||
|
printf("Pointer: %p\n", pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
void* p1 = NULL;
|
||||||
|
void* p2 = nullptr;
|
||||||
|
|
||||||
|
// Всё ОК (компилятор может выбрать функцию):
|
||||||
|
print(p1);
|
||||||
|
print(p2);
|
||||||
|
|
||||||
|
// Тут неверно (компилятор не может выбрать перегруженную функцию, произойдёт ошибка):
|
||||||
|
print(NULL);
|
||||||
|
|
||||||
|
// Тут всё OK:
|
||||||
|
print(nullptr);
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
В отличии от языка C, в C++ можно задавать значения по умолчанию
|
||||||
|
для аргументов функций
|
||||||
|
|
||||||
|
Функцию printSquare можно вызвать с одним, двумя или тремя
|
||||||
|
параметрами. Аргументы width и height будут заданы аргументами по умолчанию.
|
||||||
|
Если передаваемых аргументов будет меньше трёх.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void printSquare(char c, int width = 10, int height = 5)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
{
|
||||||
|
cout << c;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printSquare('+', 6, 4);
|
||||||
|
printSquare('#', 15);
|
||||||
|
printSquare('O');
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Написать функцию:
|
||||||
|
void print(char str[], bool isCapitalized = false)
|
||||||
|
Которая будет просто печатать строку str, если isCapitalized = false,
|
||||||
|
а если isCapitalized = true, то будет печатать всю строку в верхнем регистре
|
||||||
|
*/
|
189
seminar01_overload/homework/code/complex.h
Normal file
189
seminar01_overload/homework/code/complex.h
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct Complex {
|
||||||
|
float re;
|
||||||
|
float im;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Передаёмм аргументы через ссылки
|
||||||
|
// В данном случае можно было передавать по значению
|
||||||
|
// (так как Complex имеет малый размер)
|
||||||
|
// Но в общем случае лучше для структур лучше
|
||||||
|
// всегда использовать ссылки
|
||||||
|
|
||||||
|
Complex operator+(const Complex& a, const Complex& b) {
|
||||||
|
Complex result = {a.re + b.re, a.im + b.im};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex operator-(const Complex& a, const Complex& b) {
|
||||||
|
Complex result = {a.re - b.re, a.im - b.im};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex operator*(const Complex& a, const Complex& b) {
|
||||||
|
Complex result = {a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex operator/(const Complex& a, const Complex& b) {
|
||||||
|
float b_squared = b.re * b.re + b.im * b.im;
|
||||||
|
|
||||||
|
Complex result;
|
||||||
|
result.re = (a.re * b.re + a.im * b.im) / b_squared;
|
||||||
|
result.im = (a.im * b.re - a.re * b.im) / b_squared;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex& operator+=(Complex &a, const Complex &b) {
|
||||||
|
a.re += b.re;
|
||||||
|
a.im += b.im;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Унарный оператор -
|
||||||
|
// То есть если z - комплексное число x + iy, то -z = - x - iy
|
||||||
|
Complex operator-(const Complex& a) {
|
||||||
|
Complex result;
|
||||||
|
result.re = -a.re;
|
||||||
|
result.im = -a.im;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Унарный оператор +
|
||||||
|
// Ничего не меняет
|
||||||
|
Complex operator+(const Complex& a) {
|
||||||
|
Complex result = a;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Унарный оператор *
|
||||||
|
// То есть если z - комплексное число x + iy, то *z = x - iy
|
||||||
|
// Оператор сопряжения
|
||||||
|
Complex operator*(const Complex& a) {
|
||||||
|
Complex result;
|
||||||
|
result.re = a.re;
|
||||||
|
result.im = -a.im;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Число + комплексное число (в таком порядке)
|
||||||
|
Complex operator+(float a, const Complex& b) {
|
||||||
|
Complex result = b;
|
||||||
|
result.re += a;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Комплексное число + число
|
||||||
|
Complex operator+(const Complex& a, float b) {
|
||||||
|
Complex result = a;
|
||||||
|
result.re += b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Число - комплексное число (в таком порядке)
|
||||||
|
Complex operator-(float a, const Complex& b) {
|
||||||
|
Complex result = -b;
|
||||||
|
result.re += a;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Комплексное число - число
|
||||||
|
Complex operator-(const Complex& a, float b) {
|
||||||
|
Complex result = a;
|
||||||
|
result.re -= b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Комплексное число * число
|
||||||
|
Complex operator*(const Complex& a, float b) {
|
||||||
|
Complex result = a;
|
||||||
|
result.re *= b;
|
||||||
|
result.im *= b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Число * комплексное число
|
||||||
|
Complex operator*(float a, const Complex& b) {
|
||||||
|
Complex result = b;
|
||||||
|
result.re *= a;
|
||||||
|
result.im *= a;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Комплексное число / число
|
||||||
|
Complex operator/(const Complex& a, float b) {
|
||||||
|
Complex result = a;
|
||||||
|
result.re /= b;
|
||||||
|
result.im /= b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Число / комплексное число
|
||||||
|
Complex operator/(float a, const Complex& b) {
|
||||||
|
float b_squared = b.re * b.re + b.im * b.im;
|
||||||
|
return (a * (*b)) / b_squared;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Перегружаем оператор<< между типами
|
||||||
|
// std::ostream (такой тип имеет std::cout) и Complex
|
||||||
|
// Обратите внимание, что мы возвращаем ссылку на ostream
|
||||||
|
// Таким образом результатом выражения cout << a будет cout
|
||||||
|
// Поэтому можно делать так: cout << a << b << c ...
|
||||||
|
std::ostream& operator<<(std::ostream& out, const Complex& a) {
|
||||||
|
if (a.re != 0)
|
||||||
|
out << a.re;
|
||||||
|
|
||||||
|
if (a.im > 0) {
|
||||||
|
if (a.im != 1.0)
|
||||||
|
out << " + " << a.im << "i";
|
||||||
|
else
|
||||||
|
out << " + i";
|
||||||
|
}
|
||||||
|
else if (a.im < 0) {
|
||||||
|
if (a.im != -1.0)
|
||||||
|
out << " - " << -a.im << "i";
|
||||||
|
else
|
||||||
|
out << " - i";
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, Complex& c) {
|
||||||
|
in >> c.re >> c.im;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
float abs(const Complex& a) {
|
||||||
|
return sqrtf(a.re * a.re + a.im * a.im);
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex exp(const Complex& a) {
|
||||||
|
Complex result;
|
||||||
|
result.re = expf(a.re) * cosf(a.im);
|
||||||
|
result.im = expf(a.re) * sinf(a.im);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex sin(const Complex& a) {
|
||||||
|
Complex result;
|
||||||
|
result.re = sinf(a.re) * coshf(a.im);
|
||||||
|
result.im = cosf(a.re) * sinhf(a.im);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Complex cos(const Complex& a) {
|
||||||
|
Complex result;
|
||||||
|
result.re = cosf(a.re) * coshf(a.im);
|
||||||
|
result.im = sinf(a.re) * sinhf(a.im);
|
||||||
|
return result;
|
||||||
|
}
|
56
seminar01_overload/homework/code/complex_image.cpp
Normal file
56
seminar01_overload/homework/code/complex_image.cpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
|
#include "complex.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// В этой программе мы рисуем в картинку комплексную функцию,
|
||||||
|
// которая задаётся в функции func
|
||||||
|
|
||||||
|
struct Color {
|
||||||
|
unsigned char r, g, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
Complex func(Complex z) {
|
||||||
|
Complex f = 100/(z - 1)*exp(z);
|
||||||
|
f.re = fabs(f.re);
|
||||||
|
f.im = fabs(f.im);
|
||||||
|
if (f.re > 255)
|
||||||
|
f.re = 255;
|
||||||
|
if (f.im > 255)
|
||||||
|
f.im = 255;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int width = 800, height = 800;
|
||||||
|
float x0 = -2.0f, x1 = 2.0f;
|
||||||
|
float y0 = -2.0f, y1 = 2.0f;
|
||||||
|
|
||||||
|
// Выделяем память под пиксели
|
||||||
|
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||||
|
|
||||||
|
// data - это массив цветов размером width * height
|
||||||
|
// Задаём значения этого массива так, чтобы
|
||||||
|
// реальная часть функции func соответствовала зелёному цвету,
|
||||||
|
// а мнимая часть -- синей компоненте цвета
|
||||||
|
for (int j = 0; j < height; j++) {
|
||||||
|
for (int i = 0; i < width; i++) {
|
||||||
|
Complex z = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||||
|
Complex f = func(z);
|
||||||
|
data[i + width * j].r = 0;
|
||||||
|
data[i + width * j].g = f.re;
|
||||||
|
data[i + width * j].b = f.im;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сохраняем массив цветов data как картинку в формате .ppm
|
||||||
|
FILE* file = fopen("complex_image.ppm", "wb");
|
||||||
|
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||||
|
fwrite(data, sizeof(Color), height * width, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
// Освобождаем память
|
||||||
|
free(data);
|
||||||
|
}
|
63
seminar01_overload/homework/code/complex_movie.cpp
Normal file
63
seminar01_overload/homework/code/complex_movie.cpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
|
#include "complex.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Это программа создаёт анимацию (набор картинок)
|
||||||
|
// которая задаётся как меняющееся во времени
|
||||||
|
// комплексная функция (описана в функции func)
|
||||||
|
|
||||||
|
|
||||||
|
struct Color {
|
||||||
|
unsigned char r, g, b;
|
||||||
|
};
|
||||||
|
|
||||||
|
Complex func(Complex z, int time) {
|
||||||
|
Complex f = 100/(z - (0.02f*time))*exp(z*sin(z));
|
||||||
|
f.re = fabs(f.re);
|
||||||
|
f.im = fabs(f.im);
|
||||||
|
if (f.re > 255)
|
||||||
|
f.re = 255;
|
||||||
|
if (f.im > 255)
|
||||||
|
f.im = 255;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int width = 800, height = 800;
|
||||||
|
float x0 = -2.0f, x1 = 2.0f;
|
||||||
|
float y0 = -2.0f, y1 = 2.0f;
|
||||||
|
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||||
|
|
||||||
|
// Повторяем 200 раз
|
||||||
|
int max_time_steps = 200;
|
||||||
|
for (int time = 0; time < max_time_steps; time++)
|
||||||
|
{
|
||||||
|
// Задаём изображение в массиве data
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
{
|
||||||
|
Complex z = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||||
|
Complex f = func(z, time);
|
||||||
|
data[i + width * j].r = 0;
|
||||||
|
data[i + width * j].g = f.re;
|
||||||
|
data[i + width * j].b = f.im;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создаём в строке filename имя изображения
|
||||||
|
// Папка animation должна существовать!
|
||||||
|
char filename[100];
|
||||||
|
sprintf(filename, "animation/complex_%03d.ppm", time);
|
||||||
|
|
||||||
|
// Сохраняем изображение в картинке по имени filename
|
||||||
|
FILE* file = fopen(filename, "wb");
|
||||||
|
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||||
|
fwrite(data, sizeof(Color), height * width, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
38
seminar01_overload/homework/code/complex_test.cpp
Normal file
38
seminar01_overload/homework/code/complex_test.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "complex.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// Тут мы тестируем нашу реализацию комплексных чисел
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
Complex a;
|
||||||
|
Complex b;
|
||||||
|
|
||||||
|
cin >> a >> b;
|
||||||
|
|
||||||
|
cout << "a = " << a << endl
|
||||||
|
<< "b = " << b << endl
|
||||||
|
<< "a + b = " << a + b << endl
|
||||||
|
<< "a - b = " << a - b << endl
|
||||||
|
<< "a * b = " << a * b << endl
|
||||||
|
<< "a / b = " << a / b << endl
|
||||||
|
<< "-a = " << -a << endl
|
||||||
|
<< "+a = " << +a << endl
|
||||||
|
<< "*a = " << *a << endl
|
||||||
|
<< "a + 5 = " << a + 5 << endl
|
||||||
|
<< "5 + a = " << 5 + a << endl
|
||||||
|
<< "a * 5 = " << a * 5 << endl
|
||||||
|
<< "5 * a = " << 5 * a << endl
|
||||||
|
<< "Exp(a) = " << exp(a) << endl
|
||||||
|
<< "Sin(a) = " << sin(a) << endl
|
||||||
|
<< "Cos(a) = " << cos(a) << endl
|
||||||
|
<< "Exp((a + b) / a) * Cos(a - b) = " << exp((a + b) / a) * cos(a - b) << endl;
|
||||||
|
|
||||||
|
a += b;
|
||||||
|
cout << "a += b; a = " << a << endl;
|
||||||
|
|
||||||
|
// Оператор = мы не перегружали, но это всё равно работает
|
||||||
|
b = a;
|
||||||
|
cout << "b = a; b = " << b << endl;
|
||||||
|
}
|
BIN
seminar01_overload/homework/homework_overload.pdf
Normal file
BIN
seminar01_overload/homework/homework_overload.pdf
Normal file
Binary file not shown.
160
seminar01_overload/homework/homework_overload.tex
Normal file
160
seminar01_overload/homework/homework_overload.tex
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
\documentclass{article}
|
||||||
|
\usepackage[utf8x]{inputenc}
|
||||||
|
\usepackage{ucs}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amsfonts}
|
||||||
|
\usepackage{marvosym}
|
||||||
|
\usepackage{wasysym}
|
||||||
|
\usepackage{upgreek}
|
||||||
|
\usepackage[english,russian]{babel}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\usepackage{float}
|
||||||
|
\usepackage{textcomp}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{geometry}
|
||||||
|
\geometry{left=2cm}
|
||||||
|
\geometry{right=1.5cm}
|
||||||
|
\geometry{top=1cm}
|
||||||
|
\geometry{bottom=2cm}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{ccaption}
|
||||||
|
\usepackage{multicol}
|
||||||
|
|
||||||
|
\usepackage{listings}
|
||||||
|
%\setlength{\columnsep}{1.5cm}
|
||||||
|
%\setlength{\columnseprule}{0.2pt}
|
||||||
|
|
||||||
|
\usepackage{colortbl,graphicx,tikz}
|
||||||
|
\definecolor{X}{rgb}{.5,.5,.5}
|
||||||
|
|
||||||
|
\title{ДЗ. Работа с изображениями в формате \texttt{.ppm}}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
|
||||||
|
\lstset{
|
||||||
|
language=C++, % choose the language of the code
|
||||||
|
basicstyle=\linespread{1.1}\ttfamily,
|
||||||
|
columns=fixed,
|
||||||
|
fontadjust=true,
|
||||||
|
basewidth=0.5em,
|
||||||
|
keywordstyle=\color{blue}\bfseries,
|
||||||
|
commentstyle=\color{gray},
|
||||||
|
stringstyle=\ttfamily\color{orange!50!black},
|
||||||
|
showstringspaces=false,
|
||||||
|
%numbers=false, % where to put the line-numbers
|
||||||
|
numbersep=5pt,
|
||||||
|
numberstyle=\tiny\color{black},
|
||||||
|
numberfirstline=true,
|
||||||
|
stepnumber=1, % the step between two line-numbers.
|
||||||
|
numbersep=10pt, % how far the line-numbers are from the code
|
||||||
|
backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
|
||||||
|
showstringspaces=false, % underline spaces within strings
|
||||||
|
captionpos=b, % sets the caption-position to bottom
|
||||||
|
breaklines=true, % sets automatic line breaking
|
||||||
|
breakatwhitespace=true, % sets if automatic breaks should only happen at whitespace
|
||||||
|
xleftmargin=.2in,
|
||||||
|
extendedchars=\true,
|
||||||
|
keepspaces = true,
|
||||||
|
}
|
||||||
|
\lstset{literate=%
|
||||||
|
*{0}{{{\color{red!20!violet}0}}}1
|
||||||
|
{1}{{{\color{red!20!violet}1}}}1
|
||||||
|
{2}{{{\color{red!20!violet}2}}}1
|
||||||
|
{3}{{{\color{red!20!violet}3}}}1
|
||||||
|
{4}{{{\color{red!20!violet}4}}}1
|
||||||
|
{5}{{{\color{red!20!violet}5}}}1
|
||||||
|
{6}{{{\color{red!20!violet}6}}}1
|
||||||
|
{7}{{{\color{red!20!violet}7}}}1
|
||||||
|
{8}{{{\color{red!20!violet}8}}}1
|
||||||
|
{9}{{{\color{red!20!violet}9}}}1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
\title{Семинар \#1: Ссылки и перегрузка операторов. Домашнее задание.\vspace{-5ex}}\date{}\maketitle
|
||||||
|
\subsection*{Пространство имён:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Создайте пространство имён по имени \texttt{myspace}. В этом пространстве имён создайте функцию \\
|
||||||
|
\texttt{void print\_n\_times(char str[], int n = 10)}, которая будет печатать строку \texttt{str} \texttt{n} раз. Для печати используйте \texttt{std::cout} из библиотеки \texttt{iostream}. Вызовите эту функцию из \texttt{main}.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection*{Ссылки:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Напишите функцию \texttt{cube}, которая будет принимать одно число типа \texttt{int} и возводить его в куб. Используйте ссылки. Вызовите эту функцию из функции \texttt{main}.
|
||||||
|
\item Напишите функцию \texttt{void count\_letters(char str[], int\& n\_letters, int\& n\_digits, int\& n\_other)}, которая будет принимать на вход строку \texttt{str} и подсчитывать число букв и цифр в этой строке. Количество букв нужно записать в переменную \texttt{n\_letters}, количество цифр -- в переменную \texttt{n\_digits}, а количество остальных символов -- в переменную \texttt{n\_other}. Вызвать эту функцию из функции \texttt{main}.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection*{Перегрузка операций:}
|
||||||
|
В файлах \texttt{code/complex.h} и \texttt{code/complex.cpp} лежит реализация комплексного числа с перегруженными операторами. Используйте его в качестве примера для решения задач этого раздела:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Создайте структуру \texttt{Vector3f} - вектор в трёхмерном пространстве с полями \texttt{x, y, z} типа \texttt{float} в качестве координат. Перегрузите следующие операторы для работы с вектором. Для передачи вектора в функции используте ссылки и, там где возможно, модификатор \texttt{const}.
|
||||||
|
\begin{itemize}
|
||||||
|
\item Сложение векторов (\texttt{+})
|
||||||
|
\item Вычитание (\texttt{-})
|
||||||
|
\item Умножение вектора на число типа \texttt{float} (число \texttt{*} вектор и вектор \texttt{*} число)
|
||||||
|
\item Деление вектора на число типа \texttt{float} (вектор \texttt{/} число)
|
||||||
|
\item Скалярное произведение (\texttt{*})
|
||||||
|
\item Унарный \texttt{-}
|
||||||
|
\item Унарный \texttt{+}
|
||||||
|
\item Проверка на равенство \texttt{==} (должна возвращать тип \texttt{bool})
|
||||||
|
\item Проверка на неравенство \texttt{!=} (должна возвращать тип \texttt{bool})
|
||||||
|
\item Операторы \texttt{+=} и \texttt{-=} (вектор \texttt{+=} вектор)
|
||||||
|
\item Операторы \texttt{*=} и \texttt{/=} (вектор \texttt{*=} число)
|
||||||
|
\item Оператор вывода \texttt{ostream >{}>} вектор. Выводите вектор в виде \texttt{(x, y, z)}.
|
||||||
|
\item Оператор ввода \texttt{istream <{}<} вектор
|
||||||
|
\item Функция \texttt{float squared\_norm(const Vector3f\& a)}, которая вычисляет квадрат нормы вектора.
|
||||||
|
\item Функция \texttt{float norm(const Vector3f\& a)}, которая вычисляет норму вектора.
|
||||||
|
\item Функция \texttt{void normalize(Vector3f\& a)}, которая нормализует вектор \texttt{a}.
|
||||||
|
\end{itemize}
|
||||||
|
\item Поместите весь ваш код в отдельный файл \texttt{vector3f.h} и подключите к файлу \texttt{main.cpp}.
|
||||||
|
\item Протестируйте ваши функции:
|
||||||
|
\begin{lstlisting}
|
||||||
|
#include <iostream>
|
||||||
|
#include "vector3f.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
Vector3f a = {1.0, 2.0, -2.0};
|
||||||
|
Vector3f b = {4.0, -1.0, 3.0};
|
||||||
|
cout << "a = " << a << endl << "b = " << b << endl;
|
||||||
|
cout << "a + b = " << a + b << endl;
|
||||||
|
cout << "-a = " << -a << endl;
|
||||||
|
cout << "Scalar product of a and b = " << a * b << endl;
|
||||||
|
a /= 5;
|
||||||
|
cout << "a after a /= 5;" << a << endl
|
||||||
|
normalize(b);
|
||||||
|
cout << "Normalized b:" << b << endl
|
||||||
|
a += b;
|
||||||
|
cout << "a after a+= b;" << a << endl;
|
||||||
|
}
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
\subsection*{Задача об убегающей точке}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Предположим, что у нас есть комплексная функция $f(z) = z^2$. Выберем некоторое комплексное число $z_0$ и будем проводить следующие итерации:
|
||||||
|
\begin{equation}
|
||||||
|
\label{fractalseq}
|
||||||
|
z_1 = f(z_0)\quad z_2 = f(z_1)\quad ...\quad z_{k+1} = f(z_k)\quad ...
|
||||||
|
\end{equation}
|
||||||
|
В зависимости от выбора точки $z_0$ эта последовательность либо разойдётся, либо останется в некоторой ограниченной области. Будем называть точку $z_0$ убегающей, если $z_k \rightarrow \infty$ при $k \rightarrow \infty$. Найдите область неубегания для функции $z^2$, т.е. множество всех начальных значений $z_0$, при которых последовательность (\ref{fractalseq}) остаётся ограниченной (это можно сделать в уме). \\
|
||||||
|
|
||||||
|
\item \textbf{Julia:} Для функции $f(z) = z^2$ эта область тривиальна, но всё становится сложней для функции вида $f(z) = z^2 + c$, где $c$ -- некоторое комплексное число. Численно найдите область неубегания для функций такого вида. Для этого создайте изображение размера 800x800, покрывающую область \texttt{[-2:2]x[-2:2]} на комплексной плоскости. Для каждой точки этой плоскости проведите $N \approx 20$ итераций и, в зависимости от результата, окрасьте пиксель в соответствующий цвет (цвет можно подобрать самим, он должен быть пропорционален значению $z_N$ - меняться от яркого если $z_N$ мало и до черного если $z_N$ большое). Используйте класс Complex и перегруженные операторы. Пример работы с изображениями в формате \texttt{ppm} можно посмотреть в файле \texttt{complex\_image.cpp}. Программа должна создавать файл \texttt{julia.ppm}.
|
||||||
|
|
||||||
|
\begin{center}
|
||||||
|
\includegraphics[scale=0.7]{../images/complexplane.png}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
\item Нарисуте изображение для $c = -0.4 + 0.6i$;\quad $c = -0.70 - 0.38i$;\quad $c = -0.80 + 0.16i$\quad и\quad $c = 0.280 + 0.011i$.
|
||||||
|
\item Добавьте параметры командной строки: 2 вещественных числа, соответствующие комплексному числу $c$, и целое число итераций $N$.
|
||||||
|
\item \textbf{Mandelbrot:} Зафиксируем теперь $z_0 = 0$ и будем менять $c$. Численно найдите все параметры $c$, для которых точка $z_0$ не является убегающей. Для этого создайте изображение размера 800x800, покрывающую область \texttt{[-2:2]x[-2:2]} возможных значений $c$ на комплексной плоскости. Программа должна создавать файл \texttt{mandelbrot.ppm}.
|
||||||
|
|
||||||
|
\item \textbf{Анимация:} Программа \texttt{complex\_movie.cpp} создаёт множество изображений и сохраняет их в папку \texttt{animation} (если у вас нет такой папки -- создайте её). Эти изображения представляют собой отдельные кадры будущей анимации. Чтобы их объединить в одно видео можно использовать программу ffmpeg (Нужно скачать тут: \href{https://www.ffmpeg.org/}{www.ffmpeg.org} и изменить переменную среды \texttt{PATH} в настройках Windows или Linux). После этого можно будет объединить все изображения в одно видео такой командой:
|
||||||
|
\begin{verbatim}
|
||||||
|
ffmpeg -r 60 -i animation/complex_%03d.ppm complex_movie.mp4
|
||||||
|
\end{verbatim}
|
||||||
|
Создайте анимацию из изображений множеств Julia при $c$ линейно меняющемся от $(-1.5 - 0.5i)$ до $i$.
|
||||||
|
\end{itemize}
|
||||||
|
\end{document}
|
BIN
seminar01_overload/images/complexplane.png
Normal file
BIN
seminar01_overload/images/complexplane.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
490
seminar01_overload/images/complexplane.svg
Normal file
490
seminar01_overload/images/complexplane.svg
Normal file
|
@ -0,0 +1,490 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="complexplane.svg"
|
||||||
|
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar01_overload\images\complexplane.png"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<marker
|
||||||
|
inkscape:isstock="true"
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker4404"
|
||||||
|
refX="0.0"
|
||||||
|
refY="0.0"
|
||||||
|
orient="auto"
|
||||||
|
inkscape:stockid="TriangleOutM">
|
||||||
|
<path
|
||||||
|
transform="scale(0.4)"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
id="path4402" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutM"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="marker3702"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<path
|
||||||
|
id="path3700"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.4)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:isstock="true"
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker1848"
|
||||||
|
refX="0.0"
|
||||||
|
refY="0.0"
|
||||||
|
orient="auto"
|
||||||
|
inkscape:stockid="TriangleOutM"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<path
|
||||||
|
transform="scale(0.4)"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
id="path1846" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutL"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="marker1755"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path1753"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.8)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutM"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="TriangleOutM"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true"
|
||||||
|
inkscape:collect="always">
|
||||||
|
<path
|
||||||
|
id="path962"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.4)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow2Mend"
|
||||||
|
style="overflow:visible;"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path844"
|
||||||
|
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||||
|
transform="scale(0.6) rotate(180) translate(0,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Send"
|
||||||
|
style="overflow:visible;"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path832"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.2) rotate(180) translate(6,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Mend"
|
||||||
|
style="overflow:visible;"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path826"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutL"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="TriangleOutL"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path959"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.8)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow2Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow2Mend-1"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path844-7"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||||
|
transform="scale(-0.6)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:isstock="true"
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker1848-1"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto"
|
||||||
|
inkscape:stockid="TriangleOutM">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="scale(0.4)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 5.77,0 -2.88,5 V -5 Z"
|
||||||
|
id="path1846-2" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:isstock="true"
|
||||||
|
style="overflow:visible"
|
||||||
|
id="marker1848-1-0"
|
||||||
|
refX="0"
|
||||||
|
refY="0"
|
||||||
|
orient="auto"
|
||||||
|
inkscape:stockid="TriangleOutM">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="scale(0.4)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
|
||||||
|
d="M 5.77,0 -2.88,5 V -5 Z"
|
||||||
|
id="path1846-2-9" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.98994949"
|
||||||
|
inkscape:cx="353.12978"
|
||||||
|
inkscape:cy="607.47601"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="2048"
|
||||||
|
inkscape:window-height="1089"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)"
|
||||||
|
d="M 40.892237,140.11279 H 184.68324"
|
||||||
|
id="path815"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.44465432;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend-1)"
|
||||||
|
d="M 111.09637,191.55795 V 77.837989"
|
||||||
|
id="path815-0"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.3160204;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628"
|
||||||
|
cx="111.0882"
|
||||||
|
cy="140.01112"
|
||||||
|
r="0.76016355" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8"
|
||||||
|
cx="148.20093"
|
||||||
|
cy="118.06308"
|
||||||
|
r="1.2027128" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#8c8c8c;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8-7"
|
||||||
|
cx="122.00854"
|
||||||
|
cy="111.38131"
|
||||||
|
r="1.2027128" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="149.13637"
|
||||||
|
y="123.00754"
|
||||||
|
id="text1662"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1660"
|
||||||
|
x="149.13637"
|
||||||
|
y="123.00754"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:64.99999762%;font-family:Consolas;-inkscape-font-specification:Consolas;baseline-shift:sub"
|
||||||
|
id="tspan1664">0</tspan></tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="117.36532"
|
||||||
|
y="107.94124"
|
||||||
|
id="text1662-1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1660-7"
|
||||||
|
x="117.36532"
|
||||||
|
y="107.94124"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-size:64.99999762%;baseline-shift:sub"
|
||||||
|
id="tspan1691">0</tspan><tspan
|
||||||
|
style="font-size:64.99999762%;baseline-shift:super"
|
||||||
|
id="tspan1693">2</tspan></tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutM)"
|
||||||
|
d="m 148.06731,118.19668 c -11.62623,3.07361 -18.17432,2.67269 -24.58879,-4.67721"
|
||||||
|
id="path1695"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.28318167px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1848)"
|
||||||
|
d="m 122.80545,110.44543 7.46851,-10.603435"
|
||||||
|
id="path1823"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8-1"
|
||||||
|
cx="131.8873"
|
||||||
|
cy="97.715988"
|
||||||
|
r="1.2027128" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="132.06721"
|
||||||
|
y="94.73333"
|
||||||
|
id="text1662-2"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1660-4"
|
||||||
|
x="132.06721"
|
||||||
|
y="94.73333"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-size:64.99999762%;baseline-shift:sub"
|
||||||
|
id="tspan1931">1</tspan></tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="127.48359"
|
||||||
|
y="106.24847"
|
||||||
|
id="text1935"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1933"
|
||||||
|
x="127.48359"
|
||||||
|
y="106.24847"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.17499995px;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">c</tspan></text>
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8-1-4"
|
||||||
|
cx="83.3881"
|
||||||
|
cy="93.474258"
|
||||||
|
r="1.2027128" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="83.92263"
|
||||||
|
y="90.667931"
|
||||||
|
id="text1963"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1961"
|
||||||
|
x="83.92263"
|
||||||
|
y="90.667931"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-size:64.99999762%;baseline-shift:sub"
|
||||||
|
id="tspan1965">2</tspan></tspan></text>
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#8c8c8c;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8-7-4"
|
||||||
|
cx="73.736542"
|
||||||
|
cy="106.99813"
|
||||||
|
r="1.2027128" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.28318167px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1848-1)"
|
||||||
|
d="m 74.533458,106.06225 7.46851,-10.603432"
|
||||||
|
id="path1823-5"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="66.792633"
|
||||||
|
y="105.14875"
|
||||||
|
id="text1662-1-8"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1660-7-8"
|
||||||
|
x="66.792633"
|
||||||
|
y="105.14875"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-size:65%;baseline-shift:sub"
|
||||||
|
id="tspan3362">1</tspan><tspan
|
||||||
|
style="font-size:3.21027756px;baseline-shift:super;stroke-width:0.26458332"
|
||||||
|
id="tspan1693-5">2</tspan></tspan></text>
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8-1-4-5"
|
||||||
|
cx="104.43866"
|
||||||
|
cy="160.09435"
|
||||||
|
r="1.2027128" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="104.97319"
|
||||||
|
y="157.28801"
|
||||||
|
id="text1963-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1961-6"
|
||||||
|
x="104.97319"
|
||||||
|
y="157.28801"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-size:65%;baseline-shift:sub"
|
||||||
|
id="tspan3474">3</tspan></tspan></text>
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#8c8c8c;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path1628-8-7-4-8"
|
||||||
|
cx="94.787102"
|
||||||
|
cy="173.61821"
|
||||||
|
r="1.2027128" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.28318167px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1848-1-0)"
|
||||||
|
d="m 95.584015,172.68232 7.468515,-10.60343"
|
||||||
|
id="path1823-5-8"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="87.843193"
|
||||||
|
y="171.76883"
|
||||||
|
id="text1662-1-8-4"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1660-7-8-2"
|
||||||
|
x="87.843193"
|
||||||
|
y="171.76883"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">z<tspan
|
||||||
|
style="font-size:65%;baseline-shift:sub"
|
||||||
|
id="tspan3472">2</tspan><tspan
|
||||||
|
style="font-size:3.21027756px;baseline-shift:super;stroke-width:0.26458332"
|
||||||
|
id="tspan1693-5-9">2</tspan></tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 161.77381,138.43899 v 3.96875"
|
||||||
|
id="path3476"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="162.52975"
|
||||||
|
y="144.77008"
|
||||||
|
id="text3480"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3478"
|
||||||
|
x="162.52975"
|
||||||
|
y="144.77008"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">1</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 62.552971,138.29726 v 3.96875"
|
||||||
|
id="path3476-9"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="62.552963"
|
||||||
|
y="144.62834"
|
||||||
|
id="text3480-1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3478-1"
|
||||||
|
x="62.552963"
|
||||||
|
y="144.62834"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">-1</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="180.29465"
|
||||||
|
y="145.43155"
|
||||||
|
id="text3516"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3514"
|
||||||
|
x="180.29465"
|
||||||
|
y="145.43155"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">Re</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:4.93888855px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="114.01411"
|
||||||
|
y="78.19413"
|
||||||
|
id="text3516-5"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3514-5"
|
||||||
|
x="114.01411"
|
||||||
|
y="78.19413"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Consolas;-inkscape-font-specification:Consolas;stroke-width:0.26458332">Im</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000002;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker3702);stroke-dashoffset:0"
|
||||||
|
d="M 131.0957,96.547854 C 114.25772,93.206983 83.588544,102.82868 76.03818,106.50365"
|
||||||
|
id="path3692"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4404)"
|
||||||
|
d="M 82.185379,92.605629 C 39.819072,91.505729 40.154686,168.69649 91.71736,174.07274"
|
||||||
|
id="path4394"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 21 KiB |
Reference in a new issue