Module 2. Basic components of C programming language
Lesson 6
INPUT/OUTPUT STATEMENTS IN C
6.1 Data Input and Output
Reading data and writing the processed data, i.e., information, are two essential operations performed by a typical C programme. Generally, the input data are read by the machine either by means of a standard input device like keyboard or a programmer-defined data file (which is usually a text file that may be created using notepad like text-editors). Similarly, the information is displayed via a standard output device such as monitor, and/or written onto a printer or saved as a user-defined output file. The method for assigning data values to the variables you have seen so far is the assignment statement. However, C supports several functions, viz., getchar, putchar, scanf, printf, gets and puts for transferring the data or information between computer and standard input/output (I/O) devices. The first two functions, getchar and putchar facilitate only single characters to be transferred into and out of computer; the scanf and printf functions allow the transfer of single characters, numerical values and strings; and the functions, gets and puts support the input and output of strings.
The I/O functions can be accessed from anywhere within a programme merely by writing the function name followed by a list of arguments enclosed in parentheses. The arguments correspond to data items being sent to the function. Some I/O functions do not involve arguments but the empty parentheses must appear even in such cases. Most versions of C include a collection of header files that provides necessary information in support of the various library functions.
6.2 Header Files
C uses header files that allow programmers to split certain elements of a source programme into reusable files. Generally, the header files contain forward declarations of subroutines, variables and other identifiers. If programmers want to declare standardised identifiers in more than one source file, they can place such identifiers in a single header file, which can be included in other codes whenever the header contents are required. This is to keep the interface in the header separate from the implementation. Hence, a header file is a file containing C declarations and macro definitions to be shared between several source files. You may request the use of a header file in your C programme by including it, with the C pre-processing directive, #include, e.g., the header file required by the standard I/O library functions is stdio.h. The C statement for this purpose is written as
#include <stdio.h>.
C pre-processor
The C pre-processor is a separate step in the compilation process, but it is not a part of the compiler. C pre-processor is just a text substitution tool. All pre-processor statements always begin with the number sign (or hash symbol), #. The unconditional directives are as follows:
· #define
Defines a pre-processor macro (discussed later in this lesson)
· #include Inserts a particular header from another file
· #undef Un-defines a pre-processor macro
Example 1
The following statement instructs the C pre-processor to replace instances of MAX_ARRAY_LENGTH with 20:
#define MAX_ARRAY_LENGTH 20
You should use #define for defining constants in C programmes so as to increase readability of the code.
Example 2
Similarly, the following statement directs the C pre-processor to get mystring.h header file from the local directory/folder and then add the text to the file:
#include mystring.h
Example 3
The following code segment guides the C pre-processor to un-define MEANING_OF_LIFE and define it for the constant 42:
#undef MEANING_OF_LIFE
#define MEANING_OF_LIFE 42
Refer the books given under Suggested Readings for the conditional and other types of pre-processor directive statements.
Now, let us resume the discussion about the header files. Header files serve two purposes:
· System header files declare the interfaces to parts of the operating system. You may include these header files in your C programme to supply the definitions and declarations you need to invoke system calls and libraries.
· User defined header files contain declarations for interfaces between the source files of the users programme. Each time the user has a group of related declarations and macro definitions all or most of which are needed in several different source files, it is a good idea to create a header file for them.
Although, including a header file produces the same results as copying the contents of the header file into each source file that needs it, but such copying would be time-consuming and error-prone. However, a header file facilitates the related declarations to appear only at a single place. In case of any change in the content of the header file, the change is made in one place and programmes that include the header file will automatically use its (header files) latest version when the programme is compiled afresh. Thus, the header file eliminates the labour of finding and changing all the copies as well as the risk that a failure to find one copy will result in inconsistencies within a programme.
In C, the usual convention is to give header files names that end with .h. Generally, only letters, digits, dashes, underscores and at most one dot are used in header file names. Every external function is mentioned in a header file, including libraries that are pre-compiled into object code, and source files required to build the C programme.
6.3 Standard Header Files
There are many operations that are not catered for in the C programming language, for instance, string manipulation. However, all compilers of C provide a set of libraries to provide this missing functionality, which are collectively known as the standard libraries. A list of header files is given in Table-6.1.
Table 6.1 Standard C header files
Name |
Description |
assert.h |
Contains the assert macro, used to assist with detecting logical errors and other types of bug in debugging versions of a programme. |
complex.h |
A set of functions for manipulating complex numbers. |
conio.h |
Console I/O Routines used in old MS-DOS compilers to create text user interfaces (not a part of standard library). |
ctype.h |
Contains functions used to classify characters by their types or to convert between upper and lower case in a way that is independent of the used character set. |
errno.h |
For testing error codes reported by library functions. |
fenv.h |
For controlling floating-point environment. |
float.h |
Contains defined constants specifying the implementation-specific properties of the floating-point library, such as the minimum difference between two different floating-point numbers (_EPSILON), the maximum number of digits of accuracy (_DIG) and the range of numbers, which can be represented (_MIN, _MAX). |
inttypes.h |
For precise conversion between integer types. |
iso646.h |
For programming in ISO 646 variant character sets. |
limits.h |
Contains defined constants specifying the implementation-specific properties of the integer types, such as the range of numbers, which can be represented (_MIN, _MAX). |
locale.h |
For setlocale and related constants. This is used to choose an appropriate locale. |
math.h |
For computing common mathematical functions. |
setjmp.h |
Declares the macros setjmp and longjmp, which are used for non-local exits. |
stdarg.h |
For accessing a varying number of arguments passed to functions. |
signal.h |
For controlling various exceptional conditions. |
stdbool.h |
For a Boolean data type. |
stdint.h |
For defining various integer types. |
stddef.h |
For defining several useful types and macros. |
stdio.h |
Provides the core input and output capabilities of the C language. This file includes the venerable printf function. |
stdlib.h |
For performing a variety of operations, including conversion, pseudo-random numbers, memory allocation, process control, environment, signalling, searching and sorting. |
string.h |
For manipulating several kinds of string. |
tgmath.h |
For type-generic mathematical functions. |
time.h |
For converting between various time and date formats. |
wchar.h |
For manipulating wide streams and several kinds of string using wide characters - key to supporting a range of languages. |
wctype.h |
For classifying wide characters. |
6.4 Single Character Input The getchar Function
Single character values can be input to a programme variable (computer memory) using C library function, getchar. This function belongs to the standard I/O Library supported by C. It returns a single character from a standard input device (keyboard). The function does not require any arguments, though a pair of parentheses must follow the keyword, getchar. In general form, a function reference is written as:
character variable = getchar();
where character variable refers to some previously declared character variable. For instance, consider the following C code segment:
char c;
. . .
c = getchar();
The first statement declares that c is a character type variable. The second statement causes a single character to be input from the standard input device (usually a keyboard) and then assigned to the variable, c. Note that getchar function can also be used to read multi-character strings by reading one character at a time using a suitable loop (see Module III for detailed description about loop control statements).
6.5 Single Character Output The putchar Function
Single characters can be displayed using C library function putchar. This function is complementary to the character input function getchar. This function is also a part of the standard I/O Library supported by C. It transmits a single character to a standard output device (usually a monitor). The character being transmitted is represented as a character type variable. It must be expressed as an argument to the function enclosed in parentheses following the keyword, putchar.
For instance, consider the following C code segment:
char c;
. . .
putchar(c);
The first statement declares that c is a character type variable. The second statement causes the current value of c to be transmitted to the standard output device (e.g., monitor) where it will be displayed. Note that getchar function can also be used to output a string constant by storing the string within a one-dimensional character type array. Each character can then be written separately within a loop (discussed in Module-III).
6.6 Entering Input Data The scanf Function
Input data can be entered into the computers memory from a standard input device by means of the C library function scanf. This function facilitates to enter any combination of numerical values, single characters and strings. The function returns the number of data items that have been entered successfully. The general syntax of the scanf function is:
scanf(control string, arg_1, arg_2, , arg_n)
where control string refers to a string containing certain required formatting information and arg_1, arg_2, , arg_n are arguments that represent the individual input data items. In fact, the arguments correspond to pointers that lead to the addresses of the data items within the computers memory.
The control string consists of individual groups of characters, with one character group for each input data item. Each character group must begin with a percent symbol (%). In its simplest form, a single character group will consist of the percent symbol followed by a conversion character, which indicates the type of the corresponding data item.
Within the control string, multiple character groups can be contiguous, or they can be separated by white space characters, i.e., blank spaces, tabs or newline characters. If white space characters are used to separate multiple character groups in the control string, then all consecutive white space characters in the input data will be read but ignored. The use of blank spaces as character-group separators is a very common practice among the C programmers. The commonly used conversion characters are listed in Table-6.2.
The arguments are written as variables or arrays, whose types match the corresponding character groups in the control string. Each variable name must be preceded by an ampersand (&). The arguments are actually pointers that indicate where the data items are stored in computers memory. However, array names should not begin with an ampersand.
Table 6.2 Commonly used scanf Conversion Characters
Conversion Character |
Description |
|
c |
Data item is a single character |
|
d |
Data item is a decimal integer |
|
e |
Data item is a floating-point value |
|
f |
Data item is a floating-point value |
|
g |
Data item is a floating-point value |
|
h |
Data item is a short integer |
|
i |
Data item is a decimal, hexadecimal, or octal integer |
|
o |
Data item is an octal integer |
|
s |
Data item is a string followed by a white space character (the null character \0 will automatically be added at the end) |
|
u |
Data item is an unsigned decimal integer |
|
x |
Data item is a hexadecimal integer |
|
[. . .] |
Data item is a string, which may include white space characters |
|
A prefix may precede certain conversion characters. |
||
Prefix |
Description |
|
h |
Short data item (short integer or short unsigned integer) |
|
l |
Long data item (long integer, long unsigned integer or double) |
|
L |
Long data item (long double) |
|
Example 4: The following segment of a C programme depicts a typical application of the scanf function.
char part_name[20];
int part_no;
float unit_price;
. . .
scanf(%s %d %f, part_name, &part_no, &unit_price);
In the above example, the control string within the scanf function is %s %d %f. Evidently, it contains three character groups. The first character group, %s indicates that the first argument (part_name) represents a string; the second character group, %d indicates that the second argument (&part_no) represents a decimal integer; and the third character group, %f indicates that the third argument (&unit_price) represents a floating-point value. Note that the numerical variables part_no and unit_price are prefixed by an ampersand within the scanf function. However, an ampersand does not precede part_name being an array name. Also, note that the aforementioned scanf statement can be written as scanf(%s%d%f, part_name, &part_no, &unit_price); without any white space characters in the control string. This is valid. |
The actual data items entered through a standard input device (keyboard) are numeric values, single characters or strings or some combination thereof. These data items must correspond in number, in type and in order to the arguments mentioned in the scanf function. Numeric values are supplied same as numeric constants while floating-point values must have either a decimal point or an exponent (or both). If two or more data items are entered, they must be separated by white space characters. The data items may run in two or more lines, because the newline character is considered to be a white space character and can, therefore, separate consecutive data items. Moreover, if the control string begins with reading a character type data item, it is generally a good idea to precede the first conversion character with a blank space. This causes the scanf function to ignore any extraneous characters that may have been entered earlier, e.g., the following segment of a C programme depicts this: char part_name[20]; int part_no; float unit_price; . . . scanf( %s %d %f, part_name, &part_no, &unit_price); Note the blank space that precedes the %s. This prevents any previously entered superfluous characters from being assigned to part_name. The following data values can be entered from standard input device while the programme is executed. button 12345 0.002 Thus, the characters that make up the string button would be assigned to the first six elements of the array variable, part_name; the integer value, 12345 would be assigned to the variable part_no, and the floating-point value 0.002 would be assigned to the variable, unit_price. Note that individual items are entered on one line separated with blank spaces. However, these data values could be entered on separate lines too as newline characters are considered as white space characters. Hence, the data values could be entered in any of the following three ways: |
(i) |
(ii) |
(iii) |
Button |
Button |
button 12345 |
12345 |
12345 0.002 |
0.002 |
0.002 |
|
|
Note that the s-type conversion character applies to a string that is terminated by a white space character. Thus, the string containing white space characters cannot be entered in this manner rather there are ways to deal with such strings that include white space characters. One way is to use the getchar function within loop (see Module III). Alternatively, you can use scanf function to enter such strings. For this, the s-type conversion character within the control string is replaced by a sequence of characters enclosed in square braces. White space characters may be incorporated within the brackets so as to accommodate strings with such characters. When the programme is running, successive characters will continue to be read from the standard input device as long as each input character matches one of the characters enclosed within the square braces. The order of characters within the square braces need not correspond to the order of characters being entered. Input characters can be repeated. The string will terminate once an input character is encountered that does not match any of the characters specified within the square braces. A null character (\0) will then automatically be added to the end of the string.
Example 5: The following programme segment demonstrates the use of scanf function to feed a string (of undetermined length but restricted to maximum 80 characters including the null character) consisting of uppercase letters and blank spaces. Note the blank space that precedes the % symbol in the scanf statement.
char line[80];
. . .
scanf( %[ABCDEFGHIJKLMNOPQRSTUVWXYZ], line);
If the input string
NEW DELHI CITY
is entered from the standard input device when the programme is executed, the entire string will be assigned to the array, line as the string is comprised of uppercase letters and blank spaces. However, if the string were written as
New Delhi City
then only the single letter, N would be assigned to the array variable, line, because the first lowercase letter, i.e., e in this example, would be interpreted as the first character beyond the string.
6.7 Writing Output Data The printf Function
The information generated by a programme after processing the input data can be transmitted from computer to a standard output device (typically a monitor or printer) using the library function printf. This function can be used to output any combination of numerical values, single characters and strings. The general syntax for the printf function is
printf(control string, arg_1, arg_2, , arg_n);
where control string refers to a string that contains formatting information and arg_1, arg_2, , arg_n are arguments that represent the individual output data items. The arguments can be written as constants, single variable or array variable or even more complex expressions; function references may also be included. Mind it carefully that unlike scanf function, the arguments in printf function do not represent memory addresses and, therefore, are not preceded by ampersand. The control string consists of individual control groups of characters, with one character group for each output data item. Each control group must begin with a percent symbol (%) followed by a conversion character (as given in Table-6.3) specifying the type of the corresponding data item. Multiple character groups can be contiguous or they can be separated by other characters including white space characters. These other characters are transferred directly to the output device(s), where they are displayed and/or written. The use of blank space(s) as character group delimiters is a common practice. A list of commonly used conversion characters is given in Table-6.3.
Table 6.3 printf conversion characters
Conversion Character |
Description |
|
c |
Data item is displayed as a single character |
|
d |
Data item is displayed as a signed decimal integer |
|
e |
Data item is displayed as a floating-point value with an exponent |
|
f |
Data item is displayed as a floating-point value without an exponent |
|
g |
Data item is displayed as a floating-point value using either e-type or f-type conversion, depending on value; trailing zeros, trailing decimal point will not be displayed. |
|
i |
Data item is displayed as a signed decimal integer |
|
o |
Data item is displayed as an octal integer, without a leading zero |
|
s |
Data item is displayed as a string |
|
u |
Data item is displayed as an unsigned decimal integer |
|
x |
Data item is displayed as a hexadecimal integer, without leading 0x |
|
Some of these characters are interpreted differently than with the scanf function. A prefix may precede certain conversion characters. |
||
Prefix |
Description |
|
h |
Short data item (short integer or short unsigned integer) |
|
l |
Long data item (long integer, long unsigned integer or double) |
|
L |
Long data item (long double) |
|
Example 6:
#include <stdio.h>
#include <math.h>
. . .
float i = 2.0, j = 3.0;
printf(%f %f %f %f, i, j, i+j, sqrt(i+j));
. . .
Note that the first two arguments within the printf function are single variables; the third argument is an arithmetic expression and the last argument is a function reference that has a numeric expression as an argument. Executing the programme (after completing the missing statements to be discussed later) would produce the following output;
2.000000 |
3.000000 |
5.000000 |
2.236068 |
Example 7:
The following programme segment demonstrates as to how different types of data can be displayed using the printf function:
char part_name[20];
int part_no;
float unit_price;
. . .
scanf(%s
%d %f, part_name, &part_no,
&unit_price);
. . .
printf(%s
%d %f, part_name, part_no,
unit_price);
Example 8:
The following C programme converts the given length in feet to centimetre. You know that one foot contains 30.48 cm. (See Example-1 of Lesson-2 for pseudo code for this programme)
Note: Students may like to refer to the Section 7.7 of Lesson-7 for structure of a typical C programme.
#include <stdio.h>
void main ()
{
float len_ft, len_cm;
printf("Length in feet: ");
scanf("%f", &len_ft);
len_cm=len_ft*30.48;
printf("\nLength in feet is = %f", len_ft);
printf("\nLength in cm is = %f", len_cm);
getch();
}
Input
Length in feet : 1
Output
Length in feet is = 1
Length in cm is = 30.48