2013-09-24 35 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'中的'*'。 –