How to Determine if STDIN is Empty? - c++

I'm writing an emulator for my Operating Systems course. The problem I have is that we need to get all our .job files (they are like application programs being fed to the emulator) from STDIN and read them in.
Call:
./RMMIX < aJob.job
I just slurp it with
while(getline(std::cin, line))
line by line. The problem is, if I do not put anything to STDIN, then cin will wait for user input- NOT what I want. I need the program to recognize a lack of text on STDIN and terminate, not wait for user input instead.
I have determined that I can query the length like so:
size_t beg = std::cin.tellg();
std::cin.seekg(0, std::ios_base::end);
size_t end = std::cin.tellg();
std::cin.seekg(0, std::ios_base::beg);
and terminate if std::cin has a length of 0.
Are there any other solutions to this? Is this a portable solution?

I don't think there's a platform independent way of doing this, but on Unix-based systems you should be able to do:
#include <unistd.h>
...
int main() {
if (!isatty(0)) {
// stdin is being streamed from a file or something else that's not a TTY.
}
...
}
However, I think doing it via a command line option is the preferred approach.

You need to redesign your program. Instead of reading from standard input, read from a named file, who's name you provide on the command line. Then instead of:
./RMMIX < aJob.job
you say:
./RMMIX aJob.job
This is much easier and more portable than trying to determine if there is anything in standard input.

You might also look at this http://www.programmersheaven.com/mb/CandCPP/232821/232821/non-blocking-reads-on-stdin/ for an idea that comes at the problem from another direction -- don't check the number of bytes on the stream, but instead just make the read succeed immediately and then check to see if anything was read.

You can press Ctrl+D on the command line to signal end-of-file for standard input on the running program.
This is desired behavior. Otherwise, if programs exited immediately when no input remained, pipelines could randomly be broken by commands that were waiting on another command that had not been scheduled to run (and that had not produced any additional output), or that buffered output and emitted it all at once, like sort does.
When using io redirection to pull stdin from a file via something like ./RMMIX < file.txt, this end-of-file condition is signaled automatically when there is no more data left in the file. For input read from a terminal, waiting is probably the desired behavior.

Related

How to send input to stdin from code not terminal?

I want to send input to a variable without having to type it in the terminal, as i am implementing a test case. for example consider the input to be sent is 2:
int a;
cin >> a;
The code should not wait for the user to give input, it should enter 2 there and populate a by itself.
i cant use the cin buffer, also taking input is compulsory.
you could create unnamed pipes pipe pd[2] and dup stdin & stdout to the pipe fds.
then write "2" into one pipe and read it from another.
You can get your input from a stringstream instead:
std::stringstream data = "2";
int a;
data >> a;
The basic question here (at least in my mind) is whether you're trying to write a single program, so that one part of the program provides the input to another part of the program, or you're writing two separate programs, one of which provides input to the other.
#Madhu Narayanan has already given a good summary of how you'd go about writing the code for the first case.
But, by far the preferable way to handle things inside a program is to have something like a function that takes (a reference to) an iostream as a parameter, so you can pass std::cin to read from the console, or some stringstream to have it read some predetermined data instead.
If what you care about is the second case, then you'd probably want to use popen (or Microsoft calls it _popen), which will spawn a child process, and connect a pipe to either its standard input or its standard output (but, regrettably, not both). So if this is what you want you'd do something like this:
// spawn the child, getting a handle to its standard input:
FILE *child = popen("child program", "w");
// write the input to the child:
if (child != nullptr) {
fprintf(child, "%d", 2);
}
For better or worse, there's no analog of this that gives you access to the child via an iostream (at least, not a pre-written one in the standard library, anyway).

Disabling Ctrl-Z behaviour in `ifstream::getline`

I want to use ifstream::getline to read lines from a file, but the file contains the byte Ctrl-Z (0x1A), which makes getline think that it's reached the end of file (this is in Windows -- in *nix it would be Ctrl-D, if I'm not wrong). Can I disable this behaviour somehow, and tell getline to ignore Ctrl-Z?
Just for info: the file is comments.wast in the WebAssembly testsuite, which tests the ability of a WebAssembly parser to accept any and all characters inside a block comment.
This shouldn't happen when your ifstream object is using binary mode.
Just create it like this:
std::ifstream fin(<path>, std::ios::binary)
This of course prevents you from using other features of the stream, but if your main goal is to be able to read all sort of values while ignoring special characters, this is probably the way to go.

C++: getline freezes at end of file

I want to read in one file line-by-line and output each line I read to a new file. In this code, cin has been redirected to refer to the input file, and cout has been redirected to refer to the output file.
The loop successfully writes every line in the file, but then it gets stuck on the final getline call. As a result, "Done" is not written to the file and the program does not terminate.
#include <string>
#include <iostream>
using namespace std;
int main() {
string line;
while(getline(cin, line)) {
cout << line << endl;
}
cout << "Done";
return 0;
}
Strangely, if I forcibly terminate the program, it seems to suddenly execute as desired, with "Done" being written.
Can someone point me in the right direction? Is there a flaw in the code, or is this some external configuration issue?
Notes: The input file in question ends with a newline character. Also, I do not want to use any includes besides these two.
The code should terminate on end of file (EOF) or any sort of file error. (The getline being called is:
http://en.cppreference.com/w/cpp/string/basic_string/getline
It returns the cin istream and then invokes its boolean conversion operator:
http://www.cplusplus.com/reference/ios/ios/operator_bool/
that checks if badbit or failbit is set on the stream. The failbit state should be set when a read is attempted with the stream already at EOF, or if there is an error.)
Per the comments above, it seems like this does work when the code is run from the shell directly. My guess is Eclipse is doing something complicated where it either intentionally sends the file into the program and then switches to an interactive input mode, or has a bug in which it doesn't close its end of a pipe or pty/tty it is using to send input to the program. (I.e. Eclipse is not binding stdin directly to the file itself in running the program.)
If one wanted to debug it further, one could look at the process state using tools like lsof. (Assuming a UNIXy system.) Might also be worth raising the issue in an Eclipse forum. The IDE is not my area of expertise.

Clearing eof bit not working with while loop

I have a program I'm trying to write that constantly monitors a log file and outputs specific items into a new file.
I'm using essentially.
for (int i = 1; i < y; i ++)
getline(read, line); // skips to the last known end
while (getline(read, line))
{
cout << line;
}
read.clear();
I also keep track of the line I'm on just using the increment operator on a variable. At the end of the file I clear the eof bit and seek to the last line I was on. From using the debugger it seems that it works. I retrieve the next line in the file as its being written but when I call back to my while (getline(read,line)); it skips going through the while loop, why is that?
program reads the last line in the file.
Sleeps for 5 minutes.
The input file has had new lines added to it from a third party.
After the sleep it wakes up and goes back to the while loop.
It successfully retrieves the new lines from the input. But fails to
enter the while loop again
When using std::getline() at the end of a file both std::iostate::eofbit and std::iostate::failbit are set. In fact, it is std::iostate::failbit which causes the loop to exit. You'll need to clear both of these flags prior to any seek.
For a system which needs to use IOStreams I would actually not bother reading the leading lines but merely wait a bit, clear the flags, and try again. The main issue is detecting whether a complete line is read which could be done by simply reading individual characters, e.g., using std::istreambuf_iterator<char>.
Otherwise I'd look for a system API which provide some sort of indication that new data is available on a file. Older system generally don't provide such facilities but newer system generally have some event-based interface which can be used to get hold of newly available data. The advantage is normally that the processes doesn't poll for new data but idly waits until it gets notified about new data. I haven't used it myself but it seems libuv does this sort of operations in a somewhat platform-independent form.

in c++, after reading in a file using a terminal window how can i use standard input?

I have a program where I read in a data file to populate a list of information
(./myProgram < dataFile.dat)
After the file is read i am unable to get standard input (cin) in that terminal window to work, it does not ever give the chance to enter input, but simply skips over it most likely grabbing some random value to be stored in. Is there any way to utilize cin after reading in a file as listed above?
Depending on your shell environment, you can feed the file into another fd than stdin:
$ cat fd_in.c
int main()
{
unsigned char buf[1024];
int bytesread;
bytesread = read(3,buf,sizeof(buf));
printf("file is %d bytes\n",bytesread);
bytesread = read(1,buf,sizeof(buf));
printf("you entered %d bytes\n",bytesread);
}
$ gcc fd_in.c
$ ./a.out 3< fd_in.c
file is 220 bytes
my input!
you entered 10 bytes
./myProgram < dataFile.dat means that standard input will be sourced from dataFile.dat, not from the keyboard. So if you run the program like this, you will not be able read keyboard data from standard input. While standard input/output are easy to use and make the program amenable to piping, etc. they work most naturally when your program has a single input and/or a single output. If your input comes from two different sources, as seems to be the case for you, then you should make your program explicitly open the file and read from it, using an ifstream. That way, keyboard input will still be available from cin.
On a separate note, it is a good idea to check if your reads succeed. If you had done so, you would have seen that all your reads from cin after the file is done are failing due to the end of file being reached.