Alternative to system("Pause"); revisited - c++

I know this question has been asked a million times, but I have a coding question with it, because a couple of alternatives seem not to work with this code, and I'm not sure why. If you look right before the return 0;, I'm trying cin.get() and it doesn't stop the program, and neither does my PressEnterToContinue() function that I found somewhere that worked on other programs. The only thing I've gotten to work with this is system pause, which I don't want to use, since I will also be using this cross platform. Any ideas?
#include <iostream>
using namespace std;
void PressEnterToContinue()
{
std::cout << "Press ENTER to continue... " << std::flush;
std::cin.ignore(std::numeric_limits <std::streamsize> ::max(), '\n');
}
int main(void)
{
int pause;
double distance, x1, y1, x2, y2, x, y;
cout << "This program outputs the distance between two points on a plane!" << endl;
cout << "Please input point X1" << endl;
cin >> x1;
cout << "Please input point Y1" << endl;
cin >> y1;
cout << "Please input point X2" << endl;
cin >> x2;
cout << "Please input point Y2" << endl;
cin >> y2;
x = x2 - x1;
y = y2 - y1;
distance = sqrt(x*x + y*y);
cout << distance << endl;
//cin.get();
//PressEnterToContinue();
//system("Pause");
return 0;
}
Feel free to mention methods of stopping the system that I don't have here. Thanks,

It's because your last input (cin >> y2) leaves the newline in the input buffer. This is then read by your calls to cin.get() or PressEnterToContinue().
In the PressEnterToContinue function you might want to "peek" at the input buffer to see if there is any characters first, and if there is then do an extra cin.ignore.
When you do e.g.
cin >> y2;
And you enter the input
123\n
Then the input buffer will contain the string "123\n". After the input operator extracts the number (123) the input buffer will contain "\n", which is that the cin.get() call reads.

To solve this problem, you simply have to flush the buffer. The number 10000 in the example is just the number of characters to clear from the buffer.
cin.ignore(10000);
cin.get();
And to answer why cin >> y2 leaves a newline character in the buffer is because you entered a newline character by hitting the return key, and by retrieving the data from the console into your variable you leave the newline character behind.

Technical problem: characters (sometimes just a newline) left in the input buffer.
That said, there is never any need for the program stopping itself at the end, so a system( "pause" ) or whatever stopping action has no advantage, and some problems, including portability.
Run your program from the command line.
Or, since you're programming in Windows, use Visual Studio and run the program via Ctrl F5.
Or, place a breakpoint on the last right brace of main and run the program via a debugger, e.g. in visual studio by hitting F5.

Related

Infinite loop created when inputting "yy" into a char variable that should only take a single character such as 'y' or 'n', "nn" does not break code

The code in the cont function asks the user if they want to play my game again.
The code works when receiving proper character inputs such as 'y' or 'n' as well as their respective capital letter variants, and the else block works properly to loop the function if an invalid input such as 'a' or 'c' is entered.
However during a test run, an input of 'yy' breaks the code causing the program to infinitely loop, running not only this cont function but my game function as well.
choice is stored as a char variable. I am wondering why the code even continues to run upon inputting multi-character inputs such as 'yy' or 'yes'. What's interesting is 'nn', 'ny' and other variations of multi-character inputs that begin with 'n' causes no issues and properly results in the else if block running as intended. Which prints "Thanks for playing." then ends the program.
Can variables declared as char accept inputs greater than 1 character? Does it only take the first value? And if so why does 'yy' cause a loop rather than the program running as intended by accepting a value of 'y' or 'Y'? How can I change my program so that an input of 'yy' no longer causes issues, without specific lines targeting inputs such as 'yy' or 'yes'.
#include <iostream>
#include <string> // needed to use strings
#include <cstdlib> // needed to use random numbers
#include <ctime>
using namespace std;
// declaring functions
void cont();
void game();
void diceRoll();
// variable declaration
string playerName;
int balance; // stores player's balance
int bettingAmount; // amount being bet, input by player
int guess; // users input for guess
int dice; // stores the random number
char choice;
// main functions
int main()
{
srand(time(0)); // seeds the random number, generates random number
cout << "\n\t\t-=-=-= Dice Roll Game =-=-=-\n";
cout << "\n\nWhat's your name?\n";
getline(cin, playerName);
cout << "\nEnter your starting balance to play with : $";
cin >> balance;
game();
cont();
}
// function declaration
void cont()
{
cin >> choice;
if(choice == 'Y' || choice == 'y')
{
cout << "\n\n";
game();
}
else if (choice == 'N' || choice == 'n')
{
cout << "\n\nThanks for playing.";
}
else
{
cout << "\n\nInvalid input, please type 'y' or 'n'";
cont(); // calls itself (recursive function!!!)
}
}
void game()
{
do
{
cout << "\nYour current balance is $ " << balance << "\n";
cout << "Hey, " << playerName << ", enter amount to bet : $";
cin >> bettingAmount;
if(bettingAmount > balance)
cout << "\nBetting balance can't be more than current balance!\n" << "\nRe-enter bet\n";
} while(bettingAmount > balance);
// Get player's numbers
do
{
cout << "\nA dice will be rolled, guess the side facing up, any number between 1 and 6 : \n";
cin >> guess;
if(guess <= 0 || guess > 6 )
{
cout << "\nYour guess should be between 1 and 6\n" << "Re-enter guess:\n";
}
} while(guess <= 0 || guess > 6);
dice = rand() % 6+1;
diceRoll();
if (dice == guess)
{
cout << "\n\nYou guessed correctly! You won $" << (bettingAmount * 6);
balance = balance + (bettingAmount * 6);
}
else
{
cout << "\n\nYou guessed wrong. You lost $" << bettingAmount << "\n";
balance = balance - bettingAmount;
}
cout << "\n" << playerName << ", you now have a balance of $" << balance << "\n";
if (balance == 0)
{
cout << "You're out of money, game over";
}
cout << "\nDo you want to play again? type y or n : \n";
cont();
}
void diceRoll()
{
cout << "The winning number is " << dice << "\n";
}
Does it only take the first value?
Yes, the >> formatted extraction operator, when called for a single char value, will read the first non-whitespace character, and stop. Everything after it remains unread.
why does 'yy' cause a loop
Because the first "y" gets read, for the reasons explained above. The second "y" remains unread.
This is a very common mistake and a misconception about what >> does. It does not read an entire line of typed input. It only reads a single value after skipping any whitespace that precedes it.
Your program stops until an entire line of input gets typed, followed by Enter, but that's not what >> reads. It only reads what it's asked to read, and everything else that gets typed in remains unread.
So the program continues to execute, until it reaches this part:
cin >> bettingAmount;
At this point the next unread character in the input is y. The >> formatted extraction operator, for an int value like this bettingAmount, requires numerical input (following optional whitespace). But the next character is not numerical. It's the character y.
This results in the formatted >> extraction operator failing. Nothing gets read into bettingAmount. It remains completely unaltered by the >> operator. Because it is declared in global scope it was zero-initialized. So it remains 0.
In addition to the >> extraction operator failing, as part of it failing it sets the input stream to a failed state. When an input stream is in a failed state all subsequent input operation automatically fail without doing anything. And that's why your program ends up in an infinite loop.
Although there is a way to clear the input stream from its failed state this is a clumsy approach. The clean solution is to fix the code that reads input.
If your intent is to stop the program and enter something followed by Enter then that's what std::getline is for. The shown program uses it to read some of its initial input.
The path of least resistance is to simply use std::getline to read all input. Instead of using >> to read a single character use std::getline to read the next line of typed in input, into a std::string, then check the the string's first character and see what it is. Problem solved.
cin >> bettingAmount;
And you want to do the same thing here. Otherwise you'll just run into the same problem: mistyped input will result in a failed input operation, and a major headache.
Why do you need this headache? Just use std::getline to read text into a std::string, construct a std::istringstream from it, then use >> on the std::istringstream, and check its return value to determine whether it failed, or not. That's a simple way to check for invalid input, and if something other than numeric input was typed in here, you have complete freedom on how to handle bad typed in input.

Using consecutive while(cin >> input) successfully [duplicate]

This question already has answers here:
std::cin loops even if I call ignore() and clear()
(2 answers)
Closed 5 years ago.
My first while loop executes, until I enter a non-number to terminate it. Then, instead of while(cin >> cel) executing, it is skipped, leading the program to terminate/finish. I have tried everything including clearing the "cin bit" as described in another similiar question with no success. What am I doing wrong?
int main() {
double fah = 0;
cout << "Enter a fahrenheit value:\n";
while (cin >> fah) { // executes until a non-number input is entered
cout << fah << "F == " << fah_to_cel(fah) << "C\n";
}
// tried cin.clear(); here
// tried cin.clear(ios_base::eofbit); here
double cel = 0;
cout << "Enter a celcius value:\n";
while(cin >> cel) { // executes until a non-number input is entered
cout << cel << "C == " << cel_to_fah(cel) << "F\n";
}
return 0;
}
You were correct to call cin.clear(). That resets the error flags of cin, which you need to do before you can perform any more input operations. But you need to do one more thing. When input fails, whatever characters cin was trying to read remain in the input buffer. So when you try to collect input again (after clearing the error), it will fail again. So you need to remove the data that was left in the buffer. You can do that like this:
std::streamsize amount_to_ignore = std::numeric_limits<std::streamsize>::max();
std::cin.ignore(amount_to_ignore, '\n');
This tells cin to discard all characters in its buffer until it finds a newline character (which should be in there from when you last pressed the enter key).
This is, in my opinion, a very clunky and error prone way to do user input. I would suggest that you exclusively use std::getline when reading from cin, which should never fail (except in the unlikely event of a memory allocation failure). And then parsing the resulting string manually, which gives you a lot more control over the form of the input.

Why is this code exiting at this point?

I'm new to C++. I stumbled upon one tutorial problem, and I thought I'd use the few things I have learnt to solve it. I have written the code to an extent but the code exits at a point, and I really can't figure out why. I do not want to go into details about the tutorial question because I actually wish to continue with it based on how I understood it from the start, and I know prospective answerers might want to change that. The code is explanatory, I have just written few lines.
Here comes the code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double average_each_student() {
cout << "\n>Enter your scores seperated by spaces and terminated with a period\n"
<< ">Note: scores after total number of six will be truncated.\n"
<< endl;
double sum = 0, average = 0;
int user_input, counter = 0;
const double no_of_exams = 6;
while(cin >> user_input) {
++counter;
if(counter < 5) sum += 0.15 * user_input;
else if(counter > 4 && counter < 7) sum += 0.20 * user_input;
}
return sum / no_of_exams;
}
int reg_number() {
cout << "Enter your registration number: " << endl;
int reg_numb;
cin >> reg_numb;
return reg_numb;
}
int main() {
vector<int> reg_num_list;
vector<double> student_average;
reg_num_list.push_back(reg_number());
student_average.push_back(average_each_student());
string answer;
cout << "\n\nIs that all??" << endl;
//everything ends at this point.
//process returns 0
cin >> answer;
cout << answer;
}
The code exits at cout << "\n\nIs that all??" << endl;. The rest part after that is not what I intend doing, but I'm just using that part to understand what's happening around there.
PS: I know there are other ways to improve the whole thing, but I'm writing the code based on my present knowledge and I wish to maintain the idea I'm currently implementing. I would appreciate if that doesn't change for now. I only need to know what I'm not doing right that is making the code end at that point.
The loop inside average_each_student() runs until further input for data fails and std::cin gets into failure state (i.e., it gets std::ios_base::failbit set).
As a result, input in main() immediately fails and the output of what was input just prints the unchanged string. That is, your perception of the program existing prior to the input is actually wrong: it just doesn't wait for input on a stream in fail state. Since your output doesn't add anything recognizable the output appears to do nothing although it actually prints an empty string. You can easily verify this claim by adding something, e.g.
std::cout << "read '" << answer << "'\n";
Whether it is possible to recover from the fail state on the input stream depends on how it failed. If you enter number until you indicate stream termination (using Ctrl-D or Ctrl-Z on the terminal depending on what kind of system you are using), there isn't any way to recover. If you terminate the input entering a non-number, you can use
std::cin.clear();
To clear the stream's failure stated. You might want to ignore entered characters using
std::cin.ignore(); // ignore the next character
or
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// ignore everything up to the end of the line
use cin.clear(); before cin >> answer; That will fix the problem. But you are not controlling the input. it just runs out to cin..

Why my while loop causes infinite output

I am attempting to build a small program that includes a while loop:
int main() {
int x = 0;
int y = 0;
while (x != '|' || y != '|') {
cout << "Please enter two numbers: \n";
cin >> x >> y;
cout << "You entered: " << x << " and " << y << "\n\n" << endl;
}
return 0;
}
I compiled and ran on both my windows box with visual studio and my linux box, and when the break requirement is filled my terminal/cmd fills up infinitely like an infinite loop. I've searched in quite a few places and couldn't find a clear answer. I have tried making the while infinite and putting the break parameter inside to no avail. I have a feeling it has to do with putting the vertical symbol in an integer, but I have had for loops running well with it. The lesson I'm in asks for it and I have workarounds that are 'okay', but would like to know a clean/standard way of doing this.
The infinite loop is because you never check for input failure. After the line cin >> x >> y add:
if ( !cin )
break;
Bear in mind that x and y are ints, so they can only store numbers. When you write x != '|' you are testing whether the person successfully entered the number matching the ASCII character code of |. If you want to be able to inspect each character the person entered, input into a string instead.

Problem with consecutive cin's

#include<iostream>
int main()
{
int x, y;
cin >> x ;
cin >> y ; // This gets ignored
}
Hi
in above prog after pressing Ctrl-D during first cin second cin gets ignored. how i can make second cin work after pressing ctr-D during first cin. cin.ignore() and cin.clear() doesn;t seem to work.
My question is that if im pressing ctrl-D during first cin bascially i am leaving eof char in i/p stream which is not going to be read and it reamins there. now can't i remove this character from the stream so that it's ready again for input. if not what's the exact reason behind it.
Ctrl-D is for end-of-file. In this case, it indicates the end of the stdinstream, which means nothing is to be read again.
Pressing Ctrl+D signals that you have reached the end of input (end of file). That obviously means that the next input operation doesn't even have to try, because there can't be anything more to read.
If you don't want to terminate the input stream, just don't press Ctrl+D!
Ctrl-D signals the end of transmission or end of file. Using it will prevent all further reads from the standard input (std::cin in this case).
For safer more robust and reliable code always check the stream state before and after reading, especially after reading.
An example code fragment:
int x;
int y;
int main(void)
{
if (!(cin >> x))
{
cerr << "Error reading first value." << endl;
return EXIT_FAILURE;
}
if (!(cin >> y))
{
cerr << "Error reading second value." << endl;
return EXIT_FAILURE;
}
cout << "First number: " << x << endl;
cout << "Second number: " << y << endl;
return EXIT_SUCCESS;
}
Remember that a read may fail for other reasons than EOF. In your case the "cin >> x" may fail because the user entered something that is not a number, such as a letter or symbol.
Try this: When you found the EOF, reset the stream with
clear(eofbit)
I know you said you tried
clear()
but that makes me assume that you called it without parameters which defaults to:
clear(goodbit)