You are on page 1of 45

INTRODUCTION TO

STRUCTURED PROGRAMMING

Validations
Input validation
Having seen the material on loops and functions, it is
nowpossible to makeprograms with a logical processof
repetition according to very precise conditions.

One of the very common uses of loops is in validating


user input. When a program prompts a user to give an
input, the program often needs to obtain a value that
follows a precise input format.
Input validation
#include <iostream>
using namespace std;
int main()
{
int value;
cout << "Enter a numerical value:";
cin >> value;
cout << value << endl;
return 0;
}

In this block of code, we’re asking the user to input a


numerical value, but nothing prevents the userfrom
entering anything at all: an int, a double or even a
string!
Input validation
When this type of error occurs,we get the impression
that nothing bad has happened, but this is wrong! The
cin object is placed in fail mode, and every subsequent
useof cin following this input error will causeanother
error, while and as long as the cin object has not exited
fail mode.
Input validation – cin.fail()
When fail mode isactivated onthe cin object, it is
possible to fix the state of the object by using the fail()
function in a while loop (the best loop to use in the case
of a validation)
Input validation – cin.fail()
int main()
{
int value;
cout << "Enter a numerical value: "; cin
>> value;
while (cin.fail())
{
cout << "Warning – Enter a numerical value:";
cin >> value;
}
cout << value << endl;
return 0;
}
Input validation – cin.clear()
But that’s not all! The fact of verifying that the cin object
is in fail mode does not make it exit that mode. It’s
necessary to use the function cin.clear() for that
Input validation – cin.clear()

int value;
cout << "Enter a numerical value: ";
cin >> value;
while (cin.fail())
{
cin.clear(); // the object cin exits fail mode
cout << "Warning – numerical value!: ";
cin >> value;
}

Input validation – cin.ignore(512, ‘\n’)
But we’re missing one last important point, clearing the
input buffer:

int value;
cout << "Enter a numerical value: ";
cin >> value;
while (cin.fail())
{
cin.clear(); // the object cin exits fail mode
cin.ignore(512, '\n');
cout << "Warning – numerical value!: ";
cin >> value;
}

The input buffer

The input buffer is a region in memory that serves to


store information input by the user, while the information
is waiting to be transferred to the variable after the
Enter key is pressed.
For example, if you input 12 and you press Enter, the
buffer will look like this before the value is transferred
to the variable:
The input buffer
Next, this value is transferred into a variable of type int, character by character,
starting with the first character that was input into the buffer, for example:

int value;
cout << "Enter a numerical value: ";
cin >> value; // transfers the entered value
The buffer will be cleared up to the line feed character (\n, Enter) if the value can
be completely placed in the variable. The variable value now contains 12.
The input buffer

But if the value cannot be transferred:


The input buffer
int value;
cout << "Enter a numerical value: ";
cin >> value; // transfers the entered value
The variable value still contains whatever it contained
before, and the buffer is still full.
The object cin enters into fail mode.
The input buffer

But what happens when the object cin is able to transfer


at least one of the characters into the variable?
The input buffer
int value;
cout << "Enter a numerical value: ";
cin >> value; // transfers the entered value
Only valid numerical values will be placed into the variable.
Thevariable value nowcontains 2. Theobject cindoes not
enter into fail mode, even if it should! In the input buffer,
some characters remain, and they will be automatically
included in the next input.
The input buffer – cin.peek() != ‘\n’

Soto protect ourselvesagainst this type of error, we


should use the cin.peek() function, which returns the first
character available in the input buffer after all the
values have been transferred.
If the value is not equal to ‘\n’ (line feed character,
Enter),this isbecause there was a problem when
transferring values from the buffer to the variable.
The input buffer – cin.peek() != ‘\n’
◻ The code for handling this case is as follows:
int value;
cout << "Enter a numerical value: ";
cin >> value; // transfers the entered value
while (cin.fail() || cin.peek() != '\n')
{
cin.clear();
cin.ignore(512, '\n');
cout << "Warning – numerical value!: ";
cin >> value;
}
cout << value << endl;
A good habit for the future…

And finally, we should immediately get in the habit of
placing a cin.ignore(512, '\n') after the while:
A good habit for the future…
...
int value;
cout << "Enter a numerical value: ";
cin >> value; // transfers the entered value
while (cin.fail() || cin.peek() != '\n')
{
cin.clear();
cin.ignore(512, '\n');
cout << "Warning – numerical value!: ";
cin >> value;
}
cin.ignore(512, '\n');
cout << value << endl;
Input validation function

Since we would like to be able to reuse these


instructions more than once, we can take all the code
onthe previous slide and put it into the function
definition of a function that takes no input and returns
an int. Its signature has the following syntax:

int readInt();
Function calls without parameters
Then we can use the function as follows:
int main()
{
int val1 = readInt();
int val2 = readInt();
int val3 = readInt();
cout << val1 << val2 << val3 << endl;
return 0;
}
Other types of input
◻So far, we’ve mostly only used cin for numerical input
◻We might also want the user to input other types of
data, such as strings
◻However, this comes with its own set of concerns
https://www.youtube.com/watch?v=yMwA4u7eXEY

https://www.youtube.com/watch?v= o1jE0JSiE
Character strings
◻ When requesting a value by input, we have gotten in
the habit of using cin to accomplish the task, but in the
caseof character strings, cin isnot adapted for the
task.
◻ In a string, there are often spaces and tabulations
(tabs). Thecin object considers these characters as
field separators, or field delimiters (characters
prompting the termination of reading from a
variable).
Character strings
For the following code, if we input Hello World…
#include <iostream>
using namespace std;

int main()
{
char str[20];
cout << "Enter a message: ";
cin >> str;
cout << str << endl;
return 0;
}
Character strings

Only Hello is displayed, since the space in the input


message (between Hello and World) is treated as an
end-of-field character (separator/delimiter). But what
happens to the other characters that remain in the
buffer?
Character strings
For the following code, if we input Hello World
#include <iostream>
using namespace std;

int main()
{
char str[20];
cout << "Enter a message: ";
cin >> str;
cout << str << endl;
cout << "Enter another message: ";
cin >> str;
cout << str << endl;
return 0;
}
Character strings

Theother characters remaining in the buffer are


automatically sent to the next input, and cause a failure:
the cin object isin semi-fail mode, for cin.peek() would
return us a character different than ‘\n’ (character 32 in
fact, which is the Space character).
Character strings
Buthowcanwe input a value in the form of a character
string when the input contains spaces or tabs?

By replacing the use of cin >> with the use of the


cin.getline() function. Thisfunction takes a pointer to a
char asits first parameter, and takes the maximumsize of
the string as its second parameter:
Character strings
What happens now?
#include <iostream>
using namespace std;

int main()
{
char str[20];
cout << "Enter a message: ";
cin.getline(str, 20);
cout << str << endl;
cout << "Enter another message: ";
cin.getline(str, 20);
cout << str << endl;
return 0;
}
Character strings

But what happens when the user inputs too


many characters given the size of the array?
Character strings
#include <iostream>
using namespace std;

int main()
{
char str[20];
cout << "Enter a message: ";
cin.getline(str, 20);
cout << str << endl;
return 0;
}
Character strings
On the face of it, the only problem that has occurred is
that only one part of the string is copied into the array.
But in the background, something else has happened!
Character strings
#include <iostream>
using namespace std;

int main()
{
char str[20];
cout << "Enter a message: ";
cin.getline(str, 20);
cout << str << endl;
cout << "Enter another message: ";
cin.getline(str, 20);
cout << str << endl;
return 0;
}
Character strings

The cin object has fallen into fail mode…

Thus we need to apply an input validation to prevent this


kind of problem.
Character strings
#include <iostream>
using namespace std;
int main()
{
char str[20];
cout << "Enter a message (max 20 characters): " << endl;
cin.getline(str, 20);
while (cin.fail())
{
cin.clear();
cin.ignore(512, '\n');
cout << "Enter a message (max 20 characters): " << endl;
cin.getline(str, 20);
}
cout << str << endl;
return 0;
}
Character strings
We can see that the first message we give as input causes
the code to enter into the while loop and to ask again for
input.
If we then enter a shorter message that doesn’t exceed the
limit of 20 characters, our messagewill be displayed
properly:
Character strings
When we discussed validating values input with cin, we
placed an extra cin.ignore(512,‘\n’); following the end of
the input and validation. Something similar is used here.
int val;
cin >> val;
while (cin.fail() || cin.peek() != '\n')
{
cin.clear();
cin.ignore(512, '\n');
cin >> val;
}
cin.ignore(512, '\n');
Character strings
Adding this command was specifically in anticipation of our
future use of cin.getline().
Let’s take the following code:
Character strings
#include <iostream>
using namespace std;

int main()
{
char str[20];
cout << "Enter a message (max 20 characters): " <<
endl;
cin.getline(str, 20);
cout << str << endl;
int val;
cout << "Enter a number: ";
cin >> val;
cout << val << endl;
return 0;
Character strings

All seems to be going well...

But if we invert the order of execution of cin and


cin.getline():
Character strings
#include <iostream>
using namespace std;

int main()
{
int val;
cout << "Enter a number: ";
cin >> val;
cout << val << endl;
char str[20];
cout << "Enter a message (max 20 characters): " <<
endl;
cin.getline(str, 20);
cout << str << endl;
return 0;
Character strings
The behaviour is not correct. The program does not give us
the time to enter a message to fill the string with.
The reason is that, when we use the cin object to input
numerical values, after the input, there remainsin the
buffer the character ‘\n’ (which is in fact a line return).
Character strings
Upon subsequently calling cin.getline(), this remaining
character isautomatically interpreted by the function, and
applies a line return without giving the user the opportunity
to input anything.

It isfor this reason that we need to add the call to


cin.ignore() after usinga cin: it isin order to ensurethat
nothing remains left over in the buffer after using the cin.
Character strings
#include <iostream>
using namespace std;

int main()
{
int val;
cout << "Enter a number: ";
cin >> val;
cout << val << endl;
cin.ignore(512, '\n');
char str[20];
cout << "Enter a message (max 20 characters): " << endl;
cin.getline(str, 20);
cout << str << endl;
return 0;
}
Conclusion

Always know what is in the input buffer!

You might also like