My C++ Program wont accept inputs after the menu - c++

I am doing a program for a class in school, and when I try to run the code I wrote below (only half of the project is done, but it's in a state where it should run anyways) the menu comes up fine, but then it jumps straight to the end of the program and wont let me input the important part..
When I remove the menu (which will be a necessity later when I finish the project) it works fine, but when it's there like I need it to be, it wont run properly
//Project 4 Written By Nate
#include <iostream>
#include <iomanip>
using namespace std;
int menuOption;
char stockName[21],symbol[10];
float openingPrice,closingPrice,numberShares,gain;
int main()
{
// MENU //
cout<<"Welcome to Project 4! Please select the program you would like to run:\n\n 1)Stock Program\n\nEnter your selection: ";
cin>>menuOption;
if(menuOption == 1) {
goto stockProgram;
} else
{
cout<<"Invalid response received. Program will now terminate";
return 0;
}
stockProgram:
cout<<"This program will ask you information about a stock you own.\n\n";
cout<<"Enter stock name: ";
cin.get(stockName,21);
cin.ignore(80,'\n');
cout<<"Symbol: ";
cin.get(symbol,10);
cin.ignore(80,'\n');
cout<<"Enter opening price: ";
cin>>openingPrice;
cout<<"Enter closing price: ";
cin>>closingPrice;
cout<<"Enter the number of shares: ";
cin>>numberShares;
cout<<"\n\n";
gain=(numberShares*closingPrice)-(numberShares*openingPrice);
cout<<setw(10)<<"Stock Name"<<setw(10)<<"Symbol"<<setw(10)<<"Opening"<<setw(10)<<"Closing"<<setw(10)<<"Shares"<<setw(11)<<"Gain\n";
cout<<setw(10)<<stockName<<setw(10)<<symbol<<setw(10)<<openingPrice<<setw(10)<<closingPrice<<setw(10)<<numberShares<<setw(10)<<gain<<"\n\n";
cout<<"=====================================================================\n";
cout<<" This gain could've been yours, too bad you are an anti-mac person.\n";
return 0;
}
Thanks..

You probably still have the a newline character or other characters after the 1 in the initial input. You've used cin.ignore on other inputs but not the first.
cout<<"Welcome to Project 4! Please select the program you would like to run:\n\n 1)Stock Program\n\nEnter your selection: ";
cin>>menuOption;
cin.ignore(80,'\n');
ignore will extract the delimiting \n
Also, whenever dealing with istream check that it was successful in getting the input into the correct type:
#include <limits>
#include <sstream>
int myVariable;
if( (cin >> myVariable).fail() )
{
// Error - input was not an integer
std::cerr << "Input was not an integer" << std::endl;
return -1;
}
cin.ignore(numeric_limits<streamsize>::max(), '\n');

Adding cin.ignore() after cin>>menuOption- this will read the one int that currently resides within the buffer & discard it since the EOF is the new line after input.
int main()
{
// MENU //
cout<<"Welcome to Project 4! Please select the program you would like to run:\n\n 1)Stock Program\n\nEnter your selection: ";
cin>>menuOption; cin.ignore();
if(menuOption != 1) {
cout<<"Invalid response received. Program will now terminate";
return 0;
}
//etc
}

Related

Detect blank input on integer type variable?

I am currently working on a text based adventure game as a project for class. I have mostly everything started and working fine. The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room." For the life of me I cannot figure it out. Any help is much appreciated.
Code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
bool game_play = true;
bool game_start = true;
int room_change;
int room_current = 0;
while (game_play == true) {
if (game_start == true) {
srand((unsigned int)time(NULL));
room_change = rand() % 2 + 1;
game_start = false;
}
else {
for (bool check = false; check == false;) { // Check if input is invalid
cin >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
}
else if (room_change == room_current) {
cout << "You're already in that room.";
}
else {
check = true;
}
}
}
switch (room_change) {
case 1:
cout << "You are in room 1.";
room_current = 1;
break;
case 2:
cout << "You are in room 2.";
room_current = 2;
break;
case 3:
game_play = false;
break;
default:
cout << "That room doesn't exist.";
}
}
return 0;
}
I just ran your code and when you hit enter, it will keep waiting until you enter a number or something invalid such as a character or a string. I did find that if you change your code from
cin >> room_change;
to
cin >> noskipws >> room_change;
when the user inputs a blank, it will cause the cin.fail() to return true and then proceed to print "Choose an existing room."
In your situation, the while loop will keep getting called until we have valid input. The "Choose an existing room" does get repeated because room_change is an integer, so when we hit enter, the '\n' will be left in the buffer. The while loop on the next iteration then reads that '\n' and executes the cin.fail() before letting you input something else. One solution I found is to use more cin.ignore() statements.
for (bool check = false; check == false;) { // Check if input is invalid
cin >> noskipws >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
} else if (room_change == room_current) {
cout << "You're already in that room.";
cin.ignore();
} else {
check = true;
cin.ignore();
}
}
The reason is because we want to get rid of that '\n' so that the cin.fail() does not execute. However, I did find that when you input a character, it will print "Choose an existing room" twice. It will print the first time because a character is not an integer, and a second time because of that '\n'.
The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room."
Using std::getline and then extracting the number from the line using a std::istringstream is a better strategy for that.
std::string line;
std::cout << "Choose an existing room. ";
while ( std::getline(std::cin, line) )
{
// Try to get the room_change using istringstream.
std::istringstream str(line);
if ( str >> room_change )
{
// Successfully read the room.
break;
}
// Problem reading room_change.
// Try again.
std::cout << "Choose an existing room. ";
}
#include <iostream>
using namespace std;
int main(){
int room_change=200;
cout<<"Enter Blank";
cin>>room_change;
if(room_change==NULL){
cout<<"There is NO-THING"<<endl;
}
if(room_change!=NULL){
cout<<"There is something and that is :"<<room_change<<endl;
}
return 0;
}
But a much simpler approach to this would be to use Strings. If this is a Homework of sort and you are limited to Integer variable only. Its much more complicated if you want to detect if an Buffer is empty or not. Regardless of homework limitation, the OS layer input is String based. How can I use cin.get() to detect an empty user input?

How do I have a input statement that repeats until the number of fields chosen by the user are finished?

I am trying to create a chore chart with a bit of console code but I'm very new to C++ and I'm running into a roadblock trying to figure out how to create a loop that asks the user the following:
How many chore fields they would like to input
Input prompt for each field
When the chosen number of fields have been completed a new prompt should ask if the user would like to input more fields or if they are finished.
If they want to input more, start back at loop for # of fields to input or if finished have it print the chore chart to screen. Very basically as I am still grasping these functions.
Here's my code so far:
#include <iostream>
using namespace std;
int main()
{
int chores_num;
while (finished = true) = {
cout << "How many chores would you like to input?\n"
cin >> chores_num;
cout << "Enter Chore\n";
cin >> chore;
cout << ""
}
return 0;
}
You could think about your problem this way: Get number of chores to input; That number of times, get a specific chore input; Get whether to repeat, and do so if yes.
If you have already covered how to write simple functions, I would suggest breaking up your program into functional (pun intended) parts, each in their own function. This is widely considered good programming practice, and can make programs much more readable. If you aren't comfortable with writing/calling your own functions, don't sweat it for now, but keep this in mind later.
C++ has a bit of a learning curve, but is extremely powerful once you've got the hang of it. Keep it up!
You need 2 loops, but your code only has 1 loop. You need 1 loop to keep asking if chores should be entered, and 1 loop to enter the actual chores.
For example:
#include <iostream>
#include <string>
#include <limits>
using namespace std;
template <typename T>
T prompt(const char *msg)
{
T input;
cout << msg << " ";
while (!(cin >> input)) {
cout << "Invalid input, try again: ";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return input;
}
template <>
string prompt<string>(const char *msg)
{
string input;
cout << msg << " ";
getline(cin, input);
return input;
}
int main()
{
int chores_num;
string chore;
char choice;
do {
chores_num = prompt<int>("How many chores would you like to input?");
for (int i = 0; i < chores_num; ++i) {
chore = prompt<string>("Enter chore:");
//...
}
choice = prompt<char>("Input more chores (Y|N)?");
}
while ((choice == 'y') || (choice == 'Y'));
// print chore chart...
return 0;
}

checking if entered value is float, clearing cin

I have tried a few different variations of this code and I can't seem to get it right. I am pretty new to c++ yet so that might explain it. This code is part of a simple calculator. It basically asks the user to enter two numbers (they can be floats) and then asks the user for a mathematical operator and then does the operation. If a user enters something that's not a number and then enters a number when asked to enter a number again from the if statement the console prints "-9.25596e+061". This is the code:
#include "stdafx.h"
#include <iostream>
#include <cctype>
using namespace std;
double getUserInput()
{
//Make double, assign double, return double if number
double dUserInput;
//checks if it failed to cin
if (!(cin >> dUserInput))
{
//statement is true
cin.clear();
cin.ignore(99999, '\n');
cout << "You did not enter a number, please try again: ";
getUserInput();
}else
//statement if false
cout << "Number entered"; //for debugging purposes
return dUserInput;
}
You missed to add return in the recursive call to getUserInput.
Change the line
getUserInput();
to
return getUserInput();
Update
You can change the function to a non-recursive version.
double getUserInput()
{
//Make double, assign double, return double if number
double dUserInput;
//checks if it failed to cin
while (!(cin >> dUserInput))
{
cin.clear();
cin.ignore(99999, '\n');
cout << "You did not enter a number, please try again: ";
}
cout << "Number entered"; //for debugging purposes
return dUserInput;
}

problems with using the "cin" object

in my final project, a poker and black jack simulator, my main function doesn't appear to want "cin" to work. The entire project is syntax error free, so that's not a problem, but in order to test to see if it runs or not, I need "cin" to work. The following is my main function, where I seem to be having the trouble:
#include <iostream>
using namespace std;
#include "card.h"
#include "poker.h"
#include "blackJack.h"
void handlePoker(int&);
void handleBlackJack(int&);
//TO DO:
//FIX CIN PROBLEM
//*pulls hair out*
//main function:
//asks the user what game they want to play
//then calls a function for the appropriate
//game chosen
int main()
{ //two choices:
//one for quitting the program
//the other for whichever game they want
char yesOrNo;
char choice;
int totalMoney;
cout<< "please enter a starting amount to bet with"<<endl;
cin>> totalMoney;
do{
//ask the user which game they want
cout<<"would you like to play poker or black jack?"<<endl;
cout<<"input '1' for poker and '0' for blackjack"<<endl;
cin>>choice;
if(choice == '1')
{
handlePoker(totalMoney);
}
else if(choice == '0')
{
handleBlackJack(totalMoney);
}
else
{
cout<<"I'm sorry, the input you entered was invalid"<<endl;
cout<<"please try again"<<endl;
}
cout<<"would you like to try again?"<<endl;
cout<<"('y' for yes, or 'n' for no)"<<endl<<endl;
cin>>yesOrNo;
}while(yesOrNo == 'y' || yesOrNo == 'Y');
}
Everytime I use "cin" in the do while loop, it won't let me input anything. The program never stops for user input.
as it is not, he's the program's output:
"please enter a starting amount to bet with"
*user can enter starting amount here, this "cin" works no problem*
"input '1' for poker and '0' for black jack"
"I'm sorry, the input you entered was invalid"
"please try again"
"would you like to try again?"
"('y' for yes, or 'n' for no)
then the program ends, because none of the choices have any value in them.
I'll include more code if asked, but I believe this is where the problem with it lies.
thank you to all who may help me!
edit: The program does enter the do while loop, and all messages are printed as they should bee, but the program won't let me input any data at all, it doesn't stop to let me input data, it just acts as if they do not exist.
Usually when I see cin ignoring everything and putting me in an infinite loop, that's caused when I enter in invalid input, and never clear the stream state. Namely, entering "A" for a number will do that. The idiomatic way to do this would be something like
while (! (cin >> totalMoney)) {
cout<<"I'm sorry, the input you entered was invalid"<<endl;
cout<<"please try again"<<endl;
cin.clear(); //important
}
// totalMoney holds a valid value now
Try using cin.ignore() instead of just cin for the process to wait for user input
cin>>choice;
cin.ignore();
Check out this link on MSDN for more info

How to Use real string types to represent strings within a function of a class structure?

I have been given a task of inputting some student data, like
option 1: Enter student name and id.
option 2: input i.d (verify against student id - input option 1), input upto 10 grades for the student and then calculating the average and letter grade for the student
option 3: output the student name, id and letter grade.
The program has to be written in a Class like structure - with declared variables and functions in the structure.
I have also been given the task for entering the details of 3 students using the Class structure. For simplicity sakes for now I am just writing a program for one student.
The program compiles O.K
First specific encountered problem: When I select option 'I' the program lets me input the student name and that's it! - skips the id input for some reason and continues on.
The problem is that I have been using cin>>and also scanf() as my main input methods - but these and system("Pause") have not been serving me well - I understand system("pause") is not very efficient. In the past I have been advised to use a real string type to represent strings like std::string class from the <string> library.
I would therefore appreciate any help with string classes so I can learn of them.
I believe there may be some other problems with my program but any advice with the string classes thing and my 'first specific encountered problem' would helpful to start of with.
So I have written the following program to represent my answer.
#include <iostream>
#include <cstdio>
#include <math.h>
using namespace std;
struct classroom{
char name;
int student_id;
float grades[10];
int num_tests;
float average;
float letter_grade;
void enter_name_id(void);
void enter_grade(int);
void average_grades(int);
void letter_grades(void);
void output_name_id_grade(void);
};
void classroom::enter_name_id(){
cout<<"\n Please enter name of student: \n"<<"\n";
cin>>name;
cout<<"\n Please enter student i.d number: \n"<<"\n";
scanf("%d",student_id);
cout<<"\n"<<student_id;
system("PAUSE");
}
void classroom::enter_grade(int n_tests){
if(n_tests<=10){
cout<<"\n Please enter student test grade: \n"<<"\n";
cin>>grades[n_tests];
}
else{
cout<<"\n You have reached your max number of grades entered!!"<<"\n";
}
system ("PAUSE");
}
void classroom::average_grades(int n_tests){
float sum=0;
int i;
for(i=0;i<n_tests;i++){
sum =sum+grades[i];
}
average=sum/(float)n_tests;
system ("PAUSE");
}
void classroom::letter_grades(void){
if(average>=90){
letter_grade=65;
}
if(average>=80&&average<90){
letter_grade=66;
}
if(average>=70&&average<80){
letter_grade=67;
}
if(average>=60&&average<70){
letter_grade=68;
}
if(average<60){
letter_grade=70;
}
system ("PAUSE");
}
void classroom::output_name_id_grade(void){
cout<<"\ Name I.D Grade "<<"\n";
cout<<name <<" ";
cout<<student_id<<" ";
cout<<(char)letter_grade<<"\n";
system ("PAUSE");
}
int main()
{
classroom a;
char option,answer,ans;
int a_num_tests, id;
a_num_tests=0;
for( ; ;){
cout<<"\nEnter 'I' for Name and I.d, 'G' for grades or 'O' for Data output "<<"\n";
cin>>answer;
switch(answer){
case'I':
a.enter_name_id();
break;
case'G':
cout<<"\n Please enter student i.d number: "<<"\n";
scanf("%d",id);
cout<<"\n"<<id;
if(id==a.student_id){
a_num_tests++;
a.enter_grade(a_num_tests);
cout<<"\n Would you like to enter another grade? 'Y' or 'N': "<<"\n";
cin>>ans;
while(ans=='y'||'Y'){
a_num_tests++;
a.enter_grade(a_num_tests);
cout<<"\n Would you like to enter another grade? 'Y' or 'N': "<<"\n";
cin>>ans;
}
a.average_grades(a_num_tests);
a.letter_grades();
}
else{
cout<<"\n You have entered the wong i.d number!!! \n"<<"\n";
break;
}
case 'O':
a.output_name_id_grade();
break;
default:
cout<<"\n Wong Entry "<<"\n";
break;
}
}
system ("PAUSE");
return 0;
}
Hi again for all those whom want to know, this code worked for me:
void classroom::enter_name_id(void){
cout << " Please enter your name\n>";
std::cin.ignore( 25, '\n' );
cin.getline( name,25);
cout << " Type id\n>";
cin>>student_id;
return;
}
Not sure how this line works: 'std::cin.ignore( 25, '\n' );'!!!
But never the less it was needed in order to prevent the compiler skipping
the next line: 'cin.getline( name,25);'
Originally I had problems with just using 'cin>>name' in the class function and this is why I have asked the questions for alternative real string types.
If anyone has more to add to this question, please do so.
I would like to say thank you again to all my fans out there whom have contributed to this progress we have made together.
Sail on...
So many things to say... why would you write << "\n" << "\n"?? You can just put the entire string in one piece, << "\n\n"... anyway.
For input/output, just stick with iostreams, and don't mix and match C library functions without good cause. Perhaps like so:
std::string name;
int id;
std::cout << "Please enter your name: ";
std::getline(std::cin, name);
std::cout << "Please enter the ID: ";
std::cin >> id; // see below
Maybe this answer is of some use to you. The input operations should be checked for errors, if you want to write serious code.
Note that token extraction (>>) reads word by word, so std::cin >> name will only read one single word. For something like a name, we prefer getline() for that reason.
If you run your program from the command line, you won't need all those system("pause") calls, either...
Update: It's not generally a good idea to mix token extraction (>>) with line reading (getline()), since the former doesn't gobble up newlines while the latter does. Best to stick to just one of the two, whichever is more appropriate for the input format.
If you only use line reading, you still have to process each line, perhaps again by token extraction. To do so, you need a string stream. Include <sstream> and replace the last line by:
std::string line; // you can put this at the top with the other declarations
std::getline(std::cin, line);
std::istringstream iss(line);
iss >> id;
scanf causes buffer problem. You need to clear the buffer after using it.
fflush(stdin). this will clear your buffer and input will stop for id and other inputs.
Also you can use getch() instead of system ("PAUSE");