Search code examples
c++treebinary-tree

fstream doesn't write on file until endl


I'm trying to define this inline function. It would create a decision tree (a particoular binary tree used in operations research).

This is the code:

inline void printTreeFile(int* i_node,int* j_node,int* q_infr,int* value,int nStart,int level,std::fstream& tree)
{       int spazi=0,len,stop;   
        for(int actual_level=0;actual_level<level;actual_level++)
            {spazi+=9;
            if(i_node[actual_level]==0)
                len=1;
            else
                len=(int)log10(i_node[actual_level])+1;
            spazi+=len;
            if(j_node[actual_level]==0)
                len=1;
            else
                len=(int)log10(j_node[actual_level])+1;
            spazi+=len;
            if(q_infr[actual_level]==0)
                len=1;
            else
                len=(int)log10(q_infr[actual_level])+1;
            spazi+=len;
            }
        if(value[level]==0)
            {
            tree<<"-->("<<i_node[level]<<","<<j_node[level]<<","<<q_infr[level]<<"=1)";
            tree<<endl;
            for(int i=0;i<spazi;i++)
                tree<<" ";
            tree<<"-->("<<i_node[level]<<","<<j_node[level]<<","<<q_infr[level]<<"=0)";
            }
        else
            tree<<"-->("<<i_node[level]<<","<<j_node[level]<<","<<q_infr[level]<<"=1)";
        //cin>>stop;
}

The std::fstream& tree is defined in main as:

fstream tree;                       
remove("tree");
tree.open("tree",ios::out|ios::app);

I don't understand why the file tree is empty until is executed the command tree<<endl;

I need to see how the tree evolve itself without waiting for that command...anyone know a solution to this problem? thanks to all that will answer!


Solution

  • The endl both outputs a newline and forces a buffer flush, which is why you're seeing it at that point.

    File streams, unless you modify their properties, are fully buffered so you won't see anything until the buffer is full or you explicitly flush it.

    This can be done with an endl (assuming you want a newline sent first), via ostream::flush, or when closing the file.

    Probably the easiest fix is to add tree.flush(); as the last line in your function.


    And, as an aside given the commonality of some of those lines, I'd considering refactoring it to make it more readable, first a helper function:

    inline void outLine(std::fstream& tree, int *inode,
        int *jnode, int *qinfr, int level, int val)
    {
        tree << "-->(" << i_node[level] << "," << j_node[level]
            << "," << q_infr[level] << "=" << val << ")";
    }
    

    Then calling that helper function, which makes the code a little cleaner (includes using string constructor to get rid of loop):

    if (value[level] == 0) {
        outLine (tree, i_node, j_node, q_infr, level, 1);
        tree << '\n' << std::string(spazi, ' ');
        outLine (tree, i_node, j_node, q_infr, level, 0);
    } else {
        outLine (tree, i_node, j_node, q_infr, level, 1);
    }
    tree.flush();
    

    Keep in mind the reason why files tend to be fully buffered while standard output is line buffered. Most files you don't care about until the job is done so full buffering is more efficient.

    That's obviously not the case in this scenario but flushing more often than necessary will generally slow your code down.

    If, as you say, this is just debug code, you can forget about refactoring or the speed penalty of unnecessary flushing.