I'm having an issue using cin.ignore(), if I use it after a cin >> statement it doesn't seem to work and ends the program instead.
Here's my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int number ;
int main () {
cin >> number;
cout << number;
cin.ignore()
return 0;
}
I am typing " 4 " (without quotes) at the prompt. I'm expecting it to prompt for an int (which it does) and then display that int until the user presses enter again. However as soon as I press enter on the first prompt the program closes. If I replace the cin.ignore() with a new cin >> then it waits until I enter data at that prompt before closing, however this way I have to put data into the prompt, I can't just press enter to close it.
I read about putting cin.clear() after the cin input but that didn't help. If I replace cin.ignore() with cin >> num2; then it works fine.
What am I doing wrong?
You can reset your input stream and ignore the rest of it if for example your user did not enter a valid int type as input. The while loop will not exit until number contains an actual integer. After that, if you want the program to wait until the user presses "Enter" or any other key, you can just call ignore again.
#include <limits>
#include <iostream>
int main()
{
int number;
// we need to enforce that the input can be stored as `int` type
while(!(std::cin >> number))
{
std::cout << "Invalid value! Please enter a number." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cout << "Your number is: " << number << std::endl;
// wait for user to press Enter before exiting
// you can do this with ignore() x2 once for the newline
// and then again for more user input
std::cout << "Press Enter to exit." << std::endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
return 0;
}
Related
I'm new to C++ programming, and I've come upon a roadblock. Here's my code:
#include <iostream>
using namespace std;
int main(){
int sum = 0, a;
cout << "enter first set of numbers:";
while(cin >> a) sum += a;
cout << "first sum = " << sum;
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n');
sum = 0;
cout << "enter second set of numbers:";
while(cin >> a) sum += a;
cout << "second sum = " << sum;
}
I'm trying to sum two sets of numbers that I input at the command line. The problem is that when I hit ctrl-d to terminate my first set of numbers, it skips the second set of cin's. Most of the pages I find elsewhere on the internet tell me to use cin.clear and cin.ignore. I've tried that and it still doesn't work. This page question concerning cin.clear() even seems to have the same problems. However, the fixes they suggest don't work for me.
Does this code above work for anyone else?
When you use Ctrl-D you terminate the input stream: there is no further character coming from std::cin. Even clearing the stream doesn't help: you have told the stream it is at its end. You can't reopen it. However, clear()ing the stream and using ignore() is the solution to your problem!
You need a different indicator that one set of values is done. The easiest is to use a non-digit character or string: trying to read something which isn't an int will cause the stream to go into failure mode [without closing the stream]. That is, you read until the conversion fails, clear() the stream, and ignore() everything up to the end of the line.
Your code should already do that: instead of using Ctrl-D just enter, e.g., x.
//Use stringstream ^^ for multiple user input
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main (void)
{
string mystr;
float price = 0;
int quantity = 0;
cout << "Enter price: ";
getline (cin, mystr);
stringstream(mystr) >> price;
cout << "Enter quantity:";
getline (cin, mystr);
stringstream(mystr) >> quantity;
cout << "Total price: " << price*quantity << endl;
return 0;
}
You can use Ctrl-D, you just need to have your loop in another thread. So Ctrl-D, kills the thread, then returns to your main function, then you can start another thread.
It'd not the best solution, but it can work, http://codebase.eu/tutorial/posix-threads-c/
Please, is there a way I can wait for a single ENTER key press in all of the below cases? It works fine except when the std::getline() is used, which consumes the \n, and the ENTER needs to be pressed twice.
The code below works fine:
#include <iostream>
#include <limits>
using std::cout;
using std::cin;
using std::string;
void waitForENTERKeyPress();
int main ()
{
char c;
string s;
cout << "Enter c:"; cin >> c;
waitForENTERKeyPress();
cout << "Enter c:"; c = cin.get();
waitForENTERKeyPress();
cout << "Enter s:"; cin >> s;
waitForENTERKeyPress();
cout << "Enter s:"; std::getline(cin, s);
waitForENTERKeyPress();
return 0;
}
void waitForENTERKeyPress()
{
// Does not work with std::getline(...)
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Press an ENTER to continue...\n";
cin.get();
}
====[UPDATE]============================================
Let me rephrase what I am looking for: The way how to make the waitForENTERKeyPress() function working in both cases – with \n in the buffer, when cin operator >> or cin.get() is used and also in cases the std::getline() is used.
From what I understand it is not possible as there is not a way how to detect if the \n is still in the buffer or not.
I have tried to use cin.rdbuf()->in_avail(), but it always returns 0.
I am creating a simple login program.
#include <iostream>
#include <string>
using namespace std;
void showRegister()
{
string user;
string pw;
cout << "Enter your username:";
getline(cin, user);
cout << "Enter your password:";
getline(cin, pw);
cout << "You have successfully registered!" << endl;
writeIntoFile(user, pw);
showMenu();
}
void showMenu() {
int select;
do {
cout << "1. Register"<<endl;
cout << "2. Login" << endl;
cout << "3. Exit" << endl;
cout << "Enter your choice: ";
cin >> select;
} while (select > 3);
switch (select)
{
case 1:
showRegister();
break;
case 2:
showLogin();
break;
case 3:
default:
break;
}
}
int main()
{
showMenu();
return 0;
}
This is the result when I choose 1:
As you see, I can not enter username. In function showRegister(), when I add cin.ignore() before getline(cin, user), this is the result:
As I understand, getline() reads a line until it reaches character \n and skip the rest. So why in this case, two successive getline() commands (getline(cin, user) and getline(cin, pw) lead to the fact that I can not enter username?
The fact is getline takes input from buffer if something exists in buffer else it ask the user for value. What actually happens in your code is as soon as you enter value for select which is not greater than 3 it comes out of the loop after with a value you entered for select and the entered (which stands for \n) that you pressed get stored in buffer. So know when you come to getline for user it sees '\n' from the buffer as getline first check in buffer, so it skip the value insertion and buffer gets emptied and now when you come to getline that is used for password it ask the user for password as buffer was empty.
This will happen always after an switch from a formatted input to an unformatted input. Like from std::cin >> select to std::getline
The formatted input will read your integer "select", but not the following CR LF. (You pressed the enter key).
To solve that problem, you can simply write:
getline(cin >> std::ws, user);
std::ws will first consume the leading white space. Then the std::getline will work as expected.
Please read here about std::ws and do not forget to include <iomanip>
There are more severe bugs in your code. Like a cicrular call to "showMenu"
Based on this answer, I've written the following code
#include <iostream>
#include <vector>
#include <cstddef>
#include <limits>
int main()
{
std::cout << "Enter x and y size, followed by enter: ";
std::size_t nrOfRows, nrOfCols;
std::cin >> nrOfRows >> nrOfCols;
// initialize dynamic array of arrays
std::vector<std::vector<char>> data(nrOfRows,
std::vector<char>(nrOfCols, 'O'));
// print array
for (std::size_t rowNr = 0; rowNr < nrOfRows; rowNr++)
{
std::cout << "Row " << rowNr << ": ";
for (const auto& el : data[rowNr])
std::cout << el << " ";
std::cout << std::endl;
}
std::cout << "Press enter to continue: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Compiled with VC++ 14.1 or Visual studio 2017 v15.7.4.
After the first prompt I enter e.g. "3 5" and enter. Then the program just rolls through and exits. E.g. it outputs the strings and does not wait for the final user input (enter) at std::cin.ignore().
What did I miss?
edit
For the down-voters/nay sayers. This code does work as described.
#include <iostream>
#include <limits>
int main()
{
std::cout << "Press enter to continue: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Your problem is that the extraction operation (std::cin >> nrOfRows >> nrOfCols;) will leave delimiting whitespace in the stream, unlike getline(), which will consume the delimiter. This normally isn't a problem because the >> operator will also ignore leading whitespace, but the line break left in the stream will cause std::istream::ignore() to not wait for input.
To fix this, add a call to std::istream::ignore() to discard any whitespace before you output the Press enter to continue: message.
enter code here
int main()
{
std::string input;
std::cin >> input;
while (input != "quit")
{
// do stuff
std::cin >> input; // get another input
}
return EXIT_SUCCESS; // if we get here the input was quit
The problem is, it isn't prompting the user to enter words at all. If I enter "quit", it ends, so that's working fine. Otherwise, if I enter in anything else, then enter quit, it just quits as well. What should I do to rectify that?
Through my research, I was able to find a similar program here which uses case, but that seems a bit tedious to me. I have been instructed to use the isalpha function, which accepts a single character as a parameter and returns a Boolean indicator as to whether or not the character is a letter.
Try this small illustrative program:
#include <iostream>
#include <cstdlib>
int main(void)
{
std::cout << "This is a prompt, enter some text:\n";
std::string the_text;
std::getline(std::cout, the_text); // Input the text.
std::cout << "\n"
<< "The text you entered:\n";
std::cout << the_text;
std::cout << "\n";
// Pause the program, if necessary.
std::cout << "\n\nPaused. Press Enter to continue...\n";
std::cin.ignore(10000000, '\n');
// Return status to the Operating System
return EXIT_SUCCESS;
}
As you can see, outputting an instructional phrase before an input is known as prompting the User.
Edit 1: Prompting in a while loop
In your case, you need to prompt the user before the input:
while (input != "quit")
{
// Do stuff
std::cout << "Enter text or \"quit\" to quit: ";
std::cout.flush(); // Flush buffers to get the text on the screen.
std::cin >> input;
}