0

I have two cin validation functions in a program I'm writing - one to validate int, and the other to validate double, whilst both ensuring that the user cannot enter char values. The problem I'm having is that sometimes the function will begin validation immediately after the user is asked to enter a value, like in this case:

cout << endl << "Enter transaction ID to edit : ";
toEdit = validateIntInput(toEdit, 1, MAX_TRANS);

Or this case:

cout << "How much are you adding? : " << char(156);
tVal = validateDoubleInput(tVal, 0.01, 999999998);

However, in other cases, the program will not tell the user that their input is invalid, and simply create a new line, like in this case:

cout << "What day of the month is the bill normally paid? (1 - 31) (You can change this later) : ";
paymentDay = validateIntInput(paymentDay, 1, 31);

Or this case:

cout << "Annual interest rate (%) : ";
annualInterestRate = validateDoubleInput(annualInterestRate, 0.01, 100);

The code for validateIntInput is:

int validateIntInput(int paramToCheck, int minValue, int maxValue)
{
    paramToCheck = 999999999;
    string line;
    while (getline(cin, line))
    {
        stringstream linestream(line);
        linestream >> paramToCheck;
        // if the first if is not included, the program will assume invalid input has been entered as soon as the user is asked for input
        if (paramToCheck == 999999999)
        {
            cout << "";
            paramToCheck = 0;
        }
        // if the input contains a string or is not within bounds, throw an error
        else if (!linestream.eof() || paramToCheck < minValue || paramToCheck > maxValue)
        {
            cout << red << "Invalid input. Try again : " << white;
        }
        // if the input is valid, stop the loop and accept the input
        else
        {
            break;
        }
    }
    return paramToCheck;
}

And the code for validateDoubleInput is:

double validateDoubleInput(double paramToCheck, double minValue, double maxValue)
{
    paramToCheck = 999999999;
    string line;
    while (getline(cin, line))
    {
        stringstream linestream(line);
        linestream >> paramToCheck;
        // if the first if is not included, the program will assume invalid input has been entered as soon as the user is asked for input
        if (paramToCheck == 999999999)
        {
            cout << "";
            paramToCheck = 0;
        }
        // if the input contains a string or is not within bounds, throw an error
        else if (!linestream.eof() || paramToCheck < minValue || paramToCheck > maxValue)
        {
            cout << red << "Invalid input. Try again : " << white;
        }
        // if the input is valid, stop the loop and accept the input
        else
        {
            break;
        }
    }
    return paramToCheck;
}

NOTE: The only reason why the functions assign a value of 999999999 to the parameter and check for this on startup is because the program sometimes threw an exception even before the user had entered anything.

I really have no idea what could be going wrong here - could anyone help me get to the bottom of the problem?

Thanks in advance to anyone who can!

Rob Dudley
  • 25
  • 7
  • Guessing http://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction since this isn't a [mcve]. – chris Apr 11 '17 at 13:07
  • Why are you passing parameters (`paramToCheck`) whose value you never use? Use a local variable. – molbdnilo Apr 11 '17 at 13:19
  • @molbdnilo Completely unsure why I did that! I've jigged it around a bit now, so that's one thing solved if not the original problem – Rob Dudley Apr 11 '17 at 13:31
  • In the circumstance paramToCheck == 999999999 why are you printing a space and setting it to 0? – AresCaelum Apr 11 '17 at 13:35
  • A very common problem is having a newline in the input buffer when calling `getline`. – molbdnilo Apr 11 '17 at 13:38
  • @Eddge space has been removed – like you suggested, it wasn't particularly necessary. Although the reason paramToCheck is set to 0 is because no input in the program accepts 0 anyway, and if that isn't there then it doesn't seem to process invalid input correctly – Rob Dudley Apr 11 '17 at 13:39
  • but setting the value to 0, will make it skip that check the next time around. – AresCaelum Apr 11 '17 at 13:41
  • @Eddge I double checked in case that does happen, if 0 is entered after the initial check the program still manages to flag it up as invalid input and warn the user – Rob Dudley Apr 11 '17 at 13:44
  • @RobDudley it didn't when I just tested it... – AresCaelum Apr 11 '17 at 13:44
  • @Eddge "How much is the bill? (You can change this later) : £" with a user input of 0 followed up with "Invalid input. Try again :" – Rob Dudley Apr 11 '17 at 13:49
  • @RobDudley what values are you passing into your validate function? – AresCaelum Apr 11 '17 at 13:51
  • @Eddge minimum value accepted by the input, and maximum value. It originally also took the current value for the value that was being changed but I realised that was unnecessary – Rob Dudley Apr 11 '17 at 13:52
  • @RobDudley what I mean is, what are the values you are passing in for minimum and maximum, if I set the minimum on my end to 0, it accepts 0. – AresCaelum Apr 11 '17 at 13:54
  • @RobDudley I will just put it like this, using your code I am not getting the situation where it skips input validation, the closest I get to the is if I enter F or any other character, in which case it won't even print my input is invalid, now if 0 is my minimum value using your function, and if I hit F again, it closes the validation, and in my print where it is telling me the returned value it is telling me 0. – AresCaelum Apr 11 '17 at 14:00
  • @Eddge I see! The minimum value accepted any time the function is called is 0.01, so nothing in the program accepts a value of 0. That's the problem I'm having - if a letter is fed in, the program won't tell the user the input is invalid, it just creates a new line. – Rob Dudley Apr 11 '17 at 14:01
  • @RobDudley thats because of this `cout << "";` you aren't printing out the value is wrong. – AresCaelum Apr 11 '17 at 14:02
  • @Eddge I've removed that now, and the problem still persists. – Rob Dudley Apr 11 '17 at 14:03
  • Your validate function is also doing input and output. Have you considered making a new type to handle int or double, and performing the validation in an overloaded operator>>(istream&)? That will allow you to check the iostream results normally. – Kenny Ostrom Apr 11 '17 at 14:44

1 Answers1

0

As I stated in the comment section, I am not getting the situation where it skips input validation. The closest I got was when I entered a char value twice, and had a minimum acceptable value of 0. In which case it would just return 0.

In the circumstance that it isn't telling you the value is invalid is because in your check you are using

    if (paramToCheck == 999999999)
    {
        cout << "";  // Doesn't print out an error like you want it to
        paramToCheck = 0;
    }

I would rearrange your function to do this instead:

if (!linestream.eof() || paramToCheck < minValue || 
        paramToCheck > maxValue || paramToCheck == 999999999)
    {
        cout << red << "Invalid input. Try again : " << white;
    }
AresCaelum
  • 1,518
  • 1
  • 13
  • 18