2017-07-19 18 views
0

我想知道如何在程序讀取不合適的值後繼續在D中使用stdin。 (例如,字母,當它被期待一個int) 我寫這個測試它:如何在D readf中輸入錯誤類型後讀取輸入?

import std.stdio; 


void main() 
{ 
    int a; 
    for(;;){ 
     try{ 
      stdin.readf(" %s", a); 
      break; 
     }catch(Exception e){ 
      writeln(e); 
      writeln("Please enter a number."); 
     } 
    } 
    writeln(a); 
} 

輸入不正確的值,如「B」之後,程序將打印出消息indefinitly。我還檢查這表明它試圖再次讀取相同的字符異常,所以我做了一個版本是這樣的:

import std.stdio; 


void main() 
{ 
    int a; 
    for(;;){ 
     try{ 
      stdin.readf(" %s", a); 
      break; 
     }catch(Exception e){ 
      writeln(e); 
      writeln("Please enter a number."); 
      char c; 
      readf("%c", c); 
     } 
    } 
    writeln(a); 
} 

嘗試讀取時仍然拋出一個異常,但不是C。我也試過使用stdin.clearerr(),它沒有任何作用。有誰知道如何解決這個問題?謝謝。

回答

2

我的推薦:不要用readf。它太糟糕了。每個人一開始都會去stdlib(自從1979年以來,大聲笑,以及scanf已經......並且我認爲scanf比readf更好!但我離題了),幾乎每個人都遇到了麻煩。在正確的格式和空白消費方面真的很挑剔,當它出錯時,它會給出糟糕的錯誤消息,並使輸入流保持不確定狀態。而且,最重要的是,它實際上可以讀取的數據類型仍然非常有限,並且對用戶不友好,甚至不允許在大多數系統上進行退出等工作。

稍差不如readf是使用readln然後stripto!int它一旦你檢查線路並給出錯誤。事情是這樣的:

import std.stdio; 
import std.string; // for strip, cuts off whitespace 
import std.algorithm.searching; // for all 
import std.ascii; // for isAscii 
import std.conv; // for to, does string to other type conversions 

int readInt() { 
     for(;;) { 
       string line = stdin.readln(); 
       line = line.strip(); 
       if(all!isDigit(line)) 
         return to!int(line); 
       else 
         writeln("Please enter a number"); 
     } 
     assert(0); 
} 


void main() 
{ 
    int a = readInt(); 
    writeln(a); 
} 

我知道這是一個很大的進口垃圾郵件(和一堆個人瑣碎的功能太),和readln仍然很爛爲最終用戶,但這個小功能將是這麼多比嘗試使用readf更好的用戶和自己。它會一直消耗一條線,並給出一個很好的消息。此外,相同的模式可以擴展到您需要的任何其他類型的驗證,並且readln的調用可以通過調用更方便用戶的功能來取代,該功能允許編輯和歷史記錄,以及稍後如果您決定停用路線。


如果必須使用readf但無論如何,讓事情在你的catch塊再理智的最簡單的方法仍然只是調用readln並丟棄其結果。那麼它只是跳過包含錯誤的整行,讓您的用戶重新開始。如果他們正在做「1 2」,並且希望同時讀兩個整數,那麼它也會下降......但是,我寧願讓它們開始新鮮,而不是嘗試在中途拾取錯誤的線。