cin.get() is non-blocking - c++

I have the same problem as mentioned in the linked question. The console window (in VS 2010) disappears immediately after running the program. I use a cin.get(); at the end of the main function, but the problem still remains. Any idea about the possible reason? You can check out the code in main:
int main()
{
const int arraysize = 10;
int order;
int counter;
int a[arraysize] = {2,6,4,45,32,12,7,33,23,98};
cout<<"Enter 1 to sort in ascending order\n"
<<"Enter 2 to sort in descending order\n";
cin>>order;
cout<<"Data items in original order\n";
for(counter=0;counter<arraysize;counter++){
cout<<setw(4)<<a[counter];
}
switch (order){
case 1: cout<<"\nData items in ascending order\n";
selectionSort(a, arraysize, ascending);
break;
case 2: cout<<"\nData items in descending order\n";
selectionSort(a, arraysize, descending);
break;
default: return 0;
}
for(counter=0;counter<arraysize;counter++){
cout<<setw(4)<<a[counter];
}
cout<<endl;
cin.get();
return 0;
}
link : C++ on Windows - the console window just flashes and disappears. What's going on?

So when using cin.get() after cin, you should always remember to add cin.ignore() between them .
cin>>order;
cin.ignore();
/*
other codes here
*/
cin.get();
It is mainly because the CIN will ignore the whitespace in the buffer, so after cin>>order, there is a "newline"(\n) in the buffer, then your cin.get just read that \n, then you program successfully executed and return. The cin.ignore() will ignore previous input in the buffer. This really help!
I am a student in China. Your question is the first one I can answer here. I once had the same trouble as you. I hope this helps you.
Ignore my poor english and thank you.

My guess is that
default: return 0;
get executed.
EDIT:
You're right, that's not the issue. Read this.
The quick fix is:
cout<<endl;
cin.ignore(); // <---- ignore previous input in the buffer
cin.get();
But you might want to read the article for further info on the behavior.

I bet you hit the default switch label (return 0;). This bypasses cin.get() - you need one cin.get() per return statement.

Probably your cin.get() is reading the newline which terminated your order input? You could try calling cin.get() twice.

Related

How to implement an "ENTER" case into a switch statement

I am working on a class project where I have to create an ordering system for a coffee shop in C++. If it is applicable, I'm working in Visual Studio.
In the project outline, the teacher said that there is a simple integer input to navigate the menu; however, he specifies that if NOTHING is inputted (I'm assuming what I've seen called a "hot enter") that it calculates the receipt and the program resets.
I have tried cin.get() and checking if the buffer is '\n', and this works fine, but my current implementation seems to only be able to capture a hot enter, and fails to roll into the switch case.
For getting input from the user, I've currently tried this:
// Get menu input
if (cin.get() == '\n') { // Check if user hot entered, assign value if so
input = 0;
} else { // If not, do it normally
input = cin.get();
}
However this does not work quite right, and fails to capture inputted integers for use in the switch case. I'm unsure if this sort of implementation is sound in reasoning, or whether there is a much simpler route to have a case for a hot enter.
I don't receive any errors, so I imagine there is something wrong with my understanding of how these functions work, or my implementation is flawed in its logic.
Thank you.
You used cin.get() twice. The second cin.get() in input = cin.get(); is redundant.
// Get menu input
input = cin.get();
if (input == '\n') { // Check if user hot entered, assign value if so
input = 0;
}
//else { // If not, do it normally
// input = cin.get();
// }

Why does the console overwrite output?

I'm at the start of writing a csv-file parser for a file with around 8000 Ids. When running, after around half the Ids are read and printed, the Clion console starts overwriting the first outputs so that at the end of running the first Id in my consoles output is the 2626th instead of the first. What in my code is responsible for this?
When printing every read character before the switch starts, the output is complete. It also works with a smaller amount of Ids, when i shorten the amount in the csv to around 6000.
int main() {
string buffer;
char zeichen;
ifstream eingabe;
eingabe.open("../lib/Daten.csv");
int zustand=0;//0=Token, 1=Werte
if(eingabe){
while(!eingabe.eof()) {
eingabe.get(zeichen);
//cout<<zeichen; // with only this it works
switch(zeichen){
case';':
if(zustand==0){
cout<<"Token: "<<buffer<<"; ";
}
else if(zustand==1){
cout<<"Wert: "<<buffer<<"; ";
}
buffer="";
break;
case'\n':
if(zustand==0){
zustand=1;
cout<<"Token: "<<buffer<<endl;
}
else if(zustand==1){
cout<<"Wert: "<<buffer<<endl;
}
buffer="";
break;
default:
buffer+=zeichen;
break;
}
}
}
eingabe.close();
return 0;
}
Answered by all the helpful people in the comments. It seems to be connected to Clion

How to make this C++ Program more robust?

Sorry for the vague title but i really do not know how to describe the problem concisely..and the following is the simple codes:
#include <iostream>
using namespace std;
bool func(int a,char c,int b,int& result)
{
switch(c)
{
case '-':
result=a-b;
break;
case '+':
result=a+b;
break;
default:
return false;
}
return true;
}
int main()
{
cout<<"Usage:A {+|-} B"<<endl;
while(true)
{
int a,b,result;
char c;
cin>>a>>c>>b;
if(func(a,c,b,result))
{
cout<<result<<endl;
}
else
{
cout<<"Input Error!"<<endl;
}
}
return 0;
}
The right method to use the program is to input A {+|-} B.
For example,you can input 1[SPACE]+[SPACE]2[ENTER](which I mean "1 + 2" and then press ENTER) then it will spit out "3" for me.For the purpose of making the program more robust,I try to input 1[SPACE]+[SPACE]2[SPACE]+[ENTER] It just give me many "2" printed on the shell.Is there anyone who could tell me how to fix the bug?Many thanks!
PS:The codes is available at github:bug0x001.cpp
You fail to check if the input was read correctly. That's the first thing to do in a robust program. Also, if it failed, you should fix the input source. The endless stream of 2 is caused by a broken cin.
if( cin>>a>>c>>b &&
func(a,c,b,result))
{
}
else
{
cin.reset();
}
Your problem is that you are trying to get ints and char with cin, this is ok if you need that exact input, but crash when reading strange things (like a letter as int), as it reads garbage
The best solution (for me) is to read everything as a string (check cin.getline and stuff like that), then you "parse" the input as you whant, for example:
if you read "19+ 32 3" you can "easily" eliminate all spaces and split by any non numeric symbol, getting 3 strings: s1="19",s2="+" and s3="323", then you just parse each string as int (or whatever you need) and the symbol as char or whatever.
If you find anythng weird, you can try to understand it, eliminate it or just show an input error.
Is more complex than doing a cin.reset after testing, but allow you to "understand" more types of data input

Strange behaviour when reading in int from STDIN

Suppose we have a menu which presents the user with some options:
Welcome:
1) Do something
2) Do something else
3) Do something cool
4) Quit
The user can press 1 - 4 and then the enter key. The program performs this operation and then presents the menu back to the user. An invalid option should just display the menu again.
I have the following main() method:
int main()
{
while (true)
switch (menu())
{
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
case 3:
doSomethingCool();
break;
case 4:
return 0;
default:
continue;
}
}
and the follwing menu():
int menu()
{
cout << "Welcome:" << endl
<< "1: Do something" << endl
<< "2: Do something else" << endl
<< "3: Do something cool" << endl
<< "4: Quit" << endl;
int result = 0;
scanf("%d", &result);
return result;
}
Entering numerical types works great. Entering 1 - 4 causes the program to perform the desired action, and afterwards the menu is displayed again. Entering a number outside this range such as -1 or 12 will display the menu again as expected.
However, entering something like 'q' will simply cause the menu to display over and over again infinitely, without even stopping to get the user input.
I don't understand how this could possibly be happening. Clearly, menu() is being called as the menu is displayed over and over again, however scanf() is part of menu(), so I don't understand how the program gets into this error state where the user is not prompted for their input.
I originally had cin >> result which did exactly the same thing.
Edit: There appears to be a related question, however the original source code has disappeared from pastebin and one of the answers links to an article which apparently once explained why this is happening, but is now a dead link. Maybe someone can reply with why this is happening rather than linking? :)
Edit: Using this example, here is how I solved the problem:
int getNumericalInput()
{
string input = "";
int result;
while (true)
{
getline(cin, input);
stringstream sStr(input);
if (sStr >> result)
return result;
cout << "Invalid Input. Try again: ";
}
}
and I simply replaced
int result = 0;
scanf("%d", &result);
with
int result = getNumericalInput();
When you try to convert the non-numeric input to a number, it fails and (the important part) leaves that data in the input buffer, so the next time you try to read an int, it's still there waiting, and fails again -- and again, and again, forever.
There are two basic ways to avoid this. The one I prefer is to read a string of data, then convert from that to a number and take the appropriate action. Typically you'll use std::getline to read all the data up to the new-line, and then attempt to convert it. Since it will read whatever data is waiting, you'll never get junk "stuck" in the input.
The alternative is (especially if a conversion fails) to use std::ignore to read data from the input up to (typically) the next new-line.
1) Say this to yourself 1000 times, or until you fall asleep:
I will never ever ever use I/O functions without checking the return value.
2) Repeat the above 50 times.
3) Re-read your code: Are you checking the result of scanf? What happens when scanf cannot convert the input into the desired format? How would you go about learning such information if you didn't know it? (Four letters come to mind.)
I would also question why you'd use scanf rather than the more appropriate iostreams operation, but that would suffer from exactly the same problem.
You need to verify if the read succeeded. Hint: it did not. Always test after reading that you successfully read the input:
if (std::cin >> result) { ... }
if (scanf("%d", result) == 1) { ... }
In C++ the failed state is sticky and stays around until it gets clear()ed. As long as the stream is in failed state it won't do anything useful. In either case, you want to ignore() the bad character or fgetc() it. Note, that failure may be due to having reached the end of the stream in which case eof() is set or EOF is returned for iostream or stdio, respectively.

C++ - Quitting a program

In the C++ Without Fear: A Beginner's Guide That Makes You Feel Smart book in chapter(8), part of a code trying to display a text file is the following:
while(1)
{
for(int i=1; i <= 24 && !file_in.eof(); i++)
{
file_in.getline(input_line,80);
std::cout<<input_line<<std::endl;
}
if(file_in.eof())
{
break;
}
std::cout<<"More? (Press 'Q' and ENTER to quit.)";
std::cin.getline(input_line,80);
c=input_line[0]; // <<<<<<
if(c=='Q'||c=='q')
{
break;
}
}
The part I'm not getting here is:
c=input_line[0];
I think it is put to read 'Q' or 'q'. But, why using this form (Array)? And, isn't there a way to read 'Q' or 'q' directly?
I tried std::cin>>c; but seemed to be incorrect.
Any ideas?
Thanks.
Because input_line is string ( array from chars), so input_line[0] gets the first letter - this is in case, that the user write "quit" or "Quit", not just "Q"
std::cin >> c; would be correct, if you enter just one char and press Enter
I tried std::cin>>c; but seemed to be incorrect.
That's correct, if c is a char.
You're right; reading an entire line just to extract a single character is bizarre. I recommend a book from this list.
You are getting the first character from the "array" into which the input line has been written.
NON-STANDARD solution, but works on windows platforms.
you can use getch() function defined in conio.h
example:
#include <conio.h>
...
char c = getch();
bye