C++ if 语句未按预期工作,在请求输入之前打印"else"

c++ if statement not working as expected, printing "else" before asking for input

本文关键字:输入 请求 打印 else 语句 if 工作 C++      更新时间:2023-10-16

所以,我在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

编辑:因此,您可以看到如何定义变量,等等。链接到完整代码

问题:

您在致电std::getline()之前执行的最后提取是:

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

这很好。唯一的问题是,鉴于有效的提取,Newline字符'n'将留在流中。默认情况下,获取newline字符后的未形式输入函数std::getline()分界符输入。如果剩余的新线仍然留在流中,则无法执行输入。

请注意,从技术上讲std::getline()会丢弃角色,但一旦找到它就停止提取。


解决方案:

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

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

这是清楚的,这是明确的基础流状态(一个代表I/O期间错误的位屏幕),并忽略最大字符数量,直到找到下一个newline字符(它也消耗了newline)。

我为什么建议这样做?

如果流状态有点打开(failbiteofbitbadbit),该流将无法执行I/O(这也包括忽略字符)。ignore()调用用于丢弃任何残留输入,直到我们到达线结束,因此我们有一条新的新线以重新启动输入。

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

相反,我建议的是使用操纵器std::ws,该操作器将丢弃所有空格字符(Newline也被视为Whitespace),直到找到非Whitespace字符为止。这是丢弃新线的一种更加惯用的方法:

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' || ... )
    }
    

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

也许在IF之前打印出单元以查看其持有的内容。我个人会做以下内容以获取输入:

    string units;
    cin >> units;