I have a problem with my custom string operator += so that if I wanted to add a const char* to my custom string String, then it wouldn't add it, it would just be the String. I can get it to work with other custom String objects but not with c strings.
code in String.cpp
String::String(){
length =0;
capacity = 1024;
myStr = new char[0];
}
String::String (const String& s)
{
length = s.getLength();
myStr = new char[length];
for (unsigned j=0; j < length; j++){
myStr[j] = s[j];
}
}
String::String(char c){
length = 1;
myStr = new char(c);
}
String::String(const char* val){
if(val!= nullptr){
int counter = 0;
while(val[counter]!='\0')counter++; //Find length of the char array
length= counter;
myStr = new char[counter];
for(int i =0;i<counter;i++){
myStr[i]=val[i];
}
}else{
length = 1;
myStr = new char[length];
myStr[0] = '\0';
}
}
ostream& operator<< (std::ostream& os, const String& s)
{
os<<s.myStr;
return os;
}
istream& operator>> (std::istream& is, String& s)
{
char* c = new char[1000];
is >> c;
s = String(c);
delete[] c;
return is;
}
String::~String(){
delete[] myStr;
}
int String::getIndex(char getInd) const {
for(int i = 0;i<length;i++){
if(myStr[i]==getInd){
return i;
}
}
}
unsigned String::getLength() const{
return length;
}
String& String::operator+= (const String& s){
unsigned len = length+s.getLength();
char* str=new char[len];
for(int i = 0;i<length;i++){
str[i]=myStr[i];
}
for(int i = 0;i<s.length;i++){
str[length+1]=s[i];
}
delete myStr;
length = len;
myStr= str;
return *this;
}
String& String::operator+=(const char *c) {
unsigned l =0;
while(c[l] !='\0'){
l++;
}
unsigned len =length+l;//new length of new string
char* str = new char[len];
for(int i = 0;i<getLength();i++) {
str[i] = myStr[i];
}
for(int j = 0; j<l;j++){
str[len+j]=c[j];
}
delete myStr;
length = len;
myStr = str;
return *this;
}
String& String::operator=(const String& s){
if(this == &s){
return *this;
}
delete myStr;
length = s.getLength();
myStr = new char[length];
for(int i = 0;i<length;i++){
myStr[i]=s[i];
}
}
char& String::operator[](unsigned i){
if(i>=length) throw 1;
return myStr[i];
}
char String::operator[] (unsigned j) const
{
if (j >= length) throw 1;
return myStr[j];
}
Code in main.cpp
int main() {
char c[] = {'h','i'}
String add = "iscool";
String str="strworks";
str+=add;
str+=c;
cout<<str<<endl;
return 0;
}
The outcome for this program right now in the console is:
strworks
I am not sure what to change about the const char* c += operator function, i believe this is where the error is. I am also trying to use this string in a getline function but I try getline(file,String& s, ','); there is an error and I would appreciate any tips on how to implement the getline function with my new String class. The String str should be histrworks in the second line of output, however it is blank. I have already re written the logic of the += operator but it doesn't seem to be working. Let me know if there is any more information I need to give out that could assist you guys in finding the problem. The ultimate goal of this program is to read in a file of movie reviews and train an algorithim to find out if the review is positive/negative.
Related
#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 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 != ©)
{
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.
I'm having trouble with dynamic allocation.In my code
am I initializing the dynamic array correctly?.
When I try to write + operator member for my class String, it doesn't return what I want. Any guidance to the correct path would be great.
Ex.
String s1("One");
String s2("Two");
String s3 = s1+ s1;
cout <<s3;
//Output is OneTwo
cout <<s1;
//OUtput is OneTwo.
Also I don't understand why I can not add delete[] buf into my constructor.
class String{
public:
String (const char *s =""):buf(new char[strlen(s)]){
buf = strdup(s);
};
String (const String &s):buf(new char[strlen(s.buf)]){
buf = strdup(s.buf);
delete []buf;
};
String operator =(const String &s){
return buf =strdup(s.buf);
};
char & operator [] (int index){
assert(inBounds(index));
return buf[index];
};
int size()
{
return strlen(buf);
};
String operator + (const String s){
delete []buf;
char *temp = new char[strlen(buf)+strlen(s.buf)];
///NEed to ask about t*his acan get this operator tor work
cout<< s.buf;
return temp;
};
String operator += (const String s){
strcpy(buf + strlen(buf),s.buf);
return buf;
};
void print(ostream & out){
out << buf;
};
void read (istream & in){
in >> buf;
};
~String(){
//delete [] buf;
};
private:
bool inBounds(int x){
return x >= 0 && x < strlen(buf);
};
static int strlen(const char *s){
int len =0;
for(int i=0;s[i] != '\0';i++)
len++;
return len;
};
static char *strcpy(char *dest,const char *src){
int i=0;
for(;(dest[i] = src[i]); ++i);
dest[i] = '\0';
return dest;
};
static char *strdup(const char *s){
char * buf;
buf = new char[strlen(s)+1];
int i=0;
for(;s[i] != '\0';i++)
buf[i] = s[i];
buf[i] = '\0';
return buf;
}
char * buf;
};
Your first constructor
String (const char *s ="") : buf(new char[strlen(s)]){
buf = strdup(s);
}
first allocates a buffer that's one character too small, then it throws it away by pointing bufto the result of strdup – a memory leak.
You want
String (const char *s ="") : buf(new char[strlen(s) + 1]){
strcpy(buf, s);
}
or
String (const char *s ="") : buf(strdup(s))
{
}
Your second constructor
String (const String &s) : buf(new char[strlen(s.buf)]){
buf = strdup(s.buf);
delete []buf;
};
has the same problem with a memory leak, and has the added complication that you immediately deallocate buf.
You want something like
String (const String& s) : buf(strdup(s.buf))
{
}
Your + deallocates buf, allocates an uninitialised (and too small) buffer, prints buf(which is undefined) and then returns a String made from the uninitialised buffer.
The addition operator should not modify *this; it should use += and look like
String operator+ (const String& s) const
{
String result = *this;
result += s;
return result;
};
Which leaves +=, which needs to reallocate buf to be large enough to hold the result.
I'll leave it as an exercise.
And reimplementing standard library functions using the standard name is very confusing.
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.
I have an assignment that I need to create a custom C type string class in C++. I am having trouble getting this to work. Currently my code crashes with a run time error right at the start. I also know many of my function are wrong but I want to get the member functions sorted before I go on and fix the other functions. Bear in mind that all the function prototypes were given to us and I can not change them. I need to write the 'guts' so to speak.
What is wrong with my constructor for a start?
#include <iostream>
#include "tstr.h"
using namespace std;
//Default constructor to initialize the string to null
TStr::TStr() {
strPtr = 0;
strSize = 0;
}
//constructor; conversion from the char string
TStr::TStr(const char *str) {
int i=0;
while (str[i] != '/0') {
strPtr = new char [strlen(str)+1];
for (i=0; i <strSize;++i) {
strPtr[i] = str[i];
}
++i;
}
strSize = i;
}
//Copy constructor
TStr::TStr(const TStr&) {
}
//Destructor
TStr::~TStr() {
if (strPtr) {
delete[] strPtr;
}
}
//subscript operators-checks for range
char& TStr::operator [] (int i) {
assert (i >= 0 && i < strSize);
return strPtr[i];
}
const char& TStr::operator [] (int i) const {
assert (i >= 0 && i < strSize);
return strPtr[i];
}
//overload the concatenation oprerator
TStr TStr::operator += (const TStr& str) {
//this->strPtr += str.strPtr;
//this->strSize += str.strSize;
return *this;
}
//overload the assignment operator
const TStr& TStr::operator = (const TStr& str) {
if (this != &str) {
delete[] strPtr;
strPtr = new char[strSize = str.strSize];
assert(strPtr);
for (int i=0; i<strSize; ++i) {
strPtr[i] = str.strPtr[i];
}
}
return *this;
}
//overload two relational operators as member functions
bool TStr::operator == (const TStr& str) const {
return (strPtr == str.strPtr && strSize == str.strSize);
}
bool TStr::operator < (const TStr& str) const {
return (strPtr < str.strPtr && strSize < str.strSize);
}
//the length of the string
int TStr::size() {
return strSize;
}
Thanks for any replies/help! :)
EDIT 1: Okay the constructor is now working but I am still getting a runtime error and I'm 90% sure it is to do with my overloaded += operator. It looks fine though and compiles okay. What am I missing?
(Note: Only small changes have been made to the above code, but let me know if you want to see the whole lot.)
//overload the concatenation oprerator
TStr TStr::operator += (const TStr& str) {
for(int i = 0; i < strSize; ++i) {
strPtr[i] += str.strPtr[i];
}
return *this;
}
EDIT 2: Okay this what I have now. Compiles fine but doesn't actually add the two strings together with the += like it should. Anyone got any ideas?
//overload the concatenation oprerator
TStr TStr::operator += (const TStr& str) {
char *buffer = new char[strSize + str.strSize + 1];
strcpy(buffer, strPtr);
strcat(buffer, str.strPtr);
delete [] strPtr;
strPtr = buffer;
return *this;
}
//overload the assignment operator
const TStr& TStr::operator = (const TStr& str) {
if (this != &str) {
delete[] strPtr;
strPtr = new char[strSize = str.strSize];
assert(strPtr);
for (int i=0; i<strSize; ++i) {
strPtr[i] = str.strPtr[i];
}
}
return *this;
}
To summarize:
i is reinitialized in the pointed line
strSize is used uninitialized(God knows what's there) in the same line as above; should be strSize = strlen(str);
the string terminator chracter is wrong
as the man was saying it's kind of a mess
int i=0;
while (str[i] != '\0') { // as Seth pointed out it's '\0'
strPtr = new char [strlen(str)+1];
for (i=0; i <strSize;++i) { // i is reinitialized here !!!
strPtr[i] = str[i];
}
++i;
}
strSize = i;
To be more constructive:
// as James perfectly illustrated
TStr::TStr(const char *str)
{
int i = 0;
while (str[i] != '\0')
++i;
strSize = i;
strPtr = new char [i+1];
while (*strPtr++ = *str++); // with a bit of k&R
}
//overload the concatenation oprerator
TStr TStr::operator += (const TStr& str) {
for(int i = 0; i < strSize; ++i) {
strPtr[i] += str.strPtr[i];
}
return *this;
}
Problems:
you want to concatenate strings meaning you need a bigger storage to hold both strings together meaning you need to reallocate your char array and you don't do that
you don't update the size of your string, it's bigger now isn't it?
strPtr[i] += str.strPtr[i]; what you're doing here is really adding integers stored on 8 bits
Solution(I'm absolutely sure it can be improved but should get you started):
//overload the concatenation oprerator
TStr TStr::operator += (const TStr& str) {
unsigned int i = 0;
while (str.strPtr[i] != '\0')
++i;
// allocate the new buffer
char* newStr = new char[i + strSize + 1];
// copy the old string
unsigned int j = 0;
for (; j < strSize; ++j)
{
newStr[j] = strPtr[j];
}
// update the size
strSize += i;
// release the old buffer
delete[] strPtr;
// finally concatenate
char* copyPtr = newStr + j;
while(*copyPtr++ = *(str.strPtr)++);
// and swap the pointers
strPtr = newStr;
return *this;
}
Your ctor is pretty much a mess.
You use i for two different things -- at the same time. You also copy the entire contents of str into strPtr once for each character in str.
Basically, you have to decide, are you going to use the C run-time library or not?
Using it:
TStr::TStr(const char *str)
{
strSize = strlen(str);
strPtr = new char [strSize+1];
strcpy(strPtr, str);
}
not using it:
TStr::TStr(const char *str)
{
int i = 0;
while (str[i] != '\0')
++i;
strSize = i;
strPtr = new char [i+1];
for (i=0; i < strSize;++i)
strPtr[i] = str[i];
}
Why two loops one inside the other? You're thinking too hard, to copy characters from one string to another you only need one loop. Here's some code
//constructor; conversion from the char string
TStr::TStr(const char *str) {
strSize = strlen(str);
strPtr = new char [strSize+1];
for (int i=0; i <strSize; ++i) {
strPtr[i] = str[i];
}
strPtr[strSize] = '\0';
}
Much simpler!