Search code examples
dphobos

Reading a single character from stdin in D


The documentation for std.stdio does not list a read function which could be used to get a single character from standard input, only readln to get a line. std.file has read function, but it needs a file name, which is not available for the standard input as far as I know.

How do I read a single character from stdin?


Solution

  • A few options, depending on just what you need:

    If you just want a character for programming purposes but don't mind it being line buffered:

    • Use rawRead or byChunk to buffer a block of it (stdin is an instance of std.stdio.File so all methods from that http://dlang.org/phobos/std_stdio.html area available for it too) and read one item off that array at a time.

    • Use the C function fgetc by import core.stdc.stdio; and using the C stdin instead of the D wrapper. They are both compatible with each other so reading from one won't mess up the buffering of the other.

    • Use the readf function to grab one piece of data at a time.

    All those options will work for your program, but you'll notice the user will still have to press enter before the program does anything because the underlying input stream is buffered to one complete line at a time. That can be changed too:

    If you want one key immediately, for things like interactive sessions with the user:

    • See CyberShadow's link in the comment

    • Disable line buffering with an operating system call. It is tcsetattr on Posix and SetConsoleMode on Windows - search the web for details on how to disable line buffering in C, and the same code can be fairly easily translated to D. Also see the source to my terminal.d which does it: https://github.com/adamdruppe/arsd/blob/master/terminal.d#L1078

    • Just use a library, like my terminal.d, which provides a struct to change the buffering mode for you and functions like getch and kbhit, similar to the old conio.h in the link. Here's an example file: http://arsdnet.net/dcode/book/chapter_12/07/input.d which shows a simple "press any key to continue" example.

    • Use a more featured C library like ncurses from D. http://code.dlang.org/packages/ncurses If you've ever used it from C, it is pretty much the same.