Corey Ogburn
Corey Ogburn

Reputation: 24739

Peculiar writef/writefln behavior?

So I've been looking at D for about 15 mins, so it's no wonder I have questions, but something strange is happening for me.

I installed D from here and Visual D from here and I'm running everything in Visual Studio 2010 Professional. D examples compile and run and the debugger appears to be working fine.

While going through dsource.org's fundamental tutorials, I was reading the Wait section when I noticed that if you use writef instead of writefln then the last line of the output prints after the pause.

Here's the example's code:

import std.c.stdio; /* for getch() */
import std.process; /* for system() */
import std.stdio; /* for writefln */

void main() { 
    writefln("Press a key (using 'std.c.stdio.getch();' to wait) . . .");
    getch();

    writefln("Waiting again\n(using 'system(\"pause\");'):");
    system("pause");
}

And here's mine, note the only change is writefln to writef

import std.c.stdio; /* for getch() */
import std.process; /* for system() */
import std.stdio; /* for writefln */

void main() { 
    writef("Press a key (using 'std.c.stdio.getch();' to wait) . . .");
    getch();

    writef("Waiting again\n(using 'system(\"pause\");'):");
    system("pause");
}

With writef the program will display nothing on the screen, pause at getch, then when I press a key I see the prompt:

Press a key (using 'std.c.stdio.getch();' to wait) . . .Waiting again
Press any key to continue . . . 

but NOT "(using 'system("pause");'):". The parenthetic statement appears after I press a key to get through the 'pause' command in the console. If I use writefln it prints, waits, prints both lines, then waits again as you'd expect.

What explains this behavior?

Upvotes: 3

Views: 261

Answers (2)

Andrej Mitrović
Andrej Mitrović

Reputation: 3342

Use stdout.flush(); after any calls to write or writef. These latter calls don't flush the buffer, which is why you're seeing this behavior. Btw getch is not in std.c.stdio (at least not in D2?), it's in DMC's CRT library (SNN.lib), and to properly use it you would have to prototype it as extern (C) int getch();:

extern (C) int getch();
import std.process; /* for system() */
import std.stdio; /* for writefln */

void main() { 
    writef("Press a key (using 'std.c.stdio.getch();' to wait) . . .");
    stdout.flush();
    getch();

    writef("Waiting again\n(using 'system(\"pause\");'):");
    stdout.flush();
    system("pause");
}

But this is not cross-platform compatible due to getch(). If you want to use a nicer user-input facility you can check out Jesse's cmdln library: https://github.com/he-the-great/JPDLibs/tree/cmdln. It has a rather cool interface:

auto num = require!(int, "a > 0 && a <= 10")("Enter a number from 1 to 10");

Upvotes: 6

You
You

Reputation: 23814

This thread on gmane.comp.lang.d.learn seems to indicate that writef only flushes the output when it encounters a newline. Since writefln is a simple call to writef with a newline appended, writefln always flushes the output. All text after the last newline is buffered until the end of the program.

Upvotes: 4

Related Questions