I am getting an out of scope error in my copy function, when I try to copy the contents of the first array into the DMA one. The try-catch block is required.
#include <iostream>
#include <cstdlib>
using namespace std;
void show( const int a[], unsigned elements );
int * copy( const int a[], unsigned els );
void die(const string & msg);
int main()
{
int arr[4] = {4, 2, 3, 6};
show(arr, 4);
int * newArr = copy(arr, 4);
}
void show( const int a[], unsigned elements )
{
for (int i = 0; i < elements; i++)
cout << a[i] << endl;
}
int * copy( const int a[], unsigned els )
{
try
{
int * newArr = new int[els];
}
catch(const bad_alloc &)
{
die("Alloc Failure");
}
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
void die(const string & msg)
{
cerr << "Fatal error: " << msg << endl;
exit(EXIT_FAILURE);
}
If you declare the variable inside the try block then it's only accessible there. You can work around this by moving the declaration outside of the block.
int *newArr;
try
{
newArr = new int[els];
}
catch(const bad_alloc &)
{
die("Alloc Failure");
}
for (int i = 0; i < els; i++)
newArr[i] = a[i];
Or by moving the rest of the code inside the try.
try
{
int *newArr = new int[els];
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
catch(const bad_alloc &)
{
die("Alloc Failure");
}
Define new array before the try, otherwise it is only defined inside the try block.
The whole point of exceptions is that you do not need to handle all conceivable errors right at the point where they happen, but rather in places of your choice where you are able to respond to them meaningfully. So be generous with the size of your try blocks:
int * copy(const int a[], unsigned els)
{
try
{
int * newArr = new int[els];
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
catch (const std::bad_alloc &)
{
die("Alloc Failure");
}
}
You can change your code to
int * copy( const int a[], unsigned els ) {
int * newArr = nullptr;
try {
newArr = new int[els];
}
catch(const bad_alloc &) {
die("Alloc Failure");
}
if(newArr) {
for (int i = 0; i < els; i++)
newArr[i] = a[i];
}
return newArr;
}
to overcome your problem. Just initialize newArr correctly.
I think the problem in your Copy-Function is, that the new Array is a local Variable. When you than return it to the caller, the pointer adresses aren't the right ones.
You might better use two arrays which you pass as Referneces into the copy-function, like this:
int& copy(int& newArray, const int& oldArray) { ... }
Here you get a discription about references in c++ if you don't know what they supposed to be: http://en.wikipedia.org/wiki/Reference_%28C%2B%2B%29
Related
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.
int* filtrationBiggerValues(int* values, int nrValues, int givenValue) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
return new_array;
}
void main() {
int y[] = { 1,2,100,18,20,94 };
cout<< filtrationBiggerValues(y, 6, 8)<<"\n";
}
I should see the new array with the values bigger than a certain value, but instead I get its address.
That is not how it works. You are returning a pointer from your function not the value. If you want to see the values as output you should iterate on the array and print out each element separately. Also note returning size of your output array from the function for easy iteration.
int* filtrationBiggerValues(int* values, int nrValues, int givenValue, int& outputSize) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
outputSize = j;
return new_array;
}
void main()
{
int y[] = { 1,2,100,18,20,94 };
int outputSize = 0;
int* output = filtrationBiggerValues(y, 6, 8, outputSize);
for(int i=0; i<outputSize; ++i)
{
cout<< output[i] <<"\n";
}
}
Update (If you want to keep signature of the function as it is)
int* filtrationBiggerValues(int* values, int nrValues, int givenValue) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
new_array[j] = 0;
return new_array;
}
void main()
{
int y[] = { 1,2,100,18,20,94 };
int* output = filtrationBiggerValues(y, 6, 8);
for(int i=0; output[i]>0; ++i)
{
cout<< output[i] <<"\n";
}
}
the name of the array is actually a pointer.
if you try this:
int main()
{
int y[] = { 1,2,100,18,20,94 };
cout << y <<endl;
cout<< filtrationBiggerValues(y, 6, 8)<<"\n";
return 0;
}
the output is two address
0x7ffd7ac2bc10
0xfadc30
So much to say:
int* new_array = NULL; C++ uses nullptr. I.e. int* new_array = nullptr;
However, you should inlue the initialization you do next line:
int* new_array = new int[nrValues];
But you just created a new object on the heap, that you don't delete. That is called a memory leak.. Nowadays we use unique pointers to help us there.
std::unique_ptr<int[]> new_array = new int[nrValues];
However, in C++ we have STL containers handle all the C-style array stuff for you. As new_array is a different size then values, you probably want to use std::vector, which has a dynamic size. The STL containers have something called iterators, which can go over the element more efficiently. However, the STL containers don't have default output functions, so you'll have to write your own.
#include<vector>
#include<iostream>
std::vector<int> getBiggerThen(std::vector<int> const& input, int givenValue) {
std::vector<int> output;
for (auto it = input.cbegin(); it != input.cend(); it++) {
if (*it > givenValue) {
output.push_back(*it);
}
}
return output;
}
std::ostream& operator<< (std::ostream& out, std::vector<int> const& vec) {
for (auto const& el : vec) out << el << " ";
return out;
}
int main() {
auto y = std::vector<int>{ 1,2,100,18,20,94 };
std::cout << getBiggerThen(y, 8) << "\n";
}
oh... also important: in C++ main should always return an int.
Finally, what you are doing is required so often, that the STL library has an built-in algorithm for it. Which can reduce everything to
#include<vector>
#include<algorithm>
#include<iostream>
int main() {
auto y = std::vector<int>{ 1,2,100,18,20,94 };
std::vector<int> output{};
int givenValue = 8;
std::copy_if(std::cbegin(y), std::cend(y), std::back_inserter(output),
[givenValue](int val) { return val >= givenValue; });
for (auto const& el : output) std::cout << el << " ";
std::cout << "\n";
}
I made a function to initialize a dynamic 3d array
void initialize_array_3d(char ***Array, int size1, int size2, int size3)
{
Array = new char**[size1];
for (int t=0; t<size1+1; t++)
{
Array[t] = new char *[size2];
for (int r=0; r<size2+1; r++)
{
Array[t][r] = new char [size3];
}
}
}
And it works fine but when I try to delete it with a function
void deinitialize_array_3d(char ***Array, int size1, int size2)
{
for (int t=0; t<size1+1; t++)
{
for (int r=0; r<size2+1; r++)
{
delete[] Array[t][r];
}
delete[] Array[t];
}
delete[] Array;
}
My program crashes, why? and how do i fix it?
In main:
int main()
{
char ***Failed;
initialize_array_3d(Failed, 5, 4, 2);
deinitialize_array_3d(Failed, 5, 4);
Failed = nullptr;
return 0;
}
For starters function initialize_array_3d is wrong. It should look at least the following way
void initialize_array_3d( char ****Array, int size1, int size2, int size3 )
^^^^^^^^^^^^^^
{
*Array = new char**[size1];
for ( int t = 0; t < size1; t++ )
^^^^^^^^^
{
( *Array )[t] = new char *[size2];
for ( int r = 0; r < size2; r++ )
^^^^^^^^^
{
( *Array )[t][r] = new char [size3];
}
}
}
That is the first parameter should be passed indirectly using pointer.
A function call might look like
initialize_array_3d( &Failed, 5, 4, 2);
^^^^^^^
Otherwise parameter char ***Array is a local variable of the function and the function deals with a copy of the argument. Any changes of the local variable do not influence on the original argument.
Or you could declare the parameter as reference to the pojnter. For example
void initialize_array_3d( char *** &Array, int size1, int size2, int size3 )
^^^^^^^^^^^^^^
{
Array = new char**[size1];
for ( int t = 0; t < size1; t++ )
^^^^^^^^^
{
Array[t] = new char *[size2];
for ( int r = 0; r < size2; r++ )
^^^^^^^^^
{
Array[t][r] = new char [size3];
}
}
}
In this case the function call might look like
initialize_array_3d( Failed, 5, 4, 2);
^^^^^^
As for function deinitialize_array_3d then it should look like
void deinitialize_array_3d(char ***Array, int size1, int size2)
{
for ( int t = 0; t < size1; t++ )
^^^^^^^^^
{
for ( int r = 0; r < size2; r++ )
^^^^^^^^^
{
delete[] Array[t][r];
}
delete[] Array[t];
}
delete[] Array;
}
You are using size1 + 1 to loop through your array instead of size1, but because the array is of size1, you can't access element size1. In the initialization you're getting away with it (it's undefined behavior), but you can't delete memory you don't own, so your program crashes.
Consider using a std::vector instead.
Why is the program below crashing? I tried debugging the code but couldn't understand; I am suspecting that either the program is wrong or the memory to the passed pointer to display function should have been initialized.
#include <iostream>
using namespace std;
int display( int** intarray )
{
int size = 0;
while( size < 10 )
{
*intarray[size] = size;
size++;
}
return size;
}
int main() {
int* intptrarray;
int arraysize = 0;
arraysize = display( &intptrarray );
for ( int indx = 0; indx < arraysize; indx++ )
{
std::cout << intptrarray[indx] << std::endl;
}
return 0;
}
When a pointer is declared, it doesn't point to any specific memory address. To have it point somewhere, you need to allocate memory to it as follows:
#include <iostream>
using namespace std;
int display( int** intarray, int arraysize )
{
int size = 0;
while( size < arraysize )
{
(*intarray)[size] = size;
size++;
}
return size;
}
int main() {
int arraysize = 10;
int* intptrarray = new int[arraysize];
arraysize = display( &intptrarray, arraysize );
for ( int indx = 0; indx < arraysize; indx++ )
{
std::cout << intptrarray[indx] << std::endl;
}
delete[] intptrarray;
return 0;
}
Whenever you allocate memory, you need to remember to deallocate it yourself (delete for a single variable, delete[] for an array).
*intarray[size] should be (*intarray)[size].
However you have not yet allocated any memory either, so in both cases you are causing undefined behaviour by writing through an uninitialized pointer.
A correct way to write this program is:
void display( std::vector<int> &vec )
{
vec.resize(10);
for ( int i = 0; i < 10; ++i )
vec[i] = i;
}
int main()
{
std::vector<int> vec;
display(vec);
for ( int indx = 0; indx < vec.size(); indx++ )
{
std::cout << vec[indx] << std::endl;
}
}
This can be improved by using std::iota and range-based for-loops if you have a modern compiler.
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.