I'm using gcc 7.3 and g++ 7.3. GCC and G++ makes error. For example,
#include <stdio.h>
#include <unistd.h>
int main() {
printf("a");
sleep(1);
return 0;
}
'a' prints after waiting 1 seconds but when I use printf("a\n"); it works correctly. It's same on C++. For example,
#include <iostream>
#include <unistd.h>
int main() {
std::cout << "a";
sleep(1);
return 0;
}
'a' prints after waiting 1 seconds, too. However, when I use std::cout << "a" << std::endl; it works correctly. What's the problem and how to fix it?
sleep() is like schedule a process manually. printf() puts the data into stdout stream not directly on monitor.
printf("a"); /* data is there in stdout , not flushed */
sleep(1); /* as soon as sleep(1) statement occurs your process(a.out) jumped to waiting state, so data not gets printed on screen */
So either you should use fflush(stdout) or use \n to clear the stdout stream.
You are seeing this behaviour because stdout will be usually line buffered when used with terminal and fully buffered when used with files, the strings will be stored in a buffer and can be flushed by entering new line or when buffer fills or when program terminates
You can also override buffer mode by using setvbuf as below
setvbuf(stdout, NULL, _IONBUF, 1024);
printf("a");
It will print a without buffering, have a look at https://www.tutorialspoint.com/c_standard_library/c_function_setvbuf.htm for using setvbuf
Also have a look at different types of buffering with streams.
Hope this helps you.
Related
I've written a simple C++ program for tutorial purposes.
My goal is to loop it infinitely.
#include <iostream>
#include <string>
int main()
{
std::cout << "text";
for(;;) {
std::string string_object{};
std::getline(std::cin, string_object);
std::cout << string_object;
}
return 0;
}
After compilation I run it like this:
./bin 0>&1
What I expected to happen is that the "text" that is output to stdout, and it will now become also stdin for the program and it will loop forever. Why doesn't it happen?
First, you need to output newlines when printing to std::cout, otherwise std::getline() won't have any complete line to read.
Improved version:
#include <iostream>
#include <string>
int main()
{
std::cout << "stars" << std::endl;
for(;;) {
std::string string_object;
std::getline(std::cin, string_object);
std::cout << string_object << std::endl;
}
return 0;
}
Now try this:
./bin >file <file
you don't see any output, because it's going to the file. But if you stop the program and look at the file, behold, it's full of
stars
stars
stars
stars
:-)
Also, the reason that the feedback loop cannot start when you try
./bin 0>&1
is, that you end up with both stdin and stdout connected to /dev/tty
(meaning that you can see the output).
But a TTY device cannot ever close the loop, because it actually consists of two separate channels, one passing the output to the terminal, one passing the terminal input to the process.
If you use a regular file for in- and output, the loop can be closed. Every byte written to the file will be read from it as well, if the stdin of the process is connected to it. That's as long as no other process reads from the file simultaneously, because each byte in a stream can be only read once.
Since you're using gcc, I'm going to assume you have pipe available.
#include <cstring>
#include <iostream>
#include <unistd.h>
int main() {
char buffer[1024];
std::strcpy(buffer, "test");
int fd[2];
::pipe(fd);
::dup2(fd[1], STDOUT_FILENO);
::close(fd[1]);
::dup2(fd[0], STDIN_FILENO);
::close(fd[0]);
::write(STDOUT_FILENO, buffer, 4);
while(true) {
auto const read_bytes = ::read(STDIN_FILENO, buffer, 1024);
::write(STDOUT_FILENO, buffer, read_bytes);
#if 0
std::cerr.write(buffer, read_bytes);
std::cerr << "\n\tGot " << read_bytes << " bytes" << std::endl;
#endif
sleep(2);
}
return 0;
}
The #if 0 section can be enabled to get debugging. I couldn't get it to work with std::cout and std::cin directly, but somebody who knows more about the low-level stream code could probably tweak this.
Debug output:
$ ./io_loop
test
Got 4 bytes
test
Got 4 bytes
test
Got 4 bytes
test
Got 4 bytes
^C
Because the stdout and stdin don't create a loop. They may point to the same tty, but a tty is actually two separate channels, one for input and one for output, and they don't loop back into one another.
You can try creating a loop by running your program with its stdin connected to the read end of a pipe, and with its stdout to its write end. That will work with cat:
mkfifo fifo
{ echo text; strace cat; } <>fifo >fifo
...
read(0, "text\n", 131072) = 5
write(1, "text\n", 5) = 5
read(0, "text\n", 131072) = 5
write(1, "text\n", 5) = 5
...
But not with your program. That's because your program is trying to read lines, but its writes are not terminated by a newline. Fixing that and also printing the read line to stderr (so we don't have to use strace to demonstrate that anything happens in your program), we get:
#include <iostream>
#include <string>
int main()
{
std::cout << "text" << std::endl;
for(;;) {
std::string string_object{};
std::getline(std::cin, string_object);
std::cerr << string_object << std::endl;
std::cout << string_object << std::endl;
}
}
g++ foo.cc -o foo
mkfifo fifo; ./foo <>fifo >fifo
text
text
text
...
Note: the <>fifo way of opening a named pipe (fifo) was used in order to open both its read and its write end at once and so avoid blocking. Instead of reopening the fifo from its path, the stdout could simply be dup'ed from the stdin (prog <>fifo >&0) or the fifo could be first opened as a different file descriptor, and then the stdin and stdout could be opened without blocking, the first in read-only mode and the second in write-only mode (prog 3<>fifo <fifo >fifo 3>&-).
They will all work the same with the example at hand. On Linux, :|prog >/dev/fd/0 (and echo text | strace cat >/dev/fd/0) would also work -- without having to create a named pipe with mkfifo.
#include <iostream>
#include <stdio.h>
int main () {
std::ios::sync_with_stdio(false);
std::cout << "hi from c++\n";
printf("hi from c\n");
return 0;
}
After removing std::endl and putting \n instead in cout statement the output changed to the following:
hi from c
hi from c++
It's a buffering issue.
By default when standard output is connected to a terminal, stdout is line-buffered meaning the buffer is flushed and output actually written to the terminal on newline.
When C stdio is disconnected from the C++ standard streams, std::cout is fully buffered, meaning output is actually written when either explicitly flushed (using e.g. std::flush or std::endl manipulators) or if the buffer is full.
The two buffers used by C stdout and C++ std::cout are different and not connected.
Flushing of the buffers also happens when the program exits.
What happens in your program is that the output with printf is flushed immediately because of the trailing newline in the string. But the output to std::cout is only flushed when the program exits.
I am learning about iostream objects and flushing the buffer. I know when output buffers are guaranteed to be flushed and how to explicitly flush the buffer. However, I have never seen a case where output buffer is not flushed. It seems to me that output buffer gets flushed at the end of each statement even if I don't use manipulators such as endl, flush and ends.
So, is there any simple example(s) where the output buffer will not ( or at least, might often not) get flushed? I feel like I need to see such a case to really understand output buffers.
Depends on the system.
Take the following program as an example:
#include <iostream>
#ifdef WIN32
#include <windows.h>
#define sleep(n) Sleep((n)*1000)
#else
#include <unistd.h>
#endif
using namespace std;
int main()
{
cout << "This is line 1";
sleep(4);
cout << endl;
cout << "This is line 2" << endl;
return 0;
}
By inspecting the program, you might surmise that the program would print This is line 1, followed by pausing for 4 seconds, then printing This is line 2.
And if you compile with Visual Studio to run on Windows, you'll get that exact behavior.
On Linux and other Unix operating systems however, the program will appear to be silent for 4 seconds before printing out both lines together. The output won't reliably flush until a new line character is encountered in the output stream.
I want to do some realtime-plots during a simulation. For this, i would like to use octave or gnuplot. My current approach is to use a frontend to gnuplot, feedgnuplot, which fits actually very well.
The Simulation is written in C++, so i thought about forking (new process for feedgnuplot) and piping the relevant data to feedgnuplot.
The problem i have is that the output is only visible after the simulation.
But i want to see the plot updated during simulation.
Here is a MWE:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
int main()
{
FILE* stream = popen("feedgnuplot", "w");
for(int i = 0; i < 10; ++i)
{
fprintf(stream, "%d\n", i * i);
fflush(stream);
sleep(1);
}
}
The program stops after 10 secons, showing the plot.
When using feedgnuplot directly in the shell, everything works as expected.
(That is, newly added data is plotted without the need to end the process)
What am i doing wrong? I think i lack some understanding of how popen really works.
First, let's write a fake feedgnuplot.c:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buf = NULL;
size_t n = 0;
while (getline (&buf, &n, stdin) != -1) {
printf ("%s", buf);
}
free (buf);
return 0;
}
With this, your code works, i.e. the lines are printed as they arrive.
I suspect the problem lies in the way your feedgnuplot program reads incoming data. You should show the relevant part of that code.
If I had to take a guess, you probably need to add
setvbuf (stdin, NULL, _IOLBF, 0);
in feedgnuplot before you start to read from stdin.
That is because by default, when stdin corresponds to a terminal it is line buffered, whereas when it corresponds to a pipe it is fully buffered. The code above makes stdin line buffered no matter what so there should be no difference between reading from a terminal or a pipe.
Say I have an .exe, lets say sum.exe. Now say the code for sum.exe is
void main ()
{
int a,b;
scanf ("%d%d", &a, &b);
printf ("%d", a+b);
}
I wanted to know how I could run this program from another c/c++ program and pass input via stdin like they do in online compiler sites like ideone where I type the code in and provide the stdin data in a textbox and that data is accepted by the program using scanf or cin. Also, I wanted to know if there was any way to read the output of this program from the original program that started it.
The easiest way I know for doing this is by using the popen() function. It works in Windows and UNIX. On the other way, popen() only allows unidirectional communication.
For example, to pass information to sum.exe (although you won't be able to read back the result), you can do this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f;
f = popen ("sum.exe", "w");
if (!f)
{
perror ("popen");
exit(1);
}
printf ("Sending 3 and 4 to sum.exe...\n");
fprintf (f, "%d\n%d\n", 3, 4);
pclose (f);
return 0;
}
In C on platforms whose name end with X (i.e. not Windows), the key components are:
pipe - Returns a pair of file descriptors, so that what's written to one can be read from the other.
fork - Forks the process to two, both keep running the same code.
dup2 - Renumbers file descriptors. With this, you can take one end of a pipe and turn it into stdin or stdout.
exec - Stop running the current program, start running another, in the same process.
Combine them all, and you can get what you asked for.
This is my solution and it worked:
sum.cpp
#include "stdio.h"
int main (){
int a,b;
scanf ("%d%d", &a, &b);
printf ("%d", a+b);
return 0;
}
test.cpp
#include <stdio.h>
#include <stdlib.h>
int main(){
system("./sum.exe < data.txt");
return 0;
}
data.txt
3 4
Try this solution :)
How to do so is platform dependent.
Under windows, Use CreatePipe and CreateProcess. You can find example from MSDN :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
Under Linux/Unix, you can use dup() / dup2()
One simple way to do so is to use a Terminal (like command prompt in windows) and use | to redirect input/output.
Example:
program1 | program2
This will redirect program1's output to program2's input.
To retrieve/input date, you can use temporary files, If you don't want to use temporary files, you will have to use pipe.
For Windows, (use command prompt):
program1 <input >output
For Linux, you can use tee utility, you can find detail instruction by typing man tee in linux terminal
It sounds like you're coming from a Windows environment, so this might not be the answer you are looking for, but from the command line you can use the pipe redirection operator '|' to redirect the stdout of one program to the stdin of another. http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true
You're probably better off working in a bash shell, which you can get on Windows with cygwin http://cygwin.com/
Also, your example looks like a mix of C++ and C, and the declaration of main isn't exactly an accepted standard for either.
How to do this (you have to check for errors ie. pipe()==-1, dup()!=0, etc, I'm not doing this in the following snippet).
This code runs your program "sum", writes "2 3" to it, and than reads sum's output. Next, it writes the output on the stdout.
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int parent_to_child[2], child_to_parent[2];
pipe(parent_to_child);
pipe(child_to_parent);
char name[] = "sum";
char *args[] = {name, NULL};
switch (fork()) {
case 0:
// replace stdin with reading from parent
close(fileno(stdin));
dup(parent_to_child[0]);
close(parent_to_child[0]);
// replace stdout with writing to parent
close(fileno(stdout));
dup(child_to_parent[1]);
close(child_to_parent[1]);
close(parent_to_child[1]); // dont write on this pipe
close(child_to_parent[0]); // dont read from this pipe
execvp("./sum", args);
break;
default:
char msg[] = "2 3\n";
close(parent_to_child[0]); // dont read from this pipe
close(child_to_parent[1]); // dont write on this pipe
write(parent_to_child[1], msg, sizeof(msg));
close(parent_to_child[1]);
char res[64];
wait(0);
read(child_to_parent[0], res, 64);
printf("%s", res);
exit(0);
}
}
I'm doing what #ugoren suggested in their answer:
Create two pipes for communication between processes
Fork
Replace stdin, and stdout with pipes' ends using dup
Send the data through the pipe
Based on a few answers posted above and various tutorials/manuals, I just did this in Linux using pipe() and shell redirection. The strategy is to first create a pipe, call another program and redirect the output of the callee from stdout to one end of the pipe, and then read the other end of the pipe. As long as the callee writes to stdout there's no need to modify it.
In my application, I needed to read a math expression input from the user, call a standalone calculator and retrieve its answer. Here's my simplified solution to demonstrate the redirection:
#include <string>
#include <unistd.h>
#include <sstream>
#include <iostream>
// this function is used to wait on the pipe input and clear input buffer after each read
std::string pipeRead(int fd) {
char data[100];
ssize_t size = 0;
while (size == 0) {
size = read(fd, data, 100);
}
std::string ret = data;
return ret;
}
int main() {
// create pipe
int calculatorPipe[2];
if(pipe(calculatorPipe) < 0) {
exit(1);
}
std::string answer = "";
std::stringstream call;
// redirect calculator's output from stdout to one end of the pipe and execute
// e.g. ./myCalculator 1+1 >&8
call << "./myCalculator 1+1 >&" << calculatorPipe[1];
system(call.str().c_str());
// now read the other end of the pipe
answer = pipeRead(calculatorPipe[0]);
std::cout << "pipe data " << answer << "\n";
return 0;
}
Obviously there are other solutions out there but this is what I can think of without modifying the callee program. Things might be different in Windows though.
Some useful links:
https://www.geeksforgeeks.org/pipe-system-call/
https://www.gnu.org/software/bash/manual/html_node/Redirections.html