#include <iostream>
#include <cstdio>
using namespace std;

/* Спецификация class SmartString: 'Полезная' длина строки считается без символа конца строки, но в каждой строке он есть */     
class SmartString {
      int Length; // Длина строки
      char* Str; // Строка
      bool Org; // детектор разделения(при копировании копия и оригинал разделяют область памяти, выделенную под символы)
      
public:
       SmartString(const int len = 0); // Конструкторы без параметров (пустая строка) и с указанием длины
       SmartString(const char* st); // Конструктор преобразования из «сишной» строки
       SmartString(const SmartString& a) {Length = a.Length; Str = a.Str; Org = false;};// Конструктор копирования
       char getEl(const int ind); // Метод получения элемента по индексу
       void chngEl(const int ind, const char c); // Метод изменения элемента по индексу
       int getLen() const {return Length;}; // Метод получения длины строки
       bool getOrg() const {return Org;};
       void chngLen(const int len); // Метод изменения длины строки
       ~SmartString() // Деструктор
                      {if (Org) delete[] Str;} // только оригинал может освобождать память!
       };

/* Спецификация SmartString(const int len): 
   1. При вызове конструктора без параметров, 'полезная' длина по умолчанию 0
   2. Если 'полезная' длина строки отрицательна, то в объекте она будет нулевая "" 
*/     
SmartString:: SmartString(const int len)
      {
      int i;
      
      if (len < 0) Length = 0; else Length = len;
      Org = true;
      Str = new char[len + 1]; 
      for (i = 0; i < len; i++) Str[i] = ' ';
      Str[len] = '\0';
      }
                  

/* Спецификация SmartString(const char* st): 
   1. 'Полезная' длина строки считается без символа конца строки, но в каждой строке он есть
   2. Символ конца строки показать нельзя!
*/     
SmartString:: SmartString(const char* st)
     {
     int i;
     
     Org = true;
     Length = strlen(st); 
     Str = new char[Length + 1]; 
     for (i = 0; i <= Length; i++) Str[i] = st[i];
     }

/* Спецификация getEl:
   1. возвращает '\0' ,если вылезаем за строку
*/     
char SmartString:: getEl(const int ind)
     {
     if ((ind >= 0) && (ind < Length)) return Str[ind];
        else return '\0';
     };
     
/* Спецификация chngLen: 
   1. При уменьшении длины, обрезаем строку
   2. При увеличении - заполняем незаполненную часть пробелами
   3. Если 'полезная' длина строки отрицательна, то строка не изменяется 
   4. При изменении длины копия становится оригиналом! Только при изменении!
*/ 
void SmartString:: chngLen(const int len)
    {
    char* st; 
    int min, i;
    
    if (len >= 0)
       {
       if (len != Length) 
           {
           st = new char[len + 1];
           if (len < Length) min = len;
              else 
                {
                min = Length;
                for (i = min; i < len; i++) st[i] = ' ';
                }
           for (i = 0; i < min; i++) st[i] = Str[i];
           st[len] = '\0';
           if (Org) delete[] Str;
           Str = st;
           Org = true;
           Length = len;
           }
       }
    }
 
/* Спецификация chngEl: 
   1. Ничего не меняем, если вылезаем за строку
   2. Символ конца строки('\0') изменить нельзя!
   3. При изменении элемента копия становится оригиналом! Только при изменении!
   4. Символ-параметр не может быть символом конца строки ('\0')!(во избежании путаницы); замена не будет произведена
*/    
void SmartString:: chngEl(const int ind, const char c)
    {
    char* st; 
    int i;
    
    if ((ind >= 0) && (ind < Length) && (c != '\0'))
            {
            if ((!Org) && (Str[ind] != c))
                {
                st = new char[Length + 1];
                for (i = 0; i <= Length; i++) st[i] = Str[i];
                Str = st;
                Org = true; 
                }
    
                Str[ind] = c;
            }
    }


int main ()
    {
    SmartString QW("qwerty");
    SmartString QP(4);
    SmartString QR=QW;
    SmartString QE=QR;
    int i;
     
    QE.chngEl(4,'\0');
    QR.chngLen(0);
    
    for(i = 0;i < QW.getLen(); i++) cout << QW.getEl(i);
    cout << '|';
    for(i = 0;i < QR.getLen(); i++) cout << QR.getEl(i);
    cout << '|';
    for(i = 0;i < QE.getLen(); i++) cout << QE.getEl(i);
    cout << '|'; 
    for(i = 0;i < QP.getLen(); i++) cout << QP.getEl(i);
    cout << '|'; 
    cout << QW.getEl(8) ;
    cout << '|'; 
    cout << QR.getLen() ;
    cout << " !"; 
    cout << QW.getOrg() ;
    cout << '|'; 
    cout << QR.getOrg() ;
    cout << '|'; 
    cout << QE.getOrg() ;
    cout << '|'; 
    cout << QP.getOrg() ;
    cout << " !";
    cout << QW.getEl(0);
    
    for(;;); 
    return 0;
    }
