Home:ALL Converter>Check if scores are between 0 and 100 using pointers

Check if scores are between 0 and 100 using pointers

Ask Time:2021-09-22T05:53:13         Author:ATSpiro

Json Formatter

I need to check each score value, they need to be between 0 and 100 and if not the user needs to be prompted to reenter a valid value.

My code:

#include <iostream>

using namespace std;

void sort(int*, int);
void displaySort(int*, int);

int main()
{
    int lInput;
    cout << "Enter the size of your list: ";
    cin >> lInput;

    int* lPtr = new int[lInput];

    for (int i = 0; i < lInput; i++)
    {
        cout << "Enter a score: ";
        cin >> *(lPtr + i);

        if (*(lPtr + i) < 0 || *(lPtr + i) > 100)
        {
            cout << "Invalid input, enter again: ";
        }
    }

    cout << endl;

    sort(lPtr, lInput);
    displaySort(lPtr, lInput);

    cout << endl;

    delete[] lPtr;


    system("PAUSE");
    return 0;
}

void sort(int* array, int size)
{
    int scan, minIndex, minValue;

    for (int scan = 0; scan < (size - 1); scan++)
    {
        minIndex = scan;
        minValue = *(array + scan);
        for (int i = scan + 1; i < size; i++)
        {
            if (*(array + i) < minValue)
            {
                minValue = *(array + i);
                minIndex = i;
            }
        }
        *(array + minIndex) = *(array + scan);
        *(array + scan) = minValue;
    }
}

void displaySort(int* array, int size)
{       
    cout << "List of scores in ascending order:" << endl;

    for (int i = 0; i < size; i++)
    {
        cout << *(array + i) << " ";
    }
}

The way I have it now, it still takes the invalid number. I want it so if an invalid number is entered it does not take the number and asks for a valid one.

Author:ATSpiro,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/69275938/check-if-scores-are-between-0-and-100-using-pointers
Andreas Wenzel :

In the following code\nfor (int i = 0; i < lInput; i++)\n{\n cout << "Enter a score: ";\n cin >> *(lPtr + i);\n\n if (*(lPtr + i) < 0 || *(lPtr + i) > 100)\n {\n cout << "Invalid input, enter again: ";\n }\n}\n\nthe problem is that on invalid input, you output text which contains an error message and prompts the user to enter a new number, but you don't actually read any new input. Instead, you simply jump to the next loop iteration, which effectively means that you are accepting the bad input.\nOne way to solve the problem would be to make an infinite loop which will continue running until the user enters valid input. When that happens, you can break out of that loop with the break statement.\nfor (int i = 0; i < lInput; i++)\n{\n for (;;) //infinite loop, equivalent to while(1)\n {\n cout << "Enter a score: ";\n cin >> *(lPtr + i);\n\n if (*(lPtr + i) < 0 || *(lPtr + i) > 100)\n {\n cout << "Input must be between 0 and 100, try again!\\n";\n continue;\n }\n\n break;\n }\n}\n\nHowever, one problem with this code is that it only performs a range check, but does not check whether the input was valid at all. In particular, it does not check whether the stream extraction operator >> successfully converted the user's input into a number. This can be checked by calling cin.fail().\nIt would be best to perform this additional check before the range check, like this:\nfor (int i = 0; i < lInput; i++)\n{\n //this loop will continue until the input is valid\n for (;;) //infinite loop, equivalent to while(1)\n {\n cout << "Enter a score: ";\n cin >> *(lPtr + i);\n\n //check if stream error occurred\n if ( cin.fail() )\n {\n //check if error is recoverable\n if ( cin.bad() )\n {\n throw std::runtime_error( "unrecoverable I/O error" );\n }\n\n //print error message\n cout << "Input must be a number, try again!\\n";\n\n //discard bad input (remainder of line)\n cin.ignore( std::numeric_limits<std::streamsize>::max(), '\\n' );\n\n //clear stream status flags\n cin.clear();\n\n continue;\n }\n\n if (*(lPtr + i) < 0 || *(lPtr + i) > 100)\n {\n cout << "Input must be between 0 and 100, try again!\\n";\n continue;\n }\n\n //input is valid, so break out of the infinite loop\n break;\n }\n}\n\nNote that the code above requires you to additionally #include <limits>.\nHowever, this code is still not quite perfect. If you enter input such as 12sdlhfh, then it will accept 12 as valid input, but the next stream extraction will fail, because sdlhfh is not a valid number, and it will print an error message. This error message could be prevented by discarding the remainder of the line after every stream extraction, but in this case, this is probably not be the ideal solution, because you would probably want to reject input such as 12sdlhfh.\nTo be able to reject such input, you should not use the stream extraction operator >>, because it will stop reading as soon as it encounters a non-digit. Instead, you should always read one line at a time, using std::getline, and validate the entire line using std::stoi and some extra code to verify that no non-whitespace characters appear after the number.\nfor (int i = 0; i < lInput; i++)\n{\n //this loop will continue until the input is valid\n for (;;) //infinite loop, equivalent to while(1)\n {\n std::string line;\n std::size_t pos;\n\n cout << "Enter a score: ";\n getline( cin, line );\n\n //check if stream error occurred\n if ( cin.fail() )\n {\n //check if error is recoverable\n if ( cin.bad() )\n {\n throw std::runtime_error( "unrecoverable I/O error" );\n }\n\n //print error message\n cout << "Input error, try again!\\n";\n\n //clear stream status flags\n cin.clear();\n\n continue;\n }\n\n //attempt to perform the actual conversion\n try\n {\n *(lPtr + i) = std::stoi( line, &pos );\n }\n catch ( std::invalid_argument )\n {\n cout << "Unable to convert input to number, try again!\\n";\n continue;\n }\n catch ( std::out_of_range )\n {\n cout << "Range error, try again!\\n";\n continue;\n }\n\n //verify that rest of line does not contain any non-whitespace characters\n for ( ; pos < line.length(); pos++ )\n {\n if ( !std::isspace( static_cast<unsigned char>(line[pos]) ) )\n {\n cout << "Invalid character found, try again!\\n";\n\n //we cannot use "continue" here, because that would\n //continue to the next iteration of the innermost\n //loop, but we want to continue to the next iteration\n //of the outer loop\n goto continue_outer_loop;\n }\n }\n\n if (*(lPtr + i) < 0 || *(lPtr + i) > 100)\n {\n cout << "Input must be between 0 and 100, try again!\\n";\n continue;\n }\n\n //input is valid, so break out of the infinite loop\n break;\n\n continue_outer_loop:\n continue;\n }\n}\n\nNote that the code above additionally requires: #include <string> and #include <cctype>.\nThe code above uses one goto statement. Normally, you should not use goto if possible, but for exiting nested loops, it is acceptable.\nAlso note that if you use the above code, then it won't be compatible with using cin >> lInput; outside the loop. Mixing std::getline and std::istream::operator>> will generally not work, because std::istream::operator>> will leave the newline in the buffer, so the next call to the std::getline will probably only retrieve an empty line.",
2021-09-22T02:53:39
yy