Why can't I end my input by this? - c++

I want to terminate my input by input, EOF(^Z in windows), and here is the program:
#include<stdio.h>
#include<conio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF)
{
if (c == '\t')
{
putchar('\\');
putchar('t');
}
else if (c == '\b')
{
putchar('\\');
putchar('b');
}
else if (c == '\\')
{
putchar('\\');
putchar('\\');
}
else if (c == '\r')
{
puts("\\n");
// putchar('\n');
}
else{
putchar(c);
}
}
return 0;
}
and here is my input and output:
So I am asking: why can't I terminate my input by the first ^Z? Otherwise stated, why do I have to type enter to make a new line in order to terminate my input by input at ^Z?

See the discussions in:
read() from stdin doesn't ignore newline
How can I make the word count program (from K&R) terminate after just one application of Control-D
How to simulate EOF without preceding newline in C
On Unix, Control-D is (by default) equivalent to Control-Z on Windows.
All point out that the first time you type Control-Z, the input already accumulated in the input is sent to the program (without a newline); there is a non-zero number of characters sent, so it is not yet EOF. The second time, you type the Control-Z at the beginning of the line, and the program gets zero bytes to read, which is interpreted as EOF.

There's no real reason beyond "that's how it works". You can just press F6 instead though. That will be seen as signaling the end of file, even if it's not preceded by an enter.
The reason you have to press both F6 and enter is fairly simple: there are really two separate pieces of code involved here. The operating system has a small (somewhat crippled) editing routine that lets you enter a line of data. It has code to process back-space and a few things like that, so you can use them when entering data, even though your code doesn't include any editing capability at all. That routine returns a line of text to your program, but only when you've entered what it is programmed to "think of" as a completely line--and that only happens when enter is pressed.
Once that buffer full of data has been read in by the operating system, it's sent to your program. Your program looks at the contents, and when/if it finds the ctrl+Z, it reads that as signaling the end of the file. But, since the end of file processing is done by your program, not the operating system's editing routine, there's no way for it to be senses until you've pressed enter.
If you really don't like this behavior, most operating systems do provide some way to do un-buffered reading. The exact way varies by operating system though. One Windows, you can use _getch. Most Unix-based systems provide roughly the same capabilities in the Curses library (and if you want to use that, there's also at least one free implementation of curses for Windows).

Related

C++ use cin.get to get a character, but not end the while loop when encounter the EOF

The following is my code, that I want to read characters from stdin, and end when it meet an EOF(ctrl-z).
#include<iostream>
#include<fstream>
#include<stdio.h>
#include<string>
using namespace std;
int main()
{
string article ;
char nextChar;
while( cin.get(nextChar) ) {
if( cin.eof() ) break ;
article.append(1, nextChar) ;
}
cout << article ;
system("pause") ;
}
I test an input like this:
I am a student.<ctrl-z>
And then I press enter, but it does not halt.
When I type another [ctrl-z], and then press neter.
It just can exit from the while loop.
Why the first [ctrl-z] not to signal the eof condition?
The following explanation is slightly simplified.
It's a feature of your operating system. This is how your operating system works.
An end of file is, really, the underlying read() system call returning 0. An end of file is not CTRL-Z. CTRL-Z gets interpreted by your operating system to flush its interactive key buffer, and have the process read() its contents.
When you type in a terminal, the process does not actually end up reading anything until Enter is pressed. At that time the read() system call completes, and returns everything that's been read. In general, before pressing Enter you can backspace and edit what you typed, and your program has no indication that you've edited anything, all that it read()s is the final contents of the line after pressing Enter.
If you type something, and press CTRL-Z, the typed input is also read() by the program as if it was typed in.
Only if nothing is typed, and CTRL-Z is pressed, does the underlying read() system call returns 0, because nothing got typed in first; this is interpreted as an end-of-file indication. But if something gets typed in first, CTRL-Z needs to be entered twice, once to read() the typed in input, and clear the input buffer, then CTRL-Z a second time, to cause an read() of 0.
By the way, your code has a harmless bug. If cin.get() succeeds, cin.eof() can never be true.

using c++ input stream cin without blocking

I am trying to use the c++ standard input stream cin to get a user input without blocking the execution of the program. I have this code:
char ch;
int flag=1;
do
{
if(cin.rdbuf()->in_avail())
{
cin.get(ch);
flag=0;
}
else
//do something else
}while(flag);
//do something with the input
The idea here is to wait for user input without blocking while doing something else and as soon as the user provides an input we process the input( all in one thread). I know from the documentation the streambuf class used by the input stream provides the in_avail() function which will return a non-zero values when ever there is input ready in the buffer. The code above is not working as i expected it and is looping forever even if i provide a keyboard input at some point. i am using MS visual studio 2005 in windows 7. what am i missing here?
The function in_avail does:
Returns the number of characters available in the get area.
The get area may be empty even if some characters are readable from the underlying operating system buffer.
You will trigger a refill of the get area when you effectively call a read operation on the streambuf. And that operation will block. The reason is that the method underflow which is responsible for filling the get area:
Ensures that at least one character is available in the input area
And to ensure this, it must block until some character is read.

strange eof flags in stream

I have encountered a strange problem when parsing text file using c++ file stream. Here is the code:
while (true)
{
std::getline(inFile, line);
if (!inFile.good())
{
std::cout << "Fail, bad and eof flags:" << inFile.fail() << inFile.bad() << inFile.eof() << std::endl;
break;
}
parseLine(line);
}
When the read terminates, the output is:
Fail, bad and eof flags:001
But actually the reader does not reach the end of file. I open the file and find that the next character is actually 26 (ASCII code). Then the problem is: 1) why the eof flag is set when reading this character, and how to avoid this kind of false termination? and 2) how to recover from this state? Thanks!
PS: thanks the replies. What if I read the file in binary mode? Any better solution? I use the Windows platform but the file seems to be an unix file.
why the eof flag is set when reading this character
Because it's the EOF marker character.
From Wikipedia:
In Microsoft's DOS and Windows (and in CP/M and many DEC operating
systems), reading from the terminal will never produce an EOF.
Instead, programs recognize that the source is a terminal (or other
"character device") and interpret a given reserved character or
sequence as an end-of-file indicator; most commonly this is an ASCII
Control-Z, code 26.
how to avoid this kind of false termination
It's not a "false" termination.
how to recover from this state?
You don't need to.
If you were trying to read a "binary file" where arbitrary characters would be expected, you would open your file stream in binary mode.
The ASCII character 26 is the SUB control character, which in caret notation is ^Z. This might be recognizable to you as the Windows end of file character. So assuming ASCII and Windows, there you go.
Here you go:
Getline and 16h (26d) character
Looks like you have to write your own getline function. Seems there is no way around it :p That I know of, and it seems no one else knows. If anyone knows a better way, chime in.

Clearing keyboard buffer in C++

I one part of my application I have used Sleep(5000) (I need to wait 5 sec)
The problem is that if the user presses any keyboard key during these 5 seconds, the keys will be read after sleep and it causes problems for my app.
How can I empty the buffer after sleep?
I tried cin.clear() and setbuf(stdin, NULL) but they can't clear the buffer if there is more than one character in the buffer.
The two functions you are using don't have the effect you expect them to have:
clear() doesn't affect the buffer at all but rather clears the error flags. That is, if there was an unsuccessful read a flag is set (std::ios_base::failbit). While any error flag is set (there are a few more), the stream won't attempt to read anything.
setbuf(0, 0) affects the stream's internal buffer to not exist (calls with non-null values have implementation-defined meaning which is typically "do nothing"). This is generally a Bad Idea because it causes the streams to be very slow. Also, the keys pressed by a user are probably not stored in this buffer anyway but rather in the operating systems input buffer until they are sent to application (there are platform specific ways to turn off the operating system input buffer, e.g., on POSIX you'd use tcsetattr() to set the input into non-canonical mode).
In either case, not having a buffer doesn't really help you anyway: The user may very well have typed valid input. The proper approach is to attempt reading the available input and, if this fails, to rid of the offending character (or characters). To this end you'd attempt to read the input and if it fails you'd clear() the stream and ignore() one or more characters (this example ignores an entire line; call ignore() without parameters to just ignore one character):
T value;
while (!(std::cin >> value)) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
You always need to verify that the input was successful anyway and the few extra lines are just adding a bit of recovery code.
The simplest way to clear the keyboard input buffer is
while(kbhit()) getch();
just put that code in your program wherever you want to clear your buffer .
headerfile needed for that is conio.h
This seems to work for Windows 10 compiled with Code::Blocks:
#include <conio.h>
/**
* clears keyboard buffer
*
* #author Shaun B
* #version 0.0.2
* #fixed 15-01-2016
*/
void clearKeyboardBuffer()
{
while (_kbhit())
{
_getche();
}
}
Then called from where is needed in your C++ script.

KEY_ENTER vs '\n'?

When I'm using PDcurses and I try to have a while loop exit when the enter key is pressed with while(key != KEY_ENTER), the while loop never exits. However, when I try to have the same loop exit with while((char)key != '\n'), it exits successfully whenever I pressed enter. Why does '\n' work and not KEY_ENTER?
btw, key is an int
and I hope this is the relevant few lines of the code:
int key;
while((char)key != '\n') {
key = getch();
...
}
getch() is a function defined by the ANSI C standard for the C runtime library.
On most systems, such as Windows, Linux, etc., this function is implemented to return '\n' when the user pressed Enter. For Comparison, on Windows the key-press itself (of Enter) might be represented as the key-code VK_ENTER.
PDCurses is translating the key codes to ASCII values for you.
You can get the key values you want if you first call the PDCurses functions raw(); nonl();. Also, you should probably use wgetch() for new code.
KEY_ENTER == 0x157, '\n' == 0xA
'\n' is the standard ASCII newline, while KEY_ENTER represents a keyboard code. See the PDCurses code.
For more information, you should post the relevant part of your code.