Assignment operator overloading - deleting heap memory causes crash - c++

I am writing to write a string class and while doing assignment operator overloading I am observing crash at the part where we do deletion of previously allocated memory. I tried to trace through code but couldn't figure it out. Any pointers would help
str& str::operator=(const str &Rhs)
{
if (this != &Rhs)
{
cout << " attempt of self allocation - " << endl;
**delete[] this->_element;** // crashes here
this->_capacity = Rhs._capacity;
this->_display = Rhs._display;
this->_size = Rhs._size;
if (Rhs._size > 0)
{
this->_element = new char(this->_size);
if (this->_element == NULL)
{
cout << " mem allocation failed " << endl;
}
}
for (int counter = 0; counter <= this->_size; counter++)
{
this->_element[counter] = Rhs._element[counter];
}
}
return *this;
}
/*copy constructor */
str::str(const str& Rhs)
{
// copy constructor called
this->_capacity = Rhs._capacity;
this->_display = Rhs._display;
this->_size = Rhs._size;
if (Rhs._size > 0)
{
this->_element = new char(_size);
if (this->_element == NULL)
{
cout << " mem allocation failed " << endl;
}
for (int counter = 0; counter <= this->_size; counter++)
{
this->_element[counter] = Rhs._element[counter];
}
}
}
/* constructor */
str::str(const char *Y)
{
cout << "constructor called !!! -- " << endl;
size_t len = this->stringlen(Y);
this->_element = new char(len + 1);
for (int counter = 0; counter < len; counter++)
{
this->_element[counter] = Y[counter];
}
this->_element[len] = '\0';
this->_size = len + 1;
cout << "string in constructor is -- " << this->_element << endl;
}
From .h file
class str
{
public:
/*Default Constructor*/
explicit str();
/*Constructor with single char Argument*/
explicit str(char x);
/*Constructor with char array Argument*/
explicit str(const char* Y);
/* Creating new element with copy constructor */
str(const str& Rhs);
/* Overloading of Assignment operator */
str& operator=(const str& Rhs);
friend int string_compare(const str& Lhs, const str& Rhs);
int reverse();
size_t stringlen(const char* Y);
str& operator+(str& Rhs);
bool operator==(const str& Rhs);
bool operator!=(const str& Rhs);
friend ostream& operator<<(ostream &out, str& Lhs);
private:
char* _element;
int _capacity;
bool _display;
int _size; //largest accessed + 1
};
Main Routine -
void test1() {
const char *j = "abc";
cout << "length of j = " << strlen(j) << endl;
str s1('U');
str s2("hello");
cout << s2 << endl;
s2.reverse();
cout << s2 << endl;
str s3(s2);
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
**s2 = s1;** // crashes
cout << s2 << endl;
cout << s1 << endl;
}

There are several problems with your code.
The biggest one is: if you want to allocate an array you need to use new char[_size]. new char(_size) allocates one char with its value set to _size.
Second, once you fix that problem, you write past the end of your allocated array - judging by the comment in your header you need to allocate char[_size + 1].
Third, in your copy constructor you never initialize the _element array and in your assignment operator you never clear up the _element value. This will eventually lead to crash when you copy or assign an empty str and then try to assign to it (or at destruction time as I assume that the destructor also calls delete).

Related

Homework task: Checking the equality of two arrays

I am stuck on a homework question which requires me to create/modify a function which will set two arrays equal to each other. The question asks:
"Use the copy assignment (=) operator to set the two arrays equal to each other, this can be checked with the following:
y = x;
cout << "x equals y? " << (x == y) << endl; //Should return "True"
And is set within the following rules:
"Note that two Array objects should be considered equal only if they have the same length and the same element values."
This is the code I have, I have implemented two debugging sections which shows that they are indeed equal both in the assignment function and the main function, so my best guess is that the lengths don't match up. I am not allowed to modify any of the code which was provided (All the class and function stuff, or anything above the debugger in main), so I'm not sure how to set the lengths equal to each other in order to satisfy the condition (x==y)
#include <iostream>
using namespace std;
// definition
#define MAX_LENGTH 100
#define INIT_VALUE 0
class Array {
public:
Array(int length);
Array& operator=(const Array& other);
int length() const;
int& operator[](int index);
bool operator==(const Array& other) const;
bool operator!=(const Array& other) const;
private:
int length_;
int elements_[MAX_LENGTH];
};
// implementation
Array::Array(int length) {
length_ = length;
if (length_ > MAX_LENGTH) length_ = MAX_LENGTH;
for (int i = 0; i < length_; ++i) {
elements_[i] = INIT_VALUE;
}
}
Array& Array::operator=(const Array& other)
{
/*DEBUG*/cout << endl << endl << "<<NOW IN ASSIGNMENT FUNCTION>>" << endl << endl;
for (int i = 0; i < other.length_; ++i)
{
elements_[i] = other.elements_[i];
/*DEBUG*/cout << endl << "Elements: " << elements_[i] << " | Other Elements: " << other.elements_[i] << endl;
}
return *this;
}
int Array::length() const {
return length_;
}
int& Array::operator[](int index) {
// Q3 code goes here
return elements_[index];
}
bool Array::operator==(const Array& other) const
{
if (length_ != other.length_) return false;
for (int i = 0; i < other.length_; ++i) {
if (elements_[i] != other.elements_[i]) return false;
}
return true;
}
bool Array::operator!=(const Array& other) const
{
if (length_ != other.length_)
{
return true;
}
for (int j = 0; j < other.length_; ++j)
{
if (elements_[j] != other.elements_[j]) return true;
}
return false;
}
// testing
int main()
{
Array x(10);
x[3] = 42;
cout << "x contains ";
for (int i = 0; i < x.length(); ++i) {
cout << x[i] << " ";
}
cout << endl;
Array y(5);
cout << boolalpha;
cout << "x equals y? " << (x == y) << endl;
cout << "x notequals y? " << (x != y) << endl;
y = x;
//DEBUG SECTION
cout << endl << endl << "<<NOW IN MAIN>>" << endl << endl;
for (int i = 0; i < x.length(); ++i)
{
cout << endl << "Elements: " << x[i] << " | Other Elements: " << y[i] << endl;
}
//END OF DEBUG SECTION
cout << "x equals y? " << (x == y) << endl;
}
So the question is, how can I get these arrays to have the same length without modifying them in 'main'? Can I do this through the assignment function?
You just forgot to assign the same length in the the Array::operator=.
This can be done by writing this->length_ = other.length_; in the
Array& Array::operator=(const Array& other) before overwriting the array.
As mentioned before, you did not asign the length correctly in the = operator.
Fix like this:
Array& Array::operator=(const Array& other)
{
length_ = other.length_;
for (int i = 0; i < length_; ++i)
{
elements_[i] = other.elements_[i];
}
return *this;
}
Also you can simplify your != operator drastically
bool Array::operator!=(const Array& other) const
{
return !(*this == other);
}
However, in my opinon even more important, you should also make use of the std-containers which allow dynamic sizes such as std::vector. This also would have avoided your bug.
In my opinion you should use these std-containers as soon as possible and get used to them. They are almost always the right choice when in doubt.
With std::vector your program could look like this:
#include <iostream>
#include <vector>
using namespace std;
// definition
#define INIT_VALUE 0
class Array {
public:
Array(int length);
Array& operator=(const Array& other);
int length() const;
int& operator[](int index);
bool operator==(const Array& other) const;
bool operator!=(const Array& other) const;
private:
std::vector<int> elements_;
};
// implementation
Array::Array(int length)
:
elements_(length, INIT_VALUE)
{
}
Array& Array::operator=(const Array& other)
{
/*DEBUG*/cout << endl << endl << "<<NOW IN ASSIGNMENT FUNCTION>>" << endl << endl;
elements_ = other.elements_;
return *this;
}
int Array::length() const {
return static_cast<int>(elements_.size());
}
int& Array::operator[](int index) {
// Q3 code goes here
return elements_[index];
}
bool Array::operator==(const Array& other) const
{
return elements_ == other.elements_;
}
bool Array::operator!=(const Array& other) const
{
return !(*this == other);
}
// testing
int main()
{
Array x(10);
x[3] = 42;
cout << "x contains ";
for (int i = 0; i < x.length(); ++i) {
cout << x[i] << " ";
}
cout << endl;
Array y(5);
cout << boolalpha;
cout << "x equals y? " << (x == y) << endl;
cout << "x notequals y? " << (x != y) << endl;
y = x;
//DEBUG SECTION
cout << endl << endl << "<<NOW IN MAIN>>" << endl << endl;
for (int i = 0; i < x.length(); ++i)
{
cout << endl << "Elements: " << x[i] << " | Other Elements: " << y[i] << endl;
}
//END OF DEBUG SECTION
cout << "x equals y? " << (x == y) << endl;
}

Istream operator overloading '>>' cause infinite loop

My college teacher assigned a homework about simulating string, and here's one selection of my code:
// MyString.h
#include <iostream>
#include <cstdio>
#include <string.h>
using std::ostream;
using std::istream;
class MyString{
protected:
char *_data; // data index
int _len; // index size
public:
/////////////////////////////////////////////////////////
char* data()const{
return _data;
}
/////////////////////////////////////////////////////////
MyString& operator=(const char* &rhs){
_data = const_cast<char*>(rhs);
_len = strlen(_data)
}
MyString& operator=(const MyString& rhs){
(*this) = rhs._data;
}
/////////////////////////////////////////////////////////
friend ostream &operator<<( ostream&, const MyString & );
friend istream &operator>>( istream&, MyString & );
};
ostream& operator <<(ostream& os, const MyString& str){
os << str.data();
return os;
}
istream& operator >>(istream& is, MyString& str){
char buffer[0xff];
is.getline(buffer, 0xff);
str = buffer;
return is;
}
I totally have no idea why operator = causes infinite loop here...please help...thanks in advance
Edit:
There goes my buggy code. I have edited where cause the causes infinite loop issue but the rest of them maybe still bugged, I'll try to fix them soon, thank you all!
MyString.h
#include <iostream>
#include <cstdio>
#include <string.h>
using std::ostream;
using std::istream;
class MyString{
protected:
char *_data; // data index
int _len; // index length
static int _total_MyString; // number of instance created
public:
/////////////////////////////////////////////////////////
// basic initialization
MyString(){
_data = NULL;
_len = 0;
_total_MyString++;
}
// init with defined string
MyString(const char *s):MyString(){
(*this)= s;
}
// init with same class data
MyString(const MyString & s):MyString(s._data){}
// finalizer
~MyString(){
_total_MyString--;
delete _data;
}
/////////////////////////////////////////////////////////
static int total_MyString(){
return _total_MyString;
}
/////////////////////////////////////////////////////////
char* data()const{
return _data;
}
/////////////////////////////////////////////////////////
MyString& operator=(const char* &rhs){
char* temp = const_cast<char*>(rhs);
_len = strlen(temp);
_data = new char [_len + 1];
strcpy(_data, rhs);
return (*this);
}
MyString& operator=(const MyString& rhs){
const char* temp = rhs._data;
return (*this = temp);
}
/////////////////////////////////////////////////////////
MyString& operator+=(const char* &rhs){
_len += strlen(rhs);
strcat(_data, rhs);
return *this;
}
MyString& operator+=(const MyString& rhs){
const char* temp = rhs._data;
(*this) += temp;
return *this;
}
/////////////////////////////////////////////////////////
inline char & operator[](const int pos){
return _data[pos];
}
/////////////////////////////////////////////////////////
unsigned length() const{
return _len;
}
/////////////////////////////////////////////////////////
friend ostream &operator<<( ostream&, const MyString & );
friend istream &operator>>( istream&, MyString & );
/////////////////////////////////////////////////////////
bool operator==(const MyString& str){
return !strcmp(_data, str._data);
}
friend bool operator!=(const MyString& str, const MyString& str2){
return strcmp(str._data, str2._data) != 0;
}
};
ostream& operator <<(ostream& os, const MyString& str){
os << str.data();
return os;
}
istream& operator >>(istream& is, MyString& str){
char buffer[0xff];
is.getline(buffer, 0xff);
const char* temp = &buffer[0];
str = temp;
return is;
}
MyString.cpp
#include "MyString.h"
using namespace std ;
int MyString::_total_MyString = 0;
int main()
{
MyString Dstr1("String"), Dstr2("Test String 2"), Dstr3(Dstr1);
cout << "Dstr1 is: " << Dstr1 << endl;
cout << "Dstr2 is: " << Dstr2 << endl;
cout << "Dstr3 is: " << Dstr3 << endl;
cout << "Total MyString_Derived is: " << MyString_Derived::total_MyString() << endl;
/////////////////////////////////////////////////////////
cout << "Give one word "<< endl;
cin >> Dstr1;
cout << "Dstr1 is: " << Dstr1 << endl;
/////////////////////////////////////////////////////////
Dstr2 = Dstr1;
cout << "Dstr2 is: " << Dstr2 << endl;
return 0;
/////////////////////////////////////////////////////////
Dstr3 += Dstr1;
cout << "Dstr3 is: " << Dstr3 << endl;
/////////////////////////////////////////////////////////
cout << "Dstr3 is: ";
for(int i = 0; i<Dstr3.length(); i++)
cout << Dstr3[i];
cout << endl;
for(int i = 0; i<Dstr3.length(); i++)
Dstr3[i] = 'a' + i;
cout << "Dstr3 is: " << Dstr3 << endl;
/////////////////////////////////////////////////////////
cout << "Dstr1 is: " << Dstr1 << endl;
cout << "Dstr2 is: " << Dstr2 << endl;
cout << "Dstr3 is: " << Dstr3 << endl;
cout << "Compare Dstr1 == Dstr2 is: " << (Dstr1 == Dstr2) << endl;
cout << "Compare Dstr1 == Dstr3 is: " << (Dstr1 == Dstr3) << endl;
cout << "Compare Dstr1 != Dstr2 is: " << (Dstr1 != Dstr2) << endl;
cout << "Compare Dstr1 != Dstr3 is: " << (Dstr1 != Dstr3) << endl;
}
Consider the operator>>
istream& operator >>(istream& is, MyString& str){
char buffer[0xff];
is.getline(buffer, 0xff);
const char* temp = &buffer[0];
str = temp;
return is;
}
buffer is a local variable. you create a pointer to this local array and assing it to str. That calls
MyString& operator=(const char* &rhs){
_data = const_cast<char*>(rhs);
_len = strlen(_data);
return (*this);
}
Which is interesting: as a parameter you give the reference to a pointer, which is const, and you then strip the const-ness from it and assign it to _data.
Now char* _data is pointing to the local array buffer. What happens at the end of the function, when the local array is destroyed? The pointer becomes invalid.
You need to implement a deep copy.

C++ Overloaded + operator in a custom string class using linked list

After a fairly lengthy session with my instructor and not being able to come up with a concrete solution, I figured I'd come back here for help on a homework assignment. We're supposed to translate the string class to our own version that uses a linked list with a few basic functions. Everything seems to work so far except the + operator function (adding two strings together).
string operator +(string& s1, string& s2);
What's strange is that it appears to return the correct result when tested, only to cause a crash with a debug assertion failure. I cannot tell why this would be, since the definition:
string operator +(string& s1, string& s2)
{
s1 += s2;
return s1;
}
relies on +=, but that operator works with no issue with the test code in main(). Here's the full code:
HEADER FILE
#ifndef STRING2_H
#define STRING2_H
#include<iostream>
namespace string2
{
class string
{
private:
struct stringList
{
char character;
stringList* link;
};
stringList* headPtr;
public:
// CONSTRUCTORS AND DESTRUCTOR
string() { headPtr = NULL; };
string(const stringList* sourcePtr);
~string();
// CONSTANT MEMBER FUNCTIONS
char getChar(const size_t position) const;
size_t length() const;
char operator [ ] (size_t position) const;
// MODIFICATION MEMBER FUNCTIONS
void operator += (const string& addend);
void operator += (const char addend[]);
void operator += (char addend);
void operator =(const string& source);
// FRIEND FUNCTIONS
friend bool operator ==(const string& s1, const string& s2);
};
// NONMEMBER FUNCTIONS
string operator +(string& s1, string& s2);
std::ostream& operator <<(std::ostream& outs, const string& source);
}
#endif
IMPLEMENTATION
#include "String2.h"
#include <iostream>
namespace string2
{
string::string(const stringList* sourcePtr)
{
stringList* indexPtr;
if (sourcePtr == NULL)
{
headPtr = NULL;
return;
}
headPtr = new stringList;
indexPtr = headPtr;
indexPtr->character = sourcePtr->character;
indexPtr->link = sourcePtr->link;
sourcePtr = sourcePtr->link;
while (sourcePtr != NULL)
{
indexPtr = indexPtr->link;
indexPtr->character = sourcePtr->character;
indexPtr->link = sourcePtr->link;
sourcePtr = sourcePtr->link;
}
}
string::~string()
{
stringList *removePtr;;
while (headPtr != NULL)
{
removePtr = headPtr;
headPtr = headPtr->link;
delete removePtr;
}
}
char string::getChar(const size_t position) const
{
stringList *indexPtr = headPtr;
for (size_t i = 0; i < position - 1; i++)
indexPtr = indexPtr->link;
return indexPtr->character;
}
size_t string::length() const
{
size_t count = 0;
stringList* indexPtr = headPtr;
while (indexPtr != NULL)
{
count++;
indexPtr = indexPtr->link;
}
return count;
}
char string::operator [ ] (size_t position) const
{
stringList* indexPtr = headPtr;
for (size_t i = 0; i < position; i++)
indexPtr = indexPtr->link;
return indexPtr->character;
}
void string::operator += (const string& addend)
{
for (int index = 0; index < addend.length(); index++)
(*this) += addend[index];
}
void string::operator += (const char addend[])
{
if (addend[0] == NULL)
return;
for (int index = 0; index < (sizeof(addend) / sizeof(addend[0])); index++)
(*this) += addend[index];
}
void string::operator += (char addend)
{
stringList *indexPtr = headPtr;
if (headPtr == NULL)
{
headPtr = new stringList;
headPtr->character = addend;
headPtr->link = NULL;
return;
}
while (indexPtr->link != NULL)
indexPtr = indexPtr->link;
indexPtr->link = new stringList;
indexPtr->link->character = addend;
indexPtr->link->link = NULL;
}
void string::operator =(const string& source)
{
if (headPtr != NULL)
{
delete headPtr;
headPtr = NULL;
}
*this += source;
}
bool operator ==(const string& s1, const string& s2)
{
if (s1.length() != s2.length())
return false;
if (s1.headPtr == NULL && s2.headPtr == NULL)
return true;
for (int index = 0; index < s1.length(); index++)
{
if (s1.headPtr->character != s2.headPtr->character)
return false;
}
return true;
}
string operator +(string& s1, string& s2)
{
s1 += s2;
return s1;
}
std::ostream& operator <<(std::ostream& outs, const string& source)
{
for (int index = 0; index < source.length(); index++)
outs << source.getChar(index + 1);
return outs;
}
}
TEST CODE (final line is where it breaks)
#include "String2.h"
#include <iostream>
#include <fstream>
using namespace string2;
int main()
{
string test, test2, test3;
std::cout << "Current length: " << test.length() << std::endl;
char add[4] = { 'a', 'b', 'c', 'd' };
test += 's'; // testing third (lowest) += operator
std::cout << "First char in string: " << test.getChar(1) << std::endl;
test += 'd';
std::cout << "Current length: " << test.length() << std::endl;
std::cout << "Second char in string: " << test.getChar(2) << std::endl;
std::cout << "Second char in string testing [] operator: " << test[1] << std::endl;
std::cout << "Current string: " << test << std::endl;
test += add; // testing second (middle) += operator
std::cout << "Current length: " << test.length() << std::endl;
std::cout << "Current string: " << test << std::endl;
test2 += 'z';
test2 += 'y';
test += test2; // testing first (top) += operator
std::cout << "Current string: " << test << std::endl;
test = test2; // testing = operator
std::cout << "\nCurrent string: " << test << std::endl;
std::cout << "Compared to string: " << test2 << std::endl;
if (test == test2) // testing == operator
std::cout << "\nStrings are equal" << std::endl;
else
std::cout << "\nStrings are not equal." << std::endl;
test += 'f';
std::cout << "\nCurrent string: " << test << std::endl;
std::cout << "Compared to string: " << test2 << std::endl;
if (test == test2) // testing == operator
std::cout << "\nStrings are equal" << std::endl;
else
std::cout << "\nStrings are not equal." << std::endl;
std::cout << "\nTwo strings added together: " << test + test2 << std::endl; // testing + operator
}
Thank you for your help
Your problem is reproducible with this
int main()
{
string test, test2;
test += 'h';
std::cout << "\nTwo strings added together: " << test + test2 << std::endl; // testing + operator
}
string operator +(string& s1, string& s2)
{
s1 += s2;
return s1;
}
In operator +, return s1 returns a shallow copy of s1.So now the internal memory is being occupied by s1 as well as the returned string from operator+(). At the end of main() ~string() is triggered for s1 which frees the internal memory and then for the returned string from operator+() as well which tries to delete the already deleted memory causing double free.
You need a deep copy in operator+() or better, a rethink in design of operator+().

Overloading + operator in String class

I have to implement a string class with operators [], +, +=, <<, >>, ==, !=, <, <=, >, >= but I cannot use the string object or include the library for c++. Here is my code so far:
# define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<fstream>
using namespace std;
class MyString {
public:
MyString();
MyString(const char* chars);
int length() const;
char * getValue()const;
~MyString();
//copy constructor
MyString(const MyString&);
MyString& operator =(const MyString& s);
char& operator[](int i);
MyString& operator+=(const MyString& s);
friend ostream& operator<<(ostream&os, const MyString&s);
friend istream& operator >> (istream&is, MyString&s);
friend bool operator ==(const MyString& s1, const MyString& s2);
friend bool operator <(const MyString& s1, const MyString& s2);
private:
char* value;
int size;
};
MyString operator+(const MyString s1, const MyString& s2);
bool operator !=(const MyString& s1, const MyString& s2);
bool operator >=(const MyString& s1, const MyString& s2);
bool operator <=(const MyString& s1, const MyString& s2);
bool operator > (const MyString& s1, const MyString& s2);
//no arguments constructor
MyString::MyString() {
value = 0;
size = 0;
}
//constructor
MyString::MyString(const char* chars) {
size = strlen(chars);
value = new char[size + 1];
strcpy(value, chars);
}
int MyString::length()const {
return size;
}
char* MyString::getValue()const {
return value;
}
MyString::~MyString() {
delete[] value;
}
//copy constructor
MyString::MyString(const MyString& s) {
size = s.size;
value = new char[size + 1];
strcpy(value, s.value);
}
MyString& MyString::operator=(const MyString&s) {
if (s.value == 0) {
delete[] value;
value = 0;
size = 0;
return *this;
}
if (this != &s) {
delete[] value;
value = new char[s.size + 1];
strcpy(value, s.value);
size = s.size;
}
return *this;
}
char& MyString::operator[](int i) {
if (i < 0 || i >= size) {
cout << "Please enter correct value of index" << endl;
exit(0);
}
else {
return value[i];
}
return value[i];
}
MyString& MyString::operator+=(const MyString& s) {
char** temp = &value;
*temp = new char[size];
strcpy(value,*temp);
strcat(value, s.getValue());
if (size != 0) {
delete[] temp;
}
size = strlen(value);
return *this;
}
ostream& operator<<(ostream&out, const MyString&s) {
out << s.value;
return out;
}
istream& operator >> (istream&in, MyString&s) {
char*ptr = new char[100];
in >> ptr;
s = MyString(ptr);
delete ptr;
return in;
}
MyString operator+(const MyString s1, const MyString& s2) {
MyString answer;
answer += s1;
answer+= s2;
return answer;
}
bool operator ==(const MyString&s1, const MyString& s2) {
return(strcmp(s1.value, s2.value) == 0);
}
bool operator<(const MyString& s1, const MyString& s2) {
return (strcmp(s1.value, s2.value) < 0);
}
bool operator !=(const MyString& s1, const MyString& s2) {
return !(s1 == s2);
}
bool operator>(const MyString& s1, const MyString& s2) {
return !(s1 == s2) && !(s1 < s2);
}
bool operator<=(const MyString& s1, const MyString& s2) {
return s1 < s2 || s1 == s2;
}
bool operator >=(const MyString & s1, const MyString& s2) {
return !(s1 < s2);
}
void test_copy_and_destructor(MyString S) {
cout << "test: copy constructor and destructor calls: " << endl;
MyString temp = S;
cout << "temp inside function test_copy_and_destructor: " << temp << endl;
}
int main() {
MyString st1("abc abc");
MyString st2("9fgth");
cout << "Copy constructor , << operator" << endl;
MyString st3(st1);
cout << "st3: " << st3 << endl;
test_copy_and_destructor(st2);
MyString st4;
cout << "operator + " << endl;
st4 = st3 + st2;
cout << "st4: " << st4 << endl;
cout << "st1 + st2: " << (st1 + st2) << endl;
cout << "operators [ ] " << endl;
for (int i = 0; i < st2.length(); i++)
cout << st2[i] << " ";
cout << endl;
cout << "operators += , ==, != " << endl;
st2 += st1;
if (st3 == st1)
cout << "st3 and st1 are identical " << endl;
else cout << "st3 and st1 are not identical " << endl;
if (st2 != st1)
cout << "st2 and st1 are not identical " << endl;
else cout << "st2 and st1 are identical " << endl;
cout << "operators < , <=, >, >= " << endl;
if (st2 < st1)
cout << "st2 < st1 " << endl;
else cout << "st2 is not less than st1 " << endl;
if (st1 <= st2)
cout << "st1 <= st2 " << endl;
else cout << "st1 is not less than or equal to st2 " << endl;
if (st1 > st2)
cout << "st1 > st2 " << endl;
else cout << "not (st1 > st2) " << endl;
if (st1 >= st2)
cout << "st1 >= st2 " << endl;
else cout << "not (st1 >= st2) " << endl;
cout << "operator >> " << endl;
//Open the data file
ifstream input("A9_input.txt");
if (input.fail()) {
cout << "unable to open input file A9_input.txt, Exiting..... ";
return 0;
}
MyString temp1;
MyString temp2("aaa");
input >> temp1;
input >> temp2;
cout << "first element of input file: " << temp1 << endl;
cout << "second element of input file: " << temp2 << endl;
input.close();
cout << "MyString says farewell....." << endl;
return 0;
}
After reaching operator + my code reaches break point and crashes. I could tell something is wrong with my += operator code as + is using += code. Can someone help me figure out what is wrong with my += code?
The problem is that you are using strcpy() and strcat() to populate the old allocation, which is not large enough. Therefore, the strcat() invocation attempts to write past the end of this allocation and the result is undefined behavior, which is manifesting as a crash on your system.
char* temp = value;
temp = new char[strlen(value) + s.length() +1];
strcpy(value, temp); // <-- should be copying the other way
strcat(value, s.getValue()); // <-- should be copying into temp, not value
//if (size != 0) {
// delete[]temp;
//}
size = strlen(value);
return *this;
Rewritten to solve this problem, as well as release the original string, and check for value == nullptr:
char *oldString = value == nullptr ? "" : value;
int newSize = strlen(oldString) + s.length();
char *newString = new char[newSize + 1];
strcpy(newString, oldString);
strcat(newString, s.getValue());
delete [] value;
value = newString;
size = newSize;
return *this;
your problem is that you are trying to change what you pointer points to be using a pointer and not pointer to pointer.
when you are using the new operator your pointer simply gets new adress at the heap and than the assignment you did before(char * temp = value) is irelvent.
beacuse temp gets the adress pointed by value and not value adress, than any modification on temp adress will not effect value.
what you really wanna do is :
char * temp = new char[size]
//modify temp(add the strings)
//change value to hold the modified string
value = temp;
you can also do that :
char ** temp = &value;//now temp holds value's address.
*temp = new char[size];
//modify temp will modify value, but you need to derefrence before each use.
update
you are trying to copy a larger string temp into value which casues overflow (its a good practise to use strcpy_s/strcat_s beacuse they cannot copy more than the length you give them, that should be the size of dest).
link to strcpy/strcpy_s doc :
http://en.cppreference.com/w/c/string/byte/strcpy
http://en.cppreference.com/w/c/string/byte/strcat
what you should do is :
char * temp = new char[size];
//strcpy_s(dest, length of dest, src)
strcpy_s(temp , sizeof temp, value);//copy value to temp
strcat_s(temp, sizeof temp, s.getValue());
if(value != nullptr)
delete [] value;
value = temp;

trying to add 2 char arrays in different objects via operator+ overloading

I seem to be having tons of difficulty getting this addition operator overload to work for my objects. I've scoured the net and can't quite figure out what it is I'm doing wrong. Basically its supposed to be overloaded to concatenate 2 char arrays. Everything I try causes either a crash or a random jumble of characters.
I'm new to operator overloading, so maybe I'm utilizing it wrong.
Its called with:
String myString1, myString2;
std:: cout << "\nYour strings added are: " << myString1 + myString2;
And in the header file...
String operator+(String);
Here's the relevant code:
String String::operator+(String rhs){
String result;
int i = length;
for(int x = 0; x < length; x++)
{
result.ch[x] = ch[x];
std::cout << result.ch[x];
}
std:: cout << " ";
for (int j = 0; rhs.ch[j] != '\0'; ++i, ++j)
{
result.ch[i] = rhs.ch[j];
std::cout <<result.ch[i];
}
return result;
}
I'll provide full source code if needed. Everything else works perfectly though.
.hpp:
#include<iostream>
#include<string>
using std::istream;
using std::ostream;
const int default_size = 256;
class String
{
public:
// constructors
String();
String(const char ch, const int default_size);
String(const String& rhs, int cap = default_size); // copy constructor
// accessor functions
void getLength(String str);
void outPut(String str);
void findChar(String str);
// destructor
~String (); // destructor
// mutator functions
void getInput(String str);
// friend I/O function overloads
friend std::istream& operator>>(std::istream&, const String& str);
friend std::ostream& operator<<(std::ostream&, const String& str);
// operator overloads
String operator+(String str);
private:
int strLength, length;
int capacity;
char ch[default_size];
char *s; };
and .cpp
// String.cpp
#include "String.hpp"
#include<iostream>
// default constructor
String::String()
{
}
// char constructor
String::String(const char ch, const int default_size)
{
capacity = default_size;
s = new char[capacity];
s[0] = ch;
s[1] = '\0';
strLength = 1;
}
//copy constructor
String::String(const String& rhs, const int cap)
{
// Check if string capacity is shorter than length
if (cap <= rhs.strLength)
capacity = rhs.strLength + 1;
else
capacity = cap;
s = new char[capacity];
// Copy chars to string
for (length = 0; rhs.s[length] != '\0'; ++length)
{
s[length] = rhs.s[length];
}
s[length] = '\0';
}
// destructor
String::~String()
{
strLength = 0;
delete [] s;
}
// overloaded io operatiors
// Outputs string with << operator
ostream& operator<<(ostream& out, const String& str)
{
out << str.s;
return out;
}
// Inputs string with >> operator
istream& operator>>(istream& in, const String& str)
{
in >> str.s;
return in;
}
// gets users input
void String::getInput(String str)
{
std:: cout << "Please enter a string.\n";
std:: cin.getline(ch, default_size);
}
// getLength
void String:: getLength(String str)
{
size_t strLength = strlen(str.ch);
length = strLength;
std:: cout << "The length is " << strLength << ".\n";
}
// output
void String:: outPut(String str)
{
std:: cout << "\nYou entered.\n";
for(int x = 0; x < str.length; x++)
{
std:: cout << ch[x];
}
std:: cout << "\n";
}
// user enters a character, this provides the location(s)
void String:: findChar(String str)
{
char * charSearch;
char s;
std:: cout << "\nPlease enter a character to search for. \n";
std:: cin >> s;
std:: cout << "\n";
charSearch = strchr(ch, s);
while(charSearch != '\0')
{
std:: cout << "Found at: " << charSearch-ch+1 << "\n" ;
charSearch = strchr(charSearch+1, s);
}
std::cin.ignore();
}
// OPERATOR OVERLOADS---------------------------------------------------
// Addition operator
// adds the right hand object to the lefthand object
String String::operator+(String rhs)
{
String result;
int i = length;
for(int x = 0; x < length; x++)
{
result.ch[x] = ch[x];
std::cout << result.ch[x];
}
std:: cout << " ";
for (int j = 0; rhs.ch[j] != '\0'; ++i, ++j)
{
result.ch[i] = rhs.ch[j];
std::cout <<result.ch[i];
}
std::cout << "\nHere is result.ch: ";
for(int z = 0; result.ch[z] != '\0'; z++)
{
std::cout << result.ch[z];
}
return result;
}
You have more problems than the concatenation, and I doubt that everything else "works perfectly".
Your default constructor doesn't initialise anything.
Even String s; std::cout << s; shouldn't work, and neither should String s; std::cin >> s;.
You don't have an assignment operator.
{String s1; String s2; s2 = s1;} will most likely crash.
You have both a pointer s and an array ch.
You store data in s, but some code uses ch instead.
You need to make up your mind.
(And don't use the same name for parameters and local variables as you do for members.)
You have both strLength and length, and use them seemingly at random.
There's more undefined behaviour in your code than anyone can be bothered to list.
Your best road ahead is probably to throw the code away and start over.