Добавил:
CanyonE
СПбГУТ * ИКСС * Программная инженерия
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Решения лабораторных работ (местами есть ошибки) / Lab1_String
.cpp#include <iostream>
#include <cmath>
#include <stdexcept>
using std::cin;
using std::cout;
using std::endl;
// Класс «Строка» без использования функций стандартных библиотек cstring и string
class String {
private:
// Указатель на массив символов
char *string_ = nullptr;
// Размер строки
size_t n_ = 0;
// Функция вычисления длины строки (с учетом '\0')
static size_t len(const char *str) {
size_t i = 0;
if (str) {
++i;
while (*str != '\0') {
++str;
++i;
}
}
return i;
}
public:
// Конструкторы
String() = default;
explicit String(const char *s) {
if (s != nullptr) {
n_ = len(s);
string_ = new char[n_];
std::copy(s, s + n_, string_);
string_[n_ - 1] = '\0';
}
}
// Строка из массива символов. Включение: [start, end)
explicit String(const char *start, const char *end) {
if (start != nullptr && end != nullptr) {
n_ = end - start + 1;
string_ = new char[n_];
std::copy(start, end, string_);
string_[n_ - 1] = '\0';
}
}
// Конструктор по размеру строки
explicit String(size_t i) {
if (i > 0) {
n_ = i;
string_ = new char[n_] {'\0'};
}
}
// Конструктор копирования
String(const String &arg) {
n_ = arg.n_;
if (n_ > 0) {
string_ = new char[n_];
std::copy(arg.string_, arg.string_ + n_, string_);
}
}
// Оператор копирования
String &operator=(const String &arg) {
String temp(arg);
swap(*this, temp);
return *this;
}
// Конструктор перемещения
String(String &&arg) noexcept {
n_ = arg.n_, string_ = arg.string_;
arg.n_ = 0, arg.string_ = nullptr;
}
// Оператор перемещения
String &operator=(String &&arg) noexcept {
if (this != &arg) {
swap(*this, arg);
delete[] arg.string_, arg.string_ = nullptr;
arg.n_ = 0;
}
return *this;
}
// Деструктор
virtual ~String() {
delete[] string_;
}
// Оператор получения символа строки по индексу
char &operator[](size_t idx) {
return string_[idx];
}
// Длина (без учета символа '\0')
size_t length() const {
return ( n_ > 1 ) ? ( n_ - 1 ) : 0;
}
// Поиск символа ch в строке, начиная с индекса start (при неудаче возврат длины строки)
size_t find(char ch, size_t idx) const {
if (string_) {
char *t = string_ + idx;
while (*t != '\0' && *t != ch) {
++t;
}
return t - string_;
}
return 0;
}
// Поиск последнего вхождения символа ch в строке (при неудаче возврат длины строки)
size_t findLast(char ch) const {
if (string_) {
char *t = string_ + n_;
while (t != string_ && *t != ch) {
--t;
}
if (*t == ch) { // Если символ был найден
return t - string_;
}
return length();
}
return 0;
}
// Выделение подстроки размера count из строки, начиная с позиции idx
String substr(size_t idx, size_t count) const noexcept(false) {
if (idx + count < n_) { // Ex. idx = 0, count = 1, N = 2 (with '\0'), ((0 + 1) < 2)!
return String(string_ + idx, string_ + idx + count);
}
throw std::invalid_argument("String. Method substr. Index + Count > N");
}
// Генерация новой строки с удаленными count символами, начиная с позиции idx
String remove(size_t idx, size_t count) const noexcept(false) {
if (idx + count < n_) {
String result(string_, string_ + n_ - count - 1);
std::copy(string_, string_ + idx, result.string_);
std::copy(string_ + idx + count, string_ + n_, result.string_ + idx);
return result;
}
throw std::invalid_argument("String. Method remove. Index + Count > N");
}
// Вставка подстроки arg в строку, начиная с позиции idx
String insert(const char *arg, size_t idx) const noexcept(false) {
if (idx < n_) {
size_t arg_len = len(arg) - 1; // Не копируем символ '\0'
String result(n_ + arg_len); // "000000"
std::copy(string_, string_ + idx, result.string_); // "120000"
std::copy(arg, arg + arg_len, result.string_ + idx); // "12--00"
std::copy(string_ + idx, string_ + n_, result.string_ + idx + arg_len); // "12--56"
return result;
}
throw std::invalid_argument("String. Method insert. Index > N");
}
// Удаление результирующих и завершающих пробелов
String trim() const noexcept(false) {
if (string_) {
char *start = string_, *stop = string_ + n_ - 2; // n - 1: '\0'
while (*start == ' ' || *start == '\t') {
++start;
}
while (*stop == ' ' || *stop == '\t') {
--stop;
}
return this->substr(start - string_, stop - start + 1);
}
throw std::invalid_argument("String. Method trim");
}
// Чтение строки неопределенной длины из потока os [os must have method get()]
static String read(std::istream &os) {
// Начальное количество символов t = 10
size_t i = 0, t = 10;
char *buffer = new char[t]; // Массив размера t
while (( buffer[i] = os.get() ) != '\n') { // Выполнять тело цикла, пока не введен конец строки
if (++i < t) { // Если в массиве ещё есть место
continue; // Продолжаем
}
// Увеличиваем количество символов
char *new_buffer = new char[t * 2]; // Указатель на новый массив в new_buffer
std::copy(buffer, buffer + t, new_buffer); // Копируем из старого в новый
std::swap(buffer, new_buffer); // Меняем местами
delete[] new_buffer; // Освобождаем старый
t *= 2; // В два раза увеличиваем
}
String result(buffer, buffer + i); // Конструируем String
delete[] buffer; // Освобождаем буфер
return result;
}
// Оператор приведения к типу bool
explicit operator bool() {
return n_ > 1;
}
// Оператор сравнения 'равно'
bool operator==(const String &arg) {
char *s = string_;
char *s_arg = arg.string_;
if (s && s_arg) {
while (*s != '\0' && *s_arg != '\0' && *s == *s_arg) {
++s;
++s_arg;
}
return *s == *s_arg;
}
return s == s_arg;
}
// Оператор сравнения 'не равно'
bool operator!=(const String &arg) {
return !( *this == arg );
}
// Дружественный оператор для вывода строки в выходной поток os (cout, ...)
friend std::ostream &operator<<(std::ostream &os, const String &arg) {
if (arg.n_ > 0) {
os << arg.string_;
}
return os;
}
friend void swap(String &first, String &second) noexcept {
std::swap(first.string_, second.string_);
std::swap(first.n_, second.n_);
}
};
int main() {
// Создание строк
String strA("Okay"), strB("Hello, world!");
// Вывод строк на экран
cout << "String A: " << strA << endl;
cout << "String B: " << strB << endl;
// Получение длины строки
cout << "String A len: " << strA.length() << endl;
cout << "String B len: " << strB.length() << endl;
// Копирование строки при помощи конструктора
String strC(strA);
cout << "1. String C (String A)" << endl;
cout << "String A: " << strA << endl;
cout << "String C: " << strC << endl;
// Копирование строки при помощи оператора присваивания
strC = strB;
cout << "2. String C = String B" << endl;
cout << "String B: " << strB << endl;
cout << "String C: " << strC << endl;
// Перемещение строки при помощи конструктора
String strD(std::move(strA));
cout << "3. String D (move(String A))" << endl;
cout << "String A: " << strA << endl;
cout << "String D: " << strD << endl;
// Перемещение строки при помощи оператора присваивания
strD = std::move(strB);
cout << "4. String D = move(String B)" << endl;
cout << "String B: " << strB << endl;
cout << "String D: " << strD << endl;
// Поиск символа в строке, начиная с позиции start и поиск последнего вхождения подстроки в строку
cout << "Find (o, 0) = " << strD.find('o', 0) << endl;
cout << "Find (o, 5) = " << strD.find('o', 5) << endl;
// [Find] Если символ не найден, то результат равен размеру строки
cout << "Find (o, 10) = " << strD.find('o', 10) << endl;
cout << "FindLast (o) = " << strD.findLast('o') << endl;
cout << "Find (w, 0) = " << strD.find('w', 0) << endl;
cout << "Find (w, 10) = " << strD.find('w', 10) << endl;
cout << "FindLast (w) = " << strD.findLast('w') << endl;
// [FindLast] Если символ не найден, то результат равен размеру строки
cout << "FindLast (d) = " << strD.findLast('d') << endl;
cout << "FindLast (k) = " << strD.findLast('k') << endl;
// Выделение подстроки, начиная с индекса idx с длиной выделяемой подстроки count
for (size_t i = 0; i < strD.length(); ++i) {
cout << strD.substr(i, 1);
}
cout << endl;
cout << "Substr (0, 1) = " << strD.substr(0, 1) << " (length: " << strD.substr(0, 1).length() << ')' << endl;
cout << "Substr (2, 4) = " << strD.substr(2, 4) << " (length: " << strD.substr(2, 4).length() << ')' << endl;
// Удаление подстроки, начиная с индекса idx с длиной удаляемой подстроки count
cout << "Remove (0, 1) = " << strD.remove(0, 1) << " (length: " << strD.remove(0, 1).length() << ')' << endl;
cout << "Remove (1, 3) = " << strD.remove(1, 3) << " (length: " << strD.remove(1, 3).length() << ')' << endl;
cout << "Remove (5, 4) = " << strD.remove(5, 4) << " (length: " << strD.remove(5, 4).length() << ')' << endl;
// Вставка подстроки s в строку strD в позицию index
cout << "Insert (Okay, 0) = " << strD.insert("Okay", 0) << " (length: " << strD.insert("Okay", 0).length() << ')'
<< endl;
cout << "Insert (Okay, 1) = " << strD.insert("Okay", 1) << " (length: " << strD.insert("Okay", 1).length() << ')'
<< endl;
cout << "Insert (Okay, 13) = " << strD.insert("Okay", 13) << " (length: " << strD.insert("Okay", 13).length() << ')'
<< endl;
// Удаление из строки ведущих и завершающих пробелов и табуляций
String strF(" spaces "), strG("\t 1 length \t \t");
cout << "Trim: " << strF.trim() << " (length: " << strF.trim().length() << ')' << endl;
cout << "Trim: " << strG.trim() << " (length: " << strG.trim().length() << ')' << endl;
// Чтение строки неопределенной длины до перевода строки и её сохранение в readString
String readString(String::read(cin));
cout << "New String: " << readString << " (length: " << readString.length() << ')' << endl;
cout << "New String == New String: " << ( readString == String(readString) ) << endl;
cout << "New String != New String: " << ( readString != String(readString) ) << endl;
if (readString.length() > 0) {
String temp(readString);
temp[0] = '5';
cout << "New String: " << readString << " (length: " << readString.length() << ')' << endl;
cout << "Temp: " << temp << " (length: " << temp.length() << ')' << endl;
cout << "New String == Temp: " << ( readString == temp ) << endl;
cout << "New String != Temp: " << ( readString != temp ) << endl;
}
}
Соседние файлы в папке Решения лабораторных работ (местами есть ошибки)