-
May 13th, 2009, 10:20 AM
#1
operator overloading
hello everyone!
I met some problems with pointer here:
Code:
////////////////////////code//////////////////////////////////
//class's declaration
//file FunnyString.h
#ifndef FUNNYSTRING_H
#define FUNNYSTRING_H
#include <cassert>
#include <iostream>
using namespace std;
class FunnyString
{
friend istream &operator>>( istream&, FunnyString& );
friend ostream &operator<<( ostream&, FunnyString&) ;
public:
FunnyString(char* = 0);
~FunnyString()
{
delete [] data;
}
FunnyString( FunnyString& ); //copy constructor.
FunnyString operator+( FunnyString& );
FunnyString & operator=( FunnyString& ); //assigment operator.
private:
void SetString( char*);
char GetOneCharacter( const int & index )
{
assert( ( index < len ) && index>= 0 );
return data[index];
}
void CutBeginCharacter();
void SelfCutEndCharacter();
char* data;
int len;
};
#endif
///////////////////////////code///////////////////////////////////////////////
-----------------------------code--------------------------------------------
//FunnyString class's definition.
//FunnyString.cpp file.
#include "FunnyString.h"
#include <iostream>
#include <cassert>
using namespace std;
FunnyString::FunnyString(char *s )
:len(strlen(s)+1)
{
SetString(s);
}
FunnyString::FunnyString( FunnyString & s)
{
SetString(s.data);
}
FunnyString& FunnyString::operator= ( FunnyString& s)
{
if ( &s != this ) //prevent self assigment.
{
if ( s.len != len )
{
delete [] data;
SetString(s.data);
}
}
else cout << "Self assigment\n";
return *this;
}
FunnyString FunnyString::operator+( FunnyString & s)
{
FunnyString fString1(data);
FunnyString fString2(s.data);
FunnyString &tmp = fString1;
while ( fString1.data[len-2] == fString2.data[0] )
{
fString1.SelfCutEndCharacter();
fString2.CutBeginCharacter();
}
strcat(fString1.data,fString2.data);
return tmp;
}
ostream& operator<< (ostream& output,FunnyString& s )
{
output << s.data;
return output;
}
istream& operator>> (istream& input, FunnyString& s)
{
char tmp[100];
input >> tmp;
s.data = tmp;
return input;
}
void FunnyString::SetString( char* s )
{
if ( 0 != s )
{
len = strlen(s)+1;
data = new char[len];
strcpy(data,s);
}
else
{
len = 1;
data = 0;
}
}
void FunnyString::CutBeginCharacter()
{
char* tmp = new char[len-1];
for ( int i = 0; i < len - 2; i++)
{
tmp[i]=data[i+1];
}
tmp[len-2] = 0;
delete [] data;
SetString(tmp);
delete [] tmp;
}
void FunnyString::SelfCutEndCharacter()
{
char* tmp = new char[len-1];
strncpy(tmp,data,len-2);
tmp[len-2] = 0;
delete [] data;
SetString(tmp);
delete [] tmp; //release tmp;
}
-----------------------------code-------------------------------------
The operator+ function met a pointer problem(I don't know why, I just want this function does not change the data, so I created 2 new FunnyString objects and handle them. This function return a reference of FunnyString!!!- maybe when the function end, all the data will be destruct by destructor which released the char* data, so function can not return it).But I can't prevent it. this is a operator overloading, it can not contain more parameter,so how can I return in this function?
Last edited by HanneSThEGreaT; May 13th, 2009 at 10:44 AM.
-
May 13th, 2009, 10:33 AM
#2
Re: operator overloading
I doubt you´ll get any help without properly formatting your code. Code tags are [ code ] and [ /code ], all without spaces.
- Guido
-
May 13th, 2009, 10:46 AM
#3
Re: operator overloading
What precisely is the problem, we don't know what you what you want to do, where the error occurs ¿ Please explain properly.
-
May 13th, 2009, 11:16 AM
#4
Re: operator overloading
Originally Posted by dakotabk
hello everyone!
I met some problems with pointer here:
Code:
////////////////////////code//////////////////////////////////
FunnyString FunnyString::operator+( FunnyString & s)
{
FunnyString fString1(data);
FunnyString fString2(s.data);
FunnyString &tmp = fString1;
while ( fString1.data[len-2] == fString2.data[0] )
{
fString1.SelfCutEndCharacter();
fString2.CutBeginCharacter();
}
strcat(fString1.data,fString2.data);
return tmp;
}
-----------------------------code-------------------------------------
The operator+ function met a pointer problem(I don't know why, I just want this function does not change the data, so I created 2 new FunnyString objects and handle them. This function return a reference of FunnyString!!!- maybe when the function end, all the data will be destruct by destructor which released the char* data, so function can not return it).But I can't prevent it. this is a operator overloading, it can not contain more parameter,so how can I return in this function?
First, it is no need to use two FunnyString objects.
Second, fString1 is a local variable so it will be destroyed when the method done. When fString1 is destroyed , its destructor is called. It mean, its data is deleted.
Moreover, temp is a reference to fString1 , so data of temp is deleted too.
solution :
Code:
FunnyString FunnyString::operator+( FunnyString & s)
{
char* sResult = new char[s.len + this->len];
FunnyString fsResult;
strcpy(sResult, this->data);
strcpy(&sResult[this->len], s.data);
fsResult.data = sResult;
return fsResult;
}
-
May 13th, 2009, 02:18 PM
#5
Re: operator overloading
You really need to work on const correctness in that code.
What I would probably do is implement an insert function, then implement operator + in terms of the insert function.
It would look something like (warning, untested code):
Code:
FunnyString& Insert(size_t pos, const FunnyString& str)
{
assert(pos < this->len);
char* temp = new char[this->len + str.len];
strncpy(temp, this->data, pos - 1);
strcat(temp, str.data);
strcat(temp, this->data + pos);
delete [] this->data;
this->data = temp;
this->len += str.len;
return *this;
}
FunnyString operator +(const FunnyString& str) const
{
return FunnyString(*this).Insert(this->len - 1, str);
}
Last edited by Speedo; May 13th, 2009 at 02:20 PM.
-
May 13th, 2009, 11:48 PM
#6
Re: operator overloading
Originally Posted by ptaminh
First, it is no need to use two FunnyString objects.
Second, fString1 is a local variable so it will be destroyed when the method done. When fString1 is destroyed , its destructor is called. It mean, its data is deleted.
Moreover, temp is a reference to fString1 , so data of temp is deleted too.
solution :
Code:
FunnyString FunnyString::operator+( FunnyString & s)
{
char* sResult = new char[s.len + this->len];
FunnyString fsResult;
strcpy(sResult, this->data);
strcpy(&sResult[this->len], s.data);
fsResult.data = sResult;
return fsResult;
}
I understood what you mean. But my problem is the operator+ can not change the objects itself, so I use 2 new object to handle. And the function returns a reference of FunnyString object ( FunnyString& FunnyString:perator+() ) (sorry).
When the function ends, destructor calls delete[], so all data is destroyed....So this function seems to can not return an object!!!!?
-
May 14th, 2009, 12:44 AM
#7
Re: operator overloading
Originally Posted by dakotabk
I understood what you mean. But my problem is the operator+ can not change the objects itself, so I use 2 new object to handle. And the function returns a reference of FunnyString object ( FunnyString& FunnyString: perator+() ) (sorry).
When the function ends, destructor calls delete[], so all data is destroyed....So this function seems to can not return an object!!!!?
It can return an object because FunnyString already have copy constructor.
The error is here
Code:
FunnyString FunnyString::operator+( FunnyString & s)
{
char* sResult = new char[s.len + this->len - 1];
FunnyString fsResult;
strcpy(sResult, this->data);
strcpy(&sResult[this->len], s.data); // Error is here
strcpy(&sResult[this->len - 1], s.data); ; // fixed
fsResult.data = sResult;
return fsResult;
}
Because you assign len = strlen(...) + 1. It should be strlen(...).
when you fixed the method is ok.
Last edited by ptaminh; May 14th, 2009 at 01:03 AM.
-
May 14th, 2009, 04:53 AM
#8
Re: operator overloading
You have a constructor with a default parameter to an invalid value. If someone constructs a FunnyString with its default constructor it will cause undefined behaviour (probably access violation / segmentation fault on most common systems).
-
May 20th, 2009, 03:07 AM
#9
Re: operator overloading
You're right. When I create an object with default constructor. eg: FunnyString a; this is an error. But I dont know how to solve it? ( I just want the default constructor will create a NULL string ).
-
May 20th, 2009, 03:27 AM
#10
Re: operator overloading
Set char* data; to valid string.
Thanks for your help.
-
May 20th, 2009, 03:38 AM
#11
Re: operator overloading
Originally Posted by dakotabk
I just want the default constructor will create a NULL string
Instead of declaring:
Code:
FunnyString(char* = 0);
Declare:
Code:
FunnyString(const char* s = "");
So, now the default constructor's call of strlen(s) will work correctly. With this in place, it looks like you should tweak the SetString member function.
By the way, the jargon differs depending on what you are talking about, but in C and C++ "empty string" or "zero length string" would be a better term than "null string" since null is often used to refer to a null pointer constant or a null character.
-
May 20th, 2009, 04:47 AM
#12
Re: operator overloading
I still have problems here. So, I post it all again.
The problem is: FunnyString class overload the + operator. The operator+ works like that
FunnyString s1("123aa");
FunnyString s2("aa456");
//s1+s2 = "123456"; (the two "aa" was cut).
This class also overload some operators, so the s1 and s2 can not be changed ( in order to use later ).
I did it like that:
Code:
#ifndef FUNNYSTRING_H
#define FUNNYSTRING_H
#include <cassert>
#include <iostream>
using namespace std;
class FunnyString
{
private:
void SetString( const char*);
char* data;
int len;
public:
FunnyString(const char* = "");
~FunnyString()
{
delete [] data;
}
FunnyString( const FunnyString& ); //copy constructor.
FunnyString operator+(const FunnyString& );
}
Code:
//FunnyString class's definition.
#include "FunnyString.h"
#include <iostream>
#include <cassert>
#include <cstring>
using namespace std;
FunnyString::FunnyString(const char *s = )
{
SetString(s);
}
FunnyString::FunnyString( const FunnyString & s)
{
SetString(s.data);
}
FunnyString FunnyString::operator= ( const FunnyString& s)
{
if ( &s != this ) //prevent self assigment.
{
if ( s.len != len )
{
delete [ ] data;
SetString(s.data);
}
}
else cout << "Self assigment\n";
return *this;
}
FunnyString FunnyString::operator+( const FunnyString & s)
{
int i = 1;
int j = 0;
int count = 0;
while ( data[len-i] == s.data[j] )
{
++i;
++j;
++count;
} //for example: if "abcdhg" + "ghag", the count will get 2.
char* tmp = new char[ len + s.len - 2*count];
strncpy(tmp, data, len - count);
int k = 0;
for ( int i = count; i <= s.len ; ++i )
{
tmp[len - count + k] = s.data[i];
++k;
}
FunnyString result;
result = tmp;
delete [] tmp;
return result;
}
void FunnyString::SetString( const char* s )
{
if ( 0 != s )
{
len = strlen(s);
data = new char[len+1];
strcpy(data,s);
}
else
{
len = 0;
data = 0;
}
}
The problem is: in operator+(), delete [] tmp; // VC++ 2008 compiler error: "CRT detected that the application wrote to the memory after end of heap buffer".
????
thanks.
-
May 20th, 2009, 04:59 AM
#13
Re: operator overloading
Problem of pointing it to "" is that your destructor is now trying to illegally delete it. Before when it was NULL it was ok to call delete on it, but you cannot call delete on the pointer here.
You might solve the problem by having a flag. If it is non-empty then delete it. If it is empty then do not delete it. Ensure in your regular constructor that whenever the string passed in is an empty string it will set the flag. You also need to check this in assignment.
Writing a well-written string class is much harder than it seems. The "standard library" does not even have a formal implementation, it just has a "pattern", i.e. how a string must behave, and it is up to the writers to implement this.
operator= must return a reference. It is actually best implemented to do the following:
- Separate implementations that take const char * and const string &
- Check if the string will fit into the existing buffer and if so just copy it in.
- If not, use (copy) constructor and swap rather than reallocate.
The reason for having separate implementations for const char * and const string & is because if you use const string & all the time you will get implicit conversion which means you will often make more copies of the buffer than is necessary.
-
May 20th, 2009, 05:02 AM
#14
Re: operator overloading
What is operator+ supposed to do? Why work with a temporary char* when you can work with a temporary FunnyString that is returned? Have you considered implementing operator+=, then possibly implementing operator+ by using operator+=?
EDIT:
Originally Posted by NMTop40
Problem of pointing it to "" is that your destructor is now trying to illegally delete it. Before when it was NULL it was ok to call delete on it, but you cannot call delete on the pointer here.
Sounds possible, but I cannot find where dakotabk made the mistake of setting the data member variable to anything other than the result of new[] or a null pointer constant.
Last edited by laserlight; May 20th, 2009 at 05:08 AM.
-
May 20th, 2009, 09:28 AM
#15
Re: operator overloading
because there are also some operators (-,*,...), so it's not allow to change the FunnyString itself (There are only 2 FunnyString objects to implement, so if you change them, other operators can not begin correctly).
The problem is, when an object contains pointer and destructor also ( destruct this pointer ), you can not return this object , don't you?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|