I am new at programming at c++, and when I run this, it compiles successfully and outputs the elements of the array but I get an error that says "vector subscript out of range". What is wrong with this code? I looked at some other questions and it did not seem like any of the others had similar examples of vectors.
#include <iostream>
#include <vector>
#include <random>
#include <time.h>
using namespace std;
int main() {
srand(time(NULL));
int arraysize;
cout << "Enter the size of your array:" << endl;
cin >> arraysize;
vector<int> numbers(arraysize);
vector<int>::size_type sizecheck = numbers.size();
cout << "This is the unsorted array:" << endl;
for (int z = 0; numbers[z] < sizecheck; z++)
{
numbers[z] = rand() % 10 + 1;
cout << numbers[z] << endl;
}
return 0;
}
Your code actually would be an infinite loop given infinite memory, however, since there is a finite amount of memory allocated for your vector, it exhibits undefined behavior. numbers will value initialize (set each element to 0), meaning that the condition is always going to be 0 < sizecheck. Once z reaches the amount of elements in your vector, you exceed the array bounds and wander into undefined behavior land.
Your IDE or whatever you're using already caught the error, but you can use the safer variant, at() instead of operator[]. This will throw an exception and provide useful information. For example:
for (int z = 0; numbers.at(z) < sizecheck; z++)
{
numbers.at(z) = rand() % 10 + 1;
cout << z << " " << numbers.at(z) << endl;
}
0 2
1 8
2 10
3 9
4 8
5 2
6 3
7 4
8 4
9 2
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 10) >= this->size() (which is 10)
As stated in the comments, what you probably meant to do was z < sizecheck, although you should make z of type std::vector<int>::size_type just to be safe.
#remyabel has given you the absolutely correct answer, but in addition to that you should consider using an iteratorrather than an indexed for loop when looping over standard components like vector.
e.g.
vector<int>::iterator it;
for(it = numbers.begin(); it != numbers.end(); ++it)
{
*it = rand() % 10 + 1;
cout << *it << endl;
}
Note: this is only suitable if you are changing the number of elements in the vector as you iterate, as is happening in this case. If you add or remove elements during the iteration you may invalidate your iterator.
Related
This question already has answers here:
sizeof() a vector
(6 answers)
Closed 2 years ago.
I'm currently working on a final project for one of my introductory classes in college, and I can't seem to find out why my output is cutting out prematurely. I'm trying to append the lines of a text file in the same directory into a vector and randomly select from the vector to get a name for an enemy in a text-based fighting game, but during testing it seems like the vector either only contains three items or the last for loop (the one before the comment blocks, I'm working on it in chunks) only displays three of the possible names. Here's the code:
#include <iostream>
#include <fstream>
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <ctype.h>
using namespace std;
int main() {
srand(time(0));
int userInput;
int player_health = 100;
int boss_health = 200;
int boss_index = rand() % 3;
ifstream boss_list;
string boss_name = "";
string boss_inputs[3] = {"MACHINE GUN", "BOMB ATTACK", "CANE SMACK"};
string user_inputs[3] = {"SWORD ATTACK", "BOMB ATTACK", "MAGIC ATTACK"};
vector<string> boss_list_holder = {};
unordered_map<string, int> attacks = {
{"SWORD ATTACK", rand() % 100},
{"BOMB ATTACK", rand() % 100},
{"MAGIC ATTACK", rand() % 100}
};
unordered_map<string, int> boss_attacks = {
{"MACHINE GUN", rand() % 75},
{"BOMB ATTACK", rand() % 80},
{"CANE SMACK", rand() % 50}
};
boss_list.open("names.txt", ios::in);
while(getline(boss_list, boss_name)) {
//cout << boss_name << endl;
boss_list_holder.push_back(boss_name);
}
for(int j=0; j<(sizeof(boss_list_holder)/sizeof(boss_list_holder[0])); j++) {
cout << boss_list_holder[j] << endl;
}
//cout << "BOSS FIGHT SIMULATOR\n\n";
/*
while(userInput > 3 || userInput < 1) {
cout << "Enter the attack you want to use!\n";
for(int i=0; i<sizeof(user_inputs)/sizeof(user_inputs[0]); i++) {
cout << i + 1 << ". " << user_inputs[i] << " ";
}
cout << "\n";
cin >> userInput;
};
*/
/*
cout << boss_inputs[boss_index] << " ";
cout << boss_attacks[boss_inputs[boss_index]];
*/
return 0;
}
Any and all help would be appreciated. Thank you!
sizeof(boss_list_holder)/sizeof(boss_list_holder[0])
This is a very old-fashioned way of deducing the length of an array, and indeed it only works for arrays.
It doesn't even work on pointers, which people often have instead of arrays without realising it, so std::size(boss_list_holder) is a better general solution.
In your case, simply boss_list_holder.size() is your best bet.
You should also be using unsigned int (or, ideally, std::size_t) for array or vector indices, and your compiler will warn you about unsafe signed/unsigned comparisons if you stick with int.
(Some people will go further and recommend std::vector<string>::size_type, though personally I think that's overkill.)
Your for loop over the boss_list_holder vector is wrong:
for(int j=0; j<(sizeof(boss_list_holder)/sizeof(boss_list_holder[0])); j++)
This sizeof trick only works for fixed-sized arrays (like your user_input), where the elements are stored directly in the allocated memory of the array itself.
This does not work for dynamic containers like std::vector, which boss_list_holder is an instance of. The elements of a std::vector are not stored in the allocated memory of the std::vector object itself (ie, sizeof(boss_list_holder) is not equal to sizeof(string) * NumberOfStrings). They are stored in an array that is allocated elsewhere in memory, and the std::vector object simply holds a pointer to that array (amonst other things).
You need to use the vector's size() method instead, that will return the number of elements that have been put into the std::vector's inner array:
for(size_t j = 0; j < boss_list_holder.size(); ++j)
I want to know why the error appears when the code just gets into the function '
sort'
I made some check points using standard output. So I know where the error occurs.
I use repl.it to build this code
...
/*return pivot function*/
int partition(...){
...
}
void sort(vector<int> array, int left, int right){\
/*********"sort start" string dose not appear in console***********/
cout << "sort start";
// one element in array
if(left == right);
// two elements in array
else if( left +1 == right){
if(array.at(0) > array.at(1)){
int temp;
swap(array.at(0),array.at(1),temp);
}
}
// more then 3 elements in array
else{
int p = partition(array,left,right);
sort(array,left,p-1);
sort(array,p+1,right);
}
}
int main() {
vector<int> array;
array.push_back(1);
array.push_back(2);
array.push_back(3);
array.push_back(4);
cout << "array is ";
for(int i = 0 ; i < array.size(); i++){
cout << array.at(i) << " ";
}
cout << endl;
sort(array,0,array.size()-1);/***************sort is here*************/
cout << "sorting..." << endl;
cout << "array is ";
for(int i = 0 ; i < array.size(); i++){
cout << array.at(i) << " ";
}
return 0;
}
When I run this code console output is
array is 4 3 2 2
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 18446744073709551615) >=
this->size() (which is 4)
exited, aborted
But what I expected is
array is 4 3 2 2
sorting...
sort start
array is 2 2 3 4
You are trying to access an element at index -1, which, when converted into 64-bit unsigned value, is 18446744073709551615. Live demo: https://wandbox.org/permlink/jAhJZS3ANjkDDOUr.
There are multiple problems with your code and, first of all, you don't show us the definition of your partition and swap. Moreover, your code does not match the provided output (1 2 3 4 vs 4 3 2 2 in the first line).
Anyway, one of the problems is that you don't check for cases where left is higher than right. That can easily happen. Consider that in the very first call of sort, partition returns 0 (pivot position). Then, you call:
sort(array, left, p - 1);
which turns into
sort(array, 0, -1);
That's where negative indexes can be generated.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int typedNos;
if (cin >> typedNos)
{
vector <int> inputNos{ typedNos };
while (cin >> typedNos)
{
inputNos.push_back(typedNos);
}
for (decltype (inputNos.size()) n = 1; n < inputNos.size(); ++n)
{
cout << inputNos[0] + inputNos[1] << '\t' << inputNos[(2 * n) - 1]
+ inputNos[(2 * n)] << endl;
return 0;
}
}
else
{
cerr << " Wrong input type or no input was typed!" << endl;
//return -1;
}
}
Everything works fine till the output statement in the for loop is reached. The first two pairs of the vector's elements are manually added to account for zero. The rest are to be added automatically. But this only works for the first pair.
So, for example, an input of:
1 2 3 4 5.
Will give you an output of:
3 5.
Instead of 3 5 7 9.
This is where I have an issue. I have seen other methods of solving this problem but my question is why the sequence 2n (even positions) and 2n-1 (odd positions) do not work for the entire vector? Remember this question does not allow me to use iterators. Thanks.
The problem lies in your for-loop. Using return inside a loop will still exit from the current function. Your current function is main, so this ends the program.
I'm not really sure why you think you need 2 * n. It seems you want to iterate over every object, not every second one.
for (std::size_t n = 1; n < inputNos.size(); ++n) {
std::cout << inputNos[n] + inputNos[n-1] << '\t';
}
std::cout << std::endl;
So I've been working on problem 15 from the Project Euler's website , and my solution was working great up until I decided to remove the cout statements I was using for debugging while writing the code. My solution works by generating Pascal's Triangle in a 1D array and finding the element that corresponds to the number of paths in the NxN lattice specified by the user. Here is my program:
#include <iostream>
using namespace std;
//Returns sum of first n natural numbers
int sumOfNaturals(const int n)
{
int sum = 0;
for (int i = 0; i <= n; i++)
{
sum += i;
}
return sum;
}
void latticePascal(const int x, const int y, int &size)
{
int numRows = 0;
int sum = sumOfNaturals(x + y + 1);
numRows = x + y + 1;
//Create array of size (sum of first x + y + 1 natural numbers) to hold all elements in P's T
unsigned long long *pascalsTriangle = new unsigned long long[sum];
size = sum;
//Initialize all elements to 0
for (int i = 0; i < sum; i++)
{
pascalsTriangle[i] = 0;
}
//Initialize top of P's T to 1
pascalsTriangle[0] = 1;
cout << "row 1:\n" << "pascalsTriangle[0] = " << 1 << "\n\n"; // <--------------------------------------------------------------------------------
//Iterate once for each row of P's T that is going to be generated
for (int i = 1; i <= numRows; i++)
{
int counter = 0;
//Initialize end of current row of P's T to 1
pascalsTriangle[sumOfNaturals(i + 1) - 1] = 1;
cout << "row " << i + 1 << endl; // <--------------------------------------------------------------------------------------------------------
//Iterate once for each element of current row of P's T
for (int j = sumOfNaturals(i); j < sumOfNaturals(i + 1); j++)
{
//Current element of P's T is not one of the row's ending 1s
if (j != sumOfNaturals(i) && j != (sumOfNaturals(i + 1)) - 1)
{
pascalsTriangle[j] = pascalsTriangle[sumOfNaturals(i - 1) + counter] + pascalsTriangle[sumOfNaturals(i - 1) + counter + 1];
cout << "pascalsTriangle[" << j << "] = " << pascalsTriangle[j] << '\n'; // <--------------------------------------------------------
counter++;
}
//Current element of P's T is one of the row's ending 1s
else
{
pascalsTriangle[j] = 1;
cout << "pascalsTriangle[" << j << "] = " << pascalsTriangle[j] << '\n'; // <---------------------------------------------------------
}
}
cout << endl;
}
cout << "Number of SE paths in a " << x << "x" << y << " lattice: " << pascalsTriangle[sumOfNaturals(x + y) + (((sumOfNaturals(x + y + 1) - 1) - sumOfNaturals(x + y)) / 2)] << endl;
delete[] pascalsTriangle;
return;
}
int main()
{
int size = 0, dim1 = 0, dim2 = 0;
cout << "Enter dimension 1 for lattice grid: ";
cin >> dim1;
cout << "Enter dimension 2 for lattice grid: ";
cin >> dim2;
latticePascal(dim1, dim2, size);
return 0;
}
The cout statements that seem to be saving my program are marked with commented arrows. It seems to work as long as any of these lines are included. If all of these statements are removed, then the program will print: "Number of SE paths in a " and then hang for a couple of seconds before terminating without printing the answer. I want this program to be as clean as possible and to simply output the answer without having to print the entire contents of the triangle, so it is not working as intended in its current state.
There's a good chance that either the expression to calculate the array index or the one to calculate the array size for allocation causes undefined behaviour, for example, a stack overflow.
Because the visibility of this undefined behaviour to you is not defined the program can work as you intended or it can do something else - which could explain why it works with one compiler but not another.
You could use a vector with vector::resize() and vector::at() instead of an array with new and [] to get some improved information in the case that the program aborts before writing or flushing all of its output due to an invalid memory access.
If the problem is due to an invalid index being used then vector::at() will raise an exception which you won't catch and many debuggers will stop when they find this pair of factors together and they'll help you to inspect the point in the program where the problem occurred and key facts like which index you were trying to access and the contents of the variables.
They'll typically show you more "stack frames" than you expect but some are internal details of how the system manages uncaught exceptions and you should expect that the debugger helps you to find the stack frame relevant to your problem evolving so you can inspect the context of that one.
Your program works well with g++ on Linux:
$ g++ -o main pascal.cpp
$ ./main
Enter dimension 1 for lattice grid: 3
Enter dimension 2 for lattice grid: 4
Number of SE paths in a 3x4 lattice: 35
There's got to be something else since your cout statements have no side effects.
Here's an idea on how to debug this: open 2 visual studio instances, one will have the version without the cout statements, and the other one will have the version with them. Simply do a step by step debug to find the first difference between them. My guess is that you will realize that the cout statements have nothing to do with the error.
attempting to code a drill from C++ study book, "Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the program when a terminating '|' is entered."
i coded the following:
#include "C:\Users\Erez\Documents\Dev C++ Projects\std_lib_facilities.h"
int main(){
vector<int> v;
int value {0};
int i {1};
while (cin >> value)
{
v.push_back(value);
if (i % 2 == 0) { //using the % modulo to cout couples.
cout << v[i] << '\t' << v[i-1] << "\n"; // cout i + (i-1)
}
++i;
}
}
feeding two values separated by either space or line, i get this error:
4
5
terminate called after throwing an instance of 'Range_error'
what(): Range error: 2
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Would appreciate any help :)
Indices into vectors, arrays, etc. start at index 0
You are initializing your index to 1 and incrementing from there.
Thus, v[i] is referring to the value after the last one you pushed. This is an attempt to access something out of bounds and it is causing your program to crash.
Your statement of:
if (i % 2 == 0){
//
}
becomes true on second iteration inside your while loop and the statement of:
cout << v[i] << '\t' << v[i-1] << "\n"; // cout i + (i-1)
gets executed. The culprit here is v[i] which is actually v[2]. By now your vector only has two elements: v[0] and v[1], meaning that with the v[2] you are trying to read out of bounds. Rethink the logic inside your while statement and initialize the i counter to 0 rather than 1 to begin with. If you are trying to print out even vector elements then it should be:
if (v[i] % 2 == 0)