C++ 程序不等待cin

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12272277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:06:41  来源:igfitidea点击:

Program not waiting for cin

c++loopsinputconsole

提问by user1647490

int x=0;
string fullname = "";
float salary;
float payincrease;
float newsal;
float monthlysal;
float retroactive;
while(x<3){
    cout << "\n What is your full name?";
    cin >> fullname;
    cout << "\n What is your current salary? \t";
    cin >> salary;
    cout << "\n What is your pay increase? \t";
    cin >> payincrease;
    newsal = (salary*payincrease)+salary;
    monthlysal = newsal/12.00;
    retroactive = (monthlysal*6)-(salary/2);
    cout << "\n" << fullname << "'s SALARY INFORMATION";
    cout << "\n New Salary \t Monthly Salary \t Retroactive Pay";
    cout << "\n \t" << newsal << "\t" << monthlysal << "\t" << retroactive;
    x++;
}

My loop doesn't seem to stop for every time cin is asked, and instead instantly executes the loop 3 times on its own. How do I get it to stop when input is asked?

我的循环似乎不会在每次询问 cin 时停止,而是立即自行执行循环 3 次。当要求输入时如何让它停止?

回答by derpface

If the input stream isn't empty when you call cin, then cin uses the data already in the buffer instead of waiting for more from the user. You're using the extraction operator, so when cin is sending values to your variables, it skips leading whitespace in the buffer and stops on the next whitespace.

如果调用 cin 时输入流不为空,则 cin 使用缓冲区中已有的数据,而不是等待用户提供更多数据。您正在使用提取运算符,因此当 cin 将值发送到您的变量时,它会跳过缓冲区中的前导空格并在下一个空格处停止。

Put a breakpoint on this line:

在这一行上放置一个断点:

cout << "\n What is your current salary? \t";

Run the program, and enter Bob Smith. When you hit the break point, hover your cursor over your string fullname. You'll see it stores only "Bob" not "Bob Smith". "Bob Smith" got put into the buffer, but when you use cin with the extraction operator, it skips any leading whitespace, puts the next value it finds into your variable, then stops on the next whitespace. To demonstrate this, try running this:

运行程序,然后输入 Bob Smith。当您遇到断点时,将光标悬停在您的字符串全名上。你会看到它只存储“Bob”而不是“Bob Smith”。“Bob Smith”被放入缓冲区,但是当您将 cin 与提取运算符一起使用时,它会跳过任何前导空格,将它找到的下一个值放入您的变量中,然后在下一个空格处停止。为了证明这一点,请尝试运行:

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str1,str2;
    cin >> str1;
    cin >> str2;
    cout << str1 << " " << str2 << "\n\n";
    return 0;
}

If you type in "Bob Smith", it will take your input only one time, even though you call cin twice. However, you'll see that both "Bob" and "Smith" got captured in the strings str1 and str2.

如果您输入“Bob Smith”,即使您调用 cin 两次,它也只会接受您的输入一次。但是,您会看到“Bob”和“Smith”都被捕获在字符串 str1 和 str2 中。

Therefore, you can conclude that cin stops populating your string fullname when it gets to the space between Bob and Smith. On your next call to cin, the buffer still contains "Smith", so instead of taking more input from the user, it attempts to fill your variable salary with "Smith". Obviously this isn't want you want to do. You can call flush and ignore on cin to wipe out the buffer before every time you use cin, or instead you could fix your logic and use getline to take in the full name, including spaces.

因此,您可以得出结论,cin 在到达 Bob 和 Smith 之间的空间时停止填充您的字符串 fullname。在您下次调用 cin 时,缓冲区仍包含“Smith”,因此它不会从用户那里获取更多输入,而是尝试用“Smith”填充变量工资。显然这不是你想要做的。您可以在每次使用 cin 之前对 cin 调用 flush 和 ignore 以清除缓冲区,或者您可以修复您的逻辑并使用 getline 来获取全名,包括空格。

To fix your problem, all you need to do is use getline instead of cin >>, so replace this line:

要解决您的问题,您需要做的就是使用 getline 而不是 cin >>,因此请替换此行:

cin >> fullname;

with this:

有了这个:

getline(cin,fullname,'\n');

Secondly, you're using a while loop to execute a set of actions a specific number of times. That's typically something you'd use a for loop for.

其次,您正在使用 while 循环以特定次数执行一组操作。这通常是您使用 for 循环的东西。

As an aside, you could also write tiny input validation loops that can help you debug or otherwise avoid attempting to put invalid input into your variables (such as "Smith" into a float). Something like this could work:

顺便说一句,您还可以编写微小的输入验证循环,以帮助您调试或以其他方式避免尝试将无效输入放入变量中(例如将“Smith”放入浮点数)。这样的事情可以工作:

for(;;)
{
    if(cin >> salary)
        break;
    cin.clear();
    cin.ignore(INT_MAX,'\n');
}

Note that cin returns a value, so you can use it in an if statement. If it gets valid input, it will return true. If not, it will return false. To make it more explicit, you could also just use a normal call to cin without the if statement, and then check if cin.good(), which amounts to basically the same net effect. If you're not using Visual Studio and get an error about INT_MAX, you might need to #include limits.h to resolve it.

请注意,cin 返回一个值,因此您可以在 if 语句中使用它。如果它得到有效的输入,它将返回 true。如果没有,它将返回false。为了使它更明确,您也可以只使用普通调用 cin 而不使用 if 语句,然后检查 cin.good() 是否具有基本相同的净效果。如果您未使用 Visual Studio 并收到有关 INT_MAX 的错误,您可能需要 #include limits.h 来解决它。

回答by Software_Designer

That occurs if you input a charwhere an intis expected.

如果您输入 a charwhere an ,则会发生这种情况int

Use cin.clear();and cin.ignore(numeric_limits<streamsize>::max(), '\n');to limit an input to int's only.

使用 cin.clear();cin.ignore(numeric_limits<streamsize>::max(), '\n');将输入限制为int仅 's。

Other than that, it won't skip if the correct data type is put in.

除此之外,如果输入了正确的数据类型,它将不会跳过。

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



int main(void)
{


    int x=0;
    string fullname = "";
    float salary;
    float payincrease;
    float newsal;
    float monthlysal;
    float retroactive;

    while(x<3)
    {
        cout << "\n What is your full name?";
        cin >> fullname;
    cin.ignore( 1000, '\n' );

        cout << "\n What is your current salary? \t";
        cin >> salary;
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

        cout << "\n What is your pay increase? \t";
        cin >> payincrease;
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

        newsal = (salary*payincrease)+salary;
        monthlysal = newsal/12.00;
        retroactive = (monthlysal*6)-(salary/2);
        cout << "\n" << fullname << "'s SALARY INFORMATION";
        cout << "\n New Salary \t Monthly Salary \t Retroactive Pay";
        cout << "\n \t" << newsal << "\t" << monthlysal << "\t" << retroactive;
        x++;
    }


      cout<<" \nPress any key to continue\n";
      cin.ignore();
      cin.get();

   return 0;
}