Page 1 of 1

Console Input Rate Topic: -----

#1 nuclearfroggy   User is offline

  • D.I.C Head
  • member icon

Reputation: 82
  • View blog
  • Posts: 167
  • Joined: 04-August 08

Posted 23 January 2012 - 12:02 PM

For any console based program, console I/O streams are the only direct means of communication between user and program. Despite being encountered from the very start, there’s something slightly confusing about the different options available when taking user input. For any console input in C++ we will make use of the header <iostream> and will make use of the istream class. For C we use the header <stdio.h>.

The >> operator is known as the extraction operator, and its main use is extracting and interpreting console input. For example, if you have an integer variable on the right hand side, this operator will attempt to parse the console input and give the variable a value. This is a really neat way of getting things like floating point numbers from the console, without having to call functions. When applied to string input, the extraction operator will read both C style strings (delimited by \0) and the C++ string class. For C style strings a ‘\0’ character is automatically added. The important thing to remember with >> is it stops at delimiters and leaves them in the stream. For example, if a newline character is read by >> no more input is processed and a newline is left next in the stream. Delimiters include all whitespace (spaces, tabs, newlines), which makes it impossible to take multiple words of text from the console at once. However, this only applies after it’s successfully read some input – the >> operator skips any whitespace before valid input is encountered. An example of the extraction operator is given below:
int val;

cin >> val;

Another nifty thing with the extraction operator is you can use things called manipulators to change how the operator functions, and the syntax is nice and clear e.g.
cin >> hex >> val;

This would take input as a hexadecimal rather than decimal value. For the complete reference on manipulators for input go here.

cin.getline() comes to the rescue for retrieving text from the console. There are two versions of getline():
istream &getline(char *s, streamsize n)
istream &getline(char *s, streamsize n, char delim)

For the first version, the default delimiters are the newline (\n) and any EOFs / null character. It’s important to remember getline() stops if it meets a delimiter and discards it from the stream. This is a major difference from the extraction operator. A global version of getline() is available that supports the string class, which is the same apart from an extra parameter – the input stream.
istream &getline(istream &is, string &str)
istream &getline(istream &is, string &str, char delim)

cin.get() is another option for console input in C++, and is overloaded to either read in blocks of text like getline() or just a single character.
int get()
istream &get(char &c)

istream &get(char *s, streamsize n)
istream &get(char *s, streamsize n, char delim)
istream &get(streambuf &sb)
istream &get(streambuf &sb, char delim)

The newline is the default delimiter. The first couple of versions just take a single character from the stream. The versions with the parameter of type streamsize read n - 1 characters from the stream and automatically add the terminating null character. If the delimiter is encountered, input stops and the character is left in the stream. The bottom two versions instead take a stream as parameter, and will keep reading until the delimiter is reached, taking input from the console and transferring it into the stream passed.

For the extraction operator, something is needed which can clear delimiters out of the way: cin.ignore() discards a single character from the stream
cin.ignore(streamsize n) discards n characters from the stream
cin.ignore(streamsize n, int delim)discards up to n characters, but if the delimiter is encountered it is also extracted and the function stops.

cin.clear() resets any flags that may have been set due to input failing e.g. characters given when a number was needed. This must be called before any calls to ignore(). To wipe the input use clear() and then ignore(), ignoring up to the next newline. The function ignore() should make sure it reaches the newline, so to ensure this pass numeric_limits<streamsize>::max() as the parameter for n. This requires including the header <limits>.

To ensure you do get valid input with >>, you can form a loop with the operator in the conditional statement, e.g.
while( !(cin >> foo) ) 
// clear stream

Similarly, getline() can be used as a condition e.g. to process multiple entries in a file
while(cin.getline(str, 16)) 
// process entry

Above for the function get(), there were a couple of overloaded versions of the function that took parameters of type streambuf – basically allowing the transferring of data from one stream to another. This introduces another way of taking input – using the stringstream class. To use this you need to include the header <sstream>. The main advantage of stringstream is it means a C++ string can be treated as a stream, so lets you use the extraction operator on it. The advantage of taking input as text, and then extracting the information from a stringstream is you separate the processes of input and interpretation. The following code snippet demonstrates this:
string str;
float price;

getline(cin, str);
stringstream(str) >> price;

In C, <stdio.h> (or <cstdio> in C++) is used for console input, so there’s no cin, no >> operator and no getline(). The input stream is represented by a FILE * pointer in C. In the C standard I/O library you can find the infamous gets(), which should be avoided at all costs. This is because it makes no checks on the length of the string passed, only stopping input when it reaches a delimiter, so potentially writing to memory way beyond the bounds of the string passed. Instead, the function
char *fgets(char *str, int num, FILE *stream) is recommended, and is much safer. fgets() reads at most num - 1 characters and automatically adds the terminating null character. Also, the function stops reading at the newline character but includes it in the string. If you don’t want newlines left in, you have to remove them yourself with an additional check e.g.
length = strlen(str);
if(str[length-1] == '\n')
	str[length-1] = '\0'; // trim newline

If you then want to extract something from this input, like an integer or floating point number, there are some functions in the standard library that do this for you. To use them, you need to include the header <stdlib.h> (<cstdlib>). They all take a string, and return the thing being extracted.
int atoi(const char *str)
double atof(const char *str)
long int atol(const char *str)

For some strange reason there are multiple ways of taking a single character from the input stream in C.
getchar() reads a single character from stdin – the standard input stream, which will be the console in a console application. It’s defined:
int getchar(void)
The function getc() reads a single character from the stream given and is defined:
int getc(FILE *stream)

This version is highly optimised, and may be implemented as a macro. It may evaluate its parameter more than once, so you shouldn’t use a statement as an argument, because freaky things will happen. Instead, in this situation you should use fgetc(), which does basically the same thing (but may be slightly slower).
int fgetc(FILE *stream)

C has a function, scanf(), that is able to read and parse console input. Its parameter works in a similar way to printf() with the % character indicating a variable and certain characters telling the function what the type is. The function takes pointers to these variables as additional arguments, allowing it to store the values parsed. scanf() allows an indefinite number of arguments, which is handy for formatted input, where you could have set columns and want to read rows at a time. The function is defined:
int scanf(const char *format, ...)
scanf() is complicated to use compared to other input functions. The parameter “format” is a C-string which lays out how the input should be read, allowing both fixed string input (stuff that’s assumed; part of the formatting) and data. Format specifiers tell the function where and what the data is, and should follow the form: %[*][width][modifiers]type
* indicates that the following argument should be read in but then discarded, i.e. not stored at the given variable. This is clearly optional.
“width” specifies the maximum number of characters to be read
The modifiers available are:
• h – for short integers
• l – for long integers
• L – for long doubles
The types you can take from input are as follows:
• c is for a single character
• d is for a decimal integer, of type int
• e / E / f / g / G are all for floating point numbers, of type float
• o is for an octal integer
• s is for a string, scanf() reads until whitespace is encountered, and leaves it in the stream. \0 is automatically appended.
• u is for an unsigned integer
• x / X is for a hexadecimal integer
Much like the extraction operator, scanf() will skip through any whitespace before reaching input and is only capable of reading single words in the case of string input. The function works through the parameter “format”, any character that isn’t whitespace or a format specifier (begins with %) in “format” causes the function to read the next character from stdin and compare it. If they differ, the function terminates and returns failure. In case of success, the function returns the number of items successfully read. Below is an example of scanf being used to read a string and then a float, where the two are separated by a ‘|’ in the input.
char str[32];
float val;

scanf("%s | %f", str, &val); // e.g. foo | 1.4f

Hope this clears up any questions over console input!

Is This A Good Question/Topic? 1
  • +

Page 1 of 1