Why does this while Loop never end? - c++

So I feel that I am close to solving a programming assignment that takes the most used word of each line and prints it on a line. So for example:
I am a man, am right?
I don't know if i like that.
It's okay to not feel okay.
Would print: "am i okay" (punctuations and case are ignored for the assignment)
This is what I have done so far, but the problem is that the while loop that scans the lines never terminates and thus never prints the output in the external for loop. Anybody see where I went wrong?
string line;
vector<string> result;
while(getline(cin,line)){ //on each line
}

Your loop is correct as written; you just don't know how to signify the end of input. You're sitting there waiting for the program to progress, but the program is sitting there waiting for you to give it more input.
Press Ctrl+D (Linux) or Ctrl+Z (Windows) to send the EOF character/signal/potion to end the loop.
This way, all the common shell techniques like file redirection and pipes will also work.
Introducing artificial means like a double-newline or some magic command is non-conventional and makes your program harder to automate. (And making your program magically know that one of the newlines came from a keyboard hit rather than copy/pasting, is just not possible. Nor do you want it to be! That breaks a ton of valuable abstractions.) When writing a command-line tool, stick to standard practices as much as possible.

Currently your program is waiting for an EOF character which indicates the input has ended. If you are running this and entering the input from the command line, you can manually insert an EOF by pressing Ctrl+D on *nix, or Ctrl+Z on windows. This will cause your program to break out of your getline loop.
If you would rather not do that, you need a way to break out of the getline loop, otherwise it will continue to run in that loop.
A nice idea might be detecting an empty line, so pressing enter twice ends the loop:
while(getline(cin,line)){ //on each line
if(line == "")
break;
...
}

Related

how to end input multiple lines in console for c++?

In code like the following:
while(getline(cin, line))
{
// do something
}
How can I tell the console to stop accepting input?
This is a link to the full code.
Hitting ctrl+D on Unix-like systems (including Linux), or ctrl+Z on Windows is the standard way to signal "End of input" to command-line programs (traditionally called "EOF" for "end of file"). It will cause std::getline to return a value that will evaluate as false in your while statement, ending the loop and continuing with the rest of your program.
You should add a condition like line == "end" and break out of the while loop if that happens, but if you want to avoid changing the code, Ctrl+D will send an EOF and will tell the terminal to stop accepting inputs.

Weird Pause Behavior Fortran

I am running a fortran code. The code has no pauses nor any switches that ask user to do anything. It should run beginning to end with no stops. This is a code that has a big outer loop and several OpenMP inner loops. The only thing I output are the index of the bigger outer loop so that I can know where the code is.
The code usually runs with no problems. However, the last two times I run it, the code stopped with no error (I know that because the cores usage started being 0%). However if I press enter in the console the code resumes normally.
So my question, is there any way to pause a fortran code at run time without having an explicit pause on the code?
Do you have any READ statements in your program? They'd pause the terminal if they're waiting for input.
For example, the following program looks like it's pausing in the middle of the loop. Pressing enter allows it to continue.
integer i
do i = 1, 10
if (i == 5) read(*, *)
print *, i
end do
end
Perhaps you or someone else added a READ for debugging purposes and forgot to remove it?

How can I flush stdin? (environment: Mingw compiler, running in xterm or mintty of Cygwin)

There are two ways that I know to flush stdin:
(1) bool FlushConsoleInputBuffer(_In_ HANDLE hConsoleInput);
(2) fflush (stdin);
However, in my environment:
Compiler: MinGW g++
Running in: Windows, Cygwin xterm or Cygwin mintty
Neither of them works.
What can I do?
Note: FlushConsoleInputBuffer() works if my program runs under dos prompt window. In addition, FlushConsoleInputBuffer() nicely returns false, when it runs on Cygwin xterm or mintty.
--UPDATE--
I suspect that Cygwin handles stdin separately than Windows native stdin, which make FlushConsoleInputBuffer() fail.
#wallyk: yes. 'flush' means dropping all unread buffered inputs.
--UPDATE-- (final answer accepted and reason)
Tony D is right. The problem is that Cygwin terminal is a unix-like terminal, which allows editing before 'ENTER' key is hit. Thus any partial input must be buffered and will never be passed to stdin before the 'ENTER' key is hit, since it expects editing commands. I guess it should be possible to overcome this by setting terminal to raw mode (not experimented). Yet the editing feature will be lost in the raw mode.
fflush is meant to be used with an output stream. The behavior of fflush(stdin) is undefined. See http://en.cppreference.com/w/cpp/io/c/fflush.
If you use std::cin to access stdin, you can use std::istream::ignore() to ignore the contents of the stream up to a given number of characters or a given character.
Example:
// Ignore the rest of the line.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Working code: http://ideone.com/Z6zLue
If you are using stdin to access the input stream, you can use the following to ignore the rest of the line.
while ( (c = fgetc(stdin)) != '\n' && c != EOF);
Working code: http://ideone.com/gg0Az2
Discarding exactly and only the data currently buffered/available to stdin isn't supported using only C++ Standard library features.
Most of the time, programmers just ignore (see example at the bottom of that page) the rest of a problematic line then try the next buffered line. If you're concerned there may be a lot of problematic lines - for example, that the user may have cut-and-pasted pages of nonsense that you want to discard, but then you do want to give them a chance to enter further lines, you need to use an OS-specific function to work out when a read on stdin would block. You'd then ignore lines until that would-block condition is true.
select and poll are two such operations that work on most Operating Systems, but from memory they're only defined for socket streams on Windows so of no use to you. Cygwin may or may not support them somehow; if you want to try it - you would ignore lines as long as the stdin file descriptor (which is 0) tests readable. You'll find lots of other Q&A discussing how to see if there's input available: e.g. checking data availability before calling std::getline, Check if stdin is empty, Win32 - read from stdin with timeout
Keep in mind that your terminal program is probably internally buffering what you type until you press ENTER, so at most your program can clear the earlier lines but not a line the user's partially typed (though you could use some heuristic to discard it after it's sent to your program's stdin).
UPDATE
Cruder alternatives that might be good enough in some circumstances:
save the now() time, then loop calling getline(std::cin, my_string) until either it fails (e.g. EOF on stdin) or the time between reads is greater than some threshold - say half a second; that way it's likely to consume the already-buffered but unwanted input, and yet ENTER for further hand-typed user input's likely to happen after the discarding loop's terminated: you could prompt ala std::cout >> "bad input discarded - you may press ^U to clear your input buffer if it contains unwanted text...\n"; (Control-U works for many terminals, but check your own)
have a particular string like say "--reset--" that the user knows they can type to stop discarding lines and switch back to processing future lines

C++ stdin occasionally garbled

I've been experiencing a strange occasionally occurring bug for the last few days.
I have a console application that also displays a window opened with SDL for graphical output continuously running three threads. The main thread runs the event loop, and processes the console input. The second thread uses std::cin.getline to get the console input. This second thread, however, is also responsible for outputting logging information, which can be produced when the user clicks somewhere on the SDL window.
These log messages are sent to a mutex-protected stringstream regularly checked by thread 2. If there are log messages it deletes the prompt, outputs them and then prints a new prompt. Due to this it can't afford to block on getline, so this thread spawns the third thread that peeks cin and signals via an atomic when there's data to be got from the input stream, at which point getline is called and the input is passed to the logic on the main thread.
Here's the bit I haven't quite worked out, about 1 in 30 of these fails since the program doesn't receive exactly the same input as was typed into the terminal. You can see what I mean in the images here, the first line is what was type and the second is the Lua stacktrace due to receiving different (incorrect) input.
This occurs whether I use rlwrap or not. Is this due to peek and getline hitting the input stream at the same time? (This is possible as the peek loop just looks like:
while(!exitRequested_)
{
if (std::cin.peek())
inputAvailable_ = true; // this is atomic
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
Any thoughts? I looked at curses quickly, but it looks like quite a lot of effort to use. I've never heard of get line garbling stuff before. But I also printed every string that was received for a while and they matched what Lua is reporting.
As #davmac suggested, peek appears to have been interfering with getline. My assumption would be that this is linked to peek taking a character and then putting it back at the same time as getline takes the buffer.
Whatever the underlying cause of the issue is, I am >98% sure that the problem has been fixed by implementing the fix davmac suggested.
In several hours of use I have had no issues.
Moral, don't concurrently access cin, even if one of the functions doesn't modify the stream.
(Note, the above happened on both g++ and clang++ so I assume that it's just linked to the way the std library is frequently implemented).
As #DavidSchwartz pointed out, concurrent access to streams is explicitly prohibited, so that clearly explains why the fix works.

How to terminate a program with Ctrl-D?

I am trying to write a simple program that simulates a calculator. I would like the program to exit or turn-off when the Ctrl+D keystroke is made. I searched through stackoverflow and saw other examples of Ctrl+C or Ctrl+A but the examples are in java and C.
for C:
(scanf("%lf", &var);
for java, a SIGINT is raised when Ctrl+Z is pressed.
signal(SIGINT,leave);
for(;;) getchar();
I am wondering what can I do for Ctrl+D in C++...
Thanks everyone!
Ctrl+D will cause the stdin file descriptor to return end-of-file. Any input-reading function will reflect this, and you can then exit the program when you reach end-of-file. By the way, the C example should work verbatim in C++, though it may not be the most idiomatic C++.
Is this homework, by the way? If so, please be sure to tag it as such.
If you need to terminate with Ctrl-D while reading input.
while ( std::cin ) // Ctrl-D will terminate the loop
{
...
}
You could make life easier and scan for a keyword like "quit" or "exit". Last time I used a calculator, these words were not on the keypad.
Many simple calculator programs read the input as text terminated by a newline. They parse the text in memory, then spit out an answer.
Other more sophisticated calculator programs use windows and are event driven. Some use a button like "=" to signal end of input and start of calculation (doesn't work on RPN calculators).
These techniques remove the hassle of determining End Of Text input using a control character sequence and are more portable.
Under Unix, the terminal will interpret Ctrl+D (on an empty line) as the end of input; further reads from stdin will return EOF, which you can watch for.
Ctrl+D on Unixy platforms is EOF. If you are getting each char, you can check to see if you got EOF.