cin.get() getting too much - c++

I want a user to enter a char. I want to filter what they enter and take only the first char they type.
int main(){
while (true){
char n = readOption();
cout << n << std::endl;
}
return 0;
}
char readOption() {
char input = '\0';
while (input != '\n') {
input = cin.get();
if (isalpha(input)) {
break;
}
}
return toupper(input);
}
If I enter 13# jkjoi, the console prints.
J
K
J
O
I
I only want it to print J. Why is it printing the other letters as well?

It is printing all of the characters because (after you fix your semi-colon error) you loop forever:
while (true)
{
char n = readOption();
cout << n << std::endl;
}
This will call your read function over and over, forever! Your read function loops until he gets an alpha character, so it ignores "13# " and then grabs 1 character for each iteration of the while (true) loop. If you want it to stop after reading the first alpha character, don't loop:
char n = readOption();
cout << n << std::endl;
Updated
With your comment, you can actually re-write your code entirely:
std::locale loc;
char c = '\0';
do
{
// get a character with error checking
while (!(std::cin >> c))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
} while (!std::isalpha(c, loc));
// ignore the rest of the input
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Because you asked it to.
You perform this in a loop, forever.
If you only want to do it once, then simply do it once. Remove your loops.

Related

Why does cin.rdbuf()->sbumpc() ask me for input just one time in a loop?

This is an example of the c++ reference page of
std::basic_streambuf::sputbackc
and i am trying to find:
Why does " ch = pbuf->sbumpc() " ask me for input just one time in a loop and not in every cycle?
here is the code:
#include <iostream> // std::cin, std::cout, std::streambuf, std::streamsize
int main () {
char ch;
std::streambuf * pbuf = std::cin.rdbuf();
std::cout << "Please, enter some letters and then a number: ";
do {
ch = pbuf->sbumpc(); //why this line ask an input just once in all the loop?
if ( (ch>='0') && (ch <='9') )
{
pbuf->sputbackc (ch);
long n;
std::cin >> n;
std::cout << "You entered number " << n << '\n';
break;
}
} while ( ch != std::streambuf::traits_type::eof() );
return 0;
}
Lets say you enter LL10. pbuf->sbumpc(); reads one character from the stream. So it reads in L. Since that is not between 0 and 9 we loop again. L10 is still in the buffer so we read in L again. Again it it not in the range so we loop again. Now the buffer just has 10 in it. We read in the 1 and since it is in the range we put it back, read in the buffer using std::cin >> n; and then break out of the loop. That is why you only have to enter input once. Had you only inputted LL it would wait for you to enter more.

C++ - cin to only take one integer

This code works fine if I enter something that isn't a number in, e.g. F: it will print the error message. However, if I enter e.g. 2F2 or , it will take the 2 and pass the check, continue in my code and on the next cin >> statement it will put the F in, and then it loops back and puts the 2 in.
How do I make it so it only accepts a single number e.g. 2 and not e.g. 2F2 or 2.2?
int bet = 0;
// User input for bet
cout << " Place your bet: ";
cin >> bet;
cout <<
// Check if the bet is a number
if (!cin.good())
{
cin.clear();
cin.ignore();
cout << endl << "Please enter a valid number" << endl;
return;
}
bool Checknum(std::string line) {
bool isnum = true;
int decimalpoint = 0;
for (unsigned int i = 0; i < line.length(); ++i) {
if (isdigit(line[i]) == false) {
if (line[i] == '.') {
++decimalpoint; // Checks if the input has a decimal point that is causing the error.
}
else {
isnum = false;
break;
}
}
}
if (decimalpoint > 1) // If it has more than one decimal point.
isnum = false;
return isnum;
}
If you take a string from the user, this should work. You can convert the string to an integer or a float(stoi or stof, respectively). It may not be the best solution there is, but this is what I have. Excuse the indentation.
Do getline to read one whole line of input from cin.
Create a stringstream to parse the string you got.
In this parser, read the number; if it fails - error
Read whitespace; if it doesn't arrive to the end of string - error
#include <sstream>
...
int bet = 0;
std::cout << " Place your bet: ";
while (true)
{
std::string temp_str;
std::getline(cin, temp_str);
std::stringstream parser(temp_str);
if (parser >> bet && (parser >> std::ws).eof())
break; // success
cout << endl << "Please enter a valid number" << endl;
}
This code keeps printing the error message until it receives valid input. Not sure this is exactly what you want, but it's pretty customary UI.
Here >> ws means "read all the whitespace". And eof ("end of file") means "end of the input string".

why while loop do not need user to input in c++

I'm learning c++ and reading c++ primer plus, but I don't understand why this code need two "cin >> ch". I know the first cin will read character that was user input.but then I delete first "cin >> ch" and run code ,the program have no error.So the fist cin is necessary? why the second cin needn't user to input?
#include <iostream>
int main()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters; enter # to quit:\n";
cin >> ch; //get a character
while (ch != '#')
{
cout << ch;
++count;
cin >> ch; // get the next character
}
cout << endl << count << " characters read\n";
return 0;
}
You can evaluate your input right inside condition of while loop.
#include <iostream>
int main()
{
char ch;
int count = 0;
std::cout << "Enter characters; enter # to quit:\n";
while (std::cin >> ch && ch != '#')
{
std::cout << "entered: " << ch << std::endl;
++count;
}
std::cout << std::endl << count << " characters read" << std::endl;
return 0;
}
When while condition is entered it will wait for you to enter anything first. Once input is received it will check if the input is not #. If input is not # the loop is entered, input printed out, counter increased, and back to waiting for another input. If # is entered, condition becomes false, and loop is aborted.
If you remove the first cin then count will never be incremented. The user can enter # character before entering the loop and the program can never enter it therefore.
The first cin>>ch is obviously used to take input from user but you
have again accepting data in while loop using the same variable name "ch" ,
So when you run the program it will not give u error but accept only first value that you have accept before the while loop not in while loop.
In while loop you can assign new value to variable "ch" but not accept the new value again.

infinite loop due to buffer value -1?

I'm writing this program for class. It's supposed to take in a word 10 or less chars in size and change each char individually to uppercase using a toupper() call. The requirements of the assignment are to use toupper() on each individual char in an array that holds the word and the '\n'. Here is my code:
int main(int argc, char *argv[])
{
char again = ' ';
char word[11];
for(int count=0; count<11; count++){
word[count] = ' ';
}
while(true){
for(int clear=0; clear < 11; clear++){
word[clear] = ' ';
}
system("CLS");
cout << "Please provide a lowercase word!" << endl;
cin.getline(word, 11);
for(int letter = 0; letter < 11; letter++){
system("CLS");
if(letter < 10){
word[letter] = toupper(word[letter]);
}
for(int printw = 0; printw < 11; printw++){
cout << word[printw];
}
Sleep(200);
}
cout << endl;
while(true){
cout << "Would you like to Repeat or Quit? (R/Q)" << endl;
cin.get(again);
cin.get();
tolower(again);
if(again == 'r' || again == 'q'){
break;
}
else{
cout << "That was an invalide input!" << endl;
}
}
if(again == 'q'){
break;
}
}
system("PAUSE");
return EXIT_SUCCESS;
}
The program works just fine for 1 - 10 char words, but if the user decides to enter a string larger than 10 chars, the program will uppercase the first 10 and then hit an infinite loop when it asks if the user would like to try again. When that happens it will continue to return "That was an invalid output!" and the next prompt to repeat or quit on the next line. It will not wait for input, and I've tried clearing the buffer with cin.ignore().
I tried checking the values in the buffer with several cout << cin.get() << endl; line and they all come back with the ascii value of -1. I assume this means it is throwing a failbit exception, but I'm not actually sure.
Instead of using a character array of fixed size, you should use a string to store your input. You can use getline to read a line from cin like this:
string input;
...
getline(cin, input);
This will read the entire line, regardless of how long it is or how many characters you actually process.
What you're seeing here is the expected behaviour of cin.getline(char* s, streamsize n) From C++ ref for istream::getline:
The failbit flag is set if the function extracts no characters, or if
the delimiting character is not found once (n-1) characters have
already been written to s.
If a user types a word longer than 10 chars, then cin writes the first 10 chars to word and sets its internal flag to fail as no delimiter \n (newline) has been seen.
If you want to stick to your current solution, you could overcome this with:
const int SIZE = 11;
...
cin.getline(word, SIZE);
if (cin.fail() && cin.gcount() == SIZE-1) { // failed because user entered a word longer than 10 chars
word[SIZE-1] = '\0'; // make sure to null terminate
cin.clear(); // clear the failure from cin
cin.ignore(256, '\n'); // ignore the leftover input from cin until next newline
}
You need to both clear the failbit and ignore the leftover input. 256 is simply a number large enough, to be super safe you can use cin.ignore(numeric_limits<streamsize>::max(), '\n'); (don't forget to #include <limits>)
PS You might be better off reading a char at a time with cin.get(char& c) though.

Using C isdigit for error checking

While using the boolean check for the int num this loop doesn't work. The lines after it go unrecognized. Enter and integer like 60 and it just closes. Did I use isdigit wrong?
int main()
{
int num;
int loop = -1;
while (loop ==-1)
{
cin >> num;
int ctemp = (num-32) * 5 / 9;
int ftemp = num*9/5 + 32;
if (!isdigit(num)) {
exit(0); // if user enters decimals or letters program closes
}
cout << num << "°F = " << ctemp << "°C" << endl;
cout << num << "°C = " << ftemp << "°F" << endl;
if (num == 1) {
cout << "this is a seperate condition";
} else {
continue; //must not end loop
}
loop = -1;
}
return 0;
}
When you call isdigit(num), the num must have the ASCII value of a character (0..255 or EOF).
If it's defined as int num then cin >> num will put the integer value of the number in it, not the ASCII value of the letter.
For example:
int num;
char c;
cin >> num; // input is "0"
cin >> c; // input is "0"
then isdigit(num) is false (because at place 0 of ASCII is not a digit), but isdigit(c) is true (because at place 30 of ASCII there's a digit '0').
isdigit only checks if the specified character is a digit. One character, not two, and not an integer, as num appears to be defined as. You should remove that check entirely since cin already handles the validation for you.
http://www.cplusplus.com/reference/clibrary/cctype/isdigit/
If you're trying to protect yourself from invalid input (outside a range, non-numbers, etc), there are several gotchas to worry about:
// user types "foo" and then "bar" when prompted for input
int num;
std::cin >> num; // nothing is extracted from cin, because "foo" is not a number
std::string str;
std::cint >> str; // extracts "foo" -- not "bar", (the previous extraction failed)
More detail here:
Ignore user input outside of what's to be chosen from