2

I've just stepped into the world of competitive programming and therefore, was reading few articles to grasp the best strategies a programmer should follow while writing code in c++. I read somewhere that one should use '\n' in lieu of std::endl at the end of the line because std::endl forces the buffer to flush.

I didn't know what 'flushing of buffer' meant so I started searching for it and came across this answer What does flushing the buffer mean? After reading the answer the idea that I got 'flushing the buffer' was to print & wipe out everything in the output buffer to the console.

So, to check the validity of the answer I made this program on my machine.

#include <iostream>
#include <time.h>
using namespace std;
int main()
{
    struct timespec tim, tim2;
    tim.tv_sec = 3;
    tim.tv_nsec = 0;    
    for(int i=0; i<5; i++)
    {
        cout << i << endl;
        nanosleep(&tim , &tim2);    
    }
   return 0;
}

The results I got on executing the program came as expected. The loop printed 0 to 4 with a delay of 3 seconds after each iteration.

However, when I changed endl to '\n' I was expecting the results to show on the console all at once after 15 seconds. But, the digits got outputted after the same delay it got outputted in the previous case. Now, if '\n' doesn't flush the output buffer, shouldn't I've got the results as I was expecting?

Kartik Chauhan
  • 2,779
  • 5
  • 28
  • 39
  • 5
    btw "competitive programming" and "best strategies a programmer should follow" are quite unrelated. Competetive programming rather pushes you towards using strategies that no sane programmer would use in real code – 463035818_is_not_an_ai Nov 01 '17 at 10:55
  • Try the same using a file as output. – tkausl Nov 01 '17 at 10:56

2 Answers2

3

std::endl forces a flush of the stream. This does not mean that no flush will happen without it.

In general, the standard library will flush std::cout (and, yes, other streams are treated differently) even if the output buffers are not full if std::cout points to a tty and the buffers ends with \n. In your second case, that is precisely what's happening.

If you want to see your code working as you expect it, try redirecting the output to a file (and then watch the file with tail -f). That will cause the standard output not to be a tty, and thus not cause a flush on \n.

Also, IIRC, std::cerr is flushed on \n whether it is a TTY or not. If you write to a file, it should never flush unless you explicitly flush (e.g., with std::endl).

Edited to add

I couldn't get it to work with either stderr or stdout, but the following does print all numbers at the end:

#include <iostream>
#include <fstream>
#include <time.h>

using namespace std;
int main()
{
    struct timespec tim, tim2;
    tim.tv_sec = 3;
    tim.tv_nsec = 0;    
    ofstream out("output");
    for(int i=0; i<5; i++)
    {
        out << i << "\n";
        nanosleep(&tim , &tim2);    
    }
   return 0;
}
Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57
  • Tried tail -f but got the same result in both the cases, wiz. 0 1 2 3 4 – Kartik Chauhan Nov 01 '17 at 11:17
  • Edited the answer. It appears stdout and stderr are flush on newline (or, at the very least, have different criteria as for when they are not). A regular file, however, will behave as stated. – Shachar Shemesh Nov 01 '17 at 11:46
2

You dont have full control over when the buffer is flushed. Some systems flush it when you insert a \n into the stream, others dont.

Just because flush does flush the stream it does not mean that not calling flush will cause the stream to not flush.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185