Vector subscript out of range on iterator - c++

#include <iostream>
#include <random>
#include <fstream>
#include <time.h>
using namespace std;
bool generateRandomValue()
{
static std::default_random_engine e{};
static std::uniform_int_distribution<int> d{ 0, 100 };
bool headsTails = (d(e) > 50) ? true : false;
return headsTails;
}
int main()
{
clock_t tStart = clock();
ofstream outputFile("output.txt");
int totalHeads = 0;
int totalTails = 0;
vector<int> headList(100,0);
vector<int> tailList(100,0);
for (int out = 0; out <= 100; out++)
{
char result = '\0';
int heads = 0, tails = 0;
for (int i = 0; i < 100000; i++)
{
result = (generateRandomValue()) ? 'H' : 'T';
if (result == 'H')
{
heads++;
}
else
{
tails++;
}
}
outputFile << "Trial " << out << ": Heads: " << heads << " Tails: " << tails << endl << endl;
headList.push_back(heads);
tailList.push_back(tails);
}
for (vector<int>::iterator i = headList.begin(); i < headList.end(); i++)
{
totalHeads += headList[*i];
totalTails += tailList[*i];
}
cout << "It took: " << (double)(clock() - tStart) / CLOCKS_PER_SEC << " seconds to calculate and execute this program.\n";
outputFile << "Total number of heads: " << totalHeads << " Total number of tails: " << totalTails << endl;
return 0;
}
Above is some code I've been messing with just to try out vectors (never used them in class). The code compiles in VS2015, but the program crashes with the following error: "Vector subscript out of range".
I assume this is telling me that at some point in my program a vector is attempting to be addressed at a location outside of its bounds. I haven't been able to tell whether the error is being thrown on my storage vectors or the iterator vector in the last for loop, and debugging doesn't work because the program crashes before it can begin to debug (weird that it isn't a compile time error then).

In this code:
for (vector<int>::iterator i = headList.begin(); i < headList.end(); i++)
{
totalHeads += headList[*i];
totalTails += tailList[*i];
}
iterator i iterates over all elements of headList vector. *i gives you that value (which is amount of heads in that iteration). You use that as an index for vectors totalHeads and totalHeads which seams to be wrong. Your loop should be:
for (size_t i = 0; i < headList.size(); i++)
{
totalHeads += headList[i];
totalTails += tailList[i];
}
Note: though this loop:
for (vector<int>::iterator i = headList.begin(); i < headList.end(); i++)
works for random access iterator, it is more common to write it in form:
for (vector<int>::iterator i = headList.begin(); i != headList.end(); ++i)
this way it will also work for forward iterator and you may change container type without modifying much code. ++i can be more efficient especially for iterator, not integral type.

Related

Assigning values to multidimensional vector

I´m trying to assign values to a multidimensional vector, but I always get an "R6010 - abort()" error from visual studio.
What I want is an two dimensional vector, where the second dimension is exactly as large as needed. (Important because I don't now how many input values and I want to use later myvector.at(i).size();
So to formulate it short: Why is the following example not working?
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector < vector < int > > Vektor;
Vektor.resize(10);
int tmp;
while (true) {
cout << "Please enter a value: " << endl;
cin >> tmp;
int size;
if (tmp > 0 & tmp < 11) {
Vektor.at(tmp - 1).push_back(tmp);
}
for (int i = 1; i < 11; i++) {
size = Vektor.at(i).size();
for (int j = 0; j < size; j++) {
cout << "Value at " << i << " , " << j << " : " << Vektor.at(i).at(j) << endl;
}
}
}
return 0;
}
You are using wrong indices in the lines:
for (int i = 1; i < 11; i++) {
size = Vektor.at(i).size();
Change the lines to:
| ||
v vv
for (int i = 0; i < 10; i++) {
size = Vektor.at(i).size();
As already answered by #RSahu, you use wrong indices in a loop. In stead of correcting the values, I'll suggest that you avoid hard coded values.
That can be done in several ways. By using vector.size() your code is easy to fix. Just use these two lines instead of your current two lines:
if (tmp > 0 & tmp <= Vektor.size()) {
for (int i = 0; i < Vektor.size() ; i++) {
An alternative way of printing could be
size_t i = 0;
for (const auto& v : Vektor)
{
size_t j = 0;
for (const auto e : v)
{
cout << "Value at " << i << " , " << j << " : " << e << endl;
++j;
}
++i;
}

Insertion sort implementation in C++ results in multiple errors

This is a console application on CodeBlocks 13.12.
I am getting a variety of errors when I run this Insertion Sort.
Sometimes it prints outrageously large values that weren't in the original array. Or sometimes it runs and sorts the array perfectly fine.
Can anybody please point out what could possibly be wrong? Sorry I'm a noob.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
void insertionSort(int arr[], int size);
int main()
{
int size;
srand(time(NULL));
cout << "Specify the size of your array: ";
cin >> size;
int theArray[size]; // creates an array of a size the user chooses
cout << endl << "Your current array: {";
for (int i = 0; i < size; i++) //prints out the original array
{
theArray[i] = rand() % 10000;
cout << theArray[i];
if (i != size - 1) // to beautify output
{
cout << ", ";
}
if (i % 10 == 0 && i != 0)
{
cout << endl;
}
}
cout << "}" << endl << endl;
insertionSort(theArray, size);
}
void insertionSort(int arr[], int size)
{
int begin = clock(); // are for timing the sort
for (int i = 0; i < size; i++) //does the sorting
{
int j = i + 1;
int temp = arr[j];
while (arr[i] > arr[j])
{
arr[j] = arr[i];
arr[i] = temp;
j--;
i--;
}
}
int end = clock(); // are for timing the sort
cout << endl << "Your sorted array is: {";
for (int i = 0; i < size; i++) // prints out sorted array
{
cout << arr[i];
if (i != size - 1)
{
cout << ", ";
}
if (i % 10 == 0 && i != 0)
{
cout << endl;
}
}
cout << "}" << endl << endl << "Your sort took: " << end - begin << " milliseconds" << endl << endl;
}
Additionally to #marom's answer, in your while loop, you don't put limitations neither on i or j, hence you try to access arr[-1], arr[-2] and so on. Also, you go back to the beginning of the sorted array, since you decrement i. Have a look at this code, compiled with g++ 4.8.1 gives no errors. Also, try to use std::swap defined in header <utility> since c++11 or in header <algorithm> until c++11.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <utility>
using namespace std;
void insertionSort(int arr[], int size);
int main()
{
int size;
srand(time(NULL));
cout << "Specify the size of your array: ";
cin >> size;
int theArray[size]; // creates an array of a size the user chooses
cout << endl << "Your current array: {";
for (int i = 0; i < size; i++) //prints out the original array
{
theArray[i] = rand() % 10000;
cout << theArray[i];
if (i != size - 1) // to beautify output
{
cout << ", ";
}
if (i % 10 == 0 && i != 0)
{
cout << endl;
}
}
cout << "}" << endl << endl;
insertionSort(theArray, size);
}
void insertionSort(int arr[], int size)
{
int begin = clock(); // are for timing the sort
for (int i = 0; i < size - 1; i++) //does the sorting
{
int j = i + 1;
int temp = arr[j];
while (j > 0 && arr[j] < arr[j - 1])
{
// ^^ this ensures that we don't try to access arr[-1]
swap(arr[j], arr[j-1]); //prefer std functions if they do the job you want
j--;//we don't go back
}
}
int end = clock(); // are for timing the sort
cout << endl << "Your sorted array is: {";
for (int i = 0; i < size; i++) // prints out sorted array
{
cout << arr[i];
if (i != size - 1)
{
cout << ", ";
}
if (i % 10 == 0 && i != 0)
{
cout << endl;
}
}
cout << "}" << endl << endl << "Your sort took: " << end - begin << " milliseconds" << endl << endl;
}
At least this is wrong:
void insertionSort(int arr[], int size)
{
int begin = clock(); // are for timing the sort
for (int i = 0; i < size; i++) //does the sorting
{
int j = i + 1;
When i is size-1 then j equals size and you get over the bounds of the array (valid values are from 0 to size-1 included). You need to limit your for loop to i < size-1
First advice : don't do all your printing or clock measure in your sort function. Keep that for your main program. Your sort function must remain clear and concise with no side effect.
Now, i find it better to split the code into 2 simple functions :
First, if arr is assumed already sorted up the index n-1
you want to insert the adequate element of the table at pos offset so that
arr will be sorted up to index n:
void insert(int arr[], int n){
int i=n, temp=arr[n];
while ( (arr[i-1]>temp) && (i>0) )
{
arr[i]=arr[i-1];
i--;
}
arr[i]=temp;
}
Now we just have to call our insertion for all offsets in arr except first one:
void insertionSort(int arr[], int size)
{
for(int n=1; n<size; n++) insert(arr,n);
}
As already mentioned by marom in his answer, when i = size - 1 you set j = size and access memory out of bounds, similarly, consider the case where j is set to the smallest element in the array, in that case you reach the left most position of the array by swapping the elements and decrementing, and eventually, i will become negative (since you do not put a bound to check if i becomes less than 0) and so will j and you will be accessing memory out of your bounds again.
Moreover, you are decrementing the value of i as well, which does not make sense, since by decrementing the value of i you are making extra runs for the external for loop.
So, your function shall look something like this ::
for (int i = 0; i < size - 1; i++) //changed the limit of for loop
{
int j = i + 1;
int temp = arr[j];
while ((j > 0) && (arr[j - 1] > arr[j])) //instead of working with the values of i, now we are doing everything with j
{
arr[j] = arr[j - 1];
arr[j - 1] = temp;
j--;
}
}
Hope this helps!

c++ sort: ranking list with same value of an array

I'm trying to show a ranking list of my array qt, which contains 5 numbers.
int i, j;
int qt[5] = {10,20,10,50,20};
int tempqt;
for (i=0; i<5; i++)
{
for(j=(i+1); j<5; j++)
{
if (qt[i] >= qt[j])
{
tempqt = qt[i];
qt[i] = qt[j];
qt[j] = tempqt;
}
}
}
for(i=0; i<5; i++)
{
cout << i+1 << ".number: " << qt[i] << endl;
}
normally, the 2 for-loops sort my array and the last for-loop displays my array ordered, so it looks like this:
1.number: 10
2.number: 10
3.number: 20
4.number: 20
5.number: 50
But I want to display the numbers with the same value as the same ranking position, so like this:
1.number: 10
1.number: 10
2.number: 20
2.number: 20
3.number: 50
The idea is to increase rank counter when meet different value in qt array.
i = 0;
int rank = 1, val = qt[i];
cout << rank << ".number: " << qt[i] << endl;
for(i=1; i<5; i++)
{
if (qt[i] != val) {
++rank;
val = qt[i];
}
cout << rank << ".number: " << qt[i] << endl;
}
Use std::sort to sort the array -- you won't get anywhere until the array is sorted.
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int qt[5] = { 10, 20, 10, 50, 20 };
sort(qt, qt + 5);
int count = 1;
for (int i = 0; i < 5; ++i)
{
if (i > 0)
{
if (qt[i] != qt[i - 1])
++count;
}
cout << count << ".number: " << qt[i] << endl;
}
}
Here is another solution using a map. This is more "lazy" in that there is no real "check if number already seen" logic involved. Just add numbers to a map, and print out the results in a loop.
If there are no memory constraints (you will need to create a map of the numbers, of course), and/or you need the array to remain stable (not sorted), then this could be an alternative.
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int qt[5] = { 10, 20, 10, 50, 20 };
std::map<int, int> IntMap;
// add entries to map, adding to a counter each time
for (int i = 0; i < 5; ++i)
IntMap[qt[i]]++;
// output the results.
int count = 1;
for (auto it = IntMap.begin(); it != IntMap.end(); ++it, ++count)
{
for (int i = 0; i < it->second; ++i)
cout << count << ".number: " << it->first << endl;
}
}
The map already sorts, so that's taken care of. Then the map is set up to count the number of times each number shows up, so that's taken care of. The only thing left is to write a loop that just goes through the map and prints the information.
See it here: http://ideone.com/q08SeX
I'd rather use a do while loop:
int p = 1, x = 0;
do
{
cout << p << ".number: " << qt[x++] << endl;
if (x < 5 && qt[x] != qt[x-1])
p++;
} while (x < 5);

Print an array in C++

I'm trying to do some of my C++ homework, but I seem to have run into an issue. I need to make it so that the user inputs 8 numbers, and those said 8 get stored in an array. Then, if one of the numbers is greater than 21, to output said number. The code is below, and it's kind of sloppy. Yes, first year C++ learner here :p
#include <iostream>
using namespace std;
int main() {
const int NUM_ELEMENTS = 8; // Number of elements
int userVals[NUM_ELEMENTS]; // User numbers
int i = 0; // Loop index
int sumVal = 0; // For computing sum
int prntSel = 0; // For printing greater than 21
// Prompt user to populate array
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < NUM_ELEMENTS; ++i) {
cin >> userVals[i];
}
for (int i = NUM_ELEMENTS - 1; i > 21; i--)
cout << "Value: " << sumVal << endl;
// Determine sum
sumVal = 0;
for (i = 0; i < NUM_ELEMENTS; ++i) {
sumVal = sumVal + userVals[i];
}
cout << "Sum: " << sumVal << endl;
return 0;
}
Don't reinvent the wheel, use standard algorithms:
std::copy_if(std::begin(userVals), std::end(userVals),
std::ostream_iterator<int>(std::cout, "\n"),
[] (auto x) { return x > 21; });
I improved the rest of your program as well:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
auto constexpr count = 8;
int main() {
std::vector<int> numbers(count);
std::cout << "Enter " << count << " integer values...\n";
std::copy_n(std::istream_iterator<int>(std::cin), numbers.size(), numbers.begin());
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"),
[] (auto x) { return x > 21; });
auto sum = std::accumulate(numbers.begin(), numbers.end(), 0);
std::cout << "Sum: " << sum << '\n';
return 0;
}
See it live on Coliru!
Ok, I'm going to explain this to you and keep it simple. This loop
`for (int i = NUM_ELEMENTS - 1; i > 21; i--)`
will never execute because in your first iteration you are checking if (NUM_ELEMENTS-1=7)>21. You are then decrementing i so this will take the series (6,5,4,...) and nothing would ever happen here.
If you have to sum the numbers greater than 21, which I presume is what you need then you will have to remove the above loop and modify your second loop to:
for (i = 0; i < NUM_ELEMENTS; i++) {
if(userVals[i]>21)
sumVal = sumVal + userVals[i];
}
This way, you add the numbers in the array that are only greater than 21. The index of userVals is determined by the i variable which also acts as a counter.
You're on the right track. There's just a few things wrong with your approach.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const int NUM_ELEMENTS = 8;
int userVals[NUM_ELEMENTS];
int i = 0;
int sumVal = 0;
int prntSel = 0;
int size = sizeof(userVals) / sizeof(int); // Get size of your array
// 32/4 = 8 (ints are 4 bytes)
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < NUM_ELEMENTS; ++i) {
cin >> userVals[i];
}
for(int i = 0; i < size; i++) {
if(userVals[i] > 21) { // Is number > 21?
cout << userVals[i] << endl; // If so, print said number
exit(0); // And exit
}
else
sumVal += userVals[i]; // Else sum your values
}
cout << "Sum: " << sumVal << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
const int NUM_ELEMENTS = 8; // Number of elements
int userVals[NUM_ELEMENTS]; // User numbers
int i = 0; // Loop index
int sumVal = 0; // For computing sum
int prntSel = 0; // For printing greater than 21
// Prompt user to populate array
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < NUM_ELEMENTS; ++i) {
cin >> userVals[i];
}
// for (int i = NUM_ELEMENTS - 1; i > 21; i--)
// cout << "Value: " << sumVal << endl;
for( i = 0; i < NUM_ELEMENTS; ++i )
{
if( userVals[ i ] > 21 )
{
cout << "Value: " << i << " is " << userVals[ i ] << endl;
}
}
for (i = 0; i < NUM_ELEMENTS; ++i) {
sumVal = sumVal + userVals[i];
}
cout << "Sum: " << sumVal << endl;
return 0;
}
Try
for (int i = NUM_ELEMENTS - 1; i > 21; i--)
cout << "Value: " << sumVal << endl;
to
for (i = 0; i < NUM_ELEMENTS; ++i) {
if(userVals[i] > 21)
cout << "Value: " << userVals[i] << endl;
}
This line isnt needed as well, as you arent using it.
int prntSel = 0; // For printing greater than 21
for (int i = NUM_ELEMENTS - 1; i > 21; i--)
cout << "Value: " << sumVal << endl;
Here you are printing the value of sumVal, not the value of the array in the position i. The line should be:
cout << "Value: " << usersVals[i] << endl;
Also that that your for is not doing what you think it does. for doesn't use the condition you gave to decide if will execute the current iteration or not, it uses the condition to decide if the loop should continue or not. So when you put i > 21, means that it will continue running while i is bigger than 21. To achieve your goal, you should make a test (if statement) inside the loop.
The final result it would be:
for (i = 0; i < NUM_ELEMENTS; ++i) {
if (usersVals[i] > 21) {
cout << "Value: " << usersVals[i] << endl;
}
}

Population program in C++

I'm in desperate need of assistance.
I'm working on a population program in C++ for my Systems Software class.
This is my first foray into C++ territory, I only have some Java knowledge to help me out.
Basically, the program is supposed simulate a simple population. The guidelines are as follows:
The first elements (starting population) have random age and sex.
2 elements can pair if their lifespan falls between [0.25,0.50] (assuming they die at 1) and they are of the opposite sex.
Each element can only pair twice.
So here's my code, and take it easy guys I'm not very well versed in C++ yet...:
#include <vector>
#include <ctime>
#include <stdlib.h>
#include <iostream>
#include <iterator>
using namespace std;
class Element {
public:
int pair;
double life;
int tag;
void setValues(double, int);
int getPair() {
return pair;
}
void incrementPair() {
pair = pair++;
}
double getLife() {
return life;
}
void incrementLife() {
life = life + 0.05;
}
int getTag() {
return tag;
}
}; //Element
void Element::setValues(double b, int c) {
pair = 0;
life = b;
tag = c;
}
int main() {
double Time = 0.0;
srand(time(NULL));
vector<Element> vec;
for (int i = 0; i<50; ++i) {
Element x;
x.setValues(((double) rand() / (RAND_MAX)), rand()%2);
vec.push_back(x);
}//for
while (vec.size() != 0) {
int newPopCount = 0;
int Dead = 0;
for(int count = 0; count != vec.size(); ) {
std::vector<Element>::iterator p = vec.begin();
std::vector<Element>::iterator i = vec.begin() + 1;
if ((p->getPair() == 2) || (p->getLife() < 0.25) || (p->getLife() > 0.50)) {
count++;
p++;
}//if
else {
for(int count1 = count + 1 ; count1 != vec.size() ; ) {
if ((i->getLife() < 0.25) || (i->getLife() > 0.50) || (i->getPair() == 2) || (p->getTag() == i->getTag())) {
++i;
count1++;
}//if
else {
cout << i->getTag() << " " << p->getTag() << endl;
cout << i->getPair() << " " << p->getPair() << endl;
cout << i->getLife() << " " << p->getLife() << endl;
p->incrementPair();
i->incrementPair();
newPopCount++;
count1++;
count++;
p++;
i++;
}//else
}//for
}//else
}//for
Time += 0.05;
for ( vector<Element>::iterator m = vec.begin(); m != vec.end(); ++m ) {
m->incrementLife();
if ( m->getLife() >= 1.00 ) {
Dead++;
//vec.clear();
vec.erase(m);
//vec.shrink_to_fit();
}//if
for (int i = 0; i = newPopCount; i++) {
Element woo;
woo.setValues(0.0, rand()%2);
vec.push_back(woo);
}//for
}//for
cout << "The total number of dead is: " << Dead << endl;
cout << "The total number born is: " << newPopCount << endl;
cout << "Current population is: " << vec.size() << endl;
cout << "Population has survived for: " << Time << endl;
sleep(1);
}//while
cout<< "The populace is now extinct." << endl;
cout<< "The populace survived for: " << Time << endl;
}//main
You can see my silly debugging methods, I was getting a Segmentation Fault error before, but I believe that to be fixed. The issue now is that I'm getting stuck in the loops. The program seems to run almost erratically, and I can't pinpoint the issue any closer than inside of one of the loops.
My Dead integer is incremented and displayed properly, but the newPopCount integer is not, which makes no sense to me.
Also the program never gets out of the while loop, it will continue until it gets stuck in another of the many loops I have.
I have had several other issues, which I've been fixing slowly but surely as you can see by my patchwork code.
Any help at all will be greatly appreciated.
Two obvious issues, which your compiler will warn you about if you turn up your warnings high enough.
First:
void incrementPair() {
pair = pair++;
}
This is undefined behavior. Should be just:
void incrementPair() {
++pair;
}
Second:
for (int i = 0; i = newPopCount; i++) {
Element woo;
woo.setValues(0.0, rand()%2);
vec.push_back(woo);
}
That condition in your for loop is almost certainly wrong. It likely should be i <= newPopcount, or something like that.
As a side note, your setValues() member function looks like it's doing the job that a constructor should be doing.
EDIT: Look here:
for(int count = 0; count != vec.size(); ) {
std::vector<Element>::iterator p = vec.begin();
std::vector<Element>::iterator i = vec.begin() + 1;
Imagine you have a std::vector with only one element in it, and then think about what i is going to represent when you do i->getLife() a few lines later. Just having those definitions inside the for loop looks a bit suspicious in itself, since you increment both p and i during the loop, but you're going to reset them again on every iteration, but it's not all that easy to follow the logic, so perhaps that's what you intended.
vec.erase(m); results in an invalid m. You want to do m = vec.erase(m)