Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C++]Класс строк без использование библиотек


Автор: Centry 24.7.2008, 13:00
ОС: WindowsXP(Win32)
Комипилятор: GCC
IDE: Eclipse CDT

Постановка: Класс строк без использования std::string & std::vector и прочего

Что случилось?: Косяки с памятью и иногда Exception Error

Что делал?: Исключил возможные варианты до 1 строки!

Где ловишь?: Всё работает нормально до передачи в функцию, более того если передовать менее n раз то проблемы не возникает!!!

Где код?:
Код

#ifndef MI_String_Lib
#define MI_String_Lib

class StringC
{
 public:
 //Де/Конструкторы
 StringC():Length(0)//Пустой конструктор, ложим с строку пустоту
 {
  Allocate();
 }

 StringC(char *Line)//Передача строки символов
 {
  Assign(Line);
 }

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

 ~StringC(void)//Деструктор удаляющий массив символов Tape
 {
  Free();//ЕСЛИ УБРАТЬ ТО ВСЁ РАБОТАЕТ!!! ПОЧЕМУ???
 }


 //Интерфейсные методы
 int GetLength(void)
 {
  return Length;
 }

 char *Return(void)
 {
  return Tape;
 }

 char Return(int Position)
 {
  if(Position>0&&Position<=Length) return Tape[Position-1];
  else return '\0';
 }


//Перегруженные операторы
 void operator =(char *Line){Assign(Line);}
 void operator =(const StringC& String){Assign(String);}

 protected:
 void Assign(char *Line)
 {
  if(Tape!=Line)//Проверка на String=String.Return();
  {
   for(Length=0;Line[Length];Length++);//Подсчёт длинны переданной строки
   Free();//Освобождение текущего массива символов
   Allocate();//Выделение памяти под новый
   for(int I(0);I<Length;I++) Tape[I]=Line[I];//Посимвольное перекладывание
  }
  else return;
 }

 void Assign(const StringC& String) ЕСЛИ УБРАТЬ ТО ТОЖЕ ВСЁ РАБОТАЕТ!!! ПОЧЕМУ???
 {
  if(Tape!=String.Tape)//Проверка на String=String;
  {
   Length=String.Length;//Метод GetLength не даёт использовать, незнаю почему но так работает
   Free();//Освобождение текущего массива символов
   Allocate();//Выделение памяти под новый
   for(int I(0);I<Length;I++)Tape[I]=String.Tape[I];//Посимвольное перекладывание
  }
  else return;
 }

 void Allocate(void)
 {
  if(!Length) Length=1;
  Tape=new char[Length+1];
  Tape[Length]='\0';
 }
 void Free(void)
 {
  delete[] Tape;//суть проблемы не меняется от delete Tape;
 }

 char *Tape;//Указатель на массив символов
 int Length;//Длинна
};

#endif


Комуто может так будет удобнее:
Код

class StringC
{
 public:
 //Де/Конструкторы
 StringC():Length(0){Allocate();}
 StringC(char *Line){Assign(Line);}
 StringC(const StringC& String){Assign(String);}
 ~StringC(void){Free();}
 //Интерфейсные методы
 int GetLength(void){return Length;}
 char *Return(void){return Tape;}
 char Return(int Position){if(Position>0&&Position<=Length) return Tape[Position-1];else return '\0';}
//Перегруженные операторы
 void operator =(char *Line){Assign(Line);}
 void operator =(const StringC& String){Assign(String);}

 protected:
 void Assign(char *Line)
 {
  if(Tape!=Line)
  {
   for(Length=0;Line[Length];Length++);
   Free();Allocate();
   for(int I(0);I<Length;I++) Tape[I]=Line[I];
  }
  else return;
 }
 void Assign(const StringC& String)
 {
  if(Tape!=String.Tape)
  {
   Length=String.Length;
   Free();Allocate();
   for(int I(0);I<Length;I++)Tape[I]=String.Tape[I];
  }
  else return;
 }
 void Allocate(void)
 {
  if(!Length) Length=1;
  Tape=new char[Length+1];
  Tape[Length]='\0';
 }
 void Free(void){delete[] Tape;}
 char *Tape;
 int Length;
};


Ситуация для возникновения ошибки:
Код

void S(StringC Data)
{
 /*StringC Ya;//Иногда
 Ya=Data;*/
 cout << Data.Return();
}


void main(void)
{
 StringC A("Mage");
 S(A);//При сокращении до 2 передач, всё работает тоже!
 S(A);
 S(A);
 S(A);
 S(A);
 S(A);
 S(A);
 S(A);
 cout << "Ok";


Мои соображения:
Ошибки невозникает при аналогичной простой цепочки присваиваний, только при передаче в функцию, логично предположить что проблема с преждевременным удалением локального элемента, но такового не наблюдал

Очень прошу чего-нибудь посоветовать КРОМЕ как:
1)Использовать std::string
2)Забить на деструктор и на мегобайты памяти. Непойдёт, нужна стабильность, т.к для реального использования, не для школьного задания и т.д

Автор: vinter 25.7.2008, 23:10
неправильно написан конструктор копирования, напиши его верно. Он предназначен для копирования, а не для непойми чего.

Автор: Centry 5.8.2008, 18:27
А можно чуть-чуть по подробнее? Вроде ничего криминального не делаю:
-Беру длинну
-Удаляю старый массив
-Создаю новый
-Перекладываю в новый из полученного

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)