1

I'm relatively new to C++, but not to programming, and I'm confused as to why I am having this very strange issue with a while loop in my C++ program.

while (runUserInputLoop)
{
    displayMenu();
    cout << "Enter the number that corresponds with your choice from the menu: ";
    getline(cin, menuLoopChoice);

    if (menuLoopChoice == "1")
    {
        cout << "Enter mean: ";
        cin >> mean;
        cout << "Enter z-score: ";
        cin >> z;
        cout << "Enter standard deviation: ";
        cin >> stDev;
        cout << "Enter sample size: ";
        cin >> n;
        oneSampZInt(mean, z, stDev, n);
    }

    else if (menuLoopChoice == "2")
    {
        cout << "Enter mean: ";
        cin >> mean;
        cout << "Enter t-score: ";
        cin >> t;
        cout << "Enter standard deviation: ";
        cin >> stDev;
        cout << "Enter sample size: ";
        cin >> n;
        oneSampTInt(mean, t, stDev, n);
    }

    else if (menuLoopChoice == "3")
    {
        cout << "Enter mean for first sample: ";
        cin >> mean1;
        cout << "Enter mean for second sample: ";
        cin >> mean2;
        cout << "Enter standard deviation for first sample: ";
        cin >> stDev1;
        cout << "Enter standard deviation for second sample: ";
        cin >> stDev2;
        cout << "Enter z-score: ";
        cin >> z;
        cout << "Enter size of first sample: ";
        cin >> n1;
        cout << "Enter size of second sample: ";
        cin >> n2;
        indepMeansZInt(mean1, mean2, stDev2, stDev1, n1, n2, z);
    }

    else if (menuLoopChoice == "4")
    {
        cout << "Enter mean for first sample: ";
        cin >> mean1;
        cout << "Enter mean for second sample: ";
        cin >> mean2;
        cout << "Enter standard deviation for first sample: ";
        cin >> stDev1;
        cout << "Enter standard deviation for second sample: ";
        cin >> stDev2;
        cout << "Enter t-score: ";
        cin >> t;
        cout << "Enter size of first sample: ";
        cin >> n1;
        cout << "Enter size of second sample: ";
        cin >> n2;
        indepMeansTInt(mean1, mean2, stDev2, stDev1, n1, n2, t);
    }

    else if (menuLoopChoice == "5")
    {
        cout << "Enter sample proportion: ";
        cin >> p;
        cout << "Enter sample size: ";
        cin >> n;
        cout << "Enter z-score";
        cin >> z;
        onePropZInt(p, n, z);
    }

    else if (menuLoopChoice == "6")
    {
        cout << "Enter proportion from sample one: ";
        cin >> p1;
        cout << "Enter proportion from sample two: ";
        cin >> p2;
        cout << "Enter size of sample one: ";
        cin >> n1;
        cout << "Enter size of sample two: ";
        cin >> n2;
        cout << "Enter z-score";
        cin >> z;
        twoPropZInt(p1, p2, n1, n2, z);
    }

    else if (menuLoopChoice == "7")
    {
        cout << "Enter chi-sqaured right value: ";
        cin >> chiSqrdRight;
        cout << "Enter chi-sqaured left value: ";
        cin >> chiSqrdLeft;
        cout << "Enter sample variance: ";
        cin >> variance;
        cout << "Enter sample size: ";
        cin >> n;
        chiSqrdInt(chiSqrdRight, chiSqrdLeft, variance, n);
    }

    else if (menuLoopChoice == "8")
    {
        cout << "Enter mean of differences: ";
        cin >> DBar;
        cout << "Enter standard deviation of differences: ";
        cin >> SD;
        cout << "Enter number of matched pairs: ";
        cin >> n;
        cout << "Enter t-score: ";
        cin >> t;
        matchedPairsTInt(DBar, SD, n, t);
    }

    else if (menuLoopChoice == "A" || menuLoopChoice == "a")
    {
        cout << "Enter population mean: ";
        cin >> mean1;
        cout << "Enter sample mean: ";
        cin >> mean2;
        cout << "Enter population standard deviation: ";
        cin >> stDev;
        cout << "Enter size of sample: ";
        cin >> n;
        cout << "Enter z-score: ";
        cin >> z;
        oneSampZTest(mean1, mean2, stDev, n, z);
    }

    else if (menuLoopChoice == "B" || menuLoopChoice == "b")
    {
        cout << "Enter mean of sample one: ";
        cin >> mean1;
        cout << "Enter mean of sample two: ";
        cin >> mean2;
        cout << "Enter standard deviation of population one: ";
        cin >> stDev1;
        cout << "Enter standard deviation of population two: ";
        cin >> stDev2;
        cout << "Enter size of sample one: ";
        cin >> n1;
        cout << "Enter size of sample two: ";
        cin >> n2;
        cout << "Enter z-score: ";
        cin >> z;
        twoSampZTest(mean1, mean2, stDev1, stDev2, n1, n2, z);
    }

    else if (menuLoopChoice == "C" || menuLoopChoice == "c")
    {
        cout << "Enter population mean: ";
        cin >> mean1;
        cout << "Enter sample mean: ";
        cin >> mean2;
        cout << "Enter sample standard deviation: ";
        cin >> stDev;
        cout << "Enter size of sample: ";
        cin >> n;
        cout << "Enter t-score: ";
        cin >> t;
        oneSamptTest(mean1, mean2, stDev, n, z);
    }

    else if (menuLoopChoice == "D" || menuLoopChoice == "d")
    {
        cout << "Enter mean of sample one: ";
        cin >> mean1;
        cout << "Enter mean of sample two: ";
        cin >> mean2;
        cout << "Enter standard deviation of sample one: ";
        cin >> stDev1;
        cout << "Enter standard deviation of sample two: ";
        cin >> stDev2;
        cout << "Enter size of sample one: ";
        cin >> n1;
        cout << "Enter size of sample two: ";
        cin >> n2;
        cout << "Enter t-score: ";
        cin >> t;
        twoSamptTest(mean1, mean2, stDev1, stDev2, n1, n2, t);
    }

    else if (menuLoopChoice == "E" || menuLoopChoice == "e")
    {
        cout << "Enter the population proportion: ";
        cin >> p1;
        cout << "Enter the sample proportion: ";
        cin >> p2;
        cout << "Enter the sample size: ";
        cin >> n;
        cout << "Enter the z-score: ";
        cin >> z;
        onePropZTest(p1, p2, n, z);
    }

    else if (menuLoopChoice == "F" || menuLoopChoice == "f")
    {
        cout << "Enter sample proportion one: ";
        cin >> p1;
        cout << "Enter sample proportion two: ";
        cin >> p2;
        cout << "Enter the x value of proportion one: ";
        cin >> x1;
        cout << "Enter the x value of proportion two: ";
        cin >> x2;
        cout << "Enter the size of sample one: ";
        cin >> n1;
        cout << "Enter the size of sample two: ";
        cin >> n2;
        cout << "Enter the z-score: ";
        cin >> z;
        twoPropZTest(p1, p2, x1, x2, n1, n2, z);
    }

    else if (menuLoopChoice == "q" || menuLoopChoice == "Q")
    {
        runUserInputLoop = false;
    }
}

On the first iteration through the loop, everything works fine. However, on all subsequent iterations, the loop seems to iterate once, without any input, and then again, allowing me to enter input once again. So essentially, there is an extra iteration that causes it to perform this portion of the while loop twice:

displayMenu();
cout << "Enter the number that corresponds with your choice from the menu: ";
getline(cin, menuLoopChoice);

Here is a picture of how it looks in the console: ghost iteration. The crudely circled portion is the "ghost iteration." I feel like it should be something simple, but I'm not extremely familiar with C++ yet, so I'm stumped. The full code for the program is available here if necessary.

wjjd225
  • 57
  • 11
  • Your description of a `cin` problem as a `while loop` problem implies you are confusing yourself with some bizarre incorrect assumptions. I didn't study your post carefully enough to see **why** something is left over in an input buffer from an earlier iteration to confuse the next iteration. But you don't need to know why to see that is happening. – JSF Dec 16 '15 at 01:03
  • You can clear `cin` when you like, and if the program is interactive you might make it more robust by clearing `cin` before prompting for the next input. If input might be typed ahead or redirected in, then you need instead to make sure every line of input is fully consumed before expecting the next line. – JSF Dec 16 '15 at 01:06
  • Or, and this is probably more likely, my aforementioned lack of familiarity with programming in C++, resulted in my confusion of a cin problem with while loop problem, and it was in fact not the result of assumptions either bizarre or incorrect in nature. – wjjd225 Dec 16 '15 at 01:07
  • Off topic: Save yourself a bit of trouble and `menuLoopChoice = tolower(menuLoopChoice);` so all you have to test is the lowercase letter. – user4581301 Dec 16 '15 at 01:09
  • What you don't know never does nearly as much harm as what you think you know that isn't so. I got the impression that something you thought you know was responsible for looking for the problem in the wrong place. That seems almost universal in posts asking about issues like this in `cin` or even worse `scanf`. – JSF Dec 16 '15 at 01:10
  • I can't find the "any key" on the keyboard :) but more seriously I can't find it in the source code you posted. So when I try to look near that point in your processing to find the spot where you left something (such as a newline) dangling in the input buffer, I'm stuck. What I want to look at isn't there. But maybe you should look near that point. – JSF Dec 16 '15 at 01:14

1 Answers1

4

std::istream::operator>> reads characters from the stream until it encounters whitespace (such as an end-of-line character), but it leaves the whitespace character in the stream, so the next read will see it. That's fine if the next read is an operator>>, since it will skip over leading whitespace, but std::getline() just reads until it sees the delimiter character ('\n' by default). Since the previous call to operator>> left a '\n' as the next character in the stream, std::getline() sees it, and returns immediately. To get around this, you can call std::cin.ignore() at the end of your loop to discard the '\n' that's been left in the input stream.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52