There are a variety of library functions for handling input data that has been read in using gets(). The most useful include sscanf() and the function atoi(). The function sscanf() applies scanf() type conversions to data held in a program buffer as a single string rather than to data read from standard input. The atoi() function converts a character string from external decimal form to internal binary form.
The use of sscanf() in conjunction with gets() is illustrated by the following program, known as getin1. The purpose of the program is to read in an integer. Unlike simple uses of scanf(), input errors are detected and the prompt repeated until a valid integer is entered.
main()
{
char error;
char inbuf[256]; /* hope it's big enough */
int i;
char c;
while(1)
{
error = i = 0;
printf("Enter an integer ");
gets(inbuf); /* get complete input line */
while(*(inbuf+i) == ' ') i++; /* skip spaces */
if(*(inbuf+i) == '-' || *(inbuf+i) == '+') i++;
while(c = *(inbuf+i++)) /* while string end NUL */
{
if(c>'9' || c<'0') /* non-digit ? */
{
printf("Non-Numeric Character %c\n",c);
error = 1;
break;
}
}
if(!error) /* was everything OK ? */
{
int num; /* local variable */
sscanf(inbuf,"%d",&num); /* conversion */
printf("Number was %d\n",num);
break;
}
}
}
A typical dialogue is shown below $ getin1 Enter an integer a123 Non-Numeric Character a Enter an integer 123a Non-Numeric Character a Enter an integer 1234.56 Non-Numeric Character . Enter an integer 1234 Number was 1234 $ getin1 Enter an integer +43 Number was 43 $
There are some interesting points about this program. The main processing loop first skips any leading spaces leaving the address "inbuf+i" pointing to the first non-blank character in the input text. An initial sign is also skipped. After the optional initial sign all input characters must be digits until the input string terminating NUL is encountered. If anything other than a digit, including trailing blanks, is encountered the loop is broken and an error indicator set.
The condition
c = *(inbuf+i++) associated with the loop that checks for digits is a typical piece of C code that does several things in one go. The value of the expression "*(inbuf+i++)" is the next character from the input buffer inbuf. The value of the expression inbuf+i++ being the address of the character and the * operator yielding the value of the addressed item. In the course of calculating the address of the character, the variable "i" is incremented as a side-effect. The character value is assigned to the variable "c" to be used in the test for being a digit on the following line, the value of the assignment expression being, of course, the value assigned. The value of this expression only becomes zero, so terminating the loop, when the character in question is the string terminating NUL.
In practice the code of this program would be incorporated into a user defined function that might well return the value of the entered integer.
The function sscanf() is similar to scanf() except that it has an extra parameter that is the address of the start of the memory area that holds the character string to be processed. The library function atoi() could have been used instead of sscanf() in this example by changing the appropriate line to read
num = atoi(inbuf);
The function i atoi() takes the address of an area of memory as parameter and converts the string stored at that location to an integer using the external decimal to internal binary conversion rules. This may be preferable to sscanf() since atoi() is a much smaller, simpler and faster function. sscanf() can do all possible conversions whereas atoi() can only do single decimal integer conversions.