View mode: basic / threaded / horizontal-split · Log in · Help
September 26, 2012
read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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
Re: read single characters from stdin
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.
Top | Discussion index | About this forum | D home