Страницы

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

среда, 5 февраля 2020 г.

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

#cpp #строки #классы #перегрузка_операторов #конструктор


// Реализовать класс 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");
}

    


Ответы

Ответ 1



Мы, начинающие программисты, должны помогать друг другу.:) Начнем с того, что вам следует включить заголовок #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!

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

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