Input Validation for Vectors C++ - c++

I'm having a problem with the input validation of my do-while loop. My do-while loop only validates every other input
Here's an example:
Please Enter Grade 1: 101 (It does not accept input)
Invalid Rage. Please Enter Range 0-100.
Please Enter Grade 1: 101 (It accapts this input)
Please Enter Grade 2: 101 (It does not accept input)
Invalid Rage. Please Enter Range 0-100.
Please Enter Grade 2: 101 (It accapts this input)
Here's My Code:
for(vector<double>::size_type i = 0; i < 15; i++)
{
do
{
cout << "Please Enter Grade "<< i + 1 <<": " << flush;
cin >> gradesVector[i];
}
while(gradesVector[i] < 0.0 && gradesVector[i] > 100.0);
{
cout << "Invalid Rage. Please Enter Range 0-100:\n";
cout << "Please Enter Grade "<< i + 1 <<": " << flush;
cin >> gradesVector[i];
}
}

Try this:
int main() {
vector<double> gradesVector(15);
for(vector<double>::size_type i = 0; i < 15; i++) {
do {
cout << "Please Enter Grade "<< i + 1 <<": " << flush;
cin >> gradesVector[i];
} while(gradesVector[i] < 0.0 || gradesVector[i] > 100.0);
}
}

The statement while(gradesVector > 0.0 && gradesVector <= 100.0) is trying to check if the entire vector is greater than 0 or less than 100, which doesn't really make sense. You want to do something like while(gradesVector[i] > 0.0 && gradesVector[i] <= 100.0) (just make sure i is in the correct scope).
Edit: just get rid of the do-while loop and only use a for-loop. Inside the for-loop, add an if-statement: if(gradesVector[i] > 0.0 && gradesVector[i] <= 100.0). If the validation fails, use a break statement to exit the for-loop.

Related

Ask for the condition of guess number game

I am a newbie, i have some question:
I am coding a guessing number game, player enter the random number range, guess number, guess limit. When player enter the guess number out of the random range entered, the program require player to enter the guess number again. However, I tested my code, I entered the number range [ 3,8 ] and the guess number is 1, this number is out of range, the program didn't force me to enter the guess number again but I had to enter the guess limit. Please hint me what's wrong with my code and help me to fix this code. Thanks!
#include iostream
#include cstdlib
using namespace std;
int randnum(int min, int max)
{
return min + (int)(rand() * (max - min + 1.0) / (1.0 + RAND_MAX));
}
int main()
{
int max;
int min;
int guessnum;
int guesscou = 0;
int guesslim;
bool outofguess = false;
cout << " Enter max min of random value range = \n ";
cin >> max >> min;
cout << " Enter your guess number = \n ";
cin >> guessnum;
cout << " Enter your guess limitation = \n";
cin >> guesslim;
// enter guess loop
while (guessnum != randnum(min, max) && !outofguess) {
// guessnum condition
while (guessnum <= max && guessnum >= min) {
cout << " Unvalid number, please enter again ";
cin >> guessnum;
}
// guess limitation
if (guesscou <= guesslim) {
cout << " Please try again \n";
cin >> guessnum;
guesscou++;
}
else {
outofguess = true;
}
}
if (outofguess) {
cout << " you win";
}
else {
cout << " you lose ";
}
}
You want the user to guess again if the number is lower than the minimum or higher than the maximum. But the logic in your while loop says exactly the opposite. It should read
while (guessnum < min || guessnum > max) {
cout << " Unvalid number, please enter again ";
cin >> guessnum;
}

input validation with getline and (!(cin >> var))

I'm working on a project for my c++ class, but I'm a little hung up on how to properly validate input to make sure it's correct before proceeding. The following is a function designed to allow user input for a student's name and test scores. My issues involve 'getline' on line 6 and (!(cin >> score[i][j])) on line 11.
For getline, I need a way to check that only alphabetical characters were entered.
For (!(cin >> score...)) If the user enters a integer followed by a character (i.e. "8a") it isn't detected as an input error. Is there any way to remedy this?
EDIT: I've come up with a partial solution thanks to "David Rankin - ReinstateMonica".
I've changed the getline validation to only accept alphabetical characters, spaces, and periods using this bit of code:
while (!(names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ") == string::npos && !names[i].empty())) // check to make sure there are no invalid characters and names[i] isnt blank
{
cout << "Enter the student's name: ";
getline(cin, names[i]); // Allow for full name entry (first, middle, and last names)
if (!(names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ") == string::npos && !names[i].empty())) // another check, outputs error msg if getline value is invalid
cout << "Names must consist of letters, periods, or spaces. \n";
}
However I'm still stumped on how to validate the (!(cin >> score[i][j])) portion. Would it be possible to create a temporary char array for score[i][j] and then test if each element of the char array is a number? Or is there some easier method?
void getNameScore(string names[], double score[NGS_SIZE][S_SIZE], char grade[])
{
for (int i = 0; i < NGS_SIZE; i++)
{
cout << "Enter the student's name: ";
getline(cin, names[i]); // Allow for full name entry (first, middle, and last names)
double total = 0;
for (int j = 0; j < S_SIZE; j++)
{
cout << "Enter " << names[i] << "'s test " << j + 1 << " score: ";
while (!(cin >> score[i][j]) || score[i][j] < 0 || score[i][j] > 100) // input validation 0 to 100 as well as cin data type error checking
{
cout << "Enter a number between 0 and 100: ";
cin.clear(); // clear error flags when a non-integer value is entered in line 38
cin.ignore(10000, '\n'); // clear input buffer
}
total += score[i][j];
}
cout << endl;
cin.ignore(10000, '\n'); // clear getline buffer on line 32
double avg = total / S_SIZE;
if (avg >= 90)
grade[i] = 'A';
else if (avg >= 80)
grade[i] = 'B';
else if (avg >= 70)
grade[i] = 'C';
else if (avg >= 60)
grade[i] = 'D';
else
grade[i] = 'F';
}
}

When I enter a number between 0 to 70 it prints infinitely

When I enter a value between 0 to 70 it prints infinitely (which is wrong), but when input a number that is not between 0 to 70 it prompts the user to enter a number that should be between 0 to 70. (which is correct)
while (true)
{
if (hourswork < 0 || hourswork > 70)
{
cout<<"Please enter a value between 0 to 70: ";
cin>>hourswork;
}
else
{
wages = RATE * hourswork;
cout << "The wage is: " << wages << endl;
}
}
The result when I enter a value between 0 to 70 should only be printed once.
You should reconsider what you have in your while loop. Do you really want the output in there? You probably only want the loop to get input until it's valid. The output should instead be moved out of the loop:
int main() {
int hourswork = -1;
int RATE = 123;
while (hourswork < 0 || hourswork > 70)
{
cout << "Please enter a value between 0 to 70: ";
cin >> hourswork;
}
int wages = RATE * hourswork;
cout << "The wage is: " << wages << endl;
}
This way it will ask for a hourswork value until it is valid, which then stops the loop, and unconditionally does the print part once after the loop.
Generally the reason why your loop never terminated is because while (true) won't stop looping unless you get out of it with a break, return or something similar, neither of which is present in your code.
You need to leave your loop with a break when your hourswork was within range.
Like this:
while (true)
{
if (hourswork < 0 || hourswork > 70)
{
cout<<"Please enter a value between 0 to 70: ";
cin>>hourswork;
}
else
{
wages = RATE * hourswork;
cout << "The wage is: " << wages << endl;
break;
}
}

Program that finds Highest, Lowest, and Average of 5 number from an Array

My homework is to write a program that finds the highest, lowest, and average of 5 numbers in an Array that the user inputs. Here is my problem, the user does not have to enter all 5 numbers. But has to enter at least 2 numbers minimum.
I have the whole program done already I am having a problem with the beginning, below is my code where I am having a problem:
// Ask for name and explain program
cout << "Please enter your name: ";
cin >> name;
cout << endl;
cout << "Hi " << name << ", please enter up to 5 whole numbers." << endl;
cout << "I will find the HIGHEST, LOWEST, and AVERAGE number." << endl;
// Loop through users input
for (int i = 0; i < SIZE; i++)
{
cout << "Enter number " << (i + 1) << " : ";
cin >> number[i];
// Validate that the user has entered atleast 2 numbers
if (i >= 1 && i < 4)
{
cout << "Do you wish to enter another number (Y/N)? : ";
cin >> continue_game;
// Validate that the user only enters Y/N
while (continue_game != 'Y' && continue_game != 'y' && continue_game != 'N' && continue_game != 'n')
{
cout << "Please type in (Y/N): ";
cin >> continue_game;
}
// What happens if user chooses NO
if (continue_game == 'N' || continue_game == 'n')
{
i = 5;
}
// What happens if user chooses YES
else if (continue_game == 'Y' || continue_game == 'y')
{
i = i;
}
}
}
PROBLEM: If the user presses no after the 2nd number the remaining elements get a number asigned to them like : -8251616. Is there any way to make sure that the elements get assigned a zero or stay blank please help its due tomorrow and I can not figure it out.
SIZE = 5
Don't set i = 5 when the user says no. Just end the loop with a break; statement.
Also, the i = i; statement in the yes case is useless.
When you're getting the highest, lowest, and average values, make sure you only look at the values from 0 to i-1, so you don't access the uninitialized elemends of the array.
If you really want zeros you need to fill array with zeros:
int number[5] = {};
or
int number[5];
for (int i = 0; i < 5; ++i) {
number[i] = 0;
}
However this will give wrong output if the user enter less than 5 numbers. What you should do is to count how many numbers user entered and then use values from 0 to count - 1.
Advice, use break; instead of i = 5;.

Nested loops in C++ and user input

Pretty new here to programming, and I have an assignment where I need to achieve the following:
ask for total amount of people
get each of their names
allow user to enter up to 5 scores for each person
if there are less than 5 scores for a given person, inputting -100 will stop it
So far I have written this:
#include <iostream>
using namespace std;
int main() {
string personName;
int totalPerson, personScoreCounter;
double personGrade, personGradeTotal;
cout << "Input total amount of people: ";
cin >> totalPerson;
for (int person = 1; person <= totalPerson; person++)
{
cout << "Input name for person " << person << ": ";
getline(cin, personName);
cin.ignore();
while ( (personGrade != -100) && (personScoreCounter <= 5) )
{
cout << "Input up to 5 scores for " << personName << " (-100 to end): ";
cin >> personGrade;
if (personGrade >= 0 && personGrade <= 100) // valid range of scores
{
personGradeTotal += personGrade;
personScoreCounter++;
}
else
{
cout << "Input only scores from 0-100" << endl;
}
cout << "Input up to 5 scores for " << personName << " (-100 to end): ";
cin >> personGrade;
}
}
// calculate averages and other stuff in here.
return 0;
}
After getting their name, only the last cout inside the while loop seems to execute first, then it starts from the top and so on until the for loop hits the end depending on totalPerson. I know I'm missing a few things in here, probably in the order of operations and also the way I am executing my loops, but I just can't see it. Could any of you guys with experience in the language please give me any pointers as to what's happening here and how I can fix it? Thank you.
Inside your while group, you only want to use your cout line once (at the beginning looks good).
Your first check should be for ==-100 or similar, since as it is now, you'll get a "Input only scores from 0 to 100" message if you enter -100.
You should keep a cin.ignore(); call after each use of cin >> VARIABLE, since then you will drop the EoL character.
Example code:
#include <iostream>
using namespace std;
int main() {
int totalPerson;
cout << "Input total number of people: ";
cin >> totalPerson;
cin.ignore();
for (int person = 1; person <= totalPerson; person++)
{
int personScoreCounter=0;
double personGrade = -1, personGradeTotal=0;
string personName;
cout << "Input name for person " << person << ": ";
std::getline(cin, personName);
while ( (personGrade != -100) && (personScoreCounter < 5) )
{
cout << "Input up to 5 scores for " << personName << " (-100 to end): ";
cin >> personGrade;
cin.ignore();
if (personGrade == -100) {
break;
} else if (personGrade >= 0 && personGrade <= 100) {
personGradeTotal += personGrade;
personScoreCounter++;
} else {
cout << "Input only scores from 0-100" << endl;
}
}
// calculate averages and other stuff in here.
double avg = personGradeTotal / personScoreCounter;
cout << "Avg = " << avg << endl;
}
return 0;
}
Some of your variables also needed to move inside the for loop.
Additionally I changed the limits on the personScoreCounter to [0:4] rather than [1:5] - this way you can use it for averaging more easily.
You might also try cin.getline() instead of getline(std::cin , ... ):
int max_length = 30;
std::cin.getline(personName, max_length, '\n'); // \n is option termination.
This allows whitespaces in the input also.
http://www.cplusplus.com/reference/istream/istream/getline/