I am coding a console application on windows.
I made it multithreaded so it can print status to console while I am receiving input from the prompt.
But when printf() gets called while I am typing the command, I see the output intersecting with what I have typed.
How can I get around this problem? is there a way to keep the input line separate?
I am using getline(cin, strcommand); to collect input data
standard output is a mutual exclusive resource, so it cannot be both used by input and output at the same time.
In your problem, input and output intersect with each other, so i think you can use a buffer to store your log created by the print status thread while you are inputting. When input is over, you can check if there are logs not yet be printed.
while(cin >> x) {
//get output buffer mutex
if(log_exist)
//print the log
//clear the flags
//release output buffer mutex
}
I thingk you just need to end the line with << endl; at the end of your cout. then the input will be under the output.
Related
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.
Here is my code for test:
#include<iostream>
using namespace std;
istream& func(istream &);
int main()
{
if(func(cin))
cout<<"good"<<endl;
return 0;
}
istream& func(istream &is)
{
int num;
is.clear();
auto old_state = is.rdstate();
while(is>>num)
cout<<num<<endl;
is.setstate(old_state);
return is;
}
The problem is:if I enter a char or the mark of EOF(ctr_z in my system) to break the while loop,then the program terminates directly.I was expecting that the cin stream can be reset to a normal state and be returned:
if(func(cin))
cout<<"good"<<endl;
But I can't get that output when program ends.
So what's wrong with my understanding?
You need to ignore the eror and then clear it. So as an example you just need to change your while loop to something like this:
while(true)
{
if(is>>num)
cout<<num<<endl; //if cin is numeric
else // we have an error
{
is.ignore(); // ignore the last error (else your program will run crazy)
is.clear(); // clear the state
break; // terminate console reading
}
}
It's because setstate does not really clear the old flags (read the linked reference to see why)
If you want to completely reset the flags then you need to use the clear function. Not that I really recommend it though, as it gives you a false state of the stream. Instead you should explicitly check the state.
The state can be recovered after an invalid input: failure to parse the input according to the expected type just sets std:: ios_base::failbit which can be clear()ed. Since the character causing the problem is not removed, you'll probably need to get rid of it (e.g. using ignore()) or parae the data differently.
Although EOF is also just a flag (std::ios_base::eofbit) clearing it in general won't recover the from having reached the end of the stream. Specific streams may have a way to carry on reading but the console is likely to be disconnected after an end of stream indicator (e.g., Ctrl-D or Ctrl-Z). Depending on the system it may be possible to create a new connection to the console, e.g., by opening a file stream to /dev/tty.
If you really want to use control characters to indicate special processing you'll need to disable the default processing and manage them within the program. On UNIX systems you'd set the stream into noncanonical mode using tcgetattr() and tcsetattr(). Once this is done all characters entered are seen and can be processed accoringly, probably in a custom stream buffer. I don't know how to do something similar on other systems.
Okay, so let's say I have a program that couts a line while the user may be typing in information.
For this example, let's say we're using the code
cout << "THIS CODE IS BEING COUTED" << endl;
Let's say for our example, the user is in the process of typing up an input and as it stands they have only entered "hello", but has not yet pressed enter.
As it stands, when the line is executed, the user will see
"helloTHIS CODE IS BEING COUTED"
and they will be given a new line to input information.
What I want to do is instead of cout'ing, I would like to get the text in the current input, erase it from the input, cout the line that needs to be cout'ed, and then re-enter the info into the input.
Does this make sense or is this a bunch of jumbled nonsense?
Thanks for reading.
Edit: Clarification: I want it so if I have a string entered into my input and I cout, that the cout will be displayed above my input instead of inserting it past my input. I also want my input to be unaffected so the user can continue typing or delete what was already entered.
If you are getting the input character by character then when you need to output your text you could move the output position to the start of the line by printing carriage return, '\r'. Then your output will overwrite the current input, after which print a line feed and reprint what has been input so far
cout << "\r" << output << "\n" << currentinput;
If the output is shorter than the input then you will only partially overwrite the input, in which case you could pad the output with spaces up to the length of the current input
You may ask user in one, main thread with cin >> data there and read data from stdin in other thread by fread or something like that what works with FILE* handle.
After the data you want was typed by user you may clear screen (for example by clrscr() in conio.h or by any other better way) and cout what you want.
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.
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.