I have this vector class, and I was provided with a driver to test the class. Most of it seems to work fine but I think there is something wrong with the exceptions part (which I haven't quite fully understood)
Here is the code for the class .cpp file
int myVector::at(int i)
{
if(i<vsize)
return array[i];
throw 10;
}
and here is the driver code
#include "myVector.h"
#include <iostream>
using namespace std;
int main()
{
// Create a default vector (cap = 2)
myVector sam;
// push some data into sam
cout << "\nPushing three values into sam";
sam.push_back(21);
sam.push_back(31);
sam.push_back(41);
cout << "\nThe values in sam are: ";
// test for out of bounds condition here
for (int i = 0; i < sam.size( ) + 1; i++)
{
try
{
cout << sam.at(i) << " ";
}
catch(int badIndex)
{
cout << "\nOut of bounds at index " << badIndex << endl;
}
}
cout << "\n--------------\n";
// clear sam and display its size and capacity
sam.clear( );
cout << "\nsam has been cleared.";
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
// Push 12 values into the vector - it should grow
cout << "\nPush 12 values into sam.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capcacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
cout << "\nTest to see if contents are correct...";
// display the values in the vector
for (int i = 0; i < sam.size( ); i++)
{
cout << sam.at(i) << " ";
}
cout << "\n--------------\n";
cout << "\n\nTest Complete...";
cout << endl;
system("PAUSE");
return 0;
}
Any help is appreciated. Thanks
The driver that you have provided:
try {
cout << sam.at(i) << " ";
}
catch(int badIndex) {
cout << "\nOut of bounds at index " << badIndex << endl;
}
expects that int will be thrown (a bit weird design, but well... this is the code that will use your class...). Your implementation of at() might look like this:
int& myVector::at(int i) throw(int) {
if (i < vsize)
return array[i];
throw i;
}
just try to follow one simple rule: throw by value, catch by reference.
Also note that you have a pointer:
private:
int* array;
which points to dynamically allocated memory allocated in constructor and copy constructor and freed in destructor :
myVector::myVector(int i)
{
...
array = new int[maxsize];
}
myVector::myVector(const myVector& v)//copy constructor
{
...
array =new int[maxsize];
}
myVector::~myVector()
{
delete[] array;
}
But how about the assignment operator ? See What is The Rule of Three?
Your stop condition of for loop ends it one element after the last one (i.e. you cannot access 4th element of sam vector because there are only three elements).
std::vector::at throws std::out_of_range exception in such situation (see: http://en.cppreference.com/w/cpp/container/vector/at), not int one. So you should change your exception handling part to something like this:
#include <exception>
try
{
cout << sam.at(i) << " ";
}
catch(std::out_of_range exc)
{
cout << "\nOut of bounds at index " << exc.what() << endl;
}
Related
So, I have a vector of boats. I need to access these boats and modify them (i.e. delete them) regularly, so it would be really nice if I could print their index along with all their other information, but I can't seem to figure out how.
The closest I got to it was with a simple for loop, but that eventually prints the current index along with the previous ones, as the vector size grows (since my i was < vector.size())
vector <Boat> berths_reg;
//print vector elements info
void Boat::print_info()
{
cout << endl;
for(int i = 0; i < berths_reg.size(); i++)
{
cout << "Index : " << i << endl;
}
cout << "Boat type : " << type << endl;
cout << "Boat length : " << length << endl;
cout << "Draft depth : " << draft << endl;
cout << endl;
}
//iterate through vector to print all elements
void print_vector()
{
vector <Boat> ::iterator it;
for (it = berths_reg.begin(); it != berths_reg.end(); ++it)
{
it->print_info();
}
}
//Storing boats (objects data) inside vector
void add_boat(Boat* b, string type, int length, int draft)
{
b->get_type(type);
b->get_length(length);
b->get_draft(draft);
berths_reg.push_back(*b);
}
Simply print both the index and the info within the same loop:
void print_vector()
{
for(int i = 0; i < berths_reg.size(); ++i)
{
cout << "Index : " << i << endl;
berths_reg[i].print_info();
}
}
In the following code, when run using GNU GCC v8.2.0, code does not terminate:
int main(void)
{
/* code */
int myArray[] = {2, 4};
int otherArray[] = {777, 888};
for(int i = 0; i<4; i++)
{
myArray[i] = 0;
cout << "myArray[" << i << "]=";
cout << myArray[i] << endl;
cout << "add: " << &myArray[i] << endl;
}
for(int i = 0; i<2; i++)
{
cout << "otherArray[" << i << "]=";
cout << otherArray[i] << endl;
cout << "add: " << &otherArray[i] << endl;
}
return 0;
}
output:
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]=0
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]=0
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]=0
add:0x28ff24
myarray[2]=0
add:0x28ff28
myarray[0]=0
add:0x28ff20
myarray[1]^C
for(int i = 0; i<4; i++)
Replace the 4 in the 'for loop' by 2 like this:
for(int i = 0; i<2; i++)
Since you're using a static array so it's better to specify the fixed size, but the most important is to be aware when you try to access the array by comparing the index being processed with the size of the array to avoid this behavior.
You are invoking undefined behaviour by writing the indexes 0-3 of the 2 element array myArray.
As this is undefined behaviour there are no guarantees as to what is happening or what will happen if you run the code again in the future. A likely explanation for your observed behaviour is that when you write myArray[2] that is actually overwriting the value of i causing your loop to restart back at 0.
The simple solution is to make myArray larger or change your for loop limit to 2.
To detect this sort of behaviour use std::array instead and call the at function which has bounds checking and will throw an exception when you go outside the bounds of the array. e.g.:
#include <array>
#include <iostream>
int main(void)
{
/* code */
std::array< int, 2 > myArray = { 2, 4 };
std::array< int, 2 > otherArray = { 777, 888 };
for(int i = 0; i<4; i++)
{
myArray.at(i) = 0;
std::cout << "myArray[" << i << "]=";
std::cout << myArray[i] << "\n";
std::cout << "add: " << &myArray.at(i) << "\n";
}
for(int i = 0; i<2; i++)
{
std::cout << "otherArray[" << i << "]=";
std::cout << otherArray.at(i) << "\n";
std::cout << "add: " << &otherArray.at(i) << "\n";
}
return 0;
}
std::array also has the bonus of a size() method which can make your code safer too:
for(int i = 0; i<myArray.size(); i++)
{
myArray.at(i) = 0;
std::cout << "myArray[" << i << "]=";
std::cout << myArray[i] << "\n";
std::cout << "add: " << &myArray.at(i) << "\n";
}
I'm trying to return a vector from a function. My code compiles and I've checked my function and reckon that the error comes from the return part. It compiles fine (using Cygwin) but when running it, I get an Aborted (core dumped) error.
Here is my code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//function that returns the square
int f(int n)
{
return n*n;
}
vector<int> myVec;
int counter = 0;
//function that uses f on all elements in a list
vector<int> map(vector<int> something)
{
//base case
if(counter == something.size())
{
/*cout << "hello" << endl;
for (int i=0; i<counter; i++)
{
cout << "vector: " << myVec[i] << endl;
}*/
counter=0;
return myVec;
}
//recursion
else
{
//cout << "counter: " << counter << endl;
int n = f(something[counter]);
//cout << "n: " << n << endl;
myVec.push_back(n);
//cout << "vector: " << myVec[counter] << endl;
counter++;
map(something);
}
}
int main()
{
//making vectors
vector<int> L;
vector<int> L1;
vector<int> L2;
for (int i=0; i<20; i++)
{
L.push_back(i);
}
L1 = map(L);
}
The code was originally from a class file.
In your recursion, you do not return anything. The function is expected to return a Vector.
In your case, what happens if the function enters the "else" case on its first call? It reenters map() until the condition is met, then returns a vector. That vector is passed to the previous recursive call and immediately deleted, as it is not passed any further.
The solution here would be to change the last line of the else-case to
return map(something);
so the value is not lost and correctly passed through to the original caller (your main function).
ALWAYS return a vector when your return type is a vector. In your function, there's a branch that won't return anything, and that will cause problems.
vector<int> map(vector<int>& something)
{
//base case
if(counter == something.size())
{
/*cout << "hello" << endl;
for (int i=0; i<counter; i++)
{
cout << "vector: " << myVec[i] << endl;
}*/
counter=0;
return myVec;
}
//recursion
else
{
//cout << "counter: " << counter << endl;
int n = f(something[counter]);
//cout << "n: " << n << endl;
myVec.push_back(n);
//cout << "vector: " << myVec[counter] << endl;
counter++;
map(something); //you should return a vector here
return std::vector<int>(); //empty vector
}
}
Also notice the "&" symbol I added at the function call so that the vector is passed by reference. Otherwise you're passing a copy that won't be changed. I don't know what that "map" function does, so I can't suggest better models to what you're doing.
So here is my working code for a simple dynamic array. This has to be a sample code for a very entry level data structure implementation:
#include <iostream>
using namespace std;
class AdvancedArray {
public:
AdvancedArray();
~AdvancedArray();
int get_size() const; // get the number of elements stored
double& at(int idx) const; // access the element at idx
void push_back(double d); // adds a new element
void remove(int idx); // remove the element at idx
void clear(); // delete all the data stored
void print() const;
private:
double* elements;
int size;
};
int main()
{
AdvancedArray* arr = new AdvancedArray();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "Pusing Values: 1.2, 2.1, 3.3, 4.5 in the Array. " << endl;
arr->push_back(1.2);
arr->push_back(2.1);
arr->push_back(3.3);
arr->push_back(4.5);
arr->print();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "The Element at Index 2 is: " << arr->at(2) << endl;
cout << "Deleting Values: 2.1 from the Array. " << endl;
arr->remove(1);
cout << "The Array Size is: " << arr->get_size() << endl;
arr->print();
cout << "Clearing the Array: " << endl;
arr->clear();
cout << "The Array Size is: " << arr->get_size() << endl;
arr->clear();
return 0;
}
AdvancedArray::AdvancedArray()
{
size = -1;
elements = new double[100]; //Maximum Size of the Array
}
AdvancedArray::~AdvancedArray()
{
delete[] elements;
}
int AdvancedArray::get_size() const
{
if(size < 0)
{
return 0;
}
return size;
}
double & AdvancedArray::at(int idx) const
{
if (idx < 100 && idx >= 0 && size > 0) {
return elements[idx];
}
cout << "Index Out of Bounds." << endl;
}
void AdvancedArray::push_back(double d)
{
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
}
void AdvancedArray::remove(int idx)
{
if (size >= 100 || size < 0)
{
cout << "No Such Element Exists!" << endl;
}
else
{
for(int i = idx; i <size; i++)
{
elements[idx] = elements[idx + 1];
}
size--;
cout << "Element Deleted In Stack Successfully!" << endl;
}
}
void AdvancedArray::clear()
{
delete[] elements;
size = -1;
}
void AdvancedArray::print() const
{
cout << "[ ";
for(int i = 0; i <= size; i++)
{
cout << elements[i] << " ";
}
cout << "]" << endl;
}
So every time I try to run this I have the 2 problems:
What is wrong with my code? Why is the heap getting corrupted (I searched about the error code and that's all has to say)? Is my code doing some major access violations? I am using VS2015.
You do delete [] elements three times without setting elements to nullptr in between. That leads to undefined behavior the second time (and third) time.
When size == 99, the following piece of code attempts to access elements[100]:
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
You need to change ++size to size++.
In this program, I am using template class, I have a header file and this is my main file. I am having trouble displaying the (".....") IndexOutOfBounds and displaying it on the screen.
#include "XArray.h"
#include <iomanip>
#include <string>
using namespace std;
template<class T>
void afriend ( XArray<T> );
int main()
{
XArray<double> myAD(18);
myAD.randGen(15, 100);
cout << myAD.getType() << endl;
cout << setprecision(1) << fixed << "\n\n Unsorted: " << myAD;
myAD.sort();
cout << "\n Now Sorted: " << myAD;
cout << "\n\n";
**try
{
cout << "A[-5] = " << setw(6) << myAD[-5] << endl;
}
catch(XArray<double>::IndexOutOfBound e)
{
e.print();
}
try
{
cout << "A[8] = " << setw(6) << myAD[8] << endl;
}
catch(XArray<double>::IndexOutOfBound e)
{
e.print();
}**
cout << "\n\n" << setprecision(2) << fixed;
cout << "Size = " << setw(6) << myAD.getSize() << endl;
cout << "Mean = " << setw(6) << myAD.mean() << endl;
cout << "Median = " << setw(6) << myAD.median() << endl;
cout << "STD = " << setw(6) << myAD.std() << endl;
cout << "Min # = " << setw(6) << myAD.min() << endl;
cout << "Max # = " << setw(6) << myAD.max() << endl;
return 0;
}
There is the Array.h file posted as a dropbox link
Array.h
The code for operator[] in Array.h is:
template <class T>
T XArray<T>::operator[] (int idx)
{
if( (idx = 0) && (idx < size) )
{
return Array[idx];
}
else
{
throw IndexOutOfBound();
return numeric_limits<T>::epsilon();
}
}
Although the question is somewhat obscure, give a try to these suggestions.
Firstly, it can happen that XArray<>::IndexOutOfBounds have no proper copy ctor. You can try catching by const reference to workaround that:
try
{
...
}
catch(const XArray<double>::IndexOutOfBound& e)
{
e.print();
}
Index operator in standard library containers does not check for bounds, there is a special getter that does the check called at(). If the XArray class is designed with standard library in mind, it could behave similarly.
However to get more adequate response you need to be more specific describing the trouble you are having.
I'm still wondering what exact question is.
However, I'm understanding the question is that how I can use 'catch' by using 'IndexOutOfBound'.
#include <exception>
#include <iostream>
using namespace std;
template <typename T>
class Array
{
private:
int m_nLength;
T *m_ptData;
public:
...
...
T& operator[](int nIndex)
{
//assert(nIndex >= 0 && nIndex < m_nLength);
if(nIndex < 0 || nIndex > m_nLength)
{
throw myex;
}
else
{
return m_ptData[nIndex];
}
}
//class definition for 'IndexOutOfBound'
class IndexOutOfBound: public exception
{
public:
virtual const char* print() const throw()
{
return "Exception occured 'Index Out Of Bound'";
}
}myex;
};
int main()
{
Array<double> arr(3);
try
{
arr[0] = 1;
//exception will occur here.
arr[4] = 2;
}
catch(Array<double>::IndexOutOfBound &e)
{
cout << e.print() << '\n';
}
return 0;
}
Here is no 'XArray.h', so I've written a sample array class for example.
The problem is in the operator[] function. The code idx = 0 sets idx to 0. So all of your calls to operator[] will return the first element, and therefore there is no out-of-bounds error unless the array is empty.
You probably meant to write if ( idx >= 0 && idx < size ).
BTW the throw aborts the function, it makes no sense to return after throw.