2012-01-03 2 views
3

Так что я смотрел на D около 15 минут, поэтому неудивительно, что у меня есть вопросы, но что-то странное происходит для меня.Своеобразное поведение writef/writefln?

Я установил D из here и Visual D из here, и я запускаю все в Visual Studio 2010 Professional. D компилируются и запускаются, и отладчик работает нормально.

Проходя dsource.org's fundamental tutorials, я читал раздел Wait, когда я заметил, что если вы используете writef вместо writefln то последняя строка выходных отпечатков после паузы.

Вот код на примере в:

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"); 
} 

А вот моя, отметьте только изменение writefln к 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"); 
} 

С writef программа не будет отображаться на экране ничего, пауза в getch, затем, когда я нажимаю клавишу, я вижу приглашение:

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

, но NOT "(используя 'system (" pause ");'):". Родительский оператор появляется после нажатия клавиши, чтобы пройти через команду «пауза» в консоли. Если я использую writefln, он печатает, ждет, печатает обе строки, а затем ждет, как и следовало ожидать.

Что объясняет это поведение?

ответ

6

Использовать stdout.flush(); после любых звонков на номер write или writef. Эти последние вызовы не очищают буфер, поэтому вы видите это поведение. Btw getch не в std.c.stdio (по крайней мере, не в D2?), Это в CRT библиотеки DMC (в SNN.lib), и правильно его использовать вы бы прототип как 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"); 
} 

Но это а не межплатформенной совместимости из-за getch(). Если вы хотите использовать более удобный пользовательский механизм ввода, вы можете проверить библиотеку cmdln от Jesse: https://github.com/he-the-great/JPDLibs/tree/cmdln. У этого есть довольно прохладный интерфейс:

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

+1 для библиотеки 'cmdln'. Очень интересно. – You

+0

Можете ли вы подробно остановиться на строке 'extern'? Я удалил ненужный импорт, но код работает без «extern». –

+0

Какой компилятор вы используете? С 2.057 без прототипирования getch я получаю 'Error: undefined identifier getch, вы имели в виду функцию getc?' –

4

This thread on gmane.comp.lang.d.learn, как представляется, indicate, что writef только сбрасывает выход, когда он встречает новую строку. Поскольку writefln - это простой вызов writef с добавленной новой строкой, writefln всегда сбрасывает вывод. Весь текст после последней строки новой строки буферизуется до конца программы.

Смежные вопросы