3

I tried to read string from an input-port in Racket, but no matter what API functions I used to read (read, read-string, read-bytes etc), the return value of those functions was never equal eof-object.

(define (some_process inp)
 (begin
    (let ([c (read-string 1 inp)])
      (if (eof-object? c)
          (begin
            (display "EOF \n")
            #f)
          (if (equal? c "\n")
              (begin 
                (display "NEWLINE \n"))
              (some_process inp))))))

The c can never be an eof-object?

If you display what c is, it is always a newline.

YasirA
  • 9,531
  • 2
  • 40
  • 61

2 Answers2

4

Read reference:

  • read-char: "Reads a single character from in – which may involve reading several bytes to UTF-8-decode them into a character. If no bytes are available before an end-of-file, then eof is returned."

  • read-string: "Returns a string containing the next amt characters from in. If no characters are available before an end-of-file, then eof is returned."

Examples:

> (read-char (open-input-string "char"))
#\c
> (read-string 50 (open-input-string "the string"))
"the string"
> 

But if there are no character(s) in the buffer, you'll get eof:

> (read-char (open-input-string ""))
#<eof>
> (read-string 50 (open-input-string ""))
#<eof>

I think you just want to read some amount of characters in a loop and do something with them. If so, the solution would look something along the lines of:

(define (another-process inp)
  (let ([c (read-char inp)])
    (if (eof-object? c)
        (begin (display "==== EOF ====") (newline))
        (begin (display c) (newline)
               (another-process inp)))))

Example:

> (another-process (open-input-string "OK"))
O
K
==== EOF ====
> (another-process (open-input-string ""))
==== EOF ====
>

Notice a second call to another-process with an empty line, it detects eof immediately and exits the loop.

EDIT: In case you need to check if the read character is newline:

(define (process-moo inp)
  (let ([c (read-char inp)])
    (cond
      ((eof-object? c)
       (display "==== EOF ====") (newline))
      ((eq? c #\newline)
       (newline) (display "---- NEWLINE ----") (newline)
       (process-moo inp))
      (else
       (display c)
       (process-moo inp)))))

Example:

> (call-with-input-string "Hello\nhumans\n!" process-moo)
Hello
---- NEWLINE ----
humans
---- NEWLINE ----
!==== EOF ====
> 

Hope that helps.

YasirA
  • 9,531
  • 2
  • 40
  • 61
  • BTW, `(another-process (open-input-string "OK"))` is the same as `(call-with-input-string "OK" another-process)`. – YasirA Feb 02 '11 at 17:39
  • Thanks Yasir~ it is very helpful. Basically, I want to parse a comment in a file. If the comment is in the end of the line of file, I will not give a newline, but if it is in the middle of a file, e.g. after some code, then I have to emit a newline, so I have a eat-comment process, to eat the comment, but in the process, I need to check whether it ends with a newline, or the comment is just at the last line of the file. But when I test like my previous coding listed, the code will not execute the eof-object path, but the newline path...... –  Feb 02 '11 at 18:15
1

If you are entering your input from the console, try pressing Ctrl+D (in Unix and MacOSX), or Ctrl+Z, then Enter (in Windows). This will signal the end of the input.

YasirA
  • 9,531
  • 2
  • 40
  • 61
C. K. Young
  • 219,335
  • 46
  • 382
  • 435