Re: Code Help
* aaronWbryant@gmail.com:
yes I see that now, I have just started started using my debugger and
it crashes when fname = "Bob"; After that statement Bob does get
stored in fname but it crashes.
Here is the updated functions.cpp
#include "MyString.h"
#include <iostream>
#include <cstdlib>
using namespace std;
MyString :: MyString()
{
size = 0;
capacity = size + 1;
data = new char[capacity];
data[0] = '\0';
}
MyString :: MyString(char * s)
{
size = strlen(s);
capacity = size + 1;
data = new char[capacity];
while (size >= capacity)
{
grow();
}
This loop body will never execute.
strcpy(data, s);
data[size + 1] = '\0';
}
MyString :: MyString (const MyString& s)
{
size = s.size;
capacity = size + 1;
data = new char[capacity];
while (size >= capacity)
{
grow();
}
This loop body will never execute.
strcpy(data, s.data);
data[size] = '\0';
}
MyString :: ~MyString()
{
delete []data;
}
MyString MyString :: operator =(const MyString& s)
Uhuh -- that result type should be a reference.
{
delete [] data;
size = s.size;
capacity = size + 1;
data = new char[capacity];
If this throws you're screwed, having already changed size and capacity.
while (size >= capacity)
{
grow();
}
This loop body will never execute.
strcpy(data, s.data);
data[size + 1] = '\0';
return *this;
}
The default way to implement operator= is
void MyString::swap( MyString& other ) throw()
{
std::swap( size, other.size );
std::swap( capacity, other.capacity );
std::swap( data, other.data );
}
MyString& MyString::operator=( MyString other )
{
swap( other ); return *this;
}
MyString& MyString :: append (const MyString& s)
{
size += s.size;
while(size >= capacity)
{
grow();
}
strcat(data, s.data);
data[size + 1] = '\0';
return *this;
}
MyString& MyString :: erase()
{
size = 0;
data[0] = '\0';
return *this;
}
MyString MyString :: operator + (const MyString& s) const
{
char *addition;
addition = new char[strlen(data) + strlen(s.data)];
strcpy(addition, strcat(data, s.data));
Uh oh.
addition[size] = '\0';
return addition;
}
Consider
MyString MyString::operator+( MyString const& s ) const
{
MyString result( *this );
result.append( s );
return result;
}
Since it's much simpler, fixes that bug.
Also, consider making that a freestanding function, in order to support
"blah blah" + someMyString
bool MyString :: operator == (const MyString& s)
{
if (strcmp(data, s.data) == 0)
{
return true;
}
else
{
return false;
}
}
Consider
bool MyString::operator==( MyString const& s ) const
{
return (strcmp( data, s.data ) == 0);
}
Note the essential 'const'.
You want to be able to compare const strings and rvalue strings, don't you?
Also, see above comment about operator+.
bool MyString :: operator < (const MyString& s)
{
if (strcmp(data, s.data) < 0)
{
return true;
}
else
{
return false;
}
}
See above.
bool MyString :: operator > (const MyString& s)
{
if (strcmp(data , s.data) > 0)
{
return true;
}
else
{
return false;
}
}
See above.
bool MyString :: operator <= (const MyString& s)
{
if (strcmp(data, s.data) <= 0)
{
return true;
}
else
{
return false;
}
}
See above.
bool MyString :: operator >= (const MyString& s)
{
if (strcmp(data, s.data) >= 0)
{
return true;
}
else
{
return false;
}
}
See above.
bool MyString :: operator != (const MyString& s)
{
if (!strcmp(data, s.data))
{
return true;
}
else
{
return false;
}
}
See above.
void MyString :: operator += (const MyString& s)
{
size += s.size;
capacity = size + 1;
while(size >= capacity)
{
grow();
}
strcat(data, s.data);
data[size] = '\0';
}
See above.
char& MyString :: operator [] (int n)
{
return data[n];
}
Would be nice with a checking 'at' too.
But more important, don't forget a const version.
You want to be able to index const and rvalue strings, don't you?
void MyString :: getline (istream& in)
{
size = 0;
char c;
in.get(c);
while(c != '\n' && in)
{
data[size] = c;
size++;
if (size >= capacity)
{
grow();
}
in.get(c);
}
data[size] = '\0';
}
Design: i/o has no business being in this class!
void MyString :: grow()
{
char *temp;
temp = data;
capacity *= 2;
data = new char[capacity];
strcpy(data, temp);
data[size] = '\0';
delete [] temp;
}
If you had a constructor taking a capacity, you could do
void MyString::grow()
{
(MyString( 2*capacity ) = *this).swap( *this );
}
int MyString :: length () const
{
return size;
}
ostream& operator<< (ostream& out, MyString& m)
{
out << m.data << endl;
return out;
}
Design: i/o has no business being in this class!
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?