2014-03-30 155 views
1

我必須學習Scheme的基礎來完成一個項目,但是我在構造while循環的等價物時遇到了一些困難。例如,在下面的代碼中,我想讓用戶輸入一個字符。如果字符是x,我想跳出循環。如果是任何其他字符,則會顯示該字符,循環將繼續進行下一次迭代。「While」循環在Scheme中跳過迭代

(define getUserChar (lambda() 
(define ch) 
    (let loop() 
    (display "Enter character: ") 
    (set! ch (read-char)) 
    (if (not (char=? ch #\x)) 
     (begin 
     (display choice) 
     (loop) 
))))) 

這在技術上是可行的,但它會跳過迭代。例如:

Enter character: a 
Enter character: 
Enter character: s 

我在第二次迭代期間無法輸入字符。我似乎無法找出問題所在。任何幫助非常感謝。

回答

3

問題是,你實際上正在閱讀兩個個字符。你輸入的那個,加上換行符。我試圖從原始的解決方案保留儘可能多的,這就是我想出了:

(define getUserChar 
    (lambda() 
    (define ch #\0) 
    (let loop() 
     (display "Enter character: ") 
     (set! ch (string-ref (read-line) 0)) 
     (if (not (char=? ch #\x)) 
      (begin 
      (display ch) 
      (newline) 
      (loop)))))) 

恕我直言,更地道的解決方案並不需要一個變異操作,我更喜歡這一個:

(define (getUserChar) 
    (let loop ((ch #\0)) 
    (unless (char=? ch #\x) 
     (display "Enter character: ") 
     (let ((ch (string-ref (read-line) 0))) 
     (display ch) 
     (newline) 
     (loop ch))))) 
+0

在閱讀輸入時,我總是忘記那個細節。非常感謝您的幫助。 – Rob

+0

@Robbeh我的榮幸!我用更習慣的解決方案更新了我的答案;) –

2

這是與事實,你是在循環的第一個迭代中輸入兩個字符,即"a\n""a~n")做這使得第二次迭代只取#\NewLine你一起#\a輸入爲字符。

如果你想利用一整行同時你get-line(R6RS)或read-line(R7RS)代替或看buffer-mode(R6RS),並啓動新的迭代繼續使用字符之前發出聲音的字符。