DECLARING ARRAYS
Arrays may consist of any of the valid data types. Arrays are declared along with all other variables in the declaration section of the program.
/* Introducing array’s */
#include
main()
{
int numbers[100];
float averages[20];
numbers[2] = 10;
–numbers[2];
printf(“The 3rd element of array numbers is %dn”, numbers[2]);
}
Sample Program Output
The 3rd element of array numbers is 9
The above program declares two arrays, assigns 10 to the value of the 3rd element of array numbers, decrements this value ( –numbers[2] ), and finally prints the value. The number of elements that each array is to have is included inside the square brackets.
ASSIGNING INITIAL VALUES TO ARRAYS
The declaration is preceded by the word static. The initial values are enclosed in braces, eg,
#include
main()
{
int x;
static int values[] = { 1,2,3,4,5,6,7,8,9 };
static char word[] = { ‘H’,’e’,’l’,’l’,’o’ };
for( x = 0; x < 9; ++x )
printf(“Values [%d] is %dn”, x, values[x]);
}
Sample Program Output
Values[0] is 1
Values[1] is 2
….
Values[8] is 9
The previous program declares two arrays, values and word. Note that inside the squarebrackets there is no variable to indicate how big the array is to be. In this case, C initializes the array to the number of elements that appear within the initialize braces. So values consist of 9 elements (numbered 0 to 8) and the char array word has 5 elements.
The following program shows how to initialise all the elements of an integer based array to the value 10, using a for loop to cycle through each element in turn.
#include
main()
{
int count;
int values[100];
for( count = 0; count < 100; count++ )
values[count] = 10;
}
MULTI DIMENSIONED ARRAYS
Multi-dimensioned arrays have two or more index values which specify the element in the array.
multi[i][j]
In the above example, the first index value i specifies a row index, whilst j specifies a column index.
Declaration and calculations
int m1[10][10];
static int m2[2][2] = { {0,1}, {2,3} };
sum = m1[i][j] + m2[k][l];
NOTE the strange way that the initial values have been assigned to the two-dimensional array m2. Inside the braces are,
{ 0, 1 },
{ 2, 3 }
Remember that arrays are split up into row and columns. The first is the row, the second is the column. Looking at the initial values assigned to m2, they are,
m2[0][0] = 0
m2[0][1] = 1
m2[1][0] = 2
m2[1][1] = 3
EXERCISE C13
Given a two dimensional array, write a program that totals all elements, printing the total.
CLASS EXERCISE C14
What value is assigned to the elements which are not assigned initialised.
EXERCISE C13
Given a two dimensional array write a program that totals all elements printing the total.
#include
main()
{
static int m[][] = { {10,5,-3}, {9, 0, 0}, {32,20,1}, {0,0,8} };
int row, column, sum;
sum = 0;
for( row = 0; row < 4; row++ )
for( column = 0; column < 3; column++ )
sum = sum + m[row][column];
printf(“The total is %dn”, sum );
}
CLASS EXERCISE C14
They get initialised to ZERO.
CHARACTER ARRAYS [STRINGS]
Consider the following program,
#include
main()
{
static char name1[] = {‘H’,’e’,’l’,’l’,’o’};
static char name2[] = “Hello”;
printf(“%sn”, name1);
printf(“%sn”, name2);
}
Sample Program Output
Helloxghifghjkloqw30-=kl`’
Hello
The difference between the two arrays is that name2 has a null placed at the end of the string, ie, in name2[5], whilst name1 has not. This can often result in garbage characters being printed on the end. To insert a null at the end of the name1 array, the initialization can be changed to,
static char name1[] = {‘H’,’e’,’l’,’l’,’o’,’ ’};
Consider the following program, which initialises the contents of the character based array word during the program, using the function strcpy, which necessitates using the include file string.h
#include
#include
main()
{
char word[20];
strcpy( word, “hi there.” );
printf(“%sn”, word );
}
Sample Program Output
hi there.
SOME VARIATIONS IN DECLARING ARRAYS
int numbers[10];
static int numbers[10] = { 34, 27, 16 };
static int numbers[] = { 2, -3, 45, 79, -14, 5, 9, 28, -1, 0 };
static char text[] = “Welcome to New Zealand.”;
static float radix[12] = { 134.362, 1913.248 };
double radians[1000];
READING CHARACTER STRINGS FROM THE KEYBOARD
Character based arrays are often refered to in C as strings. C does not support a string type, so character based arrays are used in place of strings. The %s modifier to printf() and scanf() is used to handle character based arrays. This assumes that a 0 or NULL value is stored in the last element of the array. Consider the following, which reads a string of characters (excluding spaces) from the keyboard.
char string[18];
scanf(“%s”, string);
NOTE that the & character does not need to precede the variable name when the formatter %s is used! If the users response was
Hello
then
string[0] = ‘H’
string[1] = ‘e’
….
string[4] = ‘o’
string[5] = ‘ ’
Note how the enterkey is not taken by scanf() and the text string is terminated by a NULL character ‘ ’ after the last character stored in the array.

Practice Exercise 7: Arrays

2. Assign the character value ‘Z’ to the fourth element of the letters array
3. Use a for loop to total the contents of an integer array called numbers which has five elements. Store the result in an integer called total.
4. Declare a multidimensioned array of floats called balances having three rows and five columns.
5. Write a for loop to total the contents of the multidimensioned float array balances.
6. Assign the text string “Hello” to the character based array words at declaration time.
7. Assign the text string “Welcome” to the character based array stuff (not at declaration time)
8. Use a printf statement to print out the third element of an integer array called totals
9. Use a printf statement to print out the contents of the character array called words
10. Use a scanf statement to read a string of characters into the array words.
11. Write a for loop which will read five characters (use scanf) and deposit them into the character based array words, beginning at element 0.
Answers: Practice Exercise 7: Arrays
1. Declare a character based array called letters of ten elements
char letters[10];
2. Assign the character value ‘Z’ to the fourth element of the letters array
letters[3] = ‘Z’;
3. Use a for loop to total the contents of an integer array called numbers which has five elements. Store the result in an integer called total.
for( loop = 0, total = 0; loop < 5; loop++ )
total = total + numbers[loop];
4. Declare a multidimensioned array of floats called balances having three rows and five columns.
float balances[3][5];
5. Write a for loop to total the contents of the multidimensioned float array balances.
for( row = 0, total = 0; row < 3; row++ )
for( column = 0; column < 5; column++ )
total = total + balances[row][column];
6. Assign the text string “Hello” to the character based array words at declaration time.
static char words[] = “Hello”;
7. Assign the text string “Welcome” to the character based array stuff (not at declaration time)
char stuff[50];
strcpy( stuff, “Welcome” );
8. Use a printf statement to print out the third element of an integer array called totals
printf(“%dn”, totals[2] );
9. Use a printf statement to print out the contents of the character array called words
printf(“%sn”, words);
10. Use a scanf statement to read a string of characters into the array words.
scanf(“%s”, words);
11. Write a for loop which will read five characters (use scanf) and deposit them into the character based array words, begin
ning at element 0.
for( loop = 0; loop < 5; loop++ )
scanf(“%c”, &words[loop] );
FUNCTIONS
A function in C can perform a particular task, and supports the concept of modular programming design techniques.
We have already been exposed to functions. The main body of a C program, identified by the keyword main, and enclosed by the left and right braces is a function. It is called by the operating system when the program is loaded, and when terminated, returns to the operating system.
Functions have a basic structure. Their format is
return_data_type function_name ( arguments, arguments )
data_type_declarations_of_arguments;
{
function_body
}
ANSI C varies slightly in the way that functions are declared. Its format is
return_data_type function_name (data_type variable_name, data_type variable_name, .. )
{
function_body
}
This permits type checking by utilizing function prototypes to inform the compiler of the type and number of parameters a function accepts. When calling a function, this information is used to perform type and parameter checking.
ANSI C also requires that the return_data_type for a function which does not return data must be type void. The default return_data_type is assumed to be integer unless otherwise specified, but must match that which the function declaration specifies.
A simple function is,
void print_message( void )
{
printf(“This is a module called print_message.n”);
}
Note the function name is print_message. No arguments are accepted by the function, this is indicated by the keyword void in the accepted parameter section of the function declaration. The return_data_type is void, thus data is not returned by the function.
An ANSI C function prototype for print_message() is,
void print_message( void );
Function prototypes are listed at the beginning of the source file. Often, they might be placed in a users .h (header) file.
FUNCTIONS
Now lets incorporate this function into a program.
/* Program illustrating a simple function call */
#include
void print_message( void ); /* ANSI C function prototype */
void print_message( void ) /* the function code */
{
printf(“This is a module called print_message.n”);
}
main()
{
print_message();
}
Sample Program Output
This is a module called print_message.
To call a function, it is only necessary to write its name. The code associated with the function name is executed at that point in the program. When the function terminates, execution begins with the statement which follows the function name.
In the above program, execution begins at main(). The only statement inside the main body of the program is a call to the code of function print_message(). This code is executed, and when finished returns back to main().
As there is no further statements inside the main body, the program terminates by returning to the operating system.
FUNCTIONS
In the following example, the function accepts a single data variable, but does not return any information.
/* Program to calculate a specific factorial number */
#include
void calc_factorial( int ); /* ANSI function prototype */
void calc_factorial( int n )
{
int i, factorial_number = 1;
for( i = 1; i <= n; ++i )
factorial_number *= i;
printf(“The factorial of %d is %dn”, n, factorial_number );
}
main()
{
int number = 0;
printf(“Enter a numbern”);
scanf(“%d”, &number );
calc_factorial( number );
}
Sample Program Output
Enter a number
3
The factorial of 3 is 6
Lets look at the function calc_factorial(). The declaration of the function
void calc_factorial( int n )
indicates there is no return data type and a single integer is accepted, known inside the body of the function as n. Next comes the declaration of the local variables,
int i, factorial_number = 0;
It is more correct in C to use,
auto int i, factorial_number = 0;
RETURNING FUNCTION RESULTS
This is done by the use of the keyword return, followed by a data variable or constant value, the data type of which must match that of the declared return_data_type for the function.
float add_numbers( float n1, float n2 )
{
return n1 + n2; /* legal */
return 6; /* illegal, not the same data type */
return 6.0; /* legal */
}
It is possible for a function to have multiple return statements.
int validate_input( char command )
{
switch( command ) {
case ‘+’ :
case ‘-‘ : return 1;
case ‘*’ :
case ‘/’ : return 2;
default : return 0;
}
}
Here is another example
/* Simple multiply program using argument passing */
#include
int calc_result( int, int ); /* ANSI function prototype */
int calc_result( int numb1, int numb2 )
{
auto int result
result = numb1 * numb2;
return result
}
main()
{
int digit1 = 10, digit2 = 30, answer = 0;
answer = calc_result( digit1, digit2 );
printf(“%d multiplied by %d is %dn”, digit1, digit2, answer );
}
Sample Program Output
10 multiplied by 30 is 300
NOTE that the value which is returned from the function (ie result) must be declared in the function.
NOTE: The formal declaration of the function name is preceded by the data type which is returned,
int calc_result ( numb1, numb2 )
EXERCISE C15
Write a program in C which incorporates a function using parameter passing and performs the addition of three numbers. The main section of the program is to print the result.
Answer: EXERCISE C15
Write a program in C which incorporates a function using parameter passing and performs the addition of three numbers. The main section of the program is to print the result.
#include
int calc_result( int, int, int );
int calc_result( int var1, int var2, int var3 )
{
int sum;
sum = var1 + var2 + var3;
return( sum ); /* return( var1 + var2 + var3 ); */
}
main()
{
int numb1 = 2, numb2 = 3, numb3=4, answer=0;
answer = calc_result( numb1, numb2, numb3 );
printf(“%d + %d + %d = %dn”, numb1, numb2, numb3, answer);

LOCAL AND GLOBAL VARIABLES

Local
These variables only exist inside the specific function that creates them. They are unknown to other functions and to the main program. As such, they are normally implemented using a stack. Local variables cease to exist once the function that created them is completed. They are recreated each time a function is executed or called.
Global
These variables can be accessed (ie known) by any function comprising the program. They are implemented by associating memory locations with variable names. They do not get recreated if the function is recalled.
DEFINING GLOBAL VARIABLES
/* Demonstrating Global variables */
#include
int add_numbers( void ); /* ANSI function prototype */
/* These are global variables and can be accessed by functions from this point on */
int value1, value2, value3;
int add_numbers( void )
{
auto int result
result = value1 + value2 + value3;
return result
}
main()
{
auto int result
value1 = 10;
value2 = 20;
value3 = 30;
result = add_numbers();
printf(“The sum of %d + %d + %d is %dn”,
value1, value2, value3, final_result);
}
Sample Program Output
The sum of 10 + 20 + 30 is 60
The scope of global variables can be restricted by carefully placing the declaration. They are visible from the declaration until the end of the current source file.
#include
void no_access( void ); /* ANSI function prototype */
void all_access( void );
static int n2; /* n2 is known from this point onwards */
void no_access( void )
{
n1 = 10; /* illegal, n1 not yet known */
n2 = 5; /* valid */
}
static int n1; /* n1 is known from this point onwards */
void all_access( void )
{
n1 = 10; /* valid */
n2 = 3; /* valid */
}
AUTOMATIC AND STATIC VARIABLES
C programs have a number of segments (or areas) where data is located. These segments are typically,
_DATA Static data
_BSS Uninitialized static data, zeroed out before call to main()
_STACK Automatic data, resides on stack frame, thus local to functions
_C
ONST Constant data, using the ANSI C keyword const
The use of the appropriate keyword allows correct placement of the variable onto the desired data segment.
/* example program illustrates difference between static and automatic variables */
#include
void demo( void ); /* ANSI function prototypes */
void demo( void )
{
auto int avar = 0;
static int svar = 0;
printf(“auto = %d, static = %dn”, avar, svar);
++avar;
++svar;
}
main()
{
int i;
while( i < 3 ) {
demo();
i++;
}
}
Sample Program Output
auto = 0, static = 0
auto = 0, static = 1
auto = 0, static = 2
Static variables are created and initialized once, on the first call to the function. Subsequent calls to the function do not recreate or re-initialize the static variable. When the function terminates, the variable still exists on the _DATA segment, but cannot be accessed by outside functions.
Automatic variables are the opposite. They are created and re-initialized on each entry to the function. They disappear (are de-allocated) when the function terminates. They are created on the _STACK segment.
PASSING ARRAYS TO FUNCTIONS
The following program demonstrates how to pass an array to a function.
/* example program to demonstrate the passing of an array */
#include
int maximum( int [] ); /* ANSI function prototype */
int maximum( int values[5] )
{
int max_value, i;
max_value = values[0];
for( i = 0; i < 5; ++i )
if( values[i] > max_value )
max_value = values[i];
return max_value;
}
main()
{
int values[5], i, max;
printf(“Enter 5 numbersn”);
for( i = 0; i < 5; ++i )
scanf(“%d”, &values[i] );
max = maximum( values );
printf(“nMaximum value is %dn”, max );
}
Sample Program Output
Enter 5 numbers
7 23 45 9 121
Maximum value is 121
Note: The program defines an array of five elements (values) and initializes each element to the users inputted values. The array values is then passed to the function. The declaration
int maximum( int values[5] )
defines the function name as maximum, and declares that an integer is passed back as the result, and that it accepts a data type called values, which is declared as an array of five integers. The values array in the main body is now known as the array values inside function maximum. IT IS NOT A COPY, BUT THE ORIGINAL.
This means any changes will update the original array.

Functions and Arrays

C allows the user to build up a library of modules such as the maximum value found in the previous example.
However, in its present form this module or function is limited as it only accepts ten elements. It is thus desirable to modify the function so that it also accepts the number of elements as an argument also. A modified version follows,
/* example program to demonstrate the passing of an array */
#include
int findmaximum( int [], int ); /* ANSI function prototype */
int findmaximum( int numbers[], int elements )
{
int largest_value, i;
largest_value = numbers[0];
for( i = 0; i < elements; ++i )
if( numbers[i] > largest_value )
largest_value = numbers[i];
return largest_value;
}
main()
{
static int numb1[] = { 5, 34, 56, -12, 3, 19 };
static int numb2[] = { 1, -2, 34, 207, 93, -12 };
printf(“maximum of numb1[] is %dn”, findmaximum(numb1, 6));
printf(“maximum is numb2[] is %dn”, findmaximum(numb2, 6));
}
Sample Program Output
maximum of numb1[] is 56
maximum of numb2[] is 207
PASSING OF ARRAYS TO FUNCTIONS
If an entire array is passed to a function, any changes made also occur to the original array.
PASSING OF MULTIDIMENSIONAL ARRAYS TO FUNCTIONS
If passing a multidimensional array, the number of columns must be specified in the formal parameter declaration section of the function.
EXERCISE C16
Write a C program incorporating a function to add all elements of a two dimensional array. The number of rows are to be passed to the function, and it passes back the total sum of all elements (Use at least a 4 x 4 array).
#include
int add2darray( int [][5], int ); /* function prototype */
int add2darray( int array[][5], int rows )
{
int total = 0, columns, row;
for( row = 0; row < rows; row++ )
for( columns = 0; columns < 5; columns++ )
total = total + array[row][columns];
return total;
}
main()
{
int numbers[][] = { {1, 2, 35, 7, 10}, {6, 7, 4, 1, 0} };
int sum;
sum = add2darray( numbers, 2 );
printf(“the sum of numbers is %dn”, sum );
}
UNCTION PROTOTYPES
These have been introduced into the C language as a means of provided type checking and parameter checking for function calls. Because C programs are generally split up over a number of different source files which are independently compiled, then linked together to generate a run-time program, it is possible for errors to occur.
Consider the following example.
/* source file add.c */
void add_up( int numbers[20] )
{
….
}
/* source file mainline.c */
static float values[] = { 10.2, 32.1, 0.006, 31.08 };
main()
{
float result
result = add_up( values );
}
As the two source files are compiled separately, the compiler generates correct code based upon what the programmer has written. When compiling mainline.c, the compiler assumes that the function add_up accepts an array of float variables and returns a float. When the two portions are combined and ran as a unit, the program will definitely not work as intended.
To provide a means of combating these conflicts, ANSI C has function prototyping. Just as data types need to be declared, functions are declared also. The function prototype for the above is,
/* source file mainline.c */
void add_up( int numbers[20] );
NOTE that the function prototype ends with a semi-colon; in this way we can tell its a declaration of a function type, not the function code. If mainline.c was re-compiled, errors would be generated by the call in the main section which references add_up().
Generally, when developing a large program, a separate file would be used to contain all the function prototypes. This file can then be included by the compiler to enforce type and parameter checking.
ADDITIONAL ASSIGNMENT OPERATOR
Consider the following statement,
numbers[loop] += 7;
This assignment += is equivalent to add equals. It takes the value of numbers[loop], adds it by 7, then assigns the value to numbers[loop]. In other words it is the same as,
numbers[loop] = numbers[loop] + 7;
CLASS EXERCISE C17
What is the outcome of the following, assuming time=2, a=3, b=4, c=5
time -= 5;
a *= b + c;
CLASS EXERCISE C17
What is the outcome of the following, assuming time=2, a=3, b=4, c=5
time -= 5;
a *= b + c;
time = -3
a = 27
A SIMPLE EXCHANGE SORT ALGORITHM
The following steps define an algorithm for sorting an array,
1. Set i to 0
2. Set j to i + 1
3. If a[i] > a[j], exchange their values
4. Set j to j + 1. If j < n goto step 3
5. Set i to i + 1. If i < n - 1 goto step 2
6. a is now sorted in ascending order.
Note: n is the number of elements in the array.
EXERCISE C18
Implement the above algorithm as a function in C, accepting the array and its size, returning the sorted array in ascending order so it can be printed out by the calling module. The array should consist of ten elements.
A SIMPLE EXCHANGE SORT ALGORITHM
The following steps define an algorithm for sorting an array,
1. Set i to 0
2. Set j to i + 1
3. If a[i] > a[j], exchange their values
4. Set j to j + 1. If j < n goto step 3
5. Set i to i + 1. If i < n - 1 goto step 2
6. a is now sorted in ascending order.
Note: n is the number of elements in the array.
EXERCISE C18
Implement the above algorithm as a function in C, accepting the array and its size, returning the sorted array in ascending order so it can be printed out by the calling module. The array should consist of ten elements.
#include
void sort( int [], int );
void sort( int a[], int elements )
{
int i, j, temp;
i = 0;
while( i < (elements - 1) ) {
j = i + 1;
while( j < elements ) {
if( a[i] > a[j] ) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
j++;
}
i++;
}
}
main()
{
int numbers[] = { 10, 9, 8, 23, 19, 11, 2, 7, 1, 13, 12 };
int loop;
printf(“Before the sort the array was n”);
for( loop = 0; loop < 11; loop++ )
printf(” %d “, numbers[loop] );
sort( numbers, 11 );
printf(“After the sort the array was n”);
for( loop = 0; loop < 11; loop++ )
printf(” %d “, numbers[loop] );
}
RECURSION
This is where a function repeatedly calls itself to perform calculations. Typical applications are games and Sorting trees and lists.
Consider the calculation of 6! ( 6 factorial )
ie 6! = 6 * 5 * 4 * 3 * 2 * 1
6! = 6 * 5!
6! = 6 * ( 6 – 1 )!
n! = n * ( n – 1 )!
/* bad example for demonstrating recursion */
#include
long int factorial( long int ); /* ANSI function prototype */
long int factorial( long int n )
{
long int result
if( n == 0L )
result = 1L;
else
result = n * factorial( n – 1L );
return ( result );
}
main()
{
int j;
for( j = 0; j < 11; ++j )
printf(“%2d! = %ldn”, factorial( (long) j) );
}
RECURSIVE PROGRAMMING: EXERCISE C19
Rewrite example c9 using a recursive function.
#include
long int triang_rec( long int );
long int triang_rec( long int number )
{
long int result
if( number == 0l )
result = 0l;
else
result = number + triang_rec( number – 1 );
return( result );
}
main ()
{
int request;
long int triang_rec(), answer;
printf(“Enter number to be calculated.n”);
scanf( “%d”, &request);
answer = triang_rec( (long int) request );
printf(“The triangular answer is %ln”, answer);
}
Note this version of function triang_rec
#include
long int triang_rec( long int );
long int triang_rec( long int number )
{
return((number == 0l) ? 0l : number*triang_rec( number-1));

Practise Exercise 8: Functions

1. Write a function called menu which prints the text string “Menu choices”. The function does not pass any data back, and does not accept any data as parameters.
2. Write a function prototype for the above function.
3. Write a function called print which prints a text string passed to it as a parameter (ie, a character based array).
4. Write a function prototype for the above function print.
5. Write a function called total, which totals the sum of an integer array passed to it (as the first parameter) and returns the total of all the elements as an integer. Let the second parameter to the function be an integer which contains the number of elements of the array.
6. Write a function prototype for the above function.
Practise Exercise 8: Functions
1. Write a function called menu which prints the text string “Menu choices”. The function does not pass any data back, and does not accept any data as parameters.
void menu( void )
{
printf(“Menu choices”);
}
2. Write a function prototype for the above function.
void menu( void );
3. Write a function called print which prints a text string passed to it as a parameter (ie, a character based array).
void print( char message[] )
{
printf(“%s, message );
}
4. Write a function prototype for the above function print.
void print( char [] );
5. Write a function called total, which totals the sum of an integer array passed to it (as the first parameter) and returns the total of all the elements as an integer. Let the second parameter to the function be an integer which contains the number of elements of the array.
int total( int array[], int elements )
{
int loop, sum;
for( loop = 0, sum = 0; loop < elements; loop++ )
sum += array[loop];
return sum;

}
6. Write a function prototype for the above function.
int total( int [], int );
/* example one, to read a word at a time */
#include
#include
#define MAXBUFFERSIZE 80
void cleartoendofline( void ); /* ANSI function prototype */
void cleartoendofline( void )
{
char ch;
ch = getchar();
while( ch != ‘n’ )
ch = getchar();
}
main()
{
char ch; /* handles user input */
char buffer[MAXBUFFERSIZE]; /* sufficient to handle one line */
int char_count; /* number of characters read for this line */
int exit_flag = 0;
int valid_choice;
while( exit_flag == 0 ) {
printf(“Enter a line of text (
ch = getchar();
char_count = 0;
while( (ch != ‘n’) && (char_count < MAXBUFFERSIZE)) {
buffer[char_count++] = ch;
ch = getchar();
}
buffer[char_count] = 0x00; /* null terminate buffer */
printf(“nThe line you entered was:n”);
printf(“%sn”, buffer);
valid_choice = 0;
while( valid_choice == 0 ) {
printf(“Continue (Y/N)?n”);
scanf(” %c”, &ch );
ch = toupper( ch );
if((ch == ‘Y’) || (ch == ‘N’) )
valid_choice = 1;
else
printf(“ 07Error: Invalid choicen”);
cleartoendofline();
}
if( ch == ‘N’ ) exit_flag = 1;
}
}
Another Example, read a number as a string
/* example two, reading a number as a string */
#include
#include
#include
#define MAXBUFFERSIZE 80
void cleartoendofline( void ); /* ANSI function prototype */
void cleartoendofline( void )
{
char ch;
ch = getchar();
while( ch != ‘n’ )
ch = getchar();
}
main()
{
char ch;
/* handles user input */
char buffer[MAXBUFFERSIZE]; /* sufficient to handle one line */
int char_count; /* number of characters read for this line */
int exit_flag = 0, number, valid_choice;
while( exit_flag == 0 ) {
valid_choice = 0;
while( valid_choice == 0 ) {
printf(“Enter a number between 1 and 1000n”);
ch = getchar();
char_count = 0;
while( (ch != ‘n’) && (char_count < MAXBUFFERSIZE)) {
buffer[char_count++] = ch;
ch = getchar();
}
buffer[char_count] = 0x00; /* null terminate buffer */
number = atoi( buffer );
if( (number < 1) || (number > 1000) )
printf(“ 07Error. Number outside range 1-1000n”);
else
valid_choice = 1;
}
printf(“nThe number you entered was:n”);
printf(“%dn”, number);
valid_choice = 0;
while( valid_choice == 0 ) {
printf(“Continue (Y/N)?n”);
scanf(” %c”, &ch );
ch = toupper( ch );
if((ch == ‘Y’) || (ch == ‘N’) )
valid_choice = 1;
else
printf(“ 07Error: Invalid choicen”);
cleartoendofline();
}
if( ch == ‘N’ ) exit_flag = 1;
}
}
Other validation examples
More Data Validation
Consider the following program
#include
main() {
int number
printf(“Please enter a numbern”);
scanf(“%d”, &number );
printf(“The number you entered was %dn”, number );
}
The above program has several problems
      • the input is not validated to see if its the correct data type
      • it is not clear if there are explicit number ranges expected
      • the program might crash if an incorrect data type was entered
Perhaps the best way of handling input in C programs is to treat all input as a sequence of characters, and then perform the necessary data conversion.
At this point we shall want to explore some other aspects also, like the concepts of
      • trapping data at the source
      • the domino/ripple effect
Trapping Data At The Source
This means that the validation of data as to its correct range/limit and data type is best done at the point of entry. The benefits of doing this at the time of data entry are
      • less cost later in the program maintenance phase (because data is already validated)
      • programs are easier to maintain and modify
      • reduces the chances of incorrect data crashing the program later on
The Ripple Through Effect
This refers to the problem of incorrect data which is allowed to propagate through the program. An example of this is sending invalid data to a function to process.
By trapping data at the source, and ensuring that it is correct as to its data type and range, we ensure that bad data cannot be passed onwards. This makes the code which works on processing the data simpler to write and thus reduces errors.
An example
Lets look at the case of wanting to handle user input. Now, we know that users of programs out there in user-land are a bunch of annoying people who spend most of their time inventing new and more wonderful ways of making our programs crash.
Lets try to implement a sort of general purpose way of handling data input, as a replacement to scanf(). To do this, we will implement a function which reads the input as a sequence of characters.
The function is readinput(), which, in order to make it more versatile, accepts several parameters,
      • a character array to store the inputted data
      • an integer which specifies the data type to read, STRING, INTEGER, ALPHA
      • an integer which specifies the amount of digits/characters to read
We have used some of the functions covered in ctype.h to check the data type of the inputted data.
/* version 1.0 */
#include
#include
#define MAX 80 /* maximum length of buffer */
#define DIGIT 1 /* data will be read as digits 0-9 */
#define ALPHA 2 /* data will be read as alphabet A-Z */
#define STRING 3 /* data is read as ASCII */
void readinput( char buff[], int mode, int limit ) {
int ch, index = 0;
ch = getchar();
while( (ch != ‘n’) && (index < limit) ) {
switch( mode ) {
case DIGIT:
if( isdigit( ch ) ) {
buff[index] = ch;
index++;
}
break;
case ALPHA:
if( isalpha( ch ) ) {
buff[index] = ch;
index++;
}
break;
case STRING:
if( isascii( ch ) ) {
buff[index] = ch;
index++;
}
break;
default:
/* this should not occur */
break;
}
ch = getchar();
}
buff[index] = 0x00; /* null terminate input */
}
main() {
char buffer[MAX];
int number
printf(“Please enter an integern”);
readinput( buffer, DIGIT, MAX );
number = atoi( buffer );
printf(“The number you entered was %dn”, number );
}
Of course, there are improvements to be made. We can change readinput to return an integer value which represents the number
of characters read. This would help in determining if data was actually entered. In the above program, it is not clear if the user actually entered any data (we could have checked to see if buffer was an empty array).
So lets now make the changes and see what the modified program looks like
/* version 1.1 */
#include
#include
#define MAX 80 /* maximum length of buffer */
#define DIGIT 1 /* data will be read as digits 0-9 */
#define ALPHA 2 /* data will be read as alphabet A-Z */
#define STRING 3 /* data is read as ASCII */
int readinput( char buff[], int mode, int limit ) {
int ch, index = 0;
ch = getchar();
while( (ch != ‘n’) && (index < limit) ) {
switch( mode ) {
case DIGIT:
if( isdigit( ch ) ) {
buff[index] = ch;
index++;
}
break;
case ALPHA:
if( isalpha( ch ) ) {
buff[index] = ch;
index++;
}
break;
case STRING:
if( isascii( ch ) ) {
buff[index] = ch;
index++;
}
break;
default:
/* this should not occur */
break;
}
ch = getchar();
}
buff[index] = 0x00; /* null terminate input */
return index;
}
main() {
char buffer[MAX];
int number, digits = 0;
while( digits == 0 ) {
printf(“Please enter an integern”);
digits = readinput( buffer, DIGIT, MAX );
if( digits != 0 ) {
number = atoi( buffer );
printf(“The number you entered was %dn”, number );
}
}
}
The second version is a much better implementation.
Controlling the cursor position
The following characters, placed after the character in a printf() statement, have the following effect.
Modifier
Meaning
b
backspace
f
form feed
n
new line
r
carriage return
t
horizontal tab
v
vertical tab
\
backslash
double quote
single quote
line continuation
nnn
nnn = octal cha
racter value