restructured
This commit is contained in:
parent
c495b7c47f
commit
66cefdfd63
204 changed files with 538 additions and 13662 deletions
Binary file not shown.
|
|
@ -1,405 +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
|
||||
{~} {$\sim$}{1}
|
||||
}
|
||||
|
||||
|
||||
\title{Семинар \#2: Инкапсуляция. Классные задачи.\vspace{-5ex}}\date{}\maketitle
|
||||
\section*{Инкапсуляция}
|
||||
Инкапсуляция -- это размещение в классе/структуре данных и функций, которые с ними работают. Структуру с методами можно называть классом. Переменные класса называются полями, а функции класса -- методами.
|
||||
\begin{multicols}{2}\setlength{\columnseprule}{0.4pt}
|
||||
\textbf{Без инкапсуляции:}
|
||||
\begin{lstlisting}
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
float norm(const Point& p)
|
||||
{
|
||||
return std::sqrt(p.x*p.x + p.y*p.y);
|
||||
}
|
||||
|
||||
void normalize(Point& p)
|
||||
{
|
||||
float pnorm = norm(p);
|
||||
p.x /= pnorm;
|
||||
p.y /= pnorm;
|
||||
}
|
||||
|
||||
Point operator+(const Point& l,
|
||||
const Point& r)
|
||||
{
|
||||
Point result = {l.x + r.x, l.y + r.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Point p = {1, 2};
|
||||
normalize(p);
|
||||
std::cout << p.x << " "
|
||||
<< p.y << std::endl;
|
||||
}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{С инкапсуляцией:}
|
||||
\begin{lstlisting}
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
float norm() const
|
||||
{
|
||||
return stdsqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float pnorm = norm();
|
||||
x /= pnorm;
|
||||
y /= pnorm;
|
||||
}
|
||||
|
||||
Point operator+(const Point& r) const
|
||||
{
|
||||
Point result = {x + r.x, y + r.y};
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Point p = {1, 2};
|
||||
p.normalize();
|
||||
std::cout << p.x << " "
|
||||
<< p.y << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{multicols}
|
||||
Обратите внимание на следующие моменты:
|
||||
\begin{itemize}
|
||||
\item[--] Методы имеют прямой доступ к полям \texttt{x} и \texttt{y}. Передавать саму структуру(или ссылку на неё) в методах не нужно.
|
||||
\item[--] Вызов метода класса осуществляется с помощью оператора \texttt{.}(точка).
|
||||
\item[--] Спецификатор \texttt{const} после объявления метода (например, \texttt{float norm() const}) означает, что этот метод не будет менять поля.
|
||||
Желательно указывать этот спецификатор для всех методов, которые не изменяют объект.
|
||||
\item[--] При перегрузке бинарных операций объектом является левый аргумент, а параметром функции -- правый. Т.е. \texttt{p + q} превратится в \texttt{p.operator+(q)}.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\subsection*{Модификаторы доступа \texttt{public} и \texttt{private}}
|
||||
Модификаторы доступа служат для ограничения доступа к полям и методам класса.
|
||||
\begin{itemize}
|
||||
\item[--] \texttt{public} -- поля и методы могут использоваться где угодно
|
||||
\item[--] \texttt{private} -- поля и методы могут использовать только методы этого класса и друзья (особые функции и классы, объявленные с использованием ключевого слова \texttt{friend})
|
||||
\end{itemize}
|
||||
|
||||
\subsection*{Конструкторы}
|
||||
Конструктор -- это специальный метод, который вызывается автоматически при создании экземпляра класса.
|
||||
\begin{lstlisting}
|
||||
struct Point {
|
||||
private:
|
||||
float x, y;
|
||||
public:
|
||||
// Конструктор:
|
||||
Point(float ax, float ay)
|
||||
{
|
||||
x = ax;
|
||||
y = ay;
|
||||
}
|
||||
// другие методы
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// Если несколько разных синтаксов создания экземпляра класса с вызовом конструктора:
|
||||
Point a = Point(7, 3);
|
||||
Point b(7, 3);
|
||||
Point c = {7, 3};
|
||||
Point d {7, 3};
|
||||
// Все они делают одно и то же - создают переменную на стеке и вызывают конструктор
|
||||
// В современном C++ предпочтительным является способ d
|
||||
}
|
||||
\end{lstlisting}
|
||||
Особым видом конструктора является конструктор копирования:
|
||||
\begin{lstlisting}
|
||||
Point(const Point& p)
|
||||
\end{lstlisting}
|
||||
Он используется для создание нового экземпляра класса по уже имеющемуся экземпляру.\\
|
||||
\textbf{Задача 3:} Сделайте задание в файле \texttt{4point\_constructors.cpp}
|
||||
|
||||
\subsection*{Ключевое слово \texttt{this} и оператор присваивания}
|
||||
Ключевое слово \texttt{this} - это указатель на экземпляр класса, который можно использовать в методах этого класса.\\
|
||||
Оператор присваивания -- это просто перегруженный оператор \texttt{=}. Оператор присваивания должен вернуть ссылку на текущий объект, то есть \texttt{*this}.\\
|
||||
|
||||
Нужно различать оператор присваивания и вызов конструктора:
|
||||
\begin{lstlisting}
|
||||
Point a = Point(7, 3); // Конструктор ( оператор присваивания не вызывается )
|
||||
Point b = a; // Конструктор копирования ( оператор присваивания не вызывается )
|
||||
Point c; // Конструктор по умолчанию
|
||||
c = a; // Оператор присваивания
|
||||
\end{lstlisting}
|
||||
Оператор присваивания должен возвращать ссылку на левый аргумент.
|
||||
|
||||
\newpage
|
||||
\section*{Создаём свой класс строки}
|
||||
Строки в языке \texttt{C} представляют собой просто массивы с элементами типа \texttt{char}(однобайтовое число). Работать с такими строками не очень удобно. Нужно выделять и удалять необходимую память, следить за тем, чтобы строка помещалась в эту память на всём этапе выполнения программы, для работы со этими строками нужно использовать специальные функции из библиотеки \texttt{string.h}. Это всё может привести к ошибкам. В этом разделе мы создадим класс \texttt{String} -- класс строки, с которым удобнее и безопаснее работать, чем со строками в стиле \texttt{C}. Заготовка класса выглядит так (Это далеко не самая эффективная реализация строки, более правильная реализация создаётся в примерах кода):
|
||||
\begin{lstlisting}
|
||||
#include <cstdlib>
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t size;
|
||||
char* data;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size = 0;
|
||||
while (str[size])
|
||||
size++;
|
||||
|
||||
data = (char*)malloc(sizeof(char) * (size + 1));
|
||||
|
||||
for (int i = 0; str[i]; i++)
|
||||
data[i] = str[i];
|
||||
data[size] = '\0';
|
||||
}
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
const char* cStr() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Elephant";
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Схематично это можно представить следующим образом:
|
||||
\begin{center}
|
||||
\includegraphics[scale=0.86]{../images/string_base.png}
|
||||
\end{center}
|
||||
|
||||
\newpage
|
||||
\subsection*{Деструктор}
|
||||
В коде выше выделяется память для массива \texttt{data}. Эта память выделяется при вызове конструктора (то есть при создании объекта). Однако она нигде не освобождается. Освободить её вручную мы не можем, так как поле \texttt{data} является приватным и это бы противоречило принципу сокрытия данных. Эта память должна освобождаться автоматически при удалении объекта.
|
||||
\begin{lstlisting}
|
||||
~ String()
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection*{Перегруженные операторы класса \texttt{String}}
|
||||
\begin{itemize}
|
||||
\item \textbf{Оператор сложения:} \texttt{String operator+(const String\& right) const} \\
|
||||
Этот оператор должен создавать новый экземпляр, задавать его поля (в частности придётся выделить память под строку-сумму) и возвращать этот экземпляр.
|
||||
|
||||
\item \textbf{Оператор присваивания сложения:} \texttt{String\& operator+=(const String\& right)}\\
|
||||
Этот оператор не должен создавать новый экземпляр. Он должен изменять левый операнд (т. е. сам объект), и возвращать ссылку на этот объект (т. е. \texttt{*this}).
|
||||
|
||||
\item \textbf{Оператор присваивания:} \texttt{String\& operator=(const String\& right)}\\
|
||||
Этот оператор не должен создавать новый экземпляр. Он должен изменять левый операнд (т. е. сам объект), так чтобы он стал идентичен правому. Если размеры строк не совпадают, то в данной реализации строки вам придётся удалить память левой строки и снова выделить память нужного размера. При этом нужно отдельно рассмотреть случай когда левый и правый операнд это один и тот же объект.
|
||||
\begin{lstlisting}
|
||||
String a {"Cat"};
|
||||
a = a;
|
||||
\end{lstlisting}
|
||||
Конечно, в этом случае ничего удалять не нужно.
|
||||
|
||||
\item \textbf{Оператор сравнения:} \texttt{bool operator==(const String\& right) const}\\
|
||||
Этот оператор должен сравнивать строки (массивы \texttt{data}) и возвращать \texttt{true} или \texttt{false}.
|
||||
|
||||
\item \textbf{Оператор индексации:} \texttt{char\& operator[](unsigned int i)}\\
|
||||
Этот оператор должен возвращать ссылку на \texttt{i}-ый символ строки.
|
||||
|
||||
\item \textbf{Индексация с проверкой на выход за границы:} \texttt{char\& at(unsigned int i)}\\
|
||||
Этот метод должен проверять, что индекс \texttt{i} не выходит за границы диапазона и, если это так, возвращать ссылку на \texttt{i}-ый символ строки. Иначе, этот метод должен печатать сообщение об ошибке и завершать программу.
|
||||
\end{itemize}
|
||||
|
||||
\newpage
|
||||
\section*{Раздельная компиляция класса}
|
||||
Методы можно вынести из определения класса следующим образом:
|
||||
\begin{multicols}{2}\setlength{\columnseprule}{0.4pt}
|
||||
\textbf{Определение методов в теле класса:}
|
||||
\begin{lstlisting}
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
float norm() const
|
||||
{
|
||||
return std::sqrt(x *x + y * y);
|
||||
}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float pnorm = norm();
|
||||
x /= pnorm;
|
||||
y /= pnorm;
|
||||
}
|
||||
|
||||
Point operator+(const Point& r) const
|
||||
{
|
||||
Point result = {x + r.x, y + r.y};
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point p = {1, 2};
|
||||
p.normalize();
|
||||
std::cout << p.x << " "
|
||||
<< p.y << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
\vfill\null
|
||||
\columnbreak
|
||||
|
||||
\textbf{Определение методов вне тела класса:}
|
||||
\begin{lstlisting}
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
float norm() const;
|
||||
void normalize();
|
||||
Point operator+(const Point& r) const;
|
||||
};
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
void Point::normalize()
|
||||
{
|
||||
float pnorm = norm();
|
||||
x /= pnorm;
|
||||
y /= pnorm;
|
||||
}
|
||||
|
||||
Point Point::operator+(const Point& r) const
|
||||
{
|
||||
Point result = {x + r.x, y + r.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Point p = {1, 2};
|
||||
p.normalize();
|
||||
std::cout << p.x << " "
|
||||
<< p.y << std::endl;
|
||||
}
|
||||
\end{lstlisting}
|
||||
\end{multicols}
|
||||
|
||||
Теперь эти методы можно скомпилировать отдельно. Для этого их нужно вынести в отдельный компилируемый файл \texttt{point.cpp}, а определение класса в отдельный файл \texttt{point.h}. Так называемый заголовочный файл \texttt{point.h} нужен, так как определение класса нужно и файле \texttt{point.cpp} и в файле \texttt{main.cpp}. Для компиляции используем:
|
||||
\begin{verbatim}
|
||||
g++ main.cpp point.cpp
|
||||
\end{verbatim}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[scale=0.65]{../images/sepcompilation.png}
|
||||
\end{center}
|
||||
|
||||
\end{document}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
Объектно-ориентированное программирование (ООП) основано на представлении программы в виде совокупности взаимодействующих объектов
|
||||
|
||||
Основные принципы ООП: абстракция, инкапсуляция, наследование и полиморфизм
|
||||
|
||||
|
||||
Абстракция: использование только тех характеристик объекта, которые с достаточной точностью представляют его в данной системе.
|
||||
|
||||
В каком-то смысле обычные структуры из языка C являются примером абстракции
|
||||
|
||||
struct book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
};
|
||||
|
||||
Для описание книги в коде мы используем лишь некоторое её характеристики, достаточные для нашей задачи
|
||||
|
||||
|
||||
|
||||
Инкапсуляция: связывание данных некоторого абстрактного объекта и функций для работы с ним
|
||||
Тесно связано с инкапсуляцией такое понятие как сокрытие
|
||||
|
||||
Сокрытие: разделение данных и функций абстрактного объекта на открытые (видимые извне) и скрытые (видимые только внутри самого объекта)
|
||||
|
||||
|
||||
|
||||
Наследование и Полиморфизм будут пройдены позже в курсе
|
||||
*/
|
||||
|
||||
|
||||
|
||||
int main(){}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
Хоть язык C и не является объектно-ориентированным, некоторые зачатки подходов ООП в нём тоже есть
|
||||
Например, структуры языка C являются примером Абстракции
|
||||
|
||||
Для работы со структурами мы обычно писали функции так, что каждая из этих функций принимает на вход первым аргументом указатель на наш объект.
|
||||
Такой подход НЕ является примером Инкапсуляции, так как структура и функции для работы с ней являются независимыми друг от друга.
|
||||
При желании или по ошибке можно первым аргументом в эти функции передать вообще объект другого типа.
|
||||
|
||||
|
||||
|
||||
Эта программа написана на языке C, для компиляции используйте gcc:
|
||||
gcc 00book.c
|
||||
|
||||
Функции в этом примере делают следующее:
|
||||
|
||||
make_discount сделать скидку на книгу, но цена на книгу не может упасть ниже 0.
|
||||
print_book напечатать информацию о книге на экран
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
struct book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
};
|
||||
typedef struct book Book;
|
||||
|
||||
|
||||
void make_discount(Book* pb, int discount)
|
||||
{
|
||||
if (pb->price > discount)
|
||||
pb->price -= discount;
|
||||
else
|
||||
pb->price = 0;
|
||||
}
|
||||
|
||||
void print_book(const Book* pb)
|
||||
{
|
||||
printf("%s, price = %.2f, pages = %i\n", pb->title, pb->price, pb->pages);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book b = {"War and Peace", 1700, 900};
|
||||
|
||||
print_book(&b);
|
||||
make_discount(&b, 500);
|
||||
print_book(&b);
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
Эта программа написана на языке C++, для компиляции используйте g++:
|
||||
g++ 01book.cpp
|
||||
|
||||
В языке C++ появились ссылки, которые могут немного упростить код из предыдущего файла
|
||||
|
||||
Тем не менее, структура Book и функции для работы с ней всё ещё являются независимыми друг от друга.
|
||||
То есть тут тоже нет Инкапсуляции.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
};
|
||||
|
||||
|
||||
void makeDiscount(Book& b, int discount)
|
||||
{
|
||||
if (b.price > discount)
|
||||
b.price -= discount;
|
||||
else
|
||||
b.price = 0;
|
||||
}
|
||||
|
||||
void printBook(const Book& b)
|
||||
{
|
||||
std::cout << b.title << ", price = " << b.price << ", pages = " << b.pages << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book b = {"War and Peace", 1700, 900};
|
||||
|
||||
printBook(b);
|
||||
makeDiscount(b, 500);
|
||||
printBook(b);
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
Инкапсуляция - это объединение данных и функций для работы с ними
|
||||
|
||||
Объекты-данные, составляющие наш объект, называются полями
|
||||
Функции для работы с этими данными называются методами
|
||||
То есть у структуры Book из этого примера есть 3 поля (title, price и pages) и 2 метода (makeDiscount и print)
|
||||
|
||||
|
||||
Сравните код в этом файле с кодом из предыдущего файла и обратите внимание на следующие моменты:
|
||||
|
||||
1) Функции для работы со структурой сейчас объявляются внутри структуры.
|
||||
Получается методы как-бы принадлежат самой структуре
|
||||
Это делает невозможным использование этих функций (случайно или намерено) для работы с объектами других типов.
|
||||
|
||||
2) Вызов методов осуществляется с помощью точки, то есть такой вызов из прошлого файла:
|
||||
makeDiscount(b, 500);
|
||||
заменился на такой:
|
||||
b.makeDiscount(500);
|
||||
|
||||
То есть объект как бы сам вызывает функцию для работы со своими данными, а не передаётся первым аргументом в функцию.
|
||||
|
||||
|
||||
3) Методы "знают" о том объекте, который их вызвал
|
||||
|
||||
Например, в методе makeDiscount используется поле price без указания объекта, которому принадлежит это поле
|
||||
Но метод сам "знает" какой объект его вызвал, поэтому если его вызывает объект a вот так:
|
||||
a.makeDiscount(500);
|
||||
то в этом случае метод использует поле price объекта a
|
||||
|
||||
|
||||
4) Константный метод не меняет полей вызывающего объекта.
|
||||
Чтобы указать, что метод является константным нужно написать const в конце объявления метода
|
||||
|
||||
В предыдущем файле при передаче по константной ссылке передаваемый объект не мог измениться внутри функции
|
||||
void printBook(const Book& b) -> printBook(b) не изменит b
|
||||
|
||||
Аналог этого для константного метода:
|
||||
void print() const -> b.print() не изменит b
|
||||
Следовательно, внутри константного метода нельзя менять поля объекта
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
struct Book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
void makeDiscount(int discount)
|
||||
{
|
||||
if (price > discount)
|
||||
price -= discount;
|
||||
else
|
||||
price = 0;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
std::cout << title << ", price = " << price << ", pages = " << pages << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = {"War and Peace", 1700, 900};
|
||||
Book b = {"The Master and Margarita", 600, 400};
|
||||
|
||||
a.print();
|
||||
a.makeDiscount(500);
|
||||
a.print();
|
||||
}
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Напечатайте книгу b
|
||||
|
||||
2) Сделайте скидку для книги b в 1000 рублей и напечатайте её ещё раз
|
||||
|
||||
3) Напишите метод void setPrice(float newPrice) который будет задавать новую цену книги
|
||||
Вызовите этот метод для книги b и установите её цену в 1000 рублей. Напечатайте книгу ещё раз.
|
||||
|
||||
4) Попробуйте изменить поле внутри константного метода print, к какой ошибке это приведёт?
|
||||
|
||||
5) Можно ли вызвать метод makeDiscount из константного метода?
|
||||
|
||||
*/
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Задачи: Представлена структура Movie, описывающая фильм на Кинопоиске
|
||||
title - название фильма
|
||||
releaseYear - год выхода
|
||||
numVotes - число оценок этого фильма на Кинопоиске
|
||||
rating - рейтинт фильма на Кинопоиске
|
||||
|
||||
|
||||
|
||||
1) Напишите метод setReleaseYear, который будет принимать число и устанавливать новый год выхода фильма,
|
||||
равный этому числу. Этот метод не должен ничего возвращать.
|
||||
При этом, минимальный год выхода фильма должен быть 1900. При попытке установить меньший год выхода, метод
|
||||
всё-равно должен устанавливать год, равный 1900.
|
||||
|
||||
2) Установите год выхода фильма a на 1998, используя метод setReleaseYear. Напечатайте фильм.
|
||||
Попробуйте установить год выхода, равный 1600 Напечатайте фильм.
|
||||
|
||||
|
||||
3) Напишите метод void addVote(float x), который будет имитировать проставление оценки x фильму одним пользователем
|
||||
numVotes должен увеличиться на 1 и rating должен тоже изменится по формуле
|
||||
|
||||
новыйРейтинг = (старыйРейтиг * староеКоличествоГолосов + x) / (староеКоличествоГолосов + 1)
|
||||
|
||||
4) У данного фильма 4 голоса со средней оценкой 8.0. Добавьте ещё одну оценку, равную 10.0.
|
||||
Напечатайте фильм, новый рейтинг фильма должен быть равен 8.4.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Movie
|
||||
{
|
||||
char title[100];
|
||||
int releaseYear;
|
||||
int numVotes;
|
||||
float rating;
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", releaseYear = " << releaseYear << ", rating = " << rating
|
||||
<< " (" << numVotes << " votes)" << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Movie a = {"Dark City", 2000, 4, 8.0};
|
||||
a.print();
|
||||
}
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Movie
|
||||
{
|
||||
char title[100];
|
||||
int releaseYear;
|
||||
int numVotes;
|
||||
float rating;
|
||||
|
||||
void setReleaseYear(int year)
|
||||
{
|
||||
releaseYear = year;
|
||||
if (releaseYear < 1900)
|
||||
releaseYear = 1900;
|
||||
}
|
||||
|
||||
void addVote(int x)
|
||||
{
|
||||
rating = (rating * numVotes + x) / (numVotes + 1);
|
||||
numVotes += 1;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", releaseYear = " << releaseYear << ", rating = " << rating
|
||||
<< " (" << numVotes << " votes)" << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Movie a = {"Dark City", 2000, 4, 8.0};
|
||||
a.print();
|
||||
|
||||
a.setReleaseYear(1998);
|
||||
a.print();
|
||||
|
||||
a.setReleaseYear(1600);
|
||||
a.print();
|
||||
|
||||
a.addVote(10.0);
|
||||
a.print();
|
||||
}
|
||||
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Ключевое слово this
|
||||
|
||||
Используя указатель this внутри структуры, можно узнать адрес объекта.
|
||||
Например, если метод был вызван таким образом:
|
||||
a.printThis();
|
||||
то внутри метода this будет означать адрес объекта a
|
||||
|
||||
С помощью этого указателя можно доступаться до полей класса.
|
||||
Например, title и this->title это одно и то же внутри методов структуры.
|
||||
|
||||
this можно использовать, если имя аргумента метода совпадает с одним из полей, как, например, в методе setPrice
|
||||
Внутри метода setPrice поле price перекрывается аргументом price. Но можно всё-равно доступиться до поля price, используя указатель this
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
void printThis() const
|
||||
{
|
||||
cout << this << endl;
|
||||
}
|
||||
|
||||
void printTitle() const
|
||||
{
|
||||
cout << title << endl;
|
||||
cout << this->title << endl;
|
||||
}
|
||||
|
||||
void setPrice(float price)
|
||||
{
|
||||
this->price = price;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = {"War and Peace", 1700, 900};
|
||||
|
||||
cout << &a << endl;
|
||||
a.printThis();
|
||||
|
||||
a.printTitle();
|
||||
}
|
||||
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
Конструктор
|
||||
|
||||
Конструктор - это специальный метод, который вызывается при создании объекта
|
||||
|
||||
Конструктор Book(const char aTitle[], float aPrice, int aPages) принимает три аргумента и задаёт
|
||||
этими аргументами поля класса, а также печатает на экран слово Constructor.
|
||||
|
||||
Конструктор вызывается в строке Book a = Book("War and Peace", 1700, 900).
|
||||
В этом примере конструктор делает то же самое, что и обычная инициализация структуры: Book a = {"War and Peace", 1700, 900};
|
||||
Преимущество конструктора по сравнению с обычной инициализации структур состоит в том, что программист может сам задать то,
|
||||
что будет происходить при создании объекта.
|
||||
|
||||
|
||||
Напоминание:
|
||||
Функция strcpy из библиотеки string.h языка C принимает на вход 2 строки и просто копирует
|
||||
содержимое второй строки в первую строку.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
Book(const char aTitle[], float aPrice, int aPages)
|
||||
{
|
||||
cout << "Constructor" << endl;
|
||||
strcpy(title, aTitle);
|
||||
price = aPrice;
|
||||
pages = aPages;
|
||||
}
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
std::cout << title << ", price = " << price << ", pages = " << pages << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book("War and Peace", 1700, 900);
|
||||
a.print();
|
||||
|
||||
Book b = Book("The Great Gatsby", 800, -600);
|
||||
b.print();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Предположим, что программист, работая с наши классом Book, ошибся в конструкторе и установил у книги отрицательное количество страниц.
|
||||
|
||||
Измените конструктор таким образом, чтобы программа не создавала объект с отрицательным числом страниц.
|
||||
Вместо этого она должна писать сообщение об ошибке и выходить из программы.
|
||||
Для выхода из программы можно использовать функцию std::exit(1) из библиотеки <cstdlib>
|
||||
|
||||
|
||||
2) Конструкторы можно перегружать также, как и обычные функции и методы.
|
||||
Добавьте новый конструктор, который не будет принимать никаких аргументов и будет создавать объект с полями равными
|
||||
title: "Default" price: 0 pages: 0
|
||||
Вызовите этот конструктор из main
|
||||
|
||||
Конструктор, который не принимает аргументов, называется конструктором по умолчанию.
|
||||
|
||||
|
||||
|
||||
3) Конструкторы можно перегружать также, как и обычные функции и методы.
|
||||
Добавьте новый конструктор, который будет принимать объект типа Book (по константной ссылке)
|
||||
и будет задавать поля текущего объекта, используя поля аргумента
|
||||
Вызовите этот конструктор из main
|
||||
|
||||
Конструктор, который создаёт объект, используя объект такого-же типа, называется конструктором копирования.
|
||||
*/
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <string.h>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
Book(const char aTitle[], float aPrice, int aPages)
|
||||
{
|
||||
cout << "Constructor" << endl;
|
||||
strcpy(title, aTitle);
|
||||
price = aPrice;
|
||||
pages = aPages;
|
||||
|
||||
if (pages < 0)
|
||||
{
|
||||
cout << "Error! Number of pages can't be negative!" << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Book()
|
||||
{
|
||||
cout << "Default Construtor" << endl;
|
||||
strcpy(title, "Default");
|
||||
price = 0;
|
||||
pages = 0;
|
||||
}
|
||||
|
||||
|
||||
Book(const Book& b)
|
||||
{
|
||||
cout << "Copy Construtor" << endl;
|
||||
strcpy(title, b.title);
|
||||
price = b.price;
|
||||
pages = b.pages;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", price = " << price << ", pages = " << pages << endl << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book("War and Peace", 1700, 900);
|
||||
a.print();
|
||||
|
||||
Book b = Book();
|
||||
b.print();
|
||||
|
||||
Book c = Book(a);
|
||||
c.print();
|
||||
|
||||
Book d = Book("The Great Gatsby", 800, -600);
|
||||
d.print();
|
||||
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
Сокрытие данных - это разделение данных и функций абстрактного объекта на открытые (видимые извне) и скрытые (видимые только внутри самого объекта)
|
||||
В языке C++ это реализуется с помощью модификаторов доступа public и private
|
||||
|
||||
Все поля и методы объявленные в секции public называются публичными и могут быть доступны извне структуры
|
||||
Все поля и методы объявленные в секции private называются приватными и не могут быть доступны извне структуры
|
||||
Приватные поля и методы могут быть доступны только в методах самого структуры (а также в друзьях, но об этом позже)
|
||||
|
||||
|
||||
Назначение сокрытия данных заключается в том, чтобы объекты нельзя было 'поломать' извне
|
||||
'Поломать' тут означает задать поля объекта бессмысленным образом
|
||||
|
||||
Например, в нашем примере мы бы могли поломать объект просто сделав поля price или pages отрицательными
|
||||
a.pages = -100;
|
||||
но благодаря тому, что поле pages является приватным, это сделать нельзя.
|
||||
|
||||
|
||||
Учитывая проверку в конструкторе, получается, что поля pages и price в принципе никогда не смогут стать отрицательными.
|
||||
Таким образом мы уберегли себя от возникновения ошибок при неправильном задании полей структуры.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
private:
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
public:
|
||||
Book(const char aTitle[], float aPrice, int aPages)
|
||||
{
|
||||
if (aPages < 0 || aPrice < 0 || strlen(aTitle) >= 100)
|
||||
{
|
||||
cout << "Error while creating Book!" << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
strcpy(title, aTitle);
|
||||
price = aPrice;
|
||||
pages = aPages;
|
||||
}
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book("War and Peace", 1700, 900);
|
||||
a.print();
|
||||
|
||||
a.pages = -100;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
Синтаксис инициализации с помощью коструктора
|
||||
|
||||
Язык C++ имеет очень длинную историю и на её протяжении в язык добавлялись новые возможности
|
||||
В итоге в языке часто можно сделать одно и то же разными методами.
|
||||
|
||||
В частности, вызвать конструктор можно 5-ю разными способами.
|
||||
В этой программе строки для создания книг a, b, c, d, e делают одно и то же, несмотря, что имеют разный синтаксис
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
private:
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
public:
|
||||
Book(const char aTitle[], float aPrice, int aPages)
|
||||
{
|
||||
cout << "Constructor" << endl;
|
||||
strcpy(title, aTitle);
|
||||
price = aPrice;
|
||||
pages = aPages;
|
||||
}
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book("War and Peace", 1000, 500);
|
||||
|
||||
Book b("War and Peace", 1000, 500);
|
||||
|
||||
Book c = {"War and Peace", 1000, 500};
|
||||
|
||||
Book d = Book{"War and Peace", 1000, 500};
|
||||
|
||||
Book e {"War and Peace", 1000, 500};
|
||||
|
||||
a.print();
|
||||
b.print();
|
||||
c.print();
|
||||
d.print();
|
||||
e.print();
|
||||
}
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Добавьте к классу конструктор по умолчанию:
|
||||
|
||||
Book()
|
||||
{
|
||||
cout << "Default Constructor" << endl;
|
||||
strcpy(title, "default");
|
||||
price = 0;
|
||||
pages = 0;
|
||||
}
|
||||
|
||||
Создайте с помощью этого конструктора 5 книг, вызвав его 5-ю разными способами
|
||||
|
||||
*/
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Book
|
||||
{
|
||||
private:
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
public:
|
||||
Book(const char aTitle[], float aPrice, int aPages)
|
||||
{
|
||||
cout << "Constructor" << endl;
|
||||
strcpy(title, aTitle);
|
||||
price = aPrice;
|
||||
pages = aPages;
|
||||
}
|
||||
|
||||
Book()
|
||||
{
|
||||
cout << "Default Constructor" << endl;
|
||||
strcpy(title, "default");
|
||||
price = 0;
|
||||
pages = 0;
|
||||
}
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book();
|
||||
|
||||
// Book b(); // этот способ не работает, так как его невозможно отличить от объявления функции (зато добавился способ f)
|
||||
|
||||
Book c = {};
|
||||
|
||||
Book d = Book{};
|
||||
|
||||
Book e {};
|
||||
|
||||
Book f; // в отличии от переменных базовых типов, тут произойдёт инициализация (конструктором по умолчанию)
|
||||
|
||||
a.print();
|
||||
c.print();
|
||||
d.print();
|
||||
e.print();
|
||||
f.print();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
Классы. Ключевое слово class.
|
||||
|
||||
На самом деле классы мы уже прошли. Структуры с методоми из предыдущих файлов это и есть классы.
|
||||
Для объявления класса может использоваться ключевое слово class.
|
||||
|
||||
Разница между этими ключевым словами минимальна
|
||||
- при использовании struct все поля и методы по умолчанию публичны
|
||||
- при использовании class все поля и методы по умолчанию приватны
|
||||
Но, так как мы указываем private и public для всех членов, то разницы нет вообще.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl;
|
||||
|
||||
class Book
|
||||
{
|
||||
private:
|
||||
char title[100];
|
||||
float price;
|
||||
int pages;
|
||||
|
||||
public:
|
||||
Book(const char aTitle[], float aPrice, int aPages)
|
||||
{
|
||||
if (aPages < 0 || aPrice < 0 || strlen(aTitle) >= 100)
|
||||
{
|
||||
cout << "Error while creating Book!" << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
strcpy(title, aTitle);
|
||||
price = aPrice;
|
||||
pages = aPages;
|
||||
}
|
||||
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book("War and Peace", 1700, 900);
|
||||
a.print();
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Некоторые замечания по оформлению
|
||||
|
||||
1) Как правило в классе сначала описываются публичные методы, а потом приватные
|
||||
Так делают потому что если другой программист захочет воспользоваться вашим классом,
|
||||
то его будет в первую очередь будет интересовать что ваш класс может делать
|
||||
и уже потом его будет интересовать строение класса.
|
||||
|
||||
|
||||
2) Приватные поля класса желательно называть так, чтобы их можно было отличить от обычных переменных
|
||||
Это может сильно упростить понимание при написании/использовании больших програм и библиотек
|
||||
В данном курсе мы будем называть приватные поля начиная с буквы m
|
||||
Например, mTitle вместо title
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
class Book
|
||||
{
|
||||
public:
|
||||
Book(const char title[], float price, int pages)
|
||||
{
|
||||
if (pages < 0 || price < 0 || strlen(title) >= 100)
|
||||
{
|
||||
cout << "Error while creating Book!" << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
strcpy(mTitle, title);
|
||||
mPrice = price;
|
||||
mPages = pages;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
cout << mTitle << ", price = " << mPrice << ", pages = " << mPages << endl;
|
||||
}
|
||||
|
||||
private:
|
||||
char mTitle[100];
|
||||
float mPrice;
|
||||
int mPages;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book("War and Peace", 1700, 900);
|
||||
a.print();
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Это программа на языке C, для компиляции:
|
||||
gcc 00point.c
|
||||
./a.out
|
||||
|
||||
Опишем структуру точки в двумерном пространстве на языке C
|
||||
|
||||
Точка задаётся двумя координатами x и y
|
||||
Так как эта структура имеет очень маленький размер (всего 8 байт), то в функции
|
||||
её можно передавать по значению, а не по константному указателю.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
struct point
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
typedef struct point Point;
|
||||
|
||||
|
||||
void point_print(Point a)
|
||||
{
|
||||
printf("(%.2f, %.2f)\n", a.x, a.y);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
Point b = {-4.6, 2.4};
|
||||
|
||||
point_print(a);
|
||||
point_print(b);
|
||||
}
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Напишите функцию point_add,
|
||||
которая будет принимать две точки и возвращать их сумму
|
||||
|
||||
2) Напишите функцию point_norm,
|
||||
которая будет принимать точку и возвращать расстояние до этой точки от начала координат
|
||||
Будем называть расстояние от точки до начала координат нормой точки
|
||||
Для вычисления корня числа можно использовать функцию sqrt из math.h
|
||||
|
||||
3) Напишите функцию point_mult,
|
||||
которая будет принимать на вход точку и число k типа float и возвращать точку, координаты которой
|
||||
равны координатам изначальной точки, умноженные на число k
|
||||
|
||||
4) Напишите функцию point_normalize,
|
||||
которая будет принимать точку по указателю и делить координаты точки на норму точки
|
||||
Эта функция не должна ничего возвращать
|
||||
*/
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
Это программа на языке C, для компиляции:
|
||||
gcc 00point_solution.c
|
||||
./a.out
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
struct point
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
typedef struct point Point;
|
||||
|
||||
|
||||
void point_print(Point a)
|
||||
{
|
||||
printf("(%.2f, %.2f)\n", a.x, a.y);
|
||||
}
|
||||
|
||||
Point point_add(Point a, Point b)
|
||||
{
|
||||
Point result = {a.x + b.x, a.y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float point_norm(Point a)
|
||||
{
|
||||
return sqrtf(a.x * a.x + a.y * a.y);
|
||||
}
|
||||
|
||||
Point point_mult(Point a, float k)
|
||||
{
|
||||
Point result = {k * a.x, k * a.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void point_normalize(Point* pa)
|
||||
{
|
||||
float norm = point_norm(*pa);
|
||||
pa->x /= norm;
|
||||
pa->y /= norm;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
Point b = {-4.6, 2.4};
|
||||
|
||||
point_print(a);
|
||||
point_print(b);
|
||||
|
||||
Point c = point_add(a, b);
|
||||
point_print(c);
|
||||
|
||||
point_print(point_mult(c, 1.5f));
|
||||
|
||||
point_normalize(&c);
|
||||
point_print(c);
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
Это программа на языке C++, для компиляции:
|
||||
g++ 01point.cpp
|
||||
|
||||
Та же самая точка, но на языке C++
|
||||
|
||||
В этом файле была видоизменена программа из предыдущего файла.
|
||||
Были использованы перегруженные операторы для более удобного сложения и умножения точек.
|
||||
Также была использована ссылка вместо указателя в функции pointNormalize.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
void pointPrint(Point a)
|
||||
{
|
||||
cout << std::setprecision(2) << "(" << a.x << ", " << a.y << ")" << endl;
|
||||
}
|
||||
|
||||
Point operator+(Point a, Point b)
|
||||
{
|
||||
Point result = {a.x + b.x, a.y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float pointNorm(Point a)
|
||||
{
|
||||
return std::sqrt(a.x * a.x + a.y * a.y);
|
||||
}
|
||||
|
||||
Point operator*(Point a, float k)
|
||||
{
|
||||
Point result = {k * a.x, k * a.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void pointNormalize(Point& a)
|
||||
{
|
||||
float norm = pointNorm(a);
|
||||
a.x /= norm;
|
||||
a.y /= norm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
Point b = {-4.6, 2.4};
|
||||
|
||||
pointPrint(a);
|
||||
pointPrint(b);
|
||||
|
||||
Point c = a + b;
|
||||
pointPrint(c);
|
||||
|
||||
pointPrint(c * 1.5f);
|
||||
|
||||
pointNormalize(c);
|
||||
pointPrint(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Инкапсулируйте функции operator+, pointNorm, operator* и pointNormalize
|
||||
Их нужно сделать методами, то есть положить внутрь структуры Point
|
||||
Не забудьте сделать соответствующие методы константными
|
||||
|
||||
2) Можно сделать то же самое с функцией printPoint, а можно поступить по-другому
|
||||
и перегрузить оператор << для типов std::ostream и Point
|
||||
*/
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
Обратите внимание на следующие моменты в этом решении:
|
||||
|
||||
1) При переносе функций внутрь класса у них стало на 1 аргумент меньше
|
||||
Просто потому что все методы неявно принимают вызывающий их объект
|
||||
|
||||
Например, если a это точка, то при вызове:
|
||||
a.norm()
|
||||
|
||||
метод norm 'знает', что его вызвала имено точка a и может доступаться до её полей x и y
|
||||
|
||||
|
||||
2) Перегруженные операторы тоже могут быть методами
|
||||
При этом оператор преобразуется следующим образом:
|
||||
|
||||
a @ b -> a.operator@(b)
|
||||
где на месте @ может быть любой бинарный оператор
|
||||
|
||||
Например, сложение преобразуется так:
|
||||
a + b -> a.operator+(b)
|
||||
|
||||
Обратите внимание, что перегруженный оператор может стать методом только первого аргумента
|
||||
|
||||
|
||||
3) Перегрузка оператора << для типов std::ostream и Point
|
||||
Для более удобного вывода на экран можно перегрузить этот оператор
|
||||
|
||||
Когда компилятор встретит выражение cout << a где cout имеет тип std::ostream, а имеет тип Point
|
||||
то он вызовет эту функцию.
|
||||
Эта функция должна вызывать ссылку на cout так как результатом cout << a тоже должен быть cout
|
||||
чтобы мы могли выводить цепочкой, например так: cout << a << b << endl
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
Point b = {-4.6, 2.4};
|
||||
|
||||
cout << a << endl;
|
||||
cout << b << endl;
|
||||
|
||||
Point c = a + b;
|
||||
cout << c << endl;
|
||||
|
||||
cout << c * 1.5f << endl;
|
||||
|
||||
c.normalize();
|
||||
cout << c << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {2.1, 1.5};
|
||||
|
||||
cout << a * 2 << endl;
|
||||
cout << 2 * a << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) В этой программе выражение a * 2 вычисляется правильно, но
|
||||
выражение 2 * a даёт ошибку.
|
||||
|
||||
Из-за чего это происходит? Исправьте ситуацию так, чтобы выражение 2 * a также вычислялось.
|
||||
|
||||
|
||||
2) Можно ли сделать перегруженный оператор << методом класса Point?
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
Решения:
|
||||
|
||||
1) Выражение a * 2 вычисляется так как есть перегруженный оператор a.operator*(2)
|
||||
Выражение 2 * a даёт ошибку так как не было перегруженного оператора operator*(2, a)
|
||||
|
||||
Но его можно просто написать, как это сделано ниже.
|
||||
|
||||
Сделать этот оператор методом мы не можем, так как перегруженный оператор может быть методом
|
||||
только первого аргумента, первый аргумент в данном случае это число целочисленного типа float.
|
||||
Добавить метод в тип float мы не можем, так как float это вообще не класс.
|
||||
|
||||
Замечание: Литерал 2 на самом деле имеет тип int, но int может конвертироваться во float если нужно
|
||||
|
||||
|
||||
2) Можно ли сделать перегруженный оператор << методом класса Point?
|
||||
|
||||
Нет, нельзя. Перегруженный оператор может быть методом только первого аргумента.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Point operator*(float k, Point a)
|
||||
{
|
||||
return a * k;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {2.1, 1.5};
|
||||
|
||||
cout << a * 2 << endl;
|
||||
cout << 2 * a << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
До этого момента поля x и y класса Point были публичными
|
||||
|
||||
Обычно, мы не хотим делать поля публичными, так как мы не хотим, чтобы поля могли бы быть заданы некоректным значением извне класса.
|
||||
Однако, в случае класса Point некорректных значений для x и y просто не существует - любое вещественное число будет
|
||||
корректным для значения координаты точки.
|
||||
Поэтому нет ничего плохого, чтобы сделать x и y публичными для класса Point
|
||||
|
||||
|
||||
Но давайте сделаем класс с немного более сложным поведением.
|
||||
Точка RestrictedPoint - это будет точка, которая может находится только в квадрате [0,1]x[0,1]
|
||||
То есть поле x может принимать значения только от 0 до 1 и поле y может принимать значения только от 0 до 1.
|
||||
|
||||
Сделаем поля x и y приватными (и назовём их mx и my)
|
||||
Теперь до них можно будет доступиться только в методах класса RestrictedPoint и в друзьях.
|
||||
|
||||
Чтобы можно было работать с этими полями вне класса напишем методы
|
||||
getx, gety, setx, sety
|
||||
Такие методы для получения полей и записи в поля класса называются геттерами и сеттерами
|
||||
Функции getx и gety просто возвращают соответствующие координаты
|
||||
Функции setx и sety меняют соответствующие координаты и следят, чтобы они находились в диапазоне от 0 до 1
|
||||
|
||||
|
||||
Нам понадобится стандартная функция std::clamp из <algorithm>, которая принимает на вход три числа и
|
||||
если первое число находится в промежутке между вторым и третьим, то clamp возвращает первое число
|
||||
если первое число меньше, чем второе, то clamp возвращает второе число
|
||||
если первое число больше, чем третье, то clamp возвращает третье число
|
||||
Грубо говоря clamp ограничивает число в заданых пределах
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
|
||||
class RestrictedPoint
|
||||
{
|
||||
private:
|
||||
float mx, my;
|
||||
|
||||
public:
|
||||
|
||||
RestrictedPoint(float x, float y)
|
||||
{
|
||||
mx = std::clamp(x, 0.0f, 1.0f);
|
||||
my = std::clamp(y, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
RestrictedPoint()
|
||||
{
|
||||
mx = 0;
|
||||
my = 0;
|
||||
}
|
||||
|
||||
float getx() const
|
||||
{
|
||||
return mx;
|
||||
}
|
||||
|
||||
float gety() const
|
||||
{
|
||||
return my;
|
||||
}
|
||||
|
||||
void setx(float x)
|
||||
{
|
||||
mx = std::clamp(x, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void sety(float y)
|
||||
{
|
||||
my = std::clamp(y, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float norm() const
|
||||
{
|
||||
return std::sqrt(mx*mx + my*my);
|
||||
}
|
||||
|
||||
RestrictedPoint operator+(const RestrictedPoint& right) const
|
||||
{
|
||||
RestrictedPoint result;
|
||||
result.mx = std::clamp(mx + right.mx, 0.0f, 1.0f);
|
||||
result.my = std::clamp(my + right.my, 0.0f, 1.0f);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const RestrictedPoint& a)
|
||||
{
|
||||
out << "(" << a.getx() << ", " << a.gety() << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
RestrictedPoint a = RestrictedPoint(0.5, 1.2);
|
||||
cout << a << endl;
|
||||
|
||||
a.setx(2);
|
||||
cout << a << endl;
|
||||
|
||||
a.sety(-5);
|
||||
cout << a << endl;
|
||||
|
||||
|
||||
RestrictedPoint b = RestrictedPoint(0.4, 0.2);
|
||||
RestrictedPoint c = RestrictedPoint(0.8, 0.4);
|
||||
cout << c + b << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Добавьте к классу RestrictedPoint оператор умножения на число типа float
|
||||
|
||||
*/
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
Создадим свою строку
|
||||
|
||||
Один из самых главных недостатков языка C это работа со строками.
|
||||
Строки в языке C это просто массивы элементов типа char
|
||||
char str[100]; или char* p = malloc(100);
|
||||
|
||||
В языке C работать со строками очень неудобно по многим причинам:
|
||||
- Нужно постоянно следить за тем, чтобы строка умещалась в памяти, которая под нею выделена.
|
||||
- Строку можно выделить на Стеке, используя обычный массив, и тогда её вместимость нельзя будет увеличить,
|
||||
а можно выделить в Куче, но тогда придётся самостоятельно выделять и освобождать память
|
||||
и следить, чтобы не произошли утечки памяти.
|
||||
- Строки нельзя просто копировать, сравнивать, складывать и т. д. Для этого нужно использовать
|
||||
специальные функции типа strcpy и другие функции из библиотеки <string.h>.
|
||||
|
||||
|
||||
Создадим же удобный класс строки
|
||||
Такой чтобы можно было удобно создавать строки, приравнивать, складывать и сравнивать.
|
||||
Не заботясь о выделении/удалении памяти, и о том, что строка помещается в выделенную память.
|
||||
|
||||
Чтобы можно было писать вот такой код:
|
||||
|
||||
String a = "Cat";
|
||||
String b = "Dog";
|
||||
cout << a << " " << b << endl;
|
||||
|
||||
String c = "Mouse";
|
||||
c = a + b;
|
||||
c += "Bear";
|
||||
|
||||
if (c == "CatDogBear")
|
||||
cout << "Yes" << endl;
|
||||
|
||||
c = a;
|
||||
cout << c << endl;
|
||||
|
||||
|
||||
(String в переводе с английского это Строка)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
int main() {}
|
||||
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
|
||||
Создадим строку, которая при создании (т.е в конструкторе) будет автоматически выделять необходимую память в Куче.
|
||||
В чём-то реализация этой строки будет похожа на реализацию динамического массива из прошлого семестра.
|
||||
|
||||
У класса строки 3 поля:
|
||||
|
||||
mSize - размер - количество символов в строке (без учёта \0)
|
||||
mCapacity - вместимость - количество выделенной памяти в Куче
|
||||
mpData - указатель на выделенную память в Куче. В этой памяти строка будет иметь такой же вид, как и строка языка C.
|
||||
В частности она будет иметь символ '\0' на конце.
|
||||
Символ '\0' на конце оставим, чтобы было удобно конвертировать нашу строку в строку в стиле C.
|
||||
|
||||
|
||||
Размер и вместимость это разные величины.
|
||||
|
||||
Например, для хранения строки "Cat" может быть выделено памяти под 10 символов, хоть и под эту строку было бы достаточно всего 4.
|
||||
Представьте, что у вас есть длинная строка и вы хотите удалить последний символ в ней.
|
||||
Если бы мы не хранили вместимость, а всегда выделяли памяти в притык, то в этом простом случае нам бы пришлось
|
||||
перевыделять память и копировать всю строку в новую память.
|
||||
Если же мы храним вместимость, то достаточно всего лишь уменьшить размер на 1 и поставит \0 в новый конец строки.
|
||||
|
||||
|
||||
|
||||
Теперь создадим конструктор, который будет выделять память и заполнять его нужным образом
|
||||
|
||||
Конструктор String(const char* str) конструирует нашу строку из строки в стиле C.
|
||||
Принимаем на вход именно константную строку, так как в этом случае в конструктор можно будет
|
||||
передать как константные, так и неконстантые строки.
|
||||
Если бы мы написали так String(char* str) , то в конструктор нельзя было бы передать константные строки.
|
||||
|
||||
|
||||
В строках:
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
мы находим размер переданной строки (strlen не используем, чтобы не связываться со старой библиотекой)
|
||||
Вместимость на 1 больше, так как нужно учесть память под символ /0
|
||||
|
||||
|
||||
В строке:
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
выделяем необходимую память
|
||||
|
||||
|
||||
В строках:
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
|
||||
копируем содержимое переданной строки в только что выделенную память.
|
||||
|
||||
|
||||
Другие методы класса String:
|
||||
|
||||
getSize - возвращает размер строки
|
||||
getCapacity - возвращает вместимость строки
|
||||
cStr - возвращает строку в стиле C, то есть указатель на массив из char-ов с конечным символом \0
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
size_t getCapacity() const
|
||||
{
|
||||
return mCapacity;
|
||||
}
|
||||
|
||||
const char* cStr() const
|
||||
{
|
||||
return mpData;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Dog";
|
||||
String c = "Lion";
|
||||
|
||||
cout << a << endl << b << endl << c << endl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Задание:
|
||||
|
||||
1) Создайте конструктор String(), который будет создавать пустую строку
|
||||
(mSize = 0, mCapacity = 1, строка mpData содержит в себе 1 символ ('\0'))
|
||||
|
||||
Конструктор, который не принимает аргументов называется конструктором по умолчанию
|
||||
|
||||
|
||||
2) Создайте конструктор String(size_t n, char a), который будет создавать строку из n символов a
|
||||
(mSize = n, mCapacity = n + 1, строка mpData содержит в себе n + 1 символ (n раз a и '\0'))
|
||||
|
||||
|
||||
2) Создайте конструктор String(const String& s), который будет создавать строку String из другой строки String
|
||||
(mSize = s.mSize, mCapacity = s.mCapacity, строка mpData содержит в себе копию строки s.mpData)
|
||||
|
||||
Конструктор, который создаёт объект по другому объекту такого же типа называется конструктором копирования.
|
||||
|
||||
|
||||
Протестируйте эти конструкторы:
|
||||
String a;
|
||||
cout << a << endl;
|
||||
|
||||
String b(10, 'q');
|
||||
cout << b << endl;
|
||||
|
||||
String c("Cat");
|
||||
cout << c << endl;
|
||||
|
||||
String d(c);
|
||||
cout << d << endl;
|
||||
*/
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "Construtor from const char*" << endl;
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "Default Construtor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(size_t n, char a)
|
||||
{
|
||||
cout << "Construtor n equal characters" << endl;
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "Copy Constructor" << endl;
|
||||
mSize = s.mSize;
|
||||
mCapacity = s.mCapacity;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
size_t getCapacity() const
|
||||
{
|
||||
return mCapacity;
|
||||
}
|
||||
|
||||
const char* cStr() const
|
||||
{
|
||||
return mpData;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a;
|
||||
cout << a << endl << endl;
|
||||
|
||||
String b(10, 'q');
|
||||
cout << b << endl << endl;
|
||||
|
||||
|
||||
String c = "Cat";
|
||||
cout << c << endl << endl;
|
||||
|
||||
|
||||
String d(c);
|
||||
cout << c << endl << endl;
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
Делегирующий конструктор
|
||||
|
||||
В разных конструкторах может быть повторяющийся код.
|
||||
Повторений кода иногда можно избежать если писать один конструктор на основе уже написанного.
|
||||
|
||||
Это можно сделать с помощью синтаксиса так называемого делегирующего конструктора
|
||||
После объявления конструктора, но перед его телом можно написать двоеточие и вызвать другой конструктор
|
||||
|
||||
Например:
|
||||
|
||||
String() : String("")
|
||||
{
|
||||
cout << "Default Constructor" << endl;
|
||||
}
|
||||
|
||||
Этот конструктор сначала вызовет конструктор String(const char* str) с аргументом "" (то есть пустой строкой)
|
||||
а потом исполнит тело данного коструктора (в данном случае напечатает Default Constructor).
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "Constructor" << endl;
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("")
|
||||
{
|
||||
cout << "Default Constructor" << endl;
|
||||
}
|
||||
|
||||
|
||||
String(const String& s) : String(s.cStr())
|
||||
{
|
||||
cout << "Copy Constructor" << endl;
|
||||
}
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
size_t getCapacity() const
|
||||
{
|
||||
return mCapacity;
|
||||
}
|
||||
|
||||
const char* cStr() const
|
||||
{
|
||||
return mpData;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a;
|
||||
cout << "a = " << a << endl << endl;
|
||||
|
||||
|
||||
String b = "Cat";
|
||||
cout << "b = " << b << endl << endl;
|
||||
|
||||
|
||||
String c(b);
|
||||
cout << "c = " << c << endl << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
Попробуйте понять без запуска, что напечатает данная программа
|
||||
*/
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
В конструкторе мы выделили память с malloc, но нигде в программе её не освободили
|
||||
Соответственно, в предыдущей программе у нас есть очень серьёзная ошибка - утечка памяти.
|
||||
|
||||
Где же нужно освобождать память?
|
||||
Если память была выделена в конструкторе при создании объекта, то выделять её нужно при удалении объекта.
|
||||
Для того, чтобы испольнить ваш код при удалении объекта существует специальный метод, который называется Деструктор.
|
||||
|
||||
|
||||
Деструктор - это специальный метод, который вызывается тогда, когда объект уничтожается
|
||||
Объекты, созданные на стеке удаляются при выходе из области видимости
|
||||
|
||||
|
||||
Синтаксис деструктора такой:
|
||||
|
||||
~String()
|
||||
{
|
||||
...
|
||||
}
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "Constructor of " << str << endl;
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "Destructor of " << mpData << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
size_t getCapacity() const
|
||||
{
|
||||
return mCapacity;
|
||||
}
|
||||
|
||||
const char* cStr() const
|
||||
{
|
||||
return mpData;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Dog";
|
||||
|
||||
if (true)
|
||||
{
|
||||
String c = "Lion";
|
||||
}
|
||||
|
||||
String c = "Bear";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задание:
|
||||
|
||||
1) Что напечатает данная программа?
|
||||
В каком порядке вызовутся конструкторы
|
||||
|
||||
|
||||
2) Если создать строку String в цикле, то будут ли каждую итерацию вызываться конструкторы и деструкторы?
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
String s = "Elephant";
|
||||
}
|
||||
*/
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
Оператор сложения
|
||||
|
||||
Оператор сложения для строк должен принимать 2 строки и возвращать новую строку, равную результату конкатенации двух строк
|
||||
Если строка a = "Cat" , а строка b = "Mouse" , то их конкатенация это a + b = "CatMouse"
|
||||
|
||||
Оператор сложения должен принимать свои аргументы по константной ссылке
|
||||
по ссылке, чтобы не копировать объект лишний раз при передаче в функцию
|
||||
по константной, потому что мы не будем менять принимаемые объекты внутри функции
|
||||
|
||||
|
||||
То есть прототип оператора сложения, если его делать с помощью обычной функции, должен выглядеть так:
|
||||
|
||||
String operator+(const String& a, const String& b)
|
||||
|
||||
|
||||
Прототип оператора сложения, если его делать с помощью метода класса String, должен выглядеть так:
|
||||
|
||||
String operator+(const String& b) const
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "Constructor of " << str << endl;
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "Destructor of " << mpData << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Mouse";
|
||||
|
||||
cout << a + b << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задание:
|
||||
|
||||
1) Написать оператор сложения для строки String в виде свободной функции
|
||||
В этом случае эту функцию нужно сделать дружественной классу String,
|
||||
чтобы она имела доступ к приватным полям класса
|
||||
|
||||
2) Написать оператор сложения для строки String в виде метода класса String
|
||||
*/
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
|
||||
friend String operator+(const String& a, const String& b);
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
String operator+(const String& a, const String& b)
|
||||
{
|
||||
String result;
|
||||
|
||||
result.mSize = a.mSize + b.mSize;
|
||||
result.mCapacity = result.mSize + 1;
|
||||
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||
|
||||
for (size_t i = 0; i < a.mSize; ++i)
|
||||
result.mpData[i] = a.mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[a.mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Mouse";
|
||||
|
||||
cout << a + b << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
|
||||
result.mSize = mSize + b.mSize;
|
||||
result.mCapacity = result.mSize + 1;
|
||||
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
|
||||
friend String operator+(const String& a, const String& b);
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Mouse";
|
||||
|
||||
cout << a + b << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
Оператор присваивания
|
||||
|
||||
Оператор присваивания можно сделать только в виде метода
|
||||
Такой метод должен
|
||||
- принимать один аргумент - это правый аргумент оператора присваивания,
|
||||
- менять объект, вызвавший оператор (то есть левый аргумент оператора присваивания)
|
||||
- возвращать ссылку на объект, вызвавший оператор (то есть объект слева от оператора присваивания)
|
||||
|
||||
|
||||
Почему оператор присваивания должен возвращать ссылку на левый аргумент?
|
||||
Чтобы оператор присваивания работал аналогично тому как работает оператор присваивания для обычных типов
|
||||
|
||||
Рассмотрим следующий пример:
|
||||
|
||||
int a, b, c;
|
||||
a = b = c = 123; // все переменные станут равны 123, операторы выполняются справа налево
|
||||
|
||||
(a = 1) = 2; // a станет равной 2
|
||||
|
||||
|
||||
Мы хотим, чтобы и такой код работал:
|
||||
|
||||
String a, b, c;
|
||||
a = b = c = "Cat";
|
||||
|
||||
(a = "Dog") = "Mouse";
|
||||
|
||||
|
||||
Прототип оператора присваивания как метода класса String должен выглядеть так:
|
||||
|
||||
String& operator=(const String& b)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
// Ваш код нужно написать здесь
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Mouse";
|
||||
String c;
|
||||
|
||||
a = b;
|
||||
cout << a << endl;
|
||||
|
||||
a = b = c = "Elephant";
|
||||
cout << a << endl;
|
||||
cout << b << endl;
|
||||
cout << c << endl;
|
||||
|
||||
(a = "Dog") = "Axolotl";
|
||||
cout << a << endl;
|
||||
|
||||
a = a;
|
||||
cout << a << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задание:
|
||||
|
||||
1) Написать оператор присваивания для строки String в виде метода класса String
|
||||
|
||||
Не забудьте учесть случай:
|
||||
|
||||
String a = "Cat";
|
||||
a = a;
|
||||
*/
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Mouse";
|
||||
String c;
|
||||
|
||||
a = b;
|
||||
cout << a << endl;
|
||||
|
||||
a = b = c = "Elephant";
|
||||
cout << a << endl;
|
||||
cout << b << endl;
|
||||
cout << c << endl;
|
||||
|
||||
(a = "Dog") = "Axolotl";
|
||||
cout << a << endl;
|
||||
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
Оператор присваивания сложения +=
|
||||
|
||||
Очень похож на оператор присваивания, разница только в том, каким станет левый операнд после применения этого оператора
|
||||
К левому операнду в этом случае должна прибавиться копия правого оператора
|
||||
|
||||
Если a = "Cat" , b = "Dog" , то после применения a += b строка a будет равна "CatDog"
|
||||
|
||||
|
||||
|
||||
Прототип оператора присваивания сложения как метода класса String должен выглядеть так:
|
||||
|
||||
String& operator+=(const String& b)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
|
||||
result.mSize = mSize + b.mSize;
|
||||
result.mCapacity = result.mSize + 1;
|
||||
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
// Ваш код нужно написать здесь
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b = "Elephant";
|
||||
|
||||
b += a;
|
||||
|
||||
cout << b << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задание:
|
||||
|
||||
1) Написать оператор присваивания сложения для строки String в виде метода класса String
|
||||
|
||||
Подсказка: можно использовать уже написанные операторы, чтобы реализовать этот
|
||||
*/
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
|
||||
result.mSize = mSize + b.mSize;
|
||||
result.mCapacity = result.mSize + 1;
|
||||
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b = "Elephant";
|
||||
|
||||
b += a;
|
||||
|
||||
cout << b << endl;
|
||||
}
|
||||
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
По решению предыдущего занятия понятно, что операторы + = и += взаимосвязаны.
|
||||
|
||||
Если реализованы операторы + и = можно, используя их, реализовать оператор +=
|
||||
Если реализованы операторы = и += можно, используя их, реализовать оператор +
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
if (mCapacity < mSize + right.mSize + 1)
|
||||
{
|
||||
mCapacity = mSize + right.mSize + 1;
|
||||
char* pNewData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
pNewData[i] = mpData[i];
|
||||
|
||||
std::free(mpData);
|
||||
mpData = pNewData;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < right.mSize; ++i)
|
||||
mpData[mSize + i] = right.mpData[i];
|
||||
|
||||
mSize += right.mSize;
|
||||
mpData[mSize] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b = "Elephant";
|
||||
|
||||
cout << a + b << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Напишите оператор + , используя операторы = и +=
|
||||
|
||||
*/
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
if (mCapacity < mSize + right.mSize + 1)
|
||||
{
|
||||
mCapacity = mSize + right.mSize + 1;
|
||||
char* pNewData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
pNewData[i] = mpData[i];
|
||||
|
||||
std::free(mpData);
|
||||
mpData = pNewData;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < right.mSize; ++i)
|
||||
mpData[mSize + i] = right.mpData[i];
|
||||
|
||||
mSize += right.mSize;
|
||||
mpData[mSize] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result = *this;
|
||||
result += b;
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b = "Elephant";
|
||||
|
||||
cout << a + b << endl;
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
Операторы сравнения == != > >= < <=
|
||||
|
||||
К строкам можно применять операторы сравнения.
|
||||
|
||||
Очевидно, когда строки равны: должны быть равны размеры строк (mSize) и все символы от 0 до mSize
|
||||
При этом вместимость (mCapacity) у равных строк может отличаться
|
||||
|
||||
Как сравнивать строки на больше/меньше? В этом случае сравниваем лексикографически, то есть, по алфавиту.
|
||||
То слово, которое находилось бы в орфографическом словаре позже и будет большим.
|
||||
Например, "Cat" > "Camel" так как первые 2 буквы совпадают, а третья буква у слова Cat идёт дальше по алфавиту
|
||||
|
||||
|
||||
Более точное сравнение такое: мы сравниваем посимвольно до первого несовпадающего символа
|
||||
Если мы нашли первые несовпадающий символ и не дошли до конца в обоих строках, то та строка будет больше,
|
||||
у которой этот символ больше.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
cout << std::boolalpha;
|
||||
|
||||
String a = "Cat";
|
||||
String b = "Camel";
|
||||
|
||||
cout << (a > b) << endl;
|
||||
cout << (a < b) << endl;
|
||||
cout << (a == b) << endl;
|
||||
cout << (a == a) << endl;
|
||||
|
||||
|
||||
String c = "Catharsis";
|
||||
|
||||
cout << (a > c) << endl;
|
||||
cout << (a < c) << endl;
|
||||
cout << (a == c) << endl;
|
||||
cout << (a != c) << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Напишите операторы == != > >= < <= для класса String
|
||||
Подсказка: можно использовать уже написанные сравнения
|
||||
Например, если вы написали оператор > , то очень просто написать оператор <= , используя оператор >
|
||||
|
||||
*/
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool operator<(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator<=(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
cout << std::boolalpha;
|
||||
|
||||
String a = "Cat";
|
||||
String b = "Camel";
|
||||
|
||||
cout << (a > b) << endl;
|
||||
cout << (a < b) << endl;
|
||||
cout << (a == b) << endl;
|
||||
cout << (a == a) << endl;
|
||||
|
||||
|
||||
String c = "Catharsis";
|
||||
|
||||
cout << (a > c) << endl;
|
||||
cout << (a < c) << endl;
|
||||
cout << (a == c) << endl;
|
||||
cout << (a != c) << endl;
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
Операторы индексации []
|
||||
|
||||
Чтобы получить доступ к одному символу у строки в стиле C можно использовать оператор индексации (квадратные скобочки).
|
||||
Хотелось бы иметь такую же возможность и для нашей строки.
|
||||
|
||||
Для этого можно перегрузить оператор индексации:
|
||||
|
||||
char& operator[](size_t i)
|
||||
|
||||
Этот оператор вызавется при взятии символа по индексу, например, если a это строка типа String,
|
||||
|
||||
a[i] будет восприниматься компилятором как a.operator[](i)
|
||||
|
||||
|
||||
Оператор индексации должен возвращать ссылку на символ, чтобы можно было менять соответствующий символ
|
||||
|
||||
a[i] = 'A';
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
|
||||
cout << a[0] << endl;
|
||||
cout << a[2] << endl;
|
||||
cout << a[4] << endl;
|
||||
|
||||
|
||||
cout << a.at(0) << endl;
|
||||
cout << a.at(2) << endl;
|
||||
cout << a.at(4) << endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Напишите оператор индексации для класса String
|
||||
|
||||
|
||||
2) Напишите метод at, который будет работать аналогично оператору индексации, только с тем отличием, что
|
||||
если на вход приходит неправильный индекс (т. е. индекс >= mSize), то метод at должен печатать сообщение
|
||||
об ошибке и завершать программу.
|
||||
Для завершения программы используйте функцию std::exit(1) из библиотеки <cstdlib>.
|
||||
|
||||
*/
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& at(size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
cout << "Error! Index is out of bounds." << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
|
||||
cout << a[0] << endl;
|
||||
cout << a[2] << endl;
|
||||
cout << a[4] << endl;
|
||||
|
||||
|
||||
cout << a.at(0) << endl;
|
||||
cout << a.at(2) << endl;
|
||||
cout << a.at(4) << endl;
|
||||
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
Напишем ещё 2 очень полезных метода:
|
||||
|
||||
1) reserve - увеличивает вместимость строки, на вход методу передаётся новая вместмость
|
||||
если новая вместимость меньше старой, то ничего не происходит (вместимость не уменьшается)
|
||||
размер и содержимое строки не меняется
|
||||
|
||||
|
||||
2) resize - изменяет размер строки, на вход методу передаётся новый размер
|
||||
если новый размер меньше старого, то строка усекается
|
||||
при необходимости увеличивает вместимость
|
||||
|
||||
Используя эти два метода можно немного упростить код для операторов сложения и присваивания.
|
||||
Эти методы могут быть полезны и для программиста, который будет работать с нашей строкой, поэтому сделаем их публичными.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Dog";
|
||||
|
||||
cout << a.getCapacity() << endl;
|
||||
a.reserve(10);
|
||||
cout << a.getCapacity() << endl;
|
||||
|
||||
cout << a + b << endl;
|
||||
|
||||
|
||||
String c = "Sapere Aude";
|
||||
cout << c << endl;
|
||||
|
||||
c.resize(6);
|
||||
cout << c << endl;
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = "Dog";
|
||||
|
||||
cout << a.getCapacity() << endl;
|
||||
a.reserve(10);
|
||||
cout << a.getCapacity() << endl;
|
||||
|
||||
cout << a + b << endl;
|
||||
|
||||
|
||||
String c = "Sapere Aude";
|
||||
cout << c << endl;
|
||||
|
||||
c.resize(6);
|
||||
cout << c << endl;
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
Считывание строки с экрана
|
||||
|
||||
Помимо удобной печати на экран с помощью объекта std::cout, хотелось бы добавить удобное считываие строки
|
||||
с помощью объекта std::cin.
|
||||
|
||||
Для этого нужно перегрузить оператор >> с объектами типа std::istream и String, то есть написать функцию:
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& str)
|
||||
|
||||
Эта функция должна считывать символы из стандартного входа и добавлять в строку
|
||||
Основная проблема в том, что мы не знаем сколько символов нужно считать, поэтому нужно считывать
|
||||
посимвольно и добавлять символы по одному в строку пока не встретим пробельный символ (' ' или '\n' или '\t')
|
||||
|
||||
Для упрощения программы можно написать дополнительные методы
|
||||
|
||||
void clear() - метод, который будет очищать строку
|
||||
mSize = 0, mCapacity = 1, строка по адресу mpData равна "\0"
|
||||
|
||||
void addCharacter(char c) - добавляет символ в конец строки
|
||||
если у строки не хватает вместимости, то удваивает вместимость.
|
||||
|
||||
|
||||
Для того, чтобы считать символ из стандартного входа можно использовать метод get класса istream
|
||||
Этот метод возвращает следующий символ из стандартного входа
|
||||
|
||||
char x = cin.get();
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a, b;
|
||||
cin >> a >> b;
|
||||
cout << a + b;
|
||||
|
||||
a.addCharacter('!');
|
||||
cout << a << endl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
1) Напишите метод clear.
|
||||
|
||||
2) Напишите метод addCharacter.
|
||||
|
||||
3) Напишите перегруженный оператор << для считывания строки с экрана.
|
||||
|
||||
*/
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a, b;
|
||||
cin >> a >> b;
|
||||
cout << a + b << endl;
|
||||
|
||||
a.addCharacter('!');
|
||||
cout << a << endl;
|
||||
}
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
/*
|
||||
Собираем все методы вместе. Получилась строка, которой можно удобно пользоваться и не задумываться о выделении памяти.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String(size_t n, char a)
|
||||
{
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool operator<(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator<=(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& at(size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
cout << "Error! Index is out of bounds." << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b;
|
||||
cin >> b;
|
||||
String c = b;
|
||||
|
||||
if (a + c == "MouseLion")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
if (a > "Mice")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
c[0] = 'P';
|
||||
cout << c << endl;
|
||||
|
||||
c += a;
|
||||
cout << c << endl;
|
||||
|
||||
c = c + String(10, 'q');
|
||||
cout << c << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Задача:
|
||||
|
||||
|
||||
1) Напищите программу, которая будет считывать слова (используйте cin) в бесконечном цикле и каждый
|
||||
раз печатать сумму всех слов. Например, если пользователь ввёл Hello, то программа должна напечатать
|
||||
Hello и запросить следующее слово. Если затем пользователь введёт World, то программа должна будет
|
||||
напечатать HelloWorld и запросить следуещее слово и так далее.
|
||||
Программа должна останавливаться если пользователь ввёл слово "quit".
|
||||
*/
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String(size_t n, char a)
|
||||
{
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool operator<(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator<=(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& at(size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
cout << "Error! Index is out of bounds." << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String all;
|
||||
String nextWord;
|
||||
|
||||
while (true)
|
||||
{
|
||||
cin >> nextWord;
|
||||
if (nextWord == "quit")
|
||||
break;
|
||||
|
||||
all += nextWord;
|
||||
cout << all << endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
Рассмотрим при каких условиях происходит вызов того или иного метода.
|
||||
|
||||
Для этого будем использовать класс String, в котором была добавлена печать на экран для конструкторов,
|
||||
деструктора и оператора присваивания.
|
||||
Например, конструктор по умолчанию будет печатать Default Constructor и т. д.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String b = a;
|
||||
}
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Какие методы вызовутся в строке
|
||||
|
||||
String a = "Cat";
|
||||
|
||||
Выберите один из вариантов:
|
||||
|
||||
а) Только конструктор из const char*
|
||||
б) Только оператор присваивания
|
||||
в) И конструктор из const char* и оператор присваивания
|
||||
|
||||
|
||||
2) Какие методы вызовутся в строке
|
||||
|
||||
String b = a;
|
||||
|
||||
Выберите один из вариантов:
|
||||
|
||||
а) Только конструктор копирования
|
||||
б) Только оператор присваивания
|
||||
в) И конструктор копирования и оператор присваивания
|
||||
|
||||
|
||||
|
||||
3) Проверьте ваши догадки скомпилировав и запустив программу
|
||||
|
||||
*/
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
Рассмотрим при каких условиях происходит вызов того или иного метода.
|
||||
|
||||
Для этого будем использовать класс String, в котором была добавлена печать на экран для конструкторов,
|
||||
деструктора и оператора присваивания.
|
||||
Например, конструктор по умолчанию будет печатать Default Constructor и т. д.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
String c;
|
||||
c = a;
|
||||
}
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Какие методы класса String вызовутся в данной программе.
|
||||
|
||||
2) Проверьте ваши догадки, скомпилировав и запустив программу
|
||||
*/
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
Решения:
|
||||
|
||||
1) String a = "Cat";
|
||||
|
||||
Будет вызван только конструктор из const char*
|
||||
|
||||
|
||||
|
||||
2) String b = a;
|
||||
|
||||
Будет вызван только конструктор копирования
|
||||
|
||||
Несмотря на то, что в этих выражениях присутствует символ = оператор присваивания в этих случаях не вызывается.
|
||||
|
||||
|
||||
|
||||
|
||||
3) String c;
|
||||
c = a;
|
||||
|
||||
Будет вызван конструктор по умолчанию в строке String c;
|
||||
А потом будет вызван оператор присваивания в строке c = a;
|
||||
|
||||
|
||||
Получается символ = может использоваться для обозначения двух разных вещей: инициализации и присваивания.
|
||||
|
||||
|
||||
String a = "Cat"; // Инициализация строкой "Cat" (вызов коструктора от const char*)
|
||||
|
||||
String b = a; // Инициализация объектом a (вызов коструктора копирования)
|
||||
|
||||
String c; // Инициализация по умолчанию (вызов конструктора по умолчанию)
|
||||
c = a; // Присваивание (вызов метода operator=)
|
||||
|
||||
*/
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
Посмотрим какие особые методы вызываются при передаче объекта в функцию.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void print(String s)
|
||||
{
|
||||
cout << s << endl;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
print(a);
|
||||
}
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Какие методы класса String вызовутся в данной программе.
|
||||
|
||||
|
||||
2) Проверьте ваши догадки скомпилировав и запустив программу
|
||||
|
||||
|
||||
3) Что если мы будем передавать объект String в функцию print не по значению, а по ссылке, то есть изменим
|
||||
функцию print на следующую:
|
||||
|
||||
void print(const String& s)
|
||||
{
|
||||
cout << s << endl;
|
||||
}
|
||||
|
||||
Какие методы будут вызваны теперь?
|
||||
|
||||
*/
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
Решения:
|
||||
|
||||
1) В случае:
|
||||
|
||||
void print(String s)
|
||||
{
|
||||
cout << s << endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
print(a);
|
||||
}
|
||||
|
||||
Вызовутся следующие методы:
|
||||
|
||||
1) Конструктор строки из "Cat"
|
||||
|
||||
|
||||
2) При передаче объекта в функцию по значению, он должен быть скопирован.
|
||||
Соответственно при вызове print(a) объект a должен скопироваться в объект s функции print.
|
||||
Для обычных типов вроде int тут бы произошло побайтовое копирование, но для классов вызывается конструктор копирования.
|
||||
|
||||
|
||||
3) Внутри функции print объект s печатается на экран. Затем мы выходим из функции print и уничтожаем все локальные объекты этой функции.
|
||||
Соответственно вызовется деструктор для объекта s.
|
||||
|
||||
|
||||
4) Затем мы выходим из функции main и уничтожаем все объекты, локальные для функции main.
|
||||
Соответственно вызовется деструктор для объекта a.
|
||||
|
||||
|
||||
|
||||
|
||||
3) В случае:
|
||||
|
||||
void print(const String& s)
|
||||
{
|
||||
cout << s << endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
print(a);
|
||||
}
|
||||
|
||||
Вызовутся следующие методы:
|
||||
|
||||
1) Конструктор строки из "Cat"
|
||||
|
||||
|
||||
При передаче объекта в функцию по ссылке, этот объект в функцию не копируется.
|
||||
Поэтому никаких конструкторов копирования не вызывается.
|
||||
|
||||
|
||||
2) Деструктор для строки a из функии main.
|
||||
|
||||
|
||||
Получается, что обычно передавать объекты в функции более эффективно по ссылке, а не по значению.
|
||||
|
||||
*/
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
Особые методы при передачах в функцию
|
||||
|
||||
Посмотрим какие особые методы вызываются при передаче объекта в функцию
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void changeFirstLetter(String s)
|
||||
{
|
||||
s[0] = 'B';
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
cout << a << endl;
|
||||
|
||||
changeFirstLetter(a);
|
||||
cout << a << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Задачи:
|
||||
|
||||
1) Какие методы класса String вызовутся в данной программе.
|
||||
|
||||
2) Проверьте ваши догадки скомпилировав и запустив программу
|
||||
|
||||
3) Функция changeFirstLetter должна была менять первую букву нашей строки на букву 'B', но это не происходит и
|
||||
строка a после вызова changeFirstLetter(a) остаётся неизменной.
|
||||
Почему это происходит и как изменить функцию changeFirstLetter чтобы она меняла первую букву переданной строки.
|
||||
*/
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void changeFirstLetter(String& s)
|
||||
{
|
||||
s[0] = 'B';
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
cout << a << endl;
|
||||
|
||||
changeFirstLetter(a);
|
||||
cout << a << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Решение:
|
||||
|
||||
В такую функцию:
|
||||
|
||||
void changeFirstLetter(String s)
|
||||
{
|
||||
s[0] = 'B';
|
||||
}
|
||||
|
||||
строка передавалась по значению и, следовательно, происходило копирование этой строки в объект s функции changeFirstLetter.
|
||||
Функция changeFirstLetter меняла первую букву копии нашей строки, но оригинальная строка не менялась.
|
||||
|
||||
|
||||
Для того, чтобы функция changeFirstLetter меняла оригинальную строку ей нужно передавать объект не по значению, а по ссылке вот так:
|
||||
|
||||
void changeFirstLetter(String& s)
|
||||
{
|
||||
s[0] = 'B';
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
Различный синтаксис вызова конструкторов
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Cat";
|
||||
|
||||
String b = String("Dog");
|
||||
|
||||
String c("Mouse");
|
||||
|
||||
String d = {"Tiger"};
|
||||
|
||||
String e = String{"Axolotl"};
|
||||
|
||||
String f {"Lion"};
|
||||
}
|
||||
|
||||
/*
|
||||
Ввиду того, что язык C++ имеет длинную историю, на протяжении которой в язык добавлялись новые возможности,
|
||||
в языке существует множество способов сделать одно и то же разными способами.
|
||||
|
||||
Один из ярких примеров этого является инициализация объекта. В этом примере создаются 6 строк. Синтаксис различается,
|
||||
но в данном случае все эти строки по сути делают одно и то же: cоздают объект с помощью конструктора от const char*.
|
||||
При этом не вызывается никаких конструкторов копирования или операторов присваивания.
|
||||
|
||||
В современном языке C++ предпочтительным способом инициализации является вариант f:
|
||||
|
||||
String f {"Lion"};
|
||||
|
||||
|
||||
|
||||
Задачи:
|
||||
|
||||
1) Что напечатает данная программа?
|
||||
В каком порядке вызовутся конструкторы и в каком порядке вызовутся деструкторы?
|
||||
|
||||
2) Скомпилируйте программу и запустите, чтобы проверить ваши догадки.
|
||||
|
||||
3) Создайте 5 объектов типа String с помощью конструктора по умолчанию, используя разный синтаксис вызова конструктора.
|
||||
|
||||
4) Пусть есть объект x типа String:
|
||||
|
||||
String x = "Cat";
|
||||
|
||||
Создайте 6 объектов типа String с помощью конструктора копирования, используя разный синтаксис вызова конструктора.
|
||||
Все новые объекты должны копировать объект x.
|
||||
|
||||
*/
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a;
|
||||
|
||||
String b = String();
|
||||
|
||||
// String c();
|
||||
|
||||
String d = {};
|
||||
|
||||
String e = String{};
|
||||
|
||||
String f {};
|
||||
}
|
||||
|
||||
/*
|
||||
Аналогично есть множество вариантов синтаксиса вызова конструктора по умолчанию.
|
||||
|
||||
Только такой вариант вызова конструктора не работает:
|
||||
|
||||
String c();
|
||||
|
||||
Потому что в этом случае компилятор считает, что это объявление функции по имени c, которая ничего не принимает и возвращает объект типа String.
|
||||
|
||||
*/
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String x = "Cat";
|
||||
|
||||
|
||||
String a = x;
|
||||
|
||||
String b = String(x);
|
||||
|
||||
String c(x);
|
||||
|
||||
String d = {x};
|
||||
|
||||
String e = String{x};
|
||||
|
||||
String f {x};
|
||||
}
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
Особые методы
|
||||
|
||||
В прошлой части мы рассмотрели различные методы классов. Некоторые из этих методов называются особыми.
|
||||
Они выделяются по сравнению с другими методами тем, что они будут создаваться автоматически даже если вы их не напишите.
|
||||
К особым методам класса относятся:
|
||||
|
||||
|
||||
1) Конструктор по умолчанию. То есть конструктор, который не принимает ни одного аргумента.
|
||||
В случае со строкой String это контруктор:
|
||||
|
||||
String()
|
||||
|
||||
|
||||
2) Конструктор копирования. То есть конструктор, который создаёт объект из другого объекта такого же типа, что и данный.
|
||||
В случае со строкой String это контруктор:
|
||||
|
||||
String(const String& s)
|
||||
|
||||
|
||||
3) Деструктор. Это метод, который вызывается при удалении объекта. В отличии от конструкторов, деструктор у объекта всегда один.
|
||||
В случае со строкой String это:
|
||||
|
||||
~String()
|
||||
|
||||
|
||||
4) Оператор присваивания. Это метод, который вызывается при присваивании одного метода класса String другому методу класса String.
|
||||
В случае со строкой String это:
|
||||
|
||||
String& operator=(const String& right)
|
||||
|
||||
|
||||
|
||||
5,6) Есть ещё 2 особых метода, которые мы пройдём позже.
|
||||
|
||||
|
||||
Все остальные методы, включаю другие конструкторы и перегруженные операторы, к особым методам не относятся.
|
||||
То есть остальные методы не могут создаваться автоматически.
|
||||
|
||||
|
||||
В этой части мы рассмотрим при каких условиях происходит вызов того или иного особого метода.
|
||||
Для этого будем использовать класс String, в котором была добавлена печать на экран для каждого особого метода и для коструктора из const char*.
|
||||
Например, конструктор по умолчанию будет печатать Default Constructor и т. д.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Book
|
||||
{
|
||||
public:
|
||||
String title;
|
||||
int pages;
|
||||
float price;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a = Book();
|
||||
cout << a.title << " " << a.pages << " " << a.price << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
У класса Book есть 3 поля, одно из которых имеет тип String.
|
||||
Но у класса Book не определён ни один метод. У него нет никаких конструкторов или перегруженных операторов.
|
||||
|
||||
Теперь посмотрим на код:
|
||||
|
||||
Book a = Book();
|
||||
|
||||
Тут мы создаём объект типа Book с помощью конструктора по умолчанию. Но у Book не написан конструктор по умолчанию!
|
||||
Что же произойдёт в этом случае? Ошибка? Нет, на самом деле в этом случае конструктор будет создан автоматически. Вот такой:
|
||||
|
||||
Book() {}
|
||||
|
||||
Автоматически-сгенерированный конструктор по умолчанию ничего не делает.
|
||||
Тем не менее, перед вызовом этого конструктора, компилятор должен вызвать конструктор по умолчанию для всех полей класса,
|
||||
у которых есть конструктор по умолчанию.
|
||||
В этом случае, при создании объекта класса Book с помощью конструктора по умолчанию, будет вызван конструктор по умолчанию класса String.
|
||||
|
||||
|
||||
|
||||
Аналогично, автоматически сгенерируется деструктор по умолчанию, вот такой:
|
||||
|
||||
~Book() {}
|
||||
|
||||
Он пустой, но нужно помнить, что после вызова деструктора класса, автоматически вызываются деструкторы для все его полей (у которых есть деструкторы)
|
||||
В этом случае, после вызова деструктора класса Book вызовется деструктор класса String.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Задачи:
|
||||
|
||||
1) Скомпилируйте программу, запустите и убедитесь, что в этом примере вызываются
|
||||
конструктор по умолчанию и деструктор класса String.
|
||||
*/
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
Особые методы
|
||||
|
||||
Проверим, что компилятор автоматически генерирует конструктор копирования и оператор присваивания.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Book
|
||||
{
|
||||
public:
|
||||
String title;
|
||||
int pages;
|
||||
float price;
|
||||
};
|
||||
|
||||
void print(Book x)
|
||||
{
|
||||
cout << x.title << " " << x.pages << " " << x.price << endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a;
|
||||
|
||||
a.title = "War and Peace";
|
||||
a.pages = 1000;
|
||||
a.price = 1100;
|
||||
|
||||
Book b;
|
||||
b = a;
|
||||
print(b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Что напечатает данная программа?
|
||||
|
||||
Разберём код из функции main подробно:
|
||||
|
||||
1) Вызывается автоматически сгенерированный конструктор по умолчанию в строке:
|
||||
|
||||
Book a;
|
||||
|
||||
При этом перед вызовом этого конструктора вызовется и конструктор класса String поля title.
|
||||
|
||||
|
||||
|
||||
2) Полям объекта a присваиваются некоторые значения:
|
||||
|
||||
a.title = "War and Peace";
|
||||
a.pages = 1000;
|
||||
a.price = 1100;
|
||||
|
||||
Интересно отметить, что строка a.title = "War and Peace" работает, несмотря на то, что слева от знака
|
||||
присваивания стоит объект типа String, а справа от знака присваивания стоит объект типа const char[14].
|
||||
Типы не совпадают, но это работает, так как у класса String есть конструктор от const char*.
|
||||
Таким образом, сначала вызовется этот конструктор и создастся временный объект типа String, а потом
|
||||
вызовется оператор присваивания между двумя объектами класса String.
|
||||
После этого временный объект удалится и, соответственно, вызовется его деструктор.
|
||||
|
||||
|
||||
|
||||
3) Вызывается автоматически сгенерированный конструктор по умолчанию в строке:
|
||||
|
||||
Book b;
|
||||
|
||||
|
||||
|
||||
4) Вызывается автоматически сгенерированный перегруженный оператор присваивания в строке:
|
||||
|
||||
b = a;
|
||||
|
||||
Автоматически сгенерированный оператор присваивания применяет оператор присваивания для каждого поля.
|
||||
|
||||
|
||||
|
||||
5) Передача в функцию print осуществляется по значению. Следовательно в строке
|
||||
|
||||
print(b);
|
||||
|
||||
объект b должен быть скопирован внутрь функции. Для этого должен быть вызван конструктор копирования.
|
||||
Конструктор копирования у класса Book не написан, поэтому компилятор автоматически его сгенерирует.
|
||||
|
||||
Автоматически сгенерированный конструктор копирования копирует каждое поле в соответствующее поле нового объекта.
|
||||
Если у поля есть конструктор копирования (как например у класса String), то вызывается конструктор копирования этого поля.
|
||||
Если у поля нет конструктора копирования (как например у int или float), то поле просто копируется побайтово.
|
||||
|
||||
|
||||
6) Выходим из функции print и вызываем деструктор для объекта x.
|
||||
|
||||
7) Выходим из функции main и вызываем деструкторы для объектов a и b.
|
||||
*/
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
Замечание по поводу автоматической генерации конструктора по умолчанию
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Book
|
||||
{
|
||||
public:
|
||||
String title;
|
||||
int pages;
|
||||
float price;
|
||||
|
||||
Book(const String& aTitle, int aPages, float aPrice)
|
||||
{
|
||||
title = aTitle;
|
||||
pages = aPages;
|
||||
price = aPrice;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Конструктор по умолчанию не генерируется автоматически если у класса написан хотя бы один конструктор (любой).
|
||||
Например, в этом пример у класса Book написан один конструктор:
|
||||
|
||||
Book(const String& aTitle, int aPages, float aPrice)
|
||||
|
||||
Поэтому в данном случае конструктор по умочанию автоматически генерироваться не будет.
|
||||
|
||||
|
||||
|
||||
В строке Book a; должен быть вызван конструктор по умолчанию.
|
||||
Но у класса Book такого конструктора нет и автоматически он не был создан. Поэтому эта строка приведёт к ошибке.
|
||||
|
||||
|
||||
|
||||
Но конструктор копирования, оператор присваивания и деструктор автоматически генерироваться будут.
|
||||
|
||||
|
||||
Задача:
|
||||
|
||||
Исправьте ошибку, написав конструктор по умолчанию самостоятельно.
|
||||
*/
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
Удалённые методы
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; str[i]; ++i)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Book
|
||||
{
|
||||
public:
|
||||
String title;
|
||||
int pages;
|
||||
float price;
|
||||
|
||||
Book() {};
|
||||
|
||||
Book(const String& aTitle, int aPages, float aPrice)
|
||||
{
|
||||
title = aTitle;
|
||||
pages = aPages;
|
||||
price = aPrice;
|
||||
}
|
||||
|
||||
Book(const Book& b) = delete;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Book a;
|
||||
|
||||
Book b = a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Если же вы не хотите создавать какой-либо метод и не хотите чтобы он создавался автоматически,
|
||||
то его можно удалить с помощью ключевого слова delete.
|
||||
|
||||
|
||||
Например, в этом примере у класса Book удалён конструктор копирования вот так:
|
||||
|
||||
Book(const Book& b) = delete;
|
||||
|
||||
Это означает, что конструктор копирования не создастся автоматически.
|
||||
Поэтому в строке:
|
||||
|
||||
Book b = a;
|
||||
|
||||
произойдёт ошибка компиляции.
|
||||
|
||||
|
||||
|
||||
Задача:
|
||||
|
||||
1) Можно ли передать объект класса с удалённым конструктором копирования в функцию по значению?
|
||||
|
||||
Например, если есть функция:
|
||||
|
||||
void print(Book b)
|
||||
{
|
||||
cout << b.title << " "<< b.pages << " " << b.price << endl;
|
||||
}
|
||||
|
||||
Можно ли туда передать что-нибудь?
|
||||
|
||||
*/
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
/*
|
||||
Неявное приведение типа с помощью конструктора от одного параметра.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* s)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << s << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (s[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; s[i]; ++i)
|
||||
mpData[i] = s[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void print(String s)
|
||||
{
|
||||
cout << s << endl;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a;
|
||||
a = "Dog";
|
||||
|
||||
print("Mouse");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Одна из скрытых вещей, где используются конструкторы, это для неявного приведения типов.
|
||||
|
||||
Рассмотрим следующие строки:
|
||||
|
||||
String a;
|
||||
a = "Dog";
|
||||
|
||||
Во второй строке должен вызваться оператор присваивания.
|
||||
Слева от оператора присваивания стоит объект типа String, а справа от оператора присваивания стоит объект типа const char[4].
|
||||
Поэтому должен вызваться метод operator=(const char* s) класса String. (при передаче в функцию массив автоматически конвертируется в указатель)
|
||||
Но такого метода в классе String нет. Что же тогда будет сделано?
|
||||
|
||||
В этом случае будет сделано следующее:
|
||||
|
||||
1) Будет создан временный объект типа String с использованием конструтора String(const char* s).
|
||||
2) Будет вызван оператор присваивания operator=(const String& s). Объекту a присвоится временный объект.
|
||||
3) Временный объект будет уничтожен, при этом вызовется деструктор класса String.
|
||||
|
||||
|
||||
|
||||
|
||||
Рассмотрим строку:
|
||||
|
||||
print("Mouse");
|
||||
|
||||
Функция print должна принимать объект типа String, но на вход ей приходит объект типа const char[6].
|
||||
Что будет сделано в этом случае?
|
||||
И в этом случае всё сработает, так как объект s функции print будет создан с помощью конструктора класса String от const char*.
|
||||
|
||||
|
||||
|
||||
Таким образом конструктор от одного аргумента автоматически используется для неявного приведения одного типа в другой.
|
||||
|
||||
|
||||
|
||||
Задачи:
|
||||
|
||||
1) Что если мы напишем конструктор класса String от числа типа int.
|
||||
Этот конструктор будет принимать число n и создавать строку, состоящую из n символов 'a'
|
||||
|
||||
|
||||
String(int n)
|
||||
{
|
||||
cout << "String Constructor from int (" << n << ")" << endl;
|
||||
|
||||
mSize = n;
|
||||
mCapacity = mSize + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = 'a';
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
Будет ли этот конструктор использоваться для неявного приведения чисел типа int в строки типа String?
|
||||
Например, будет ли работать следующий код:
|
||||
|
||||
String b;
|
||||
b = 5;
|
||||
|
||||
(b будет строкой состоящей из 5 символов 'a' ?)
|
||||
|
||||
|
||||
print(10);
|
||||
|
||||
(напечатает строку, состоящую из 10 символов 'a')
|
||||
*/
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
Ключевое слово explicit.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using std::cout, std::endl, std::size_t;
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
size_t mSize;
|
||||
size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
explicit String(const char* s)
|
||||
{
|
||||
cout << "String Constructor from const char* (" << s << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
while (s[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; s[i]; ++i)
|
||||
mpData[i] = s[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
explicit String(int n)
|
||||
{
|
||||
cout << "String Constructor from int (" << n << ")" << endl;
|
||||
|
||||
mSize = n;
|
||||
mCapacity = mSize + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = 'a';
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String()
|
||||
{
|
||||
cout << "String Default Constructor" << endl;
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char));
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
String(const String& s)
|
||||
{
|
||||
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||
|
||||
size_t i = 0;
|
||||
mSize = s.mSize;
|
||||
mCapacity = mSize + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = s.mpData[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
cout << "String Destructor (" << mpData << ")" << endl;
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
|
||||
mSize = right.mSize;
|
||||
mCapacity = right.mCapacity;
|
||||
|
||||
std::free(mpData);
|
||||
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
char& operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
size_t getSize() const {return mSize;}
|
||||
size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||
{
|
||||
left << right.cStr();
|
||||
return left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void print(String s)
|
||||
{
|
||||
cout << s << endl;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a;
|
||||
a = "Dog";
|
||||
|
||||
print("Mouse");
|
||||
print(10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Иногда всё-таки не хочется, чтобы конструкторы использовались для неявного приведения типов.
|
||||
Ведь такое приведение типов может произойти там, где мы этого не хотим.
|
||||
|
||||
Чтобы конструктор не использовался для неявного приведения, его нужно пометить с помощью ключевого слова explicit.
|
||||
В этом примере, конструкторы String(const char* s) и String(int n) помечены как explicit.
|
||||
Поэтому эти конструкторы не будут использоваться для неявного приведения типов и код в функции main выдаст ошибку.
|
||||
Но эти конструкторы всё равно можно вызывать явно, вот так:
|
||||
|
||||
String a;
|
||||
a = String("Dog");
|
||||
|
||||
print(String("Mouse"));
|
||||
print(String(10));
|
||||
*/
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
Раздельная компиляция.
|
||||
|
||||
В этой части мы вынесем весь код, связанный с нашим классом Point в отдельные файлы.
|
||||
А также скомпилируем отдельно код, относящийся к нашему классу Point.
|
||||
|
||||
Это будет проделано в следующий примерах, а пока тут просто лежит код
|
||||
класса Point из предыдущих частей.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
cout << a.norm() << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
Вынос определений методов вне класса.
|
||||
|
||||
Методы внутри класса можно только объявить, а определить их можно вне класса.
|
||||
Например, метод norm объявлен внутри класса:
|
||||
|
||||
float norm() const;
|
||||
|
||||
а определён вне класса:
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
|
||||
Чтобы компилятор понимал к какому классу относится тот или иной метод,
|
||||
к его имени вне класса нужно добавить название класса и два двоеточия.
|
||||
Поэтому метод norm вне класса Point называется как Point::norm.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const;
|
||||
float norm() const;
|
||||
Point operator*(float k) const;
|
||||
void normalize();
|
||||
};
|
||||
|
||||
|
||||
Point Point::operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point Point::operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void Point::normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
cout << a.norm() << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
Перенос кода в заголовочный файл
|
||||
|
||||
В этом примере мы перенесли весь код, связанный с классом Point в отдельный файл point.hpp.
|
||||
Файл point.hpp подключается к файлу main.cpp с помощью директивы #include в строке:
|
||||
|
||||
#include "point.hpp"
|
||||
|
||||
На самом деле директива #include делает очень простую вещь: она просто берёт всё содержимое
|
||||
передаваемого ей файла и вставляет это содержимое на место директивы.
|
||||
То есть в этом примере за место #include "point.hpp" подставится всё содержимое файла point.hpp.
|
||||
|
||||
Так как директива #include уже сама вставила файл point.hpp в файл main.cpp, то дополнительно
|
||||
указывать файл point.hpp при компиляции не нужно. Скомпилировать этот пример можно так:
|
||||
|
||||
g++ main.cpp
|
||||
|
||||
|
||||
Стандартные библиотеки типа iostream подключаются так же. То есть где-то в системе, в какой-то папке
|
||||
хранится стандартная библиотека C++ и, соответственно, есть файл под название iostream (без расширения).
|
||||
Этот файл и подставляется за место строки #include <iostream>.
|
||||
Чтобы посмотреть в каких папках компилятор ищет файлы стандартной библиотеки можно скомпилировать программу так:
|
||||
|
||||
g++ -v main.cpp
|
||||
|
||||
Он напечатает множество информации о компиляции, в числе прочего пути где происходит поиск при исполнении #include.
|
||||
Вы могли заметить, что стандартные библиотеки в директиве #include пишутся в треугольных скобочках, а нашу
|
||||
библиотеку point.hpp мы написали в двойных кавычках. В чём разница между этими вариантами?
|
||||
На самом деле разница лишь в том, в каких папках компилятор ищет данные файлы.
|
||||
Если мы пишем библиотеку в треугольных скобках, то компилятор ищет её в папках стандартной библиотеки.
|
||||
Если мы пишем библиотеку в кавычках, то компилятор ищет её в папках текущей директории.
|
||||
|
||||
|
||||
|
||||
Защита от двойного включения
|
||||
|
||||
Используя директивы #include, очень легко включить один и тот же файл 2 и более раз.
|
||||
Например, в этом примере файл iostream включается 2 раза: один раз непосредственно в файле main.cpp, а второй раз
|
||||
он включится после того, как включиться файл point.hpp. Внутри файла point.hpp тоже есть #include <iostream>.
|
||||
Если не предпринимать никаких действий, то произойдёт ошибка, так как одинаковые функции и классы
|
||||
будут повторяться в программе несколько раз.
|
||||
|
||||
Чтобы защититься от этой проблемы нужно в начале заголовочного файла написать директиву
|
||||
|
||||
#pragma once
|
||||
|
||||
Таким образом компилятор будет понимать, что вы не хотите включать файл более одного раза и включит только одну копию файла.
|
||||
Эта директива была использовани и в файле point.hpp.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "point.hpp"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
cout << a.norm() << endl;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
Всё что относится к классу Point мы перенесли в отдельный файл point.hpp.
|
||||
А также мы разделили объявления и определения методов в файле point.hpp.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
#include "point.hpp"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
cout << a.norm() << endl;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const;
|
||||
float norm() const;
|
||||
Point operator*(float k) const;
|
||||
void normalize();
|
||||
};
|
||||
|
||||
|
||||
Point Point::operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point Point::operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void Point::normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
Раздельная компиляция
|
||||
|
||||
Теперь мы разделим объявления и определения всех методов класса Point.
|
||||
Все объявления класса Point поместим в файл point.hpp, а определения методов в файл point.cpp.
|
||||
Таким образом у нас получилось 2 компилируемых файла: main.cpp и point.cpp и 1 заголовочный файл point.hpp.
|
||||
|
||||
При этом заголовочный файл point.hpp должен подключаться везде, где используется класс Point.
|
||||
То есть в данном случае он должен подключаться и в файл main.cpp и в файл point.cpp.
|
||||
|
||||
|
||||
Для компиляции программы нужно указать компилятору на все компилируемые файлы вот так:
|
||||
|
||||
g++ main.cpp point.cpp
|
||||
|
||||
Если это не сделать и скомпилировать только файл main.cpp, то возникнет ошибка undefined reference to norm().
|
||||
Грубо говоря программа будет знать, что есть класс Point и знать его методы (так как это всё описано в point.hpp),
|
||||
но любые попытки вызвать эти методы будут приводить к ошибке, так как они не были скомпилированы.
|
||||
|
||||
|
||||
Преемущество раздельной компиляции заключается в том, что компилировать разные .cpp файлы можно поотдельности.
|
||||
Представьте, что у вас огромный проект, содержащий тысячи файлов и миллионы строк кода. Такой проект может компилироваться часами.
|
||||
Теперь вы сделали небольшое изменение в одном файле этого проекта. Если бы нельзя было бы компилировать файлы поотдельности,
|
||||
то после любого изменения вам бы пришлось компилировать весь проект заново и ждать часы пока компиляция закончится.
|
||||
К счастью, .cpp файлы можно компилировать поотдельности и, если вы сделали изменение в одном файле, то скомпилировать
|
||||
потребуется только тот файл, который вы изменили.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "point.hpp"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
Point a = {7.2, 3.1};
|
||||
cout << a.norm() << endl;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
#include "point.hpp"
|
||||
|
||||
Point Point::operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point Point::operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void Point::normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const;
|
||||
float norm() const;
|
||||
Point operator*(float k) const;
|
||||
void normalize();
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a);
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Пространства имён
|
||||
|
||||
|
||||
Имя Point достаточно распространённое и есть очень большая вероятность того, что при подключении нескольких библиотек
|
||||
в некоторых из них тоже будет класс с именем Point. Конечно, если ничего не предпринять, это приведёт к ошибке.
|
||||
|
||||
Чтобы избежать ошибок, связанных с конфликтами имён, положим весь код нашего класса Point в пространство имён mipt.
|
||||
Для этого обернём наш код в файлах point.hpp и point.cpp
|
||||
|
||||
namespace mipt
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
Теперь наш класс Point будет лежать в пространстве имён mipt.
|
||||
Для его использования вне пространства имён mipt нужно писать mipt::Point (ну либо использовать using mipt::Point;)
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "point.hpp"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
mipt::Point a = {7.2, 3.1};
|
||||
cout << a.norm() << endl;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cmath>
|
||||
#include "point.hpp"
|
||||
|
||||
namespace mipt
|
||||
{
|
||||
|
||||
Point Point::operator+(Point b) const
|
||||
{
|
||||
Point result = {x + b.x, y + b.y};
|
||||
return result;
|
||||
}
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
Point Point::operator*(float k) const
|
||||
{
|
||||
Point result = {k * x, k * y};
|
||||
return result;
|
||||
}
|
||||
|
||||
void Point::normalize()
|
||||
{
|
||||
float normv = norm();
|
||||
x /= normv;
|
||||
y /= normv;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a)
|
||||
{
|
||||
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace mipt
|
||||
{
|
||||
|
||||
struct Point
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Point operator+(Point b) const;
|
||||
float norm() const;
|
||||
Point operator*(float k) const;
|
||||
void normalize();
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Point a);
|
||||
|
||||
}
|
||||
|
|
@ -1,265 +0,0 @@
|
|||
/*
|
||||
В данной программе содержится класс String, написанный нами в одной из предыдущих частей.
|
||||
|
||||
Задачи:
|
||||
|
||||
1) Вынесите класс String в отдельный заголовочный файл string.hpp и скомпилируйте программу.
|
||||
|
||||
|
||||
2) Вынесите объявления методов класса String в заголовочный файл string.hpp, а определения
|
||||
методов в компилируемый файл string.cpp. Скомпилируйте программу.
|
||||
|
||||
|
||||
3) Вынесите объявления методов класса String в заголовочный файл string.hpp, а определения
|
||||
методов в компилируемый файл string.cpp. А также поместите весь код класса String в пространство имён mipt.
|
||||
Скомпилируйте программу.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
std::size_t mSize;
|
||||
std::size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String(std::size_t n, char a)
|
||||
{
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void reserve(std::size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(std::size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (std::size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool operator<(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator<=(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& operator[](std::size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& at(std::size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
std::size_t getSize() const {return mSize;}
|
||||
std::size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b;
|
||||
std::cin >> b;
|
||||
String c = b;
|
||||
|
||||
if (a + c == "MouseLion")
|
||||
std::cout << "Yes" << std::endl;
|
||||
else
|
||||
std::cout << "No" << std::endl;
|
||||
|
||||
|
||||
if (a > "Mice")
|
||||
std::cout << "Yes" << std::endl;
|
||||
else
|
||||
std::cout << "No" << std::endl;
|
||||
|
||||
|
||||
c[0] = 'P';
|
||||
std::cout << c << std::endl;
|
||||
|
||||
c += a;
|
||||
std::cout << c << std::endl;
|
||||
|
||||
c = c + String(10, 'q');
|
||||
std::cout << c << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "string.hpp"
|
||||
|
||||
using std::cout, std::cin, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b;
|
||||
cin >> b;
|
||||
String c = b;
|
||||
|
||||
if (a + c == "MouseLion")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
if (a > "Mice")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
c[0] = 'P';
|
||||
cout << c << endl;
|
||||
|
||||
c += a;
|
||||
cout << c << endl;
|
||||
|
||||
c = c + String(10, 'q');
|
||||
cout << c << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
std::size_t mSize;
|
||||
std::size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String(std::size_t n, char a)
|
||||
{
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void reserve(std::size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(std::size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (std::size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool operator<(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator<=(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& operator[](std::size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& at(std::size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
std::size_t getSize() const {return mSize;}
|
||||
std::size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
Компиляция:
|
||||
|
||||
g++ main.cpp string.cpp
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "string.hpp"
|
||||
using std::cout, std::cin, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
String a = "Mouse";
|
||||
String b;
|
||||
cin >> b;
|
||||
String c = b;
|
||||
|
||||
if (a + c == "MouseLion")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
if (a > "Mice")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
c[0] = 'P';
|
||||
cout << c << endl;
|
||||
|
||||
c += a;
|
||||
cout << c << endl;
|
||||
|
||||
c = c + String(10, 'q');
|
||||
cout << c << endl;
|
||||
}
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "string.hpp"
|
||||
|
||||
|
||||
String::String(const char* str)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String::String() : String("") {}
|
||||
String::String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String::String(std::size_t n, char a)
|
||||
{
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void String::reserve(std::size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void String::resize(std::size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& String::operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (std::size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String String::operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& String::operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool String::operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool String::operator<(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool String::operator<=(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool String::operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool String::operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool String::operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& String::operator[](std::size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& String::at(std::size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void String::clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void String::addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
std::size_t String::getSize() const {return mSize;}
|
||||
std::size_t String::getCapacity() const {return mCapacity;}
|
||||
const char* String::cStr() const {return mpData;}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
std::size_t mSize;
|
||||
std::size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str);
|
||||
|
||||
String();
|
||||
String(const String& s);
|
||||
|
||||
String(std::size_t n, char a);
|
||||
~String();
|
||||
|
||||
void reserve(std::size_t capacity);
|
||||
void resize(std::size_t size);
|
||||
|
||||
String& operator=(const String& right);
|
||||
String operator+(const String& b);
|
||||
String& operator+=(const String& right);
|
||||
|
||||
bool operator==(const String& right) const;
|
||||
bool operator<(const String& right) const;
|
||||
bool operator<=(const String& right) const;
|
||||
bool operator!=(const String& right) const;
|
||||
bool operator>(const String& right) const;
|
||||
bool operator>=(const String& right) const;
|
||||
|
||||
char& operator[](std::size_t i);
|
||||
char& at(std::size_t i);
|
||||
|
||||
void clear();
|
||||
void addCharacter(char c);
|
||||
|
||||
std::size_t getSize() const;
|
||||
std::size_t getCapacity() const;
|
||||
const char* cStr() const;
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s);
|
||||
std::istream& operator>>(std::istream& in, String& s);
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#include <iostream>
|
||||
#include "string.hpp"
|
||||
using std::cout, std::cin, std::endl;
|
||||
|
||||
int main()
|
||||
{
|
||||
mipt::String a = "Mouse";
|
||||
mipt::String b;
|
||||
cin >> b;
|
||||
mipt::String c = b;
|
||||
|
||||
if (a + c == "MouseLion")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
if (a > "Mice")
|
||||
cout << "Yes" << endl;
|
||||
else
|
||||
cout << "No" << endl;
|
||||
|
||||
|
||||
c[0] = 'P';
|
||||
cout << c << endl;
|
||||
|
||||
c += a;
|
||||
cout << c << endl;
|
||||
|
||||
c = c + mipt::String(10, 'q');
|
||||
cout << c << endl;
|
||||
}
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "string.hpp"
|
||||
|
||||
namespace mipt {
|
||||
|
||||
String::String(const char* str)
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (str[i] != '\0')
|
||||
i++;
|
||||
mSize = i;
|
||||
mCapacity = i + 1;
|
||||
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; str[i]; i++)
|
||||
mpData[i] = str[i];
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String::String() : String("") {}
|
||||
String::String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String::String(std::size_t n, char a)
|
||||
{
|
||||
mSize = n;
|
||||
mCapacity = n + 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void String::reserve(std::size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = capacity;
|
||||
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
newData[i] = mpData[i];
|
||||
newData[mSize] = '\0';
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void String::resize(std::size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& String::operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
for (std::size_t i = 0; i <= mSize; ++i)
|
||||
mpData[i] = right.mpData[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String String::operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
result.mpData[i] = mpData[i];
|
||||
|
||||
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||
result.mpData[mSize + i] = b.mpData[i];
|
||||
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& String::operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool String::operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool String::operator<(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool String::operator<=(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool String::operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool String::operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool String::operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& String::operator[](std::size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& String::at(std::size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void String::clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void String::addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
std::size_t String::getSize() const {return mSize;}
|
||||
std::size_t String::getCapacity() const {return mCapacity;}
|
||||
const char* String::cStr() const {return mpData;}
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace mipt {
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
std::size_t mSize;
|
||||
std::size_t mCapacity;
|
||||
char* mpData;
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str);
|
||||
|
||||
String();
|
||||
String(const String& s);
|
||||
|
||||
String(std::size_t n, char a);
|
||||
~String();
|
||||
|
||||
void reserve(std::size_t capacity);
|
||||
void resize(std::size_t size);
|
||||
|
||||
String& operator=(const String& right);
|
||||
String operator+(const String& b);
|
||||
String& operator+=(const String& right);
|
||||
|
||||
bool operator==(const String& right) const;
|
||||
bool operator<(const String& right) const;
|
||||
bool operator<=(const String& right) const;
|
||||
bool operator!=(const String& right) const;
|
||||
bool operator>(const String& right) const;
|
||||
bool operator>=(const String& right) const;
|
||||
|
||||
char& operator[](std::size_t i);
|
||||
char& at(std::size_t i);
|
||||
|
||||
void clear();
|
||||
void addCharacter(char c);
|
||||
|
||||
std::size_t getSize() const;
|
||||
std::size_t getCapacity() const;
|
||||
const char* cStr() const;
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s);
|
||||
std::istream& operator>>(std::istream& in, String& s);
|
||||
|
||||
}
|
||||
|
|
@ -1,202 +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}
|
||||
|
||||
\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
|
||||
{~} {$\sim$}{1}
|
||||
}
|
||||
|
||||
\title{Семинар \#2: Инкапсуляция. Домашнее задание.\vspace{-5ex}}\date{}\maketitle
|
||||
|
||||
\section*{Класс Circle}
|
||||
Допустим, что мы хотим создать программу, которая будет работать с окружностями (это может быть игра или, например, графический редактор). Для того, чтобы сделать код более понятным и удобным в использовании, мы решили создать класс окружности. Кроме того, мы решили использовать уже ранее написанный класс точки в 2D пространстве (файлы \texttt{point.h} и \texttt{point.cpp}). Создайте класс окружности, который будет включать следующие методы:
|
||||
\begin{itemize}
|
||||
\item Конструктор \texttt{Circle(const Point\& acenter, float aradius)}, который будет задавать поля \texttt{center} и \texttt{radius} соответстующими значениями.
|
||||
\item Конструктор по умолчанию \texttt{Circle()} - задаются значения, соответствующие единичной окружности с центром в начале координат.
|
||||
\item Конструктор копирования \texttt{Circle(const Circle\& circle)}
|
||||
\item Сеттеры и геттеры, для полей \texttt{center} и \texttt{radius}. Поле \texttt{radius} нельзя задать отрицательным числом. При попытке задания его отрицательным числом оно должно устанавливаться в значение \texttt{0}.
|
||||
\item Метод \texttt{float getArea() const}, который будет возвращать площадь поверхности круга.
|
||||
\item Метод \texttt{float getDistance(const Point\& p) const}, который будет возвращать расстояние от точки \texttt{p}, до ближайшей точки окружности.
|
||||
\item Метод \texttt{bool isColliding(const Circle\& c) const}, который будет возвращать \texttt{true}, если круг пересекается с кругом \texttt{c}.
|
||||
\item Метод \texttt{void move(const Point\& p)}, который будет перемещать кружок на вектор \texttt{p}.
|
||||
\end{itemize}
|
||||
Весь начальный код содержится в папке \texttt{0circle}. При компиляции нужно указывать все \texttt{.cpp} файлы, которые вы хотите скомпилировать:
|
||||
\begin{verbatim}
|
||||
g++ main.cpp point.cpp
|
||||
\end{verbatim}
|
||||
\begin{itemize}
|
||||
\item Создайте файлы \texttt{circle.h} и \texttt{circle.cpp} и перенесите реализацию класса окружности из файла \texttt{main.cpp} в эти файлы.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\newpage
|
||||
\section*{Класс Number (большое число)}
|
||||
Стандартные целочисленные типы данных, такие как \texttt{int} имеют фиксированный небольшой размер. Соответственно значения, которые можно хранить в переменных этих типов ограничены. Типичное максимальное значение \texttt{char} равно $2^7 - 1 = 127$, тип \texttt{int} обычно ограничен $2^{31}-1 = 2147483647$ и даже тип \texttt{unsigned long long} имеет ограничение в $2^{64}-1 = 1.8 * 10^{19}$. Хранить действительно большие числа в этих типах невозможно. В этом задании нужно сделать класс, с помощью которого будет удобно складывать и умножать большие целые положительные числа. Начальный код этого класса содержится в \texttt{1number/number.cpp}. Изучите этот код.
|
||||
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[scale=1]{../images/number1.png}
|
||||
\caption{Представление числа 12345678 в памяти с помощью нашего класса Number}
|
||||
\label{fig:nummber1}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\subsection*{Задания:}
|
||||
\begin{itemize}
|
||||
\item \textbf{Конструктор по умолчанию:} Напишите конструктор по умолчанию \texttt{Number()}, который будет создавать число равное нулю.
|
||||
\item \textbf{Конструктор копирования:} Напишите конструктор копирования \texttt{Number(const Number\& n)}.
|
||||
\item \textbf{Конструктор из строки:} Напишите конструктор \texttt{Number(const char* str)}, который будет создавать большое число на основе строки. Предполагаем, что на вход конструктору всегда идёт корректная строка. Например, число из примера можно будет создать так:
|
||||
\begin{lstlisting}
|
||||
Number a = Number("12345678");
|
||||
\end{lstlisting}
|
||||
\item \textbf{Присваивание:} Напишите оператор присваивания \texttt{Number\& operator=(const Number\& right)}.
|
||||
\item \textbf{Сложение:} Напишите и протестируйте операторы сложения \texttt{operator+} и оператор присваивания сложения \texttt{operator+=}. Реализовывать оба этих оператора с нуля необязательно. Ведь, если написан один из этих операторов, то очень просто написать другой.
|
||||
\item \textbf{Числа Фибоначчи:} Числа Фибоначчи задаются следующим образом:
|
||||
\begin{align*}
|
||||
F_0 &= 0\\
|
||||
F_1 &= 1\\
|
||||
F_n &= F_{n-1} + F_{n-2}
|
||||
\end{align*}
|
||||
Используйте класс \texttt{Number}, чтобы вычислить $F_{1000}$. Правильный ответ:
|
||||
\begin{verbatim}
|
||||
F(1000) = 43466557686937456435688527675040625802564660517371780402481729089536555417949051890
|
||||
40387984007925516929592259308032263477520968962323987332247116164299644090653318793829896964992
|
||||
8516003704476137795166849228875
|
||||
\end{verbatim}
|
||||
|
||||
|
||||
|
||||
|
||||
\item \textbf{Четность:} Напишите метод \texttt{bool isEven() const}, который будет проверять является ли наше число чётным и, если это верно, возвращает \texttt{true}, в ином случае возвращает \texttt{false}.
|
||||
|
||||
\item \textbf{Произведение:} Напишите метод \texttt{Number operator*(const Number\& right) const} - оператор умножения одного числа \texttt{Number} на другое. Протестируйте вашу функцию на различных примерах (умножение большого числа на большое, умножение большого числа на небольшое ($< 100$) или на ноль, умножение двух небольших чисел и т. д.).\\
|
||||
\item \textbf{Факториал:} Используйте написанный оператор для вычисления факториала от 1000. \\
|
||||
Правильный ответ:
|
||||
\begin{verbatim}
|
||||
1000! = 40238726007709377354370243392300398571937486421071463254379991042993851239862902059
|
||||
2044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759
|
||||
9188236277271887325197795059509952761208749754624970436014182780946464962910563938874378864
|
||||
8733711918104582578364784997701247663288983595573543251318532395846307555740911426241747434
|
||||
9347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379
|
||||
5345242215865932019280908782973084313928444032812315586110369768013573042161687476096758713
|
||||
4831202547858932076716913244842623613141250878020800026168315102734182797770478463586817016
|
||||
4365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186
|
||||
1168115536158365469840467089756029009505376164758477284218896796462449451607653534081989013
|
||||
8544248798495995331910172335555660213945039973628075013783761530712776192684903435262520001
|
||||
5888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838
|
||||
9714760885062768629671466746975629112340824392081601537808898939645182632436716167621791689
|
||||
0977991190375403127462228998800519544441428201218736174599264295658174662830295557029902432
|
||||
4153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690
|
||||
8979684825901254583271682264580665267699586526822728070757813918581788896522081643483448259
|
||||
9326604336766017699961283186078838615027946595513115655203609398818061213855860030143569452
|
||||
7224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136
|
||||
4932734975655139587205596542287497740114133469627154228458623773875382304838656889764619273
|
||||
8381490014076731044664025989949022222176590433990188601856652648506179970235619389701786004
|
||||
0811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614
|
||||
8396573822911231250241866493531439701374285319266498753372189406942814341185201580141233448
|
||||
2801505139969429015348307764456909907315243327828826986460278986432113908350621709500259738
|
||||
9863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826
|
||||
2809561214509948717012445164612603790293091208890869420285106401821543994571568059418727489
|
||||
9809425474217358240106367740459574178516082923013535808184009699637252423056085590370062427
|
||||
1243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000
|
||||
\end{verbatim}
|
||||
|
||||
\item \textbf{Числа-градины:} Возьмём некоторое число $n$ и будем последовательно применять к нему следующую функцию:
|
||||
\begin{equation*}
|
||||
f(n) =
|
||||
\begin{cases}
|
||||
n / 2, &\textup{если n - четное}\\
|
||||
3 n + 1, &\textup{если n - нечетное}
|
||||
\end{cases}
|
||||
\end{equation*}
|
||||
В результате получится некоторая последовательность. Например, при $n = 7$ получится:
|
||||
\begin{verbatim}
|
||||
7 -> 22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
|
||||
\end{verbatim}
|
||||
Последовательность доходит до 1. Вам нужно написать функцию, которая будет по начальному числу находить длину такой последовательности (\texttt{steps}) и максимальное число в этой последовательности(\texttt{max}). Например, для числа $7$, максимальное число в последовательности будет равно $52$, а длина последовательности -- $16$. Напишите программу, которая будет по начальному числу находить длину последовательности и максимальный элемент в ней.
|
||||
|
||||
Тесты для проверки:
|
||||
\begin{verbatim}
|
||||
n = 7 steps = 16; max = 52
|
||||
n = 256 steps = 8; max = 256
|
||||
n = 1117065 steps = 527; max = 2974984576
|
||||
n = 4761963248413673697 steps = 2337; max = 9926927712374950744648
|
||||
|
||||
n = 90560792656972947582439785608972465789628974587264056284658721771
|
||||
steps = 1630;
|
||||
max = 773658021643749360792171137214151494851244403993540980838080564520
|
||||
\end{verbatim}
|
||||
Для решения этой задачи нужно написать оператор сравнения и метод деления на 2 (оператор целочисленного деления можно не писать).
|
||||
\item \textbf{Раздельная компиляция:} Перенесите объявление класса \texttt{Number} в файл \texttt{number.h}, а определение методов в файл \texttt{number.cpp}. Раздельно скомпилируйте эту программу.
|
||||
\end{itemize}
|
||||
|
||||
\end{document}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -1,263 +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="number1.svg"
|
||||
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar02_encapsulation\images\number1.png"
|
||||
inkscape:export-xdpi="300"
|
||||
inkscape:export-ydpi="300">
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutM"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path1145"
|
||||
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>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="317.04261"
|
||||
inkscape:cy="872.15364"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
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">
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815"
|
||||
width="23.450636"
|
||||
height="8.9508085"
|
||||
x="62.878162"
|
||||
y="28.701445" />
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-2"
|
||||
width="23.450638"
|
||||
height="8.9508085"
|
||||
x="62.878166"
|
||||
y="37.652252" />
|
||||
<rect
|
||||
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-0"
|
||||
width="23.450638"
|
||||
height="8.9508085"
|
||||
x="62.878166"
|
||||
y="46.603043" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="73.134239"
|
||||
y="35.031639"
|
||||
id="text840"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan838"
|
||||
x="73.134239"
|
||||
y="35.031639"
|
||||
style="stroke-width:0.26458332">4</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="50.580757"
|
||||
y="111.18085"
|
||||
id="text844"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan842"
|
||||
x="50.580757"
|
||||
y="115.4662"
|
||||
style="stroke-width:0.26458332"></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="73.19175"
|
||||
y="43.75705"
|
||||
id="text840-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan838-0"
|
||||
x="73.19175"
|
||||
y="43.75705"
|
||||
style="stroke-width:0.26458332">5</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="51.218136"
|
||||
y="34.563919"
|
||||
id="text872"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan870"
|
||||
x="51.218136"
|
||||
y="34.563919"
|
||||
style="stroke-width:0.26458332">size</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="40.424309"
|
||||
y="43.743973"
|
||||
id="text872-4"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan870-4"
|
||||
x="40.424309"
|
||||
y="43.743973"
|
||||
style="stroke-width:0.26458332">capacity</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="51.084499"
|
||||
y="53.3396"
|
||||
id="text894"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan892"
|
||||
x="51.084499"
|
||||
y="53.3396"
|
||||
style="stroke-width:0.26458332">data</tspan></text>
|
||||
<circle
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.35941789;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path896"
|
||||
cx="74.336952"
|
||||
cy="50.934158"
|
||||
r="1.8411777" />
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-5"
|
||||
width="11.451464"
|
||||
height="8.5778608"
|
||||
x="101.42937"
|
||||
y="46.831276" />
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-5-8"
|
||||
width="11.451464"
|
||||
height="8.5778608"
|
||||
x="112.88083"
|
||||
y="46.831276" />
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-5-1"
|
||||
width="11.451464"
|
||||
height="8.5778608"
|
||||
x="124.33229"
|
||||
y="46.831276" />
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-5-5"
|
||||
width="11.451464"
|
||||
height="8.5778608"
|
||||
x="135.78375"
|
||||
y="46.831276" />
|
||||
<rect
|
||||
style="opacity:1;fill:#ebffeb;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-5-82"
|
||||
width="11.451464"
|
||||
height="8.5778608"
|
||||
x="147.23523"
|
||||
y="46.831276" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="104.47309"
|
||||
y="52.654404"
|
||||
id="text840-07"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan838-4"
|
||||
x="104.47309"
|
||||
y="52.654404"
|
||||
style="stroke-width:0.26458332">78</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="115.86423"
|
||||
y="52.529114"
|
||||
id="text840-07-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan838-4-7"
|
||||
x="115.86423"
|
||||
y="52.529114"
|
||||
style="stroke-width:0.26458332">56</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="127.49047"
|
||||
y="52.54583"
|
||||
id="text840-07-4"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan838-4-8"
|
||||
x="127.49047"
|
||||
y="52.54583"
|
||||
style="stroke-width:0.26458332">43</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="139.01648"
|
||||
y="52.495712"
|
||||
id="text840-07-8"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan838-4-9"
|
||||
x="139.01648"
|
||||
y="52.495712"
|
||||
style="stroke-width:0.26458332">12</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutM)"
|
||||
d="m 74.537403,51.067801 c 4.677216,-0.36749 21.181108,-0.8018 24.288118,-0.80179"
|
||||
id="path998"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="63.742908"
|
||||
y="27.441465"
|
||||
id="text1806"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1804"
|
||||
x="63.742908"
|
||||
y="27.441465"
|
||||
style="stroke-width:0.26458332">Number</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 304 KiB |
|
|
@ -1,338 +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="sepcompilation.svg"
|
||||
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar02_encapsulation\images\sepcompilation.png"
|
||||
inkscape:export-xdpi="300"
|
||||
inkscape:export-ydpi="300">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.98994949"
|
||||
inkscape:cx="243.20281"
|
||||
inkscape:cy="570.05869"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
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">
|
||||
<rect
|
||||
style="opacity:1;fill:#e7eef4;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815"
|
||||
width="138.83838"
|
||||
height="58.966839"
|
||||
x="23.432297"
|
||||
y="13.06549" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="28.503822"
|
||||
y="24.373625"
|
||||
id="text823"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan821"
|
||||
x="28.503822"
|
||||
y="24.373625"
|
||||
style="stroke-width:0.26458332"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan845">struct</tspan> Point {</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.503822"
|
||||
y="30.547235"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan825"> <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan837">float</tspan> x, y;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.503822"
|
||||
y="36.720848"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan827"></tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.503822"
|
||||
y="42.894459"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan829"> <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan841">float</tspan> norm() const;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.503822"
|
||||
y="49.068069"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan831"> <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan843">void</tspan> normalize();</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.503822"
|
||||
y="55.24168"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan833"> Point <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan847">operator</tspan>+(<tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan851">const</tspan> Point& r) <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan849">const</tspan>;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.503822"
|
||||
y="61.415291"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan835">};</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="25.79151"
|
||||
y="11.021605"
|
||||
id="text855"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan853"
|
||||
x="25.79151"
|
||||
y="11.021605"
|
||||
style="stroke-width:0.26458332">point.h</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#e7eef4;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-8"
|
||||
width="139.52013"
|
||||
height="114.80299"
|
||||
x="23.665709"
|
||||
y="86.590546" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="26.57818"
|
||||
y="89.27375"
|
||||
id="text823-4"><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="89.27375"
|
||||
style="fill:#0000ff;stroke-width:0.26458332"
|
||||
id="tspan835-0"> </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="95.447365"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1159"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1161">#include</tspan> <cmath></tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="101.62097"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1163"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1171">#include</tspan> "point.h"</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="107.79458"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan997" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="113.96819"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan995"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1001">float</tspan> Point::norm() <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1003">const</tspan> {</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="120.14181"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan969"> <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1005">return</tspan> sqrt(x*x + y*y);</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="126.31542"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan971">}</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="132.48901"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan973" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="138.66263"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan975"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1007">void</tspan> Point::normalize() {</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="144.83624"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan977"> <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1009">float</tspan> pnorm = norm();</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="151.00984"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan979"> x /= pnorm;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="157.18346"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan981"> y /= pnorm;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="163.35707"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan983">}</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="169.53069"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan985" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="175.7043"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan987">Point Point::<tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1011">operator</tspan>+(<tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1013">const</tspan> Point& r) <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1015">const</tspan>{</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="181.8779"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan989"> Point result = {x + r.x, y + r.y};</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="188.05151"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan991"> <tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1017">return</tspan> result;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="26.57818"
|
||||
y="194.22513"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan993">}</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="25.736752"
|
||||
y="81.801659"
|
||||
id="text855-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan853-3"
|
||||
x="25.736752"
|
||||
y="81.801659"
|
||||
style="stroke-width:0.26458332">point.cpp</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#e7eef4;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815-6"
|
||||
width="139.8732"
|
||||
height="58.965"
|
||||
x="23.31591"
|
||||
y="215.80164" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="28.386515"
|
||||
y="227.10884"
|
||||
id="text823-9"><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="227.10884"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan835-8"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1149">#include</tspan> <iostream></tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="233.28246"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1143"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1151">#include</tspan> "point.h"</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="239.45607"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1145" /><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="245.62967"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1141"><tspan
|
||||
style="fill:#0000ff"
|
||||
id="tspan1153">int</tspan> main() {</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="251.80327"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1131"> Point p = {1, 2};</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="257.97687"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1133"> p.normalize();</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="264.15048"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1137"> std::cout << p.x << " " << p.y << std::endl;</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="28.386515"
|
||||
y="270.3241"
|
||||
style="stroke-width:0.26458332"
|
||||
id="tspan1139">}</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="25.674202"
|
||||
y="213.75682"
|
||||
id="text855-5"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan853-9"
|
||||
x="25.674202"
|
||||
y="213.75682"
|
||||
style="stroke-width:0.26458332">main.cpp</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
|
|
@ -1,344 +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="string_base.svg"
|
||||
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar02_encapsulation\images\string_base.png"
|
||||
inkscape:export-xdpi="300"
|
||||
inkscape:export-ydpi="300">
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
inkscape:stockid="TriangleOutM"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker5033"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path5031"
|
||||
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="TriangleOutL"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="TriangleOutL"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4853"
|
||||
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">
|
||||
<path
|
||||
id="path4856"
|
||||
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>
|
||||
</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="315.82303"
|
||||
inkscape:cy="843.84077"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
showguides="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
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">
|
||||
<rect
|
||||
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4520"
|
||||
width="30.468725"
|
||||
height="9.6217022"
|
||||
x="39.030174"
|
||||
y="38.982063" />
|
||||
<rect
|
||||
style="opacity:1;fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4520-4"
|
||||
width="30.468725"
|
||||
height="9.6217022"
|
||||
x="39.030174"
|
||||
y="48.603767" />
|
||||
<circle
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.44303662;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path4543"
|
||||
cx="54.455605"
|
||||
cy="53.397713"
|
||||
r="2.573324" />
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot4545"
|
||||
style="fill:black;fill-opacity:1;stroke:none;font-family:Consolas;font-style:normal;font-weight:normal;font-size:18.66666667px;line-height:1.25;letter-spacing:0px;word-spacing:0px;-inkscape-font-specification:'Consolas, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal"><flowRegion
|
||||
id="flowRegion4547"><rect
|
||||
id="rect4549"
|
||||
width="38.385796"
|
||||
height="35.860416"
|
||||
x="342.94678"
|
||||
y="370.46112" /></flowRegion><flowPara
|
||||
id="flowPara4551"></flowPara></flowRoot> <rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="91.456924"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="95.248917"
|
||||
y="51.714432"
|
||||
id="text4566"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564"
|
||||
x="95.248917"
|
||||
y="51.714432"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">E</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="103.08315"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="106.99326"
|
||||
y="51.714439"
|
||||
id="text4566-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3"
|
||||
x="106.99326"
|
||||
y="51.714439"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">l</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-8"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="114.70938"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="118.61949"
|
||||
y="51.714439"
|
||||
id="text4566-3-5"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-6"
|
||||
x="118.61949"
|
||||
y="51.714439"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">e</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-4"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="126.33562"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="130.24574"
|
||||
y="51.714439"
|
||||
id="text4566-3-6"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-7"
|
||||
x="130.24574"
|
||||
y="51.714439"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">p</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-8-4"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="137.96185"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="141.87195"
|
||||
y="51.714439"
|
||||
id="text4566-3-5-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-6-4"
|
||||
x="141.87195"
|
||||
y="51.714439"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">h</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-6"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="149.58807"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="153.49818"
|
||||
y="51.714447"
|
||||
id="text4566-3-8"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-0"
|
||||
x="153.49818"
|
||||
y="51.714447"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">a</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-8-5"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="161.21431"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="165.12442"
|
||||
y="51.714447"
|
||||
id="text4566-3-5-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-6-2"
|
||||
x="165.12442"
|
||||
y="51.714447"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">n</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-61"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="172.84053"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="176.75064"
|
||||
y="51.714432"
|
||||
id="text4566-3-7"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-9"
|
||||
x="176.75064"
|
||||
y="51.714432"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">t</tspan></text>
|
||||
<rect
|
||||
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4553-2-8-57"
|
||||
width="11.626225"
|
||||
height="9.0871639"
|
||||
x="184.46677"
|
||||
y="44.917343" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="186.10507"
|
||||
y="51.714432"
|
||||
id="text4566-3-5-96"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-3-6-9"
|
||||
x="186.10507"
|
||||
y="51.714432"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">\0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="52.359035"
|
||||
y="45.97747"
|
||||
id="text4566-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4564-37"
|
||||
x="52.359035"
|
||||
y="45.97747"
|
||||
style="font-size:7.05555534px;stroke-width:0.26458332">8</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5033)"
|
||||
d="M 54.1309,53.481438 C 68.229368,51.744187 78.051525,49.806481 86.938236,49.539213"
|
||||
id="path4709"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="39.555893"
|
||||
y="36.946739"
|
||||
id="text5223"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5221"
|
||||
x="39.555893"
|
||||
y="36.946739"
|
||||
style="font-size:4.23333311px;stroke-width:0.26458332">String a</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="28.549953"
|
||||
y="45.468987"
|
||||
id="text5223-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5221-1"
|
||||
x="28.549953"
|
||||
y="45.468987"
|
||||
style="font-size:4.23333311px;stroke-width:0.26458332">size</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
x="28.480877"
|
||||
y="55.038445"
|
||||
id="text5223-0-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5221-1-1"
|
||||
x="28.480877"
|
||||
y="55.038445"
|
||||
style="font-size:4.23333311px;stroke-width:0.26458332">data</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 17 KiB |
Reference in a new issue