c ++ if语句没有按预期工作,在请求输入之前打印“else”

时间:2014-01-31 13:28:18

标签: c++ if-statement getline

所以,我在c ++中写这个问题

    cout << "Would you like the answer in Joules or eV?" << endl;
    cout << "Type 'j' or 'e' to make the selection" << endl;
    invalid = true;
    while (invalid) { //This while loop repeats the question until the user enters e or j
        invalid = false;
        getline(cin, units);
        if (units == "e"|| units == "E") {
            answer = energy(Z,n1,n2);
            cout << "The answer is: " << answer << " eV" << endl;
        }
        else if (units == "j"|| units == "J" || units == "joules" || units == "joule") {
            answer = energy_j(Z,n1,n2);
            cout << "The answer is: " << answer << " J" << endl;    
        }
        else {
            cout << "Please enter either j or e, and press enter." << endl;
            invalid = true;
        }
    }

它似乎很好,但由于某种原因,它总是在我运行它时打印“else”位。我有完全相同的代码,它运行正常。有人可以帮忙吗? (我正在使用linux上的g ++进行编译,如果这有所不同的话)

代码运行正常,但我想知道为什么会发生这个小错误。输出如下所示:

Would you like the answer in Joules or eV?
Type 'j' or 'e' to make the selection
Please enter either j or e, and press enter.
k
Please enter either j or e, and press enter.
e

编辑:这样你就可以看到如何定义变量等等。Link to full code here

3 个答案:

答案 0 :(得分:1)

在getline之前尝试使用std::cin.clear();

答案 1 :(得分:1)

  

问题:

您在调用std::getline()之前执行的最后一次提取是:

while (!(cin >> n2))
{
    cout << "Please enter a number for the final state" << endl;
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

哪个非常好。唯一的问题是,在有效提取的情况下,换行符'\n'将保留在流中。默认情况下,未格式化的输入函数std::getline()在获取换行符时界定输入。如果剩余换行仍留在流中,则无法执行输入。

请注意,技术上std::getline()会丢弃该字符,但一旦找到就停止提取。


  

解决方案:

我在您的问题的评论部分中建议的解决方案是在无格式提取之上执行以下代码行:

std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

这样做的顺序是清除基础流状态(在I / O期间表示错误的位掩码)并忽略最大字符数量,直到找到下一个换行符(它也消耗换行符)。

  

为什么我建议这样做?

如果流状态开启(failbiteofbitbadbit),则流将无法执行I / O(这还包括忽略字符)。 ignore()调用用于丢弃任何剩余输入,直到我们到达行尾,因此我们有一个新的新行来重新开始输入。

但是,由于您更新了显示完整代码的帖子,我现在意识到不需要这两个调用,因为您在我向您展示的第一个代码示例中已经处理了无效输入。此外,由于您确保最近的提取成功,因此无需重置流状态。

相反,我建议使用操纵器std::ws,它将丢弃所有空白字符(换行也被视为空格),直到找到非空白字符。丢弃换行符是一种更惯用的方法:

std::getline(std::cin >> std::ws, units);
//           ^^^^^^^^^^^^^^^^^^^

这应该等同于ignore()调用,因为流中剩下的所有内容都是换行符。

  

改进:

以下是一些:

  1. 第一个是始终检查您的输入是否成功:

    if (std::getline(std::cin >> std::ws, units))
    {
        //
    }
    
  2. 如果units始终是一个字符,那么只需使用一个字符:

    char units;
    if (std::cin >> units)
    {
        if (units == 'e' || ... )
    }
    

答案 2 :(得分:0)

也许在if之前打印单位以查看它持有的内容。我个人会做以下事情来获得输入:

    string units;
    cin >> units;