I have this code in main:
Array<int> array1 = Array<int>(5);
array1.coutArray();
cout << "Minimal value: " << min(array1, 5);
And I need function to get minimal value of array. I Tried this function:
template<class Array>
Array min(const Array* data, int size) {
T result = data[0];
for (int i = 1; i < size; i++)
if (result > data[i])
result = data[i];
return result;
}
But for every variant from internet I have one error about types of first argument. How to properly write this function or it's calling?
Array class:
template <class T>
class Array {
protected:
int size;
T* DynamicArray;
public:
Array() {};
Array(size_t s) : size(s) {
DynamicArray = new T[size];
for (int i = 0; i < size; i++) {
cout << "Element " << i+1 << ": ";
cin >> DynamicArray[i];
}
}
void coutArray() {
for (int i = 0; i < size; i++) {
cout << DynamicArray[i] << " ";
}
}
~Array() {
delete[]DynamicArray;
}
};
template<class Array>
Array getMin(Array* arr, int size)
{
for (int i = 0; i < size; i++) {
cout << arr[i];
}
}
If you need this for your Array template, it would be best to provide begin and end for it:
template <class T>
class Array {
protected:
int size;
T* DynamicArray;
public:
....
using value_type = T;
const T* begin() const {
return DynamicArray;
}
const T* end() const {
return DynamicArray + size;
}
T* begin() {
return DynamicArray;
}
T* end() {
return DynamicArray + size;
}
};
Then you should be able use STL algorithms.
template<typename T>
T minimum(const T &tab)
{
return *std::minimum_element(std::begin(tab), std::end(tab));
}
Note that your array is poor version of std::vector.
The function getMin should be either a member function of the class or a friend function of the class to have access to protected data members of the class.
Here is a demonstrative program that shows how the function can be defined as a member function of the class. I also made some minor changes in the class definition.
#include <iostream>
template <class T>
class Array {
protected:
size_t size;
T* DynamicArray;
public:
Array() : size( 0 ), DynamicArray( nullptr ) {}
Array(size_t s) : size(s) {
DynamicArray = new T[size];
for ( size_t i = 0; i < size; i++) {
std::cout << "Element " << i+1 << ": ";
std::cin >> DynamicArray[i];
}
}
void coutArray() const {
for ( size_t i = 0; i < size; i++) {
std::cout << DynamicArray[i] << " ";
}
}
~Array() {
delete[]DynamicArray;
}
const T * getMin() const
{
T *min = DynamicArray;
for ( size_t i = 1; i < size; i++ )
{
if ( DynamicArray[i] < *min ) min = DynamicArray + i;
}
return min;
}
};
int main()
{
Array<int> a( 5 );
const int *min = a.getMin();
if ( min != nullptr ) std::cout << "The minimum is equal to " << *min << '\n';
return 0;
}
The program output might look for example the following way
Element 1: 2
Element 2: 3
Element 3: 1
Element 4: 4
Element 5: 5
The minimum is equal to 1
And below there is a demonstrative program when the function is defined as a non-template friend function of the class.
#include <iostream>
template <class T>
class Array {
protected:
size_t size;
T* DynamicArray;
public:
Array() : size( 0 ), DynamicArray( nullptr ) {}
Array(size_t s) : size(s) {
DynamicArray = new T[size];
for ( size_t i = 0; i < size; i++) {
std::cout << "Element " << i+1 << ": ";
std::cin >> DynamicArray[i];
}
}
void coutArray() const {
for ( size_t i = 0; i < size; i++) {
std::cout << DynamicArray[i] << " ";
}
}
~Array() {
delete[]DynamicArray;
}
friend const T * getMin( const Array &a )
{
T *min = a.DynamicArray;
for ( size_t i = 1; i < a.size; i++ )
{
if ( a.DynamicArray[i] < *min ) min = a.DynamicArray + i;
}
return min;
}
};
int main()
{
Array<int> a( 5 );
const int *min = getMin( a );
if ( min != nullptr ) std::cout << "The minimum is equal to " << *min << '\n';
return 0;
}
Related
The error is on line 76 int res[mSize]; the problem is on mSize. It seems like a simple fix but I can't figure it out. If someone can figure it out or point me in the right direction that would be greatly appreciated.
Also, the deconstructor ~MyContainer(), I am not sure if I am using it right or if there is a correct place to put it.
Here is my code:
#include <iostream>
using namespace std;
class MyContainer
{
private:
int* mHead; // head of the member array
int mSize; // size of the member array
public:
MyContainer();
MyContainer(int*, int);
//~MyContainer();
void Add(int);
void Delete(int);
int GetSize();
void DisplayAll();
int FindMissing();
~MyContainer() {}
};
MyContainer::MyContainer()
{
mHead = NULL;
mSize = 0;
}
MyContainer::MyContainer(int* a, int b)
{
mHead = a;
mSize = b;
}
void MyContainer::Add(int a)
{
*(mHead + mSize) = a;
mSize++;
}
void MyContainer::Delete(int a)
{
int index;
for (int i = 0; i < mSize; i++)
{
if (*(mHead + i) == a)
{
index = i;
break;
}
}
for (int i = index; i < mSize; i++)
{
*(mHead + i) = *(mHead + i + 1);
}
mSize--;
}
int MyContainer::GetSize()
{
return mSize;
}
void MyContainer::DisplayAll()
{
cout << "\n";
for (int i = 0; i < mSize; i++)
{
cout << *(mHead + i) << " ";
}
}
int MyContainer::FindMissing()
{
int res[mSize];
int temp;
int flag = 0;
for (int i = 1; i <= mSize; i++)
{
flag = 0;
for (int j = 0; j < mSize; j++)
{
if (*(mHead + j) == i)
{
flag = 1;
break;
}
}
if (flag == 0)
{
temp = i;
break;
}
}
return temp;
}
int main()
{
const int cSize = 5;
int lArray[cSize] = { 2, 3, 7, 6, 8 };
MyContainer lContainer(lArray, cSize);
lContainer.DisplayAll();
lContainer.Delete(7);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl; lContainer.Add(-1);
lContainer.Add(-10);
lContainer.Add(15);
lContainer.DisplayAll();
cout << "Size now is: " << lContainer.GetSize() << endl;
cout << "First missing positive is: " << lContainer.FindMissing() << endl;
system("PAUSE"); return 0;
}
int res[mSize];
The size of the array mSize must be known at compile time. You cannot use a variable here. An option may be to define a macro with an largish value that will not exceeded.
static const int kLargeSize =100;
int res[kLargeSize];
Edited in response to the comments - const and constexpr are a better option than a macro.
Or even better, you can use std::vector - https://en.cppreference.com/w/cpp/container/vector
I'm trying write my own vector class:
template <typename T>
class Vector {
public:
Vector(int default_size = 2) :
size(0), data_member(new T[default_size]), capacity(default_size) {};
Vector(const Vector& obj)
{
data_member = new T[obj.size];
data_member = obj.data_member;
size = obj.size;
capacity = obj.capacity;
}
void push_back(T& elem)
{
if (size == capacity)
resize(2 * size);
data_member[size] = elem;
size++;
}
void push_front(T& data)
{
if (size + 1 == capacity)
resize(2 * size);
for (int i = size - 1; i >= 0; i--)
{
data_member[i + 1] = data_member[i];
}
data_member[0] = data;
size++;
}
void pop_back()
{
--size;
}
void resize(int size_)
{
if (size_ > capacity)
{
T* temp = new T[size_];
memcpy(temp, data_member, size * sizeof(T));
delete[] data_member;
data_member = new T[size_];
data_member = temp;
//delete[] temp;
capacity = size_;
}
}
int get_size() { return size; }
T* getarr() { return data_member; }
private:
T* data_member;
int size;
int capacity;
};
and here is a main for testing my class
int main()
{
Vector<int> myint;
int a = 5, b = 8, c = 9;
myint.push_back(a);
myint.push_back(b);
myint.push_back(c);
Vector<int> you = myint;
int* arr1 = you.getarr();
for (int i = 0; i < you.get_size(); i++)
{
cout << *arr1 << endl;
arr1++;
}
cout << endl << endl;
int h[3] = { 1,2,3 };
int* hp = h;
int g[3] = { 4,5,6 };
int* gp = g;
int f[3] = { 4,5,6 };
int* fp = f;
Vector<int*> myarrint;
myarrint.push_back(hp);
myarrint.push_back(gp);
myarrint.push_back(fp);
int** arr = myarrint.getarr();
for (int i = 0; i < myarrint.get_size(); i++)
{
for (int j = 0; j < 3; j++)
{
cout << **arr << endl;
(*arr)++;
}
arr++;
}
cout << endl << endl;
Vector<string> mystr;
string s1 = "I";
string s2 = "went";
string s3 = "shopping";
mystr.push_back(s1);
mystr.push_back(s2);
mystr.push_back(s3);
string* str1 = mystr.getarr();
for (int i = 0; i < mystr.get_size(); i++)
{
cout << *str1 << endl;
str1++;
}
cout << endl << endl;
string i = "wow";
mystr.push_front(i);
string* str2 = mystr.getarr();
for (int i = 0; i < mystr.get_size(); i++)
{
cout << *str2 << endl;
str2++;
}
cout << endl << endl;
return 0;
}
I'm new in c++ and I'm really confused, I think in my push_back function, I'm just making my objects point to temp and I'm not copying temp in them , so if I want to delete temp in the end of my push_back function my data_members will be lost. So what is the right way to do so?
second if I want to make a dynamic array of strings my program will crash sometimes, and I think ,it's because of memcpy() in my resize function, still I don't know what should I do instead of it?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
So, this is just few methods from my myArray.cpp class. It gives me error on
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
these above code(error - which is non-class type double). can anyone please help me? I'm trying to copy an array to the object array
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
}
void myArray::setSize(int value) {
if (value > 0) {
size = value;
}
}
void myArray::setData(int index, double value) {
if ((index >= 0) && (index < size)) {
arr[index] = value;
} else {
// cout << "NO!" << endl;
}
}
double myArray::getData(int index) const {
if ((index >= 0) && (index < size)) {
return arr[index];
} else {
return arr[size - 1];
}
}
That's my main.cpp class
#include <iostream>
#include "myArray.h"
//#include "myArray.cpp"
using namespace std;
int main (int argc, char **argv)
{
cout << "**************Testing Default Constructor*****************" << endl;
myArray A1;
cout << "A1: ";
A1.print();
cout << "**************Testing Alt Constructor 1*****************" << endl;
myArray A2(5,0);
cout << "A2: ";
A2.print();
cout << "**************Testing init*****************" << endl;
A2.init();
cout << "A2 after init: ";
A2.print();
int size = 5;
double *temp = new double[size];
for(int i = 0; i < size; i++)
{
temp[i] = i;
}
cout << "**************Testing Alt Constructor 2*****************" << endl;
myArray A3(temp, size);
cout << "A3: ";
cout << A3.getSize();
cout << endl;
cout << "Fe";
A3.print();
That's my myArray.cpp class
#ifndef MYARRAY_H_INCLUDED
#define MYARRAY_H_INCLUDED
/***************************************************************************
* myArray class header file
***************************************************************************/
class myArray
{
public:
myArray();
myArray(int,double);
myArray(double*, int);
~myArray();
int getSize() const;
bool equal(const myArray &rhs) const;
void setData(int index, double value);
void insert(int, double);
void remove(int);
double get(int);
void clear();
int find(double);
bool equals(myArray&);
void print() const;
void init();
double getData(int index) const;
// void init();
// void print() const;
void expand();
private:
int size;
double *arr;
void setSize(int value);
};
#endif // MYARRAY_H_INCLUDED
That's my myArray.cpp class where I'm getting the error in the default paramaterized constructor
#include "myArray.h"
#include <iostream>
using namespace std;
myArray::myArray() : size(0) {
// size = 10;
arr = new double [size];
}
/*myArray::myArray(int _size) : size(_size) {
// size = _size;
arr = new double [size];
for (int i = 0; i < size; i++) {
arr[i] = i;
}
} */
myArray::myArray(int _size, double value) : size(_size) {
// size = _size;
arr = new double [size];
for (int i = 0; i < size; i++) {
arr[i] = value;
}
}
/*myArray::myArray(myArray* temp, int size)
{
setSize(temp.getSize());
for (int i = 0; i < getSize(); i++) {
setData(i, temp.getData(i));
}
} */
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
//double arr[size];
// arr = new double[size];
// p = orig;
// for(int i = 0;i<size;i++)
// {
// arr[i] = orig[i];
// cout << arr[i] << " ";
// }
// cout << endl;
// setSize(size);
// for (int i = 0; i < getSize(); i++)
// setData(i, orig.getData(i));
// cout << "hell";
// for (int i = 0; i < size; i++) {
// arr[i] = myArray[i];
// cout << arr[i];
//}
// arr = myArray;
}
myArray::~myArray() {
delete [] arr;
}
int myArray::getSize() const {
return size;
}
void myArray::setSize(int value) {
if (value > 0) {
size = value;
}
}
void myArray::setData(int index, double value) {
if ((index >= 0) && (index < size)) {
arr[index] = value;
} else {
// cout << "NO!" << endl;
}
}
double myArray::getData(int index) const {
if ((index >= 0) && (index < size)) {
return arr[index];
} else {
return arr[size - 1];
}
}
void myArray::print() const {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
void myArray::expand() {
double *localArray = new double[size + 1];
for (int i = 0; i < size; i++) {
localArray[i] = arr[i];
}
localArray[size] = size;
delete [] arr;
setSize(size + 1);
arr = localArray;
// myArray = new int[size];
//
// //Is this a deep-copy or a shallow-copy?
// //Can you replace one with the other?
// //What are the advantages and disadvantages?
// for(int i=0; i < size; i++) {
// myArray[i] = localArray[i];
// }
// delete [] localArray;
}
bool myArray::equal(const myArray& rhs) const {
bool result(true);
if (getSize() != rhs.getSize()) {
result = false;
} else {
for (int i = 0; i < getSize(); i++) {
if (getData(i) != rhs.getData(i)) {
result = false;
}
}
}
return result;
}
void myArray::init()
{
cout << "Enter the " << size << " elements to populate the array " << endl;
for(int i = 0;i<getSize();i++)
{
int value;
cin >> value;
setData(i,value);
}
}
Sorry I somehow I thought you wanted help with a runtime error but you want help with the compile errors.
The compile error in this part of the code
myArray::myArray(double* orig, int size) {
setSize(orig.getsize());
for(int i = 0; i<getSize();i++)
setData(i,orig.getData(i));
is specifically about the orig.getSize() part. orig is of type double* (pointer to double) and pointers do not have member functions only classes do which is why the compiler says: "which is non-class type double"
Actually there is no way in c++ to know from a pointer to how many elements it points but luckily your function already has a parameter size which i guess is meant to pass in the size of the orig array. So that line should be setSize(size);
Now two lines lower you get a similar error on setData(i,orig.getData(i)); orig is still a double* so it still doesn't have member functions. The correct way is setData(i, orig[i]);
EDIT:
BTW, i quick look through the rest of your code shows me that your setSize method doesn't allocate an array of appropriate size so you should fix that to.
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.
I've been working on some code for an assignment and I'm having an issue with nested templated types.
I need the following code to create a 3 element array of 3 element arrays (sort of like int b[3][3]):
Array< Array<int> > b(3);
Here are the relevant parts of my Array.h:
template <class T>
class Array{
public:
Array() : size(0){ data = NULL; }
Array(int s) : size(s) { data = new T[size]; }
Array(const Array & a) : size(a.length()) {
data = new T[a.length()];
for(int i = 0; i < a.length(); ++i)
data[i] = a[i];
}
~Array(){ delete[] data; }
T & operator[](int i) {
if (i >= 0 && i < size){
return data[i];
} else {
throw ArrayOutOfBounds(i);
}
}
T operator[](int i) const{
if (i >= 0 && i < size){
return data[i];
} else {
throw ArrayOutOfBounds(i);
}
}
Array<T> & operator=(const Array<T> &a){
if(this == &a) return *this;
delete[] data;
data = new T[a.length()];
for(int i = 0; i < a.length(); ++i)
data[i] = a[i];
size = a.length();
}
int length() const { return size; }
// Members
private:
int size;
T * data;
}
Update 6/1 the full driver code:
// Test driver for generic Array object with assignment and bounds checking
#include "Array.h"
int main() {
Array<int> a1(10);
for (int i = 0; i < a1.length(); ++i)
a1[i] = i * i;
Array<int> a2 = a1;
try {
for (int i = 0; i <= a2.length(); ++i)
cout << a2[i] << " ";
cout << endl;
}
catch (const ArrayOutOfBounds & e) {
cout << endl << "ArrayOutOfBounds index=" << e.index << endl;
}
Array< Array<int> > b(3);
for (int i = 0; i < b.length(); ++i) {
for (int j = 0; j < b[i].length(); ++j)
b[i][j] = i*b[i].length() + j;
}
for (int i = 0; i < b.length(); ++i) {
cout << "b[" << i << "]= ";
for (int j = 0; j < b[i].length(); ++j)
cout << b[i][j] << " ";
cout << endl;
}
Array<const char *> c(3);
c[0] = "moe"; c[1] = "curly"; c[2] = "larry";
Array<const char *> d(10);
d = c;
for (int i = 0; i < d.length(); ++i)
cout << "d[" << i << "]=" << d[i] << " ";
cout << endl;
return 0;
}
Expected output:
0 1 4 9 16 25 36 49 64 81
ArrayOutOfBounds index=10
b[0]= 0 1 2
b[1]= 3 4 5
b[2]= 6 7 8
d[0]=moe d[1]=curly d[2]=larry
Update 6/2
Per Guillaume's solution, here is the resize method I used:
Array<T> & resize(int newsize){
delete[] data;
data = new T[newsize];
size = newsize;
for(int i = 0; i < size; ++i)
init(data[i], size);
}
Recursive resizing works for higher dimensions, such as Array< Array< Array<int> > > q(3);
Based on the code, you pasted, this should not crash. Did you forget the destructor? You should have a destructor that deletes the memory. When you have one, you need to make sure that data is initialized to nullptr (or NULL) so it does not crash when deleting an empty array.
But your approach is confusing. Is Array size supposed to be determined at runtime or at compile time? int b[3][3] is determined at compile time. If you want that, you should make the size a template argument like std::array in C++11, see http://en.cppreference.com/w/cpp/container/array
If you want to detemrine the size at runtime, you'll need a resize method to determine the size of the the 2nd dimension.
EDIT:
Based on the driver code, you need to do something different in the constructor (passing the int to T if T is an Array). To be quite honest, this seems almost like a bug. This kind of specification makes it really hard to describe what the constructor do (call the default ctor for all types T except for Array)
I'd something like this:
private:
template <typename U>
void init(U&, int) {}
template <typename U>
void init(Array<U>& a, int sz)
{
a.resize(sz);
}
public:
Array(int s) : size(s) {
data = new T[size];
for (int i = 0 ; i < size; ++i) {
init(data[i], s);
}
}
It works but this is ugly. If you can use C++11, you can something nicer with std::enable_if