Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstring>
- using namespace std;
- class SimpleString { //базовый класс
- protected:
- char* data; //указатель на строку
- size_t size; //размер строки
- static int copyUse; //количество вызовов конструктора копирования
- void init() //создание пустой строки
- {
- cout << "SimpleString: init без параметров" << endl;
- data = new char;
- *data = '\0';
- size = 0;
- }
- void init(const char* str) //создание непустой строки
- {
- cout << "SimpleString: init с параметрами" << endl;
- size = strlen(str); //определяем длину строки
- data = new char[size+1]; //выделяем память
- strcpy(data, str); //копируем строку
- }
- public:
- SimpleString() //конструктор без параметров
- {
- cout << "SimpleString: Конструктор без параметров" << endl;
- init();
- }
- SimpleString(const char* str) //конструктор, принимающий в качестве параметра си-строку
- {
- cout << "SimpleString: Конструктор, принимающий в качестве параметра си-строку" << endl;
- init(str);
- }
- SimpleString(const SimpleString& str) //конструктор копирования
- {
- init(str.data);
- copyUse++;
- cout << "SimpleString: Конструктор копирования, общее количество вызовов " << copyUse << endl;
- }
- SimpleString(char c) //конструктор, принимающий символ
- {
- cout << "SimpleString: Конструктор, принимающий символ" << endl;
- data = new char[2]; //выделяем память
- *data = c; //добавляем в строку символ
- *(data+1) = '\0'; //добавляем в строку символ конца строки
- }
- ~SimpleString() //деструктор
- {
- cout << "SimpleString: Деструктор" << endl;
- delete[] data; //освобождаем память
- }
- SimpleString& operator=(const SimpleString& str) //перегрузка операции присваивания
- {
- cout << "SimpleString: Операция присваивания" << endl;
- init(str.data);
- return *this;
- }
- size_t getSize() const //получение длины строки
- {
- cout << "SimpleString: Получение длины строки" << endl;
- return size;
- }
- void print() const //вывод строки на экран
- {
- if(size!=0)
- cout << data << endl;
- else
- cout << "Пустая строка" << endl;
- }
- int virtual type() const //виртуальная функция получения типа строки(нужна для организации пользовательского меню)
- {
- cout << "SimpleString: type" << endl;
- return 1;
- }
- void clear() //удаление строки(очистка памяти)
- {
- cout << "SimpleString: clear" << endl;
- if(size!=0)
- {
- delete[] data; //освобождаем память
- init(); //инициализируем пустую строку
- }
- }
- };
- class IdString : public SimpleString { //строка-идентификатор
- private:
- static int copyUse; //количество вызовов конструктора копирования
- public:
- IdString()
- {
- cout << "IdString: Конструктор без параметров" << endl;
- //нужен только вызов конструктора базового класса(автоматически), дополнительных действий не нужно
- }
- IdString(const char* str) //конструктор, принимающий в качестве параметра си-строку
- {
- cout << "IdString: Конструктор, принимающий в качестве параметра си-строку" << endl;
- if(strlen(str)==0 || !(isalpha((unsigned char)str[0]) || str[0]=='_')) //проверяем первый символ
- {
- //если строка пустая или первый символ не является латинской буквой или _
- //ничего делать не нужно, конструктор базового класса без параметров был вызван автоматически
- return;
- }
- for(int i=1; i<strlen(str); i++) //проходим по остальным символам
- {
- if(! (isalpha((unsigned char)str[i]) || isdigit((unsigned char)str[i]) || str[i]=='_') )
- {
- //символ не подходит, ничего делать не нужно
- return;
- }
- }
- init(str); //все символы подходят, можно инициализировать строку
- }
- IdString(const IdString& str) //конструктор копирования
- {
- init(str.data);
- copyUse++;
- cout << "IdString: Конструктор копирования, общее количество вызовов " << copyUse << endl;
- }
- ~IdString() //деструктор
- {
- //вызывает деструктор базового класса, больше ничего делать не нужно
- cout << "IdString: Деструктор" << endl;
- }
- IdString& operator=(const IdString& str) //перегрузка операции присваивания
- {
- cout << "IdString: Операция присваивания" << endl;
- init(str.data);
- return *this;
- }
- int lastPos(char c) const //поиск последнего вхождения символа в строку
- {
- cout << "IdString: поиск последнего вхождения символа в строку" << endl;
- for(int i=(size-1); i>=0; i--) //проходим строку от последнего символа к первому
- {
- if(data[i]==c)
- return (int)i+1;
- }
- return -1; //если символ не найден, возвращаем -1
- }
- bool operator >=(const IdString str) const //сравнение строк
- {
- cout << "IdString: >=" << endl;
- int i = 0;
- for(; i<size && i<str.size; i++) //проходим по обеим строкам, пока не дойдем до отличающихся символов(либо одна из строк кончится)
- {
- if(data[i] != str.data[i])
- break;
- }
- return data[i]>=str.data[i]; //сравниваем первые отличающиеся символы
- }
- bool operator <=(const IdString str) const //сравнение строк
- {
- cout << "IdString: <=" << endl;
- int i = 0;
- for(; i<size && i<str.size; i++) //проходим по обеим строкам, пока не дойдем до отличающихся символов(либо одна из строк кончится)
- {
- if(data[i] != str.data[i])
- break;
- }
- return data[i]<=str.data[i]; //сравниваем первые отличающиеся символы
- }
- int virtual type() const //перегрузка функции получения типа
- {
- cout << "IdString: type" << endl;
- return 2;
- }
- };
- class DecString : public SimpleString { //десятичная строка
- private:
- static int copyUse; //количество вызовов конструктора копирования
- public:
- DecString() //конструктор без параметров
- {
- cout << "DecString: Конструктор без параметров" << endl;
- //нужен только вызов конструктора базового класса(автоматически), дополнительных действий не нужно
- }
- DecString(const char* str) //конструктор, принимающий в качестве параметра си-строку
- {
- cout << "DecString: Конструктор, принимающий в качестве параметра си-строку" << endl;
- if(strlen(str)==0 || !(isdigit((unsigned char)str[0]) || str[0]=='-' || str[0]=='+'))
- {
- //проверяем первый символ, если он не цифра или знак - или +, ничего не делаем
- return;
- }
- for(int i=1; i<strlen(str); i++)
- {
- if(!isdigit((unsigned char)str[i]))
- {
- //символ не подходит, ничего делать не нужно
- return;
- }
- }
- //все символы подходят, инициализируем строку
- if(isdigit(str[0])) //если первый символ не является знаком, запишем знак(для единообразия строк)
- {
- char *tmp = new char[strlen(str)+1]; //создаем новую строку на один символ длиннее
- tmp[0] = '+'; //записываем +
- tmp[1] = '\0'; //записываем символ конца строки
- strcat(tmp, str); //добаляем существующую строку
- init(tmp); //инициализируем
- delete[] tmp; //освобождаем память
- }
- else
- init(str); //инициализируем
- }
- DecString(const DecString& str) //конструктор копирования
- {
- //никаких дополнительных проверок не нужно, так как они уже произведены при создании объекта str
- init(str.data);
- copyUse++;
- cout << "DecString: Конструктор копирования, общее количество вызовов " << copyUse << endl;
- }
- ~DecString() //деструктор
- {
- //вызывает деструктор базового класса
- cout << "DecString: Деструктор" << endl;
- }
- DecString& operator=(const DecString& str) //перегрузка операции присваивания
- {
- cout << "DecString: Операция присваивания" << endl;
- //никаких дополнительных проверок не нужно, так как они уже произведены при создании объекта str
- init(str.data);
- return *this;
- }
- bool isUnsignedChar() const //проверка, можно ли представить число как unsigned char
- {
- cout << "DecString: isUnsignedChar" << endl;
- if(size==0 || data[0]=='-' || size>4) //если строка пустая или число отрицательное или больше 4 символов
- return false;
- int n=0; //для получения самого числа
- int m=1; //множитель (чтобы учитывать разряд)
- for(int i=(size-1); i>0; i--) //от последнего символа к первому (единицы, десятки и т.д.)
- {
- n+=m*(data[i]-'0'); //переводим код симлова в число и умножаем на соответствующий множитель
- m*=10;
- }
- return n<256; //если число меньше 256, его можно представить в unsigned int
- }
- bool operator >=(const DecString str) const //сравнение чисел
- {
- cout << "DecString: >=" << endl;
- if(size==0 && str.size==0) //обе строки пустые
- return true;
- if(size==0) //если первая строка пустая
- return str.data[0]=='-'; //первая больше, если вторая отрицательная
- if(str.size==0) //если вторая строка пустая
- return data[0]=='+'; //первая больше, если она положительная
- if(data[0]!=str.data[0]) //строки имеют разные знаки
- return data[0]=='+'; //первая больше, если она положительная
- if(size>str.size) //если в одном числе больше цифр, то оно больше, если числа положительные
- return data[0]=='+';
- else if(str.size>size)
- return data[0]=='-';
- for(int i=1; i<size; i++) //в числах одинаковое количество цифр
- {
- if(data[i]>str.data[i]) //сравниваем, начиная со старших разрядов
- return data[0]=='+';
- else if(str.data[i]>data[i])
- return data[0]=='-';
- }
- return true; //если все цифры были одинаковые, числа равны
- }
- bool operator <=(const DecString str) const //сравнение чисел
- {
- cout << "DecString: <=" << endl;
- if(size==0 && str.size==0) //обе строки пустые
- return true;
- if(size==0) //если первая строка пустая
- return str.data[0]=='+'; //первая меньше, если вторая положительная
- if(str.size==0) //если вторая строка пустая
- return data[0]=='-'; //первая меньше, если она отрицательная
- if(data[0]!=str.data[0]) //строки имеют разные знаки
- return data[0]=='-'; //первая меньше, если она отрицательная
- if(size<str.size) //если в одном числе меньше цифр, то оно меньше, если числа положительные
- return data[0]=='+';
- else if(str.size<size)
- return data[0]=='-';
- for(int i=1; i<size; i++) //в числах одинаковое количество цифр
- {
- if(data[i]<str.data[i]) //сравниваем, начиная со старших разрядов
- return data[0]=='+';
- else if(str.data[i]<data[i])
- return data[0]=='-';
- }
- return true; //если все цифры были одинаковые, числа равны
- }
- int virtual type() const //перегрузка функции оперделения типа строки
- {
- cout << "DecString: type" << endl;
- return 3;
- }
- };
- int SimpleString::copyUse = 0;
- int IdString::copyUse = 0;
- int DecString::copyUse = 0;
- void init(SimpleString**& strings, int& N) //меню инициализации
- {
- cout << "1 - Число элементов\n2 - Начальное значение\n";
- int m;
- cin >> m;
- switch (m) {
- case 1: //задать число элементов
- if(N==0) //число элементов еще не задано
- {
- cout << "Введите число элементов: " << endl;
- cin >> N;
- if(N<0) //отрицательное значение недопустимо
- {
- N=0;
- return;
- }
- strings = new SimpleString*[N]; //выделяем память
- for(int i=0; i<N; i++)
- {
- strings[i] = NULL; //строк пока нет, все указатели нулевые
- }
- }
- else
- {
- cout << "Число элементов уже введено" << endl;
- }
- break;
- case 2: //задать начальное значение
- if(N==0)
- {
- cout << "Не введено число элементов" << endl;
- }
- else
- {
- int n = 0;
- while(!(n>0 && n<=N)) //спрашиваем номер до тех пор, пока не будет введен существующий
- {
- cout << "Введите номер элемента: ";
- cin >> n;
- }
- cout << "Тип строки: 1 - произвольная, 2 - идентификатор, 3 - десятичная" << endl;
- int type;
- cin >> type; //выбор типа
- char str[256];
- cout << "Введите значение: " << endl;
- cin >> str; //ввод строки
- if(strings[n-1]!=NULL)
- strings[n-1]->clear(); //очищаем строку
- switch (type) { //создаем объект в зависимости от выбранного типа
- case 1:
- strings[n-1] = new SimpleString(str);
- break;
- case 2:
- strings[n-1] = new IdString(str);
- break;
- case 3:
- strings[n-1] = new DecString(str);
- break;
- default:
- break;
- }
- }
- break;
- default:
- break;
- }
- }
- void test(SimpleString **strings, int N) //меню тестирования
- {
- int m;
- cout << "1 - Строка, 2 - Строка-идентификатор, 3 - Десятичная строка, 4 - задать операнды" << endl;
- cin >> m;
- int strNum;
- switch (m) {
- case 1: //простая строка
- cout << "Выберите одну из введенных строк: " << endl;
- for(int i=0; i<N; i++)
- {
- if(strings[i] && strings[i]->type()==1) //показываем только объекты SimpleString
- {
- cout << i+1 << " - ";
- strings[i]->print(); //выводим строку на экран
- }
- }
- cin >> strNum; //получаем номер
- if(strings[strNum-1] && strings[strNum-1]->type()==1) //если номер введен правильно
- {
- cout << "Строка ";
- strings[strNum-1]->print();
- int t = strings[strNum-1]->getSize(); //проверяем функцию получения размера
- cout << "Длина строки: " << t << endl;
- }
- break;
- case 2: //идентификатор
- cout << "Выберите одну из введенных строк: " << endl;
- for(int i=0; i<N; i++)
- {
- if(strings[i] && strings[i]->type()==2) //показываем только строки-идентификаторы
- {
- cout << i+1 << " - ";
- strings[i]->print(); //выводим на экран
- }
- }
- cin >> strNum;
- if(strings[strNum-1] && strings[strNum-1]->type()==2) //если номер введен правильно
- {
- cout << "Поиск последнего вхождения символа в строку, введите символ: ";
- char c;
- cin >> c;
- int t = ((IdString*)strings[strNum-1])->lastPos(c); //тестируем функцию поска последнего вхождения символа в строку
- cout << "Последнее вхождение сивола в строку " << t << endl;
- }
- break;
- case 3: //десятичная строка
- cout << "Выберите одну из введенных строк: " << endl;
- for(int i=0; i<N; i++)
- {
- if(strings[i] && strings[i]->type()==3) //показываем только десятичные строки
- {
- cout << i+1 << " - ";
- strings[i]->print();
- }
- }
- cin >> strNum;
- if(strings[strNum-1] && strings[strNum-1]->type()==3) //если номер введен правильно
- {
- bool b = ((DecString*)strings[strNum-1])->isUnsignedChar(); //тестируем функцию isUnsignedChar
- if(b)
- cout << "Число можно представить в формате unsigned char" << endl;
- else
- cout << "Число нельзя представить в формате unsigned char" << endl;
- }
- break;
- case 4: //тестирование операций сравнения
- cout << "Введите номера операндов: " << endl;
- int a, b;
- cin >> a >> b;
- if(strings[a-1]->type()!=strings[b-1]->type()) //для проверки операций типы строк должны быть одинаковые
- {
- cout << "Разные типы строк" << endl;
- }
- else
- {
- if(strings[a-1]->type()==1) //для класса SimpleString операции >= и <= не определены
- {
- cout << "Нет доступных операций" << endl;
- }
- else
- {
- strings[a-1]->print(); //выводим операнды
- strings[b-1]->print();
- cout << "1 - >=, 2 - <=" << endl;
- int t;
- cin >> t; //выбор операции
- bool yes;
- if(t==1) // >=
- {
- if(strings[a-1]->type()==2) //строки-идентификаторы
- yes = *((IdString*)strings[a-1])>=*((IdString*)strings[b-1]);
- else //десятичные строки
- yes = *((DecString*)strings[a-1])>=*((DecString*)strings[b-1]);
- }
- else // <=
- {
- if(strings[a-1]->type()==2) //строки-идентификаторы
- yes = *((IdString*)strings[a-1])<=*((IdString*)strings[b-1]);
- else //десятичные строки
- yes = *((DecString*)strings[a-1])<=*((DecString*)strings[b-1]);
- }
- if(yes)
- {
- cout << "да" << endl;
- }
- else
- {
- cout << "нет" << endl;
- }
- }
- }
- break;
- default:
- break;
- }
- }
- int main(int argc, const char * argv[]) {
- setlocale(LC_ALL, "Russian");
- SimpleString **strings;
- int N = 0;
- int m = -1;
- while(m!=0) //0 - выход
- {
- cout << "1 - Инициализация\n2 - Тестирование\n0 - Выход\n";
- cin >> m;
- switch (m) {
- case 1: //инициализация
- init(strings, N);
- break;
- case 2: //тестирование
- if(N==0) //доступно только если введено количество элементов
- cout << "Не введено количество элементов" << endl;
- else
- test(strings, N);
- default:
- break;
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement