When trying to compile the following code:
int main(){
Array<int> *testArray = new Array<int>(5);
testArray->initArray<int>(testArray);
testArray->printArray<int>(testArray);
return 0;
}
Using this template:
template<typename T>
class Array{
public:
Array(int size){
size = size;
data = new T[size];
};
Array<T> addData(T dataToAdd){
Array <T> *tmp = new Array <T> (this->size);
tmp = this->data;
Array <T> *newData = new Array<T> (this->size + 1);
for (int i = 0; i < this->size + 1; ++i){
if (i < this->size){
newData->data[i] = tmp[i];
}
else{
newData->data[i] = dataToAdd;
}
}
return newData;
};
void initArray(T arrayToInit){
for (int i = 0; i < this->size; ++i){
this->data[i] = i;
}
};
void printArray(T arrayToPrint){
ostringstream oss;
string answer = "";
for (int i = 0; i < arrayToPrint->size; ++i){
oss << arrayToPrint[i] + " ";
}
answer = oss.str();
cout << answer << endl;
};
private:
int size;
T* data;
};
I get the following error in my int main() :
"expected primary-expression before ‘int’"
for both of my function calls (initArray and printArray). I am fairly new to C++ and have little experience with templates in particular, any advice would be greatly appreciated. Thank you for your time.
EDIT: Thank you everyone for the responses and constructive criticism, I have made a great amount of progress thanks to everybody's help.
You don't need <int> to call the function in this case. (Thinking about std::vector<int>, you will write hoge.push_back(0) instead of hoge.push_back<int>(0).)
The arguments of Array::initArray and Array:;:printArray are also invalid and unneeded.
Fixed code (emits no compile errors/warnings, but not working properly):
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template<typename T>
class Array{
public:
Array(int size){
size = size;
data = new T[size];
};
Array<T> addData(T dataToAdd){
Array <T> *tmp = new Array <T> (this->size);
tmp = this->data;
Array <T> *newData = new Array<T> (this->size + 1);
for (int i = 0; i < this->size + 1; ++i){
if (i < this->size){
newData->data[i] = tmp[i];
}
else{
newData->data[i] = dataToAdd;
}
}
return newData;
};
void initArray(){
for (int i = 0; i < this->size; ++i){
this->data[i] = i;
}
};
void printArray(){
ostringstream oss;
string answer = "";
for (int i = 0; i < this->size; ++i){
oss << data[i] + " ";
}
answer = oss.str();
cout << answer << endl;
};
private:
int size;
T* data;
};
int main(){
Array<int> *testArray = new Array<int>(5);
testArray->initArray();
testArray->printArray();
return 0;
}
Here is the changed working code:
#include <string>
#include <iostream>
#include <cstdint>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template<typename T>
class Array{
public:
Array(int size){
size = size;
data = new T[size];
}
Array<T> addData(T dataToAdd){
Array <T> *tmp = new Array <T> (this->size);
tmp = this->data;
Array <T> *newData = new Array<T> (this->size + 1);
for (int i = 0; i < this->size + 1; ++i){
if (i < this->size){
newData->data[i] = tmp[i];
}
else{
newData->data[i] = dataToAdd;
}
}
return newData;
}
void initArray(Array<T>* arrayToInit){
for (int i = 0; i < this->size; ++i){
this->data[i] = i;
}
}
void printArray(Array<T>* arrayToPrint){
ostringstream oss;
string answer = "";
//for (int i = 0; i < arrayToPrint->size; ++i){
// oss << data[i] + " ";
answer = oss.str();
cout << answer << endl;
}
private:
int size;
T* data;
};
int main()
{
string s;
double d =9.0;
s=d;
Array<int> *testArray = new Array<int>(5);
testArray->initArray(testArray);
testArray->printArray(testArray);
return 0;
}
Changes carried out:
Template Instantiation happens when you declare the class.No need to again do it for its member functions.
Also no need to append ; after every member function definition, only needed for class definition.
Related
#include<iostream>
using namespace std;
class Text{
public:
~Text(){
delete data;
}
char* data{};
int mSize{};
void fill(char* stringInput) {
mSize = strlen(stringInput);
data = new char [mSize];
for (int i = 0; i < mSize; i++){
data[i] = stringInput[i];
}
}
};
class myString{
public:
explicit myString(int size){ // constructor
strAmount = size;
strings = new Text [size];
}
~myString(){ // destructor
delete[] strings;
}
void addString(char* input){
strings[filledAmount].fill(input);
filledAmount++;
}
void delString(int pos){
for ( int i = pos; i < filledAmount; i++){
swap(strings[i], strings[i+1]);
}
strings[filledAmount].data = nullptr;
strings[filledAmount].mSize = 0;
filledAmount--;
}
void eraseEverything(){
for ( int i = 0; i < filledAmount; i++){
strings[i].data = {};
strings[i].mSize = 0;
}
filledAmount = 0;
}
int maxString() const {
int index{};
for ( int i = 0 ; i < filledAmount; i++){
if (strings[i].mSize > strings[index].mSize){
index = i;
}
}
return index;
}
int charAmount(){
int counter{};
for(int i = 0 ; i < filledAmount; i++){
counter+=strings[i].mSize;
}
return counter;
}
double digitPercentage(){
int digitsAmount{};
for(int i = 0; i < filledAmount; i++){
for ( int j = 0; j < strings[i].mSize; j++){
if (isdigit(strings[i].data[j])){
digitsAmount++;
}
}
}
double digitPercent = (digitsAmount/(double)charAmount())*100;
return digitPercent;
}
int filledAmount{};
int strAmount{};
Text* strings;
};
void render_text(myString& obj) {
for (int k = 0; k < obj.filledAmount; k++) {
for (int i = 0; i < obj.strings[k].mSize; i++)
cout << obj.strings[k].data[i];
cout << endl;
}
cout << endl;
}
int main(){
myString a(5);
a.addString((char *) "zxc 1v1 forever shadow fiend");
a.addString((char *) "This is a string");
a.addString((char *) "12345");
a.addString((char *) "Hello");
a.addString((char *) "A1oha Dance");
render_text(a);
a.delString(1);
render_text(a);
int maxInd = a.maxString();
cout << "Max string :\n";
for (int i = 0; i < a.strings[maxInd].mSize; i++) {
cout << a.strings[maxInd].data[i];
}
cout << "\n\n";
}
Please help me find the crash point. I suppose it crashes in the destructor pole, but I still can't figure it out.
This is something like a self-written string class, the problem is that I can't find the place where the problems start.
I also have a thought that the destructor tries to delete too much memory from the heap so the compiler prevents it from doing that. Can I somehow change the size of the strings array?
I have fixed all your memory errors, with the help of address sanitizers
The main change here is:
Add copy constructors and copy assignment operators
Manually delete the last element in the function delString
Though that the code now works, it's not a true modern c++ style code. I highly recommend that your using std::string to replace your Text class. Use std::vector to replace the dynamic array. Then you will stay away from the pain of memory errors. The delString should be replaced with vector::erase,which is much neat than your hand write algorithm.
https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/container/vector
I strongly recommend rewriting the code with std::string and std::vector
#include <cstring>
#include <iostream>
using namespace std;
class Text {
public:
~Text() { delete[] data; }
char* data{};
int mSize{};
Text() = default;
Text(const Text& oth) {
mSize = oth.mSize;
data = new char[mSize];
std::copy(oth.data, oth.data + oth.mSize, data);
}
Text& operator=(const Text& oth) {
delete[] data;
mSize = oth.mSize;
data = new char[mSize];
std::copy(oth.data, oth.data + oth.mSize, data);
return *this;
}
void fill(char* stringInput) {
mSize = strlen(stringInput) + 1;
data = new char[mSize];
for (int i = 0; i < mSize; i++) {
data[i] = stringInput[i];
}
}
};
class myString {
public:
explicit myString(int size) { // constructor
strAmount = size;
strings = new Text[size];
}
myString(const myString& oth) {
strAmount = oth.strAmount;
strings = new Text[oth.strAmount];
for (size_t i = 0; i < strAmount; ++i) {
strings[i] = oth.strings[i];
}
}
myString& operator=(const myString& oth) {
delete[] strings;
strAmount = oth.strAmount;
strings = new Text[oth.strAmount];
for (size_t i = 0; i < strAmount; ++i) {
strings[i] = oth.strings[i];
}
return *this;
}
~myString() { // destructor
delete[] strings;
}
void addString(char* input) {
strings[filledAmount].fill(input);
filledAmount++;
}
void delString(int pos) {
for (int i = pos; i < filledAmount; i++) {
swap(strings[i], strings[i + 1]);
}
delete[] strings[filledAmount].data;
strings[filledAmount].data = nullptr;
strings[filledAmount].mSize = 0;
filledAmount--;
}
void eraseEverything() {
for (int i = 0; i < filledAmount; i++) {
strings[i].data = {};
strings[i].mSize = 0;
}
filledAmount = 0;
}
int maxString() const {
int index{};
for (int i = 0; i < filledAmount; i++) {
if (strings[i].mSize > strings[index].mSize) {
index = i;
}
}
return index;
}
int charAmount() {
int counter{};
for (int i = 0; i < filledAmount; i++) {
counter += strings[i].mSize;
}
return counter;
}
double digitPercentage() {
int digitsAmount{};
for (int i = 0; i < filledAmount; i++) {
for (int j = 0; j < strings[i].mSize; j++) {
if (isdigit(strings[i].data[j])) {
digitsAmount++;
}
}
}
double digitPercent = (digitsAmount / (double)charAmount()) * 100;
return digitPercent;
}
int filledAmount{};
int strAmount{};
Text* strings = nullptr;
};
void render_text(myString& obj) {
for (int k = 0; k < obj.filledAmount; k++) {
for (int i = 0; i < obj.strings[k].mSize; i++)
cout << obj.strings[k].data[i];
cout << endl;
}
cout << endl;
}
int main() {
myString a(6);
a.addString((char*)"zxc 1v1 forever shadow fiend");
a.addString((char*)"This is a string");
a.addString((char*)"12345");
a.addString((char*)"Hello");
a.addString((char*)"A1oha Dance");
render_text(a);
a.delString(1);
render_text(a);
int maxInd = a.maxString();
cout << "Max string :\n";
for (int i = 0; i < a.strings[maxInd].mSize; i++) {
cout << a.strings[maxInd].data[i];
}
cout << "\n\n";
return 0;
}
Having trouble with the printing copy constructors elements from Arr s to Arr s1 , also having troubles with << operator it doesn't work, please help cuz I am not pro just a student.
#include <iostream>
using namespace std;
class Arr {
private:
int size;
int *arr;
public:
Arr(int size,int *arr) {
this->size = size;
this->arr = new int [size];
for (int i = 0; i < size ; ++i) {
this->arr[i] = arr[i];
}
}
~Arr() {
delete[] arr;
}
Arr(const Arr &x) {
this->size = x.size;
this->arr = new int[x.size];
for (int i = 0; i < x.size; ++i) {
this->arr = x.arr;
}
}
Arr() : size(0),arr(0) {}
Arr(Arr &&x) {
this->size = x.size;
this->arr = new int[x.size];
for (int i = 0; i < x.size; ++i) {
this->arr = x.arr;
}
}
friend ostream &operator<<(ostream &out, const Arr &t) {
out << t.size;
for (int i = 0; i < t.size; i++) {
out << t.arr[i];
}
return out;
}
friend istream &operator>>(istream &in, Arr &t) {
in >> t.size;
for (int i = 0; i < t.size; ++i) {
in >> t.arr[i];
}
return in;
}
};
int main() {
int size = 3;
int arr [] = {1,2,3};
Arr s1(size,arr);
cin << s1;
cout<<s1;
Arr s(s1);
cout<<s; // not working at all
return 0;
}
You are writing
this->arr = x.arr;
in the copy constructor, rather than
this->arr[i] = x.arr[i];
That is, currently your code is copying the array pointer, not the elements of the array.
When you're debugging, first look over your code to make sure each part is doing what you want it to do and that you didn't make a typo like this. Then, if you don't find the problem, you can use a debugger like gdb to step through your code and monitor the values of the variables to make sure your program is doing what you'd like.
I want to write a program that can use a dynamic array.
A size is to be passed via the constructor and as soon as this size is reached, a new array is generated in which the previous values are copied into it.
For this, I overloaded the [] operator. The program seems to work at first glance.
But after I tried to implement an array with the size 100 and to save 20000 elements here, different numbers are output.
At the first run, more than 7000 numbers were displayed. After another run over 1800. However, never the desired 20000.
What could be the reason for this?
#include <iostream>
using namespace std;
template<class T>
class Container{
public:
T *dynamicArray;
private:
T *newArray;
int size;
public:
Container(int size){
this->size=size;
dynamicArray=new T[size];
}
T operator[] (unsigned long index){
if(index>size-1){
newArray=new T[size+(index-size)];
T i;
for(i=0; i<(size+(index-size)); i++){
newArray[i]=dynamicArray[i];
}
delete[] dynamicArray;
dynamicArray=newArray;
delete[] newArray;
}
return dynamicArray[index];
}
};
int main()
{
Container <int> dArray(100);
for(int i=1; i<20000; i++){
dArray.dynamicArray[i]=i;
cout << dArray.dynamicArray[i] << "\n";
}
return 0;
}
Thank you!
first , this code didn't call the overloaded [] operator function , its just using default operator [] of type T array , and it never allocate any memory , you can output at allocate memory position
dArray.dynamischesArray[i]=i;
cout << dArray.dynamischesArray[i] << "\n";
and there it some error logic in the overloaded [] operator function
T operator[] (unsigned long index){
if(index>size-1){
neuesArray=new T[size+(index-size)];
T i;
for(i=0; i<(size+(index-size)); i++){
neuesArray[i]=dynamischesArray[i];
}
delete[] dynamischesArray;
dynamischesArray=neuesArray;
//delete[] neuesArray; cannot deleted ,course error
size = index + 1; //keep size sync real size
}
return dynamischesArray[index];
}
this is modified code can be run correct :
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Container {
public:
T *dynamischesArray;
private:
T *neuesArray;
int size;
public:
Container(int size) {
this->size = size;
dynamischesArray = new T[size];
}
T& operator[] (unsigned long index) {
if (index > size - 1) {
cout << "allocate :" << index<<"\n";
neuesArray = new T[index+1];
unsigned long i;
for (i = 0; i < size; i++) {
neuesArray[i] = dynamischesArray[i];
}
delete[] dynamischesArray;
dynamischesArray = neuesArray;
//delete[] neuesArray;
size = index+1;
}
T&ret = dynamischesArray[index];
//return dynamischesArray[index];
return ret;
}
};
int main()
{
Container <int> dArray(100);
for (int i = 1; i < 20000; i++) {
dArray[i] = i;
cout <<"i="<<i<<" "<< dArray[i] << "\n";
//dArray.dynamischesArray[i] = i;
//cout << dArray.dynamischesArray[i] << "\n";
}
return 0;
}
this is result
I'm building a vector class for my data structures class, and I can't figure out why this is throwing an exception. Here's the complete Vector.h file:
#include <iostream>
using namespace std;
template <class T>
class Vector {
private:
// not yet implemented
Vector(const Vector& v);
Vector& operator=(const Vector& v);
T * Tarray;
int arraySize;
int currentSize;
public:
Vector() {
arraySize = 2;
currentSize = 0;
Tarray = new T[arraySize];
};
~Vector() {
delete[] Tarray;
};
void push_back(const T &e) {
++currentSize;
if (currentSize > arraySize) {
arraySize *= 4;
T * temp = new T[arraySize];
for (int i = 0; i < currentSize; i++) {
temp[i] = Tarray[i];
}
delete[] Tarray;
Tarray = new T[arraySize];
for (int j = 0; j < currentSize; j++) {
Tarray[j] = temp[j];
}
delete[] temp;
Tarray[currentSize - 1] = e;
}
else {
Tarray[currentSize - 1] = e;
}
};
void print() {
for (int i = 0; i < currentSize; i++) {
cout << Tarray[i] << " ";
}
};
int getCurrentSize() {
return currentSize;
};
int getArraySize() {
return arraySize;
};
// Not yet implemented
void pop_back();
int size() const;
T& operator[](int n);
};
And here's my complete main.cpp I was using to test it.
#include "Vector.h"
#include <iostream>
#include <string>
using namespace std;
int main() {
char c;
string * temp = new string[8];
Vector<string> newVector;
for (int i = 0; i < 8; i++) {
newVector.push_back("Hello world");
newVector.push_back("Hello world");
}
newVector.print();
cout << endl << "Current Size: " << newVector.getCurrentSize();
cout << endl << "Array Size: " << newVector.getArraySize();
cin >> c;
}
I would rewrite push_back as follows:
void push_back(const T &e) {
if (currentSize+1 > arraySize) {
arraySize *= 4;
T * temp = new T[arraySize];
for (int i = 0; i < currentSize; i++) {
temp[i] = Tarray[i];
}
delete[] Tarray;
Tarray = temp;
}
Tarray[currentSize] = e;
++currentSize;
};
Changes are:
Don't update currentSize until after you have copied the contents (thus not going out of bounds in Tarray).
Don't allocate and copy twice. Just assign Tarray to temp after deleting it.
Only stick element into Tarray in one place.
Update currentSize after, to avoid having to do -1 (It does require a single +1 in the first if instead.
For a C++ class I am taking, I am creating a Vector Library. We are not allowed to use the built in vector library, of course, and I have decided to use arrays in my 'myvector' class.
I am currently trying to test my code and I am not sure how to create an object of class myvector.
The error I get is Incomplete type is not allowed.
main.cpp:
#include "my_vectorHeader.h"
using namespace std;
int main(){
myvector<int> vector = new myvector<int>(3);
}
my_vectorLib.cpp:
#include "my_vectorHeader.h"
#include iostream
#include exception
using namespace std;
template<typename T> class myvector {
private:
int vector_size, //holds current size
vector_capacity; //holds current capacity
public:
//constructors
myvector<T>(int length){
T vector[length];
vector_size = length;
vector_capacity = length;
}
myvector<T>(const T& doppelganger){
T vector = doppelganger;
while(vector[vector_size] != NULL)
vector_size++;
}
myvector<T>(const T& dat_arr, int arr_size){
vector_size = arr_size;
vector_capacity = arr_size;
for(int i = 0; i < arr_size; i++)
vector[i] = dat_arr[i];
}
~myvector(){ //destructor
delete [] vector;
delete myvector;
}
myvector& myvector::operator[](int index){ //override []
try{
throw vector[index];
} catch(exception e){
cout << e.what() << endl;
}
return vector[index];
}
T at(int index){
return vector[index];
}
int size(){
return vector_size;
}
int capacity(){
return vector_capacity;
}
bool empty(){
if(size() > 0)
return false;
else
return true;
}
void resize(int new_size){
T vector_copy[new_size];
for(int i = 0; i < new_size; i++){
if(i >= vector_size)
vector_copy[i] = NULL;
else
vector_copy[i] = vector[i];
if(new_size > capacity)
capacity = new_size;
}
vector_size = new_size;
delete [] vector;
T *vector;
vector = vector_copy;
for(int i = 0; i < vector_size; i++)
vector[i] = vector_copy[i];
delete [] vector_copy;
}
void reserve(int new_capacity){
if(new_capacity < vector_size){
cout << "Error. Newly provided vector capacity is smaller than the current vector size. The capacity is " << vector_capacity << " and has not been changed.";
} else {
vector_capacity = new_capacity;
}
}
T pop_back(){
T return_val = vector[size() - 1];
resize(size() - 1);
return return_val;
}
void push_back(T new_val){
resize(size() + 1);
vector[size() - 1] = new_val;
}
void assign(int position, T new_val){
vector[position] = new_val;
}
void clear(){
for(int i = 0; i < size(); i++)
vector[i] = NULL;
}
void erase(int position){
vector[position] = NULL;
do{
vector[position] = vector[position + 1];
}while(position != NULL);
resize(size() - 1);
}
void erase(int in, int between){
int i = in + 1, j = between;
while(i < between){
vector[i] = vector[j];
vector[j] = NULL;
i++, j++;
}
resize(between);
}
void insert(int index, T new_val){
for(int i = size + 1; i > index; i--)
vector[i] = vector[i - 1];
vector[index] = new_val;
}
};
Declaration and implementation of templates should be in the same file(or implementation should be included too). Also this
myvector<int> vector = new myvector<int>(3);
is incorrect(new returns pointer) and unnecessary. Just use
myvector<int> vector(3);
Put the class (all the code) found at my_vectorLib.cpp in your my_vectorLib.h As #soon pointed you, templates classes (unless specialized) need to be at the header file (the one you include at main.cpp which where the class is instantiated, which means the compiler generates the actual code when you use the template).