2013-09-24 65 views
1

getRegionTotal()是我現在用於驗證的函數。它工作得很好,因爲如果用戶輸入類似「二十」或-7的東西,它不會接受它,它會一直詢問新的值,直到它得到一個有效的值。但是,如果用戶輸入60.7的北部地區的事故數量,它將接受60並放棄.7部分。當它要求南部地區的事故數量時,它會給出正常指示和更具體的指示。如何使整數驗證函數不接受浮點值?

//These will hold the number of accidents in each region last year 
int northTotal = 0; 
int southTotal = 0; 
int eastTotal = 0; 
int westTotal = 0; 
int centralTotal = 0; 

//passing 0 for northTotal, southTotal etc. because main doesn't know 
//values of them until the function returns a value. When it returns a value 
//it will go into the variables on the left. getRegionTotal will get the number 
//of accidents for a region from the user and prompt the user using the string that 
//is in the first argument. 
northTotal = getRegionTotal("North", northTotal); 
southTotal = getRegionTotal("South", southTotal); 
eastTotal = getRegionTotal("East", eastTotal); 
westTotal = getRegionTotal("West", westTotal); 
centralTotal = getRegionTotal("Central", centralTotal); 


int getRegionTotal(string regionName, int regionTotal) 
{ 
    //instructs user to enter number of accidents reported in a particular region 
    cout << "\nNumber of automobile accidents reported in " << regionName << " " << cityName << ": "; 
    //while regionTotal is not an integer or regionTotal is negative 
    while (!(cin >> regionTotal) || (regionTotal < 0)) 
    { 
     //give user more specific instructions 
     cout << "\nPlease enter a positive whole number for the number of\n"; 
     cout << "automobile accidents in " << regionName << " " << cityName << ": "; 
     cin.clear(); //clear out cin object 
     cin.ignore(100, '\n'); //ignore whatever is in the cin object 
           //up to 100 characters or until 
           // a new line character 
    } 
    //returns a valid value for the number of accidents for the region 
    return regionTotal; 
} 
+0

爲什麼不解析浮點數並使用強制類型轉換爲int,或者檢查解析的數字是否有小數位(例如使用模運算符)? – Jost

+0

小數位將自動刪除。我不知道如何使用模數運算符來檢查它。如果我將while循環條件更改爲'while(!(cin >> regionTotal)||(regionTotal <0)||(regionTotal%1!= 0))'問題仍然存在 – user2234760

+0

您需要_parse_一個float而不是int - 後來你轉換它(但它只是一個想法 - 它有點骯髒;-)) – Jost

回答

1

解析整條線,確保你已經消耗了整條線。

隨着輸入輸出流:

#include <iostream> 
#include <sstream> 
#include <string> 

for (std::string line; std::getline(std::cin, line);) 
{ 
    std::istringstream iss(line); 
    int result; 

    if (!(iss >> result >> std::ws && iss.get() == EOF)) 
    { 
     // error, die. For example: 

     std::cout << "Unparsable input: '" << line << "'\n"; 
     continue; 
    } 

    // else use "result" 
} 

隨着STDLIB:

#include <errno> 
#include <cstdlib> 

char const * input = line.c_str(); // from above, say 
char * e; 
errno = 0; 

long int result = std::strtol(input, &e, 10); 

if (e == input || *e != '\0' || errno != 0) 
{ 
    // error 
} 

兩種方法是從根本上相同的,但是前者可以是更 「慣用C++」。也就是說,如果你已經有了一個字符串,strtol -approach是一個很好的選擇,因爲它給你精確的錯誤處理:你是否使用了整個字符串(如果沒有,e指向下一個字符);你是否消費的任何的字符串(如果沒有,e指向開頭);有沒有溢出或下溢(檢查errno)。另一方面,iostreams方法可以讓你消耗尾隨的空白(感謝>> std::ws),而解決方案則不需要。

還有std::stol它包裝strtol(以及同樣爲strtoull/strtod等),但它拋出出錯異常,並且我相信例外是不適合的正常行爲,如閱讀結構的控制流的正確工具用戶輸入。另外,您無法控制這些包裝紙的操作方式;例如,即使他們沒有使用整個字符串(但不告訴你他們有多遠),也可以成功,並且不能指定數字基數。

+0

第二個版本中需要最後一個檢查:該字符串不是空的開始。 –

+0

怎麼可能?如果字符串是空的,'* e'唯一可以指向的是''\ 0''。 (如果字符串是空的,可能會在'errno'中出現某種錯誤,但標準另有說明。) –

+0

並且在修正中存在拼寫錯誤。你不希望'* e == input'中的'*'。 –