Strange behaviour on a std::getline

Hi all! I would like to show you my script because there something strange about the "bool Ripetere() " function.

The program seems to ignore the “std::getline” inside of that function, and if you try to type something, it will just close itself.

I’ve manage to do it the first time during the BullCowGame, but I can’t replicate it, and I don’t know why. Can someone help me? thank you very much!

#include <iostream>
#include <string>

int number;
int multiplier;

int InserisciNumero();
int MoltiplicaPer();
int Risultato();
bool Ripetere();

void main()
{
	bool bRisposta = false;	
	do 
	{
		InserisciNumero();
		MoltiplicaPer();
		Risultato();
		bRisposta = Ripetere();
	} 	
	while (bRisposta);

	std::cout << std::endl;

	return;
}

int InserisciNumero()
{
	std::cout << "Inserisci un numero intero: ";
	std::cin >> number;

	return 0;
}

int MoltiplicaPer() 
{
	std::cout << "Per quale valore intero vuoi moltiplicarlo? Inserisci un numero: ";
	std::cin >> multiplier;

	return 0;
}

int Risultato() 
{
	std::cout << number << " * " << multiplier << " = " << number * multiplier << std::endl;
	std::cout << std::endl;

	return 0;
}

bool Ripetere() 
{
	std::cout << "Vuoi fare un altro calcolo? (y/n)" << std::endl;
	std::string Response = "";
	std::getline(std::cin, Response);

	return (Response[0] == 'y') || (Response[0] == 'Y');
}
1 Like

@sampattuzzi can you shed any light on this.

Firstly you should be using int main not void main. See here for reasons.

Your problem stems from you using std::cin >> number. When you enter a number, say 1 and then press enter, the input buffer will be “1\n”, the 1 will go into number and then you will be left with “\n” in the buffer which would be used the next time you use std::cin (in std::getline), to solve this you will have to throw away the buffer, or you could use std::getlline and use std::stoi to get that as an int. Solution for the first would be

std::cin >> number;
//clear error flags
std::cin.clear();
//reads max streamsize upto and including a newline and discards it
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
2 Likes

Thanks @DanM

1 Like

Thank you all for you help!

So, if I get the logic behind it, std::cin >> number collect ALL the inputs I give it, including the “Enter” button, that is trasnlated in a “\n”. So if I digit for example 5 and then Enter, the system will read it like “5\n”. When I ask to insert again another number to multiply the first, the “\n” from the “5\n” is returned and given to the second std::cin, but is ignored because std::cin won’t accept “\n” as an input alone, so everything work fine. I then input, for example, 6 and then press Enter, so, again, is a “6\n”. The third time I won’t have a std::cin, but ai std::getline, that will accept the last “\n” as an input e automaticly end the program because \n != (y or Y). We can then solve the problem with your script put inside “int MoltiplicaPer()” so that we can ignore the last “\n” OR I can use another std::cin and then return the input inside “std::string Response” because std::cin automaticly ignore the last “\n”.

Maybe my reasoning was a little bit intricated, I’m sorry, I’m not very experienced, but I hope I got the meaning of your script and how std::cin work. Can you explain to me what every line of yout script exactly do, if you don’t mind? Thank you again!

Close, you are correct at the first part because std::cin >> will ignore the first whitespace character when reading input so using std::cin >> the next time is fine since the newline is ignored.

The actual problem isn’t that “\n != (y or Y)”. It’s that std::getline reads up to and including a newline and then discards the newline, so in actuality your string is empty.

I’m not sure how to describe it in more detail than what the comments provide.

//clear error flags
std::cin.clear();

This clears the error state flags (eofbit, failbit and badbit)

//reads max streamsize upto and including a newline and discards it
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

std::numeric_limits<std::streamsize>::max() would just be whatever the maximum possible size a stream (like iostream) can be. So it would just be like std::cin.ignore(9223372036854775807, '\n');, since apparently that’s what that number is.

And whilst I was making sure everything I’m saying is correct, I learned that you can use std::ws to discard leading whitespace. So you could just do

std::cin >> number >> std::ws;

and whereever else you use std::cin >> and you shouldn’t have a problem reading with std::getline

1 Like

Thank you very much, you where amazing! That was a nasty sneaky issue for a newbie like me. Now it’s far more clear for me and we managed to solve the problem! Thank you again!

Privacy & Terms