Пример 3: Класс, описывающий строку символов

В этом примере описание класса выделено в отдельный файл.

// файл _string_.h:

#include <string.h>

#include <iostream>

#include <assert.h>

using namespace std;

class String

{

char* str; // указатель на строку

int len; // длина строки

// операторные функции ввода-вывода строки:

friend istream& operator >> (istream&, String&);

friend ostream& operator << (ostream&, String&);

public:

String() //Конструктор по умолчанию

{ str = NULL; len=0;}

String(char *); //Основной конструктор

String(const String &); //Конструктор копирования

int GetLength() {return strlen(str);} // количество символов строки

int GetMem() {return len;} // объем памяти, выделенный для символов // строки

~String(){ delete [] str;} // деструктор

// операторные функции:

String& operator += (const String&);

String operator + (const String&);

String& operator = (const String&);

char& operator [](int i);

String operator () (int, int); //Подстрока

};

//Определение функций:

// функция ввода:

istream& operator >> (istream& is, String& st)

{

char *tmp = new char[129];

/* используем временную строку, поскольку заранее неизвестно, сколько символов будет введено */

is.getline(tmp, 128);

st = String(tmp);

delete []tmp;

return is;

}

// функция вывода:

ostream& operator << (ostream& os, String& st)

{

os << st.str;

return os;

}

// основной конструктор:

String::String(char* source)

{

len = strlen(source);

str = new char[len+1];

strcpy(str, source);

}

// конструктор копирования:

String::String(const String& source)

{

len = source.len;

str = new char[len + 1]; /* конструктор создает новый объект, поэтому освобождение ранее выделенной памяти не требуется */

strcpy(str, source.str);

}

// оператор присваивания:

String& String::operator = (const String& source)

{

if (&source!= this) //Проверка самоприсваивания

{

len = source.len;

if (str) delete []str; // освобождаем ранее выделенную память

str = new char[len+1];

strcpy(str,source.str);

}

return *this; // возвращаем текущий объект

}

// операция += (добавляет строку к текущему объекту):

String& String::operator += (const String& source)

{

len = len + source.len;

char* tmp = new char[len+1]; // выделяем память для суммы строк

strcpy(tmp, str); // копируем символы текущего объекта

strcat(tmp, source.str); // добавляем символы второй строки

if (str) delete [] str; // освобождаем память, ранее выделенную текущему объекту

str = tmp; // новая строка становится основой объекта

return *this; // функция возвращает текущий объект

}

// операция +:

String String:: operator + (const String& str2)

{

String str1(str); // создаем временный объект, чтобы не изменять текущий

str1 += str2; // используем уже запрограммированную операцию +=

return str1; // возвращаем временный объект

}

/*операция [], которая позволяет считывать и изменять символы строки, используя номер символа: */

char& String::operator [](int i)

/*тип функции обязательно должен быть ссылкой, иначе невозможно будет изменять символы */

{

assert(i>=0 && i<len); /*функция assert() проверяет условие и, если оно не выполняется, выводит сообщение об ошибке и останавливает работу программы */

return str[i];

}

/*операция (), которая будет выбирать из строки подстроку, начиная с символа с заданным номером index; длина подстроки определяется параметром count */

String String:: operator () (int index, int count)

{

String sub;

if (index <= len-1) // проверяем, не выходит ли индекс за границы строки

{

int ost = len-index;

// определяем, сколько символов осталось до конца строки

sub.len = count>ost? ost: count;

/* если запрошенное количество символов больше, чем имеется, то функция вернет имеющийся остаток строки */

sub.str = new char[sub.len+1]; // выделяем память

strncpy(sub.str, str+index, count); // копируем сиволы

sub.str[sub.len]='\0';

// функция strncpy() не дописывает признак конца строки

}

return sub;

}

// файл string.cpp:

#include <iostream>

#include <conio.h>

#include <windows.h>

#include "_string_.h"

using namespace std;

int main()

{

//Настройки шрифтов и региональных стандартов:

if(SetConsoleCP(1251)==0)

//проверка правильности установки кодировки символов для ввода

{

cerr<<"Fialed to set codepage!"<<endl;

/* если не удалось установить кодовую страницу, вывод сообщения об ошибке */

}

if(SetConsoleOutputCP(1251)==0)//тоже самое для вывода

{

cerr<<"Failed to set OUTPUT page!"<<endl;

}

do

{

String s1, s2; // исходная и результирующая строки

cout<<"Введите строку: ";

cin>>s1;

int len=s1.GetLength();

if (len)

{

unsigned n;

cout << "На сколько символов сдвинуть строку? ";

cin>>n;

n %= len; /* в результате циклического сдвига на длину строки, она принимает исходное состояние, поэтому имеет смысл выполнять сдвиг только на число, равное остатку от деления n на длину строки */

cout << "Результат:\n";

s2 = s1(n, len-n) + s1(0,n);

// в результате сдвига влево первые n символов уходят в конец строки

cout <<s2<<endl;

/* проверим соответствие выделяемой под строку памяти и количества символов строки (они должны быть равны): */

cout << "длина " << s2.GetLength() <<

" память: " << s2.GetMem() << endl;

}

} while (_getch()!= 27);

return 0;

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: