I have a problem with the execution of this program. I do not know why it ends up running so abruptly ("The program stopped working"). The results of it are what I hope, however that happens. And I tried many things to avoid it and found that what causes the error is the function void IntArr::addElement(int qtty,int *vec); since if I remove it, the program finishes perfectly and without any error. Analyze the function and for me it's fine, I do not know what is slipping from my hands. The function that what you should do is pass an array with the amount of elements that I want from it and add them to another array.
PS: the original program was well divided by files (class.h, class.cpp, main.cpp), nothing more than to copy them here I had to paste everything together.
I would appreciate your help. Regards!
#include <iostream>
using std::cout;
using std::endl;
#define PRESS_KEY std::cout<<"\nPresione Enter para continuar . . .\n";std::cin.get();
class IntArr{
private:
int * p;
int size;
int used;
//Verificador
void redimensionador(int cant);
public:
//Constructores
IntArr (int sz);
IntArr (int sz,int qtty,int *vec);
//Destructor
~IntArr();
//Visualizadores
void prtArr (void) const;
void prtArr (int cant);
//Accesores
int getSize(){return size;};
int getUsed(){return used;};
//Operaciones
void addElement(int xx);
void addElement(int qtty,int *vec);
};
//Constructores
IntArr::IntArr(int sz){
size = sz;
used = 0;
p = new int[size];
}
IntArr::IntArr(int sz,int qtty,int* vec){
if(qtty>sz){
sz = qtty;
}
size = sz;
used = qtty;
p = new int[size];
p = vec;
}
//Destructor
IntArr::~IntArr(){
delete []p;
}
//Visualizadores
void IntArr::prtArr(void) const{
if(used == 0){
cout<<endl<<"El array no tiene elementos."<<endl;
}
else{
cout<<endl<<"Array: ";
for(int i=0;i<used;i++){
cout<<p[i]<<", ";
}
cout<<endl;
}
}
void IntArr::prtArr(int cant){
if(used == 0){
cout<<endl<<"El array no tiene elementos."<<endl;
}
else{
cout<<endl<<"Array: ";
for(int i=0;i<cant;i++){
cout<<p[i]<<", ";
}
cout<<endl;
}
}
//Operaciones
double IntArr::getAvg(){
double acum = 0;
for(int i=0;i<used;i++){
acum += p[i];
}
return (acum/used);
}
void IntArr::addElement(int xx){
redimensionador(1);
p[used] = xx;
used++;
}
void IntArr::addElement(int qtty,int *vec){
int j=0;
redimensionador(qtty);
for(int i=used;i<(used+qtty);i++){
p[i] = vec[j];
j++;
}
used += qtty;
}
//Verificador
void IntArr::redimensionador(int cant){
if(cant+used>size){
if(cant > 5){
size += cant;
}
else{
size += 5 + cant;
}
}
}
int main(int argc, char *argv[]){
int v_aux[]= {0,5,10,15,20,25,30,35,40};
IntArr A(10,sizeof(v_aux)/sizeof(int),v_aux);
cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
A.prtArr();
A.addElement(77);
cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
A.prtArr();
A.addElement(11);
cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
A.prtArr();
A.addElement(8,v_aux);
cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
A.prtArr();
PRESS_KEY;
}
One problem I noticed is in the following lines:
p = new int[size];
p = vec;
When you do that:
You have a memory leak. The value returned by new int[size] is lost to your program.
You point p to the statically defined array in main. That leads to undefined behavior when you use delete [] p; in the destructor.
I am guessing you want to copy the values from vec to p. You'll have to copy the values one by one.
The manually coded version for that:
for (int i = 0; i < used; ++i )
{
p[i] = vec[i];
}
Using the standard library function std::copy:
std::copy(vec, vec+used, p);
If you run out of memory, you can not just say you have more size by adding to an integer. You have to reallocate the memory, copy the values from the old array into the new array, then delete the old array.
You also need to be careful here. Raw pointers are error prone, and I see you have some strange constructs here. For example, IntArr::IntArr(int sz,int qtty,int* vec) you allocate a pointer, then immediately overwrite it. That allocation is a leak.
Be sure you properly update size and used so that you don't lose track of how much memory you actually have. When size changes, so must your buffer or you are out of sync.
Even this constructor has a memory leak and can result in undefined behaviour (for example when vec points to first element of a local array or when the array poined by the argument vec will be deleted).
IntArr::IntArr(int sz,int qtty,int* vec){
if(qtty>sz){
sz = qtty;
}
size = sz;
used = qtty;
p = new int[size];
p = vec;
}
At first a memory is allocated and its address is assigned to p and then p is reassigned.
p = new int[size];
p = vec;
You have to copy elements from the array pointed to by the argument vec into the allocated memory pointed to by the data member p.
And this member function
void IntArr::redimensionador(int cant){
if(cant+used>size){
if(cant > 5){
size += cant;
}
else{
size += 5 + cant;
}
}
}
does not make sense. You have to reallocate the original array pointed to by the data member p.
Related
Create a dynamic array of int with a initial space of 4. Write a function ‘append’ that appends a given value to this array. At any stage, if this function finds the array full it automatically doubles the size of array to accommodate this new value. Also write a function to display all the elements of this array. Write a main to test all these functions.
I made an attempt to solve the above question as given below. However, I am unable to get the correct code. Please help me
#include<iostream>
using namespace std;
void append(int*& array, int val, int n, int r)
{
int i,p;
int *array1;
for (i=r;i<n;i++)
array[i] = val;
if(i==n)
{
p = 2*n;
array1 = new int [p];
}
for(int j =0; j<r/2; j++)
array1[j]= array[j];
append(array1, val, p, p/2);
}
int main()
{
int q,p=0,val, n = 4;
int n1 = p/2;
int *array = new int[n];
while(1)
{
cout<<"Enter 0 to end and 1 to continue";
cin>>q;
while(q!=0)
{
cin>>val;
append(array,val,n,n1);
}
}
return 0;
}
I need to solve this without using "Classes". How shall I do it?
Your function needs to do the following:
1) Be able to check if the current append call will result in an out-of-bounds write attempt. So you need something like (and give variables explanatory names like this) this as the first line in your function:
if (array_size < item_count) {
//double size of array
}
To double the size of the array, you have to make a new array with twice the size, copy all the items over from the old array, DELETE the old array, null the old array's pointer, and somehow update the array_size variable (return to main is one option, a static int counter in the function itself is another). You may have to return a pointer to the new array to main, as well. Or maybe you can just re-address the old pointer to the new array AFTER using that pointer to delete the old array. This is all about avoiding memory leaks. So, try to come up with a method declaration like:
int append(int* arrPtr, int value, int array_size, int item_count)
This particular approach means main is getting sent back the array size as an int after each append. So you need something in main like:
array_size = append(array, val, array_size, item_count);
The tricky part will be when you make the new array:
array_size = 2 * array_size;
int* temp = new int[array_size]
//copy everything over from old array to new using arrPtr and temp
for (int i = 0; i < array_size / 2; i++) {
temp[i] = arrPtr[i]
}
//delete the contents of the old array:
delete[] arrPtr;
//pointer gymnastics to redirect arrPtr to the new array:
arrPtr = temp;
temp = nullptr;
//okay, now you are back out of the conditional and can use item_count to insert the
//value into the array (doubled or not)
arrPtr[item_count] = value;
//don't forget to return array_size, and remember main must track item_count as well.
return array_size;
That's the general gist of it. This is not a complete answer, but should give you enough to work with. Basically, most of your code has to be rewritten, and the above is not a complete solution. Good luck.
After taking cue from Double size of dynamic array I have solved it.
#include<iostream>
using namespace std;
void add_element(int* &array, int &size)
{int count = 0;
while(1)
{
int number;
cout << "What number do you want to add? " << endl;
cin >> number;
if (count == size)
{
int newSize = size * 2;
int *newArr = new int[newSize];
for (int i = 0; i < count; ++i)
{
newArr[i] = array[i];
}
delete[] array;
array = newArr;
size = newSize;
}
array[count] = number;
++count;
int k;
cout<<"Do u want to end, then press 0";
cin>>k;
if(k==0) break;
}
for(int g = 0; g<count; g++)
cout<<array[g]<<'\t';
}
int main()
{
int i,j,k,size;
cin>>size;
int* array = new int [size];
add_element(array, size);
}
I am trying to implement a dynamically created array using new that I want to resize but the resize action is not working correctly.
This is an exercise on dynamic arrays, so I need dynamic arrays using new and not std::vector.
Here is my code :
int main ()
{
// Build an application here
int length = 0;
int size = 0;
int input;
bool endAdding = false;
cout << "Please enter the length of the new array : ";
cin >> length;
int* oPtrDynamicArray = CreateDynamicArray (length, size);
do
{
cout << "Add an element (0 to quit) : " << endl;
cin >> input;
cout << endl << endl;
if (input == 0){
endAdding = true;
}
else
{
InsertElement(oPtrDynamicArray, input, size, length);
}
cout << "The array contains : " << endl;
for (int i = 0; i < size; i++)
{
cout << i << ": [" << oPtrDynamicArray[i] << "]" << endl;
}
} while (!endAdding);
DeleteDynamicArray (oPtrDynamicArray, size);
}
int *CreateDynamicArray (int capacity, int &size)
{
size = 0;
return new int[capacity];
}
void DeleteDynamicArray (int *dynamicArray, int &size)
{
delete[] dynamicArray;
dynamicArray = nullptr;
size = 0;
}
void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (&dynamicArray, size+1);
}
dynamicArray[size] = element;
size++;
}
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int ** newArray = new int*[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = dynamicArray[i];
}
*dynamicArray = *newArray;
delete[] newArray;
newArray = nullptr;
}
The problem is that the array is passed to my InsertElement() function and then to ResizeDynamicArray() only if capacity <= size, but the array passed to the first function, is passed with good values, but with abnormal pointers in the array.
Example :
For an array of 3, I have :
array[0] = 1 --> adress 0x0004e300 containing value 1
array[1] = 2 --> adress 0x00000003 containing ???
array[2] = 3 --> adress 0x008ffb24 containing value 2
I really don't understand, it would be really great if someone could explain my error :/.
The problem is here
void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (&dynamicArray, size+1);
}
dynamicArray[size] = element;
size++;
}
when you call ResizeDynamicArray you are changing the dynamicArray pointer declared as a parameter to InsertElement. You are not changing the oPtrDynamicArray pointer in main.
If you want to make this work you need to change InsertElement to take a double pointer (just like ResizeDynamicArray)
void InsertElement (int **dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (dynamicArray, size+1);
}
(*dynamicArray)[size] = element;
size++;
}
Or you could do the easy thing and just use std::vector<int>.
EDIT now that I look at it your ResizeDynamicArray function I see that function is completely wrong as well. It's clear that you have some learning to do with pointers
Here's how ResizeDynamicArray should be
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int * newArray = new int[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = (*dynamicArray)[i];
}
delete[] *dynamicArray;
*dynamicArray = newArray;
}
You're not the first newbie to fail to understand pointers. Have a good look at the code above and compare it with your code. The main difference is that my code using a pointer to change what is being pointed to. Your code tried to change the pointer itself, which is incorrect. It's confusing because what is being pointed to is another pointer (the dynamic array).
There are several issues in your code:
First, in ResizeDynamicArray, you allocate an array of pointers to ints, not an array of ints. int ** newArray = new int*[newCapacity] should be int *newArray = new int[newCapacity].
Second, once you have fixed that, you need to write *dynamicArray = newArray;;
but you should free the old array before you assign the pointer to the new memory block.
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int *newArray = new int[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = (*dynamicArray)[i];
}
delete[] *dynamicArray;
*dynamicArray = newArray;
}
Third, you since InsertElement may call ResizeDynamicArray (which will give you back a new memory block), you need to alter the originally passed pointer. So you need to pass a pointer to a pointer int the function, just as you did with ResizeDynamicArray:
void InsertElement (int **dynamicArray, int element, int &size, int capacity)
adapt the body accordingly then.
I know the question is already answered but not the why.
You have to keep in mind that pointers are passed to functions by value.
The pointer value, the address it points to, is lost when the function ends.
But you are still able to change the value stored at the address it points to by dereferencing the pointer.
To pass be able to change the pointer value, the address it points to, inside a function, you have to pass a pointer to a pointer. In this case passing a double pointer is synonym for passing a pointer to a function by reference.
void Foo(int **ptr)
{
// Don't use ptr, changes are lost after function end as ptr is a local copy
// Use *ptr to change the value of the pointer you passed to the function.
// Use **ptr to change the value at the address the pointer you passed to the funcion points to
}
In this case you can change the pointer value, the address it points to, by dereferencing the double pointer once. Which applies to above answers.
Hi i was creating a simple Vector Class for my studies.
Just to store Variable LONG
i kept everything simple. When i build nothing was return error/ warning.
Then after run the program, it works but the program crash.
Code Vector.h
class Vector{
public:
Vector();
void add(long i);
void getData();
private:
long *anArray;
long maxSize;
long position;
void reSize(int i);
};
Vector.cpp
Vector::Vector(){
maxSize = 2;
anArray = new long[maxSize];
position = 0;
}
void Vector::add(long i){
if(position==maxSize-1)
reSize(maxSize * 2);
anArray[position] = i;
position++;
}
void Vector::reSize(int i){
long *temp = new long[maxSize];
for(int i =0; i<maxSize; i++)
{
temp[i] = anArray[i];
}
delete[] anArray;
anArray = temp;
}
void Vector::getData(){
for(int i = 0; i<position; i++)
{
cout << "Element" << i+1 << " : " << anArray[i] << endl;
}
}
Main
int main()
{
Vector vecStore;
for(int i = 0; i < 1000; i++)
{
long a;
vecStore.add(a = i + 1);
}
cout << "GET DATA _________ :: " << endl;
vecStore.getData();
return 0;
}
The program wouldn't crash if the input data small(e.g. 10-20)
but when i change it to 100 or even bigger. the program sometime crash and sometime its not.
Did i make a mistake?
In
void Vector::add(long i){
if(position==maxSize-1)
reSize(maxSize * 2);
anArray[position] = i;
position++;
}
when position==maxSize-1, reSize is called to double the size of the array. Unfortunately, reSize is broken.
void Vector::reSize(int i){
long *temp = new long[maxSize];
for(int i =0; i<maxSize; i++)
{
temp[i] = anArray[i];
}
delete[] anArray;
anArray = temp;
}
The parameter i is never used. This should be the new size of the Vector, but instead the new array is allocated with the same maxSize as the previous array. maxSize goes unchanged.
Back in add, data is stored at position and position is increased by one. This means on the next add position is equal to maxSize, so the check to prevent overrunning the array,
if(position==maxSize-1)
will not do what you want and the program writes outside the bounds of the array. From there, position keeps getting larger, will never be equal to maxSize minus one, and writes even further out of bounds, not that it matters at that point. Undefined Behaviour has already been invoked, and Crom only knows what will happen. Maybe the program crashes, maybe the program crashes later, maybe it does something bizarre, and maybe it even chugs on looking like everything is working just fine.
You want something more along the lines of
void Vector::reSize(int newSize){ // note more descriptive name
long *temp = new long[newSize]; // using new size, not old size
for(int i =0; i<maxSize; i++)
{
temp[i] = anArray[i];
}
delete[] anArray;
anArray = temp;
maxSize = newSize; // store new size.
}
Vector also needs a destructor to clean up anArray, but in order to properly fix this error, here's a bit of recommended reading: What is The Rule of Three?
I'm trying to implement vector's insert function in c++. The basic idea is
initialize a tmp_vector with the size of the new array;
2.copy the original data into a tmp_vector;
delete the old vector; copy the
tmp_vector to new_vector
Here's my code:
double* Vector::insert(int index, double *newNum, int newNum_size)
{
//insert into empty vector
if(size == 0){
//if there's enough memory to hold newNum
if(newNum_size < capacity)
{
for(int i = 0; i < newNum_size; i++)
{
data[i] = newNum[i];
}
}
}
//expand the vector
if(size != 0){
double *tmp_vector = NULL;
try{
tmp_vector = new double(size+newNum_size);
}
catch(bad_alloc &e){
cerr << "Vector::insertion(): " << e.what();
}
//move the vector to tmp
for(int i=0; i < size; i++)
{
tmp_vector[i] = data[i];
}
//copy the tmp_vector pointer to newNum pointer
tmp_vector[size+newNum_size] = *newNum;
//realease the memory from data
delete[] data;
}
return newNum;
}
However, it gives me a compile error when I call it from main
myVector.insert(0,1.0,1);
The error is "Cannot initialize a parameter type 'double' with an rvalue of type 'double'". What does this mean?
You have:
(int index, double *newNum, int newNum_size)
(0, 1.0, 1)
I think the problem is that 1.0 is not a double[*]... it's just a double.
How about using the STL implementation? This way you can avoid unnecessary complications. http://www.cplusplus.com/reference/vector/vector/insert/
In the signature of your function:
double* Vector::insert(int index, double *newNum, int newNum_size)
you are expecting double pointer/an array of doubles, whereas in insert(0,1.0,1) you are passing a single double value.
Moreover, I don't see where did size variable come from. Provided you would have it declared inside the function/passed to a function, this would be incorrect: tmp_vector = new double(size+newNum_size) and what you want is probably: tmp_vector = new double(size*newNum_size) (the latter would allocate newNum_size times size memory, i.e. space for your array).
I am learning about pointers and the new operator in class.
In my readArray function I am to read in a size. Use the size to dynamically create an integer array. Then assign the array to a pointer, fill it, and return the size and array.
I believe I've gotten that part corrected and fixed but when I try to sort the array, i get the error "uninitialized local variable temp used."
The problem is though I get that error when I am trying to intialize it.
Any help appreciated thank you. Seeing my errors is very helpful for me.
#include <iostream>
using namespace std;
int* readArray(int&);
void sortArray(int *, const int * );
int main ()
{
int size = 0;
int *arrPTR = readArray(size);
const int *sizePTR = &size;
sortArray(arrPTR, sizePTR);
cout<<arrPTR[1]<<arrPTR[2]<<arrPTR[3]<<arrPTR[4];
system("pause");
return 0;
}
int* readArray(int &size)
{
cout<<"Enter a number for size of array.\n";
cin>>size;
int *arrPTR = new int[size];
for(int count = 0; count < (size-1); count++)
{
cout<<"Enter positive numbers to completely fill the array.\n";
cin>>*(arrPTR+count);
}
return arrPTR;
}
void sortArray(int *arrPTR, const int *sizePTR)
{
int *temp;
bool *swap;
do
{
swap = false;
for(int count = 0; count < (*sizePTR - 1); count++)
{
if(arrPTR[count] > arrPTR[count+1])
{
*temp = arrPTR[count];
arrPTR[count] = arrPTR[count+1];
arrPTR[count+1] = *temp;
*swap = true;
}
}
}while (swap);
}
You make temp an int pointer (uninitiialized), and then set the thing it points at (anything/nothing) to arrPTR[ccount]. Since you are using temp only to swap, it should be the same type as those being swapped, in this case: an int.
If it absolutely must be a pointer (there is no good reason for this, it's slow, confusing, adds potential for errors, and adds potential for memory leaks):
int *temp = new int; //make an int for the pointer to point at
bool *swap = new bool; //make an bool for the pointer to point at
do
{
//your code
}while (swap);
delete temp;
delete swap;
You declared temp as a pointer. You need to allocate it on the heap before dereferencing and assigning to it later. However perhaps a variable on the stack would be preferable?
FYI: You should be aware of the memory leak in readArray as well which is leaving callers responsible for calling delete []
Edit: I hope this will help clear up some of the other problems.
#include <iostream>
int* readArray(int&);
void sortArray(int*, int);
int main ()
{
int size(0); // use stack when possible
int *arrPTR = readArray(size);
sortArray(arrPTR, size);
// arrays are zero based index so loop from 0 to size
for (int index(0); index < size; ++index)
std::cout << arrPTR[index];
delete [] arrPTR; // remember to delete array or we have a memory leak!
// note: because we did new[] for an array we match it with delete[]
// if we just did new we would match it with delete
system("pause");
return 0;
}
int* readArray(int& size)
{
std::cout << "Enter a number for size of array.\n";
std::cin >> size;
int *arrPTR = new int[size]; // all news must be deleted!
// prefer pre-increment to post-increment where you can
for(int count(0); count < size; ++count)
{
std::cout << "Enter positive numbers to completely fill the array.\n";
std::cin >> arrPTR[count];
}
return arrPTR;
}
// passing size by value is fine (it may be smaller than pointer on some architectures)
void sortArray(int *arrPTR, int size)
{
// you may want to check if size >= 2 for sanity
// we do the two loops to avoid going out of bounds of array on last iteration
for(int i(0); i < size-1; ++i) // the first to compare (all except last)
{
for(int j(i+1); j < size; ++j) // the second to compare (all except first)
{
// do comparison
if (arrPTR[i] > arrPTR[j]) // from smallest to biggest (use < to go from biggest to smallest)
{
// swap if needed
int temp(arrPTR[i]); // put this on stack
arrPTR[i] = arrPTR[j];
arrPTR[j] = temp;
}
}
}
}
temp is a "pointer to int, which you're not initializing. When you say *temp = ... you're actually assigning to whatever temp happens to be pointing, but since you haven't told it what to point to, it can write pretty much anywhere in the address space of your program.
Because of the way you're using them, it seems that temp and swap shouldn't be pointers at all, just a plain int and bool.
You didn't initialize the temp pointer do when you dereference it you are writing to a random part of memory. Temp doesn't need to be a pointer, it can just be an int. Just replace EVERY instance of *temp with temp.