How to go about reformatting my code to use an array? - c++

I basically need to make an array and put it in the private member section, and have it work the random number generator. Im not even sure if my teacher is asking for an array to hold the 1000 values, or if I need to make an array for each variable (zero, one, ....). The rubric states to use the private member array to hold the count of values returned from calls to the random generator.
3 hours of youtube videos.
class Gen
{
private:
int Numbergenerated;
public:
Gen();
void set_Numbergenerated(int);
int get_Numbergenerated();
void gener();
void display(int zero, int one, int two, int three, int four, int five, int six, int seven, int eight, int nine);
};
Gen::Gen()....
void Gen::set_Numbergenerated(int n)...
int Gen::get_Numbergenerated()...
void Gen::gener()
{
int result_of_gener;
result_of_gener = rand() % 10;
set_Numbergenerated(result_of_gener);
}
void display....
int main()
{
Gen g;
unsigned seed;
int zero = 0, one = 0, two = 0, three = 0, four = 0, five = 0, six = 0, seven = 0, eight = 0, nine = 0, count, num;
seed = time(0);
srand(seed);
cout << "Press Enter key to begin generating numbers" << endl;
cin.get();
for (count = 0; count <= 1000; count++)
{
g.gener();
num = g.get_Numbergenerated();
cout << "Generation " << "+" << count << ":\t" << "Number generated: " << num << endl;
switch (num)
{
case 0: zero++;
break;.....
g.display(zero, one, two, three,four,five, six, seven, eight, nine);
`````````````
*******spots with ...... placed to save space, probably unimportant parts.

Once you fill the array with 1000 elements, you can use the count function to determine the number of occurrences of a specific value in the array. Here is how.
So, assuming you are using C++ arrays, we can declare the array in the private section of your class:
// An array of ints, with 1000 elements.
std::array<int,1000> randomNumberArray;
We can assume your set_Numbergenerated function adds a new random number to the array, so, in main(), we can generate and insert 1000 random numbers:
/** Generate 1000 random numbers to fill the array. */
for (size_t i = 0; i < 1000; i++)
{
g.gener();
}
Since our array is a private member, and not directly accessible from main, we can add a public member function to Gen to access the array for us. We can also tell this method to count the number of occurrences of a specific value in the array (a great C++ algorithm):
// Return the number of occurrences of 'val' in the array.
int Gen::get_Occurrences(int val) {
return std::count(this->randomNumberArray.begin(), this->randomNumberArray.end(), val);
}
Finally, we can call this method for each number of interest (0 through 9), and give the result of each to the display method call in main:
g.display(g.get_Occurrences(0), g.get_Occurrences(1), g.get_Occurrences(2),
g.get_Occurrences(3), g.get_Occurrences(4), g.get_Occurrences(5),
g.get_Occurrences(6), g.get_Occurrences(7), g.get_Occurrences(8), g.get_Occurrences(9));
These and a few other minor edits produced the output:
Press Enter key to begin generating numbers
Occurrences of each number [0 - 9]: 95 87 106 112 107 96 109 104 100 84

The problem is a little ambiguous. I tried to keep as much of your code as I could, but I may have removed parts that were required to be in the assignment.
The numberGenerated is a confusing variable. It seems that the more important thing you are trying to track is the frequencies of each digit. To do this, I created a 10 element vector which is zeroed by the constructor.
Then, as each number is stored into the object, the corresponding bucket in the array is incremented.
Note that the constructor also calls the seed function for the random number generator.
#include <iostream>
#include <random>
#include <string>
#include <vector>
class Gen {
private:
int Numbergenerated;
unsigned seed;
std::vector<int> frequencies;
public:
Gen();
void set_Numbergenerated(int);
int get_Numbergenerated();
void generate_random_number();
void display();
};
Gen::Gen()
{
seed = time(0);
srand(seed);
for (int i = 0; i < 10; i++) {
frequencies
.push_back(0);// create and zero 10 buckets in our frequencies vector
}
}
void Gen::set_Numbergenerated(int n)
{
Numbergenerated = n;
frequencies[n] = frequencies[n] + 1;
}
int Gen::get_Numbergenerated()
{
return Numbergenerated;
}
void Gen::generate_random_number()
{
int result_of_generate;
result_of_generate = rand() % 10;
set_Numbergenerated(result_of_generate);
}
void Gen::display(){
int sum = 0;
for(int i = 0; i < 10; i++) {
std::cout << i << "'s: " << frequencies[i] << " ";
sum += frequencies[i];
}
std::cout << std::endl;
std::cout << "Total generated: " << sum << std::endl;
}
int main()
{
Gen g;
std::cout << "Press Enter key to begin generating numbers" << std::endl;
// std::cin.get();
for (int count = 0; count < 1000; count++) {
g.generate_random_number();
int num = g.get_Numbergenerated();
std::cout << "Generation " << "+" << count << ":\t" << "Number generated: "
<< num << std::endl;
}
g.display();
}

Related

Program does not prompt input after the first time [c++] [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 15 days ago.
Improve this question
Here is my program, it is using c++ and I done it on MacOS VSCode.
Library:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <iomanip>
using namespace std;
Function:
float* read_data(int& size){
int a_size = 0;
static float a[10];
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){
cin >> a[i];
if (cin.fail()){
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
Main function:
int main(){
int size1 = 10;
int size2 = 10;
int size3 = 0;
float array[10];
float addarray[10];
float longarray[20];
float* ptr = array;
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i);
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
The main objective of the program was to prompt the user for an array, maximum of 10 elements. Prompting the user was done using the float* read_data(int& size) function.
The program would echo or print out the inputted array.
After that, the user was prompt for a second time using the same function to get another array of elements, in this case is a list of float values.
Then, the program would use a dynamic data allocation (DMA) technique to combine the two array into one long array. The new array will be printed out and the program is terminated.
Problem
As I said before, the program are supposed to prompt the user for inputs every time the read_data() were called.
I called the function twice. It did run twice, but failed to prompt the user for input the second time around.
I thought the problem was due to the cin.fail() arguments. That is why I tried to mess with the cin.ignore() and cin.clear() either by removing them or only using one of them.
I am honestly at lost on what is the root of the problem.
The heart of the issue is that you want users to enter 'Q', a char, into your float variable.
Here's a small example:
#include <iostream>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
0
~/tmp
❯ ./a.out
3
All clear.
3
6
So, you can see that you were on the right track. The issue is that if std::cin did fail, you are now responsible to clean up your mess.
std::cin.clear() is a good start. It resets the fail flag bits. But the stream is still in a bad state. What you haven't done is clean it up completely.
You're calling std::cin.ignore(), but leaving the parameter list empty.
Something like this is best practice:
#include <iostream>
#include <limits>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
3
6
While that should fix address the question, your code is still fundamentally broken.
EDIT
Here's a mini-code review:
#include <iostream>
#include <algorithm> // These includes
#include <cmath> // are
#include <cstdlib> // not
#include <string> // used
#include <iomanip>
using namespace std; // Bad practice
// You should not attempt to return a C-style array
float* read_data(int& size){ // Why is the size being passed by reference?
int a_size = 0;
static float a[10]; // Not doing what you think
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){ // Formatting; should be ") {"
cin >> a[i];
if (cin.fail()){ // Addressed above; root cause of your question
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
// While I assume the goal of the assignment is to get familiar with pointers,
// This assignment is trivial with vectors.
int main(){
int size1 = 10; // If declared const/constexpr, you'd only need one **
int size2 = 10; // These are bad names
int size3 = 0; // Front loading declarations is bad practice.
float array[10]; // ** And could use that variable here to avoid the magic number
float addarray[10];
float longarray[20]; // Not dynamic per your requirements.
float* ptr = array; // Still not dynamic, also unnecessary given the prior declarations
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
// The first cout is not good, what do you think *ptr will print?
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i); // The pointers can still use array syntax
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
// As soon as you start repeating yourself, consider writing a function.
// The logic will only live in one place, and only need to be changed in
// one place.
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
A lot going on that is less than great. The biggest flub appears to be the static array. static in this scenario extends the lifetime of the variable until the end of the program. So, when you call this function the second time, you overwrite the first array with the second because there's only ever one array for every call of that function. In the future, I would refrain from grabbing random code online and just dumping it in your program unless you know what it does.
Now, let's move on to a working solution.
The first thing I'm going to do is state the requirements as I understood them.
Have the user enter data to fill two arrays of floats.
Each array should hold a maximum of ten elements.
The user enters "Q" to indicate that they are finished entering data.
Print the first array.
Tack the second array on to the end of the first, in a dynamic fashion.
Print the combined array.
Anytime you get an assignment, your first task should be to restate the problem in your own words. This will clarify requirements and you will demonstrate to yourself that you understand the problem to be solved.
What makes this interesting is the "Q" to quit. Note that I'm using double quotes. We will read all of our data as strings, and we have to convert to float as needed.
std::stof() exists, but it's not as simple as just calling it. That function can throw exceptions, and we want to ensure that only actual float values get converted.
So we'll wrap that call in a function of our own. Here's an example:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
int main() {
float f = 0.0f;
// Test the function
try {
f = convert_string_to_float("5.6");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("5.6cat");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("Q");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << '\n';
}
Output:
❯ ./a.out
5.6
Issue.
0
In convert_string_to_float
stof: no conversion
Issue.
0
Now that we can convert strings to floats, with guarantees, we are ready to read values. To test that we're reading correctly, we also want to be able to print our arrays:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
void read_array_from_user(float* arr, int& size, const int maxCapacity, std::istream& sin = std::cin) {
size = 0;
std::string input;
while (size < maxCapacity && std::getline(sin, input)) {
if (input == "Q" || input == "q" || input.length() == 0) {
return;
}
try {
arr[size] = convert_string_to_float(input);
} catch(const std::exception& e) {
std::cerr << "Bad input. Reason: " << e.what() << "\nTry again.\n";
continue;
}
++size;
}
}
void print_array(float* arr, int size, std::ostream& sout = std::cout) {
sout << "{ ";
for (int i = 0; i < size; ++i) {
sout << arr[i] << (i == size - 1 ? " " : ", ");
}
sout << "}\n";
}
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
}
Output:
~/tmp
❯ ./a.out
1
2
3
4
q
{ 1, 2, 3, 4 }
~/tmp took 3s
❯ ./a.out
1
2
Q
{ 1, 2 }
~/tmp took 2s
❯ ./a.out
1
2
3
4
5
6
{ 1, 2, 3, 4, 5, 6 }
~/tmp took 4s
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 5s
❯ compilecpp tmp_repair.cpp
~/tmp
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 4s
❯ ./a.out
1
2
3
q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2b
Bad input. Reason: User input was not valid.
Try again.
2
3
Q
{ 1, 2, 3 }
~/tmp took 3s
❯ ./a.out
1
2
3
Q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2
3
{ 1, 2, 3 }
So, we can read an array with a maximum of 10 values. The reading is robust enough to handle typos or obviously bad input. But we don't have to read 10 values, it's the maximum. We keep track of the actual size ourselves.
Take note on how simple the main() function is because we put our sub-tasks into their own functions.
Reading the second array only requires a few lines in our main() now.
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayOneSize);
}
Easy-peasy there. Now we need to combine the arrays "dynamically."
We know the sizes of our two arrays, so we know the size of the final array. Now we just need to allocate the memory on the heap. I'm not going to use new, which is what I assume you're supposed to do. My reasoning is that C++ has had better methods for managing dynamic allocations since 2011.
#include <memory>
// ...
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayTwoSize);
int combinedArraySize = arrayOneSize + arrayTwoSize;
// This is considered dynamic; it's allocated on the heap
auto combinedArray = std::make_unique<float[]>(combinedArraySize);
int idx = 0;
for (int i = 0; i < arrayOneSize; ++i) {
combinedArray[idx] = arrayOne[i];
++idx;
}
for (int i = 0; i < arrayTwoSize; ++i) {
combinedArray[idx] = arrayTwo[i];
++idx;
}
print_array(combinedArray.get(), combinedArraySize);
}
Output:
~/tmp
❯ ./a.out
1
2
q
{ 1, 2 }
3
4
5
q
{ 3, 4, 5 }
{ 1, 2, 3, 4, 5 }
Hopefully, the most gnarly stuff is over where you get the user input, mostly due to the requirement that users can enter a letter to signal they're done. And that makes sense since now you have to do type conversions. Other languages like python make it possible with a lot less LOC (Lines Of Code) on your part. The task itself is not difficult, but ensuring users behave is a whole other beast. If you're allowed to assume well-behaved input will always be provided, you can simplify the code quite a bit.

C++ Data Structure: Can't display string corresponding to the largest number

My first C++ class coming from a basic Java class. This class is a more advanced C++ programming class about Data Structures. I don't know the basics of C++, only a little basics of Java.
Assignment is to :
-get 3 user inputs of states and their population (done).
-Get the most populated (biggest of three) and post it. (1/2)
I am able to get the highest number... but I'm not sure on the syntax on how to post it with the corresponding string (state).
I know this is some kind of array using struct, but I dont know how to post st.title
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct states_t {
string statename;
int population;
} state[3];
int main()
{
string mystr;
int n;
for (n = 0; n<3; n++)
{
cout << "Enter state name: ";
getline(cin, state[n].statename);
cout << "Enter population: ";
getline(cin, mystr);
stringstream(mystr) >> state[n].population;
}
cout << "\nYou have entered these movies:\n";
for (n = 0; n < 3; n++)
cout << state[n].statename << "\n" << state[n].population << "\n";
return 0;
}
==== UPDATED CODE WITH LARGEST POPULATION ====
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct states_t {
string statename;
int population;
} state[3];
int main()
{
string mystr;
int n;
for (n = 0; n<3; n++)
{
cout << "Enter state name: ";
getline(cin, state[n].statename);
cout << "Enter population: ";
getline(cin, mystr);
stringstream(mystr) >> state[n].population;
}
cout << "\nYou have entered these states:\n";
for (n = 0; n < 3; n++)
cout << state[n].statename << " " << state[n].population << "\n" << "\n";
if ((state[0].population >= state[1].population) && (state[0].population >= state[2].population))
cout << "The most populous state you entered is: " << state[0].statename << " with a population of " << state[0].population << "\n";
else if ((state[1].population >= state[0].population) && (state[1].population >= state[2].population))
cout << "The most populous state you entered is: " << state[1].statename << " with a population of " << state[1].population << "\n";
else
cout << "The most populous state you entered is: " << state[2].statename << " with a population of " << state[2].population << "\n";
return 0;
}
The first step is to store the name of each state with its population. It will help if you change title to name to make it more clear what the variable is for. If you do this correctly, you will quickly see that you no longer need mystr. (Note that you should always use meaningful variable names. A generic name like mystr often means that you do not know the purpose of the variable. Keep thinking about what the variable is for in order to make a more useful name.)
Now once you have the state data input into the array correclty, you should keep track of the data for the least and most populous state, rather than just its population. Instead of
int mn, mx;
declare
state_t mn, mx;
Then in your if statement do
mn = st[n];
and similarly for mx.
You will have to change your if condition to access the value in the struct. Then you can print the values directly from mn and mx.
Your code is designed to find the highest (and lowest) population of all states. You could also have tried to find out what the index-number is of the state with the highest population and use that number to index the state array to get what you need from there.
Here's how I would do it:
I would first make two int arrays, one corresponding to the index values of the array of struct states_t, and then one corresponding to the population values, like such:
int index[3];
int pop[3];
for (int i = 0; i < 3; i++)
{
index[i] = i;
pop[i] = st[i].population;
}
Next, perform a bubble sort algorithm on the population, and move the indices of the objects around according to the actions of the sort algorithm like such:
int n = 3;
for (int i = 0 ; i < ( n - 1 ); i++)
{
for (int j = 0 ; j < n - i - 1; j++)
{
//if the population of the next element
//is higher than the current element, swap it
//perform the same operation for state indices
if (array[j] > array[j+1])
{
int swap = pop[j];
int swap2 = index[j];
pop[j] = pop[j+1];
index[j] = index[j+1];
pop[j+1] = swap;
index[j+1] = swap2;
}
}
}
All that's left to do now is to call the first object in the list with the index array like such:
st[index[0]].title; //state with highest population
Coolest part about this method is that you can make this work for any number of States by changing the value of int n.
While there is nothing that prevents you from using a standard array-of-struct as you would in C, embracing the C++ std::vector can take a bulk of the tedium out of it. While using the array-of-struct, you get the benefit of protecting your array bounds manually indexing and manually handling storage, C++ has long sought to help alleviate or ease the manual aspects of handling collections of "things" (for lack of better words)
The std::vector container is tailor made to allow you to add to a collection of things using the simple push_back modifier. Basically you define your struct (say s_state_t) holding your name and pop, much as you have, and then declare and create an instance of a vector of type <s_state_t> (say state). Then to add a state (say s) to the vector you simply state.push_back(s) and let std::vector handle the storage and indexing. (vector also provides many other helpful member functions and modifiers to help get information about your collection)
Then the C++ way to approach managing a collection of states is to create either an additional struct or class to manipulate your collections of states, to add to, check and keep track of the max/min populations, etc. In a very simple form, you could create a class, that provides member functions that do just that, add a new state, check the max/min and then provide a way to output the contents of your collection. For example, you could do something like:
#include <vector>
#include <string>
#include <iomanip>
#include <limits>
typedef struct { /* struct holding state name and population */
std::string name;
int pop;
} s_state_t;
class country { /* class country - a collection of states */
std::vector<s_state_t> state; /* declare vector for states */
s_state_t mx = { "", 0 }, /* declare structs for max min */
mn = { "", std::numeric_limits<int>::max() };
void chkmxmn (s_state_t s) { /* function to set max/min */
if (s.pop < mn.pop)
mn = s;
if (s.pop > mx.pop)
mx = s;
}
public:
void addstate (std::string name, int pop) { /* add a state */
s_state_t s = { name, pop }; /* struct for new state */
chkmxmn (s); /* update max and min */
state.push_back (s); /* push_back to vector */
}
void prnstates() { /* output saved states, max/min */
for (auto& i : state) /* loop over vector */
std::cout << std::setw(16) << std::left << i.name <<
std::setw(10) << std::right << i.pop << "\n";
std::cout << "\nminimum and maximum populations:\n" <<
std::setw(16) << std::left << mn.name <<
std::setw(10) << std::right << mn.pop << "\n" <<
std::setw(16) << std::left << mx.name <<
std::setw(10) << std::right << mx.pop << "\n";
}
};
int main (void) {
country us; /* instance of country */
us.addstate ("Texas", 25000000); /* add names/pops */
us.addstate ("Louisiana", 12000000);
us.addstate ("California", 50000000);
us.prnstates(); /* output results */
return 0;
}
(note: you should add additional validations to check the name is not NULL or empty and pop is a reasonable number -- that is left to you)
Example Use/Output
$ ./bin/vector_states
Texas 25000000
Louisiana 12000000
California 50000000
minimum and maximum populations:
Louisiana 12000000
California 50000000
note: you can also create a typedef to your new vector type to cut down on the typing associated with specifying instances and parameters of the type with something similar to:
typedef std::vector<s_state_t> state_t; /* typedef to cut down typing */
which then allows you to declare new instances or parameters as simply, e.g.:
state_t state; /* declare vector for states */
Look things over. Neither method is more "right or wrong", but if you are going to learn C++ instead of C, you might as well go ahead and use the nice parts of it.

Pointer to pointer gets EXC_BAD_ACCESS when calling function

I have two classes, one called Handler and one called Dice. In my Handler class i have a private variable called Dice **dices and a public function called rollDices. And in my Dice class i have a function called toss that will randomize a number 1-6. The problem is that when the function rollDices is calling the function toss I get EXT_BAD_ACCESS in toss function. Does anyone know why, and have a solution for it?
My Handler.cpp:
void Handler::rollDices(){
Dice **allDices = new Dice*[this->nrOfDices];
this->dices = allDices;
dices[nrOfDices]= new Dice(nrOfDices);
int count =1;
for (int i = 0; i < this->nrOfDices; i++)
{
allDices[i]->toss();
cout << "Dice "<< count << ": " << allDices[i]->getValue() << endl;
count ++;
}
}
My Dice.cpp:
void Dice::toss(){
this->value = rand()%this->nrOfSides+1; //Value is a private int in Dice class
}
If you need more code i can post it, just tell me!
Dice **allDices = new Dice*[nrOfDices];
Allocates the top level pointer so now we have all of the rows in memory. When you add the columns
dices[nrOfDices]= new Dice(nrOfDices);
This does not add a new Dice to all of the rows. It adds a new Dice to one past the end of valid range of dices. What you need to do is use a loop and go through all of the rows and add a Dice to each one like
for (int i = 0; i < nrOfDices; i++)
dices[i] = new Dice(nrOfDices);
You are only allocating a single Dice object at index nrOfDices (which is of bounds by the way), if you want to allocate all Dice objects you need:
void Handler::rollDices(){
Dice **allDices = new Dice*[nrOfDices];
this->dices = allDices;
int count =1;
for (int i = 0; i < this->nrOfDices; i++)
{
dices[i] = new Dice(nrOfDices);
allDices[i]->toss();
cout << "Dice "<< count << ": " << allDices[i]->getValue() << endl;
count ++;
}
}
How about using modern C++? Try something like this:
void Handler::rollDice()
{
std::vector<Dice> allDice( nrOfDice );
int count = 1;
for( const auto & d : allDice )
{
d.toss();
cout << "Die "<< count << ": " << d.getValue() << endl;
++count;
}
}

C++ Vector subscript out of range Line 1201

I am working on a program that takes in grades from the user and returns the max, min, avg, median, and standard deviation. I keep encountering this error whenever I try to run my code:
File: c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector
Line: 1201
Expression: Vector subscript out of range
Could someone tell me what I'm doing wrong? No matter what I do, I can't seem to fix it. Completely new to coding in C++, so if you could explain in-depth that would be extremely helpful.
This is the block of code it is referring to in the vector file:
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() <= _Pos)
{ // report error
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
Specifically pointing to this line:
_DEBUG_ERROR("vector subscript out of range");
My code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void enterGrades()
{
int count = 0;//initialize count
int grade;//initialize grade variable
int maxGrade = 0;
vector<int> gradeList;//initialize vector
vector<int>::iterator gradeListIt;//initialize iterator
do {
cout << "Enter grades [0 to exit]: ";//enter grades
cin >> grade;//user input
count += 1;//for each grade, increase count
gradeList.push_back(grade);//append grades to vector
} while (grade != 0);
};
int maxNum(vector<int> gradeList)
{
int largest = gradeList[0];//initialize largest number
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)//traverse vector
{
if (gradeList[value] > largest)//if current value > largest
largest = gradeList[value];//set largest to that value
}
return largest;//return largest
};
int minNum(vector<int> gradeList)
{
int smallest = gradeList[0];
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)
{
if (gradeList[value] < smallest)
smallest = gradeList[value];
}
return smallest;
};
int avgNum(vector<int> gradeList)
{
int total = 0;
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)
{
total += value;
}
return total / length;
};
//int stdDev (vector<int>& gradeList)
//{
// int variance = 0;
// int avg = avgNum(vector<int>& gradeList);
// int length = gradeList.size();
// for(int value = 1; value < length; value++)
// {
// variance = variance + pow(value - avg, 2);
// }
// variance = pow(variance / length, 0.5);
// return variance;
//
//};
int main()
{
vector<int> gradeList;//initialize vector
vector<int>::iterator gradeListIt;//initialize iterator
enterGrades();//
cout << "Maximum grade is: " << maxNum(gradeList) << endl;
cout << "Minimum grade is: " << minNum(gradeList) << endl;
cout << "Average grade is: " << avgNum(gradeList) << endl;
}
Also, in my main function; can I call other functions like I did in my output statements?
Giving things the same name doesn't make them the same thing.
After enterGrades returns, the vector named "gradeList" in main is still empty.
When you try access the first element of an empty vector, you get an error.
Your main should look like this:
int main()
{
std::vector<int> gradeList = enterGrades();
cout << "Maximum grade is: " << maxNum(gradeList) << endl;
cout << "Minimum grade is: " << minNum(gradeList) << endl;
cout << "Average grade is: " << avgNum(gradeList) << endl;
}
Changing the implementation of enterGrades to fit is left as an exercise.
Also, this thing that you keep doing:
int length = gradeList.size();
gradeList.resize(length);
doesn't make sense, as it's resizing a vector to the size it already had.
Remove it.
You're also repeatedly declaring an iterator for no reason at all.
You also probably want to review what average you're supposed to calculate, as you're calculating the average index in a vector, not the average value.
And watch out for those integer divisions.

Program is generating same random numbers on each run? [duplicate]

This question already has answers here:
Why does rand() yield the same sequence of numbers on every run?
(7 answers)
Closed 5 years ago.
I just finished coding a Minesweeper type game, and everything's good except for that each time I run the application, it generates the same number (I ran it 3 different times, saved the output to 3 text files and used the diff command in Linux, it didn't find any differences). It's seeded by time(NULL) so it should change every time, right?
Here's my code:
main.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Minesweeper/box.h"
#include <cstdio>
int main(int argc, char** argv){
using namespace std;
bool gameOver = false;
int x, y, score = 0;
const int HEIGHT = 10;
const int WIDTH = 10;
unsigned int Time = time(0);
cout << "Welcome to Minesweeper. " << endl;
//setup grid
Box grid[10][10];
for(int i = 0; i < WIDTH; i++)
for(int n = 0; n < HEIGHT; n++){
unsigned int value = rand() %100 + 1;
cout << value << endl;
if(value <= 38){
grid[i][n].setFill(MINE);
//cout << i << "," << n << " is mined." << endl;
}
else
grid[i][n].setFill(EMPTY);
}
for(int r = 0; r < WIDTH; r++)
for(int l = 0; l < HEIGHT; l++)
if(grid[r][l].getFill() == EMPTY)
cout << r << "," << l << " - EMPTY." << endl;
else if (grid[r][l].getFill() == MINE)
cout << r << "," << l << " - MINE." << endl;
while(!gameOver){
cout << "Enter coordinates (x,y): ";
scanf("%i,%i",&x,&y);
if(grid[x][y].getFill() == MINE)
gameOver = true;
else{
cout << "Good job! (You chose " << x << "," << y << ")" << endl;
score++;
}
}
cout << "You hit a mine! Game over!" << endl;
cout << "Final score: " << score << endl;
getchar();
return EXIT_SUCCESS;
}
It's seeded by time(NULL)
If it is, I can't see it. In fact, a search for it in your code returns nothing. The default behaviour, if you don't explicitly seed, is the same as if you had seeded it with the value 1.
You need to explicitly state something like:
srand (time (NULL));
at the start of main somewhere (and make sure you do this once and once only).
Though keep in mind this makes it dependent on the current time - if you start multiple jobs in the same second (or whatever your time resolution is), they'll start with the same seed.
From the C standard (on which C++ is based for these compatibility features):
The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.
You need to seed randomizer. Call srand() at the beginning.
To add to the answers by others, you can use the Mersenne Twister Algorithm, which is a part of the C++11 library. Its fast becoming a standard in many common softwares to generate random numbers.
For example, this is the function I wrote, which I use often to generate random numbers in my other codes:
std::vector<double> mersennetwister(const int& My,const int& Mz,
const int& Ny,const int& Nz)
{
int ysize = (My + 2*Ny + 1);
int zsize = (Mz + 2*Nz + 1);
int matsize = ysize*zsize;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// Seeding the generator with the system time
std::mt19937_64 generator (seed);
// Calling the Mersenne-Twister Generator in C++11
std::uniform_real_distribution<double> distribution(0,1);
// Specifying the type of distribution you want
std::vector<double> randarray(matsize,0);
// Saving random numbers to an array
for (int i=0;i<matsize;++i)
{
randarray[i] = distribution(generator); // Generates random numbers fitting the
// Distribution specified earlier
}
return(randarray);
}
Bottomline: C++11 has some excellent features for numerical operations and it would be a good idea to look into them. As for the Mersenne Twister, http://en.wikipedia.org/wiki/Mersenne_twister