Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.77 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4.  
  5. class SimpleString { //базовый класс
  6. protected:
  7.     char* data; //указатель на строку
  8.     size_t size; //размер строки
  9.     static int copyUse; //количество вызовов конструктора копирования
  10.     void init() //создание пустой строки
  11.     {
  12.         cout << "SimpleString: init без параметров" << endl;
  13.         data = new char;
  14.         *data = '\0';
  15.         size = 0;
  16.     }
  17.     void init(const char* str) //создание непустой строки
  18.     {
  19.         cout << "SimpleString: init с параметрами" << endl;
  20.         size = strlen(str); //определяем длину строки
  21.         data = new char[size+1]; //выделяем память
  22.         strcpy(data, str); //копируем строку
  23.     }
  24. public:
  25.     SimpleString() //конструктор без параметров
  26.     {
  27.         cout << "SimpleString: Конструктор без параметров" << endl;
  28.         init();
  29.     }
  30.     SimpleString(const char* str) //конструктор, принимающий в качестве параметра си-строку
  31.     {
  32.         cout << "SimpleString: Конструктор, принимающий в качестве параметра си-строку" << endl;
  33.         init(str);
  34.     }
  35.     SimpleString(const SimpleString& str) //конструктор копирования
  36.     {
  37.         init(str.data);
  38.         copyUse++;
  39.         cout << "SimpleString: Конструктор копирования, общее количество вызовов " << copyUse << endl;
  40.     }
  41.     SimpleString(char c) //конструктор, принимающий символ
  42.     {
  43.         cout << "SimpleString: Конструктор, принимающий символ" << endl;
  44.         data = new char[2]; //выделяем память
  45.         *data = c; //добавляем в строку символ
  46.         *(data+1) = '\0'; //добавляем в строку символ конца строки
  47.     }
  48.     ~SimpleString() //деструктор
  49.     {
  50.         cout << "SimpleString: Деструктор" << endl;
  51.         delete[] data; //освобождаем память
  52.     }
  53.     SimpleString& operator=(const SimpleString& str) //перегрузка операции присваивания
  54.     {
  55.         cout << "SimpleString: Операция присваивания" << endl;
  56.         init(str.data);
  57.         return *this;
  58.     }
  59.     size_t getSize() const //получение длины строки
  60.     {
  61.         cout << "SimpleString: Получение длины строки" << endl;
  62.         return size;
  63.     }
  64.     void print() const //вывод строки на экран
  65.     {
  66.         if(size!=0)
  67.             cout << data << endl;
  68.         else
  69.             cout << "Пустая строка" << endl;
  70.     }
  71.     int virtual type() const //виртуальная функция получения типа строки(нужна для организации пользовательского меню)
  72.     {
  73.         cout << "SimpleString: type" << endl;
  74.         return 1;
  75.     }
  76.     void clear() //удаление строки(очистка памяти)
  77.     {
  78.         cout << "SimpleString: clear" << endl;
  79.         if(size!=0)
  80.         {
  81.             delete[] data; //освобождаем память
  82.             init(); //инициализируем пустую строку
  83.         }
  84.     }
  85. };
  86.  
  87. class IdString : public SimpleString { //строка-идентификатор
  88. private:
  89.     static int copyUse; //количество вызовов конструктора копирования
  90. public:
  91.     IdString()
  92.     {
  93.         cout << "IdString: Конструктор без параметров" << endl;
  94.         //нужен только вызов конструктора базового класса(автоматически), дополнительных действий не нужно
  95.     }
  96.     IdString(const char* str) //конструктор, принимающий в качестве параметра си-строку
  97.     {
  98.         cout << "IdString: Конструктор, принимающий в качестве параметра си-строку" << endl;
  99.         if(strlen(str)==0 || !(isalpha((unsigned char)str[0]) || str[0]=='_')) //проверяем первый символ
  100.         {
  101.             //если строка пустая или первый символ не является латинской буквой или _
  102.             //ничего делать не нужно, конструктор базового класса без параметров был вызван автоматически
  103.             return;
  104.         }
  105.         for(int i=1; i<strlen(str); i++) //проходим по остальным символам
  106.         {
  107.             if(! (isalpha((unsigned char)str[i]) || isdigit((unsigned char)str[i]) || str[i]=='_') )
  108.             {
  109.                 //символ не подходит, ничего делать не нужно
  110.                 return;
  111.             }
  112.         }
  113.         init(str); //все символы подходят, можно инициализировать строку
  114.     }
  115.     IdString(const IdString& str) //конструктор копирования
  116.     {
  117.         init(str.data);
  118.         copyUse++;
  119.         cout << "IdString: Конструктор копирования, общее количество вызовов " << copyUse << endl;
  120.     }
  121.     ~IdString() //деструктор
  122.     {
  123.         //вызывает деструктор базового класса, больше ничего делать не нужно
  124.         cout << "IdString: Деструктор" << endl;
  125.     }
  126.     IdString& operator=(const IdString& str) //перегрузка операции присваивания
  127.     {
  128.         cout << "IdString: Операция присваивания" << endl;
  129.         init(str.data);
  130.         return *this;
  131.     }
  132.     int lastPos(char c) const //поиск последнего вхождения символа в строку
  133.     {
  134.         cout << "IdString: поиск последнего вхождения символа в строку" << endl;
  135.         for(int i=(size-1); i>=0; i--) //проходим строку от последнего символа к первому
  136.         {
  137.             if(data[i]==c)
  138.                 return (int)i+1;
  139.         }
  140.         return -1; //если символ не найден, возвращаем -1
  141.     }
  142.     bool operator >=(const IdString str) const //сравнение строк
  143.     {
  144.         cout << "IdString: >=" << endl;
  145.         int i = 0;
  146.         for(; i<size && i<str.size; i++) //проходим по обеим строкам, пока не дойдем до отличающихся символов(либо одна из строк кончится)
  147.         {
  148.             if(data[i] != str.data[i])
  149.                 break;
  150.         }
  151.         return data[i]>=str.data[i]; //сравниваем первые отличающиеся символы
  152.     }
  153.     bool operator <=(const IdString str) const //сравнение строк
  154.     {
  155.         cout << "IdString: <=" << endl;
  156.         int i = 0;
  157.         for(; i<size && i<str.size; i++) //проходим по обеим строкам, пока не дойдем до отличающихся символов(либо одна из строк кончится)
  158.         {
  159.             if(data[i] != str.data[i])
  160.                 break;
  161.         }
  162.         return data[i]<=str.data[i]; //сравниваем первые отличающиеся символы
  163.     }
  164.     int virtual type() const //перегрузка функции получения типа
  165.     {
  166.         cout << "IdString: type" << endl;
  167.         return 2;
  168.     }
  169. };
  170.  
  171. class DecString : public SimpleString { //десятичная строка
  172. private:
  173.     static int copyUse; //количество вызовов конструктора копирования
  174. public:
  175.     DecString() //конструктор без параметров
  176.     {
  177.         cout << "DecString: Конструктор без параметров" << endl;
  178.         //нужен только вызов конструктора базового класса(автоматически), дополнительных действий не нужно
  179.     }
  180.     DecString(const char* str) //конструктор, принимающий в качестве параметра си-строку
  181.     {
  182.         cout << "DecString: Конструктор, принимающий в качестве параметра си-строку" << endl;
  183.         if(strlen(str)==0 || !(isdigit((unsigned char)str[0]) || str[0]=='-' || str[0]=='+'))
  184.         {
  185.             //проверяем первый символ, если он не цифра или знак - или +, ничего не делаем
  186.             return;
  187.         }
  188.         for(int i=1; i<strlen(str); i++)
  189.         {
  190.             if(!isdigit((unsigned char)str[i]))
  191.             {
  192.                 //символ не подходит, ничего делать не нужно
  193.                 return;
  194.             }
  195.         }
  196.         //все символы подходят, инициализируем строку
  197.         if(isdigit(str[0])) //если первый символ не является знаком, запишем знак(для единообразия строк)
  198.         {
  199.             char *tmp = new char[strlen(str)+1]; //создаем новую строку на один символ длиннее
  200.             tmp[0] = '+'; //записываем +
  201.             tmp[1] = '\0'; //записываем символ конца строки
  202.             strcat(tmp, str); //добаляем существующую строку
  203.             init(tmp); //инициализируем
  204.             delete[] tmp; //освобождаем память
  205.         }
  206.         else
  207.             init(str); //инициализируем
  208.     }
  209.     DecString(const DecString& str) //конструктор копирования
  210.     {
  211.         //никаких дополнительных проверок не нужно, так как они уже произведены при создании объекта str
  212.         init(str.data);
  213.         copyUse++;
  214.         cout << "DecString: Конструктор копирования, общее количество вызовов " << copyUse << endl;
  215.     }
  216.     ~DecString() //деструктор
  217.     {
  218.         //вызывает деструктор базового класса
  219.         cout << "DecString: Деструктор" << endl;
  220.     }
  221.     DecString& operator=(const DecString& str) //перегрузка операции присваивания
  222.     {
  223.         cout << "DecString: Операция присваивания" << endl;
  224.         //никаких дополнительных проверок не нужно, так как они уже произведены при создании объекта str
  225.         init(str.data);
  226.         return *this;
  227.     }
  228.     bool isUnsignedChar() const //проверка, можно ли представить число как unsigned char
  229.     {
  230.         cout << "DecString: isUnsignedChar" << endl;
  231.         if(size==0 || data[0]=='-' || size>4) //если строка пустая или число отрицательное или больше 4 символов
  232.             return false;
  233.         int n=0; //для получения самого числа
  234.         int m=1; //множитель (чтобы учитывать разряд)
  235.         for(int i=(size-1); i>0; i--) //от последнего символа к первому (единицы, десятки и т.д.)
  236.         {
  237.             n+=m*(data[i]-'0'); //переводим код симлова в число и умножаем на соответствующий множитель
  238.             m*=10;
  239.         }
  240.         return n<256; //если число меньше 256, его можно представить в unsigned int
  241.     }
  242.     bool operator >=(const DecString str) const //сравнение чисел
  243.     {
  244.         cout << "DecString: >=" << endl;
  245.         if(size==0 && str.size==0) //обе строки пустые
  246.             return true;
  247.         if(size==0) //если первая строка пустая
  248.             return str.data[0]=='-'; //первая больше, если вторая отрицательная
  249.         if(str.size==0) //если вторая строка пустая
  250.             return data[0]=='+'; //первая больше, если она положительная
  251.         if(data[0]!=str.data[0]) //строки имеют разные знаки
  252.             return data[0]=='+'; //первая больше, если она положительная
  253.         if(size>str.size) //если в одном числе больше цифр, то оно больше, если числа положительные
  254.             return data[0]=='+';
  255.         else if(str.size>size)
  256.             return data[0]=='-';
  257.         for(int i=1; i<size; i++) //в числах одинаковое количество цифр
  258.         {
  259.             if(data[i]>str.data[i]) //сравниваем, начиная со старших разрядов
  260.                 return data[0]=='+';
  261.             else if(str.data[i]>data[i])
  262.                 return data[0]=='-';
  263.         }
  264.         return true; //если все цифры были одинаковые, числа равны
  265.     }
  266.     bool operator <=(const DecString str) const //сравнение чисел
  267.     {
  268.         cout << "DecString: <=" << endl;
  269.         if(size==0 && str.size==0) //обе строки пустые
  270.             return true;
  271.         if(size==0) //если первая строка пустая
  272.             return str.data[0]=='+'; //первая меньше, если вторая положительная
  273.         if(str.size==0) //если вторая строка пустая
  274.             return data[0]=='-'; //первая меньше, если она отрицательная
  275.         if(data[0]!=str.data[0]) //строки имеют разные знаки
  276.             return data[0]=='-'; //первая меньше, если она отрицательная
  277.         if(size<str.size) //если в одном числе меньше цифр, то оно меньше, если числа положительные
  278.             return data[0]=='+';
  279.         else if(str.size<size)
  280.             return data[0]=='-';
  281.         for(int i=1; i<size; i++) //в числах одинаковое количество цифр
  282.         {
  283.             if(data[i]<str.data[i]) //сравниваем, начиная со старших разрядов
  284.                 return data[0]=='+';
  285.             else if(str.data[i]<data[i])
  286.                 return data[0]=='-';
  287.         }
  288.         return true; //если все цифры были одинаковые, числа равны
  289.     }
  290.     int virtual type() const //перегрузка функции оперделения типа строки
  291.     {
  292.         cout << "DecString: type" << endl;
  293.         return 3;
  294.     }
  295. };
  296.  
  297. int SimpleString::copyUse = 0;
  298. int IdString::copyUse = 0;
  299. int DecString::copyUse = 0;
  300.  
  301. void init(SimpleString**& strings, int& N) //меню инициализации
  302. {
  303.     cout << "1 - Число элементов\n2 - Начальное значение\n";
  304.     int m;
  305.     cin >> m;
  306.     switch (m) {
  307.         case 1: //задать число элементов
  308.             if(N==0) //число элементов еще не задано
  309.             {
  310.                 cout << "Введите число элементов: " << endl;
  311.                 cin >> N;
  312.                 if(N<0) //отрицательное значение недопустимо
  313.                 {
  314.                     N=0;
  315.                     return;
  316.                 }
  317.                 strings = new SimpleString*[N]; //выделяем память
  318.                 for(int i=0; i<N; i++)
  319.                 {
  320.                     strings[i] = NULL; //строк пока нет, все указатели нулевые
  321.                 }
  322.             }
  323.             else
  324.             {
  325.                 cout << "Число элементов уже введено" << endl;
  326.             }
  327.             break;
  328.         case 2: //задать начальное значение
  329.             if(N==0)
  330.             {
  331.                 cout << "Не введено число элементов" << endl;
  332.             }
  333.             else
  334.             {
  335.                 int n = 0;
  336.                 while(!(n>0 && n<=N)) //спрашиваем номер до тех пор, пока не будет введен существующий
  337.                 {
  338.                     cout << "Введите номер элемента: ";
  339.                     cin >> n;
  340.                 }
  341.                 cout << "Тип строки: 1 - произвольная, 2 - идентификатор, 3 - десятичная" << endl;
  342.                 int type;
  343.                 cin >> type; //выбор типа
  344.                 char str[256];
  345.                 cout << "Введите значение: " << endl;
  346.                 cin >> str; //ввод строки
  347.                 if(strings[n-1]!=NULL)
  348.                     strings[n-1]->clear(); //очищаем строку
  349.                 switch (type) { //создаем объект в зависимости от выбранного типа
  350.                     case 1:
  351.                         strings[n-1] = new SimpleString(str);
  352.                         break;
  353.                     case 2:
  354.                         strings[n-1] = new IdString(str);
  355.                         break;
  356.                     case 3:
  357.                         strings[n-1] = new DecString(str);
  358.                         break;
  359.                     default:
  360.                         break;
  361.                 }
  362.             }
  363.             break;
  364.         default:
  365.             break;
  366.     }
  367. }
  368.  
  369. void test(SimpleString **strings, int N) //меню тестирования
  370. {
  371.     int m;
  372.     cout << "1 - Строка, 2 - Строка-идентификатор, 3 - Десятичная строка, 4 - задать операнды" << endl;
  373.     cin >> m;
  374.     int strNum;
  375.     switch (m) {
  376.         case 1: //простая строка
  377.             cout << "Выберите одну из введенных строк: " << endl;
  378.             for(int i=0; i<N; i++)
  379.             {
  380.                 if(strings[i] && strings[i]->type()==1) //показываем только объекты SimpleString
  381.                 {
  382.                     cout << i+1 << " - ";
  383.                     strings[i]->print(); //выводим строку на экран
  384.                 }
  385.             }
  386.             cin >> strNum; //получаем номер
  387.             if(strings[strNum-1] && strings[strNum-1]->type()==1) //если номер введен правильно
  388.             {
  389.                 cout << "Строка ";
  390.                 strings[strNum-1]->print();
  391.                 int t = strings[strNum-1]->getSize(); //проверяем функцию получения размера
  392.                 cout << "Длина строки: " << t << endl;
  393.             }
  394.             break;
  395.         case 2: //идентификатор
  396.             cout << "Выберите одну из введенных строк: " << endl;
  397.             for(int i=0; i<N; i++)
  398.             {
  399.                 if(strings[i] && strings[i]->type()==2) //показываем только строки-идентификаторы
  400.                 {
  401.                     cout << i+1 << " - ";
  402.                     strings[i]->print(); //выводим на экран
  403.                 }
  404.             }
  405.             cin >> strNum;
  406.             if(strings[strNum-1] && strings[strNum-1]->type()==2) //если номер введен правильно
  407.             {
  408.                 cout << "Поиск последнего вхождения символа в строку, введите символ: ";
  409.                 char c;
  410.                 cin >> c;
  411.                 int t = ((IdString*)strings[strNum-1])->lastPos(c); //тестируем функцию поска последнего вхождения символа в строку
  412.                 cout << "Последнее вхождение сивола в строку " << t << endl;
  413.             }
  414.             break;
  415.         case 3: //десятичная строка
  416.             cout << "Выберите одну из введенных строк: " << endl;
  417.             for(int i=0; i<N; i++)
  418.             {
  419.                 if(strings[i] && strings[i]->type()==3) //показываем только десятичные строки
  420.                 {
  421.                     cout << i+1 << " - ";
  422.                     strings[i]->print();
  423.                 }
  424.             }
  425.             cin >> strNum;
  426.             if(strings[strNum-1] && strings[strNum-1]->type()==3) //если номер введен правильно
  427.             {
  428.                 bool b = ((DecString*)strings[strNum-1])->isUnsignedChar(); //тестируем функцию isUnsignedChar
  429.                 if(b)
  430.                     cout << "Число можно представить в формате unsigned char" << endl;
  431.                 else
  432.                     cout << "Число нельзя представить в формате unsigned char" << endl;
  433.             }
  434.             break;
  435.         case 4: //тестирование операций сравнения
  436.             cout << "Введите номера операндов: " << endl;
  437.             int a, b;
  438.             cin >> a >> b;
  439.             if(strings[a-1]->type()!=strings[b-1]->type()) //для проверки операций типы строк должны быть одинаковые
  440.             {
  441.                 cout << "Разные типы строк" << endl;
  442.             }
  443.             else
  444.             {
  445.                 if(strings[a-1]->type()==1) //для класса SimpleString операции >= и <= не определены
  446.                 {
  447.                     cout << "Нет доступных операций" << endl;
  448.                 }
  449.                 else
  450.                 {
  451.                     strings[a-1]->print(); //выводим операнды
  452.                     strings[b-1]->print();
  453.                     cout << "1 - >=, 2 - <=" << endl;
  454.                     int t;
  455.                     cin >> t; //выбор операции
  456.                     bool yes;
  457.                     if(t==1) // >=
  458.                     {
  459.                         if(strings[a-1]->type()==2) //строки-идентификаторы
  460.                             yes = *((IdString*)strings[a-1])>=*((IdString*)strings[b-1]);
  461.                         else //десятичные строки
  462.                             yes = *((DecString*)strings[a-1])>=*((DecString*)strings[b-1]);
  463.                     }
  464.                     else // <=
  465.                     {
  466.                         if(strings[a-1]->type()==2) //строки-идентификаторы
  467.                             yes = *((IdString*)strings[a-1])<=*((IdString*)strings[b-1]);
  468.                         else //десятичные строки
  469.                             yes = *((DecString*)strings[a-1])<=*((DecString*)strings[b-1]);
  470.                     }
  471.                     if(yes)
  472.                     {
  473.                         cout << "да" << endl;
  474.                     }
  475.                     else
  476.                     {
  477.                         cout << "нет" << endl;
  478.                     }
  479.                 }
  480.             }
  481.             break;
  482.         default:
  483.             break;
  484.     }
  485. }
  486.  
  487. int main(int argc, const char * argv[]) {
  488.     setlocale(LC_ALL, "Russian");
  489.     SimpleString **strings;
  490.     int N = 0;
  491.     int m = -1;
  492.     while(m!=0) //0 - выход
  493.     {
  494.         cout << "1 - Инициализация\n2 - Тестирование\n0 - Выход\n";
  495.         cin >> m;
  496.         switch (m) {
  497.             case 1: //инициализация
  498.                 init(strings, N);
  499.                 break;
  500.             case 2: //тестирование
  501.                 if(N==0) //доступно только если введено количество элементов
  502.                     cout << "Не введено количество элементов" << endl;
  503.                 else
  504.                     test(strings, N);
  505.             default:
  506.                 break;
  507.         }
  508.     }
  509.     return 0;
  510. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement