Символьный массив — самый распространенный тип массива в С++. Объясняется это тем, что встроенного строкового типа в С++ нет. Хотя средства обработки строк в С++ достаточно развиты (см. приложение), для изучения механизма использования массивов как полей классов реализуем простой класс строк, похожих на строки Turbo Pascal [44], а заодно разберемся и с перегрузкой операции индексирования operator []. Отметим, что для добавления строк в язык программирования в системе Turbo Pascal потребовалось реализовать их в трансляторе, а мы сделаем это сами средствами стандартного языка С++.
Назовем наш класс строк TString, чтобы не иметь проблем со стандартным классом string, который реализован в составе стандартной библиотеки С++ (см. п. 21 в [1]). В Turbo Pascal строка представляет собой массив байтов длиной 256 элементов. Первый байт содержит длину строки, остальные байты — информационные, они содержат символы строки. Индексы символов изменяются от 1 до 255. В системе реализованы операции сравнения, присваивания, сцепления строк и индексирования отдельного символа. Со строками в системе Turbo Pascal оперируют шесть функций:
? L е n g t h () возвращает длину строки;
? Pos() выполняет поиск одной строки в другой слева направо; результатом является номер первого символа найденной строки или нуль, если строка не найдена;
? Delete() удаляет из строки заданное количество символов, начиная с указанного;
? Insert() выполняет вставку одной строки в другую после указанного символа;
? Сору () возвращает подстроку исходной строки;
? Concat () выполняет сцепление произвольного количества строк.
Кроме того, со строками работают стандартные функции ввода-вывода системы Turbo Pascal.
Очевидно, что набор операций слишком ограничен, поэтому в нашем классе TSt г i ng существенно расширим множество методов и операций, по возможности максимально приблизив интерфейс класса к интерфейсу стандартного класса string.
Обязательный набор операций включает в себя все операции сравнения, а также операции сцепления + и индексирования [ ]. Писать операцию присваивания, очевидно, нет необходимости, так как она создается по умолчанию. Помимо перечисленных, мы можем реализовать еще несколько полезных операций. Первым кандидатом является операция сцепления с присваиванием +=. Операции удаления подстроки тоже можно разнообразить, реализовав, например, операции -= и -.
Перегруженные операции дают возможность оперировать только всей строкой. Для манипулирования подстроками реализуем множество дополнительных методов:
? присваивания с общим именем assign;
? сравнения с общим именем compare;
? поиска подстроки слева и справа с общими именами find и rfind соответственно;
? добавления, удаления, вставки и замены подстрок с общими именами append, erase, insert и replace;
? преобразования строки в верхний и нижний регистры.
Полезной также будет функция substrO, возвращающая подстроку текущей строки. Так как преобразование строки в верхний и нижний регистры представляет собой фактически унарную операцию, преобразование в верхний регистр можно реализовать, перегрузив операцию инкремента ++, а преобразование в нижний регистр — перегрузив операцию декремента
Нам потребуются конструктор без аргументов и несколько конструкторов инициализации: символьной и строковой константой, подстрокой уже объявленной строки и символьного массива. Конструктор копирования, как обычно, можно не определять. Интерфейс класса TString представлен в листинге 4.2.
Листинг 4.2. Интерфейс класса TString
class TString { public:
typedef unsigned char byte: // для сокращения записи
// конструкторы
TStringO:size(),s() { }; // конструктор без аргументов
TString(const char ch, byte count = 1); TString(const char S[]);
TString(const char *First, const char *Last);
TString(const char S[], byte ind, byte count=-l);
TString(const TString &S, byte ind, byte count=-l); // методы присваивания
TString& assign(const char ch, byte count = 1);
TString& assign(const char rhs[], byte ind, byte count=-l);
TString& assign(const char *First, const char *Last);
TString& assign(const TString &rhs, byte ind, byte count=-l); // индексирование
char& operator[](const byte &ind);
const char& operator[](const byte &ind) const;
byte LengthO const { return size; }
Листинг 4.2 (продолжение)
const TString &rhs) const;
byte pos_rhs. byte count_rhs) const; const char rhs[]) const;
II сравнение
int compare(byte pos, byte count int compare(byte pos, byte count
const TString &rhs, int compare(byte pos, byte count int compare(const char *First, const char *Last) const; int compare(byte pos, byte count,
const char rhs[], byte pos_rhs, byte count_rhs) const; // добавление в конец
TString& oper'ator+=(const TString &rhs); TString& append(const char ch, byte count = 1); TString& append(const char rhs[], byte ind, byte count=-l); TString& append(const char *First, const char *Last); TString& append(const TString &S, byte ind, byte count=-l); // вставка в строку
TString& insert(byte pos, TString& insert(byte pos.
byte ind, byte count = -1);
byte n, const char ch, byte count = 1);
byte n, const char rhs[], byte count = -1);
byte n, const char *First, const char *Last);
byte n, const TString &rhs);
byte n,
byte ind, byte count = -1);
const char ch, byte count = 1); const char rhs[], byte count = -1); TString& insert(byte pos, const char *First, const char *Last); TString& insert(byte pos, const TString &rhs); TString& insert(byte pos,
const TString &rhs
// замена подстроки
TString& replace(byte pos, TString& replace(byte pos, TString& replace(byte pos, TString& replace(byte pos, TString& replace(byte pos,
const TString &rhs
// удаление подстроки
TString& erase(byte pos, byte count = -1); TString& operator-=(const TString &rhs); // получение подстроки
TString substr(byte pos, byte count = -1) const; // поиск подстрок // поиск слева направо
byte find(const TString &rhs, byte pos = 0) const; byte find(byte index, const TString &rhs, byte pos = 0) const; byte find(const char rhs[], byte pos = 0) const; byte find(byte index, const char rhs[], byte pos = 0) const; byte find(const char rhs) const; byte find(byte index, const char rhs) const; // поиск справа налево
byte rfind(const TString &rhs, byte pos = 0) const; byte rfind(byte index, const TString &rhs, byte pos = 0) const; byte rfind(const char rhs[], byte pos = 0) const; byte rfind(byte index, const char rhs[], byte pos = 0) const; byte rfind(const char rhs) const; byte rfind(byte index, const char rhs) const; // смена регистра
// toUpper // toLower
TString operator++(); TString operator--(); // дружественные функции
friend TString operator+(const TString &lhs, const TString &rhs); friend TString operator-(const TString &lhs, const TString &rhs);
friend ostream& operator<<(ostream& t, const TString &S); friend istream& operator>>(istream& t, TString &S); friend bool operator==(const TString &lhs, const TString &rhs); friend bool operator!=(const TString &lhs, const TString &rhs); friend bool operator<(const TString &lhs, const TString &rhs); friend bool operator>(const TString &lhs, const TString &rhs); friend bool operator<=(const TString &lhs, const TString &rhs); friend bool operator>=(const TString &lhs, const TString &rhs); private:
byte size; char s[256];
}:
Если у вас свой дом и вам нужен громоотвод, то подробнее об этом можете почитать тут - http://groundtech.ru/interesnye-materialy/153-gromootvod-svoimi-rukami.html.
Поля данных в нашем классе, естественно, закрыты. Поле size содержит длину строки. Строки Turbo Pascal не завершаются нулем и имеют максимальную длину 255 символов, но мы для надежности зарезервировали массив на 256 байт, чтобы в последнем байте всегда был нуль — это гарантирует нам отсутствие неожиданностей при обработке массива функциями библиотеки <cstring>1. Индексирование символов, как принято в С++, будем начинать с нуля. Индекс последнего символа равен 254, а максимальная длина строки — 255 символам. |