Thread: String Class

  1. #1
    Registered User
    Join Date
    Jul 2007
    Posts
    109

    String Class

    Hi,
    I am making a String class that has many overloaded operators. I am positive there are some problems with the overloaded operators that I have already made. There are also some functions that I could not define and need help in defining. Can somebody please look at my code and tell me my errors and how to fix them as well as help me in defining the functions that are not yet defined.

    Code:
    //string.h
    
    #ifndef _String_H
    #define _String_H
    
    #include <iostream>
    #include "strdrv.h"
    using namespace std;
    
    class String
    {
    	friend String operator+(const String& lhs, const String& rhs);
    	friend String operator+(const String& rhs, const char* str);
    	friend String operator+(const char* str, const String& rhs);
    	friend String operator+(const String& rhs, char str);
    	friend String operator+(char str, const String& rhs);
    	friend int operator==(const String& lhs, const String& rhs);
    	friend int operator!=(const String& lhs, const String& rhs);
    	friend int operator< (const String& lhs, const String& rhs);
    	friend int operator<=(const String& lhs, const String& rhs);
    	friend int operator> (const String& lhs, const String& rhs);
    	friend int operator>=(const String& lhs, const String& rhs);
    	friend char* operator+(const String&, int);
    	friend char* operator+(int, const String&);
    	friend ostream& operator<<(ostream&, const String&);
    
    public:
    	String();
    	String(const char* str);
    	String(char * nme);
    	String(int string);
    	String(const String& rhs);
    	String(char, int);
    	~String();
    	void setName(const char* aname);
    	String& operator= (const String& rhs);
    	String& operator= (const char *st);
    	const String& operator+=(const String & st);
    	char& operator[](int i);
    	char& operator[](int i) const;
    	String& operator++();
    	String& operator--();
    	String operator++(int x);
    	String operator--(int x);
    	int getLength()const;
    	String substr(int start, int length);
    	void print();
    
    private:
    	int stringlength;
    	int size;
    	char * name;
    	char *buf;
    
    
    
    };
    
    #endif 
    
    
    // string.cpp
    #define _CRT_SECURE_NO_DEPRECATE 1	
    #include <iostream>
    #include "string.h"
    #include "strdrv.h"
    
    using namespace std;
    
    String::String()
    {
    	stringlength = 0;
    	size = 1;
    	buf = new char[size];
    	buf[0] = '\0';
    }
    
    String::String(const char* str)
    { 
        if (str==NULL)
        {
            stringlength = 0; 
            buf = new char[1];  
            buf[0]='\0';
        }
        else
        {
            stringlength = strlen(str); 
            buf = new char[stringlength+1];
            for(int i=0; i <= stringlength; i++)
                buf[i] = str[i];
        }
    }
    
    String::String(char * nme)
    {
    	name = nme;
    }
    
    String::String(int string)
    {
    	if(string <= 0)
    	{	
    		stringlength = 0;
    		buf = new char[1];
    		buf[0] = '\0';
    	}
    	else
    	{
    		buf = NULL;
    		stringlength = string;
    		buf = new char[stringlength + 1];
    	}
    }
    
    
    
    String::String(const String& rhs)
    {
    	stringlength = rhs.stringlength;
    	buf = new char[stringlength + 1];
    	for (int i=0; i <= stringlength; i++)
    		buf[i] = rhs.buf[i];
    }
    
    String::~String()
    {
    	delete [] buf;
    }
    
    void String::setName(const char* aname)	
    {
    	name = new char[strlen(aname + 1)];		
    	strcpy(name, aname);					
    }
    
    String& String::operator =(const String& rhs)
    {
    	if(this != &rhs)
    	{
    		delete []buf;
    		stringlength = rhs.stringlength;
    		buf = new char[stringlength + 1];
    		for(int i = 1; i <= stringlength; i++)
    			buf[i] = rhs.buf[i];
    	}
    	return *this;
    }
    
    String& String::operator =(const char *st)
    {
    	stringlength = strlen(st);
    	if(size <= stringlength)
    	{
    		delete []buf;
    		buf = new char[stringlength + 1];
    	}
    	strcpy(buf, st);
    	return *this;
    }
    		
    
    char& String::operator [](int i) const 
    {
    	if(i >= 0 && i<= stringlength)
    		cout<< "Out of bounds" << endl;
    	return buf[i];
    }
    
    char& String::operator [](int i)
    {
    	if(i >= 0 && i <= stringlength)
    		cout<< "Out of bounds" << endl;
    	return buf[i];
    }
    
    const String& String::operator +=(const String & str)
    {
    	String copystring(str);
    	int anotherstringlength = getLength() + str.getLength();
    	int previous = getLength();
    	if(anotherstringlength >= size)
    	{
    		size = anotherstringlength + 1;
    		char * secbuf = new char[size];
    		strcpy(secbuf, buf);
    		delete []buf;
    		buf = secbuf;
    	}
    	strcpy(buf + previous, buf);
    	stringlength = anotherstringlength;
    	return *this;
    }
    
    
    String operator +(const String& lhs, const String& rhs)
    {
    	String result(lhs);
    	result += rhs;
    	return result;
    }
    
    String operator +(char str, const String& rhs)
    {
    	String result;
    	result = str;
    	result += rhs;
    	return result;
    }
    
    String operator +(const String& rhs, char str)
    {
    	String result(rhs);
    	result += str;
    	return result;
    }
    
    String String::substr(int start, int length)
    {
    	if(start >= 0 && start < stringlength)
    		cout<< "Start of substring not in string bounds" << endl;
    	if(length >= 0)
    		cout<< "Error: length of substring is negative" << endl;
    	if((start + length) > stringlength)
    		length = stringlength - start;
    	char* stringArray = new char[length + 1];
    	int i;
    	for(i = start; i < (start + length) ; i++)
    		stringArray[i-start] = (*this)[i];
    	stringArray[i - start] = '\0';
    	String temp(stringArray);
    	delete []stringArray;
    	return temp;
    }
    
    
    
    int operator==(const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf)==0;
    }
    
    int operator!= (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) !=0;
    }
    
    int operator< (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) <0;
    }
    
    int operator<= (const String& lhs, const String&rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) <=0;
    }
    
    int operator> (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) >0;
    }
    
    int operator>= (const String& lhs, const String& rhs)
    {
    	return strcmp(lhs.buf, rhs.buf) >=0;
    }
    
    ostream& operator<< (ostream& output, const String& stringoutput)
    {
    	output<< stringoutput.buf;
    	return output;
    }
    
    
    String& String::operator ++()
    {
    	buf[stringlength] = 'X';
    	stringlength++;
    	return *this;
    }
    
    String String::operator ++(int x)
    {
    	String Return("");
    	Return = *this;
    	buf[stringlength] = 'X';
    	stringlength++;
    	return Return;
    }
    
    String& String::operator --()
    {
    	stringlength--;
    	return *this;
    }
    
    String String::operator --(int x)
    {
    	String Return("");
    	Return = *this;
    	stringlength--;
    	return Return;
    }
    
    void String::print()
    {
    	int i;
    	for(i= 0; i<stringlength; i++)
    		printf("%c", buf[i]);
    }
    
    int String::getLength()const
    {
    	return stringlength;
    }

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Do we look like compilers to you? lol...

    Can't you even do us the courtesy of telling us what is wrong with your code and where you're having trouble?

  3. #3
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    There are problems with the += operator specifically this line:

    Code:
    strcpy(buf + previous, buf);

  4. #4
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Thank you, but "problems" are so generic. Learn to be a little more descriptive and not make others do so much of your work.

    Try this:

    Code:
    const String & String::operator +=(const String & str)
    {
    	int newsize = getLength() + str.getLength() + 1; // Size of current + new string + '\0'.
    	char *temp = NULL;
    	if(newsize > size)
    	{
    		temp = new char[newsize];
    		strcpy(temp, buf);
    		delete []buf;
    		buf = temp;
    		size = newsize;  // Accidentally left this out.
    	}
    	strcat(buf, str.buf);
    	stringlength = newsize;
    	return *this;
    }
    Disclaimer: I'm really more of a C programmer, so check it over to make sure I didn't break anything.
    Last edited by MacGyver; 08-01-2007 at 11:09 PM. Reason: Accidentally left out setting var size.

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    String::String(char * nme)
    {
    	name = nme;
    }
    I'm not quite sure what this is for (sharing a pointer? but attempting to delete it anyway later? how can you be sure nme is allocated with new?) but it looks like this constructor leaves the String practically uninitialized.
    Last edited by anon; 08-01-2007 at 10:48 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  6. #6
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    That was the constructor I was unsure about. How do I fix it?

  7. #7
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by MacGyver View Post
    Thank you, but "problems" are so generic. Learn to be a little more descriptive and not make others do so much of your work.

    Try this:

    Code:
    const String & String::operator +=(const String & str)
    {
    	int newsize = getLength() + str.getLength() + 1; // Size of current + new string + '\0'.
    	char *temp = NULL;
    	if(newsize > size)
    	{
    		temp = new char[newsize];
    		strcpy(temp, buf);
    		delete []buf;
    		buf = temp;
    		size = newsize;  // Accidentally left this out.
    	}
    	strcat(buf, str.buf);
    	stringlength = newsize;
    	return *this;
    }
    Disclaimer: I'm really more of a C programmer, so check it over to make sure I didn't break anything.
    The code you suggested gives the runtime error that the heap is corrupted. The problem is with this line:

    Code:
    temp = new char[newsize];

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    That was the constructor I was unsure about. How do I fix it?
    Instead of copying the pointer, do a deep copy of the string, either manually with a loop until the null character, or using strcpy() from <cstring>.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by laserlight View Post
    Instead of copying the pointer, do a deep copy of the string, either manually with a loop until the null character, or using strcpy() from <cstring>.
    so do you just mean:

    strcpy(nme, name);

    ?

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You already have that constructor (for const char*).

    If you have tested with strings constructed with that constructor there is no wonder that the code crashes at first possibility. Unlike Strings constructed with other constructors, it doesn't own the memory, yet doesn't treat it no differently.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #11
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by BKurosawa View Post
    The code you suggested gives the runtime error that the heap is corrupted.
    I believe you're doing something wrong elsewhere and the problem is being manifested here.

    For example, this is the main() I went with and had no visible problems:

    Code:
    int main()
    {
    	String s("Testing123");
    	String s2("456Hello,there");
    	
    	std::cout << "s = \"" << s << "\"" << std::endl;
    	std::cout << "s+=s2 = \"" << (s+=s2) << "\"" << std::endl;
    	
    	std::cin.ignore();
    	
    	return 0;
    }

  12. #12
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by anon View Post
    You already have that constructor (for const char*).

    If you have tested with strings constructed with that constructor there is no wonder that the code crashes at first possibility. Unlike Strings constructed with other constructors, it doesn't own the memory, yet doesn't treat it no differently.
    oh.. then how do I make this constructor:
    String(char)

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> so do you just mean: strcpy(nme, name);
    You have to allocate the right amount of memory first, then use strcpy to copy.

  14. #14
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    How do I define this constructor:

    String(char);

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Do you mean String(char*)? If so, I'm not sure you need it. The String(const char*) should work for both char* and const char*. If you really do mean String(char), then I'm not sure if you need that either. Do you really want to initialize your string with a single character? If you do, then treat it like a string with one character but instead of using strcpy just assign that character to the first index in the array you allocate and add the null as the second.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. String issues
    By The_professor in forum C++ Programming
    Replies: 7
    Last Post: 06-12-2007, 09:11 AM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. class object manipulation
    By guda in forum C++ Programming
    Replies: 2
    Last Post: 10-09-2004, 10:43 AM
  5. Headers that use each other
    By nickname_changed in forum C++ Programming
    Replies: 7
    Last Post: 10-03-2003, 04:25 AM