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