Program that checks whether numbers are already in an array - c++

This program is supposed to accept values from the keyboard, and require that the user re-enter the value for the employee's id number. However it keeps outputting "Invalid variable" even if I enter a correct value. It needs to only output that if the value is already been entered. For example
if I enter "3453" as the id number it will still output "Invalid Variable" even if I have not entered that number before.
#include <iostream>
using namespace std;
struct Employee
{
int idNum;
double payRate;
char firstName, lastName;
};
int main()
{
int error;
const int SIZE = 5;
Employee employee[SIZE];
for (int k = 0; k < SIZE; ++k)
{
employee[k].idNum = 0;
employee[k].payRate = 0;
}
for (int count = 0; count < SIZE; ++count)
{
error = 0;
cout << "Enter the employee's id number " << endl;
cin >> employee[count].idNum;
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == employee[count].idNum)
error = 1;
}
while (error == 1)
{
cout << "Invalid entry. Please enter a new id number " << endl;
cin >> employee[count].idNum;
for (int i = 0; i < SIZE; ++i)
{
error = 0;
if (employee[i].idNum == employee[count].idNum)
error = 1;
}
}
cout << "Enter the employee's pay rate " << endl;
cin >> employee[count].payRate;
cout << "Enter the employee's first name " << endl;
cin >> employee[count].firstName;
cout << "Enter the employee's last name " << endl;
cin >> employee[count].lastName;
int choice;
cout << "Enter 1 to search for an employee by id number, enter 2 to search by last name, and enter 3 to search by pay "
<< endl;
cin >> choice;
}
int choice;
cout << "Enter 1 to search for an employee by id number, enter 2 to search by last name, and enter 3 to search by pay "
<< endl;
cin >> choice;
if (choice == 1)
{
int idNumC;
cout << "Enter an id number ";
cin >> idNumC;
for (int count = 0; count < SIZE; ++count)
{
if (employee[count].idNum == idNumC)
cout << employee[count].idNum;
}
}
if (choice == 2)
{
char name;
cout << "Enter the employee's last name " << endl;
cin >> name;
for (int count = 0; count < SIZE; ++count)
{
if (employee[count].lastName == name)
cout << "ID number: " << employee[count].idNum
<< " First name: " << employee[count].firstName
<< " Last Name: " << employee[count].lastName
<< " Hourly Pay: " << endl;
}
}
if (choice == 3)
{
int name;
cout << "Enter the employee's last name " << endl;
cin >> name;
for (int count = 0; count < SIZE; ++count)
{
if (employee[count].payRate == name)
cout << "ID number: " << employee[count].idNum
<< " First name: " << employee[count].firstName
<< " Last Name: " << employee[count].lastName
<< " Hourly Pay: " << endl;
}
}
}
My program also will not accept a value of more than one letter into the name. If I try and enter that into the program, the program keeps printing "Invalid entry" until I hit ctrl+c.

for (int i = 0; i < SIZE; ++i)
This checks every element in the array, including the one you have just read. You probably meant to put
for (int i = 0; i < count; ++i)
which will check every element up to (but not including) the one you have just read.

in
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == employee[count].idNum)
error = 1;
}
employee[count] is one of the employee[i] you're going to compare against which means at some point you will
if (employee[count].idNum == employee[count].idNum)
Which is guaranteed to be true.
But if instead you
int tempId;
cin >> tempId;
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == tempId)
error = 1;
}
and then set
employee[count].idNum = tempId;
at some later time, you can avoid this problem.
Addendum: I recommend picking this logic up and placing it in its own function. That way A) you don't have to repeat it inside the loop a few lines down where you're repeating the check for each retry and it gets the logic out of the way of the rest of the code. B) you can use the same function later for any other "Does this employee exist?" checks you need to write in the future.
In general You want to have lots of simple, easily-tested functions over one monolithic jack-of-all-trades.

Related

Output does not include all input for my array

I have this program that is barely started:
#include <iostream>
#include <iomanip>
#include <ctime>
#include <string>
using namespace std;
class Grade
{
public:
string studentID;
int userChoice = 0;
int size = 0;
double* grades = new double[size]{0};
};
void ProgramGreeting(Grade &student);
void ProgramMenu(Grade& student);
string GetID(Grade& student);
int GetChoice(Grade& student);
void GetScores(Grade& student);
int main()
{
Grade student;
ProgramGreeting(student);
ProgramMenu(student);
}
// Specification C1 - Program Greeting function
void ProgramGreeting(Grade &student)
{
cout << "--------------------------------------------" << endl;
cout << "Welcome to the GPA Analyzer! " << endl;
cout << "By: Kate Rainey " << endl;
cout << "Assignment Due Date: September 25th, 2022 " << endl;
cout << "--------------------------------------------" << endl;
GetID(student);
cout << "For Student ID # " << student.studentID << endl;
}
void ProgramMenu(Grade &student)
{
cout << "--------------------------------------------" << endl;
cout << setw(25) << "Main Menu" << endl;
cout << "1. Add Grade " << endl;
cout << "2. Display All Grades " << endl;
cout << "3. Process All Grades " << endl;
cout << "4. Quit Program." << endl;
cout << "--------------------------------------------" << endl;
GetChoice(student);
}
string GetID(Grade &student)
{
cout << "Enter the student's ID: ";
cin >> student.studentID;
if (student.studentID.length() != 8) {
cout << "Student ID's contain 8 characters ";
GetID(student);
}
return student.studentID;
}
int GetChoice(Grade &student)
{
cout << "Enter your selection: ";
cin >> student.userChoice;
if (student.userChoice == 1) {
GetScores(student);
}
else if (student.userChoice == 2)
{
}
else if (student.userChoice == 2)
{
}
else if (student.userChoice == 4)
{
exit(0);
}
else
{
cout << "Please enter 1, 2, 3 or 4" << endl;
GetChoice(student);
}
}
void GetScores(Grade &student)
{
int count = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# "
<< student.studentID << "? ";
cin >> student.size;
while (count != student.size) {
cout << "Enter a grade: ";
cin >> score;
for (int i = 0; i < student.size; i++) {
student.grades[i] = score;
}
count++;
}
for (int i = 0; i < student.size; i++) {
cout << student.grades[i] << " ";
}
}
I am trying to make sure my array is recording all test scores, but when I output the array in my GetScore function, each element in the array is the same or equal to the last score I entered. For example, if I choose 3 for size and then enter three values of 99.2 86.4 90.1, all three elements will read 90.1.
Why is this happening?
Your Grade class is allocating an array of 0 double elements (which is undefined behavior), and then your GetScores() function does not reallocate that array after asking the user how many scores they will enter, so you are writing the input values to invalid memory (which is also undefined behavior).
Even if you were managing the array's memory correctly (ie, by using std::vector instead of new[]), GetScores() is also running a for loop that writes the user's latest input value into every element of the array, instead of just writing it to the next available element. That is why your final output displays only the last value entered in every element. You need to get rid of that for loop completely.
Try something more like this instead (there are several other problems with your code, but I'll leave those as separate exercises for you to figure out):
class Grade
{
public:
...
int size = 0;
double* grades = nullptr;
};
...
void GetScores(Grade &student)
{
int size = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# " << student.studentID << "? ";
cin >> size;
if (student.size != size) {
delete[] student.grades;
student.grades = new double[size]{0};
student.size = size;
}
for(int i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades[i] = score;
}
for (int i = 0; i < size; ++i) {
cout << student.grades[i] << " ";
}
}
Alternatively:
#include <vector>
...
class Grade
{
public:
...
vector<double> grades;
};
...
void GetScores(Grade &student)
{
size_t size = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# " << student.studentID << "? ";
cin >> size;
student.grades.resize(size);
for (size_t i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades[i] = score;
}
/* alternatively:
student.grades.clear();
for (size_t i = 0; i < size; ++i) {
cout << "Enter a grade: ";
cin >> score;
student.grades.push_back(score);
}
*/
for (size_t i = 0; i < size; ++i) {
cout << student.grades[i] << " ";
}
}
I removed my for loop from my while loop.
void GetScores(Grade &student)
{
int count = 0;
double score = 0;
cout << "How many test scores would you like to enter for ID# "
<< student.studentID << "? ";
cin >> student.size;
while (count != student.size) {
cout << "Enter a grade: ";
cin >> score;
student.grades[count] = score;
count++;
}
for (int j = 0; j < student.size; j++) {
cout << student.grades[j] << " ";
}
}

for loop with invalid error and looping questions

I am fairly new to C++, I am trying to write a code that allows input number of reviewers then allows number of reviewers to enter movie rating and display asterisks based on the number input. I am having difficulty incorporating an if statement that display "Movie ratings must be from 1 to 5." when the user input any number that's outside of 1 to 5. Another thing when it does work, it still continues the for loop of cout << "\nReviwer " << r << " rating: " ; instead of stopping and restarting. Any assistance is appreciated.
complied code
int reviewers;
int rating;
//input how many reviewers will be reviewing
cout << "How many reviewers? ";
cin >> reviewers;
cout << "Movie ratings must be from 1 to 5." << endl;
for (int r = 1; r <= reviewers; r++) {
cout << "\nReviwer " << r << " rating: ";
cin >> rating;
if (rating < 1 || rating > 5)
cout << "Movie ratings must be from 1 to 5." << endl;
else {
for (int j = 1; j <= rating; j++) {
cout << "* ";
} //end for
cout << endl;
} //end if
} //end for
Output example should be like this
You should have
#include <iostream>
#include <string>
using namespace std;
int main(){
int reviewers;
int rating;
//input how many reviewers will be reviewing
cout << "How many reviewers? ";
cin >> reviewers;
cout << "Movie ratings must be from 1 to 5." << endl;
for (int r = 1; r <= reviewers; r++) {
cout << "\nReviwer " << r << " rating: ";
cin >> rating;
while (rating < 1 || rating > 5){
cout << "Movie ratings must be from 1 to 5." << endl;
cout << "\nReviwer " << r << " rating: ";
cin >> rating;
}
if (rating >= 1 && rating <=5){
for (int j = 1; j <= rating; j++) {
cout << "* ";
} //end for
cout << endl;
} //end if
} //end for
}
};
It's not optimised but do the trick
if your mean is the reviewer must input the number between 1 and 5,
you can use a do while loop like this:
do
{
//enter rating;
}while (rating < 1||rating >5);
//print out rating;
I suppose you aim at something like this:
int reviewers;
int rating;
//input how many reviewers will be reviewing
cout << "How many reviewers? ";
cin >> reviewers;
cout << "Movie ratings must be from 1 to 5." << endl;
for (int r = 1; r <= reviewers; r++) {
while(true) {
cout << "\nReviewer " << r << " rating: ";
cin >> rating;
if (rating < 1 || rating > 5) {
cout << "Movie ratings must be from 1 to 5." << endl;
} else {
break;
}
}
for (int j = 1; j <= rating; j++) {
cout << "* ";
} //end for
cout << endl;
} //end for
Here is some code I quickly put together. I hope the comments are useful and if you have any questions just ask!
The main part is the recursive function get_ratings which will loop forever until it returns 1
// All this function does is returns the correct amount of stars
// E.G. make_stars(4) returns " * * * *"
string make_stars(int star_Count) {
string stars;
for (int i = 0 ; i < star_Count ; i++) {
stars += " *";
}
return stars;
}
// We get the ratings and returns 1 or 0 depending of it succeeded or failed
int get_ratings(int reviewer_count) {
// We initialise the ratings integer
int rating;
// We loop through all reviewers
for (int i = 0 ; i < reviewer_count ; i++) {
// We do i + 1 so it is more readable (usually in English we start at 1 not 0 like computers)
cout << "What is reviewer " << (i + 1) << "'s rating?" << endl;
//We get the user input
cin >> rating;
// We check to see if rating is withing the range. We could also do is NOT in the range and flip line 27 and 29
if (1 <= rating && rating <= 5) {
// If it is within range we will print the correct amount of stars
cout << make_stars(rating) << endl;
} else {
// We return 0 so we can determine the function "failed"
return 0;
}
}
// We return 1 so we can determine the function "succeeded"
return 1;
}
// This is a recursive function (it can run itself)
int get_ratings_rec(int reviewers) {
cout << "All ratings must be given between 1 and 5 (inclusive)" << endl;
// get_ratings_status is equal to 1/0 depending on if get_ratings() succeeded or failed
int get_ratings_status = get_ratings(reviewers);
if (get_ratings_status == 1) {
// If it was a success we print "Success!"
cout << "Success!" << endl;
} else {
// If it was a failure we tell the user and run get_ratings_loop() again until it succeeds
cout << "Failed, please try again\n" << endl;
get_ratings_loop(reviewers);
}
}
// Our main entry point to the program
int main() {
// We initialise the reviewers integer
int reviewers;
cout << "How many reviewers?\n>>> " << endl;
cin >> reviewers;
// We run get_ratings_loop() with the integer given
get_ratings_loop(reviewers);
}
You'd want to keep asking the number of stars if the user inputs a value outside the range, something like:
for (int r = 1; r <= reviewers; r++)
{
cout << "\nReviwer " << r << " rating: ";
do
{
cin >> rating;
if (rating < 1 || rating > 5) // print error message
cout << "Movie ratings must be from 1 to 5." << endl;
} while (rating < 1 || rating > 5); // repeat the loop if out of range
for (int j = 1; j <= rating; j++)
{
cout << "* ";
} //end for
cout << endl;
}
Note that you should be doing input validation also, e.g., if the input is an alphabetic character, your code will trigger an infinite loop, here an example of a possible solution:
#include <limits>
//...
do
{
if (!(cin >> rating))
{
std::cout << "Bad input, try again";
cin.clear(); //clear error flags
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // clear buffer
rating = 0;
}
if (rating < 1 || rating > 5)
cout << "Movie ratings must be from 1 to 5." << endl;
} while (rating < 1 || rating > 5);

Program gives errors using strings in array

I am creating an employee structure, with an array. However, it keeps returning this error.
The program is supposed to allow the user to enter an id number and validate, which already works. Then it is supposed to allow the user to search for a value inside the array.
#include <iostream>
#include <string.h>
using namespace std;
struct Employee
{
int idNum;
double payRate;
string firstName, lastName;
};
int main()
{
int error;
const int SIZE = 5;
Employee employee[SIZE];
for(int k = 0; k < SIZE; ++k)
{
employee[k].idNum = 0;
employee[k].payRate = 0;
}
for(int count = 0; count < SIZE; ++count)
{
error = 0;
cout << "Enter the employee's id number " << endl;
int tempId;
cin >> tempId;
for (int i = 0; i < SIZE; ++i)
{
if (employee[i].idNum == tempId)
error = 1;
}
while(error == 1)
{
cout << "Invalid entry. Please enter a new id number " << endl;
cin >> employee[count].idNum;
for(int i = 0; i < count; ++i)
{
error = 0;
if(employee[i].idNum == employee[count].idNum)
error = 1;
}
}
cout << "Enter the employee's pay rate " << endl;
cin >> employee[count].payRate;
cout << "Enter the employee's first name " << endl;
cin >> employee[count].firstName;
cout << "Enter the employee's last name " << endl;
cin >> employee[count].lastName;
}
int choice;
cout << "Enter 1 to search for an employee by id number, enter 2 to search by last name, and enter 3 to search by pay " << endl;
cin >> choice;
if(choice == 1)
{
int idNumC;
cout << "Enter an id number ";
cin >> idNumC;
for(int count = 0; count < SIZE; ++count)
{
if(employee[count].idNum == idNumC)
cout << employee[count].idNum;
}
}
if(choice == 2)
{
string name;
cout << "Enter the employee's last name " << endl;
cin >> name;
for(int count = 0; count < SIZE; ++count)
{
if(strcmp(employee[count].lastName, name) == 0)
cout << "ID number: "<< employee[count].idNum << " First name: " << employee[count].firstName << " Last Name: " << employee[count].lastName << " Hourly Pay: " << endl;
}
}
if(choice == 3)
{
int nam;
cout << "Enter the employee's pay rate " << endl;
cin >> nam;
for(int count = 0; count < SIZE; ++count)
{
if(employee[count].payRate == nam)
cout << "ID number: "<< employee[count].idNum << " First name: " << employee[count].firstName << " Last Name: " << employee[count].lastName << " Hourly Pay: " << endl;
}
}
}
I get
76:41: error: cannot convert 'std::string {aka
std::basic_string<char>}' to 'const char*' for argument '1' to 'int
strcmp(const char*, const char*)'
How can I fix this error? Thank you for your time.
You can compare two string with == so i should you if(employee[count].lastName==name) instead of if(strcmp(employee[count].lastName, name) == 0)
But if you want use strcmp try
if(strcmp(employee[count].lastName.c_str(), name.c_str()) == 0)

How create a user defined vector size with my existing code?

I have a program that takes in 10 "purchase prices" from a user and displays them in the console screen. I am attempting to modify the code to make it to where the user can determine how many inputs they like for "purchase prices" and then displays that amount of them on the console screen.
The current modification i was successful in was changing was the for loop inside the vector from for "(int i = 0; i < 10; i++)" to "for (int i = 0; i < purchases.size(); i++)" but from here I am stuck.
It seems that I may need some function or loop prior to the vector declaration to set the size variable based on user entries possibly but I am not sure. Thank you for you help-
My code:
vector<double> purchases(10);
{
for (int i = 0; i < purchases.size(); i++)
{
cout << "Enter a purchase amount: ";
cin >> purchases[i];
}
cout << "The purchase amounts are: " << endl;
for (int i = 0; i < 10; i++)
{
cout << purchases[i] << endl;
}
}
system("PAUSE");
return (0);
}
I can think of the following approaches.
Ask the user for the number of purchases they wish to enter. Then, create the vector with that size.
int num;
cout << "Enter the number of purchases: ";
cint >> num;
vector<double> purchases(num);
for (int i = 0; i < num; i++)
{
cout << "Enter a purchase amount: ";
cin >> purchases[i];
}
cout << "The purchase amounts are: " << endl;
for (int i = 0; i < num; i++)
{
cout << purchases[i] << endl;
}
When asking the user for the purchase price, provide the option to enter something else to stop. After each successful read, use push_back.
vector<double> purchases;
while ( true )
{
std::string s;
cout << "Enter a purchase amount or q to stop: ";
cin >> s;
if ( s == "q" )
{
break;
}
std::istringstream str(s);
double purchase;
str >> purchase;
purchases.push_back(purchase);
}
cout << "The purchase amounts are: " << endl;
size_t num = purchases.size();
for (int i = 0; i < num; i++)
{
cout << purchases[i] << endl;
}

error string subscript out of range c++

i have a guessed name game. and i have a problem with this function. in the nested loop if the user entered a wrong letter it gives me this error:
line: 1440
expression: string subscript out of range
this is the function:
void Play(int selection, int FArraySize, int MArraySize,string Female[], string Male[])//Receive the selected name category array and its size and implements the game logic as shown in the sample run. Uses function GetRandomName(…).
{
int MAX_TRIES = 4;
int m = 0;
int x=0;
int j=0;
ofstream ofFile;
ifstream InFile;
int num_of_wrong_guesses=0;
char letter;
string GuessedName;
GuessedName = GetRandomName(selection, FArraySize, MArraySize, Female, Male);
cout << "Guess the following name:" << endl;
for(int y = 0; y < GuessedName.length(); y++){
cout << "?";
j++;
}
cout << "\nEnter a guess letter? or * to enter the entire name" << endl;
cin >> letter;
int i =0;
for ( int count = 0 ; count <= MAX_TRIES ; count++)
{
while (i <= j)
{
if (letter == GuessedName[i])
{
i = m;
cout << letter << " exists in the name";
cout << "\nyou have " << MAX_TRIES << " remaining guess attemps... "<< endl;
break;
}
if (i == j)
{
cout <<"Sorry! " << letter << " dose not exist in the name";
cout << "\nyou have " << MAX_TRIES-- << " remaining guess attemps... ";
break;
}
i++;
}
cout << "\nGuess the following name:" << endl;
for(int y = 0; y < GuessedName.length(); y++){
cout << "?";
j++;
}
cin >> letter;
}
return;
}
hope you can help me.
while (i <= j) should be while (i < j).
Otherwise GuessedName[i] will try to access out-of-bounds when i == j. j - 1 is the index of the last letter.