restructured
This commit is contained in:
parent
c495b7c47f
commit
66cefdfd63
204 changed files with 538 additions and 13662 deletions
Binary file not shown.
|
@ -1,180 +0,0 @@
|
|||
\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}
|
|
@ -1,33 +0,0 @@
|
|||
#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");
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
#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
|
||||
|
||||
*/
|
|
@ -1,25 +0,0 @@
|
|||
#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));
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#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};
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
#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
|
||||
*/
|
|
@ -1,36 +0,0 @@
|
|||
#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
|
||||
*/
|
|
@ -1,60 +0,0 @@
|
|||
#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) Что напечатает данная программа?
|
||||
*/
|
|
@ -1,78 +0,0 @@
|
|||
#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;
|
||||
|
||||
Приведёт ли это к ошибке и, если да, то почему?
|
||||
*/
|
|
@ -1,65 +0,0 @@
|
|||
#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
|
||||
|
||||
*/
|
|
@ -1,16 +0,0 @@
|
|||
#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;
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#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
|
||||
|
||||
*/
|
|
@ -1,41 +0,0 @@
|
|||
#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>
|
||||
|
||||
*/
|
|
@ -1,10 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
float a, b;
|
||||
std::cin >> a >> b;
|
||||
std::cout << sqrt(a * b);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
Что теперь напечатает программа? Объясните результат.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
Что теперь напечатает программа? Объясните результат.
|
||||
*/
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
#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 в квадрат
|
||||
|
||||
*/
|
|
@ -1,39 +0,0 @@
|
|||
#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 в конце этой программы
|
||||
|
||||
|
||||
*/
|
|
@ -1,43 +0,0 @@
|
|||
#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
|
||||
Напечатайте этот массив
|
||||
|
||||
*/
|
|
@ -1,49 +0,0 @@
|
|||
#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-х случаях?
|
||||
*/
|
|
@ -1,52 +0,0 @@
|
|||
#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) Запустите программу, проверьте ваши догадки и объясните результат
|
||||
|
||||
*/
|
|
@ -1,44 +0,0 @@
|
|||
#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 в конце данной программы
|
||||
|
||||
*/
|
|
@ -1,46 +0,0 @@
|
|||
#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;
|
||||
|
||||
*/
|
|
@ -1,69 +0,0 @@
|
|||
#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)
|
||||
|
||||
|
||||
*/
|
|
@ -1,50 +0,0 @@
|
|||
#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)
|
||||
|
||||
|
||||
*/
|
|
@ -1,81 +0,0 @@
|
|||
#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
|
||||
|
||||
*/
|
|
@ -1,41 +0,0 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#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
|
||||
|
||||
*/
|
|
@ -1,54 +0,0 @@
|
|||
#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;
|
||||
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
#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)
|
||||
*/
|
|
@ -1,63 +0,0 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
*/
|
|
@ -1,51 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
*/
|
|
@ -1,39 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Что напечатает данная программа?
|
||||
*/
|
|
@ -1,17 +0,0 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
Напишите функцию multiplyBy2, которая принимает число по ссылке и увеличивает его в 2 раза
|
||||
Вызовите эту функцию из функции main
|
||||
|
||||
*/
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
void multiplyBy2(int& a)
|
||||
{
|
||||
a *= 2;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 10;
|
||||
multiplyBy2(x);
|
||||
cout << x << endl;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
Напишите функцию sumAndSave, которая должна принимать 3 аргумента
|
||||
Первые два аргумента по значению
|
||||
Третий аргумент по ссылке
|
||||
|
||||
Функция должна складывать первые 2 аргумента и сохранять результат по третей ссылке
|
||||
|
||||
Вызовите эту функцию из функции main
|
||||
|
||||
*/
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#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;
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
#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?
|
||||
|
||||
*/
|
|
@ -1,66 +0,0 @@
|
|||
#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
|
||||
|
||||
*/
|
|
@ -1,30 +0,0 @@
|
|||
#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 -- неправильно
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
#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;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#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);
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#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);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#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;
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
|
||||
*/
|
|
@ -1,30 +0,0 @@
|
|||
#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);
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#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)
|
||||
|
||||
*/
|
|
@ -1,44 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
#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)
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
|
@ -1,50 +0,0 @@
|
|||
#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;
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
#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)
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
|
@ -1,38 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
#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 друг с другом
|
||||
|
||||
*/
|
|
@ -1,110 +0,0 @@
|
|||
#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. Это и приводит к ошибке.
|
||||
*/
|
|
@ -1,49 +0,0 @@
|
|||
#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; выдаёт ошибку в данной программе.
|
||||
|
||||
Из-за чего это происходит и как исправить эту ошибку?
|
||||
|
||||
*/
|
|
@ -1,63 +0,0 @@
|
|||
#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 по ссылке.
|
||||
|
||||
*/
|
|
@ -1,52 +0,0 @@
|
|||
#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;
|
||||
*/
|
|
@ -1,52 +0,0 @@
|
|||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Задача:
|
||||
|
||||
Исправьте ошибки компиляции, явно приведя указатель к правильным типам.
|
||||
|
||||
*/
|
|
@ -1,13 +0,0 @@
|
|||
#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));
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#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)));
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
#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);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#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, то будет печатать всю строку в верхнем регистре
|
||||
*/
|
|
@ -1,160 +0,0 @@
|
|||
\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}
|
Binary file not shown.
Before Width: | Height: | Size: 51 KiB |
|
@ -1,490 +0,0 @@
|
|||
<?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>
|
Before Width: | Height: | Size: 21 KiB |
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue