Зависает программа после ввода строки.Подскажите в чем ошибка?
#include<iostream>
#include <cstring>
class MyString
{
private:
size_t length;
char *str;
public:
MyString ();
MyString (const char *c);
MyString (const MyString& t);
~MyString ();
MyString& operator= (const MyString& t);
MyString& operator= (const char *c);
MyString operator+ (const MyString& t) const;
MyString& operator+= (const MyString& t);
char& operator[] (size_t i);
const char& operator[] (size_t i) const;
char& at (size_t i);
const char& at (size_t i) const;
void get_input (std::istream& in);
size_t get_length () const;
void from_c_str (const char *other);
friend std::ostream& operator<< (std::ostream& out, const MyString& t);
friend std::istream& operator>> (std::istream& in, MyString& t);
friend bool operator== (const MyString& t, char *c);
friend bool operator== (const MyString& t, const MyString& t1);
friend bool operator!= (const MyString& t, char *c);
friend bool operator!= (const MyString& t, const MyString& t1);
};
MyString::MyString ()
{
length = 1;
str = '\0';
}
MyString::MyString (const char *c)
{
from_c_str (c);
}
MyString::MyString (const MyString& t)
{
from_c_str (t.str);
}
MyString::~MyString ()
{
delete[] str;
}
MyString& MyString::operator= (const MyString& t)
{
from_c_str (t.str);
return *this;
}
MyString& MyString::operator= (const char *c)
{
from_c_str (c);
return *this;
}
MyString MyString::operator+ (const MyString& t) const
{
return (MyString(str) += t.str);
}
bool operator== (const MyString& t, char *c)
{
return (strcmp(t.str, c) == 0);
}
bool operator== (const MyString& t, const MyString& t1)
{
return (strcmp(t.str, t1.str) == 0);
}
bool operator!= (const MyString& t, char *c)
{
return !(operator== (t, c));
}
bool operator!= (const MyString& t, const MyString& t1)
{
return !(operator== (t, t1.str));
}
MyString& MyString::operator+= (const MyString& t)
{
length = strlen (str) + strlen (t.str) + 1;
char *newStr = new char[length];
strcpy (newStr, str);
strcat (newStr, t.str);
strcpy (str, newStr);
str[length-1] = '\0';
delete[] newStr;
return *this;
}
char& MyString::operator[] (size_t i)
{
return str[i];
}
const char& MyString::operator[] (size_t i) const
{
return str[i];
}
void MyString::get_input (std::istream& in)
{
while (true)
{
char c = in.get ();
if (c == '\n')
{
break;
}
if (length == 0)
{
length = 2;
}
else
{
++length;
}
char* newStr = new char[length];
if (str != NULL)
{
strcpy (newStr, str);
}
newStr[length-2] = c;
newStr[length-1] = '\0';
delete[] str;
str = newStr;
}
}
size_t MyString::get_length () const
{
return (length - 1);
}
void MyString::from_c_str (const char *c)
{
length = strlen (c) + 1;
str = new char[length];
strcpy (str, c);
}
std::ostream& operator<< (std::ostream& out, const MyString& t)
{
out << t.str;
return out;
}
std::istream& operator>> (std::istream& in, MyString& t)
{
t.get_input (in);
return in;
}
int main()
{
MyString st;
MyString zt;
MyString tt;
cin >> st;
cout << st<<endl;
cin >> zt;
cout <<zt<<endl;
tt = st += zt;
cout << tt;
system("pause");
return 0;
}
MyString::MyString ()
{
length = 1;
str = '\0';
}
Начиная с C++11 str = '\0'
уже запрещено. Да и даже до С++11 такая запись хоть и являлась корректной, но все равно была сбивающей с толку. Это эквивалентно str = nullptr
. Почему при этом делается length = 1
- не ясно. Откуда взялось
1
?
MyString& MyString::operator+= (const MyString& t)
{
length = strlen (str) + strlen (t.str) + 1;
char *newStr = new char[length];
strcpy (newStr, str);
strcat (newStr, t.str);
strcpy (str, newStr);
str[length-1] = '\0';
delete[] newStr;
return *this;
}
Тут уже написана какая-то чушь. Результат правильно формируется в newStr
, но потом зачем-то тупо копируется в str
при помощи strcpy (str, newStr)
(!). Это как это? В str
не хватит места для всей newStr
. Вылет за пределы выделенной памяти, поведение не определено.
MyString& MyString::operator= (const MyString& t)
{
from_c_str (t.str);
return *this;
}
MyString& MyString::operator= (const char *c)
{
from_c_str (c);
return *this;
}
В результате такого "присваивания" старое содержимое строки становится утечкой памяти. Оператор присваивания обязан освобождать старое содержимое строки.
Оператор +=
написан только в одной форме
MyString MyString::operator+ (const MyString& t) const
но при этом используется в коде со вторым операндом типа char *
. Это работает благодарая конструктору конверсии
MyString::MyString (const char *c)
Но почему тогда для всех остальных операторов реализовано две отдельных версии? одна для MyString
, другая для const char *c
? Где логика? И почему в реализации
MyString MyString::operator+ (const MyString& t) const
{
return (MyString(str) += t.str);
}
делается вызов +=
именно с использованием конструктора конверсии, когда можно было запросто обойтись без него
MyString MyString::operator+ (const MyString& t) const
{
return MyString(*this) += t;
}
?
В конструкторе
MyString::MyString ()
{
length = 1;
str = '\0';
}
переменная str указывает на константную область кода, а в коде везде вы удаляете str последствия непредсказуемые. Сначала нужно выделять память и записывать туда нулевой байт. Ошибка в сложении двух строк :
MyString& MyString::operator+= (const MyString& t)
{
length = strlen (str) + strlen (t.str) + 1;
char *newStr = new char[length];
strcpy (newStr, str);
strcat (newStr, t.str);
strcpy (str, newStr);
str[length-1] = '\0';
delete[] newStr;
return *this;
}
Новая строка newStr уже собрана, а вы копируете большую строку в маленькую часть памяти str. Можно сделать это так :
delete[] str;
str = newStr;
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Как можно упростить/улучшить код, чтобы он не кушал ~50% ЦП? Вот, собственно, код:
возникла проблема с использованием boost, использую пример по туториалу с двуноправленным контейнером, но он почему-то отказывается работать
Мне нужно сделать bool, который будет возвращать true, если (1 + (rand() % 101)) <= 50, в противном случае возвращать false