Hello,
I am a beginning level C++ programmer. I have an assignment in which I need to create my own basic string class. There are several methods that I need to support, such as leftTrim, righttrim, toLowerCase, toUpperCase. I have been able to handle all of those, but I am now trying to code a substring class.
The prototype is defined as substring(int start, int end), the method should return a new string that is a substring of the string object that the mehod is being used against.
The example that I was able to get from my teacher is:
~~~~~~~~~~
//my class is called mystring
//initialize the variable temp
mystring temp (“hello”);
//return the value of substring to temp2, the value of the string would be “hel”
mystring temp2 = temp.substring(0,2);
~~~~~~~~~~~
The problem that I think I am having (I’m not completely sure) is trying to return an object of mystring from the substring method. My thought was that I would need to have an object of type mystring defined within the class mystring. See the class definition below) I would then modify that object to contain the substring and return that object.
First I tried declaring the variable as - mystring m_mystringTemp -, but the compiler complained:
error C2460: 'm_mystringTemp' : uses 'mystring', which is being defined
c:\cis569 _obj_or_prog_with_c++\assn3\mystring.h(19) : see declaration of 'mystring'
I then changed it to a pointer and did not receive this error. But I get a run time error when I execute the program. When I step thru the program, I see that is calling a constructor at the time that it is returning the value from the substring method and that is where the error occurs. But I am not sure why the constructor is being called or what to do next.
The code for the substring method is incomplete, I was just starting when I ran into this issue.
Below I will include the mystring,h file and the mystring.cpp file in case it is needed. I am not looking for someone to write the code, just help me understand what I am missing or doing wrong.
Thanks for any help,
Paul
################################################## ###
Mystring.h
#include <iostream>
using namespace std;
class mystring
{
public:
mystring();
mystring(char* charArray);
mystring(const mystring &string);
virtual ~mystring();
char charAt(int index);
bool concat(mystring string);
mystring substring(int start, int end);
void toLowerCase(void);
void toUpperCase(void);
void trim(void);
void rightTrim(void);
void leftTrim(void);
char *display(void);
private:
char *m_buff; //pointer to a character array
char *m_buffTemp;
int counter1;
int counter2;
mystring *m_mystringTemp;
};
mystring.cpp
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//Default constructor - allocate a new string containing no characters
mystring::mystring()
{
cout << "Inside the mystring() Constructor\n";
m_buff = (char *) malloc( sizeof(0));
m_buff= NULL;
//******************
m_buffTemp = (char *) malloc( sizeof(0));
m_buffTemp = NULL;
//******************
cout << "Leavingthe mystring()\n\n";
}
///////////////////////////////////////////////////////////////////////
//Constructor Two - Convert the array of characters
mystring::mystring(char *charArray)
{
cout << "Inside the mystring(char *charArray) Constructor\n";
//allocate memory
//m_buff = (char *) malloc( sizeof(charArray) +1);
m_buff = (char *) malloc( strlen(charArray) +1);
//copy charArray into m_buff variable
strcpy(m_buff,charArray);
//add the NULL value on end
m_buff[strlen(m_buff)] = '\0';
//******************
m_buffTemp = (char *) malloc( sizeof(0));
m_buffTemp = NULL;
//******************
cout << "m_buff =" << m_buff << endl;
cout << "Leaving mystring(char *charArray) constructor\n\n";
}
///////////////////////////////////////////////////////////////////////
//Constructor Four - Allocate a new string that contains the same sequence of characters
// as the string argument
//Question -
mystring::mystring(const mystring &string)
{
cout << "Inside the mystring(mystring string) Constructor\n";
//allocate memory
m_buff = (char *) malloc( strlen(string.m_buff) +1);
//copy string char* data into this new string object
strcpy(m_buff, string.m_buff);
//******************
m_buffTemp = (char *) malloc( sizeof(0));
m_buffTemp = NULL;
//******************
cout << "Leaving mystring(const mystring &string) constructor\n\n";
}
////////////////////////////////////////////////////////////////////////
// Destructor - Destructor - Destructor
mystring::~mystring()
{
if (m_buff !=NULL)
delete[]m_buff;
}
////////////////////////////////////////////////////////////////////////
// charAt -- charAt -- charAt
// Returns the character at the specified index
// Return -1 if the index is beyond the length of string or the string is NULL
char mystring::charAt(int index)
{
//if the string is empty return to calling method
if( m_buff == NULL )
{
return(-1);
}
cout<< "In charAt ";
cout<< "Buff -" << m_buff << "-" <<endl;
if(index > strlen(m_buff) || index < 0)
return(-1);
else
return(m_buff[index]);
}
//////////////////////////////////////////////////////////////////////////
// trim -- trim - trim
// Removes white space from both ends of this string
void mystring::trim(void)
{
cout << "Inside trim\n";
//if the string is empty return to calling method
if( m_buff == NULL )
{
return;
}
counter1=0;
counter2=strlen(m_buff);
//allocate memory for temporary buffer
m_buffTemp = (char *) malloc( strlen(m_buff) +1);
//skip all blanks at beginning and get index value
while(m_buff[counter1]==' ')
{
counter1++;
}
cout << "Counter 1 = " << counter1 << endl;
//skip all blanks at end and get index value
while(m_buff[counter2--]==' ')
{
counter2--;
}
cout << "Counter 2 = "<< counter2 << endl;
//copy the trimmed text to a temporary string and add NULL
strncpy(m_buffTemp,&m_buff[counter1],counter2 - counter1);
m_buffTemp[counter2 - counter1] = '\0';
cout << "Trimmed text = -" << m_buffTemp << "-"<<endl;
//copy the temporary string back over original
strcpy(m_buff, m_buffTemp);
cout << "Original text now trimmed -" << m_buff << "-" <<endl;
}
//////////////////////////////////////////////////////////////////////////
// rightTrim -- rightTrim - rightTrim
// Removes white space from right end of this string
void mystring::rightTrim(void)
{
//if the string is empty return to calling method
if( m_buff == NULL )
{
return;
}
cout << "Inside rightTrim - Text -" << m_buff << "-" << "\n";
counter1=0;
counter2=strlen(m_buff);
//allocate memory for temporary buffer
m_buffTemp = (char *) malloc( strlen(m_buff) +1);
//skip all blanks at end and get index value
while(m_buff[counter2--]==' ')
{
counter2--;
}
cout << "Counter 2 = "<< counter2 << endl;
//copy the trimmed text to a temporary string and add NULL
strncpy(m_buffTemp,&m_buff[counter1],counter2 - counter1);
m_buffTemp[counter2 - counter1] = '\0';
cout << "RightTrimmed text = -"<< m_buffTemp << "-" << endl;
//copy the temporary string back over original
strcpy(m_buff, m_buffTemp);
cout << "Original text now RightTrimmed -" << m_buff << "-" <<endl;
}
//////////////////////////////////////////////////////////////////////////
// leftTrim -- leftTrim - leftTrim
// Removes white space from left end of this string
void mystring::leftTrim(void)
{
//if the string is empty return to calling method
if( m_buff == NULL )
{
return;
}
cout << "Inside leftTrim - Text -" << m_buff << "-" << "\n";
counter1=0;
counter2=strlen(m_buff);
//allocate memory for temporary buffer
m_buffTemp = (char *) malloc( strlen(m_buff) +1);
//skip all blanks at beginning and get index value
while(m_buff[counter1]==' ')
{
counter1++;
}
cout << "Counter 1 = " << counter1 << endl;
//copy the trimmed text to a temporary string and add NULL
strncpy(m_buffTemp,&m_buff[counter1],counter2 - counter1);
m_buffTemp[counter2 - counter1] = '\0';
cout << "LeftTrimmed text = -" << m_buffTemp << "-"<<endl;
//copy the temporary string back over original
strcpy(m_buff, m_buffTemp);
cout << "Original text now LeftTrimmed -" << m_buff << "-" <<endl;
}
//////////////////////////////////////////////////////////////////////////
// toLowerCase -- toLowerCase -- toLowerCase
// Converts this string to lowercase
void mystring::toLowerCase(void)
{
cout << "Inside toLowerCase\n";
//if the string is empty return to calling method
if( m_buff == NULL )
{
return;
}
counter1=strlen(m_buff);
counter2 = 0;
//convert all to lowercase
while(m_buff[counter2]!='\0' || counter2 < counter1)
{
m_buff[counter2]=tolower(m_buff[counter2]);
counter2++;
}
cout << "Original text now tolower -" << m_buff << "-" <<endl;
}
//////////////////////////////////////////////////////////////////////////
// toUpperCase -- toUpperCase -- toUpperCase
// Converts this string to uppercase
void mystring::toUpperCase(void)
{
cout << "Inside toUpperCase\n";
//if the string is empty return to calling method
if( m_buff == NULL )
{
return;
}
counter1=strlen(m_buff);
counter2 = 0;
//convert all to uppercase
while(m_buff[counter2]!='\0' || counter2 < counter1)
{
m_buff[counter2]=toupper(m_buff[counter2]);
counter2++;
}
cout << "Original text now toupper -" << m_buff << "-" <<endl;
}
//////////////////////////////////////////////////////////////////////////
// concat -- concat - concat
// Concatenates the specified string to the end of this string
// NULL - if the object string m_buff is NULL, it will have memory allocated
// for the size of the concated string and then that concated string
// string.m_buff will be copied over. The first check is if both
// strings are NULL, if so then return a 0 value.
// Return a value of 1 if successfull
// QUESTION - Code for an empty string - test it out
bool mystring::concat(mystring string)
{
cout << "Inside concat\n";
//Test if string to concat is NULL
if(string.m_buff == NULL)
return(0);
//Test if the m_buff string is NULL, if so allocate mem and copy over the
// string to concat and return a true value
if(m_buff == NULL)
{
m_buff = (char *) malloc( strlen(string.m_buff) +1);
strcpy(m_buff, string.m_buff);
return(1);
}
//**Logic below will get used if neither string is NULL
//allocate memory for temporary buffer that is enough for both strings
m_buffTemp = (char *) malloc( strlen(m_buff) + strlen(string.m_buff) +1);
//copy over this objects string and then concat the other string into temp
strcpy(m_buffTemp, m_buff);
strcat(m_buffTemp, string.m_buff);
cout << "The concat string in buffTemp -" <<m_buffTemp <<"-\n";
//delete the m_buff, re-allocate mem and copy the temporary back over it
free(m_buff);
m_buff = (char *) malloc( strlen(m_buffTemp) +1);
strcpy(m_buff, m_buffTemp);
cout << "The concat string in m_buff in concat -" <<m_buffTemp <<"-\n";
//delete the m_buffTemp and set to NULL, not sure if need to set to NULL
// need to see if free does this for you.
free(m_buffTemp);
m_buffTemp = NULL;
return(1);
}
//////////////////////////////////////////////////////////////////////////
// subString -- subString -- subString
// Returns a new string that is a substring of thsi string (start at
// int1 and end at int2
// QUESTION - Code for an empty string - test it out
mystring mystring::substring(int start, int end)
{
//check that the start value is valid, if not then leave method
if(start < 0 || start > strlen(m_buff))
return(*m_mystringTemp);
return(*m_mystringTemp);
//check that end value is valid, if not then reassign a value that
// is equal to the length of the string that this method is acting on
// This will allow the method to continue without error
//copy the substring value into the temporary string class and then return it
}
//////////////////////////////////////////////////////////////////////////
// display
// Displays the m_buff data
char *mystring::display(void)
{
if(m_buff == NULL)
return (NULL);
else
return(m_buff);
}