Страницы

Поиск по вопросам

понедельник, 29 апреля 2019 г.

Перегрузка оператора +=

// Реализовать класс String для работы со строками. Перегрузить операторы = + += - > < [] (подстрока) ++ -- #pragma once #include using namespace std;
class String {
char* s; int length;
public:
String(const char* str="") { this->length = strlen(str); this->s = new char[this->length+1]; for (int i = 0; i < length; i++) this->s[i] = str[i]; }
String(const String& s1) { this->length = s1.length; this->s = new char[this->length]; for (int i = 0; i < this->length; i++) this->s[i] = s1.s[i]; }
~String() { delete[] s; }

String& String::operator=(String& right); String String::operator+(String right); //String& String::operator+=(const String& right); friend String& operator+=(String& left, const String& right); void String::show();
};
А это цпп файл:
#include "String.h"
void String::show() { for (int i = 0; i < this->length; i++) cout << this->s[i]; }
String& String::operator=(String& right) { delete[] this->s; this->length = right.length; this->s = new char[this->length]; for (int i = 0; i < this->length; i++) this->s[i] = right.s[i]; return *this; }
String String::operator+(String right) { String new_string; new_string.length = this->length + right.length; new_string.s =new char[this->length + right.length+1]; for (int i = 0; i < this->length; i++) new_string.s[i] = this->s[i]; for (int i = 0; i < right.length; i++) new_string.s[this->length + i] = right.s[i]; return new_string; }
String& operator+=(String& left, const String& right) { return left+right; }
Почему у меня s3 всё равно при выводе пустая? Помогите начинающему!
#include "String.h"
void main() { String s2("Hello"); String s3; s3 += s2; s3.show(); system("pause"); }


Ответ

Мы, начинающие программисты, должны помогать друг другу.:)
Начнем с того, что вам следует включить заголовок
#include
так как вы используете функции, объявленные в этом заголовке.
Длину строки лучше определять, как имеющую тип size_t вместо int
class String { char* s; size_t length; //...
Ваши конструкторы неверно копируют строки. Они не копируют в результирующую строку завершающий символ нуля '\0'. Например,
String(const char* str="") { this->length = strlen(str); this->s = new char[this->length+1]; for (int i = 0; i < length; i++) // символ нуля не входи в диапазон `[0, length)` this->s[i] = str[i]; }
Иначе непонятно, зачем вы выделяете память длиною this->length+1 вместо this->length. Непонятно, зачем вы вообще используете циклы для копирования строк, когда вы уже используете стандартные C функции из заголовка
Лучше было бы объявить конструктор следующим образом
String( const char *str = "" ) { this->length = std::strlen( str ); this->s = new char[ this->length + 1 ]; std::strcpy( this->s, str ); }
То же самое замечание справедливо и для конструктора копирования.
В определении класса нельзя указывать квалифицированное имя функций-членов класса при их объявлении. Хотя MS VC++ это допускает, но это является его собственным расширением языка, которое не соответствует стандарту.
String& String::operator=(String& right); ^^^^^^^^
Эти объявления
String String::operator+(String right); friend String& operator+=(String& left, const String& right);
лучше переопределить следующим образом
friend String operator + ( const String &left, const String &right ); String & operator += ( const String &right );
Функцию show лучше объявить как
std::ostream & String::show( std::ostream &os = std::cout ) const;
Переопределите соответствующие функции с учетом выше приведенных замечаний.
Что касается копирующего оператора присваивания, то он может быть определен следующим образом
String & String::operator =( const String &right ) { if ( this != &right ) { size_t n = std::strlen( right.s ); char tmp = new char[ n + 1 ];
std::strcpy( tmp, right.s );
delete [] this->s;
this->s = tmp; this->length = n; }
return *this; }
Аналогичным образом вам нужно определить оператор
String & operator += ( const String &right );
Например
String & String::operator +=( const String &right ) { size_t n = this->length + std::strlen( right.s ); char tmp = new char[ n + 1 ];
std::strcpy( tmp, this->s ); std::strcat( tmp, right.s );
delete [] this->s;
this->s = tmp; this->length = n;
return *this; }
Функция show определяется просто
std::ostream & String::show( std::ostream &os ) const { return os << this->s; }
Что касается вашего вопроса
Почему у меня s3 всё равно при выводе пустая?
то этот оператор
String& operator+=(String& left, const String& right) { return left+right; }
не изменяет левый аргумент. И более того имеет неопределенное поведение, так как возвращает ссылку на временный объект, создаваемый выражением left+right.
EDIT: Если оператор operator [], который, как я понимаю, вы также должны определить, позволяет вставлять в объект класса символ '\0', то вам следует изменить определения конструктора копирования, копирующего опреатора присваивания, оператора operator +=, и дружественной функции operator +, заменив стандартные C функции strXXX на memXXX. Ниже приведена демонстрационная программа, которая показывает, как это можно сделать на примере некоторых членов класса. Другие члены класса постарайтесь определить сами.
#include #include
class String { private: char *s; size_t length;
public: String( const char *str = "" ) { this->length = std::strlen( str ); this->s = new char[ this->length + 1 ];
std::strcpy( this->s, str ); }
String( const String &src ) { this->length = src.length; this->s = new char[ this->length + 1 ];
std::memcpy( this->s, src.s, this->length + 1 ); }
String & operator =( const String &src ) { if ( this !=+ &src ) { char *tmp = new char[ src.length + 1 ];
std::memcpy( tmp, src.s, src.length + 1 );
delete [] this->s;
this->s = tmp; this->length = src.length; }
return *this; }
String & operator +=( const String &src ) { size_t n = this->length + src.length; char *tmp = new char[ n + 1 ];
std::memcpy( tmp, this->s, this->length ); std::memcpy( tmp + this->length, src.s, src.length + 1 );
delete [] this->s;
this->s = tmp; this->length = n;
return *this;
}
~String() { delete [] this->s; }
std::ostream & show( std::ostream &os = std::cout ) { return os << this->s; } };
int main() { String s1( "Hello world!" ); String s2;
s2 = s1;
s2.show() << std::endl;
s2 += " Glad to see you!";
s2.show() << std::endl;
return 0; }
Вывод программы будет следующим
Hello world! Hello world! Glad to see you!

Комментариев нет:

Отправить комментарий