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!