Validating User Input, Explained with Code Examples

UPI Study › Courses › C++ Programming › Free lessons › Lesson 7.6 Free with a free account

Validating User Input

C++ Programming · Chapter 7: Text and Applied CollectionsSection 7.6 · lesson 48 of 84video coming soon

← Presenting Text PreciselyNext lesson: Dynamic Vectors Challenge →

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

In this lesson

Guarding against bad data.

  • Name the 4 stream states, and which recover
  • Restore a failed stream with clear, then ignore
  • Write a reprompt loop bad input can't escape
  • Read a whole line first, then convert it

Transcript

Everything said in the video, section by section (1,533 words). Read along, or search it.

Opening Problem

User Input Is Only a Promise

Everything a program reads from a person is a promise that may not be kept. Ask for an age, and you'll receive a word, a blank line, a negative number, or 300. A program that assumes otherwise doesn't crash. It quietly carries on with a zero, and reports an answer built on it. This lesson covers how to tell that a read went wrong, how to put the stream back in order, and the loop that keeps asking until the value is usable.

Framework

Three Gates of Valid Input

Is this input valid? That's really three questions, asked in order, each with a different answer and a different remedy. Gate one is form. Is it a number at all? The stream answers this. If not, clear the stream, discard the line, and ask again. Gate two is range. Is it a sensible number? Only you can answer this. If not, explain the acceptable range, and ask again. Gate three is leftovers. Is anything still waiting? If so, the next read pays for it. A value that fails gate one has no meaning yet, so testing its range is pointless. Mixing the questions is why validation code so often ends up tangled.

Definitions

The Four Stream States

A stream carries a record of how it's doing, and every read updates it. There are four states. Good means the last read worked. Fail means it couldn't be performed: letters were typed where a number was expected. Nothing was consumed, and the variable was set to zero. This is the one you'll meet constantly, and it's recoverable. E O F means the input has run out, for good. Asking again won't help, because there's nobody left to ask. Stop the loop instead. And bad means something has gone wrong with the stream itself, not the data. It's rare, and effectively unrecoverable.

Demonstration

Why Failed Streams Stay Failed

Once a stream is in the failed state, that state is sticky. Every later read does nothing, and returns immediately, without waiting for anybody to type. Watch. The first read gets the letters a b c and fails: good is zero, fail is one, E O F is zero, and value is 0. The second read never even tries. Next keeps its 99. That's why one bad entry makes every remaining prompt flash past at once. Nothing's broken. The stream is refusing to work until it's told to start again.

Technique

Using a Read as a Condition

Testing the state is easier than the four names suggest. A read expression can be used directly as a condition. Cin, reading into value, produces the stream itself. And a stream used where a yes-or-no answer is wanted reports whether it's in working order. If it worked, value holds something meaningful. If not, value is zero, and the offending text is still waiting.

Recovery

Clear the State, Ignore the Text

A failed read leaves two separate problems behind, and each needs its own remedy. The state must be reset, with clear. And the text that caused the trouble must be thrown away, with ignore. Picture it. After the failed read, a b c is still waiting, and the state is fail. After clear, the state is good, but the text is still there. After ignore, the stream is empty, and ready for the next question. Doing only the first step leaves the same bad characters sitting there, so the next read fails on them again, forever.

Common Mistake

Ignore Before Clear Fails

And the order matters. While the stream is failed, every operation on it does nothing, including ignore. Here, ignore comes first. It does nothing, then clear resets the state, and the bad characters survive. All three tries fail on the same letters. Swap the two lines, and the first failure is cleaned up properly: the next try reads 42.

Details

Discarding the Whole Line

The two arguments to ignore mean: discard as many characters as it takes, and stop after a newline has been thrown away too. Discarding a fixed small number instead leaves the rest of the line waiting. Someone who types hello there gets two complaints from one mistake. Throwing away the whole line means one bad entry produces exactly one reprompt.

Worked Example

The Standard Reprompt Loop

Put the pieces together, and the standard shape appears. Accepted starts false. While a value hasn't been accepted, prompt for an age in whole years, and try to read it. If the read works, accept it. If it fails, say what was wrong, clear the stream, and ignore the rest of the line. Run it with abc, then hello there, then 30. Every route through the loop either accepts a value, or leaves the stream clean for another attempt.

Visual Model

The Loop as a Cycle

Drawn as a cycle: prompt, read, and ask whether it worked and is sensible. If yes, accept it and carry on. If no, say what was wrong, clear, ignore the line, and go round again. There's no way out except through a successful read. That's the property that makes it a guard, rather than a suggestion. And every failure route ends by putting the stream back in a usable state. Skip that, and the loop spins forever without pausing.

Range Checks

Good Numbers That Are Still Wrong

A value can be a perfectly good number, and still be wrong. Once the form is confirmed, ask whether the value makes sense for the thing it represents. Here, an age must be between 0 and 130. And say so in the message, because a bare "Invalid input" tells nobody what to type instead. Notice what isn't on that path: no clear, and no ignore. The read succeeded, so the stream is in perfect health. Only the value was unacceptable. Run it with minus 5, 9000, abc, and 120. The first two get the range message, the word gets the clear and ignore path, and 120 is accepted.

More Examples

Other Kinds of Value Checks

Range is one kind of check. A month is from 1 to 12. A quantity can't be negative. A divisor can't be zero, and say why. A choice must be one of a set: 1, 2, or 3. And a value can be consistent with another: the end year must not be before the start year. Clearing is for a stream that has stopped working, not for a value you've decided to refuse.

Pitfall

The Newline Left Before getline

An extraction stops at the newline, and leaves it behind. A getline that follows meets that newline immediately, reads nothing, and returns an empty string. With prompts, the second one would flash past without waiting. Run it with 5, then a name. The line comes back empty. The remedy is the ignore call already in hand. After a successful read, before a getline, it removes just the newline, and the name arrives. Always handle the leftover newline before a getline.

Alternative

Read the Line, Then Parse

There's a second approach that avoids the failed state altogether. Read the whole line as text, which practically always succeeds. Then try to convert it, in a string stream, where a failure costs nothing. If the parser can't read a number, say so. If it can, ask whether anything else is left on the line. If there is, reject it. Otherwise, accept. Run it with 12abc, hello, a blank line, and 7. Only the 7 gets through.

Comparison

Extraction Versus Line Reading

Compare the two approaches. Extracting from the keyboard accepts 12abc as 12, and leaves abc waiting to ambush the next read. Reading the line first rejects it. The failed state happens routinely with extraction, and must be cleared every time. Reading the line, only the parser fails. Extraction is shorter for a single simple value, and suits several numbers on one line. Reading the line suits anywhere a person types exactly one value.

Reuse

Turning the Loop into a Template

The loop is the same every time, apart from three things: the prompt, the acceptable range, and the message that explains it. Written with those three separated out, it becomes something to copy into any program and adjust in three places. Here, the lowest and highest months are constants. Anything that isn't a single whole number is rejected. A number outside the range gets a message naming the range. Copying is a stage, not the destination. A change to the wording has to be made in every copy, and one will be missed. Test it the way a person would break it: 13, a word, 0, and then 12. Chapter eight's tools let you package this block by name.

Testing

Eight Trials for Every Read

Every validated read deserves the same short list of trials. A valid value. A word instead of a number. An empty line. A value one below the minimum, and one above the maximum. The minimum and maximum themselves. And a valid number with something stuck to it. Eight entries, less than a minute, and they cover every route through the code you just wrote.

Quick Check

Input Ends Without a Valid Number

Quick check. The age loop from earlier is fed from a file that ends without a valid number. What does the program do, and why? Pause and think. It spins forever, printing its complaint. Clear makes the stream look healthy, but the input has ended, so every read fails again. A loop must also test for end of input, and stop.

Key Takeaways

Validation Rules to Remember

To summarize. Validation asks about form, then range, then leftovers. A failed stream is sticky. Clear it first, then ignore the rest of the line. Exit a reprompt loop only through a successful, sensible read. A range failure needs a helpful message, not a clear. And reading the whole line first rejects entries like 12abc.

About C++ Programming at UPI Study

C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.

Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Where the credit goes

Universities that work with NCCRS

C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.

FAQ

Questions students ask us

About Validating User Input

What are the four stream states in C++, and which ones can you recover from?
The four states are good, fail, eof, and bad. Good means the last read worked. Fail means a read could not be performed, such as letters typed where a number was expected, and it is recoverable with clear. Eof means input has run out, so you should stop the loop. Bad means the stream itself is broken, and it is effectively unrecoverable.
How do I fix cin after the user types letters instead of a number?
Call cin.clear() first, then cin.ignore(numeric_limits<streamsize>::max(), '\n'). Clear resets the fail state, and ignore throws away the bad text through the newline. Order matters: while the stream is failed, ignore does nothing, so calling it first leaves the bad characters waiting. Skipping ignore means the next read fails on the same letters again.
How do I write a loop that keeps asking until the user enters a valid number?
Use a flag such as bool accepted = false and loop with while (!accepted). Prompt, then read with if (cin >> age). On success, check the range and set accepted to true. On failure, print a helpful message, call clear, then ignore the rest of the line. The loop exits only through a successful, sensible read. Also test for end of input, or the loop may spin forever.
Why is it better to read a whole line with getline and then convert it?
Reading the whole line first lets you reject entries like 12abc that extraction with cin would accept as 12, leaving abc to break the next read. Read the line into a string, then parse it with an istringstream. If the number fails to parse, or anything remains on the line, reject it. Only the parser fails, so cin itself never needs clearing.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

Ready for the full course? Earn 3 credits in C++ Programming.

84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.

C++ Programming
3 credits · NCCRS
Enroll →