Thread overview
read single characters from stdin
Sep 26, 2012
Thomas Koch
Sep 26, 2012
Adam D. Ruppe
Sep 28, 2012
1100110
Sep 26, 2012
Ali Çehreli
Sep 28, 2012
Thomas Koch
Sep 27, 2012
nazriel
Sep 28, 2012
Thomas Koch
Sep 28, 2012
nazriel
Sep 28, 2012
Jacob Carlborg
September 26, 2012
Hi,

to learn D, I'd like to write a simple type trainer. It should write a line to stdout and then read single characters from stdin and only accept the correct characters

How can I read single characters?

A similar question has been asked before without a working answer: http://forum.dlang.org/thread/jl79f7$2083$1@digitalmars.com

But I can't beliebe that there isn't a simple solution in D for this problem...

Regards, Thomas Koch
September 26, 2012
On Wednesday, 26 September 2012 at 17:51:03 UTC, Thomas Koch wrote:
> How can I read single characters?

The way I'd do it is with the C call fgetc(stdin). You can do it in D the same way if you import core.stdc.stdio;

But, if you are on Linux, it isn't going to be that simple. The Linux terminal/operating system will buffer input, not sending any data to you until the user presses enter.

You'll probably want to use a library like ncurses on linux... you can do without too, turning on raw mode to the terminal I think, but I don't remember how to do it right now. Are you on Linux or Windows?

(I'm pretty sure it just works on windows but it's been a while since I've done an app like this.)
September 26, 2012
On 09/26/2012 10:51 AM, Thomas Koch wrote:
> Hi,
>
> to learn D, I'd like to write a simple type trainer. It should write a line
> to stdout and then read single characters from stdin and only accept the
> correct characters
>
> How can I read single characters?
>
> A similar question has been asked before without a working answer:
> http://forum.dlang.org/thread/jl79f7$2083$1@digitalmars.com

Considering that stdin is a char stream and that there is no concept of a keyboard or a monitor in D (nor in C and nor in C++), I stand by my solution from that thread: :)

import std.stdio;

void main()
{
    while (!stdin.eof) {
        char code;
        readf("%s", &code);
        writefln("%u", code);
    }
}

Just remember that char is a UTF-8 code unit.

> But I can't beliebe that there isn't a simple solution in D for this
> problem...

This thread may have some answers:

  http://forum.dlang.org/thread/im8cnf$ioe$1@digitalmars.com?page=1

Ali

September 27, 2012
On Wednesday, 26 September 2012 at 17:51:03 UTC, Thomas Koch wrote:
> Hi,
>
> to learn D, I'd like to write a simple type trainer. It should write a line
> to stdout and then read single characters from stdin and only accept the
> correct characters
>
> How can I read single characters?
>
> A similar question has been asked before without a working answer:
> http://forum.dlang.org/thread/jl79f7$2083$1@digitalmars.com
>
> But I can't beliebe that there isn't a simple solution in D for this
> problem...
>
> Regards, Thomas Koch

http://dpaste.dzfl.pl/eb1387cc

;-)
September 28, 2012
nazriel wrote:
> http://dpaste.dzfl.pl/eb1387cc
Thank you. Your solution does not seem to work with multibyte characters, so I extended it:


import core.sys.posix.termios;
import core.stdc.stdio;

char getch()
{
        int ch;
        termios oldt;
        termios newt;

        tcgetattr(0, &oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(0, TCSANOW, &newt);
        ch = getchar();
        tcsetattr(0, TCSANOW, &oldt);

        return cast(char) ch;
}

import std.utf;

char readChar()
{
    char[4] buffer;

    buffer[0] = getch();
    auto len = stride(buffer,0);

    foreach (i ; 1 .. len)
        buffer[i] = getch();

    size_t i;
    return cast(char) decode(buffer, i);
}

September 28, 2012
Ali Çehreli wrote:
> Considering that stdin is a char stream and that there is no concept of a keyboard or a monitor in D (nor in C and nor in C++), I stand by my solution from that thread: :)
Thank you, especially for the link, but your proposal still requires to press enter.

Regards, Thomas Koch
September 28, 2012
On Friday, 28 September 2012 at 09:45:30 UTC, Thomas Koch wrote:
>
> nazriel wrote:
>> http://dpaste.dzfl.pl/eb1387cc
> Thank you. Your solution does not seem to work with multibyte characters, so
> I extended it:
>

Nice, I didn't need multibyte support as I was using it mainly for getting keycode

>
> import core.sys.posix.termios;
> import core.stdc.stdio;
>
> char getch()
> {
>         int ch;
>         termios oldt;
>         termios newt;
>
>         tcgetattr(0, &oldt);
>         newt = oldt;
>         newt.c_lflag &= ~(ICANON | ECHO);
>         tcsetattr(0, TCSANOW, &newt);
>         ch = getchar();
>         tcsetattr(0, TCSANOW, &oldt);
>
>         return cast(char) ch;
> }
>
> import std.utf;
>
> char readChar()
> {
>     char[4] buffer;
>
>     buffer[0] = getch();
>     auto len = stride(buffer,0);
>
>     foreach (i ; 1 .. len)
>         buffer[i] = getch();
>
>     size_t i;
>     return cast(char) decode(buffer, i);
> }

I think it should return dchar then, and cast(char) should be dropped otherwise you will lose visual representation of anything that is bigger than 8bits
September 28, 2012
On 2012-09-26 19:51, Thomas Koch wrote:
> Hi,
>
> to learn D, I'd like to write a simple type trainer. It should write a line
> to stdout and then read single characters from stdin and only accept the
> correct characters
>
> How can I read single characters?
>
> A similar question has been asked before without a working answer:
> http://forum.dlang.org/thread/jl79f7$2083$1@digitalmars.com

This works for me on Mac OS X:

http://forum.dlang.org/thread/jl79f7$2083$1@digitalmars.com?page=2#post-jlhn4d:241a5v:241:40digitalmars.com

-- 
/Jacob Carlborg
September 28, 2012
On Wed, 26 Sep 2012 13:06:03 -0500, Adam D. Ruppe <destructionator@gmail.com> wrote:

> On Wednesday, 26 September 2012 at 17:51:03 UTC, Thomas Koch wrote:
>> How can I read single characters?
>
> The way I'd do it is with the C call fgetc(stdin). You can do it in D the same way if you import core.stdc.stdio;
>
> But, if you are on Linux, it isn't going to be that simple. The Linux terminal/operating system will buffer input, not sending any data to you until the user presses enter.
>
> You'll probably want to use a library like ncurses on linux... you can do without too, turning on raw mode to the terminal I think, but I don't remember how to do it right now. Are you on Linux or Windows?
>
> (I'm pretty sure it just works on windows but it's been a while since I've done an app like this.)


ncurses will do it with getch().
pdpurses should have the same function.

You will most likely still have to ncurses setup and teardown though. shrug.