Why am i getting out-of-range error? - c++

I can't seem to find where my issue is. Its a three file program with aDie class in one file, aHistogram class in another file, and the main.cpp file. It is supposed to print a histogram constructed with X's to show how many times the die landed on each of the six faces. I cant move forward because of the vector error... There may be other issues with the program that i haven't worked out yet, but I just want to know about the vector error. Thank you.
main.cpp:
#include <iostream>
#include <stdlib.h> //srand and rand
#include <time.h> //Time
#include <vector>
#include <algorithm>
#include "aHistogram.h"
#include "aDie.h"
using namespace std;
int main()
{
srand (time(NULL));
int numRolls;
const int maxLengthOfLine = 50;
cout << "How many rolls? " << endl;
cin >> numRolls;
aDie fairDie;
aHistogram fairHistogram;
//For Loop rolls the die and updates the histogram vector ~~binHistogram.
for(int i = 0; i < numRolls; i++)
{
int face = fairDie.roll();
fairHistogram.update(face);
}
cout << "*******************" << endl;
cout << "*****Histogram*****" << endl;
cout << "*******************" << endl;
fairHistogram.display(maxLengthOfLine);
}
aDie.h:
#ifndef ADIE_H_INCLUDED
#define ADIE_H_INCLUDED
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
/********************************************/
/*******Definition of aDie class*************/
/********************************************/
class aDie
{
public:
int roll(); //return an integer between 1 and 6 to represent what face appears when the die is rolled.
aDie(); //Default constructor
~aDie(); //Destructor
private:
int numFaces = 6;
};
int aDie::roll()
{
return ((rand() % numFaces) + 1); //returns a random number between 1 and 6
}
aDie::aDie()
{
cout << "Dice Roll...." << endl;
return;
}
aDie::~aDie()
{
return;
}
#endif // ADIE_H_INCLUDED
aHistogram.h:
#ifndef AHISTOGRAM_H_INCLUDED
#define AHISTOGRAM_H_INCLUDED
#include <algorithm>
#include <stdlib.h>
#include <vector>
using namespace std;
/********************************************/
/*******Definition of aHistogram class*******/
/********************************************/
class aHistogram
{
public:
void update(int face);
void display(int maxLengthOfLine);
int Count(int face);
void clear();
aHistogram(); //Constructor
~aHistogram(); //Destructor
private:
vector<int> binHistogram;
const int numFaces = 6;
int totalRolls;
int largeBin = 0;
double xScale;
};
//Adds a count to each face every time the die lands on said face.
void aHistogram::update(int face)
{
binHistogram.at(face) += 1;
return;
}
//Displays the histogram with X's
//maxLengthOfLine represents the maximum number of x’s to be printed for the largest bin count.
void aHistogram::display(int maxLengthOfLine)
{
xScale = maxLengthOfLine / largeBin;
for(int i = 1; i <= 6; i++)
{
cout << i << " : " << Count(i) << " : ";
int numXs = xScale * binHistogram.at(i);
for(int j = 0; j < numXs; j++)
{
cout << "X";
}
}
}
//To be called AFTER aHistogram::update
//Returns a count of how many times for each face of the die
int aHistogram::Count(int face)
{
//For Loop determines the largest bin count
for (int i = 1; i < numFaces; i++)
{
while (binHistogram[i] >= largeBin)
{
largeBin = binHistogram.at(i);
}
}
//
return binHistogram.at(face);
}
void aHistogram::clear()
{
binHistogram.clear();
return;
}
//Defines the DEFAULT CONSTRUCTOR. Sets all elements of the histogram to zero.
aHistogram::aHistogram()
{
return;
}
//Defines the DESTRUCTOR. Clears vector after use.
aHistogram::~aHistogram()
{
binHistogram.clear(); //Clears vector
return;
}
#endif // AHISTOGRAM_H_INCLUDED

I didnt find the place where you initialize the histogram this might be the problem. But even if you fix that, you will hit two other bugs:
for (int i = 1; i < numFaces; i++)
{
while (binHistogram[i] >= largeBin)
{
largeBin = binHistogram.at(i);
}
}
you are accessing elements 1....6 when probably it should be 0...5. Same problem in the line where you have
largeBin = binHistogram.at(i);
which is most likely the line that causes the error (the one above wont be so nice to tell you what is the problem but just crash your program).

You never change the size of the vector in the aHistogram class, which means its size will always zero. Any index will be out of bounds.
For things like histograms I would actually recommend you to use std::unorderd_map instead of std::vector, with the "face" being the key and the count being the data. Then you could do e.g.
binHistogramMap[face] += 1;
without worrying about the element for face not existing (it will be created and initialized to zero if the entry doesn't exist).

Related

C++ Class of array of objects

I am learning C++ and for that, I try to do a simple game project (having the same rows as columns and randomly distributed numbers from 0-blank to rows*rows-1. Target is for player to change numbers to be in numeric order by rows). Then 0-blank can be switched with any neighborhood horizontally or vertically) I code it through procedural code and it works fine. Now I am trying to redo it using object-oriented programming and classes.
For that reason I have 2 classes:
Number - stores 2 integers with position x and y
Deck - stores array of Numbers, practically s index of an array is the number itself and Number object just store position.
Deck deck (rows) creates sorted numbers with position and is checked by std::cout.
Now I am trying to implement the shuffle function which will take randomly 2 Numbers and switch their positions (m_posX and m_posY) however trying the same principle to get m_posX is not correct and gives different large numbers compared to the creation of the position.
getNumber just does not work as I intended.
Practically I need to return m_posX and m_posY from exact Number object in array of m_game deck.
Any suggestions what am I doing wrong is welcome.
I have this code:
Number.h
#ifndef NUMBER_H
#define NUMBER_H
#include <array>
class Number
{
public:
// Number(int x, int y, int d);
setPosition (int x, int y);
setPosition (std::array <int,2> &xy ); // std::array [2]
setDigits (int d);
switchPosition (Number &c1, Number &c2);
std::array<int,2> getPosition (); // std::array [2]
int getPositionX ();
int getPositionY ();
int getDigits(); // int
protected:
int m_posX;
int m_posY;
int m_digits;
};
#endif // NUMBER_H
Number.cpp
Number::setPosition (int x, int y)
{
m_posX = x;
m_posY = y;
}
Number::setPosition (std::array <int,2> &xy )
{
m_posX = xy [0];
m_posY = xy [1];
}
Number::setDigits (int d)
{
m_digits=d;
}
Number::switchPosition (Number &c1, Number &c2)
{
int tempX {c1.m_posX};
int tempY {c1.m_posY};
c1.setPosition (c2.m_posX, c2.m_posY);
c2.setPosition (tempX, tempY);
}
std::array<int,2> Number::getPosition ()
{
static std::array <int,2> position;
position [0] = m_posX;
position [1] = m_posY;
return position;
}
int Number::getDigits ()
{
return m_digits;
}
int Number::getPositionX ()
{
return m_posX;
}
int Number::getPositionY ()
{
return m_posY;
}
deck.h
#ifndef DECK_H
#define DECK_H
#include "number.h"
class Deck
{
public:
Deck(int rows=3);
shuffleDeck (int rows);
Number & getNumber (int elementNumber);
protected:
std::array <Number,100> m_game;
};
#endif // DECK_H
deck.cpp
#include "deck.h"
#include "number.h"
#include "rnd.h"
#include <iostream>
Deck::Deck(int rows)
{
std::array <Number,100> m_game;
for (int j {0}; j < (rows); ++j)
{
for (int i {0}; i < (rows); ++i)
{
m_game[i+j*rows].setPosition (i,j);
std::cout << "Number: " << (i+j*rows) << '\t' << "Coordinates: " << '\t' << m_game[i+j*rows].getPosition()[0] <<"," << m_game[i+j*rows].getPosition()[1] << '\n' ;
};
};
std::cout << "fc Deck::Deck (int rows) Number10 posX: "<< m_game[10].getPosition()[0] << '\n';
std::cout << "fc Deck::Deck (int rows) Number10 posY: "<< m_game[10].getPosition()[1] << '\n';
}
Number & Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
game.cpp running code
#include "game.h"
#include "gmath.h"
#include "constant.h"
#include "graphics.h"
#include "number.h"
#include "deck.h"
#include <iostream>
int game (int rows)
{
int steps = 0;
Graphics piece {};
Deck deck(rows);
Number temp = deck.getNumber(10);
int tempI = temp.getPosition()[10];
//
// THIS DOES NOT WORK GETTING printed large number as 28573728
// [10] has m_posX set to 2 and m_posY set to 2 by Deck deck (rows);
//
std::cout << "CHECK game.h Number10 positionX: "<< tempI << '\n';
return steps; // for future counting score
}
Try return by value and not by reference here:
Number & Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
like this:
Number Deck::getNumber (int elementNumber)
{
std::cout << "fc Deck::getNumber() Number " << elementNumber << " getPosition X,Y: " << m_game[elementNumber].getPositionX() << "," << m_game[elementNumber].getPositionY() << '\n' ;
return m_game[elementNumber];
}
and of course do not forget to change the declaration:
Number getNumber (int elementNumber);
The problem is very obvious.
In function game you are writing int tempI = temp.getPosition()[10];.
The function getPosition() returns a std::array<int, 2>. So, an array having 2 elements. One for x and one for y position. But with [10] your are trying to access the element number 10 from your array (which has only 2 elements). This is an out of bounds error. So, It will read some random nonesense value and show that. This is undefined behaviour.
I am not sure, which compiler you have, but in debug mode, it should throw an exception and inform you about the problem.
Correct it to
int tempx = temp.getPosition()[0];
int temp< = temp.getPosition()[1];
You anyway need to enable ALL compiler warnings. It did it and got dozens of messages.
You define many functions without return type. You must use void for this, e.g. function setPosition(int x, int y); must be defined as void setPosition(int x, int y);. And so on.
Also in constructor of Deck you are redefining and with that overwriting the already defined array std::array <Number, 100> m_game; in class deck. Delete the line in the constructor.
You may also consider to replace the std::array <int, 2>& xy by a std::pair or a simple struct like:
struct Position{
int x;
int y;
};
That would be more intuitive . . .

This program takes user input and is supposed to sort it using bubbleSort but its outputting letters and numbers and I'm not sure why

The output I'm getting when I run this code after inputting any set of integers, and ending the loop with the sentinel number 999, is always 0x7ffd85bc43b0 and I can't figure out why. I think I'm missing some important code somewhere, but I'm not sure where? This program is also eventually supposed to be able to find the mean and median of the inputted numbers as well.
// HouseholdSize.cpp - This program uses a bubble sort to arrange up to 300 household sizes in
// descending order and then prints the mean and median household size.
// Input: Interactive.
// Output: Mean and median household size.
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <any>
#include <stdio.h>
using namespace std;
void swapping(int &a, int &b) { //swap the content of a and b
int temp;
temp = a;
a = b;
b = temp;
}
void display(int householdSizes, int size) {
for(int i = 0; i<size; i++){
}
}
void bubbleSort(int householdSizes[], int size) {
for(int i = 0; i<size; i++) {
int swaps = 0; //flag to detect any swap is there or not
for(int j = 0; j<size-i-1; j++) {
if(householdSizes[j] > householdSizes[j+1]) { //when the current item is bigger than next
swapping(householdSizes[j], householdSizes[j+1]);
swaps = true; //set swap flag
}
}
if(swaps== false)
break; // No swap in this pass, so array is sorted
}
}
int main()
{
// Declare variables.
const int SIZE = 300; // Number of household sizes
int householdSizes[SIZE]; // Array used to store 300 household sizes
int x;
int limit = SIZE;
int householdSize = 0;
int pairsToCompare;
bool switchOccurred;
int temp;
double sum = 0;
double mean = 0;
double median = 0;
// Input household size
cout << "Enter household size or 999 to quit: ";
cin >> householdSize;
// This is the work done in the fillArray() function
x = 0;
while(x < limit && householdSize != 999)
{
// Place value in array.
householdSizes[x] = householdSize;
// Calculate total of household sizes
x++; // Get ready for next input item.
cout << "Enter household size or 999 to quit: ";
cin >> householdSize;
} // End of input loop.
// Find the mean
// This is the work done in the sortArray() function
int n = sizeof(householdSizes)/sizeof(householdSizes[0]);
bubbleSort(householdSizes, n);
cout <<householdSizes;
// This is the work done in the displayArray() function
// Print the mean
// Find the median
// Print the median
return 0;
} // End of main function
An array can't be printed directly using cout << householdSizes; Since an array is convertible to a pointer, that is what is done implicitly behind the scenes. Change cout << householdSizes; to:
for(int i = 0; i < x; ++i){
std::cout << householdSizes[i] << " ";
}
P.S. Also do as #0x5453 says. He is right.

Inheritance Robot Race that doesn't update array

I am working on a program that is suppose to have 3 different Robots racing on a track. The track is suppose to be 100 in length. I have just learned inheritance and still trying to understand how to connect data members from one .h to another. When I run my program, nothing happens when I call any of my Robots. I will show one of them as an example. Can you explain how to make their movements update the race 2D array?
robotRace.h
#ifndef ROBOTRACE_H
#define ROBOTRACE_H
using namespace std;
class robotRace {
public:
robotRace (); //constructor
static const int rows = 5;
static const int columns = 100;
protected:
int race[rows][columns]; //initial base for race floor
};// end superclass robotRace that should do no movement
#endif
robotRace.cpp
#include <iostream>
#include "robotRace.h"
using namespace std;
robotRace :: robotRace() {
for (int i = 0; i < rows; i++)
for (int j= 0; j<columns; j++)
race[i][j] = ' ';
}//end constructor
This is one of the Robots and their functions to update array. Not sure how to make it work.
FunctionRobot.h
#ifndef FUNCTIONROBOT_H
#define FUNCTIONROBOT_H
#include "robotRace.h"
using namespace std;
class FunctionRobot : public robotRace{
public:
FunctionRobot();
int position(int);
void print();
protected:
};
#endif
FunctionRobot.cpp
#include <iostream>
#include "FunctionRobot.h"
#include <cmath>
using namespace std;
FunctionRobot :: FunctionRobot (): robotRace() {
int initPos =0;
race[initPos][0] = '*';
cout <<"Initial position of Function Robot is at begin of race."<<endl;
}
int FunctionRobot :: position(int place=0){
// log with a base 2 needs to be divided by the "x"
// below is the Robots formula to determine each of their movements
double x = ( 2 * (log(place)/log(2)));
return (int) x;
}
void FunctionRobot :: print(){
for (int i;i=0; i<100; i++)
for (int j;j=0; j<1; j++)
race[position()][j];
}
this is my main file as requested. This is basic format. I am hoping to make the while loop more practical so that the user doesn't have to keep entering 1.
There is also no error coming from my code. It runs just shows nothing.
main.cpp
#include <iostream>
#include "robotRace.h"
#include "FunctionRobot.h"
using namespace std;
int main() {
int userInput;
cout << "Welcome to the Robot Race of the year!" << endl;
cout << "For our contestants we have the amazing three!" << endl;
cout << "The contestants are Robots F, R and U" << endl;
cout << "Let the games begin! \n\n";
cout << "Enter 1 to begin. " << endl;
cin >> userInput;
FunctionRobot functionObj;
//functionObj.position();
//functionObj.print();
cout << "Ready... Set... Go!!" << endl;
while (userInput == 1) {
functionObj.position(4);
functionObj.print();
} //end while
return 0;
}
Your print() goes out of bounds:
void FunctionRobot :: print(){
for (int i; i<100; i++)
for (int j; j<1; j++)
race[position()][j];
}
j is not initialized. You could try int j = 0 for a start. Similar for i.
Moreover you know that this function is named PRINT but doesn't PRINT ANYTHING, actually it doesn't do anything but calling position().
int FunctionRobot :: position(int place=0){
// log with a base 2 needs to be divided by the "x"
// below is the Robots formula to determine each of their movements
double x = ( 2 * (log(place)/log(2))); <-------- now x is a double
return (int) x; <-------- now x is an integer, are you sure about that?
}
Loss of precision happens here. Let's say that x is assigned a value of 3.14. Then you cast it (the cast would happen automatically since the return type of the function is also an int) into an integer, thus it will be converted to 3, thus you loss precision.
About main.cpp
You call the user to input 1 and then you have:
while (userInput == 1) {
functionObj.position(4);
functionObj.print();
} //end while
but userInput is not going to be modified, thus you are running into a non-ending loop.

Class Rolling Dice program

I need to write C program for rolling dice using class Dice. The main requirement is that I need to use this main, editing it:
int main()
{
Dice* ptrDice;
???
for (int i = 0; i < 5; i++)
{
???? // roll the 5 dice
???? // print the outcome
}
}
I just cannot get how to use pointers here. Can anyone help, pls?!
Here is my code but it's not working :(
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
class Dice{
public:
Dice();
int getNums();
void Roll();
private:
int nNums;
};
Dice::Dice(){
nNums=5;
}
int Dice::getNums()
{
return nNums;
}
void Dice::Roll()
{
nNums = rand()%6 + 1;
}
int main()
{
Dice* ptrDice = new Dice;
ptrDice -> getNums();
for (int i = 0; i < 5; i++)
{
getNums[i] = rand()%6 + 1; // roll the 5 dice
cout << "You rolled: ";
cout << ptrDice->getNums() << setw(4);
cout << endl; // print the outcome
}
}
My main trouble is to use that ptrDice and printing it in main function, I guess!
You're making this more complicated than it needs to be.
A simple Dice object needs no data members and only one member function. If you're using the rand() function, the constructor should seed the random number generator with srand(seed). The Roll() function should return the number rolled as an int. You don't need the getNums() function at all, which will only return 5 as your class is defined.
class Dice() {
public:
int roll() { return rand() % 6 + 1; }
};
...
int main() {
Dice* ptrDice = new Dice;
for (int i=0; i<5; i++) {
cout << "You rolled" << ptrDice->roll() << '\n';
}
delete ptrDice;
}
You could expand this class to simulate multiple dice with any number of sides. Then you could use integer data members to retain the number of dice and their number of sides.

garbage value is obtained

this is a sample of my code. i am getting the value for maximum height. but my minimum height is a garbage value. what am i doing wrong
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;
#define MAX 20
struct DATA
{
int id;
string name;
float height;
}numarray[MAX];
int main()
{
int num = 0;
numarray[num].height = fstr3;// contains float values from a file
float minimum, maximum;
minimum = numarray[0].height;
maximum = numarray[0].height;
for(int i = 0; i < MAX; i++)
{
{
if(numarray[i].height < minimum)
{
minimum = numarray[i].height;
}
else if(numarray[i].height > maximum)
{
maximum = numarray[i].height;
}
}
cout<< minimum<< " " << maximum<< endl;
return 0;
}
}
Garbage in, garbage out. It looks like your input routine (which you didn't post) may be populating the data incorrectly. I'd look at the input data in the debugger (even if your choice of debugger is printf()).
Your code assumes that minimum is unequal to the maximum.
Solution second if should be on its own and not in else clause from first.
assuming you do initialize the array in your real code, with these modifications:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;
#define MAX 20
struct DATA
{
int id;
string name;
float height;
}numarray[MAX];
int main()
{
int num = 0;
numarray[num].height = fstr3;// contains float values from a file
float minimum, maximum;
minimum = numarray[0].height;
maximum = numarray[0].height;
for(int i = 1 /* skip 0 - already read */; i < MAX; i++)
{
if(numarray[i].height < minimum)
{
minimum = numarray[i].height;
}
// remove the else here
if(numarray[i].height > maximum)
{
maximum = numarray[i].height;
}
}
// move outside the loop
cout<< minimum<< " " << maximum<< endl;
return 0;
}
this should be OK