// Реализовать класс String для работы со строками. Перегрузить операторы = + += - > < [] (подстрока) ++ -- #pragma once #include <iostream> 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(); }; 

And this is the cpr file:

 #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; } 

Why do I still have s3 when output is empty? Help the beginner!

 #include "String.h" void main() { String s2("Hello"); String s3; s3 += s2; s3.show(); system("pause"); } 

    1 answer 1

    We, novice programmers, should help each other. :)

    To begin with, you should include the header <cstring>

     #include <cstring> 

    since you are using the functions declared in this header.

    The length of the string is better defined as having size_t type instead of int .

     class String { char* s; size_t length; //... 

    Your constructors copy strings incorrectly. They do not copy the terminating zero character '\0' into the result string. For example,

     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]; } 

    Otherwise, it is not clear why you allocate memory with a length of this->length+1 instead of this->length . It is not clear why you generally use loops to copy strings when you already use standard C functions from the <cstring> header

    It would be better to declare the constructor as follows.

     String( const char *str = "" ) { this->length = std::strlen( str ); this->s = new char[ this->length + 1 ]; std::strcpy( this->s, str ); } 

    The same remark applies to the copy constructor.

    In the class definition, you cannot specify the qualified name of class member functions when they are declared. Although MS VC++ allows this, it is its own language extension that does not conform to the standard.

     String& String::operator=(String& right); ^^^^^^^^ 

    These ads

     String String::operator+(String right); friend String& operator+=(String& left, const String& right); 

    better override as follows

     friend String operator + ( const String &left, const String &right ); String & operator += ( const String &right ); 

    The show function is best declared as

     std::ostream & String::show( std::ostream &os = std::cout ) const; 

    Redefine the corresponding functions taking into account the above remarks.

    As for the copying assignment operator, it can be defined as follows.

     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; } 

    Similarly, you need to define an operator

     String & operator += ( const String &right ); 

    for example

     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; } 

    The show function is simply determined

     std::ostream & String::show( std::ostream &os ) const { return os << this->s; } 

    As for your question

     Почему у меня s3 всё равно при выводе пустая? 

    then this operator

     String& operator+=(String& left, const String& right) { return left+right; } 

    does not change the left argument. And what's more, it has an undefined behavior, since it returns a reference to a temporary object created by the expression left+right .

    EDIT: If operator [], which, as I understand it, you also need to define, allows you to insert the '\0' character into the class object, then you should change the definitions of the copy constructor, the copy assignment operator, operator += , and the friend function operator + , replacing the standard C functions of strXXX with memXXX . Below is a demo program that shows how this can be done using some class members as examples. Other members of the class try to determine for yourself.

     #include <iostream> #include <cstring> 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; } 

    The output of the program will be as follows.

     Hello world! Hello world! Glad to see you! 
    • Thank you, your answer was really helpful! :) - Nikita
    • @Nikita I corrected the definition of the following statement, since I had a typo and the return type was not a String & String :: operator + = (const String & right) reference. That is, the return type must be String &. - Vlad from Moscow
    • @ Nikita See my updated answer. :) - Vlad from Moscow