2010-05-02 91 views
4

我有一个我写的Win32控制台程序,它工作正常。该程序从用户处获得输入并执行一些计算并显示输出 - 标准内容。为了好玩,我试图让程序在我的Fedora盒子上工作,但是当用户输入与我的变量类型不匹配的东西时,我遇到了清除cin的问题。这是有问题的代码:C++:Linux和Windows之间的cin区别帮助

void CParameter::setPrincipal() { 
double principal = 0.0; 

cout << endl << "Please enter the loan principal: "; 
cin >> principal; 

while(principal <= 0) 
{ 
    if (cin.fail()) 
    { 
      cin.clear(); 
      cin.ignore(INT_MAX, '\n'); 
    } 
    else 
    { 
     cout << endl << "Plese enter a number greater than zero. Please try again." << endl; 
     cin >> principal; 
    } 
} 

m_Parameter = principal; 

}

此代码在Windows中。例如,如果用户试图输入char数据类型(而不是double),程序会通知用户错误,重置cin,并允许用户再次输入一个有效值。

当我将这段代码移动到Fedora时,它编译得很好。当我运行程序并输入无效的数据类型时,while循环不会中断以允许用户更改输入。

我的问题是;如何在Fedora环境中输入无效数据时清除cin?另外,我该如何编写这段代码才能在两种环境下工作(Windows & Linux)?

在此先感谢您的帮助!

回答

1

我认为这是一个坏主意,用格式化输入读取用户的响应。我会使用getline - 如下所示:

#include <iostream> 
#include <string> 
#include <sstream> 
using namespace std; 

template <typename T> 
bool Read(T & t, istream & is) { 
    string s; 
    if (! getline(is, s)) { 
     return false; 
    } 
    else { 
     istringstream ss(s); 
     return ss >> t; 
    } 
}  

int main() { 
    while(1) { 
     double d; 
     if (! Read(d, cin)) { 
      cout << "invalid\n"; 
     } 
     else { 
      cout << "You entered " << d << "\n"; 
     } 
    } 
} 

它在Windows上工作 - 我目前没有打开我的Linux机器。

2

我认为cin.ignore设置cin上的失败标志,这使得它永远留在最上面的if语句中。 INT_MAX是一个非常大的数字 - 你确定它可以在所有平台上使用cin.ignore吗?

+4

好一点,我想。 'std :: numeric_limits :: max()'可能是更好的选择。 – 2010-05-02 14:50:30

1

我切换到使用一个getline读取输入,然后用stringstream解析:

double principal = 0; 
string temp; 
while (principal <= 0) 
{ 
    getline(cin, temp); 
    istringstream converter(temp); 
    if (!(converter>>principal) || 
     !(converter>>std::ws).eof() || 
     principal <= 0) 
    { 
     cout << "Try again" << endl; 
     principal = 0; 
    } 
} 
0

我同意Anders Abel和Johannes Schaub;我还认为,如果发生错误,可能无法保证本金不变,因此您可以考虑在周期开始时增加principal=0.0;

顺便说一句,进行这种工作,我通常使用这个模板函数:

template<typename InType> void AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString, InType & Result) 
{ 
    do 
    { 
     Os<<Prompt.c_str(); 
     if(Is.fail()) 
     { 
      Is.clear(); 
      Is.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
     } 
     Is>>Result; 
     if(Is.fail()) 
      Os<<FailString.c_str(); 
    } while(Is.fail()); 
} 

template<typename InType> InType AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString) 
{ 
    InType temp; 
    AcquireInput(Os,Is,Prompt,FailString,temp); 
    return temp; 
} 

,如果你想避免复制第一个重载可优选,第二个可能是内建类型更方便。 使用示例:

//1st overload 
double aDouble; 
AcquireInput(cout,cin,"Please insert an integer: ","Invalid value.\n",aDouble); 

//2nd overload (more convenient, in this case and in general with POD) 
double aDouble=AcquireInput(cout,cin, "Please insert an integer: ","Invalid value.\n"); 

在你的情况可能会改变你的代码是这样的:

double principal=0.0; 
const char * errMsg="Plese enter a number greater than zero. Please try again.\n"; 
while(principal<=0.0) 
{ 
    principal=0.0; 
    principal=AcquireInput(cout,cin,"Please enter the loan principal: ",errMsg); 
    if(principal<=0.0) 
     cout<<errMsg; 
} 
相关问题