Overloading insertion and extraction operators for strings - c++

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();

Related

writing custom string class in c++

I am trying to write a basic string class for practice, and I am struggling with the reserve() function to increase my char array's memory allocation.
This is the error message I get:
free(): double free detected in tcache 2
This is my approach:
void string::reserve(size_t n)
{
if (n <= space+1) return; // never decrease allocation
char *p = new char[n+1]; // allocate new space
for (int i=0; i<sz; ++i) p[i]=pChars[i]; // copy old elements
//strcpy(p, pChars); // didn't work either
p[n] = '\0';
delete[] pChars; // deallocate old space
pChars = p;
space = n+1;
}
I will also share a picture of my header file below:
Here is the entire code:
#include "String.h"
namespace String
{
string::string(): sz(0), pChars(nullptr), space(0) {}
string::string(const char* s): sz(strlen(s)), pChars(new char[strlen(s)+1]), space(sz+1) ///Constructor using a null-terminated C String
{
//for (int i = 0; s[i] != '\0'; i++) pChars[i] = s[i];
strcpy(pChars,s);
pChars[strlen(s)] = '\0';
}
string::string(const string& s): sz(s.sz), pChars(new char[s.sz]), space(s.sz) ///copy constructor
{
for (size_t i = 0 ; i<s.sz; i++) pChars[i] = s.pChars[i];
pChars[s.sz] = '\0';
}
string& string::operator=(const string& s) ///copy assignment
{
if (this==&s) return *this; // self-assignment, no work needed
if (s.sz<=space)
{ // enough space, no need for new allocation
for (size_t i = 0; i<s.sz; ++i) pChars[i] = s.pChars[i]; // copy elements
sz = s.sz;
return *this;
}
char *p = new char [s.sz]; // copy and swap
for (size_t i = 0; i<s.sz; ++i) p[i] = s.pChars[i];
delete[] pChars;
sz = s.sz;
space = s.sz;
pChars = p;
return *this;
}
string& string:: operator=(const char* s) ///copy assignment using a null-terminated C String
{
char *p = new char[strlen(s)+1];
for(size_t i = 0; s[i] != '\0'; i++) p[i] = s[i];
p[sz] = '\0';
delete [] pChars;
sz = strlen(s);
space = sz;
strcpy(pChars, p);
return *this;
}
///string(string&& s); ///move constructor, not needed (compiler copy elision)
string& string:: operator=(string&& s) ///move assignment
{
delete[] pChars; // deallocate old space
pChars = s.pChars; // copy a's elem and sz
sz = s.sz;
space = s.space;
s.pChars = nullptr; // make a the empty vector
s.sz = 0;
cout << "Move" << endl;
return *this;
}
string::~string()
{
delete [] pChars;
}
char& string:: operator[](size_t pos) {return pChars[pos];} ///set operator
const char& string:: operator[](size_t pos) const {return pChars[pos];} ///get operator
void string::reserve(size_t n)
{
if (n <= space+1) return; // never decrease allocation
char *p = new char[n+1]; // allocate new space
for (int i=0; i<sz; ++i) p[i]=pChars[i]; // copy old elements
//strcpy(p, pChars);
p[sz] = '\0';
delete[] pChars; // deallocate old space
pChars = p;
space = n+1;
}
void string:: push_back(const char c) ///push char c to the end
{
if (sz==0) // no space: grab some
reserve(8);
else if (sz==space) // no more free space: get more space
reserve(2*space);
pChars[sz] = c; // add d at end
++sz; // and increase the size (sz is the number of elements)
}
bool operator==(const string& lhs, const string& rhs) ///check equality (same size, all chars the same)
{
if (lhs.size() != rhs.size()) return false;
else
{
for (size_t i = 0; i<lhs.size(); i++)
{
if (lhs[i] != rhs[i]) return false;
}
}
return true;
}
bool operator==(const string& lhs, const char* rhs) ///equality with null terminated C string
{
if(lhs.size() == strlen(rhs))
{
for (size_t i = 0; i< lhs.size(); i++)
{
if(lhs[i] == rhs[i]) return true;
}
}
return false;
}
bool operator>(const string& lhs, const string& rhs) ///greater than operator, true if lhs > rhs
{
}
string operator+(const string& lhs, const string& rhs) ///concatenate two MyStrings, return the result
{
}
ostream& operator<<(ostream& os, const string& s)
{
for (size_t i = 0; i<s.size(); i++)
{
os << s[i];
}
return os;
}
istream& operator>>(istream& is, string& s)
{
char c;
while(is.get(c))
{
if (c!=' ') s.push_back(c);
}
return is;
}
}
First error
string::string(const string& s): sz(s.sz), pChars(new char[s.sz]), space(s.sz) ///copy constructor
{
for (size_t i = 0 ; i<s.sz; i++) pChars[i] = s.pChars[i];
pChars[s.sz] = '\0';
}
This allocates an array of s.sz chars and then writes off the end of it
SHould be
string::string(const string& s): sz(s.sz), pChars(new char[s.sz] + 1), space(s.sz) ///copy constructor
{
for (size_t i = 0 ; i<s.sz; i++) pChars[i] = s.pChars[i];
pChars[s.sz] = '\0';
}

Repeating words in string class

So I have to write a string class, and I need help with reading from a file into a vector of string classes I've created. It somewhat works, as it reads from the file but it repeats the the word read in a few times depending on which word it's on.
// .h
/*Class description:
A string class. Various functions for the class.
String is passed into objects of the class. Reads
and writes to files.*/
#ifndef MYString12_H
#define MYString12_H
#include <fstream>
using namespace std;
class MYString12
{
public:
MYString12();
MYString12(const MYString12 & mstr);
MYString12(const char* ptr);
~MYString12();
MYString12& operator = (const MYString12& argStr);
friend MYString12 operator + (const MYString12& str1, const MYString12& str2);
char operator [] (int index);
bool operator > (const MYString12& argStr2);
bool operator < (const MYString12& argStr2);
bool operator == (const MYString12& argStr);
friend istream& operator >> (istream& istr, MYString12& argStr);
friend ostream& operator << (ostream& istr, MYString12& argStr);
int length() const;
int capacity()const;
char at(int index);
const char* c_str()const;
static int getCurrentCount();
static int getCreatedCount();
private:
char* str;
int cap = 20;
int end;
const int compareTo(const MYString12& argStr);
static int currentCount;
static int createdCount;
};
#endif
Here is class cpp file
// MYString12.cpp
#include "stdafx.h"
#include "MYString12.h"
#include <iostream>
#include <iomanip>
#include <math.h>
#include <cstdlib>
using namespace std;
int MYString12::createdCount = 0;
int MYString12::currentCount = 0;
// default constructor
MYString12::MYString12()
{
cap = 20;
end = 0;
str = new char[cap];
str[end] = '\0';
createdCount++;
currentCount++;
}
// copy constructor
MYString12::MYString12(const MYString12& mstr)
{
this->end = mstr.end;
this->cap = mstr.cap;
this->str = new char[mstr.cap];
while (end >= cap) {
cap += 20;
}
for (int i = 0; i < end; i++) {
str[i] = mstr.str[i];
}
//mstr.str[end] = '\0';
createdCount++;
currentCount++;
}
// constructor with string passed in
MYString12::MYString12(const char* ptr)
{
int i = 0;
while (ptr[i] != '\0') {
end++;
i++;
}
while (end >= cap) {
cap += 20;
}
str = new char[cap];
for (int j = 0; j < end; j++) {
str[j] = ptr[j];
}
createdCount++;
currentCount++;
}
// destructor
MYString12::~MYString12()
{
delete[] str;
currentCount--;
}
// overloaded assignment operator
GAString12& GAString12::operator = (const GAString12& mstr)
{
if (this == &mstr) {
return *this;
}
this->end = mstr.end;
this->cap = mstr.cap;
while (end >= cap) {
cap += 20;
}
for (int i = 0; i < end; i++) {
str[i] = mstr.str[i];
}
//mstr.str[end] = '\0';
return *this;
}
// overloaded concatanation operator
MYString12 operator + (const MYString12& str1, const MYString12& str2)
{
int temp = str1.end + str2.end + 1;
char tempArray[200];
int i = 0;
int j = 0;
while (i < temp)
{
if (i < str1.end)
{
tempArray[i] = str1.str[i];
i++;
} else {
tempArray[i] = str2.str[j];
i++;
j++;
}
}
tempArray[i] = '\0';
MYString12 concatenatedObj(tempArray);
return concatenatedObj;
}
// overloaded index operator
char MYString12::operator [] (int index)
{
return str[index];
}
// overloaded greater than operator
bool MYString12::operator > (const MYString12& argStr)
{
if ((*this).compareTo(argStr) > 0)
{
return true;
}
else {
return false;
}
}
// overloaded less than operator
bool MYString12::operator < (const MYString12& argStr)
{
if ((*this).compareTo(argStr) < 0)
{
return true;
}
else {
return false;
}
}
// overloaded equals equals operator
bool MYString12::operator == (const MYString12& argStr)
{
if ((*this).compareTo(argStr) == 0)
{
return true;
}
else {
return false;
}
}
// compares ascii values of objStr and argStr
const int MYString12::compareTo(const MYString12& argStr)
{
int asciiSubtraction = 0;
int limit = 0;
if (end <= argStr.end)
{
limit = end;
}
else {
limit = argStr.end;
}
int i = 0;
while (i <= limit && (str[i] == argStr.str[i])) {
i++;
}
asciiSubtraction = str[i] - argStr.str[i];
return asciiSubtraction;
}
// overloaded extraction operator
istream& operator >> (istream& istr, MYString12& argStr)
{
char temp[100];
istr >> temp;
argStr = GAString12(temp);
return istr;
}
// overloaded insertion operator
ostream& operator << (ostream& ostr, MYString12& argStr)
{
int i = 0;
while (argStr.str[i] != '\0')
{
ostr << argStr.str;
i++;
}
return ostr;
}
// returns size of passed in string
int MYString12::length() const
{
return end;
}
// returns size of memory allocated
int MYString12::capacity() const
{
return cap;
}
// returns a char of string at passed index
char MYString12::at(int index)
{
if (index < 0 || index > end) {
return '\0';
}
else {
return str[index];
}
}
// returns passed in string as c string
const char* MYString12::c_str() const
{
createdCount++;
currentCount++;
return str;
}
// returns the amount of alive instances of class
int MYString12::getCurrentCount()
{
return currentCount;
}
// returns the amount of overall created instances of class
int MYString12::getCreatedCount()
{
return createdCount;
}
And here is main
// main
int main()
{
vector<MYString12> word(100);
ifstream fin;
fin.open("infile3.txt");
if (fin.fail()) {
cout << "Error." << endl;
exit(1);
}
int wordCount = 0;
while (fin >> word[wordCount]) {
cout << word[wordCount];
system("pause");
wordCount++;
}
word.resize(wordCount);
fin.close();endl;
return 0;
}
It doesn't print out to the console any of the words. Nothing is printed. Why doesn't it print?

Overload operator>> in self-made class 'String' C++

I am creating class 'String'.
But I have a problem with overloading of operator>>.
I've tried to do like this:
istream& operator >> (istream& input, String& inputStr)
{
char str[] = "";
input >> str;
inputStr.size = strlen(str);
inputStr.str = new char[inputStr.size];
for (int i = 0; i < inputStr.size; i++)
{
inputStr.str[i] = str[i];
}
return input;
}
But it doesn't work =(
Can you help me to overload this operator ?
Here is a code:
#pragma once
#include<iostream>
using namespace std;
class String
{
private:
int size;
char* str;
public:
String();
~String();
String(char* arr);
String(const String& copy);
int sizeStr();
friend ostream& operator << (ostream& output, const String& outputStr);
friend istream& operator >> (istream& input, String& inputStr);
};
String::String()
{
this->size = 0;
this->str = nullptr;
}
String::String(char* str)
{
this->size = strlen(str);
this->str = new char[size];
for (int i = 0; i < size; i++)
{
this->str[i] = str[i];
}
}
String::~String()
{
delete[] str;
}
String::String(const String& copy)
{
if (this != &copy)
{
this->size = copy.size;
this->str = new char[size];
for (int i = 0; i < size; i++)
{
this->str[i] = copy.str[i];
}
}
}
int String::sizeStr()
{
return this->size;
}
ostream& operator << (ostream& output, const String& outputStr)
{
for (int i = 0; i < outputStr.size; i++)
{
output << outputStr.str[i];
}
return output;
}
istream& operator >> (istream& input, String& inputStr)
{
return input;
}
I`m looking forward to your help.

Apply operator overriding to classes with dynamic allocation pointers

I have defined the MyString class, and now I want to implement the addition operation. It's horrible for memory leaks to occur, so I've taken care of releasing the dynamically allocated pointers from the destructor.
#include <iostream>
class MyString {
private:
int _size;
char* _str;
public:
MyString() {
_size = 0;
_str = nullptr;
}
MyString(int size, char* str) {
_size = size;
_str = new char[size + 1];
strcpy(_str, str);
}
~MyString() {
delete[] _str;
}
void print() {
std::cout << _str << std::endl;
}
friend MyString operator+(const MyString& lhs, const MyString& rhs);
};
MyString operator+(const MyString& lhs, const MyString& rhs) {
char* temp = new char[lhs._size + rhs._size + 1];
strcpy(temp, lhs._str);
strcat(temp, rhs._str);
MyString ret(lhs._size + rhs._size, temp);
delete[] temp;
return ret;
}
int main() {
MyString first(5, "first");
MyString second(6, "second");
MyString add = first + second;
first.print();
second.print();
add.print();
}
However, if I compile the code and run it, the first.print() and second.print() is printed well, but the add.print() will print the garbage value, and crashes (Debug Assertion Failed!).
Output:
first
second
硼硼硼硼硼硼硼硼?흚 (and creashes :(.. )
If I annotate and run the destructor, it prints well, but a memory leak occurs. Why is this happening? I have looked at several examples of operator overriding, but I have not found an example of this dynamic allocation of pointers.
Any suggestion will be highly appreciated!
MyString operator+(const MyString& lhs, const MyString& rhs) {
char* temp = new char[lhs._size + rhs._size + 1];
strcpy(temp, lhs._str);
strcat(temp, rhs._str);
MyString ret(lhs._size + rhs._size, temp);
delete[] temp;
return ret;
}
At the end of this function 'ret' is destroyed which calls the destructor and deletes the buffer. What is returned is a new instance of MyString that was copied from 'ret', and its buffer points to the same memory location as the original. Since this has been deleted you are now printing out garbage.
To fix this you can add a copy constructor to ensure the buffer is copied:
class MyString {
// Other class details
public:
MyString(const MyString & other) : MyString(other._size, other._str) {}
// Other class details
}
This will ensure the buffer is copied when one MyString is assigned to another MyString.
#include<iostream>
using namespace std;
class Mystring{
private:
int size;
char *str;
public:
friend Mystring operator*(const Mystring &a, const int &d);
friend Mystring operator+(const Mystring &a, const Mystring& b);
friend ostream& operator << (ostream &os, const Mystring a);
friend istream& operator >> (istream &is, const Mystring a);
Mystring (int a, char b) {
this->size = a;
this->str = new char(a);
for (int i = 0; i < a; i++) {
this->str[i] = b;
}
}
~Mystring() {}
};
Mystring operator+(const Mystring &a, const Mystring& b) {
Mystring c(a.size + b.size, { 0 });
for (int i = 0; i < a.size; i++)
{
c.str[i] = a.str[i];
}
for (int i = 0; i < b.size; i++)
{
c.str[a.size + i] = b.str[i];
}
return c;
}
Mystring operator*(const Mystring& a,const int &d){
int z = a.size*d;
Mystring c(z, { 0 });
int k=0;
for (int j = 0; j < d; j++)
{
for (int i = 0; i < a.size; i++)
{
c.str[k+i] = a.str[i];
}
k = a.size + k;
}
return c;
}
ostream& operator << (ostream &os, const Mystring a) {
os << "[";
int i;
for ( i = 0; i < a.size; i++)
{
os << a.str[i];
}
os << "]";
return os;
}
istream& operator >> (istream &is, const Mystring a) {
for (int i = 0; i < a.size; i++)
{
cout << i << "번째 문자 : ";
is >> a.str[i];
}
return is ;
}
int main()
{
int aSize, bSize, iter;
char aInit, bInit;
cout << "문자열A의 크기와 초기문자를 입력: ";
cin >> aSize >> aInit;
Mystring str1(aSize, aInit);
cout << str1 << endl;
cout << "문자열A 입력" << endl;
cin >> str1;
cout << str1 << endl;
cout << "문자열B의 크기와 초기문자를 입력: ";
cin >> bSize >> bInit;
Mystring str2(bSize, bInit);
cout << str2 << endl;
cout << "문자열B 입력" << endl;
cin >> str2;
cout << str2 << endl;
cout << "문자열A와 문자열B 합치기 : ";
Mystring str3 = str1 + str2;
cout << str3 << endl;
cout << "문자열A 반복횟수 입력 : ";
cin >> iter;
Mystring str4 = str1*iter;
cout << str4 << endl;
}
enter code here
why error
~Mystring(){}

Function to find a string within a larger string

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?"