C++ getline function continuous loop - c++

I am trying to use a getline function in the following code, however it just enters an indefinite loop. Should I enter 1, it will then jump to the another iteration of the loop and ask for my menu choice again, rather than asking for my name.
Does anyone have any idea where I'm going wrong?
#include <iostream>
#include <string>
#include <ncurses.h>
using namespace std;
// DECLARE
void menu();
void menu_act_on_choice();
void string_function();
// CODE
void menu_act_on_choice(int choice_in) {
switch (choice_in) {
case 1:
string_function();
break;
default:
break;
}
}
void string_function() {
string user;
cout << "Enter your first and last: ";
getline(cin, user);
cout << user << endl;
}
void menu() {
int choice = 0;
do {
cout << "1. String functions" << endl;
cout << "2. Array functions" << endl;
cout << "3. Exit" << endl;
cout << "Enter choice: ";
cin >> choice;
menu_act_on_choice(choice);
} while(choice != 3);
}
//EXECUTE
int main() {
menu();
}

When you enter the menu choice which is read by
cin >> choice;
you ended that with the Enter key right?
That Enter key will be added to the input buffer as a newline. But cin >> choice will not read it, instead that happens with the getline call which reads it as an empty line.
The simple solution is to ignore all input until (and including!) the newline after getting the menu choice.
cin >> choice;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Add cin.ignore(); before getline line.

Related

Why is this cin validation not working on other file while work only on one file?

I am trying to use this cin validation on every input on my project, mostly for 'choosing' activity.
if (cin.fail()) { // Failed to parse input correctly
cin.clear(); // Clear the internal flags
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Ignore the rest of the buffer
}
This code works only on one file which is the Menu.cpp, but not Conference.cpp. It shows one error which is 'E0040 expected an identifier' and it highlighted the max() syntax. I also try to copy the code from Menu.cpp to Conference.cpp but still it shows the same error on Conference.cpp. I don't know what causes the error.
Menu.h
#pragma once
class Menu
{
public:
Menu();
void mainmenu();
void dataregmenu();
~Menu();
};
Menu.cpp
#include "Menu.h"
#include "Menu_controller.h"
#include <iostream>
using namespace std;
Menu::Menu()
{
}
void Menu::mainmenu()
{
int choose;
cout << "-----Conference Vault----- \n\n";
cout << "1. Data Registration \n";
cout << "2. Conference \n";
cout << "3. Report \n\n";
cout << "Choose: ";
cin >> choose;
if (cin.fail()) { // Failed to parse input correctly
cin.clear(); // Clear the internal flags
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Ignore the rest of the buffer
}
new Menu_controller(choose);
}
void Menu::dataregmenu()
{
int choose;
cout << "-----Data Registration----- \n\n";
cout << "1. ADUN \n";
cout << "2. Department \n\n";
cout << "3. Back \n\n";
cout << "Choose: ";
cin >> choose;
if (cin.fail()) { // Failed to parse input correctly
cin.clear(); // Clear the internal flags
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Ignore the rest of the buffer
}
}
Menu::~Menu()
{
}
Conference.h
#pragma once
#include <iostream>
using namespace std;
class Conference
{
public:
Conference();
void conferencemenu();
void addconference();
~Conference();
};
Conference.cpp
#include "Conference.h"
#include "Conference_controller.h"
#include <iostream>
using namespace std;
Conference::Conference()
{
}
void Conference::conferencemenu()
{
int choose;
cout << "Choose what to do: \n\n";
cout << "1. Add new conference \n";
cout << "2. Find conference \n\n";
cout << "3. Back \n\n";
cout << "Choose: ";
cin >> choose;
if (cin.fail()) { // Failed to parse input correctly
cin.clear(); // Clear the internal flags
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Ignore the rest of the buffer
}
new Conference_controller(choose);
}
void Conference::addconference()
{
string year, month, number;
Conference_controller conf;
cout << "-----New Conference----- \n\n\n";
cout << "Please fill in the required fields: \n\n";
cout << "Year: ";
cin >> year;
cout << "Month: ";
cin >> month;
cout << "Number: ";
cin >> number;
conf.addconference(year, month, number);
}
Conference::~Conference()
{
}

While loop not breaking, using cin.ignore and cin.clear() to verify input

I'm trying to use a loop to verify that the input grade is an integer, but when I intentionally input a char, the program does nothing. It only starts a newline upon pressing enter.
void fillvector(vector<student>& parameter)
{
string newname;
int newgrade;
int number;
cout << "How many students are in your class: ";
cin >> number;
for (int i = 0; i < number; i++)
{
cout << endl << "Enter student name: ";
while (1)
{
cin >> newname;
cout << "Enter student grade: ";
cin >> newgrade;
if (cin.fail())
{
cout << endl << "Grade must be an integer value, try again.";
cin.clear();
cin.ignore(INT_MAX);
i--;
break;
}
else
{
student student(newname, newgrade);
parameter.push_back(student);
break;
}
}
}
cout << endl;
}
cin.ignore(INT_MAX);
This will make cin ignore any further characters you enter up to MAX_INT..
What you wanted is to ignore up-to the next newline:
cin.ignore(INT_MAX, '\n');
Besides, there is no point in making a while(1) loop that will break in all paths in the first iteration. You can remove that inner loop.

c++ getline function does not let me input

So i have a palindrome program and here are the codes:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
void palindrome();
void compareTwoInt();
bool validation(const string&);
int main()
{
int selection;
cout << "\t\t\t MENU\n";
cout << "\t\t\t ----\n";
cout << "\t\t\t1. Palindrome";
cout << "\n\t\t\t2. Compare Two Integers";
cout << "\n\t\t\t3. End program\n";
cout << "\n\t\t\tEnter your choice : ";
cin >> selection;
while (selection < 0 || selection > 4)
{
cout << "\t\t\nInvalid entry. Please enter an appropriate entry.";
cout << "\n\n \t\t\tEnter your choice: ";
cin >> selection;
}
if (selection == 1)
{
cout << "Enter a word, phrase, sentence: \n";
string input;
getline(cin, input);
string input2;
for (unsigned int i = 0; i < input.length(); i++)
{
if (isalnum(input[i]))
{
input2 += toupper(input[i]);
}
}
cout << input2 << endl;
if (validation(input2))
{
cout << "The phrase is a palindrome!" << endl;
cout << "Press <Enter> key back to menu" << endl;
}
else
{
cout << "The phrase is not a palindrome!" << endl;
cout << "Press <Enter> key back to menu" << endl;
}
fflush(stdin);
cin.get();
system("cls");
return main();
}
else if (selection == 2)
{
compareTwoInt();
fflush(stdin);
system("cls");
return main();
}
else if (selection == 3)
{
cout << "\t\t Good Bye. Press <Enter> key to End the program.\n";
}
fflush(stdin);
cin.get();
return 0;
}
void compareTwoInt()
{
int first, second;
cout << "\n\nEnter your positive integer : ";
cin >> first;
cout << "\nEnter your positive integer : ";
cin >> second;
fflush(stdin);
cin.get();
}
bool validation(const string& input)
{
return input == string(input.rbegin(), input.rend());
}
for some reason when i choose 1 for the palindrome, it doesn't let me write the words, (in another words, it doesn't let me input)
the console just says:
Enter a word, phrase, sentence:
The phrase is palindrome!
Press key back to menu
Anybody have an idea how to fix this?
Thanks in advance!
When you choose 1 for the palindrome, you hit enter. Thus your input consists of the number 1 followed by a newline. Your cin >> selection; reads the number 1 and then your getline(cin, input); reads the newline, which it interprets as an empty line. You have written no code to do anything sensible with the newline character input after the number, so nothing sensible happens.
Try typing 1foof<enter> instead. Your code will read that as a 1 followed by a line containing foof.

Code to get user input not executing/skipping in C++

In the below code, I'm running into an error when I try to get the user to input their name. My program just skips it over and goes right over to making the function calls without allowing the user to enter their name. Despite the error, my program is compiling. I'm not sure what's going wrong as I wrote that part based off other examples I found on here. Any suggestions?
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
char showMenu();
void getLottoPicks(int[]);
void genWinNums(int[]);
bool noDuplicates(int[]);
const int SIZE = 7;
int main()
{
int userTicket[SIZE] = {0};
int winningNums[SIZE] = {0};
char choice;
string name;
srand(time(NULL));
do
{
choice = showMenu();
if (choice == '1')
{
cout << "Please enter your name: " << endl;
getline(cin, name);
getLottoPicks(userTicket);
genWinNums(winningNums);
for (int i = 0; i < SIZE; i++)
cout << winningNums[i];
}
} while (choice != 'Q' && choice != 'q');
system("PAUSE");
return 0;
}
Added the code for showMenu:
char showMenu()
{
char choice;
cout << "LITTLETON CITY LOTTO MODEL:" << endl;
cout << "---------------------------" << endl;
cout << "1) Play Lotto" << endl;
cout << "Q) Quit Program" << endl;
cout << "Please make a selection: " << endl;
cin >> choice;
return choice;
}
And getLottoPicks (this part is very wrong and I'm still working on it):
void getLottoPicks(int numbers[])
{
cout << "Please enter your 7 lotto number picks between 1 and 40: " << endl;
for (int i = 0; i < SIZE; i++)
{
cout << "Selection #" << i + 1 << endl;
cin >> numbers[i];
if (numbers[i] < 1 || numbers[i] > 40)
{
cout << "Please choose a number between 1 and 40: " << endl;
cin >> numbers[i];
}
if (noDuplicates(numbers) == false)
{
do
{
cout << "You already picked this number. Please enter a different number: " << endl;
cin >> numbers[i];
noDuplicates(numbers);
} while (noDuplicates(numbers) == false);
}
}
}
After doing cin >> choice; inside char showMenu(), if a user inputs 1[ENTER], the char consumes 1 character from cin, and the newline stays inside the stream. Then, when the program gets to getline(cin, name);, it notices that there's still something inside cin, and reads it. It's a newline character, so getline gets it and returns. That's why the program is behaving the way it is.
In order to fix it - add cin.ignore(); inside char showMenu(), right after you read the input. cin.ignore() ignores the next character - in our case, the newline char.
And a word of advice - try not to mix getline with operator >>. They work in a slightly different way, and can get you into trouble! Or, at least remember to always ignore() after you get anything from std::cin. It may save you a lot of work.
This fixes the code:
char showMenu()
{
char choice;
cout << "LITTLETON CITY LOTTO MODEL:" << endl;
cout << "---------------------------" << endl;
cout << "1) Play Lotto" << endl;
cout << "Q) Quit Program" << endl;
cout << "Please make a selection: " << endl;
cin >> choice;
cin.ignore();
return choice;
}
from looking at code showMenu function has problem. and it's not returning asccii equivalent of '1' that is: 31 integer. try printing value returned by showmenu. you will get that
UPDATE:
It is because cin in delimited by ' '(whitespace) and getline by '\n' character, so when enter name and press enter cin in showmenu will consume whole string except '\n' from istream and that is read by getline. to see this when it ask for choice enter string like 1 myname (1 whitespace myname)and press ENTER will display name. now cin will read 1 in choice and myname in name by getline.

issue with c++ code skipping get line statement

Hey guys i am having an issue with an assignment I am working on.
The code is as follows:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
class payroll
{
private:
char empnum[10];
char empfirstname[150];
char emplastname[150];
char empsin[9];
char empdob[10];
char empphone [15];
char empstreet[100];
char empcity[60];
char empprovince[150];
char empcountry[200];
char empstatus[50]; //Employee status. EX: Terminated, On leave, Active etc.
int empsalaryei;
int empsalaryfedtax;
int empsalarycpp;
int empsalarynet;
int empsalarygross;
public:
void addrec(void);
void modrec(void);
void viewrec(void);
void exit(void);
};
payroll rec;
payroll emp;
ifstream inFile1;
ifstream inFile2;
bool check = false;
int main()
{
system("CLS");
char ch;
do
{
cout<<"1. Add an employee\n";
cout<<"2. Modify employee record\n";
cout<<"3. View employee record\n";
cout<<"0. Exit\n";
cout<<"Please choose an item: ";
if (check == true)
{
system("CLS");
ch=0;
}
else
cin>>ch;
switch(ch)
{
case '1':
emp.addrec();
break;
case '2':
emp.modrec();
break;
case '3':
emp.viewrec();
break;
case '0':
emp.exit();
return 0;
}
}while(ch !=0);
return 0;
}
void open_employee_info() //function to open employee data file
{
string filename1 = "employee-details.dat"; //define which file to open
inFile1.open(filename1.c_str()); //open our payroll file
if(inFile1.fail()) //if our file open fails....
{
cout << "\nSorry the file was not opened successfully"<< "\n Please check that the file does exist or create it" << endl;
exit(1);
}
cout << "\n The file was opened successfully" << endl;
}
void open_payroll_info() //function to open payroll salary information file
{
string filename2 = "payroll-info.dat"; //define file name
inFile2.open(filename2.c_str());
if(inFile2.fail())
{
cout << "\nSorry the file was not opened successfully"<< "\n Please check that the file does exist or create it" << endl;
exit(1);
}
cout << "\n The file was opened successfully" << endl;
}
void payroll::addrec(void) //Record adding
{
char userinputadd = ' ';
cout << "\nPlease Enter the Employee number: ";
gets(rec.empnum);
cout << "\nPlease Enter the Employee's First Name: ";
gets(rec.empfirstname);
cout << "\nPlease Enter the Employee's Last Name: ";
gets(rec.emplastname);
cout << "\nPlease Enter the Employee's Date of Birth (mmddyyyy): ";
gets(rec.empdob);
cout << "\nPlease Enter the Employee's Social Insurance Number: ";
gets(rec.empsin);
cout << "\nPlease Enter the Employee's Phone Number: ";
gets(rec.empphone);
cout << "\nPlease Enter the Employee's Address: ";
gets(rec.empstreet);
cout << "\nPlease Enter the Employee's City: ";
gets(rec.empcity);
cout << "\nPlease Enter the Employee's Province: ";
gets(rec.empprovince);
cout << "\nPlease Enter the Employee's Country: ";
gets(rec.empcountry);
cout<<"\nPlease Enter the Employee's Status: ";
gets(rec.empstatus);
cout << "\nPlease Enter the Employee's Weekly Gross Salary: ";
cin >> rec.empsalarygross;
cout<<"Would you like to return to the main menu?(y), else the program will exit: ";
cin>>userinputadd;
if (userinputadd =='y' || userinputadd =='Y')
main();
else
exit();
}
void payroll::modrec(void) //Record Modification
{
system("CLS");
int empmodnum=0;
check = false;
char userinputmod = ' ';
cout<<"\nEnter the employee number for the record you would like to modify: ";
cin>>empmodnum;
cout<<"Would you like to return to the main menu?(y), else the program will exit: ";
cin>>userinputmod;
if (userinputmod =='y' || userinputmod =='Y')
main();
else
exit();
}
void payroll::viewrec(void) //Record viewing
{
system("CLS");
check = false;
char userinputview = ' ';
cout<<"Would you like to return to the main menu?(y), else the program will exit: ";
cin>>userinputview;
if (userinputview =='y' || userinputview =='Y')
main();
else
exit();
}
void payroll::exit(void)
{
inFile1.close();
inFile2.close();
check = true;
}
So on the front menu if you hit 1 to add a record you will see it skips the first cin statement being employee number.
Does anyone have an idea why this would occur?
You are leaving the newline character in your input stream after you press 1.
Consider all of the keys that you are typing. If you type "1" for addrec, then an employee ID of 987, then the name "John", your input stream looks like this:
1, \n, 9, 8, 7, \n, J, o, h, n, \n
You read the first character with cin >> ch. The next input statement you have is gets().
gets() reads, correctly, all of the characters up to the next newline. Since you still have the newline that follows '1', that first line will be read as blank.
Try adding this somewhere to your program:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You probably have a buffer issue so you need to flush stdin. Check google for details.