#include<iostream>
#include<cstring>
#include<utility>
class String {
// think about the private data members...
char* input;
int length;
public:
// provide definitions of following functions
String() {
input = NULL;
length = 0;
}
// default constructor
String(const char* str) {
int size = strlen(str);
char* string = new char[size];
for (int i = 0; i < size; i++) {
string[i] = str[i];
}
input = string;
length = size;
}
// initializes the string with constant c-string
String(const String& str) {
input = str.input;
length = str.length;
}
// copy constructor to initialize the string from the existing string
String(int x) {
length = x;
input = new char[length];
} // initializes a string of predefined size
char& operator[](int i) {
return *(input + i);
}
// returns the character at index [x]
const char operator[](int i) const {
return *(input + i);
}
// Assignment Operators
void swap(String& other)
{
std::swap(input, other.input);
std::swap(length, other.length);
}
String& operator=(char ch)
{
String newstr(1);
newstr[0] = ch;
newstr.swap(*this);
return *this;
}
String& operator=(const char* str)
{
String(str).swap(*this);
return *this;
}
String& operator=(const String& str)
{
if (this != &str)
String(str).swap(*this);
return *this;
}
String& operator=(String&& str)
{
String(std::move(str)).swap(*this);
return *this;
}
String& operator-(const String& substr) //remove the substr from the string
{
char* fd;
int p = substr.length;
fd = strstr(input, substr.input);
if (fd)
{
int newsize = length - p;
String newstr(newsize);
int n = fd - input;
for (int i = 0; i < n; i++)
newstr.input[i] = input[i];
int m = length - p - n;
for (int i = n; i <= n + m; i++)
newstr.input[i] = input[i + p];
}
return *this;
}
String& operator-(const string& substr) // remove the substr from the string
{
char* fd;
int p = substr.size();
fd = strstr(input, substr.c_str());
if (fd)
{
int newsize = length - p;
String newstr(newsize);
int n = fd - input;
for (int i = 0; i < n; i++)
newstr.input[i] = input[i];
int m = length - p - n;
for (int i = n; i <= n + m; i++)
newstr.input[i] = input[i + p];
delete[]input;
length = newsize;
input = newstr.input;
}
return *this;
}
int main()
{
String s1("ababacc");
String s2("aba");
String string2("cc");;
s2 = s1 - s2;
cout<< s2[0];
cout<< s2[1];
cout<<s2[2];
s2 = s2 - string2;
cout<< s2[0];
cout<< s2[1];
}
I have overloaded the minus operator two times i.e String& operator-(const String& substr) and String& operator-(const string& substr). The cout statements in main functions are not giving the actual output. cout<<s2[0] is supposed to give 'b' in output. cout<< s2[1]; is supposed to give 'a' in output and cout<<s2[2] is supposed to give 'c' in output. But when I run this code I am not getting these actual values. What am I doing wrong?
I would like to make a CMyString class. It represents an object with contains char array. I need to overload opereators to be able to sum these objects. Here is this class
CMyString::CMyString()
{
i_length = 0;
n_string = new char[1];
n_string[0] = '\0';
}
CMyString::CMyString(const char *cChar)
{
i_length = iSourceLength(cChar);
n_string = new char[i_length];
for (int ii = 0; ii < i_length; ii++)
n_string[ii] = cChar[ii];
}
CMyString::CMyString(const CMyString &pcOther)
{
i_length = pcOther.i_length;
n_string = new char[i_length];
for (int ii = 0; ii < i_length; ii++)
n_string[ii] = pcOther.n_string[ii];
}
void CMyString::vCopyFrom(const CMyString &pcOther)
{
for (int ii = 0; ii < i_length; ii++)
n_string[ii] = pcOther.n_string[ii];
}
bool CMyString::bResize(int newSize)
{
if (newSize <= 0)
return false;
delete(this->n_string);
this->n_string = new char[newSize];
i_length = newSize;
return true;
}
//bool CMyString::bResize(int newSize)
int CMyString::iSourceLength(const char *cChar)
{
int i_source_length = 0;
while (cChar[i_source_length] != '\0')
i_source_length++;
return i_source_length;
}
//int CMyString::iSourceLength(const char *cChar)
CMyString& CMyString:: operator= (const CMyString& pcOther)
{
if (this != &pcOther) // guard against a = a;
{
delete[] n_string; // release old memory & then allocate new memory
i_length = pcOther.i_length;
n_string = new char[i_length];
vCopyFrom(pcOther);
}
return *this; // return a reference to itself to allow a = b = c;
}
//CMyString& CMyString:: operator= (const CMyString& pcOther)
void CMyString:: operator= (const char *cChar)
{
if (i_length != 0)
delete[] n_string;
i_length = iSourceLength(cChar); // count the length of init value
n_string = new char[i_length]; // allocate storage
for (int ii = 0; ii < i_length; ii++) // copy init value into storage
n_string[ii] = cChar[ii];
}
//void CMyString:: operator= (const char *cChar)
CMyString& CMyString:: operator+ (const CMyString& pcOther)
{
CMyString *c_res = new CMyString;
if (i_length == 0 && pcOther.i_length == 0)
{
c_res->i_length = 0;
c_res->n_string = NULL;
}
c_res->i_length = i_length + pcOther.i_length;
c_res->n_string = new char[c_res->i_length];
int ii;
for (ii = 0; ii < i_length; ii++)
c_res->n_string[ii] = n_string[ii];
for (int ij = 0; ij < pcOther.i_length; ij++, ii++)
c_res->n_string[ii] = pcOther.n_string[ij];
return *c_res;
}
CMyString::operator char*()
{
return n_string;
}
//CMyString& CMyString:: operator+ (const CMyString& pcOther)
CMyString::operator char*() const
{
return n_string;
}
What should i do to be able to write c_str = "smth" + c_str?? Compiler underlines me this plus. No operator "+" matches this operands. Operands types are: const char[4] and CMyString?
For more information you can visit this website.
class CMyString
{
private:
string str;
public:
CMyString(string _str) { str = _str; }
friend CMyString operator+(string value, CMyString Str);
string GetStr() {return str;};
};
CMyString operator+(string value, CMyString Str)
{
return CMyString(value + Str.str);
}
int main()
{
CMyString test("Test");
test = "smth" + test;
cout << test.GetStr();
return 0;
}
Memory Management : character arrays and = operator
Q. In terms of Memory Management, What error would you have with the following code?
class String
{
public:
String(const char right[]);
String& operator= (const String& right);
int length() const;
private:
char* buffer;
int len;
};
int String::length() const {return len;}
String::String(const char right[])
{
len = 0;
while (right[len] != '\0')
len++;
buffer = new char[len+1];
for (int i = 0; i < len; i++)
buffer[i] = right[i];
buffer[len] = '\0';
}
String& String::operator= (const String& right)
{
int n = right.length();
for (int i = 0; i <= n; i++)
buffer[i] = right.buffer[i];
return *this;
}
Answer.
I have no clue... Could you help me?
The array size seems okay... new operator...
is it because of the dangling pointer because there is no delete operator?
Or rule of three?
I would appreciate your help!
Please let me know.
Thanks,
Is all I can suggest
~String()
{
if(buffer)
delete [] buffer;
len = 0;
}
String(int length)
{
buffer = new char[length];
len = length;
}
String String::operator = (String rhs)
{
if(this != &rhs)
{
delete [] buffer;
buffer = new char[strlen(rhs.m_str) + 1];
strcpy(buffer, rhs.buffer);
}
return *this;
}
If you don't have a destructor, every time you new the buffer in your class, it will be a memory leak because your code has no way of getting rid of it.
Here are the full codes that I am using to implement this program. Everything seems to compile and run, but once it runs my find method, the program seems to stop and does not execute the last line stating the matching substring within the main.cpp file. Any help is definitely appreciated!
.h file:
#include <iostream>
using namespace std;
class MyString
{
public:
MyString();
MyString(const char *message);
MyString(const MyString &source);
~MyString();
const void Print() const;
const int Length() const;
MyString& operator()(const int index, const char b);
char& operator()(const int i);
MyString& operator=(const MyString& rhs);
bool operator==(const MyString& other) const;
bool operator!=(const MyString& other) const;
const MyString operator+(const MyString& rhs) const;
MyString& operator+=(const MyString& rhs);
friend ostream& operator<<(ostream& output, const MyString& rhs);
const int Find(const MyString& other);
MyString Substring(int start, int length);
private:
char *String;
int Size;
};
istream& operator>>(istream& input, MyString& rhs);
.cpp file:
#include <iostream>
#include <cstdlib>
#include "MyString.h"
using namespace std;
//default constructor that sets the initial string to the value "Hello World"
MyString::MyString()
{
char temp[] = "Hello World";
int counter(0);
while(temp[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = temp[i];
}
//alternate constructor that allows for setting of the inital value of the string
MyString::MyString(const char *message)
{
int counter(0);
while(message[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = message[i];
}
//copy constructor
MyString::MyString(const MyString &source)
{
int counter(0);
while(source.String[counter] != '\0')
{
counter++;
}
Size = counter;
String = new char[Size];
for(int i = 0; i < Size; i++)
String[i] = source.String[i];
}
//Deconstructor
MyString::~MyString()
{
delete [] String;
}
//Length() method that reports the length of the string
const int MyString::Length() const
{
int counter(0);
while(String[counter] != '\0')
{
counter ++;
}
return (counter);
}
/*Parenthesis operator should be overloaded to replace the Set and Get functions of your previous assignment. Note that both instances should issue exit(1) upon violation of the string array bounaries.
*/
MyString& MyString::operator()(const int index, const char b)
{
if(String[index] == '\0')
{
exit(1);
}
else
{
String[index] = b;
}
}
char& MyString::operator()(const int i)
{
if(String[i] == '\0')
{
exit(1);
}
else
{
return String[i];
}
}
/*Assignment operator (=) which will copy the source string into the destination string. Note that size of the destination needs to be adjusted to be the same as the source.
*/
MyString& MyString::operator=(const MyString& rhs)
{
if(this != &rhs)
{
delete [] String;
String = new char[rhs.Size];
Size = rhs.Size;
for(int i = 0; i < rhs.Size+1 ; i++)
{
String[i] = rhs.String[i];
}
}
return *this;
}
/*Logical comparison operator (==) that returns true iff the two strings are identical in size and contents.
*/
bool MyString::operator==(const MyString& other)const
{
if(other.Size == this->Size)
{
for(int i = 0; i < this->Size+1; i++)
{
if(&other == this)
return true;
}
}
else
return false;
}
//Negated logical comparison operator (!=) that returns boolean negation of 2
bool MyString::operator!=(const MyString& other) const
{
return !(*this == other);
}
//Addition operator (+) that concatenates two strings
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
MyString result;
delete [] result.String;
result.String = tmp;
result.Size = Size+rhs.Size;
return result;
}
/*Addition/Assigment operator (+=) used in the following fashion: String1 += String2 to operate as String1 = String1 + String2
*/
MyString& MyString::operator+=(const MyString& rhs)
{
char* tmp = new char[Size + rhs.Size + 1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
} for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
delete [] String;
String = tmp;
Size += rhs.Size;
return *this;
}
istream& operator>>(istream& input, MyString& rhs)
{
char* t;
int size(256);
t = new char[size];
input.getline(t,size);
rhs = MyString(t);
delete [] t;
return input;
}
ostream& operator<<(ostream& output, const MyString& rhs)
{
if(rhs.String != '\0')
{
output << rhs.String;
}
else
{
output<<"No String to output\n";
}
return output;
}
const int MyString::Find(const MyString& other)
{
int nfound = -1;
if(other.Size > Size)
{
return nfound;
}
int i = 0, j = 0;
for(i = 0; i < Size; i++)
{
for(j = 0; j < other.Size; j++)
{
if( ((i+j) >= Size) || (String[i+j] != other.String[j]) )
{
break;
}
}
if(j == other.Size)
{
return i;
}
}
return nfound;
}
/*MyString::Substring(start, length). This method returns a substring of the original string that contains the same characters as the original string starting at location start and is as long as length.
*/
MyString MyString::Substring(int start, int length)
{
char* sub;
sub = new char[length+1];
while(start != '\0')
{
for(int i = start; i < length+1; i++)
{
sub[i] = String[i];
}
}
return MyString(sub);
}
//Print() method that prints the string
const void MyString::Print() const
{
for(int i=0; i < Size; i++)
{
cout<<String[i];
}
cout<<endl;
}
main.cpp file:
#include <cstdlib>
#include <iostream>
#include "MyString.h"
using namespace std;
/*
*
*/
int main (int argc, char **argv)
{
MyString String1; // String1 must be defined within the scope
const MyString ConstString("Target string"); //Test of alternate constructor
MyString SearchString; //Test of default constructor that should set "Hello World". W/o ()
MyString TargetString (String1); //Test of copy constructor
cout << "Please enter two strings. ";
cout << "Each string needs to be shorter than 256 characters or terminated by /\n." << endl;
cout << "The first string will be searched to see whether it contains exactly the second string. " << endl;
cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator
if(SearchString.Find(TargetString) == -1) {
cout << TargetString << " is not in " << SearchString << endl;
}
else {
cout << TargetString << " is in " << SearchString << endl;
cout << "Details of the hit: " << endl;
cout << "Starting poisition of the hit: " << SearchString.Find(TargetString) << endl;
cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(TargetString), TargetString.Length());
}
return 0;
}
It appears the inner loop's invariant is that j is between 0 and end-2 inclusive. Hence j will NEVER equal end (the "matching" condition).
Looks like you have a problem with your found logic.
Your for loop is defined as for(int j = 0; j < end -1; j++)
but then you test for if(j == end)
j can never be equal to end in this for loop. Consider what you're actually trying to test for in your if statement.
I think you need to declare i and j outside the loops.
I think you meant j < end and not j < end - 1
I think you need to if((i+j>=end1) || String[i+j] != other.String[j]) and not just if(String[i+j] != other.String[j])
and if(j == end) needs to be outside the inner loop.
Here is a similar implementation.
#include <string>
#include <iostream>
using namespace std;
class MyString
{
private:
string String;
unsigned int Size;
public:
MyString() {
this->String = "";
this->Size = 0;
}
MyString(string initial_value) {
this->String = initial_value;
this->Size = initial_value.length();
}
const int Find(const MyString& other);
};
const int MyString::Find(const MyString& other)
{
if (other.Size > Size)
return -1; // if the substring is greater then us, there's no way we can have it as a substring
int i = 0, j = 0;
for (i = 0; i < Size; i++)
{
for (j = 0; j < other.Size; j++)
if ( ((i + j) >= Size) || (String[i + j] != other.String[j]) ) // if they don't match, offset exceeded Size, break
break ;
if (j == other.Size) // We went through the entire substring, didn't hit break so j == Other.size
return i; // return index
}
return -1; // if we never return anything means, we didn't find it, so return -1
}
int main()
{
string temp1, temp2;
getline(std::cin, temp1, '\n');
getline(std::cin, temp2, '\n');
MyString main_string(temp1), sub_string(temp2);
cout << main_string.Find(sub_string) << endl;
return 0;
}
MyString MyString::Substring(int start, int length)
{
char* sub = new char[length + 2]; // 2 byte buffer to be safe
int i = 0;
for (i = 0; i < length; i++)
sub[i] = String[start + i];
sub[i] = '\0'; // always null terminated to be safe!
return MyString(sub);
}
if theres any bugs or issues, I apologize, haven't tested it.
Along with what everyone else said, in your Substring method you have the following bit of code:
while(start != '\0')
{
for(int i = start; i < length+1; i++)
{
sub[i] = String[i];
}
}
Take a moment to go over the logic of the while loop and ask yourself "what am I trying to achieve here, and what does this code actually do?"
I would like to implement both of these functions so that I would be able to input and output objects of my class. I have gotten the >> operator to work but not so much <<.
Here is my code in my .h file:
class MyString
{
public:
MyString();
MyString(char *message);
~MyString();
void Print();
void Copy(MyString& rhs);
int Length();
MyString& operator()(const int index, const char b);
char& operator()(const int i);
MyString& operator=(const MyString& rhs);
bool operator==(const MyString& other) const;
bool operator!=(const MyString& other) const;
const MyString operator+(const MyString& rhs) const;
MyString& operator+=(const MyString& rhs);
private:
char *String;
int Size;
};
istream& operator>>(istream& input, MyString& rhs);
ostream& operator<<(ostream& output, const MyString& rhs);
Here is my code for the two functions in my .cpp file:
MyString::MyString()
{
char temp[] = "Hello World";
int counter(0);
while(temp[counter] != '\0') {
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = temp[i];
}
MyString::MyString(char *message)
{
int counter(0);
while(message[counter] != '\0') {
counter++;
}
Size = counter;
String = new char [Size];
for(int i=0; i < Size; i++)
String[i] = message[i];
}
MyString::~MyString()
{
delete [] String;
}
int MyString::Length()
{
int counter(0);
while(String[counter] != '\0')
{
counter ++;
}
return (counter);
}
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
const MyString MyString::operator+(const MyString& rhs) const
{
char* tmp = new char[Size + rhs.Size +1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i < rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
MyString result;
delete [] result.String;
result.String = tmp;
result.Size = Size+rhs.Size;
return result;
}
MyString& MyString::operator()(const int index, const char b)
{
if(String[index] == '\0')
{
exit(1);
}
else
{
String[index] = b;
}
}
MyString& MyString::operator=(const MyString& rhs)
{
if(this != &rhs)
{
delete [] String;
String = new char[rhs.Size];
Size = rhs.Size;
for(int i = 0; i < rhs.Size+1 ; i++)
{
String[i] = rhs.String[i];
}
}
return *this;
}
void MyString::Copy(MyString& rhs)
{
delete [] String;
Size = rhs.Size;
String = new char[rhs.Size];
String = rhs.String;
}
MyString& MyString::operator+=(const MyString& rhs)
{
char* tmp = new char[Size + rhs.Size + 1];
for(int i = 0; i < Size; i++)
{
tmp[i] = String[i];
}
for(int i = 0; i <rhs.Size+1; i++)
{
tmp[i+Size] = rhs.String[i];
}
delete [] String;
String = tmp;
Size += rhs.Size;
return *this;
}
bool MyString::operator!=(const MyString& other) const
{
return !(*this == other);
}
bool MyString::operator==(const MyString& other)const
{
if(other.Size == this->Size)
{
for(int i = 0; i < this->Size+1; i++)
{
if(&other == this)
return true;
}
}
else
return false;
}
char& MyString::operator()(const int i)
{
if( String[i] == '\0')
{
exit(1);
}
else
{
return String[i];
}
}
void MyString::Print()
{
for(int i=0; i < Size; i++)
cout << String[i];
cout << endl;
}
istream& operator>>(istream& input, MyString& rhs)
{
char* temp;
int size(256);
temp = new char[size];
input.getline(temp,size);
rhs = MyString(temp);
delete [] temp;
return input;
}
ostream& operator<<(ostream& output, const MyString& rhs)
{
char* p;
int size(256);
p = new char[size];
output << rhs.MyString(p);
delete [] p;
return output;
}
Here is how it is called in the main.cpp file:
cin >> SearchString >> TargetString; // Test of cascaded string-extraction operator<</*
if(SearchString.Find(ConstString) != -1) {
cout << ConstString << " is not in " << SearchString << endl; }
else {
cout << ConstString << " is in " << SearchString << endl;
cout << "Details of the hit: " << endl;
cout << "Starting poisition of the hit: " << SearchString.Find(ConstString) << endl;
cout << "The matching substring is: " << SearchString.Substring(SearchString.Find(ConstString), ConstString.length()); }
Again, the cin>> operator works perfectly but please help me to figure out how to output the string.
Not really sure what you are asking. The implementation depends on how you want to output the string.
For some raw output the code will most likely look like this:
output << rhs.get_data();