2009-08-27 111 views
3

我有三個變量聲明爲雙打:檢查輸入爲空時,輸入被聲明爲雙[C++]

double Delay1 = 0; 
double Delay2 = 0; 
double Delay3 = 0; 

我再從用戶那裏得到他們的價值觀:

cout << "Please Enter Propogation Delay for Satellite #1:"; 
cin >> Delay1; 
... 

但是,當我檢查這些值,看看它們是空(用戶只需點擊進入,並沒有把數字)它不工作:

if(Delay1 || Delay2 || Delay3 == NULL) 
     print errror... 

氏每次都在運行。
什麼是正確的方法來檢查是否已被宣佈爲雙重輸入是空白的?

回答

11

喜歡的東西

cin >> Delay1; 
if(cin) { ... } 

不會根據您的規格工作,因爲cin會跳過前導空白。用戶不能僅僅輸入。他首先必須輸入一些文字。如果他進入以下

3a 

然後輸入被讀入雙,上漲到a,並停止。 cin將不會發現任何錯誤,並將a留在流中。通常,這是足夠的錯誤處理,我想。但是如果需要在用戶輸入類似上面的內容時實際重複,則需要更多代碼。

如果你想測試整個輸入到新行是否是一個數字,那麼你應該使用getline,讀入一個字符串,然後嘗試轉換爲數字

string delay; 
if(!getline(std::cin, delay) || !isnumber(delay)) { 
    ... 
} 

isnumber功能使用stringstream的測試串

bool isnumber(string const &str) { 
    std::istringstream ss(str); 
    double d; 

    // allow leading and trailing whitespace, but no garbage 
    return (ss >> d) && (ss >> std::ws).eof(); 
} 

operator>>會吃的空白,以及std::ws將消耗尾隨空白。如果它碰到流尾,它將發出信號eof。這樣,您可以立即向用戶發出錯誤信號,而不是在您下次嘗試從cin讀取時錯誤出現。

編寫一個類似的函數,返回double或將double的地址傳遞給`isnumber,以便它可以在解析成功時寫入結果。


這也是值得看看的各種錯誤標誌和它們如何與operator void*operator!good()fail()bad()eof()它可以是相當混亂:

  flag | badbit | failbit | eofbit 
function   |   |   | 
-----------------+---------+-----------+-------- 
op void*   | x |  x  | 
-----------------+---------+-----------+-------- 
op !    | x |  x  | 
-----------------+---------+-----------+-------- 
good()   | x |  x  | x 
-----------------+---------+-----------+-------- 
fail()   | x |  x  | 
-----------------+---------+-----------+-------- 
bad()   | x |   | 
-----------------+---------+-----------+-------- 
eof()   |   |   | x 
-----------------+---------+-----------+-------- 

有如果相應位影響結果則爲x。轉換爲boolif(cin) ...)時,同時operator!用於代碼做!cin

+2

@litb:那張桌子很棒! +1 – sbi

+0

我已經向這個人投了票,我希望能再次提高它;) – AraK

0

我認爲你需要以字符串的形式讀取變量,然後檢查它是否爲空,然後將其轉換爲double(並檢查它是否是有效的雙精度型 - 用戶可能只是鍵入了「hello」) 。

+1

而且,由於在C++字符串,從轉換的最簡單的使用字符串流進行operator void*時,他又回到了起點。糟糕的想法IMO。 – sbi

+0

爲你+1。我認爲@colen有一點。看到我的代碼答案。這不是一個正方形,因爲串流的行爲與連接到標準輸入的流不同(特別是關於EOF)。 –

+0

@litb:他們的行爲有何不同? – sbi

4
std::cout << "Enter doubles: "; 
std::cin >> d1 >> d2 >> d3; 

if(std::cin.fail()) 
{ 
    // error! 
} 
+1

原始類型如double不能在Java中爲NULL –

+0

@Tyler對不起,我只是一個java新手:) – AraK

+1

@Tyler我刪除了有關Java的錯誤部分,謝謝。 – AraK

3

檢查,如果流輸入的工作方式是測試流:

if(!std::cin) throw "Doh!"; 

由於operator>>總是返回其左側參數,這個工作,也:

if(std::cin >> Delay1) 
    good(); 
else 
    bad(); 

輸入流如果輸入失敗,則不會改變該值。在你的情況下,他們會保持以前的隨機值。未經檢查流,您絕不應接受輸入。

2

這裏有很多事情不對。

首先:檢查解析是否失敗,使用if (cin.fail()) { /* print error */ }

第二:Delay1 || Delay2 || Delay3會將雙打轉換爲布爾值,然後將它們邏輯或運算在一起。

第三:== NULL會比較您的布爾值(在這種情況下爲false)與指針值NULL。我相信這將永遠是true

1

只是使用流狀態,如果它無法讀取雙精度型,它將處於失敗狀態。

if(!(std::cin >> Delay1 >> Delay2 >> Delay3)) { 
    // error 
} 
3

你需要檢查的是在你嘗試讀入double之後輸入流的狀態。

例如

cin >> Delay1; 
if (!cin.fail()) { 
    // Input was a double 
} else { 
    // Input was something that could not be interpreted as a double 
} 

你可以更簡潔地寫爲如下

if (cin >> Delay1) { 
    // Input was a double 
} else { 
    // Input was something that could not be interpreted as a double 
} 

如果輸入失敗,延遲1的值將不會改變,因此,如果您以前沒有初始化,它,這將是一些武斷的價值。正如已經指出的那樣,它不會變成「NULL」,因爲只有指針可以是空值,而不是值類型。

+1

請注意'if(is.good())'和'if(is)'之間有區別:如果'is.eof()'爲'true',前者也會失敗。如果是'cin >> var;如果(cin.good())'這將報告錯誤,即使'var'被正確讀取,但似乎是輸入流中的最後一件事。這使得第一個例子**錯誤**。 – sbi

+0

你說得對。它應該是!失敗。固定。 –

+0

@Tyler:刪除了投票。 ':)' – sbi

2

你的條件是否有錯。如果延遲是而不是等於零或延遲2是而不是等於零或者延遲3是零,則if(Delay1 || Delay2 || Delay3 == NULL)將成立。當然,這不是你想要的。你也應該使用0作爲原始數據類型。此外,將雙數值與絕對值進行比較總是很危險。您檢查該值是否小於小epsilon值。