StringBuilder Class in C++ not working properly - c++

I'm working on an assignment to create a class called StringBuilder that is used for fast string concatenation. I'm supposed to store strings in a dynamic array and have methods such as Append(string) which adds a new string to the dynamic array. The method I'm currently struggling with is GetString() that creates a single string on the heap that is the length of all the strings in the dynamic array that have been added thus far.
the code I have so far is:
okay my main problem is my GetString() function prints out hello over and over again until I force quit the program in Xcode. I don't understand what inside that method is making that happen.
My header file:
#pragma once
#include <string>
using namespace std;
class StringBuilder
{
public:
StringBuilder();
//~StringBuilder();
void GetString();
void AppendAll(string*, int);
void Length();
void Clear();
void Append(string userString);
void DoubleArray(string*& allWords, int newCapacity);
private:
string* p_array;
int capacity = 5;
};
my .cpp file :
#include "StringBuilder.hpp"
#include <iostream>
#include <string>
using namespace std;
----------
void StringBuilder::Append(string userString)
{
int nextWordPosition = 0;
for(int i=0; i < capacity ; i++)
{
p_array[i] = userString;
cout << p_array[i] << endl;
nextWordPosition +=1;
if(capacity == nextWordPosition)
{
capacity *=2;
DoubleArray(p_array, capacity * 2);
}
}
nextWordPosition++;
}
void StringBuilder::DoubleArray(string*& allWords, int newCapacity)
{
string* p_temp = new string[newCapacity];
for(int i =0; i < newCapacity / 2; i++)
{
p_temp[i] = allWords[i];
}
delete[] allWords;
allWords = p_temp;
}
void StringBuilder:: GetString()
{
for(int i=0; i < capacity ; i++)
{
cout << p_array[i]<< endl;
}
}
my main.cpp file :
#include <iostream>
#include <string>
#include "StringBuilder.hpp"
using namespace std;
int main()
{
string testString = "hello";
string test = "world!";
StringBuilder Builder1;
Builder1.Append(testString);
Builder1.Append(test);
Builder1.GetString();
return 0;
}

Related

Pass array to the derived class in C++

In Class Dim I created array G and I want to pass it to the derived Class PHYS_FIELD. Instead of output (0..9) it gives (0..0). I realize that it is just a new copy of G but I do not know how to do it correctly.
arr1.h:
#ifndef ARR1_H
#define ARR1_H
#include<iostream>
using namespace std;
template <class T> class arr1
{
public:
T* data;
size_t size;
arr1(const size_t isize)
{ size=isize;
data = new T[size];
}
T & operator ()(size_t const index)
{ return data[index]; }
};
#endif /*ARR1_H */
dim.h:
#ifndef DIM_H
#define DIM_H
#include "arr1.h"
class DIM {
public:
DIM();
protected:
int N;
};
#endif /* DIM_H */
dim.cpp:
#include "arr1.h"
#include "dim.h"
using namespace std;
DIM :: DIM()
{
N=10;
arr1<double> G(N);
for (int i=0; i<N; i++)
G(i)=i;
};
phys_field.h:
#ifndef PHYS_FIELD_H
#define PHYS_FIELD_H
#include "dim.h"
#include "arr1.h"
class PHYS_FIELD : public DIM {
public:
PHYS_FIELD();
arr1<double> G;
};
#endif /* PHYS__FIELD_H */
phys_field.cpp:
#include "dim.h"
#include "phys_field.h"
#include <arr1.h>
using namespace std;
PHYS_FIELD :: PHYS_FIELD(): G(N) {
cout<< " from phys_field.cpp "<<endl;
cout<<N<<endl;
for (int i=0; i<N ; i++)
cout<<i<<" "<<G(i)<<endl;
};
main.cpp:
#include "dim.h"
#include "phys_field.h"
using namespace std;
int main(int argc, char* argv[]){
PHYS_FIELD *F= new PHYS_FIELD();
return 0;
}
modify class arr1 and add a constructor that accepts zero parameters (this way we can declare arr1 G and later build it in DIM::DIM constructor
arr1()
{
}
class DIM:
protected:
arr1<double> G; //I've moved G from the constructor so that PHYS_FIELD can inherit it directly
DIM::DIM()
{
N=10;
G = arr1<double>(N);
for (int i=0; i<N; i++)
G(i)=i;
};
class PHYS_FIELD
remove arr1<double> G; from PHYS_FIELD header so that it doesn't hide the G inherited from DIM
PHYS_FIELD::PHYS_FIELD() { //removed G(N)
cout << " from phys_field.cpp " << endl;
cout << N << endl;
for (int i=0; i<N; i++)
cout << i << " " << G(i) << endl;
};
Is this what you are looking for?

Program stops working when class member function executes

I know there is something wrong with the class member functions because I comment everything in them out and the program will run fine but when I uncomment anything it stops working. The constructor runs fine as well.
Here is my CharArray.h file:
#ifndef CHARARRAY_H
#define CHARARRAY_H
class CharArray
{
private:
char * pArray;
int iSize;
public:
CharArray(int size)
{
char *pArray = nullptr;
iSize = size;
pArray = new char[iSize];
pArray = '\0';
}
void setItem (int loc, char ch);
char getItem (int loc);
~CharArray()
{
delete [] pArray;
}
};
#endif // CHARARRAY_H
Here is my member functions:
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdio>
#include "CharArray.h"
using namespace std;
void CharArray::setItem (int loc, char ch)
{
pArray[loc] = ch;
cout << pArray[loc] << endl;
return;
}
char CharArray::getItem (int loc)
{
char c;
c = pArray[loc];
return c;
}
And here is my main file:
#include <iostream>
#include <iomanip>
#include "CharArray.h"
using namespace std;
int main()
{
CharArray myChar (5);
int size;
char cstr[10] = "Drew";
myChar.setItem(1, 'A');
char c = myChar.getItem(5);
cout << c << endl;
return 0;
}
Your first problem is in the constructor:
CharArray(int size)
{
char *pArray = nullptr; // <-- unrelated to the pArray in the object!
iSize = size;
pArray = new char[iSize];
pArray = '\0'; // <-- we just lost the handle to new array
}
That last line should instead be:
*pArray = '\0';
Also, it would be better to use a more modern constructor style such as this:
CharArray(int size)
: pArray(new char[size]),
iSize(size)
{
*pArray = '\0';
}

how to reverse char array using class member pointer?

im tryin to reverse an array using pointer which is a class member:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class my_string
{
char* ptr;
int size;
public:
my_string(){};
my_string(char* str) : ptr(str),size(strlen(ptr)){};
char* getstr () {return ptr;};
void reverse();
int find (char);
void print();
};
void my_string::reverse()
{
int size2=size;
for (int i=0;i<(size/2);i++)
{
char tmp=ptr[i];
ptr[i]=ptr[size2-1];
ptr[size2-1]=ptr[i];
size2--;
}
}
int my_string::find(char c)
{
for (int i=0;i<size;i++)
{
if (ptr[i]==c)
return i;
}
return -1;
}
void my_string::print()
{
for (int i=0;i<size;i++)
cout<<ptr[i];
cout<<endl;
}
int main()
{
my_string s1("abcde");
s1.print();
s1.reverse();
s1.print();
}
im not gettin any errors but the reverse function is surely not working.
can someone please explain to me why?
*this is an homework assignment asking me not to use dynamic allocation or strings (for now).
You didn't mention not being able to use standard library algorithms, so
std::reverse(ptr, ptr+size);
You can use standard algorithm std::reverse declared in header <algorithm>.
For example
std::reverse( ptr, ptr + size );
But if you want to do it yourself then the function could look the following way
void my_string::reverse()
{
for ( int i = 0; i < size/2; i++ )
{
char tmp = ptr[i];
ptr[i] = ptr[size-1-i];
ptr[size-1-i] = tmp;
}
}
A test program
#include <iostream>
#include <cstring>
int main()
{
char s[] = "123456789";
char *ptr = s;
int size = std::strlen( ptr );
std::cout << s << std::endl;
for ( int i = 0; i < size/2; i++ )
{
char tmp = ptr[i];
ptr[i] = ptr[size-1-i];
ptr[size-1-i] = tmp;
}
std::cout << s << std::endl;
}
Output is
123456789
987654321

Fail to store values to the list

It seems the attribute test aisbn is successfully storing the data invoking setCode(), setDigit(). But The trouble starts failing while I attempt these values to store into list<test> simul
The list attribute takes the value of digit after setDigit() but the code. How can I put both code and digit into the list attribute? I can't see where the problem is. The code:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[i] = other.code[i];
}
//set up the private values
void setCode(const string &temp, const int num);
void setCode(const string &temp);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, const int num)
{
if((int)code.size() <= num)
{
code.resize(num+1);
}
code[num] = temp[num];
}
void test::setCode(const string &temp)
{
code = temp;
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
const string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
cout << contents << '\n';
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
It looks like you are having issues with your for loop, you need to modify your for loop like so:
for(testitr = simul.begin(); testitr !=simul.end(); testitr++)
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^
although, push_back does not invalidate iterators for std::list I think it is more readable to set the iterator where you are using it. Based on your response you also need to modify the copy constructor:
test(const test &other): code(other.code), digit(other.digit) {}
^^^^^^^^^^^^^^^^
how about using the vector
std::vector<test> simul;
for(int i=0; i < (int)contents.length(); i++)
{
aisbn.setCode(contents);
aisbn.setDigit(count+1);
simul.push_back(aisbn);
count++;
}
iterators, pointers and references related to the container are invalidated.
Otherwise, only the last iterator is invalidated.

c++ Expression: string subscript out of range

When I try debugging the code, it runs into the debugging error "c++ Expression: string subscript out of range"
Pretty sure the problem was brought while calling setCode().
How do I fix the code inside setCode()?
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <list>
using namespace std;
class test
{
private:
string code;
int digit;
public:
//constructor
test(): code(""), digit(0) { }
//copy constructor
test(const test &other):
digit(other.digit)
{
for(unsigned int i=0; i < code.length(); i++)
code[digit] = other.code[digit];
}
//set up the private values
void setCode(const string &temp, const int num);
void setDigit(const int &num);
//return the value of the pointer character
const string &getCode() const;
const unsigned int getDigit() const;
};
const string& test::getCode() const
{
return code;
}
const unsigned int test::getDigit() const
{
return digit;
}
void test::setCode(const string &temp, int num)
{
code[num] = temp[num];
}
void test::setDigit(const int &num)
{
digit = num;
}
int main()
{
string contents = "dfskr-123";
test aisbn;
list<test> simul;
list<test>::iterator testitr;
testitr = simul.begin();
int count = 0;
cout << contents << '\n';
aisbn.setCode(contents, count);
aisbn.setDigit(count);
simul.push_back(aisbn);
count++;
/*for(; testitr !=simul.end(); simul++)
{
cout << testitr->getCode() << "\n";
}*/
}
When you create an instance of the test class, the string inside it is empty. This means that whenever you do e.g. code[something] you will be out of range. It doesn't matter what the index is.
You either need to set the string to a certain length from the start, and make sure that the index is within the range. Or to make sure that the index is within range by dynamically extending the string when needed.
You have to make sure that when this statement executes:
code[num] = temp[num];
both code and temp are at least of size num + 1.