[racket] Does read-char have an extra character in the stream on Windows?

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Feb 15 10:29:26 EST 2014

When you type Enter in a Windows console, Racket recieves a carriage
return character, #\return, followed by a linefeed character,
#\newline, in its input stream.

To read a line of input, probably you want `(read-line 'any)`, which
handles whatever kind of line separator comes in: LF or CRLF.

At Sat, 15 Feb 2014 07:50:07 +0900, 亀田馬志 wrote:
> Hello.
> 
> I wrote a tiny and silly joking program as below.
> 
> ;;;;;;;;;;;;;;;;;;
> 
> #lang racket
> 
> (require srfi/48)
> 
> ;;;;; Data
> 
> (define *script*
>   #hasheq((intro . "Let me help to show you the age of marrage to be happy,
> Lady!~%~%1. You need only one input later.~%2. If you'd like to step
> forward, just hit the Enter/Return key.~%~%Do you want to play? [y/n]")
>           (first-step . "~%At first, please call a two-digit number
> whichever you like in your mind.~%Then please hit the Enter/Return key~%~%")
>           (second-step . "Please add the one's digit and the ten's digit in
> your mind.~%Then please hit the Enter/Return key.~%~%")
>           (question . "Is the number still a two-digit number? [y/n] ")
>           (third-step . "~%Next, please multiply the answer you've just got
> by 9 in your mind.~%Then please hit the Enter/Return key.~%~%")
>           (forth-step . "Now, Please add the one's digit and the ten's
> digit of the answer you've just got in your mind.~%Then please hit the
> Enter/Return key.~%~%")
>           (fifth-step . "At last, please add the number of guys you've
> slept with to the answer you've just got in your mind.~%Then please input
> the answer you've got below.~%==> ")
>           (conclusion . "~%You'd better get married when you are ~a years
> old to have a happy life,~%and that implies you've slept with ~a ~a
> ~a.~%~%")
>           (only . "only")
>           (nothing . "")
>           (man . "man")
>           (men . "men")
>           (play-again? . "Play again?")))
> 
> ;;;;; Environment
> 
> (define *env* (hasheq 'phase #f 'messages *script*))
> 
> ;;;;; Read
> 
> (define (y-or-n?)
>   (let ((i (read)))
>     (let ((sym (string->symbol (string-upcase (substring (symbol->string i)
> 0 1)))))
>       (case sym
>         ((Y) #t)
>         ((N) #f)
>         (else (raise 'not-yes-nor-no))))))
> 
> (define (parser x env)
>   (case (hash-ref env 'phase)
>     ((intro question play-again?) (values (y-or-n?) env))
>     ((fifth-step) (let ((i (read)))
>                     (values (if (integer? i)
>                                 i
>                                 (raise 'input-error)) env)))
>     ((first-step
>       second-step
>       third-step
>       forth-step) (read-char) (values x env))  ;;; THIS PART DOESN'T WORK
> PROPERLY!
>     (else (values x env))))
> 
> ;;;;; Eval
> 
> (define (interp x env)
>   (case (hash-ref env 'phase)
>     ((intro play-again?) (if x
>                              (values x (hash-set env 'phase 'first-step))
>                              (exit)))
>     ((first-step) (values x (hash-set env 'phase 'second-step)))
>     ((second-step) (values x (hash-set env 'phase 'question)))
>     ((question) (values x (hash-set env 'phase (if x
>                                                    'second-step
>                                                    'third-step))))
>     ((third-step) (values x (hash-set env 'phase 'forth-step)))
>     ((forth-step) (values x (hash-set env 'phase 'fifth-step)))
>     ((fifth-step) (values (- x 9) (hash-set env 'phase 'conclusion)))
>     ((conclusion) (values x (hash-set env 'phase 'play-again?)))
>     (else (values x (hash-set env 'phase 'intro)))))
> 
> ;;;;; Print
> 
> (define (print x env)
>   (let ((c (hash-ref env 'phase))
>         (s (hash-ref env 'messages)))
>     (case c
>       ((intro
>         first-step
>         second-step
>         question
>         third-step
>         forth-step
>         fifth-step
>         play-again?) (format #t (hash-ref s c)))
>       ((conclusion) (format #t
>                             (hash-ref s c)
>                             (+ x 9)
>                             (hash-ref s (if (< x 2)
>                                             'only
>                                             'nothing))
>                             x
>                             (hash-ref s (if (< x 2)
>                                             'man
>                                             'men))))))
>   (flush-output)
>   (values x env))
> 
> ;;;;; REPL
> 
> (define (main x env)
>   (let-values (((x env) (parser x env)))
>     (let-values (((x env) (interp x env)))
>       (let-values (((x env) (print x env)))
>         (main x env)))))
> 
>  (main #f *env*)
> 
> ;;;;;;;;;;;;;;;;;;;;;; THE END OF PROGRAM
> 
> I would like to implement something like "HIT ENTER TO CONTINUE", and I
> used read-char for it; however it doesn't work as I wished.
> It seems like when I hit the enter key, it keeps having something other
> than #\newline in the stream, and two messages of data are shown at once.
> This is not what I mean.
> 
> I tried using charterm, but as implied, it does not work on Windows and
> says ttf; therefore I gave up using the library on Windows.
> 
> Is there any good idea to implement "HIT ENTER TO CONTINUE"?
> 
> By the way, I'm using Windows 7 and Racket V.5.93.
> 
> Thanx.
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users


Posted on the users mailing list.