So I've been trying to write string class for learning purposes, and when I tried to overload the + operator I got the strangest problem: The array I've been trying to crate had 4 extra spaces, no matter what amount I tried to create it with (Also the entire thing crashed horribly). So for example, when I wrote:
newStr.length = this->length + other.length;
newStr.str = new char[newStr.length+1];
newStr.str kept having 4 more spaces than this->length + other.length + 1, and when I just left it at newStr.str = new char[1], the array still have been created with 5 cells for some reason. I've tried to write the entire class without ever creating "int length" but that didn't work, nor did any my attempts to isolate the array creation from class(It works normally when not in class and not working with these specific class objects so it's not some visual studio bug). I've tried everything I could think of, though I'm new at this and most likely missed something. Could anybody please help me? Here's the entire code for reference, it's not that long:
#include <iostream>
#define DEBUG
using namespace std;
class MyString
{
private:
char* str;
int length;
public:
MyString()
{
str = nullptr;
length = 0;
}
MyString(const char *str)
{
length = strlen(str);
this->str = new char[length + 1];
for (int i = 0; i < length; i++)
{
this->str[i] = str[i];
}
this->str[length] = '\0';
}
~MyString()
{
delete[] str;
}
MyString& operator =(const MyString& other)
{
if (this->str != nullptr) delete[] str;
length = other.length;
this->str = new char[length + 1];
for (int i = 0; i < length; i++)
{
this->str[i] = other.str[i];
}
this->str[length] = '\0';
return *this;
}
MyString operator +(const MyString& other)
{
MyString newStr;
newStr.length = this->length + other.length;
newStr.str = new char[newStr.length+1];
for (int i = 0; i < this->length; i++)
{
newStr.str[i] = this->str[i];
}
for (int i = this->length; i < newStr.length; i++)
{
newStr.str[i] = other.str[i-strlen(this->str)];
}
newStr.str[newStr.length] = '\0';
return newStr;
}
void Print()
{
cout << str;
}
};
int main()
{
MyString a("TESTY");
MyString b("WUBBA");
a = a + b;
a.Print();
return 0;
}
Related
I need to assign one object to another object by overloading the "=" operator. Wrote code, but it doesn`t work. What could be the problem?
CString operator =(const CString& obj) {
CString temp;
temp.c = obj.c;
temp.length = obj.length;
return temp;
}
Full code:
#include <iostream>
using namespace std;
class CString {
private:
char* c;
int length;
public:
CString() {
length = 0;
c = new char[1];
*c = 0;
}
CString(const char* s) {
length = strlen(s);
c = new char[length + 1];
for (int i = 0; i < length; i++) { c[i] = s[i]; }
c[length] = '\0';
}
CString(int leng, char* payload) {
length = leng;
c = payload;
}
~CString() {
delete[] c;
}
CString operator +(const CString& b) {
int newlength = length + b.length;
char* newstr = new char[newlength + 1];
strcpy(newstr, c);
strcpy(newstr + length, b.c);
return CString(newlength, newstr);
}
void Show(void) { cout << c << endl; }
CString operator =(const CString& obj) {
CString temp;
temp.c = obj.c;
temp.length = obj.length;
return temp;
}
};
int main() {
CString a("First, ");
CString b("Second.");
a = c;
return 0;
}
First comment: as long as you specify the non-trivial destructor, and - even more imortant - the copy assignment, you need to specify the copy constructor as well.
Next, the copy operator shall return the reference to *this: this allows you to employ chaining like that: 'a = b = c;'
The copy-assignment may look like that:
CString& operator =(const CString& obj) {
delete[] c;
length = obj.length;
c = new char[length + 1];
for (int i = 0; i <= length; i++) { c[i] = obj.c[i]; }
return *this;
}
However, taking my first comment into consideration, you may implement the copying just once:
CString(const CString& obj) {
length = obj.length;
c = new char[length + 1];
for (int i = 0; i <= length; i++) { c[i] = obj.c[i]; }
}
CString& operator =(const CString& obj) {
CString tmp(obj)
swap(length, tmp.length);
swap(c, tmp.c);
return *this;
}
In addition your constructor CString(int leng, char* payload) looks suspicious. Do you realize that the c-string has to be allocated with new (and will be deleted in destructor)?
it's course's one of project and its goal is to make fully-worked MyString Class. Until made destructor method, it was worked well. but in main.cpp, when i tried to use these method i made, it occurs heap corruption. i thought the problem comes up from order of calling destructor but i couldn't figure out where it occurred.
try to check allocated memory(reverse called order)
processing without destructor method(it works)
main.cpp
void main() {
MyString a = MyString("HELLOMYNAMEIS");
char ab[10] = "thisiskrw";
MyString c = ab;
a = a + c;
cout << a;
}
MyString.cpp
MyString::~MyString() {
delete[] str_;
}
MyString operator+(const MyString& lhs, const MyString& rhs) {
MyString a(lhs);
MyString b(rhs);
a += b;
cout << a;
return a;
}
MyString& MyString::operator+=(const MyString& str) {
int i = 0;
if (this->capacity() < (this->length_ + str.length_)) {
char* temp = new char[this->length_ + str.length_+1];
memset(temp, '\0', this->length_+str.length_+1);
strcpy(temp, this->str_);
for (int i = 0; i < str.length_; i++) {
temp[(this->length_) + i] = str.str_[i];
}
temp[this->length_ + str.length_] = '\0';
strcpy(this->str_,temp);
this->length_ = this->length_ + str.length_;
delete[] temp;
}
else {
for (int i = 0; i < str.length_; i++) {
this->str_[(this->length_) + i] = str.str_[i];
}
this->length_ = this->length_ + str.length_;
}
return *this;
}
it will print string inside MyString object.
You forgot to write this->str_ = temp; anywhere. You just try to write the longer string into the shorter space.
strcpy(this->str_,temp);
this->length_ = this->length_ + str.length_;
delete[] temp;
Should be
delete [] this->str_;
this->str_ = temp;
Firstly here is my code:
header:
#pragma once
#include <iostream>
using namespace std;
class CString
{
private://Main attribute
char* str;
private:// Aux attribute
int len;
public:
//constructor and destructor
CString(char* x);
CString() { len = 0; str = NULL; }
~CString()
{
if (NULL != str)
delete[] str;
str = NULL;
}
//some operator
CString operator+(CString x);
CString operator+(char* x);
void operator=(CString x);
//operator() is to extract a part of other CString object
CString operator()(unsigned pos, unsigned c_len);
//operator[] return position of CString::str[pos]
char& operator[](unsigned pos);
//Ostream output
friend ostream& operator<<(ostream& os, CString x);
};
//to do char+CString
CString operator+(char* a, CString x);
header cpp code:
#include "CString.h"
CString::CString(char * x)
{
len = 0;
while(x[len])
len++;
str = new char[len];
for (int i = 0;i < len;i++)
str[i] = x[i];
if (str[len - 1] != '\0')
{
len++;
char* tmp;
tmp = new char[len];
for (int i = 0;i < len - 1;i++)
tmp[i] = str[i];
delete[]str;
str = tmp;
tmp = NULL;
str[len - 1] = '\0';
}
}
CString CString::operator+(CString x)
{
CString* result;
result = new CString;
result->len = this->len + x.len - 1;
result.str=new char[result.len];
for (int i = 0; i < this->len - 1;i++)
{
result->str[i] = this->str[i];
}
for (int i = 0, j = this->len - 1;i < x.len;i++, j++)
{
result->str[j] = x.str[i];
}
return *result;
}
CString CString::operator+(char * x)
{
return CString(*this+CString(x));
}
void CString::operator=(CString x)
{
str = new char[x.len];
for (int i = 0; i < x.len;i++)
str[i] = x.str[i];
len = x.len;
}
CString CString::operator()(unsigned pos, unsigned c_len)
{
CString* result;
result = new CString;
result->len = c_len;
result.str=new char[c_len];
for (int i = pos;i < pos + c_len;i++)
result->str[i - pos] = str[i];
return *result;
}
char& CString::operator[](unsigned pos)
{
if (pos < len - 1)
{
char* ptr;
ptr = this->str + pos;
return *ptr;
}
else
{
int o_len = len;
len = pos + 2;
char* tmp;
tmp = new char[len];
for (int i = 0;i < o_len;i++)
{
tmp[i] = str[i];
}
tmp[len - 1] = '\0';
delete[]str;
str = tmp;
tmp = NULL;
return *(str + pos);
}
}
ostream & operator<<(ostream & os, CString x)
{
os << x.str;
return os;
}
CString operator+(char * a, CString x)
{
return CString(CString(a) + x);
}
main:
CString a("string 1"), b = "Initialize " + a;
b[15] = '2'; cout << a + " - " + b << endl;
CString c = a + b;
cout << "String extracted from string \"" << c
<< "\" from position 3 with length of 6 is: \""
<< c(3, 6) << "\"" << endl;
Problem:
When I try to compile this program, there is no error, but still operator+(CString), operator(), and destructor seem to malfunction.
When I debug this program, my program triggered a breakpoint some where at line CString a("String 1"), b = "initilize " + a; I have no idea why. I am do not know if there is any problem for the rest of the program because I always get stuck at that line. SO if somebody can find out any other problem, please tell me, that will save me another day.
Btw, I just wonder at operator+(CString) and operator(), I have create a pointer then I use new and then I return that pointer, so that I have no change to delete that pointer, will it leave me an orphan memory? Since I have read another question about return a class object, I found out that if I use CString result and then return result, result would be destroyed before return. SO is there any better way to do that?
Summary:
1.My program triggered a breakpoint some where in the second line of main().
2.How to properly return a class object?
P.S: I am really bad at communicating and just have 1 year period of C/C++ learning. So if I have type some thing could give you a cancer, please forgive me.
Sincerely thank you.
So I'm trying to overload the += operator for a dictionary program assignment.
This is my function:
Definition& Definition::operator += (const String& input) {
String** temp;
temp = new String*[numDefs + 1];
temp[0] = new String[numDefs];
for (int i = 0; i < numDefs; i++) {
temp[i] = def[i];
}
temp[0][numDefs] = input;
delete[] def;
def = temp;
numDefs++;
return *this;
}
However when I try to put 'input' into 'temp' it doesn't seem to work. This is my String class function for allocating string to string:
String& String::operator=(const String& input) {
data = NULL;
(*this) = input.getData();
return *this;
}
and:
String& String::operator=(const char* input) {
if (data != input)
{
if (data != NULL)
{
delete[] data;
data = NULL;
}
data_len = strSize(input);
if (input != NULL)
{
data = new char[data_len + 1];
strCopy(data, input);
}
}
return *this;
}
Can't seem to find the problem.
There was an answer posted a minute ago that the user deleted and helped me, I changed the code to:
Definition& Definition::operator += (const String& input) {
String** temp;
int tempSize = numDefs + 1;
temp = new String*[tempSize];
for (int i = 0; i < numDefs; i++) {
temp[i] = new String;
temp[i] = def[i];
}
temp[numDefs] = new String;
(*temp[numDefs]) = input;
delete[] def;
def = temp;
numDefs = tempSize;
return *this;
}
Whoever it was, Thanks!
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.