Its been a while since i have coded c++ and i have forgot an annoying thing that happens when you gather string input. Basically if this loops back through, say if you use negative numbers then it skips the cin from the employee name line the second go round. I remember having this issue before and having to clear or do something of that sort before or after the string is input. Please help!
PS Also for extra help can anyone help me with a correct loop below. How can i check for a value in the string input to make sure they input a value?
#include <string>
#include <iostream>
#include "employee.h"
using namespace std;
int main(){
string name;
int number;
int hiredate;
do{
cout << "Please enter employee name: ";
getline(cin, name);
cout << "Please enter employee number: ";
cin >> number;
cout << "Please enter hire date: ";
cin >> hiredate;
}while( number <= 0 && hiredate <= 0 && name != "");
cout << name << "\n";
cout << number << "\n";
cout << hiredate << "\n";
system("pause");
return 0;
}
You want to change your loop condition to be whether or not any of the below are not set. The logical AND will only trigger if all three are unset.
do {
...
} while( number <= 0 || hiredate <= 0 || name == "");
Next, use cin.ignore() as prescribed by #vidit to get rid of issues with reading in newline characters.
Lastly, and importantly, your program will run an infinite loop if one enters an alphabetic character for an integer instead of...an integer. To mitigate that, use isdigit(ch) from the <cctype> library.
cout << "Please enter employee number: ";
cin >> number;
if(!isdigit(number)) {
break; // Or handle this issue another way. This gets out of the loop entirely.
}
cin.ignore();
cin leaves a newline character(\n) in the stream, which causes the next cin to consume it. There are many ways of getting around that. This is one way.. using ignore()
cout << "Please enter employee name: ";
getline(cin, name);
cout << "Please enter employee number: ";
cin >> number;
cin.ignore(); //Ignores a newline character
cout << "Please enter hire date: ";
cin >> hiredate;
cin.ignore() //Ignores a newline character
Related
I have just started learning C++ and trying to learn the syntax.
#include <iostream>
#include <limits>
using namespace std;
int main(){
bool answer;
cout << "Did you enjoy testing this program? (1 for yes, 0 for no) ";
cin >> answer;
while (!(cin >> answer)) {
cout << "Invalid value!\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Please type either 0 or 1: ";
cin >> answer;
}
cout << "Your feedback has been registered. Feedback: " << answer;
}
The aim is to keep making the user ask over and over until they input either 0 or 1. The code snippet just makes things freeze when either of those values is given. How should this be fixed?
The cin >> answer; statement above the loop, and the cin >> answer; statement at the end of the loop body, both need to be removed.
You are prompting the user to enter a value, then you read in that value and ignore it, and then you wait for the user to enter in another value, even though you didn't prompt the user to enter more than 1 value.
If they do happen to enter a 2nd value, and it fails, your loop will then prompt the user to enter in a new value, then you read in that value and ignore it, and then you wait for the user to enter yet another value without prompting the user to do so.
You should be invoking cin >> answer only 1 time per loop iteration, eg:
#include <iostream>
#include <limits>
using namespace std;
int main(){
bool answer;
cout << "Did you enjoy testing this program? (1 for yes, 0 for no) ";
// cin >> answer; // <- remove this!
while (!(cin >> answer)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid value!\n";
cout << "Please type either 0 or 1: ";
// cin >> answer; // <- remove this!
}
cout << "Your feedback has been registered. Feedback: " << answer;
}
Trying to check if cin obtained valid input (eg - no string or char in int variable), but the while loop gets stuck at an infinite loop and doesn't even wait for user input
#include <iostream>
#include <string>
using namespace std;
int main(){
cout << "How many would you like to buy ? ";
int buyAmt;
cin >> buyAmt;
while (!cin) {
cin.clear();
cin >> buyAmt;
cout << "Sorry, you must enter an integer" << endl << endl;
}
}
Expected result:
How many would you like to buy ? fdssd
Sorry, you must enter an integer (asks for usr input here)
Actual result:
How many would you like to buy ? fdssd
Sorry, you must enter an integer
Sorry, you must enter an integer
Sorry, you must enter an integer
Sorry, you must enter an integer
Sorry, you must enter an integer
Sorry, you must enter an integer
After applying cin.clear(); you need to consume the wrong input first, before applying cin >> buyAmt; again.
Something like
while (!cin) {
std::string dummy;
cin.clear();
cin >> dummy;
cout << "Sorry, you must enter an integer" << endl << endl;
cout << "How many would you like to buy ? ";
cin >> buyAmt;
}
I have a switch in which one case asks the user for several inputs to use for constructing a class object. One of these inputs should be in the form of a number. If a number is not entered it breaks the switch and ends up terminating the program. I want to set up a while(){} condition so that if a non integer is entered it will prompt the user to enter an integer and then continue on with the program.
int main(){
int in_yob, ranking;
string in_first_name, in_last_name, in_genre, in_fact, last_name, in_composer;
char selection, choice;
do {
DisplayMenu();
cin >> selection;
cout << endl;
while (!cin || selection < 48 || selection > 53){
cin.clear();
cout << "Please make a valid selection" << endl;
DisplayMenu();
cin >> selection;
}
switch (selection) {
case 49 : {
cout << "First Name: ";
cin >> in_first_name;
cout << "Last Name: ";
cin >> in_last_name;
cout << "Genre: ";
cin >> in_genre;
cout << "Year of Birth: ";
cin >> in_yob;
cout << "Fact: ";
cin >> in_fact;
last_name = in_last_name;
transform(last_name.begin(), last_name.end(), last_name.begin(), ::tolower);
Composer& last_name = myDB.AddComposer(in_first_name, in_last_name,
in_genre, in_yob, in_fact);
cin.clear();
} break;
...
default:
cout << "Please make a valid selection" << endl;
}
} while (selection != 48);
}
I have tried inserting a while loop after cin >> in_yob; as:
while(!cin || in_yob > 1){
cin.clear();
cout << "Enter a positive enter for year of birth: ";
cin >> in_yob;
}
but the result is an infinite loop of "Enter a positive enter for year of birth: ". I know this construct for error checking works outside of a switch case so what is the reason that within a switch case i'm getting this result? Also how would you go about fixing this so that I can check for and prevent an input error? Thanks.
[To explain my self with more space and better formatting better than in a comment I post this as an answer instead as of a comment.]
When you enter input, like for example
1
the input buffer actually contains two characters, firs the digit '1' and then the newline '\n'.
When you read a single character, the input operation extracts the first character, the digit, and writes it to your variable.
If you then read another character, it will read the newline, and not whatever comes after.
There is a trick to "ignore" characters until, for example, a newline, and that is done by using the std::istream::ignore, and if you follow the link to the reference you will see a very good example on how to ignore anything up to and including the newline.
So in your case it's not enough to just call clear you need to call ignore as well in your input validation loop. And if you continue to read single characters, you need to call ignore before that as well.
You needed to clear the input stream.
#include <iostream>
#include <string>
int in_yob = 0;
int main()
{
while(std::cin.good() && in_yob < 1){
std::cin.clear();
std::cout << "Enter a positive enter for year of birth: ";
if( !(std::cin >> in_yob) ) {
std::cin.clear();
std::cin.ignore(10000,'\n');
}
}
std::cout << "YOB " << in_yob << std::endl;
}
Case 3 is an option to add a book to the structure. As long as books with titles without spaces are added, they are ok, whenever I try to put a name that has a space in it, the compiler goes crazy, sorta like what it would do if you execute an infinite loop. Why and what is the solution?
struct bookStruct
{
string bookTitle;
int bookPageN;
int bookReview;
float bookPrice;
};
const int MAX_BOOKS=10;
case 3:
{
for(int i=0;i<MAX_BOOKS;i++)
{
if(books[i].bookTitle=="\0")
{
cout << "\nPlease Enter the Title: ";
cin >> books[i].bookTitle ;
cout << "\nPlease Enter Total Number of Pages: ";
cin >> books[i].bookPageN ;
cout << "\nPlease Enter Rating (stars): ";
cin >> books[i].bookReview ;
cout << "\nPlease Enter Price: ";
cin >> books[i].bookPrice;
cout << "\n\nBook Added.\n\n";
break;
}
}break;
}
The input operator >> stops at space when reading strings.
What you want to use is std::getline.
cout << "\nPlease Enter the Title: ";
std::getline(std::cin, books[i].bookTitle);
The input operator >> when reading a number will also stop at a space or newline (leaving them on the input stream). Thus when you wrap around to the next book there is still a '\n' character on the input stream. So for numbers you also need to use std::getline(). But in this case you need to convert the value to an integer.
cout << "\nPlease Enter Total Number of Pages: ";
std::string line;
std::getline(std::cin, line);
std::stringstream linestream(line);
linestream >> books[i].bookPageN ;
int x=0;
string fullname = "";
float salary;
float payincrease;
float newsal;
float monthlysal;
float retroactive;
while(x<3){
cout << "\n What is your full name?";
cin >> fullname;
cout << "\n What is your current salary? \t";
cin >> salary;
cout << "\n What is your pay increase? \t";
cin >> payincrease;
newsal = (salary*payincrease)+salary;
monthlysal = newsal/12.00;
retroactive = (monthlysal*6)-(salary/2);
cout << "\n" << fullname << "'s SALARY INFORMATION";
cout << "\n New Salary \t Monthly Salary \t Retroactive Pay";
cout << "\n \t" << newsal << "\t" << monthlysal << "\t" << retroactive;
x++;
}
My loop doesn't seem to stop for every time cin is asked, and instead instantly executes the loop 3 times on its own. How do I get it to stop when input is asked?
If the input stream isn't empty when you call cin, then cin uses the data already in the buffer instead of waiting for more from the user. You're using the extraction operator, so when cin is sending values to your variables, it skips leading whitespace in the buffer and stops on the next whitespace.
Put a breakpoint on this line:
cout << "\n What is your current salary? \t";
Run the program, and enter Bob Smith. When you hit the break point, hover your cursor over your string fullname. You'll see it stores only "Bob" not "Bob Smith". "Bob Smith" got put into the buffer, but when you use cin with the extraction operator, it skips any leading whitespace, puts the next value it finds into your variable, then stops on the next whitespace. To demonstrate this, try running this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1,str2;
cin >> str1;
cin >> str2;
cout << str1 << " " << str2 << "\n\n";
return 0;
}
If you type in "Bob Smith", it will take your input only one time, even though you call cin twice. However, you'll see that both "Bob" and "Smith" got captured in the strings str1 and str2.
Therefore, you can conclude that cin stops populating your string fullname when it gets to the space between Bob and Smith. On your next call to cin, the buffer still contains "Smith", so instead of taking more input from the user, it attempts to fill your variable salary with "Smith". Obviously this isn't want you want to do. You can call flush and ignore on cin to wipe out the buffer before every time you use cin, or instead you could fix your logic and use getline to take in the full name, including spaces.
To fix your problem, all you need to do is use getline instead of cin >>, so replace this line:
cin >> fullname;
with this:
getline(cin,fullname,'\n');
Secondly, you're using a while loop to execute a set of actions a specific number of times. That's typically something you'd use a for loop for.
As an aside, you could also write tiny input validation loops that can help you debug or otherwise avoid attempting to put invalid input into your variables (such as "Smith" into a float). Something like this could work:
for(;;)
{
if(cin >> salary)
break;
cin.clear();
cin.ignore(INT_MAX,'\n');
}
Note that cin returns a value, so you can use it in an if statement. If it gets valid input, it will return true. If not, it will return false. To make it more explicit, you could also just use a normal call to cin without the if statement, and then check if cin.good(), which amounts to basically the same net effect. If you're not using Visual Studio and get an error about INT_MAX, you might need to #include limits.h to resolve it.
That occurs if you input a char where an int is expected.
Use cin.clear(); and cin.ignore(numeric_limits<streamsize>::max(), '\n'); to limit an input to int's only.
Other than that, it won't skip if the correct data type is put in.
#include <string>
#include <iostream>
#include <limits>
using namespace std ;
int main(void)
{
int x=0;
string fullname = "";
float salary;
float payincrease;
float newsal;
float monthlysal;
float retroactive;
while(x<3)
{
cout << "\n What is your full name?";
cin >> fullname;
cin.ignore( 1000, '\n' );
cout << "\n What is your current salary? \t";
cin >> salary;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "\n What is your pay increase? \t";
cin >> payincrease;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
newsal = (salary*payincrease)+salary;
monthlysal = newsal/12.00;
retroactive = (monthlysal*6)-(salary/2);
cout << "\n" << fullname << "'s SALARY INFORMATION";
cout << "\n New Salary \t Monthly Salary \t Retroactive Pay";
cout << "\n \t" << newsal << "\t" << monthlysal << "\t" << retroactive;
x++;
}
cout<<" \nPress any key to continue\n";
cin.ignore();
cin.get();
return 0;
}
Check your variable types, I noticed mine accepting a digit instead of a character, had the same problem (not stopping, loop just kept going on).
> std::cin >> this->controls.button
> DETOX_NUMBER button; // (int)
Change to:
> char button;