This question already has answers here:
What is The Rule of Three?
(8 answers)
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 2 months ago.
I am trying this program
#include<iostream>
#include<string.h>
class stringTest
{
char* p;
int len;
public:
stringTest() { len = 0; p = 0; }
stringTest(const char* s);
stringTest(const stringTest& s);
~stringTest() { delete p; }
friend stringTest operator+(const stringTest& s, const stringTest& t);
friend int operator<=(const stringTest& s, const stringTest& t);
friend void show(const stringTest s);
};
stringTest::stringTest(const char* s)
{
len = strlen(s);
p = new char[len + 1];
strcpy(p, s);
}
stringTest::stringTest(const stringTest& s)
{
len = s.len;
p = new char[len + 1];
strcpy(p, s.p);
}
stringTest operator+(const stringTest &s, const stringTest &t)
{
stringTest temp;
temp.len = s.len + t.len;
temp.p = new char[temp.len + 1];
strcpy(temp.p, s.p);
strcat(temp.p, t.p);
return (temp);
}
int operator<=(const stringTest& s, const stringTest& t)
{
int m = strlen(s.p);
int n = strlen(t.p);
if (m <= n) return (1);
else return (0);
}
void show(const stringTest s)
{
cout << s.p;
}
int main()
{
stringTest s1 = "New ";
stringTest s2 = "York";
stringTest s3 = "Delhi";
stringTest string1, string2, string3;
string1 = s1;
string2 = s2;
string3 = s1+s2;
cout << "\nstirng1 = "; show(string1);
cout << "\nstring2 = "; show(string2);
cout << "\n";
cout << "\nstring3 = "; show(string3);
cout << "\n\n";
if (string1 <= string3)
{
show(string1);
cout << " smaller than ";
show(string3);
cout << "\n";
}
else
{
show(string3);
cout << " smaller than ";
show(string1);
cout << "\n";
}
return 0;
}
here in the function operator+ I am providing two string and getting an junk character in return.
stringTest operator+(const stringTest &s, const stringTest &t)
{
stringTest temp;
temp.len = s.len + t.len;
temp.p = new char[temp.len + 1];
strcpy(temp.p, s.p);
strcat(temp.p, t.p);
return (temp);
}
I debugged the code and saw in the memory i am able to get the proper data in temp.p but when i return it become junk character .
Please help me if i am missing something.
Thanks in advance
Vivek
Related
I am new bee for c++ . I got follow error when I override operator+ .
ConsoleApplication1.out: /root/projects/ConsoleApplication1/sdstring.cpp:43: static sdstring::size_t sdstring::strlen(const char*): Assertion `str' failed.
This is my test code!
sdstring sd1(NULL);
cout << "sd1:" << sd1 << endl;
sdstring sd2("sd2");
cout << "sd2:" << sd2 << endl;
sdstring sd3;
cin >> sd3;
cout << "sd3:" << sd3 << endl;
sd3 +=sd2 ;
cout << "sd3:" << sd3 << endl;
sdstring sd4 =sd3+sd1;
cout << "sd4:" << sd2 << endl;
sd1 = sd2 + sd1;
cout << "sd1:" << sd1 << endl;
cout << "sd3==sd2:" << (sd3 == sd2)<<endl;
Error happened in This line .
sdstring sd4 =sd3+sd1;
This is my sdstring.cpp file.
#include "sdstring.h"
#include <assert.h>
sdstring::sdstring(const char *str) {
if (!str) {
datas = new char[1];
datas[0] = '\0';
}
else {
datas = new char[strlen(str)+1];
strcpy(datas, str);
}
}
sdstring::sdstring(const sdstring& str) {
datas = new char[strlen(str.datas) + 1];
strcpy(datas, str.datas);
}
sdstring& sdstring::operator+(const sdstring& str)const {
sdstring result(NULL);
size_t total_size = getlen() + str.getlen();
result.datas = new char[total_size + 1];
strcpy(result.datas, datas);
strcat(result.datas, str.datas);
return result;
}
bool sdstring::operator==(const sdstring& str)const {
return strcmp(datas, str.datas) == 0;
}
sdstring& sdstring::operator=(const sdstring& str) {
if (this == &str)
return *this;
delete[] datas;
datas = new char[str.getlen() + 1];
strcpy(datas, str.datas);
return *this;
}
sdstring::size_t sdstring::strlen(const char* str) {
assert(str);
size_t len = 0;
while ('\0' != *str++)
len++;
return len;
}
char* sdstring::strcpy( char* des, const char* src){
assert(des&& src);
char* temp = des;
while ('\0' != (*des++ = *src++));
return temp;
}
int sdstring::strcmp(const char* fir, const char* sec) {
assert(fir && sec);
while (*fir == *sec)
{
if (*fir == '\0') {
return 0;
}
++fir;
++sec;
}
return *fir - *sec;
}
char* sdstring::strcat(char* des,const char* src) {
char* temp = des;
while ('\0' != *des)
{
des++;
}
while ('\0' != (*des++ = *src++));
return temp;
}
sdstring::~sdstring()
{
if (datas)
{
delete[] datas;
datas = nullptr;
}
}
char& sdstring::operator[](const unsigned int position)const
{
return position < getlen() ? datas[position] : datas[position-1];
}
sdstring& sdstring::operator+=(const sdstring& str)
{
size_t total_size = getlen() + str.getlen();
if (total_size != getlen()) {
char* temp = datas;
datas = new char[total_size + 1];
strcpy(datas,temp);
strcat(datas, str.datas);
delete[] temp;
}
return *this;
}
ostream& operator<<(ostream& os, const sdstring& str)
{
os << str.datas;
return os;
}
istream& operator>>(istream& is, sdstring& str)
{
char* cache = new char[1024];
is >> cache;
delete[]str.datas;
str.datas = new char[sdstring::strlen(cache)];
sdstring::strcpy(str.datas, cache);
delete[]cache;
return is;
}
Who can help me , Thanks for first!
There are several things wrong with your code. However the operator + is wrong in that it is returning a reference to a local variable, which is undefined behavior.
sdstring& sdstring::operator+(const sdstring& str)const
{
sdstring result(NULL);
//..
return result; // Undefined behavior.
}
operator + should be returning a brand new object, not a reference to an object.
sdstring sdstring::operator+(const sdstring& str)const // <-- Note the return value is sdstring
{
sdstring result(NULL);
//..
return result;
}
The other issues with your code:
1) The operator= destroys the memory using delete[] datas; before calling new[] to allocate memory for the new string. If new[] throws an exception, the sdstring object would be corrupted since the data has been destroyed and you can't go back and reset the string with the old data. Use the copy / swap idiom to prevent this from happening.
2) You should store the length of the string in a member variable instead of calling strlen every time you want to know the length of the string. The strlen is slow in that it has to loop to count every single character to determine where the terminating '\0' character is located. Instead of that, just store the length of the string once and keep using that value.
3) Instead of writing your own strlen and strcmp functions, use the library functions strlen and strcmp. Your versions are not optimized, unlike the library versions.
4) operator + can be written in terms of operator +=. operator + should be written very simply as:
sdstring sdstring::operator + (const sdstring& rhs)
{
return sdstring(*this) += rhs;
}
I have defined the MyString class, and now I want to implement the addition operation. It's horrible for memory leaks to occur, so I've taken care of releasing the dynamically allocated pointers from the destructor.
#include <iostream>
class MyString {
private:
int _size;
char* _str;
public:
MyString() {
_size = 0;
_str = nullptr;
}
MyString(int size, char* str) {
_size = size;
_str = new char[size + 1];
strcpy(_str, str);
}
~MyString() {
delete[] _str;
}
void print() {
std::cout << _str << std::endl;
}
friend MyString operator+(const MyString& lhs, const MyString& rhs);
};
MyString operator+(const MyString& lhs, const MyString& rhs) {
char* temp = new char[lhs._size + rhs._size + 1];
strcpy(temp, lhs._str);
strcat(temp, rhs._str);
MyString ret(lhs._size + rhs._size, temp);
delete[] temp;
return ret;
}
int main() {
MyString first(5, "first");
MyString second(6, "second");
MyString add = first + second;
first.print();
second.print();
add.print();
}
However, if I compile the code and run it, the first.print() and second.print() is printed well, but the add.print() will print the garbage value, and crashes (Debug Assertion Failed!).
Output:
first
second
硼硼硼硼硼硼硼硼?흚 (and creashes :(.. )
If I annotate and run the destructor, it prints well, but a memory leak occurs. Why is this happening? I have looked at several examples of operator overriding, but I have not found an example of this dynamic allocation of pointers.
Any suggestion will be highly appreciated!
MyString operator+(const MyString& lhs, const MyString& rhs) {
char* temp = new char[lhs._size + rhs._size + 1];
strcpy(temp, lhs._str);
strcat(temp, rhs._str);
MyString ret(lhs._size + rhs._size, temp);
delete[] temp;
return ret;
}
At the end of this function 'ret' is destroyed which calls the destructor and deletes the buffer. What is returned is a new instance of MyString that was copied from 'ret', and its buffer points to the same memory location as the original. Since this has been deleted you are now printing out garbage.
To fix this you can add a copy constructor to ensure the buffer is copied:
class MyString {
// Other class details
public:
MyString(const MyString & other) : MyString(other._size, other._str) {}
// Other class details
}
This will ensure the buffer is copied when one MyString is assigned to another MyString.
#include<iostream>
using namespace std;
class Mystring{
private:
int size;
char *str;
public:
friend Mystring operator*(const Mystring &a, const int &d);
friend Mystring operator+(const Mystring &a, const Mystring& b);
friend ostream& operator << (ostream &os, const Mystring a);
friend istream& operator >> (istream &is, const Mystring a);
Mystring (int a, char b) {
this->size = a;
this->str = new char(a);
for (int i = 0; i < a; i++) {
this->str[i] = b;
}
}
~Mystring() {}
};
Mystring operator+(const Mystring &a, const Mystring& b) {
Mystring c(a.size + b.size, { 0 });
for (int i = 0; i < a.size; i++)
{
c.str[i] = a.str[i];
}
for (int i = 0; i < b.size; i++)
{
c.str[a.size + i] = b.str[i];
}
return c;
}
Mystring operator*(const Mystring& a,const int &d){
int z = a.size*d;
Mystring c(z, { 0 });
int k=0;
for (int j = 0; j < d; j++)
{
for (int i = 0; i < a.size; i++)
{
c.str[k+i] = a.str[i];
}
k = a.size + k;
}
return c;
}
ostream& operator << (ostream &os, const Mystring a) {
os << "[";
int i;
for ( i = 0; i < a.size; i++)
{
os << a.str[i];
}
os << "]";
return os;
}
istream& operator >> (istream &is, const Mystring a) {
for (int i = 0; i < a.size; i++)
{
cout << i << "번째 문자 : ";
is >> a.str[i];
}
return is ;
}
int main()
{
int aSize, bSize, iter;
char aInit, bInit;
cout << "문자열A의 크기와 초기문자를 입력: ";
cin >> aSize >> aInit;
Mystring str1(aSize, aInit);
cout << str1 << endl;
cout << "문자열A 입력" << endl;
cin >> str1;
cout << str1 << endl;
cout << "문자열B의 크기와 초기문자를 입력: ";
cin >> bSize >> bInit;
Mystring str2(bSize, bInit);
cout << str2 << endl;
cout << "문자열B 입력" << endl;
cin >> str2;
cout << str2 << endl;
cout << "문자열A와 문자열B 합치기 : ";
Mystring str3 = str1 + str2;
cout << str3 << endl;
cout << "문자열A 반복횟수 입력 : ";
cin >> iter;
Mystring str4 = str1*iter;
cout << str4 << endl;
}
enter code here
why error
~Mystring(){}
I decided to code all assignments from last semesters c++ class over summer in order to better prepare for c++ 3 but I don't understand how to pass through a String class or what steps are even needed in order to concatenate two strings and the display the result in the main cpp file.
In my Main.cpp:
#include <iostream>
using namespace std;
#include "String.h"
int main()
{
String Str1;
String Str2("this is a test");
String Str3(Str2);
String Str4("bruh");
int result;
cout << "Testing Display: " << endl;
Str2.Display();
cout << endl;
cout << "Testing displayLine: " << endl;
Str2.displayLine();
cout << endl;
result = Str2.Compare(Str3);
if (result < 0)
{
Str2.Display();
cout << " comes before " << endl;
Str3.Display();
cout << endl;
}
else
if (result > 0)
{
Str3.Display();
cout << " comes before " << endl;
Str2.Display();
}
else
{
Str3.Display();
cout << " is equal to " << endl;
Str2.Display();
}
cout << endl;
result = Str2.Compare("wxyz");
Str1.Copy(Str3);
cout << "Str1 contains " << Str1.length() <<" characters"<< endl;
cout << "Concatenation: ";
Str2.Concat(Str4);
cout << endl;
return 0;
}
In my String.cpp:
#include <iostream>
using namespace std;
#include <string.h>
#include "String.h"
#pragma warning(disable:4996)
String::String()
{
NumChars = 0;
MaxSlots = 0;
pChar = new char[NumChars+1];
pChar[0] = '\0';
}
String::String(const char Str[])
{
NumChars = strlen(Str);
pChar = new char[NumChars + 1];
strcpy(pChar, Str);
}
String::String(const String & Str)
{
NumChars = Str.NumChars;
pChar = new char[NumChars + 1];
strcpy(pChar, Str.pChar);
}
String::~String()
{
delete[] pChar;
}
int String::Compare(const String & Str) const
{
return strcmp(pChar, Str.pChar); //case sensitive
}
int String::Compare(const char Str[]) const
{
return strcmp(pChar, Str); //case sensitive
}
String& String::Copy(const String & Str)
{
if (this != &Str)
{
if (MaxSlots < Str.NumChars)
{
delete[]pChar;
MaxSlots = Str.NumChars;
pChar = new char[NumChars + 1];
}
else;
NumChars = Str.NumChars;
strcpy(pChar, Str.pChar);
}
else;
return *this;
}
String& String::Copy(const char Str[])
{
delete[] pChar;
NumChars = strlen(Str);
MaxSlots = NumChars;
pChar = new char[MaxSlots + 1];
return *this;
}
String& String::Concat(const String & Str)
{
pTemp = new char[NumChars+1];
strcpy(pTemp, pChar);
strcat(pTemp, Str.pChar);
delete[]pChar;
pChar = pTemp;
return *this;
}
String & String::Concat(const char Str[])
{
return *this;
/*
NumChars = strlen(Str);
MaxSlots = NumChars;
delete[] pChar;
MaxSlots = MaxSlots + NumChars;
NumChars = NumChars + strlen(Str);
pChar = new char[MaxSlots + 1]; */
}
void String::Display() const
{
cout << pChar;
}
void String::displayLine() const
{
cout << pChar;
}
In my String.h:
#ifndef STRING_H
#define STRING_H
class String
{
public:
String(); //default constructor
String(const char[]);
String(const String &); //copy constructor
~String();
int Compare(const String &) const;
int Compare(const char[])const;
String& Copy(const String&);
String& Copy(const char[]);
String& Concat(const String&);
String& Concat(const char[]);
void Display()const;
void displayLine() const;
int length() const;
private:
char * pChar;
char *pTemp;
int NumChars;
int MaxSlots;
};
inline int String::length() const
{
return NumChars;
};
#endif
You expect the length of the concatenated string to be the sum of the length of the two strings. Therefore:
String& String::Concat(const String & Str)
{
pTemp = new char[NumChars + Str.NumChars + 1];
strcpy(pTemp, pChar);
strcat(pTemp, Str.pChar);
delete[]pChar;
pChar = pTemp;
return *this;
}
You can optimize this further by not strcat()-ing but strcpy()-ing twice (with an offset added to pTemp second time), as you already know the string length.
I'm not sure to understand the use of your MaxSlots; it's the size of allocated pChar (minus 1)? If so, there are points in your code where you forget to set/update/use.
And I don't understand what do you mean with "how to pass through a String class", but regarding "what steps are even needed in order to concatenate two strings", you've forgotten to take in count the number of chars already present in the object.
First of all, I suggest to create e Reserve() method; something like [caution: code not tested]
String& String::Reserve (int n)
{
if ( n > MaxSlots )
{
MaxSlots = n;
pTemp = new char[MaxSlots+1];
strcpy(pTemp, pChar);
delete[]pChar;
pChar = pTemp;
}
}
Next, rewrite your Concat() methods in this way
String& String::Concat(const String & Str)
{
NumChars += Str.NumChars;
Reserve(NumChars);
strcat(pChar, Str.pChar);
return *this;
}
String & String::Concat(const char * Str)
{
if ( Str )
{
NumChars += strlen(Str);
Reserve(NumChars);
strcat(pChar, Str);
}
return *this;
}
p.s.: sorry for my bad English
When I try add person to vector it doesn't work + I can't add more than one person. Im pretty new to C++ and I can't figure it out. Sorry for my English :( Thanks for any help/tips. I was searching about it and try a lot of things, but couldnt make it work anyway. What I'm doing wrong or maybe this code is at mess anyway?
class Osoba
{
public:
char *name, *surname, *phone;
Osoba();
Osoba(const char *name, const char *surname, const char *phone);
~Osoba();
};
inline Osoba::Osoba(){};
inline Osoba::Osoba(const char *name, const char *surname, const char *phone)
{
Osoba::name = new char[strlen(name) + 10];
strcpy(Osoba::name, name);
Osoba::surname = new char[strlen(surname) + 1];
strcpy(Osoba::surname, surname);
Osoba::phone = new char[strlen(phone) + 1];
strcpy(Osoba::phone, phone);
}
inline Osoba::~Osoba()
{
delete name;
delete surname;
delete phone;
}
int main()
{
const char *name2, *surname2, *phone2;
vector <Osoba> osoba;
cout << "\n1.-Workers list\n2.-Add person\n3.-Quit";
char odp;
do
{
odp = getch();
switch (odp)
{
case '1':
cout << "\n\n\nList:\n";
for (int i = 0; i < osoba.size(); i++)
{
cout << endl;
cout << "Name: " << osoba[i].name << endl;
cout << "Surname: " << osoba[i].surname << endl;
cout << "Phone: " << osoba[i].phone << endl;
}
break;
case '2':
cout << "\n\nADD PERSON";
cout << "\nName: ";
string name;
cin >> name;
name2 = name.c_str();
cout << "Surname: ";
string surname;
cin >> surname;
surname2 = surname.c_str();
cout << "Phone: ";
string phone;
cin >> phone;
phone2 = phone.c_str();
osoba.push_back(Osoba(name2, surname2, phone2));
break;
}
} while (odp != '3');
return 0;
}
Since you are doing C++, why not doing it the C++ - way
#include <string>
using std::string;
class Osoba
{
public:
Osoba() = default;
Osoba(const string& name, const string& surname, const string& phone);
Osoba(const Osoba&) = default;
Osoba& operator=(const Osoba&) = default;
~Osoba() = default;
const string& Name() const { return name; }
const string& Surname() const { return surname; }
const string& Phone() const { return phone; }
void Name(const string& n) { name =n; }
void Surname(const string& s) { surname =s; }
void Phone(const string& p) { phone =p; }
private:
string name, surname, phone;
};
Osoba::Osoba(const string& name, const string& surname, const string& phone)
: name(name), surname(surname), phone(phone)
{
}
There are few problems:
Define copy constructor as below:
Osoba::Osoba(const Osoba& src) {
if (src.name != NULL) {
name = new char[strlen(src.name) + 1];
strcpy(name, src.name);
}
if (src.surname != NULL) {
surname = new char[strlen(src.surname ) + 1];
strcpy(surname , src.surname );
}
if (src.phone != NULL) {
phone = new char[strlen(src.phone) + 1];
strcpy(phone, src.phone);
}
}
Change constructors as below:
Osoba::Osoba(){
name = (char *) NULL;
surname = (char *) NULL;;
phone = (char *) NULL;
}
};
Osoba::Osoba(const char *name, const char *surname, const char *phone)
{
if (name != NULL) {
this->name = new char[strlen(name) + 1];
strcpy(this->name, name);
}
if (surname != NULL) {
this->surname = new char[strlen(surname ) + 1];
strcpy(this->surname , surname );
}
if (phone != NULL) {
this->phone = new char[strlen(phone) + 1];
strcpy(this->phone, phone);
}
}
Also, assignment operator:
Osoba& Osoba::operatoe = (const Osoba& src) {
if (this == &src)
return *this;
if (src.name != NULL) {
name = new char[strlen(src.name) + 1];
strcpy(name, src.name);
}
if (src.surname != NULL) {
surname = new char[strlen(src.surname ) + 1];
strcpy(surname , src.surname );
}
if (src.phone != NULL) {
phone = new char[strlen(src.phone) + 1];
strcpy(phone, src.phone);
}
return *this;
}
I'm probably missing something obvious here. This is my code (I'm just learning true C++, and I want to get some practice):
#include <iostream>
#include <cstring>
using namespace std;
class String {
private:
char * value;
int len;
friend ostream & operator<<(ostream & os, String s);
public:
String();
String(const char * base);
~String();
String operator+(String s);
String operator*(int n);
int length();
};
String::String() {
this->value = new char[0];
this->len = 0;
}
String::String(const char * base) {
this->value = new char[this->len = strlen(base)];
strcpy(this->value, base);
}
String::~String() {
delete [] this->value;
}
int String::length() {
return this->len;
}
String String::operator+(String s) {
String n;
delete [] n.value;
cout << "Upon entering, I am: \"" << *this << "\"\n";
n.value = new char[this->len + s.len];
for(int i = 0; i < this->len; i++) {
n.value[i] = this->value[i];
}
for(int i = 0; i < s.len; i++) {
n.value[i + this->len] = s.value[i];
}
n.len = this->len + s.len;
cout << "String::operator+(" << *this << ", " << s << ") succeeded with new value = \"" << n << "\"\n";
return n;
}
String String::operator*(int n) {
String s;
delete [] s.value;
s.value = new char[this->len * n];
for(int i = 0; i < this->len * n; i++) {
s.value[i] = this->value[i % this->len];
}
cout << "String::operator* succeeded with new value = \"" << s << "\"\n";
return s;
}
ostream & operator<<(ostream & os, String s) {
return os << s.value;
}
int main() {
String s("Hello, world!");
cout << s << "\nLength = " << s.length() << "\n\n";
cout << (s + String("\n")) * 5;
return 0;
}
And the string initializes and displays correctly, but my output is really strange; it seems that upon entering the operator+, "Hello, world!" suddenly becomes "x%r"?
C:\Users\Ryan\Documents\My Dropbox\C++ Projects>strings
Hello, world!
Length = 13
Upon entering, I am: "x%r"
String::operator+(x%r,
) succeeded with new value = "x%r"
String::operator* succeeded with new value = "╚%r"
─
Try this:
ostream & operator<<(ostream & os, const String& s) {
return os << s.value;
}
otherwise your should define copy constructor for your String class.
You need to provide copy constructor and assignment operator.
There are a lot of problems with your code.
You are managing your own memory. You should avoid doing this if at all possible.
You are consitantly forgetting that strings have a null terminator. In order to accomodate the strin Hello, world! you need a char buffer that is 14 bytes, not 13.
You have a len member variable that does effectively the same thing as the strlen function, except for the inconsistent consideration of #1 above.
Your string class does not have a copy constructor, which results in wild pointers and eventually crashes.
Here is a refactoring of your code that pretty much works.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
class String {
private:
char * value;
// size_t len;
friend ostream & operator<<(ostream & os, String s);
public:
String();
String(const char * base);
String(const String& rhs)
{
value = new char[strlen(rhs.value)+1];
strcpy(value,rhs.value);
}
~String();
String operator+(String s);
String operator*(int n);
size_t length();
};
String::String() {
this->value = new char[0];
}
String::String(const char * base) {
this->value = new char[strlen(base)+1];
strcpy(this->value, base);
}
String::~String() {
delete [] this->value;
}
size_t String::length() {
return strlen(value);
}
String String::operator+(String s) {
String n;
delete [] n.value;
cout << "Upon entering, I am: \"" << *this << "\"\n";
n.value = new char[strlen(value)+strlen(s.value)+1];
for(int i = 0; i < strlen(value); i++) {
n.value[i] = this->value[i];
}
for(int i = 0; i < strlen(s.value); i++) {
n.value[i + strlen(value)] = s.value[i];
}
n.value[strlen(value)+strlen(s.value)] = '\0';
cout << "String::operator+(" << *this << ", " << s << ") succeeded with new value = \"" << n << "\"\n";
return n;
}
String String::operator*(int n) {
String s;
delete [] s.value;
s.value = new char[(strlen(value)*n)+1];
for(int i = 0; i < strlen(value) * n; i++) {
s.value[i] = this->value[i % strlen(value)];
}
s.value[strlen(value)*n] = '\0';
cout << "String::operator* succeeded with new value = \"" << s << "\"\n";
return s;
}
ostream & operator<<(ostream & os, String s) {
return os << s.value;
}
int main() {
String s("Hello, world!");
cout << s << "\nLength = " << s.length() << "\n\n";
cout << (s + String("\n")) * 5;
return 0;
}