2014-03-30 161 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),并启动新的迭代继续使用字符之前发出声音的字符。