Out of Range error - c++

The question is:
Jay had borrowed a friend's coffee mug and somehow lost it. As his friend will be extremely angry when he finds out about it, Jay has decided to buy his friend a replacement mug to try to control the damage.
Unfortunately, Jay does not remember the color of the mug he had borrowed. He only knows that the color was one of White, Black, Blue, Red or Yellow.
Jay goes around his office asking his colleagues if they are able to recall the color but his friends don't seem to remember the color of the mug either. What they do know is what color the mug definitely was not.
Based on this information, help Jay figure out what the color of the mug was.
The way I'm going about this:
I create a vector of all possible colors: White, Black, Blue, Red or Yellow. Then ask the user to enter the number of colleagues he will be questioning. Then take the color suggestions, and for every entry I compare it against the vector. If it is in there, I pop the color out. Eventually only one color will be left in the vector which is the color of the lost mug.
My issue:
I get an out of bound error after entering the first color and I am not able to figure out why. The exact error is:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Abort (core dumped)
My code is:
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
#include <stdio.h>
#include <vector>
using namespace std;
int main(int argv, char* argc[])
{
string color;
vector<string> colorVector;
colorVector.push_back("White");
colorVector.push_back("Black");
colorVector.push_back("Blue");
colorVector.push_back("Red");
colorVector.push_back("Yellow");
int numColleagues;
cout<< "Please enter the number of Colleagues" << endl;
cin >> numColleagues;
cout<< "Please enter each suggested color" << endl;
int counter = 0;
while (counter < numColleagues) {
getline(cin, color);
counter++;
for (int i = 0; i < 5; i++) {
if (colorVector.at(i) == color) {
colorVector.erase(colorVector.begin() + i);
}
}
}
return 0;
}

You are erasing elements of your vector, but you wish to access all five elements (the loop runs from 0 to 5). So, let's say you remove the first and then you try to access the element at position 4. Out of bounds!
So change your loop to this:
colorVector.erase(std::remove(colorVector.begin(),
colorVector.end(), color), colorVector.end());
More on erase-remove idiom.

When you call vector::erase, it will return an iterator pointing to the new location of the element that followed the erased element. So if we erase this element:
1 2 3 4 5 6
^
Our iterator will automatically update to point to the 5. So we don't have to increment the iterator again, it's already sort of incremented. With that in mind:
auto it = colorVector.begin();
for (; it != colorVector.end(); /* do not increment it */ )
{
if (*it == color)
{
it = colorVector.erase(it); // erase and update
}
else
{
++it; // just update
}
}
Of course even better to just use the algorithms which are less error prone
colorVector.erase(
std::remove(colorVector.begin(), colorVector.end(), color),
colorVector.end()
);

You are modifying colorVector during an iteration.
As soon as you remove one of the colors, the vector is suddenly only 4 items in length. Now when you try to go to the 5th item (which was safe to do before the deletion) - it crashes
Try this:
for (int i = 0; i < colorVector.size(); i++) {
if (colorVector.at(i) == color) {
colorVector.erase(colorVector.begin() + i);
--i;
}
}
By stopping at colorVector.size instead of a hard-coded 5 you are ensured that the list never goes out of bounds.
Edit:
Added --i statement to avoid skipping next one
Edit2:
As the comments below state, it is generally a bad idea to remove items from the array you're currently iterating from.

Related

C++ how to move Text with ncurses.h?

C++ how to move Text from off screen to inside the terminal (animation 20/50 millisec.) and then stop the animation. with ncurses.h ? pls with examples
with perhaps a loop that increases the X coordinate from (x = 0-number characters text-1) to (x = 2 or 1), for each Line of text containing the color.
let me explain: the previous sentence no longer moves (it remains stationary on X2 coordinates), the sentence of now makes the entry animation, as soon as the animation ends, it becomes the still sentence together with the other preceding sentences. moves the next one, and continues the loop until it is finished.
I didn't get the result I wanted: (this is the code)
#include <iostream>
#include <windows.h>
#include <ncurses.h>
using namespace std;
void tdnVoid(short colore)
{
HANDLE a = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(a, colore);
}
int main()
{
initscr();
int b = 0;
while (b != 256)
{
b++;
refresh();
move(0, 0);
tdnVoid(b);
cout << b << ". ■ ";
cout << "\n";
if (b % 16 == 0)
{
cout << "\n";
}
Sleep(100);
}
return 0;
}
☑️the result I wanted (GIF):
Gif Hello World example - GIF
❌the result I got: Gif C++ Program execution, pls help me solve it
NEW EDIT:
according to the documentation, you can use this:
mvprintw(y,x,"your string",); refresh(); but i use and try for like 2 hours, having errors;
pls if someone can help me, you will really help me!
this program may seem useless, but I am using it to learn C ++, once I have learned this, I can use the same function and complicate and do more interesting things. hope you understand me (there are those who created Nokia's Snake game with ncurses, there are those who 3D things that rotate in space) thank pls help me to understand :)
stackoverflow guys. i started stackoverflow bad. sorry for my wrong attitude
(that's why I didn't get an answer)
but luckily I managed to get the result I wanted! I can be of help for you! in the documentation it won't say, but through a while () loop I managed to do it!
int main()
{
initscr();
int x = -1;
while (x < 22)
{
x++;
refresh();
mvprintw(0, x, " C++ colori", 10);
Sleep(300);
}
//other my code
}
before putting refresh (); which is important to update, then mvprintw() which is like a cout << /*from <iostream> library*/ but with mv (mv is move()) ... which is what I wanted !! the first attribute is the Y which are the vertical, and the second attribute is the X that is to move in the same horizontal line.
all separated by commas, attention: I put the x as a variable and not as a number because I made it move through the while loop.
after put the string of characters, remember: put a space before if not you have a result like this
❌output: CCCCCCCCCCCCCC++ colori
with a space before, it appears to be invisible, so it works.
☑️output:                                    C++ colori
after I put Sleep(/*milliseconds*/); remember to put the <windows.h> library
10 is the number of characters, I know you could have done better by automating it with char [] =" your string " and make the program count, but it was was a beta.
===========
remember: if you don't put endwin (); at the end of the loop what you saw in the GIF will happen. on all your next normal code. here my first Bug

How can I 'pan out' (make screen bytes smaller) of the console screen to render 2d pyramids larger?

I am using Windows 10 with code blocks to compile my code.
I wonder WHY you want to do that. This seems to be a typical homework assignment problem for practising loops and logic. That usually is restricted to numbers easily fitting on a console. Could you elaborate what causes the need to go beyond say a size of 30? – Yunnosch 10 hours ago
#Yunnosch For pure hypothetical and experimental reasons. I essentially have a dream I could write a program that renders massive 2d pyramids on a console screen, and maybe create some game out of it. I was hoping I could figure out a way to 'pan out' of the console screen thus making the screen bytes smaller. Somebody has to know more than me, and can lead me in the right direction to accomplishing this '2d pyramid rendering' program. Thanks in advance! – Fibonacci 3 mins ago
My goal is to be able to render massive pyramid structures onto a console output screen. The code here simply asks for a number of rows and prints out a pyramid. ex. drawPyramid(50);
#include <iostream> // include iostream
using namespace std; // include std
// Draw pyramid function here
void drawPyramid(int rows)
{
// initializes space and creates for loop to keep track of rows, I and k
int space;
for(int i = 1, k = 0; i <= rows; ++i, k=0)
{
// draws spaces required
for(space = 1; space <= rows-i; ++space)
{
cout << " ";
}
// draws matter
while(k != 2*i-1)
{
cout << "* ";
++k;
}
//prints new line based on rows
cout << endl;
}
}
//driver program
int main()
{
bool fTrue = false;
// loops until user presses '0'
while(!fTrue)
{
cout << "Press (0) to quit...\n";
int i,rows;
cout << "Enter number of rows: \n";
cin >> rows;
drawPyramid(rows); // draw function called
if(rows == 0)
{
fTrue = true;
}
}
return 0;
}
Output:
While the program works great I'd like to be able to pass in bigger values such as drawPyramid(500); or drawPyramid(1000); anything above the value 50 produces results like so.
Results:
Hopefully you can understand what I am trying to ask. I want to be able to 'pan out' and move the asterisks closer together so that I can pass in larger input values into the drawPyramid() function... Thanks in advance!
I am using Windows 10 with code blocks to compile my code.

C++ - seg fault from inserting elements into array in ascending order

As part of a BookGroup class that manages an array of Book objects, I'm asked to create a void add(Book* b) member function that adds the given Book b to an array of books in its correct place (from oldest to most recent year of publication). I'm required to shift the elements in the array towards the back of the array to make room for the new element in its correct place. I am not allowed to simply add to the end of the array and then sort or use any sorting function/sorting algorithm on the array.
I tried testing my add function and I get a seg fault. My approach was to add any new book at the end of the array and if that specific book's publication year was older (number is less) than the last book in the array, I would make the two books swap places. If not, the book would stay in the same spot at the very end of the array. I then continue this process.
I don't know what's causing the seg fault. As a side note, I was wondering if I'm supposed to use the delete function at any point in add()? I did a valgrind check on my compiler and it says there are a bunch of bytes lost somewhere in my program. My guess is that a good chunk of the bytes are probably coming from the add function, but I'm not sure and just wanted to double check.
bookCollection is supposed to be a statically allocated array of Book object pointers. There are two classes - Book.cc and BookGroup.cc.
I decided to show all of my code so people can compile it, but please post only what is necessary and refrain from posting all of it in the answers below.
BookGroup.cc:
#include <iostream>
#include <iomanip>
using namespace std;
#include "BookGroup.h"
BookGroup::BookGroup(int n){
numOfBooks = n;
}
void BookGroup::add(Book* b){
if(numOfBooks != MAX_BOOKS){
if(numOfBooks == 0){
bookCollection[0] = b; //add first element
++numOfBooks; //increase numOfBooks by 1 and go to next statement
}else{
for(int i = numOfBooks-1; i >= 0; --i){ //start at end of array and work towards front where lowest years are
if(b->getPubYear() < bookCollection[i]->getPubYear()){
bookCollection[i + 1] = bookCollection[i]; //swap positions if b is lower than last element
bookCollection[i] = b;
}else{
b = bookCollection[i + 1]; //otherwise stay in the same spot (keep b at the end)
//break;
}
}
++numOfBooks;
}
}
cout<<"Book could not be added to collection. No more space "<<endl;
}
BookGroup.h:
#ifndef BOOKGROUP_H
#define BOOKGROUP_H
#define MAX_BOOKS 15
#include <string>
using namespace std;
class BookGroup
{
public:
BookGroup(int);
BookGroup(BookGroup&);
~BookGroup();
void print();
void add(Book*);
Book* bookCollection[MAX_BOOKS];
private:
int numOfBooks;
};
#endif
Book.cc: https://pastebin.com/9swrwYgx
Book.h: https://pastebin.com/mqDn2C30
makefile: https://pastebin.com/xHKDsVL1
main: https://pastebin.com/TBzyduMC
When I try to run it:
Declaring two book groups...
Initializing two book groups...
-- default Book ctor: Peter pan year: 1982
Segmentation fault
This
BookGroup::BookGroup(int n){
numOfBooks = n;
}
together with this
BookGroup suzy(2);
creates book groups which do not contain any pointers to valid books but DO pretend to contain 2.
Then here
for(int i = numOfBooks-1; i >= 0; --i)
{ //start at end of array and work towards front where lowest years are
if(b->getPubYear() < bookCollection[i]->getPubYear()){
you start accessing index 1 (because of numBooks==2), which is not a valid pointer.
You should
correctly initialise your array, e.g. with NULL, to make sure that checks work cleanly later
double check that you only use valid pointer, everywhere, if necessary twice
not initialise an empty group with a non-zero number of pretended books

Erasing Element From a Vector Erases Multiple (C++)

I've been building a small Roguelike ASCII game that uses the console to build my limited knowledge of C++. I have it set up so when the player object's coordinates are the same as an item(which is stored in a vector), it removes the item and adds 10 to the player's HP.
The program starts out with 9 items in the room. BUT, whenever I get the item, it deletes the first 5 items in the vector(But they're still being drawn on the screen for some reason), and adds 50 to the health. So I'm left with 4 items. The next time I get an item, it removes the first 2 and adds 20 to the health. Now I'm left with 2 items. The last two times, it removes one item at a time.
So, essentially, the vector is being split in half each time I get an item. I've narrowed down the problem through a lot of debugging, and I'm pretty sure it's coming from this chunk of code:
for(int i=0;i<ia.size();i++) //If the player touches an item
{
if(grid[p.getY()][p.getX()]==itm)
{
hp+=10;
cout << "Item "<<i<<" removed\n";
swap(ia[i], ia.back());
ia.pop_back();
system("pause");
}
}
I'm still trying to figure out vectors, so if someone could tell me what I'm doing wrong, I would really appreciate it. :)
There're comments suggesting erase(), but be aware that it will copy later array elements one by one to fill in the index being vacated: your swap approach may be massively faster and is better if you don't care about element order.
One issue is that you swap the back() element into the position occupied by the element you're removing, then increment the iterator to test the next ia index. This means that the items copied from the back() are never themselves tested - for that you want to avoid the i++ after doing a swap. Of course if only one item can ever occupy a grid position, you can just break as abiessu commented....
Here's some code that works as I think you want:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> ia{ 10, 20, 30, 40, 50, 60, 70 };
for(size_t i=0;i<ia.size(); ) //If the player touches an item
{
if(ia[i] % 20)
{
cout << "Item "<<i<<" removed\n";
swap(ia[i], ia.back());
ia.pop_back();
continue;
}
else
++i;
}
for (size_t i = 0; i < ia.size(); ++i)
std::cout << '[' << i << "] " << ia[i] << '\n';
}
See it at http://ideone.com/JJ6CE6
That said, for some data types ia[i] = ia.back(); will be faster than swap - for others slower (if they use and benefit from C++11 style "move"). You may also want to skip any self-swap/assignment if i == size() - 1 (at least check that the array element type supports that safely).

C++ selecting a number of random items without repeating

Write a program that randomly selects from a bag of eight objects.
Each object can be red, blue, orange, or green, and it can be a ball or a cube.
Assume that the bag contains one object for each combination (one red ball, one
red cube, one orange ball, one orange cube, and so on). Write code similar to
Example 5.3, using two string arrays—one to identify colors and the other to
identify shapes.
I am trying to write a program to carry out the above exercise - the problem I am having is the same object can be selected more than once each time.
This is the code so far
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
using namespace std;
int rand_0toN1(int n);
void choose_object();
char *colour[4] =
{"Red", "Blue", "Orange", "Green"};
char *object[2] =
{"Ball", "Cube"};
int main()
{
int n, i;
srand(time(NULL)); // Set seed for randomizing.
while (1) {
cout << "Enter no. of objects to draw ";
cout << "(0 to exit): ";
cin >> n;
if (n == 0)
break;
for (i = 1; i <= n; i++)
choose_object();
}
return 0;
}
void choose_object() {
int c; // Random index (0 thru 4) into
// colours array
int o; // Random index (0 thru 2) into
// object array
c = rand_0toN1(4);
o = rand_0toN1(2);
cout << colour[c] << "," << object[o] << endl;
}
int rand_0toN1(int n) {
return rand() % n;
}
Let's try to solve this by making a real world analogy:
Let's say you have a massive jar of marbles, of the colors listed above. It's so massive (infinite size!) that you always have the same chance to draw a marble of a given color, always 1/4 each time.
How would you do this in real life? Would you just keep picking randomly, chucking the marble away as you draw it? Or would you maybe keep a little list of things you've drawn already?
Or maybe you only have one of each in the jar... You wouldn't put it back in would you? Because that's kind of what you're doing here.
Each of these thought paths will lead you to a good solution. I don't want to provide a code or anything because this kind of assignment is one that teaches you how to think like a computer.
Since this is homework, I'm not going to give an exact answer, but describe what you could do:
Keep a list of objects you've already chosen.
After you choose an object, compare that object to the list of objects you've already chosen. If it's in the list, choose another object. If it's not in the list, add it to the list.
Make sure that you don't try to choose more than 8 objects, or else you'll end up in an infinite loop in part 2.
These would go in your choose_object() subroutine. You could do it in a while() loop, something like:
int seen_before = 0;
while(!seen_before) {
pick your random numbers
if(numbers not in list) {
add to list
break
}
}