I've created a program that allows the user to enter 10 grades. I've used a while loop to store grades in the array, but if the user only has 5 grades to input, he can type done to exit the program.
After the loop has finished, it will then calculate and display. the highest grade, lowest grade, and the average grade within the array
Unfortunately, when the user types done, the program will display the rest of the grade lines that were not entered.
Can you help me find out how to stop the while loop from displaying the rest of unentered grades of the loop?
#include <iostream>
using namespace std;
int main()
{
const int SIZE = 10;
int grade[SIZE];
int count = 0;
int lowestGrade;
int highestGrade;
bool done = false;
cout << "This program is limited to entering up to 10 grades." << endl;
while ( grade[count] != done && count < SIZE)
{
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
cin >> grade[count];
count++;
}
//LOWEST GRADE
lowestGrade = grade[0];
for (count = 0; count < SIZE; count++)
if (grade[count] < lowestGrade)
{
lowestGrade = grade[count];
}
//HIGHEST GRADE
highestGrade = grade[0];
for (count = 0; count < SIZE; count++)
{
if (grade[count] > highestGrade)
{
highestGrade = grade[count];
}
}
//AVERAGE GRADE
double total = 0;
double average;
for (int count = 0; count < SIZE; count++)
total += grade[count];
average = (total / SIZE);
cout << endl;
cout << "Your highest grade is: " << highestGrade << endl;
cout << "Your lowest grade is: " << lowestGrade << endl;
cout << "Your average grade is: " << average << endl;
system("pause");
return 0;
}
Here are two problems with your code.
First:
....
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
cin >> grade[count];
count++;
....
The code above will attepmpt to read word "done" into integer variable, producing 0. Not what you want to do!
Second:
...
for (count = 0; count < SIZE; count++)
...
Code above will try to iterate over all possible elements (SIZE). However, you might have enetered less than that! You need to use count calculated in the previous loop as your boundary (and of course, use a different name for control variable in the loop).
There are a couple of things to unpack here.
Basically, the input you are retrieving is a char * and the >> operator is casting that to an int to fit into your array of grades.
Next what you are checking with grade[count] != done is if the integer in "grade" at the id "count" is not equal to the bool false. This will always return true in this case.
For your use case what you want to be checking is if your input is equal to the char * "done"
This cannot be happening in the predicate of the while loop because your grade array stores only int.
Therefore the simplest solution to the problem in my opinion, is to check whether the input is equal to "done".
If it is you want to set the done boolean to true
Otherwise we can try to cast it to an int and store that in the grades array.
Here is the revised loop:
while (!done && count < SIZE)
{
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
string input = "";
cin >> input;
if (input == "done")
{
done = true;
}
else
{
grade[count] = stoi(input);
}
count++;
}
The following is somewhat outside the scope of the question, but an additionnal advantage to using stoi() is that it ignores input that is not a number, which will shield against someone entering invalid input like "potato". This is why I immediately cast the input into a string.
Use another variable to store the amount ofgrades the user entered. You also cannot store a string in your integer array:
std::string input = "";
while(count < SIZE)
{
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
getline(cin, input);
if(input == "done")
break;
try
{
grade[count] = std::stoi(input);
count++;
}
catch(std::invalid_argument)
{
cout << "not a valid number\n";
}
}
int actualsize = count;
and then use this variable to abort your for loops:
for (int i = 0; i < actualsize; i++)
There are two simple ways to solve your problem:
You can read strings instead of integers and in case the read string is "done", break the loop, else, convert the read string to an integer, something as follows:
```
// rest of the code
int total_count = 0;
while (count < SIZE) {
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
string temp;
cin >> temp;
if(temp == "done") {
break;
} else {
grade[count] = stoi(temp);
count++;
total_count = count;
}
}
// rest of the code
```
If you don't want to use strings, then, assuming grades will be non-negative, you can stop reading input when the user types a negative number, say "-1". So, you will need to do something as follows:
```
// rest of the code
int total_count = 0;
while (count < SIZE) {
cout << "Enter a grade #" << count + 1 << " or -1 to quit: ";
int temp;
cin >> temp;
if(temp == -1) {
break;
} else {
grade[count] = temp;
count++;
total_count = count;
}
}
// rest of the code
```
Also, don't forget to replace SIZE by total_count in rest of the loops i.e. the ones computing 'LOWEST GRADE', 'HIGHEST GRADE' and 'AVERAGE GRADE'.
NOTE: You will have to do #include <string> at the top as well, if you use the first option.
Related
int main() {
cout << "Enter some numbers fam! " << endl;
cout << "If you wanna quit, just press q" << endl;
int n{ 0 };
int product = 1;
char quit = 'q';
while (n != 'q') {
cin >> n;
product = product* n;
cout <<"The product is : " << product << endl;
}
cout << endl;
cout << product;
return 0;
}
Whenever I print it out and cut the code using 'q', it prints me an infinite amount of "The product is 0". Also, how can I print out the final product of all numbers at the end?
So, there are some problems in your code.
First, you are taking input and assigning it to an int, which might not have been a problem, but you are also comparing the int to a char(which will cause problems in your case)
int n{ 0 };
while(n != 'q') {
cin >> n;
}
To solve that, you can make the n a string and then convert it into an integer with stoi(n) to use with the calculation
string n; // don't need to initialize a string, they are initialized by default.
int product = 1;
cin >> n; // Taking input before comparing the results
while(n != "q") { // Had to make q a string to be able to compare with n
product *= stoi(n); // Short for product = product * stoi(n)
cout <<"The product is : " << product << endl;
cin >> n; // Taking input for the next loop round
}
cout << endl;
cout << product;
How to fix the code? I can't use vectors. I need to be able to call the names for the courses from the first while to the second one and display them.
cout << "Please enter the number of classes"<< endl;//Number of classes for the while
cin >> nclass;
while (count <= nclass ) // while
{
//Information for the class
{
cout << "Please enter the course name for the class # "<< count << endl;
getline (cin, name);
string name;
string coursename[nclass];
for (int i = 0; i < nclass; i++) {
coursename[i] = name;
}
}
char choose;
cin >> choose;
while ( choose == 'B' || choose == 'b') {//Name the courses
for (int x = 0; x < nclass; x++){
cout << "Here is a list of all the courses: \n" << coursename[i] << endl;
}
return 0 ;
}
you are declaring coursename as local inside loop and then using it outside so you get a compile time error (coursename is undeclared identifier).
one question: what is the role of inner for-loop????!!!
you use a for loop inside while loop through which you are assigning all the elements the same value as the string name has!!!
so every time count increments the inner for loop assigns the new value of name after being assigned, to the all elements of coursename.
count is undefined! so declare it and initialize it to 1 or 0 and take this in mind.
you wrote to the outbounds of coursname: count <= nclss to correct it:
while(count < nclass)...
another important thing: clear the input buffer to make cin ready for the next input. with cin.ignore or sin.sync
cout << "Please enter the number of classes"<< endl;//Number of classes for the while
cin >> nclass;
string coursename[nclass];
int count = 0;
while (count < nclass ) // while
{
//Information for the class
string name;
cout << "Please enter the course name for the class # "<< count << endl;
cin.ignore(1, '\n');
getline (cin, name);
coursename[count] = name;
cin.ignore(1, '\n');
count++;
}
char choose;
cin >> choose;
while ( choose == 'B' || choose == 'b') {//Name the courses
for (int x = 0; x < nclass; x++){
cout << "Here is a list of all the courses: \n" << coursename[x] << endl;
}
This code works!
#include <iostream>
#include <string>
using namespace std;
int main()
{
int nclass = 0, count = 1, countn = 1;
string name[100];
cout << "Please enter the number of classes" << endl;
cin >> nclass;
while (count <= nclass) {
cout << "Please enter the course name for the class # " << count << endl;
cin >> name[count];
count++;
}
cout << "Here is a list of all the courses: " << endl;
while (countn <= nclass) {
cout << name[countn] << endl;
countn++;
}
return 0;
}
Note that gave the array "name" the size of 100. Nobody is going to have 100 classes! There is no need for the for loops. It is a good practice to initialize the count and the new count which is designated by countn. Why is my answer voted down when it works?
while (counter < total)
{
inFile >> grade;
sum += grade;
counter++;
}
Above is the while loop I had for my original program and below is my attempt at converting that to a for loop.
for (counter = 0; counter < total; counter++)
{
inFile >> grade;
cout << "The value read is " << grade << endl;
total = total + grade;
}
This is a simple program to get grade averages. Here is the entire program:
#include <iostream>
#include <fstream>
using namespace std;
int average (int a, int b);
int main()
{
// Declare variable inFile
ifstream inFile;
// Declare variables
int grade, counter, total;
// Declare and initialize sum
int sum = 0;
// Open file
inFile.open("input9.txt");
// Check if the file was opened
if (!inFile)
{
cout << "Input file not found" << endl;
return 1;
}
// Prompt the user to enter the number of grades to process.
cout << "Please enter the number of grades to process: " << endl << endl;
cin >> total;
// Check if the value entered is outside the range (1…100).
if (total < 1 || total > 100)
{
cout << "This number is out of range!" << endl;
return 1;
}
// Set counter to 0.
counter = 0;
// While (counter is less than total)
// Get the value from the file and store it in grade.
// Accumulate its value in sum.
// Increment the counter.
while (counter < total)
{
inFile >> grade;
sum += grade;
counter++;
}
// Print message followed by the value returned by the function average (sum,total).
cout << "The average is: " << average(sum,total) << endl << endl;
inFile.close();
return 0;
}
int average(int a, int b)
{
return static_cast <int> (a) /(static_cast <int> (b));
}
I tried to convert while loop to a for loop but when I debug I get an infinite loop. There are no errors when I build my solution. I'm not sure what other details to add.
You are increasing the value of total in the for loop. Hence, counter never reached total if you keep entering positive values.
Perhaps you meant to use sum instead of total in the loop.
for (counter = 0; counter < total; counter++)
{
inFile >> grade;
cout << "The value read is " << grade << endl;
sum = sum + grade;
}
You are using wrong variables names, value of total is increasing in the for loop so it becomes an infinite loop, use a different variable names for storing sum and for for-loop termination condition.
score is an array of 10 scores in ascending order.
scoreName is an array of names associated with with each score.
I need to check if a new score is good enough to enter the the high score table and if so, insert it into the correct position and make sure scoreName is also updated to reflect any changes.
I am having problems with my current code:
//Table
for (int i = 0; i < leaderBoardSize; i++)
{
cout << scoreName[i] << "\t\t" << score[i] << endl;
}
system("pause");
//Check to see if you made the highScore
if (diceTotal >= score[9])
{
cout << "Congrats, you have made the HighScore Table !\nEnter Your Name.";
cin >> playerName;
for (int i = 9; i < leaderBoardSize; i--)
{
if (diceTotal <= score[i])
{
scoreName[i = i + 1] = scoreName[i];
score[i = i + 1] = score[i];
scoreName[i] = playerName;
score[i] = diceTotal;
break;
}
scoreName[i = i + 1] = scoreName[i];
score[i = i + 1] = score[i];
}
}
Here is the entire code:
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
int main()
{
//dice game variables
int dice1 = 0;
int dice2 = 0;
int diceTotal = 0;
int round = 0;
string choice;
bool isDone = true;
//Scoreboard
const int leaderBoardSize = 10;
int score[10] = { 40, 33, 29, 24, 22, 19, 15, 12, 11, 9 };
string scoreName[leaderBoardSize] = { "Jason", "Steve", "Bob", "Timberduck", "Eric", "Susan", "Tyler", "Nick", "NinjaDave", "RaidenGunfire" };
string playerName;
//random number seeder
srand((unsigned int)time(NULL));
//Game instructions
cout << "dice game\n---------\nCreated By: Darcy Tellier\n--------------------------\nInstructions:\nRoll 2 dices. Try to get as close to 50 without going over." << endl;
//The Game loop
do
{
//resets game variables
diceTotal = 0;
round = 1;
//in game match loop
do
{
// display round #, current dice total, ask user to quit or re-roll.
cout << "Round\n-----\n " << round << endl;
cout << "current total:" << diceTotal << endl;
cout << "Roll dice (y/n)?";
cin >> choice;
//Checks the users imput for invalid characters
while (choice != "Y" && choice != "y" && choice != "N" && choice != "n")
{
cout << "invalid option. Choose y/n:" << endl;
cin >> choice;
}
if (choice == "Y" || choice == "y")
{
//roll dice
round += 1;
dice1 = rand() % 6 + 1;
dice2 = rand() % 6 + 1;
diceTotal = diceTotal + dice1 + dice2;
cout << "you have rolled a " << dice1 << " and a " << dice2 << endl;
if (diceTotal > 50)
{
isDone = false;
}
}
else
{
//break was used because "isDone = false" does not work here. The debugger shows that when the variable is set to false, it still ignores it and skips to the next round.
break;
}
} while (isDone == true || diceTotal < 50);
//end of round
if (diceTotal > 50)
{
cout << "\nGameOver" << endl;
cout << "You went over in " << round << " turns. You Lose!!! " << endl;
}
else
{
cout << "You stopped at " << round << " turns. Final score: " << diceTotal << "." << endl;
system("pause");
system("cls");
}
//Table
for (int i = 0; i < leaderBoardSize; i++)
{
cout << scoreName[i] << "\t\t" << score[i] << endl;
}
system("pause");
//Check to see if you made the highScore
if (diceTotal >= score[9])
{
cout << "Congrats, you have made the HighScore Table !\nEnter Your Name.";
cin >> playerName;
for (int i = 9; i < leaderBoardSize; i--)
{
if (diceTotal <= score[i])
{
scoreName[i] = playerName;
score[i] = diceTotal;
break;
}
}
}
//board display #2
for (int i = 0; i < leaderBoardSize; i++)
{
cout << scoreName[i] << "\t\t" << score[i] << endl;
}
system("pause");
//do you want to play again?
cout << "Do you want to play again";
cin >> choice;
while (choice != "Y" && choice != "y" && choice != "N" && choice != "n")
{
cout << "invalid option. Choose y/n:" << endl;
cin >> choice;
}
if (choice == "Y" || choice == "y")
{
system("cls");
isDone = true;
}
else
{
cout << "game over" << endl;
isDone = false;
}
} while (isDone);
system("pause");
return 0;
}
This is a copy of the assignment.
Note: I am not asking for you guys to do my work. I just want to figure out the highScore sorting thing.
The problem: arrays are not a good way to achieve what you want
You are trying to see if a score beat another score, and if so, replace that and move the rest of the scores down. I assume your scores are sorted, and that score is a int[10], but you have several problems:
1.
for (int i = 9; i < leaderBoardSize; i--)
You are attempting to iterate through your scores backwards, so you start at 9 (which I assume is the last index) and work your way down. Assuming leaderBoardSize is the total size of the leaderboard, and likely 10, i will always be less than leaderBoardSize and your for loop will go for a loooong time. You probably meant to say:
for (int i = 9; i >= 0; i--)
2.
scoreName[i = i + 1] = scoreName[i];
score[i = i + 1] = score[i];
This is assigning i to a new value, which will also ruin your for loop. You should only be doing
scoreName[i + 1] = scorename[i];
Trying to swap all the values in an array in cumbersome, and you are trying to do everything manually, so I give you:
The solution: use the standard library!
C++ is a great language, if for no other reason than containing a standard library: a library of functions and classes that solve many basic problems for you.
It is far easier to sort, insert and remove elements by using a standard container. Let's use std::vector:
// Simple class to handle a player score: a name and score
struct PlayerScore
{
std::string name;
unsigned int score;
};
// Create some test scores. I assume you have another means of storing high scores, perhaps in a file, but for this small purpose I am just hard-coding some scores:
std::vector<PlayerScore> hiScores = { {"ABC", 5000}, {"XJK", 10000}, {"FOO", 20000}, {"EGG", 4000}, {"HI", 50000} };
You may keep your scores sorted, but if, like mine they aren't sorted, you can sort them easily with std::sort:
std::sort(hiScores.begin(), hiScores.end(), [](PlayerScore ps1, PlayerScore ps2){ return ps1.score > ps2.score; });
With that out the way, you can proceed to play your game and obtain a name for the player and their score. I haven't bothered, and will just create a value for the score:
auto score = 10123u;
// Check if this score beats any of the current high scores:
auto it = std::find_if(hiScores.begin(), hiScores.end(), [score](PlayerScore ps){ return score > ps.score; });
if (it != hiScores.end())
{
// Yes! We beat a score!
std::cout << "Found score: " << it->score << std::endl;
// Insert this score before the other score
hiScores.insert(it, {"NewScore", score});
// Remove the last score:
hiScores.pop_back();
}
You no longer need to iterate and manually try to manipulate the positions of scores. Standard containers with random access such as std::vector allow you to just insert and access elements as you need to. Your 10 lines of code simply becomes 2 lines. std::vector also manages the size for you, so if you only have 3 high scores initially, it can grow easily to contain 10, 100 or many more scores.
std::find_if can find an element in your container without the need to manually iterate over every element. A predicate is passed in which acts as a find condition, which in our case we pass our score and check if it's greater than any PlayerScore in the container. The first element it's greater than is returned to us, and then we can insert our score in front of it, then remove the last score via pop_back
and if so, insert it into the correct position and make sure scoreName is also updated
This is a poor design. If scores and names need to stay together, you should make them a single entity. Define a struct or class to hold a name and associated score, and then store instances of that entity in a single array.
I made a game where the player types in the scrambled word. Take for example, I have the word 'wall' which is then jumbled up to saying wlal. For a correct answer I multiply the length of the given word to the user by 1000, then report the score at the end.
However, I also have a hint feature set up, so when they type in hint they get a hint. As a penalty, I'd like it so the user get's their score cut in half. Also, if the player answers incorrectly, there is a 1000 point reduction to the score.
My program always sets the score to 0. What's the problem here.
EDITED CODE:
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
using namespace std;
int main()
{
enum fields {WORD, HINT, NUM_FIELDS};
const int NUM_WORDS = 5;
const string WORDS[NUM_WORDS][NUM_FIELDS] = //5x2 array
{
{"wall", "Do you feel you're banging your head against something?"},
{"glasses", "These might help you see the answer."},
{"labored", "Going slowly, is it"},
{"persistent", "Keep at it."},
{"jumble", "It's what the game is all about."}
};
srand(static_cast<unsigned int>(time(0)));
int choice = rand() % NUM_WORDS;
//Choice value in array, than area in array where word and hint are
string theWord = WORDS[choice][WORD]; //word to guess
string theHint = WORDS[choice][HINT]; //hint for word
string jumble = theWord; //jumbled version of word
int length = jumble.size();
//Index1 and index2 are random locations in the string theWord
//last two lines swaps areas, ending the for function with a different
//jumble variable every time.
for (int i = 0; i < length; ++i)
{
int index1 = rand() % length;
int index2 = rand() % length;
char temp = jumble[index1];
jumble[index1] = jumble[index2];
jumble[index2] = temp;
}
cout << "\t\tWelcome to Word Jumble!\n\n";
cout << "Unscramble the letters to make a word.\n";
cout << "\n\n\nReady? (y/n)";
//I'm asking here if the player is ready
string isready;
cin >> isready;
if ((isready == "y") || (isready == "Y"))
{
cout << "Ok this is how the scoring works\n";
cout << "The length of the word you will guess is times by 5000.\n";
cout << "If you ask for a hint, your score will go down by half.\n";
cout << "If you get the wrong answer, your score will go down by 1000.";
cout << "\nOk, lets start!\n";
int counter = 3;
for(int i = 0; i < 3; ++i)
{
sleep(1);
cout << counter << "..." << endl;
counter--;
}
sleep(1);
}
else
{
cout << endl;
return 0;
}
cout << "Enter 'quit' to quit the game.\n";
cout << "Enter 'hint' for a hint.\n";
cout << "The jumble is: " << jumble;
//Score system
double score;
double amount_of_guesses, amount_of_wrong = 0;
string guess;
cout << "\n\nYour guess: ";
cin >> guess;
double wrong = 0;
while ((guess != theWord) && (guess != "quit"))
{
if (guess == "hint")
{
cout << theHint;
amount_of_guesses++;
}
else if (guess != theWord)
{
cout << "Sorry, that's not it.";
wrong++;
}
cout << "\n\nYour guess: ";
cin >> guess;
}
if (guess == theWord)
{
score = (theWord.length() * 1000);
}
if (amount_of_guesses != 0)
{
score = score / (amount_of_guesses * 2);
}
if( wrong != 0)
{
score = score - (wrong * 1000);
}
cout << "Your score is: " << score;
cout << "\nThanks for playing.\n";
return 0;
}
Your code works fine for me when double amount_of_guesses, amount_of_wrong = 0; is changed as: double amount_of_guesses=0; double amount_of_wrong = 0;
Additionally, the code score = score / (amount_of_guesses * 2); does not correctly penalize the player by cutting his or her score in half each time they ask for a hint.
You could replace that line with the following code segment to correctly penalize by cutting the score in half every time:
if (amount_of_guesses != 0)
{ while(amount_of_guesses!=0)
{
score = (score / 2);
amount_of_guesses--;
}
}
The code
int amount_of_guesses, amount_of_wrong = 0;
does not initialize amount_of_guesses to 0. It is likely to be a huge number since it will be what is in memory when program is running. If score is lower than amount_of_guesses, result will be 0 using integer division.
I believe the issue is that you never initialize amount_of_guesses. This declaration
int amount_of_guesses, amount_of_wrong = 0;
initializes amount_of_wrong to 0, but amount_of_guesses will just hold some random value that depends on what happens to be in memory. If that's a large value, then this:
if (amount_of_guesses != 0)
{
score = score / (amount_of_guesses * 2);
}
will end up making score == 0 (note that since score is an integer score / (amount_of_guesses * 2) ends up being the floor of that division)