【问题标题】:standard input stream cin failing to prompt for input标准输入流 cin 未能提示输入
【发布时间】:2015-11-05 17:52:45
【问题描述】:
1 #include<iostream>
  2 using namespace std;
  3 
  4 int main()
  5 {
  6     const double yen_to_euro=0.007215;
  7     const double euro_to_dollar=1.12;
  8     char currency;
  9     double x;
 10 
 11     while(currency!='q')
 12     {
 13         cout << "enter currency and unit(y , e, or d)";
 14         cin >> x >>currency;
 15 
 16         switch(currency){
 17 
 18             case 'y':
 19                 cout <<"euro:"<< x*yen_to_euro<<" dollar:"<<x*yen_to_euro*euro_to_dollar<<'\n';
 20                 break;
 21             case 'e':
 22                 cout <<"yen:"<< (x*(1.0/yen_to_euro))<<" dollar:"<<(x*euro_to_dollar)<<'\n';
 23                 break;
 24             case 'd':
 25                 cout <<" yen:"<< x*(1.0/yen_to_euro)*(1.0/euro_to_dollar)<<" euro:"<<x*(1.0/euro_to_dollar)<<'\n';
 26                 break;
 27             case 'q':
 28                 currency='q';
 29                 break;
 30             default:
 31                 cout << "invalid";
 32                 break;
 33 
 34         }
 35 
 36     }
 37 
 38 
 39 }
~             

上述代码的预期功能是将选定的货币(y 代表日元,e 代表欧元,d 代表美元)转换为其他货币。

例如,如果我想兑换成 12 日元,我会输入:

12 年

然后程序会输出

欧元:0.08658 美元:0.0969696

但是,如果我输入 12e,我会收到一个无限循环。仔细检查代码,似乎没有任何逻辑错误。 尽管如此,我感觉问题的根源与第 14 行的 cin 有关,因为如果我像这样分别取 x 和货币类型:

cin>> x;
cin>> currency;

代码工作正常,但我需要输入金额,然后按回车,然后按代表货币类型的字符。有没有办法只在一行中输入所有内容,没有空格?

此外,它为什么会这样?这种通过无限循环的不寻常行为仅在我输入 e 表示 Euro 和 q 表示退出时发生。

【问题讨论】:

  • 'e' 字符使解析器误以为您正在尝试以科学计数法传递值。在大多数情况下,解析器会在遇到非数字字符时立即放弃,并返回它目前已解析的值。但在这种情况下,它会将'e' 作为数字的一部分读取,切换到科学模式,然后确定数字格式错误并失败(您可以检查cin.good() 以检查此错误和其他解析错误)。

标签: c++ cin spacing


【解决方案1】:

12e 被解释为浮点数的开头,例如 12e03。但是缺少结尾,因此您的流被置于错误(故障位)。此状态会导致所有后续输入失败,直到故障状态被清除。

您可以有一个内部循环来检查此类格式错误:

while (...) {
     ...
     while ( (cin >> x >> currency).fail() && !cin.eof()) { // loops as long as there's input and it's invalid
         cout << "invalid format";
         cin.clear(); 
     }
     if (cin.eof())  // if there's no longer input stop looping
         break; 
     ...
 }

live demo

请注意,如果您想确保在任何情况下都执行循环,则应将 currency 初始化为不同于 'q' 的值。

顺便说一句,如果您输入 12 e(带空格),则 12 将被解释为数字并将 x 和 e 放入货币中,正如您所期望的那样。

【讨论】:

    【解决方案2】:

    正如其他答案所解释的,12e 指的是浮点数的科学记数法,因此currency 不存储“e”。

    要在没有空格的单行中获取输入,您应该使用std::getline,然后解析输入字符串。

    由于您知道最后一个字符始终表示货币,因此可以使用std::stoi 将前面的字符转换为数字。

    【讨论】:

      【解决方案3】:

      替换cin &gt;&gt; x &gt;&gt;currency; 与

          try{
            std::string myLine;
            std::getline (std::cin, myLine); // store line into myLine.
            currency = myLine.back(); // get last character from line.
            myLine.pop_back(); // remove last character from myLine.
            x = std::stod(myLine); // try to conver the rest of the string to a double.
          }
          catch (...) {
            //The user typed in something invalid.
            currency= 'i';
          }
      

      另外,请务必#include &lt;string&gt;

      请注意,此解决方案假定您使用的是 C11。

      【讨论】:

      • 它永远循环的原因是 '12e' 是科学计数法中格式错误的浮点数,它正在设置故障位。之后,每次从流中读取输入的尝试都会中止,因为 failbit 永远不会取消设置,并且它尝试读取的值永远不会改变。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      • 2019-12-05
      相关资源
      最近更新 更多