Chapter 1

Overview of ‘C’

CHAPTER OUTLINE
1.1 THE HISTORY

In 1971 Dennis Ritchi, a system programmer from Bell laboratories, developed a very powerful language called C for writing UNIX, a large and complex operating system. Even the compiler of ‘C’ was written in C. In fact, it is a high level language that not only supports the necessary data types and data structures needed by a normal programmer but it can also access the computer hardware through specially designed declarations and functions and, therefore, it is often called as a “middle-level” language.

It is popular because of the following characteristics:

  • Small size
  • Wide use of functions and function calls
  • Loose typing
  • Bitwise low level programming support
  • Structured language
  • Wide use of pointers to access data structures and physical memory of the system

Besides the above characteristics, the C programs are small and efficient. A ‘C’ program can be compiled on variety of computers.

1.2 CHARACTERS USED IN ‘C’

The set of characters allowed in ‘C’ consists of alphabets, digits, and special characters as listed below:

  1. Letters: Both upper case and lower case letters of English:

     

    A, B, C, …. X, Y, and Z

    a, b, c, …. x, y, and z

     

  2. Decimal digits:

     

    0, 1, 2, …. 7, 8, 9

     

  3. Special characters:

     

    ! * + “ <<

    #(= ! {

    %) ; “ /

    ^_ [ :, ?

    &_ ]’ . blank

1.3 DATA TYPES

Every program specifies a set of operations to be done on some data in a particular sequence. However, the data can be of many types such as a numbers, characters, floating points, etc. ‘C’ supports the following simple data types: Integer data type, character data type, floating point data type.

1.3.1 Integer Data Type (int)

An integer is an integral whole number without a decimal point. These numbers are used for counting. Examples of integers are:

 

923

47

5

15924

−56

2245

‘C’ allows four types of representation of integers, i.e., integer, long integer, short integer, and unsigned integer.

  • Integer: An integer is referred to as int. It is stored in one word of the memory.
  • Long integer: A long integer is referred to as long int or simple long. It is stored in 32 bits and does not depend upon the word size of the memory.
  • Short integer: A short integer is referred to as short int or simple short. It is stored in 16 bits and does not depend upon the size of the memory.
  • Unsigned integers: C supports two types of unsigned integers: the unsigned int and the unsigned short.

The unsigned int is stored in one word of the memory whereas the unsigned short is stored in 16 bits and does not depend upon the word size of the memory.

Examples of invalid integers are:

  (i) 9, 24, 173 illegal-comma used
  (ii) 5.29 illegal-decimal point used
  (iii) 79 248 blank used

1.3.2 Character Data Type (char)

It is a non-numeric data type consisting of single alphanumeric character enclosed between a pair of apostrophes, i.e., single quotation marks.

Examples of valid character type are:

‘A’

‘N’

‘*’

‘7’

It may be noted that the character ‘7’ is different from the numeric value 7. In fact, former is of type char and later of type int. Each character has a numeric code, i.e., the ASCII code. For instance, the ASCII code for the character ‘A’ is 65 and that of ‘*’ is 42. A table of ASCII codes is given in Appendix A.

A character data type is referred to as char. It is stored in one byte of memory. However, the representation varies from computer to computer. For instance, some computers support signed as well as unsigned characters. The signed characters can store integer values from –128 to +127 whereas the unsigned characters store ASCII codes from 0 to 255.

1.3.3 The Floating Point (float) Data Type

A floating point number is a real number which can be represented in two forms: decimal and exponent forms. Floating point numbers are generally used for measuring quantities.

  1. Decimal form: The floating point number in this form has a decimal point. Even if it is an integral value, it must include the decimal point.

    Examples of valid “decimal form” numbers are:

       973.24
       849.
        73.0
    –82349.24
         9.0004
  2. Exponent form: The exponent form of floating point number consists of the following parts:
         <integer>. <fraction> e <exponent>

    Examples of valid floating point numbers are:

     

    3.45 e 7

    0.249 e –6

It may be noted that exponent form is a scientific notation wherein the number is broken into two parts: mantissa and exponent. The mantissa is a floating point number of decimal form. The exponent part starts with a letter ‘e’ followed by an integer (signed or unsigned).

For example, the number 324.5 can be written as 3.245 times 102. In exponential form, the number is represented as 3.245 e2. In fact, the base 10 has been replaced by the character e (or E).

The utility of exponential form is that very small numbers can be easily represented by this notation of floating points.

For example, the number 0.00001297 can be written as 0.1297 e–4 or as 12.97 e–6 or as 129.7 e–7.

‘C’ allows the following two data types for floating prints:

  • float: These types of numbers are stored in 32 bits of memory.
  • double: The numbers of double data type are stored in 64 bits of memory.

A summary of ‘C’ basic data types is given the Table 1.1. From this table, it may be observed that character and integer type data can also be declared as unsigned. Such data types are called unsigned data types. In this representation, the data is always a positive number with range starting from 0 to a maximum value. Thus, a number twice as big as a signed number can be represented through unsigned data types.

 

Table 1.1 Basic data types in ‘C’

Basic data types in ‘C’
1.4 C TOKENS

A token is a group of characters that logically belong together. In fact, a programmer can write a program by using tokens. ‘C’ supports the following types of tokens:

  • Identifiers
  • Keywords
  • Constants
  • Variables

1.4.1 Identifiers

Symbolic names can be used in ‘C’ for various data items. For example, if a programmer desires to store a value 27, then he can choose any symbolic name (say, ROLL) and use it as given below:

  ROLL = 27;

Where ROLL is a memory location and the symbol ‘=’ is an assignment operator.

The significance of the above statement is that ‘ROLL’ is a symbolic name for a memory location where the value 27 is being stored. A symbolic name is generally known as an identifier.

The identifier is a sequence of characters taken from ‘C’ character set. The number of characters in an identifier is not fixed though most of the C compilers allow 31 characters. The rules for the formation of an identifier are:

  • An identifier can consist of alphabets, digits and and/or underscores.
  • It must not start with a digit.
  • C is case sensitive, i.e., upper case and lower case letters are considered different from each other.
  • An identifier can start with an underscore character. Some special ‘C’ names begin with the underscore.
  • Special characters such as blank space, comma, semicolon, colon, period, slash, etc. are not allowed.
  • The name of an identifier should be so chosen that its usage and meaning becomes clear. For example, total, salary, roll no, etc. are self explanatory identifiers.

Examples of acceptable identifiers are:

    TOTAL
    Sum
    Net_sal
    P123
    a_b_c
    total
    _sysreg

Examples of unacceptable identifiers are:

Bas ic (blank not allowed)

H, rent (special character ‘, ‘ included)

It may be noted here that TOTAL and total are two different identifier names.

1.4.2 Keywords

A keyword is a reserved word of C. This cannot be used as an identifier by the user in his program. The set of C keywords is given in Table 1.2.

 

Table 1.2 Standard keywords in ‘C’

Standard keywords in ‘C’

1.4.3 Variables

A variable is the most fundamental aspect of any computer language. It is a location in the computer memory which can store data and is given a symbolic name for easy reference. The variables can be used to hold different values at different times during a program run. To understand this concept, let us have a look at the following set of statements:

 

Total = 500.25;      …(i)

Net = Total − 100.00;      …(ii)

 

In statement (i), value 500.25 has been stored in a memory location called Total. The variable Total is being used in statement (ii) for the calculation of another variable Net. The point worth noting is that ‘the variable Total is used in statement (ii) by its name not by its value’.

Before a variable is used in a program, it has to be defined. This activity enables the compiler to make available the appropriate amount of space and location in the memory. The definition of a variable consists of its type followed by the name of the variable. For example, a variable called Total of type float can be declared as shown below:

   float Total;

Similarly, the variable net of type int can also be defined as shown below:

   int Net;

Examples of valid variable declarations are:

  1. int count;
  2. int i, j, k;
  3. char ch, first;
  4. float Total, Net;
  5. long int sal;
  6. double salary.

Let us now look at a variable declaration from a different perspective. Whenever a variable (say, int val) is declared, a memory location called val is made available by the compiler as shown in Figure 1.1.

 

Memory allocated to variable val

 

Fig. 1.1 Memory allocated to variable val

 

Thus, val is the name associated by the compiler to a location in the memory of the computer. Let us assume that, at the time of execution, the physical address of this memory location (called val) is 4715 as shown in Figure 1.2.

 

The physical address of val

 

Fig. 1.2 The physical address of val

 

Now, a point worth noting is that this memory location is viewed by the programmer as a variable called val and by the computer system as an address 4715. The programmer can store a value in this location with the help of an assignment operator, i.e., ‘=’. For example, if the programmer desires to store a value 100 into the variable val, he can do so by the following statement:

  val = 100;

Once the above statement is executed, the memory location called val gets the value 100 as shown in Figure 1.3.

 

The contents of a variable (rvalue)

 

Fig. 1.3 The contents of a variable (rvalue)

 

‘C’ allows the initialization of variables even at the time of declaration as shown below:

  int val = 100;

From Figure 1.3, we can see that besides its type a variable has three entities associated with it, i.e., the name of variable (val), its physical address (4715), and its contents (100). The content of a variable is also called its rvalue whereas the physical address of the variable is called its lvalue. Thus, lvalue and rvalue of variable val are 4715 and 100, respectively. The lvalue is of more importance because it is an expression that should appear on the left hand side of assignment operator because it refers to the variable or object.

1.4.4 Constants

A constant is a memory location which can store data in such a manner that its value during execution of a program does not change. Any attempt to change the value of a constant will result in an error message. A constant in ‘C’ can be of any of the basic data types, i.e., integer constant, floating point constant, and character constant. const qualifier is used to declare a constant as shown below:

  const <type> <name> = <val>;

where

   const: is a reserved word of ‘C’
  <type>: is any of the basic data types
  <name>: is the identifier name
   <val>: is the value to be assigned to the constant.
  1. Integer constant: It is a constant which can be assigned integer values only. For example, if we desire to have a constant called rate of type integer containing a fixed value 50, then the following declaration can be used:
      const int rate = 50;

    The above declaration means that rate is a constant of type integer having a fixed value 50. Consider the following declaration:

      const int rate;
      rate = 50;

    The above initialization of constant rate is illegal. This is because of the reason that a constant cannot be initialized for a value at a place other than where it is declared. It may be further noted that if a program does not change or mutatesa constant or constant object then the program is called as const correct.

  2. Floating point constant: It is a constant which can be assigned values of real or floating point type. For example, if it is desired to have a constant called Pi containing value 3.1415, then the following declaration can be used.
      const float Pi = 3.1415;

    The above declaration means that Pi is a constant of type float having a fixed value 3.1415. It may be noted here that by default a floating point constant is of type double.

  3. Character constant: A character constant can contain a single character of information. Thus, data such as ‘Y’ or ‘N’ is known as a character constant. Let us assume that it is desired to have a constant called Akshar containing the character ‘Q’; following declaration can be used to obtain such a constant.
      const char Akshar = ’Q’;

    The above declaration means that Akshar is a constant of type char having a fixed value ‘Q’.

    A sequence of characters enclosed within quotes is known as a string literal. For example, the character sequence “computer” is a string literal. When a string literal is assigned to an identifier declared as a constant, then it is known as a string constant. In fact, a string is an array of characters. Arrays are discussed later in the chapter.

1.5 STRUCTURE OF A ‘C’ PROGRAM

A simple program in ‘C’ can be written as a module. More complex programs can be broken into sub-modules. In ‘C’, all modules or subprograms are referred to as functions.

The structure of a typical ‘C’ program is given below:

  main ()
  {
     ....;
     ....;
     ....;
  }

Note:

  1. C is a case sensitive language, i.e., it distinguishes between upper case and lower case characters. Thus, main() is different from Main(). In fact, most of the characters used in C are lowercase. Hence, it is safest to type everything in lower case except when a programmer needs to capitalize some text.
  2. Every C program has a function called main followed by parentheses. It is from here that program execution begins. A function is basically a subprogram and is complete in itself.
  3. The task to be performed by a function is enclosed in curly braces called its body, i.e., {}. These braces are equivalent to begin and end keywords used in some other languages like Pascal. The body of function contains a set of statements and each statement must end with a semicolon.

1.5.1 Our First Program

Let us break the myth that ‘C’ is a difficult language to start with. Without going into the details, the beginner can quickly start writing the program such as given below:

  #include <stdio.h>
  main()
  {
    puts (“This is my first program”);
  }

The above program displays the following text on the screen:

This is my first program.

1.6 printf() AND scanf() FUNCTIONS

‘C’ uses printf() and scanf() functions to write and read from I/O devices, respectively. These functions have been declared in the header file called stdio.h.

Let us use printf() function to rewrite our first program. The modified program is given below:

  #include <stdio.h>
  main()
  {
    printf (“This is my first program”);
  }

This program displays the following message on the screen:

This is my first program.

In fact, any text written within the pair of quotes (“ ”) is displayed as such by printf() function on the screen. However, this function is much more powerful than puts() in the sense that it can display all types of data on the screen as explained below.

1.6.1 How to Display Data using printf() Function

An integer, stored in a variable, can be displayed on the screen by including a format specifier (%d) within a pair of quotes as shown below:

  #include <stdio.h>
  main()
  {
     int age = 25;
     printf (“%d”, age);
  }

The above program does the following:

  1. Declares a variable age of type int.
  2. Initializes age to 25, an integer value.
  3. Specifies %d, a format specifier indicating that an integer is to be displayed by printf() and the data is stored in the variable called age.

It may noted that printf() has two arguments separated by a comma, i.e., format specifier written within quotes and the variable age. It may be further noted that both messages and format specifiers can be included within the pair of quotes as shown below:

  printf (“ The age of student = %d”, age);

The above statement would display the following data on the screen:

 

The age of student = 25

 

Thus, the text between the quotes has been displayed as such but for %d, the data stored in the variable age has been displayed.

A float can be displayed on the screen by including a format specifier (%f) within the pair of quotes as shown below:

  float rate = 9.5;
  printf (“The rate of provident fund = %f”, rate);

The above statements would produce the following display:

The rate of provident fund = 9.5

A char can be displayed by including a format specifier (%c) within the pair of quotes as shown below:

  char ch = ’A’
  printf (“The first alphabet is: %c”, ch);

Obviously, the output of the above set of statements would be:

The first alphabet is: A.

The other specifiers which can be used in printf() function are given in Appendix B.

1.6.2 How to Read Data from Keyboard using scanf()

Similar to printf() function, scanf() function also uses the %d, %f, %c, and other format specifiers to specify the kind of data to be read from the keyboard.

However, it expects the programmer to prefix the address operator ‘&’ to every variable written in the argument list as shown below:

  int roll;
  scanf (“%d”, & roll);

The above set of statements declares the variable roll of type int, and reads the value for roll from the keyboard. It may be noted that ‘&’, the address operator, is prefixed to the variable roll. The reason for specifying ‘&’ would be discussed later in the book.

Similarly, other format specifiers can be used to input data from the keyboard.

Example 1: Write an interactive program that reads the marks secured by a student for four subjects Sub1, Sub2, Sub3, and Sub4, the maximum marks of a subject being 100. The program shall compute the percentage of marks obtained by the student.

Solution: The scanf() and prinf() functions would be used to do the required task. The required program is as follows:

  #include <stdio.h>
  main()
  {
    int sub1, sub2, sub3, sub4;
    float percent;
    printf (“Enter the marks for four subjects:”);
    scanf (“%d %d %d %d”,&sub1, &sub2, &sub3, &sub4);
    percent = (sub1 + sub2 + sub3 + sub4)/ 400.00*100;
      printf (“The percentage = %f”, percent);
  }

For input data 45 56 76 90, the above program computes the percentage and displays the following output:

 

The percentage = 66.750000

 

Though the output is correct, but it has displayed unnecessary four trailing zeros. This can be controlled by using field width specifiers discussed later in the chapter.

1.7 COMMENTS

A comment can be added to the program by enclosing the text between the pair / * ... * /, i.e., the pair ‘/*’ indicates the beginning of the comment whereas the pair ‘*/’ marks the end of it. It is also known as multiple line comment. For example, the following line is a comment:

  /* This is my first program */

Everything written within ‘/*’ and ‘*/’ is ignored by the compiler. A comment written in this fashion can overflow to multiple lines as shown below:

  /* This is an illustration of multiple line comment. The C compiler ignores  these lines. A programmer can use comment lines for documentation of his  programs*/

In fact, a comment is a non-executable statement in the program.

1.8 ESCAPE SEQUENCE (BACKSLASH CHARACTER CONSTANTS)

‘C’ has some special character constants called backslash character constants. These are unprintable ASCII characters which can perform special functions in the output statements. A backslash character constant is nothing but a back slash (’’) character followed by another character.

For example, “ ” can be used in a printf() statement to send the next output to the beginning of the next line.

Consider the following program:

  #include <stdio.h >
  main()
  {
      printf(“A backslash character constant”);
      printf(“prints the output on the next line.”);
  }

The output of this program would be:

A backslash character constant prints the output on the next line.

It may be noted that though two separate printf() statements were written in the above program, the output has been displayed on the same line.

In order to display the text in two lines, the “ ” character constant should be placed either at the end of the text in the first printf() statement or at the beginning of the text in the second printf() statement.

Consider the following modified program:

  #include <stdio.h>
  main()
  {
      printf(“A backslash character constant”);
      printf(“
 prints the output on the next line.”);
  }

The character constant “ ” has been placed at the beginning of the text of the second printf() statement and, therefore, the output of the program would be:

A back slash character constant

prints the output on the next line.

Some other important backslash constants are listed below:

Backslash character constant Meaning
tab
 backspace
a bell (alert)
newline character

Note:

The backslash characters are also known as escape sequences; such characters can be used within apostrophes or within double quotes.

  1. ‘ ’ (tab): This character is called a tab character. Whenever it is inserted in an output statement, the display moves over to the next present tab stop. Generally, a tab is of 8 blank spaces on the screen. An example of usage of character ‘ ’ is given below:
      #include <stdio.h>
      main()
      {
          printf(“
     hello 	 Comp-Boy”);
      }

    The output of the above statement would be on the new line with spacing as shown below:

    hello Comp-Boy
  2. ‘’ (Backspace): This character is also called backspace character. It is equivalent to the backspace key symbol (image) available on the computer or typewriter. It moves one column backward and positions the cursor on the character displayed on that column. An example of usage of character ‘’ is given below:
      #include <stdio.h>
      main()
      {
          printf(“
     ASHOKA-”);
      }

    The output of the above statement would be:

      ASHOK-

    We can see that the trailing letter ‘A’ has been overwritten by the character ‘-’ at the end of the string constant <ASHOKA> the reason being that ‘’ moved the curser one column backward, i.e., at ‘A’ and printf() printed the character ‘-’ on that column position.

  3. ‘a’ (Alert): This character is also called alert or bell character. Whenever it is inserted in an output statement, it sounds a bell which can be heard by the user sitting on the computer terminal. It can be used in a situation where the programmer wants to catch the attention of the user of this program. An example of usage of ‘a’ character is given below:
      #include <stdio.h>
      main()
      {
          printf(“
     Error in data a”);
      }

    The output of the above statement would be the following message on the screen and a sounding of a bell on the system speaker.

      Error in data
  4. ‘ ’ (new line): As discussed earlier, this character is called newline character. Wherever it appears in the output statement, the immediate next output is taken to the beginning of the next new line on the screen. Consider the statement given below:
      #include <stdio.h>
      main()
      {
          printf(“
     This is 
     a test.”);
      }

    The output of this statement would be:

    This is
    a test.
1.9 OPERATORS AND EXPRESSIONS

An operator is a symbol or letter used to specify a certain operation on variables in a program. For example, the symbol ‘+’ is an add operator that adds two data items called operands.

Expressions: An expression is a combination of operands (i.e., constants, variables, numbers) connected by operators and parenthesis. For example, in the expression given below A and B are operands and ‘+’ is an operator.

  A + B

‘C’ supports many types of operators such as arithmetic, relational, logical, etc. An expression that involves arithmetic operators is known as an arithmetic expression. The computed result of an arithmetic expression is always a numerical value. The expression which involves relational and/or logical operators is called as a boolean expression or logical expression. The computed result of such an expression is a logical value, i.e., either 1 (True) or 0 (False).

 

The rules of formation of an expression are:

  • A signed or unsigned constant or variable is an expression.
  • An expression connected by an operator to a variable or a constant is an expression.
  • Two expressions connected by an operator is also an expression.
  • Two operators should not occur in continuation.

1.9.1 Arithmetic Operators

The valid arithmetic operators supported by ‘C’ are given in Table 1.3.

 

Table 1.3 Arithmetic operator

Symbol Stands for Example
+ addition x + y
subtraction x – y
* multiplication x *y
/ division x/y
% modulus or remainde x%y
–– decrement ––x
x––
++ increment x++

1.9.1.1 Unary Arithmetic Operators

A unary operator requires only one operand or data item. The unary arithmetic operators supported by ‘C’ are unary minus (‘-’), increment (‘++’), and decrement (‘--’). As compared to binary operators, the unary operators are right associative in the sense that they evaluate from right to left.

The unary minus operator is written before a numerical value, variable or an expression. Examples of usage of unary minus operator are:

  1. –57
  2. –2.923
  3. ++x
  4. ––(a*b)
  5. 8*(––(a + b))

It may be noted here that the result of application of unary minus on an operand is the negation of its operand.

The operators ‘++’ and ‘--’ are unique to C. These are called increment and decrement operators, respectively. The increment operator ‘++’ adds 1 to its operand. Therefore, we can say that the following expressions are equivalent.

  i = i + 1 image ++i;

For example, if the initial value of i is 10 then the expression ++i will increment the contents of i to 11. Similarly, the decrement operator ‘--’ subtracts 1 from its operand. Therefore, we can say that the following expressions are equivalent:

  j = j - 1 image --j;

For example, if the initial value of j is 5 then the expression --j will decrement the contents of j to 4.

The increment and decrement operators can be used both as a prefix and as a postfix to a variable as shown below:

  ++ x or x++
  --y or y--

As long as the increment or decrement operator is not used as part of an expression, the prefix and postfix forms of these operators do not make any difference. For example, ++x and x++ would produce the same result. However, if such an operator is part of an expression then the prefix and postfix forms would produce entirely different results.

In the prefix form, the operand is incremented or decremented before the operand is used in the program. Whereas in the postfix form, the operand is used first and then incremented or decremented.

1.9.2 Relational and logical Operators

A relational operator is used to compare two values and the result of such an operation is always logical, i.e., either true or false. The valid relational operators supported by C are given in Table 1.4.

 

Table 1.4 Relational operators supported by C

Symbol Stands for Example
> greater than x > y
> = greater than equal to x > = y
< less than x < y
< = less than equal to x < = y
= = equal to x = = y
! = not equal to x ! = y

Example 2: Take two variables x and y with initial values 10 and 15, respectively. Demonstrate the usage of relational operators by using x and y as operands.

Solution: The usage of relational operators is illustrated below with the help of a table:

x = 10, y = 15
Expression Result
x > y False
x + 5 > = y True
x < y True
x < = y True
x = = y False
x + 5= = y True
x! = y True

A logical operator is used to connect two relational expressions or logical expressions. The result of such an operation is always logical, i.e., either true or false. The valid logical operators supported by C are given in Table 1.5.

 

Table 1.5 Logical operators supported by C

Symbol Stands for Example
&& Logical AND x&&y
|| Logical OR x||y
! Logical NOT !x

Rules of logical operators:

  1. The output of a logical AND operation is true if both of its operands are true. For all other combinations, the result is false.
  2. The output of logical OR operation is false if both of its operands are false. For all other combinations, the result is true.
  3. The logical NOT is a unary operator. It negates the value of the operand.

For initial value of x = 5 and y = 7, consider the following expression:

  (x < 6) && (y > 6)

The operand x < 6 is true and the operand y > 6 is also true. Thus, the result of above given logical expression is also true. However, the result of following expression is false because one of the operands is false:

  (x < 6) && (y > 7)

Similarly, consider the following expression:

  (x < 6) || (y > 7)

The operand x < 6 is true whereas the operand y > 7 is false. Since these operands are connected by logical OR, the result of this expression is true (Rule 2). However, the result of the following expression becomes false because both the operands are false.

  !(x < 6) || (y > 7)

Note: The expression on the right hand side of logical operators && and || does not get evaluated in case the left hand side determines the outcome.

Consider the expression given below:

  x && y

If x evaluates to false (zero), then the outcome of the above expression is bound to be false irrespective of y evaluating to any logical value. Therefore, there is no need to evaluate the term y in the above expression.

Similarly, in the following expression, if x evaluates to true (non zero) then the outcome is bound to be true. Thus, y will not be evaluated.

  x || y

1.9.3 Conditional Operator

‘C’ provides a conditional operator (? :) which can help the programmers in performing simple conditional operations. It is represented by the symbols ‘?and:’. For example, if one desires to assign the bigger of the two variables x and y to a third variable z the conditional operator is an excellent tool.

The general form of this operation is:

  E1?E2:E3

where E1, E2, and E3 are expressions.

In the conditional operation, the expression E1 is tested, if E1 is true then E2 is evaluated otherwise the expression E3 is evaluated as shown in Figure 1.4.

 

conditional operator

 

Fig. 1.4 conditional operator

 

Consider the following conditional expression:

  z = (x > y)? x : y;

The expression x > y is evaluated. If x is greater than y, then z is assigned x otherwise z gets y. Examples of valid conditional expressions are:

  1. y = (x > = 10)?0:10;

  2. Res = (i < j)? sum + i : sum + j;

  3. q = (a = = 0)?0:(x/y);

It may be noted here that the conditional operator (? :) is also known as a ternary operator because it operates on three values.

1.9.4 Order of Evaluation of Expressions

A number of logical and relational expressions can be linked together with the help of logical operators as shown below:

  (x < y) || (x > 20) && !(z) || ((x < y) && (z > 5))

For a complex expression such as given above, it becomes difficult to make out as to in what order the evaluation of sub-expressions would take place.

In ‘C’, the order of evaluation of an expression is carried out according to the operator precedence given in Table 1.6.

 

Table 1.6 Operator precedence

Operator precedenc

It may be noted here that in C, false is represented as zero and true as any non-zero value. Thus, expressions that use relational and logical operators return either 0 (false) or 1 (true).

1.9.5 Some Special Operators

There are many other operators in C. In this section, the two frequently used operators—sizeof and comma operators—have been discussed.

  1. Sizeof operator: C provides a compile time unary operator called sizeof which, when applied on an operand, returns the number of bytes the operand occupies in the main memory. The operand could be a variable, a constant or a data type. For example, the following expressions:
      a = sizeof (“sum”);
      b = sizeof (char);
      c = sizeof (123L);

    would return the sizes occupied by variables sum, data type char and constant ‘123L’ on your machine. It may be noted that

    • the parentheses used with sizeof are required when the operand is a data type with variables or constants, the parentheses are not necessary.
    • sizeof operator has the same precedence as prefix increment/decrement operators.
  2. Comma operator: The comma operator is used to string together a number of expressions which are performed in a sequence from left to right.

    For example, the following statement

      a = (x = 5, x + 2)

    executes in the following order

    1. value 5 is assigned to variable x.
    2. x is incremented by 2.
    3. the value of expression x + 2 (i.e., 7) is assigned to the variable a.

    The following points may be noted regarding comma operator:

    • A list of expressions separated by a comma is always evaluated from left to right.
    • The final value and type of a list of expressions separated by a comma is always same as the type and value of the rightmost expression in the list.
    • The comma operator has the lowest precedence among all C operator.

1.9.6 Assignment Operator

Statements are the smallest executable units of a C program and each statement is terminated with a semicolon. An assignment statement assigns the value of the expression on the right hand side to a variable on the left hand side of the assignment operator (=). Its general form is given below:

  <variable name> = <expression>

The expression on the right hand side could be a constant, a variable or an arithmetic, relational, or logical expression. Some examples of assignment statements are given below:

         a = 10;
         a = b;
         a = b*c;
  1. The assignment operator is a kind of a store statement, i.e., the value of the expression on the right hand side is stored in the variable appearing on the left side of the assignment operator. The variable on the left side of the assignment operator is also called lvalue and is an accessible address in the memory. Expressions and constants on the right side of the assignment operator are called rvalues.
  2. The assignment statement overwrites the original value contained in the variable on the left hand side with the new value of the right hand side.
  3. Also, the same variable name can appear on both sides of the assignment operator as shown below:
      count = count +1;
  4. Multiple assignments in a single statement can be used, especially when same value is to be assigned to a number of variables.
      a = b = c = 30;

    These multiple assignment statements work from right to left and at the end, all variables have the same value. The above statement assigns the value (i.e., 30) to all variables c, b, and a. However, the variables must be of same type.

  5. A point worth nothing is that C converts the type of value on the right hand side to the data type on the left.

1.9.7 Bitwise Shift Operators

‘C’ supports special bitwise shift operators: shift left (<<) and shift right (>>). We know that data at machine level is represented in the binary form and it can be shifted to left or right by these special operators. However, the number of bits to be shifted is specified by an integer written next to the operatoras shown below:

  x << 3;

The above statement means that the value contained in x is shifted to left by 3 bits. Thus, the leftmost 3 bits of x will be lost and the resultant vacant 3 rightmost bits will be filled by zeros as shown in Figure 1.5.

 

The contents of x before and after left shift

 

Fig. 1.5 The contents of x before and after left shift

 

Similarly, the following expression would shift the contents of y to right by two bits:

  y >> 2

In this case, the rightmost two bits would be lost and the resultant 2 vacant leftmost bits would be filled by zeros as shown in Figure 1.6.

 

The contents of y before and after right shift

 

Fig. 1.6 The contents of y before and after right shift

1.10 FLOW OF CONTROL

A statement is the smallest executable unit of a C program. It is terminated with a semicolon. It is an instruction given to the computer to perform a particular task like reading input, displaying output or evaluating an expression, etc.

A single statement is also called a simple statement. Some examples of simple statement are given below:

  1. int a = 100;
  2. S = S + a;
  3. count ++;

A statement can also be an empty or null statement as shown below:

     ;

The high level languages are designed for computers based on Von-Neumann architecture. Since this architecture supports only sequential processing, the normal flow of execution of statements in a high level language program is also sequential, i.e., each statement is executed in the order of its appearance in the program. For example in the following C program segment, the order of execution is sequential from top to bottom.

image

 

The first statement to be executed is ‘x = 10’, and the second statement to be executed is ‘y = 20’. The execution of statement ‘z = x + y’ will take place only after the execution of the statement ‘y = 20’. Thus, the processing is strictly sequential. Moreover, every statement is executed once and only once.

Depending upon the requirements of a problem, it is often required to alter the normal sequence of execution in the program. This means that we may desire to selectively and/or repetitively execute a program segment. A number of ‘C’ control structures are available for controlling the flow of processing. These structures are discussed in the following sections.

1.10.1 The Compound Statement

A compound statement is a group of statements separated from each other by a semicolon. The group of statements, also called a block of code, is enclosed between a pair of curly braces, i.e., ‘{’ and ‘}’. The significance of a block is that the sequence of statements enclosed in it is treated as a single unit. For example, the following group of statements is a block.

  /* a block of code*/
  {
     scanf (“%d %d”, & a, & b);
     c = a + b;
     printf (“
 %d”, c);
  }

One compound statement can be embedded in another as shown below:

  {
     :
     {
        :
     }
     :
  }

In fact, the function of curly braces ‘{’ and ‘}’ in a ‘C’ program to create a block, is same as the function of begin and end, the reserved words in Pascal. ‘C’ calls these braces as delimiters.

1.10.2 Selective Execution (Conditional Statements)

In some cases, it is desired that a selected segment of a program be executed on the basis of a test, i.e., depending upon the state of a particular condition being true or false. In ‘C’, ‘if statement’ is used for selective execution of a program segment.

  1. The if statement: This statement helps us in the selection of one out of two alternative courses of action. The general form of ‘if statement’ is given below:
       if (expression)
       {
           statement sequence
       }
      where         if: is a reserved word.
       expression: is a boolean expression enclosed within a set of parentheses (These parentheses are necessary even if there is a single variable in the expression).
    statement sequence: is either a simple statement or a block. However, it cannot be a declaration.

    Examples of acceptable ‘if statements’ are:

    1. if (A > B) A 5 B;
    2. if (total < 100) {
                total = total + val;
                count = count + 1;
                }
    3. if ((Net > 7000) && (l_tex == 500)) {
               :
                               }
  2. The if-else statement: It can be observed from the above examples that the simple if statement does nothing when the expression is false. An if-else statement takes care of this aspect. The general form of this construct is given below:
    if (expression)
    {
      statement sequence1
    }
    else
    {
      statement sequence2
    }
     where         if: is a reserved word.
       expression: is a boolean expression, written within parentheses.
    statement sequence1: can be a simple or a compound statement.
             else: is a reserved word.
    statement sequence2: can be a simple or a compound statement.

    Examples of if-else statements are:

    1. if (A > B) C = A;
      else C = B;
    2. if (x == 100)
        printf (“
       Equal to 100”);
      else
        printf (“
       Not Equal to 100”);

    It may be noted here that both the ‘if’ and ‘else’ parts are terminated by semicolons.

  3. Nested if statements (if-else-if ladder): The statement sequence of if or else may contain another if statement, i.e., the if-else statements can be nested within one another as shown below:
    if (exp1)
     if (exp2)
      {
        :
      }
    else
      if (exp3)
      {
        :
      }
      else
      {
        :
      }

    It may be noted here that sometimes the nesting may become complex in the sense that it becomes difficult to decide “which if does the else match”. This is called “dangling else problem”. The ‘C’ compiler follows the following rule in this regard:

    Rule: Each else matches to its nearest unmatched preceding if.

    Consider the following nested if:

       if (x < 50) if (y > 5) Net = x + y; else Net = x – y;

    In the above statement, the else part matches the second if (i.e., if (y . 5)) because it is the nearest preceding if. It is suggested that the nested if(s) should be written with proper indentation. The else(s) should be lined up with their matching if(s). Nested if(s) written in this fashion are also called if-else-if ladder. For example, the nested if given above should be written as:

      if (x < 50)
      if (y > 5)
          Net = x + y;
      else
          Net = x – y;

    However, if one desires to match the else with the first if, then the braces should be used as shown below:

      if (x < 50) {
                  if (y > 5)
                      Net = x + y;
                  }
      else
          Net = x – y;

    The evaluation of if-else-if ladder is carried out from top to bottom. Each conditional expression is tested and if found true, only then its corresponding statement is executed. The remaining ladder is, therefore, by passed. In a situation where none of the nested conditions is found true, the final else part is executed.

  4. Switch statement (selection of one of many alternatives): If it is required in a program to select one of several different courses of action, then the switch statement of ‘C’ can be used. In fact, it is a multibranch selection statement that makes the control to jump to one of the several statements based on the value of an int variable or expression. The general form of this statement is given below:
    switch (expression)
    {
       case constant 1:
                      statement;
                      break;
       case constant 2:
                      statement;
                      break;
                      :
       default:
                      statement;
    }
      where switch: is a reserved word.
     expression: it must evaluate to an integer or character value.
     case: is a reserved word.
     constant: it must be an int or char compatible value.
     statement: a simple or compound statement.
     default: is a reserved word and is an optional entry.
     break: is a reserved word that stops the execution within the switch and control comes out of the switch construct.

    The switch statement works according to the following rules:

    • The value of the expression is matched with the random case constants of the switch construct.
    • If a match is found then its corresponding statements are executed and when break is encountered, the flow of control jumps out of the switch statement. If break statement is not encountered, then the control continues across other statement. In fact, switch is the only statement in ‘C’ which is error prone. The reason is that if the control is in a particular case and then it keeps running through all cases in the absence of a proper break statement. This phenomenon is called “fall-through”.
    • If no match is found and if a default label is present, then the statement corresponding to default is executed.
    • The values of the various case constants must be unique.
    • There can be only one default statement in a switch statement.

    Examples of acceptable switch statements are:

    1.   switch (BP)
        {
           case 1 : total + = 100;
                    break;
           case 2 : total + = 150;
                    break;
           case 3 : total + = 250;
        }
    2.   switch (code)
      {
        case 101 : Rate = 50; break;
        case 102 : Rate = 70; break;
        case 103 : Rate = 100; break;
        default  : Rate = 95;
      }

    In the statement (ii), it can be observed that depending on the value of the code one out of the four instructions is selected and obeyed. For example, if the code evaluates to 103, the third instruction (i.e., Rate =100) is selected. Similarly if the code evaluates to 101, then the first instruction (i.e., Rate = 50) is selected.

1.10.3 Repetitive Execution (Iterative Statements)

Some problems require a set of statements to be executed a number of times, each time changing the values of one or more variables so that every new execution is different from the previous one. This kind of repetitive execution of a set of statements in a program is known as a loop.

We can categorize loop structures into two categories: non-deterministic loops and deterministic loops. When the number of times the loop is to be executed is not known, then the loop is called non-deterministic loop otherwise it is called a deterministic loop.

‘C’ supports while, do while, and for loop constructs to help repetitive execution of a compound statement in a program. The ‘while’ and ‘do while’ loops are non-deterministic loops and the ‘for’ loop is a deterministic loop.

  1. The while loop: It is the fundamental conditional repetitive control structure in C. The general form of this construct is given below:
      while <cond> statement;
      where while: is a reserved word of C.
         <cond>: is a boolean expression.
      statement: can be a simple or compound statement.

    The sequence of operation in a while loop is as follows:

    1. Test the condition.
    2. If the condition is true, then execute the statement and repeat step 1.
    3. If the condition is false, leave the loop and go on with the rest of the program.

    It may be noted here that the variables used in the <cond> or boolean expression must be initialized somewhere before the while statement is encountered. It is a pre-test loop in the sense that the condition is tested before the body of the loop is executed.

  2. The do-while loop: It is another conditional repetitive control structure provided by C. The syntax of this construct is given below:
      do
      {
          statement;
      }
      while <cond>;
      where     do: is a reserved word.
        statement: can be a simple or a compound statement.
        while: is a reserved word.
       <cond>: is a boolean expression.

    The sequence of operations in a do-while loop is as follows:

    1. Execute the statement.
    2. Test the condition.
    3. If the condition is true, then repeat steps 1 to 2.
    4. If the condition is false, leave the loop and go on with the rest of the program.

    Thus, it performs a post-test in the sense that the condition is not tested until the body of the loop is executed at least once.

    3. The for loop: It is a count controlled loop in the sense that the program knows in advance as to how many times the loop is to be executed. The general form of this construct is given below:
      for (initialization; expression; increment)
      {
          statement
      }
      where        for: is a reserved word.
         initialization: is usually an assignment expression wherein a loop control variable is initialized.
       expression: is a conditional expression required to determine whether the loop should continue or be terminated
        increment: it modifies the value of the loop control variable by a certain amount.
        statement: can be a simple or a compound statement.

    The loop is executed with the loop control variable at initial value, final value and the values in between.

    We can increase the power of for-loop with the help of the comma operator. This operator allows the inclusion of more than one expression in place of a single expression in the ‘for’ statement as shown below:

      for (exp1a, exp1b; exp2; exp3a, exp3b;) statement;
    Consider the following program segment:
       :
      for (i = 1, j = 10; i < = 10; i++, j--)
     {
        :
      }

    The variable i and j have been initialized to values 1 and 10, respectively. Please note that these initialization expressions are separated by a ‘comma’. However, the required semicolon remains as such. During the execution of the loop, i increases from 1 to 10 whereas j decreases from 10 to 1 simultaneously. Similarly, the increment and decrement operations have been separated by a ‘comma’ in the ‘for statement’.

    Though the power of the loop can be increased by including more than one initialization and increment expression separated with the comma operator but there can be only one test expression which can be simple or complex.

1.10.3.1 The ‘break’ and ‘continue’ Statements

The break statement can be used in any ‘C’ loop to terminate execution of the loop. We have already seen that it is used to exit from a switch statement. In fact, whenever the break statement is encountered in a loop the control is transferred out of the loop. This is used in a situation where some error is found in the program inside the loop or it becomes unnecessary to continue with the rest of the execution of the loop.

Consider the following program segment:

  :
  while (val != 0)
  {
       :
       printf (“
 %d”, val);
       if (val < 0) {
         printf (“
 Error in input”);
       break;
       }
       :
  }

Whenever the value contained, in variable val becomes negative, the message ‘Error in input’ would be displayed and because of the break statement the loop will be terminated.

The continue statement can also be used in any ‘C’ loop to bypass the rest of the code segment of the current iteration of the loop. The loop, however, is not terminated. Thus, the execution of the loop resumes with the next iteration. For example, the following loop computes the sum of positive numbers in a list of 50 numbers:

  :
  sum = 0;
  for (i = 0; i < 50; i ++)
  {
       printf (“
 %d”, val);
      if (val <= 0) continue;
      sum = sum + val;
  }
  :

It may be noted here that continue statement has no relevance as far as the switch statement is concerned. Therefore, it cannot be used in a switch statement.

1.10.4 The exit() Function

In the event of encountering a fatal error, the programmer may desire to terminate the program itself. For such a situation, ‘C’ supports a function called exit() which can be invoked by the programmer to exit from the program. This function can be called from anywhere inside the body of the program. For normal termination, the programmer can include an argument ‘0’ while invoking this library function as shown below:

  #include <stdio.h>
  #include <process.h>
  void main()
  {
     :
     if (error) exit (0);
     :
  }

It may be noted here that the file process.h has to be included as header file because it contains the function prototype of the library function exit().

1.10.5 Nested Loops

It is possible to nest one loop construct inside the body of another. The inner and outer loops need not be of the same construct as shown below.

  while <cond>
  {
     do
     {
     } while <cond>;
     for (init; exp; inc)
     {
     :
     }
     :
  }

The rules for the formation of nested loops are:

  1. An outer for loop and an inner for loop cannot have the same control variable.
  2. The inner loop must be completely nested inside the body of the outer loop.

1.10.6 The Goto Statement (Unconditional Branching)

The unconditional transfer of control means that the sequence of execution will be broken without performing any test and the control will be transferred to some statement other than the immediate next one. ‘C’ supports the following statement for this purpose.

    goto <statement label>
  where       goto: is a reserved word.
<statement label>: is an identifier used to label the target statement.

The goto statement causes control to be transferred to the statement whose label is specified in the goto statement. Consider the following program segment:

         -
         -
         goto rpara;
         -
         -
  rpara: -
         -
         -

The goto statement will cause the control to be transferred to a statement whose label is rpara. The normal flow of execution will continue from this statement (i.e., having label rpara) onwards. Consider the following program segment:

     :
     k = 50;
  back: I++
     :
     sum = sum + k*I ;
     k--;
     goto back;
     :

It is clear from the above segment that as and when the control reaches the goto statement, it transferred to the statement with label back.

Statement label A statement label is an identifier which can be placed before any C statement followed by a colon (i.e., :) as shown below:

again: C = A + B;

Thus, again is a label attached to the statement C = A + B and the control of execution can be transferred to this statement by the following goto statement.

  goto again;

It may be noted here that the transfer of control out of a control structure is allowed. However, a goto branch into a control structure is not allowed.

Some example programs using control structures are given below.

Example 3: Write a program that reads three numbers and prints the largest of them.

Solution: The if-else ladder would be used. The required program is given below:

  /* This program displays the largest of three numbers */
  #include <stdio.h>
  main()
  {
    int A, B, C;
     printf (“
 Enter the Numbers A, B, C:”);
    scanf (“%d %d %d”, &A, &B, &C);
             /* if-else ladder */
    if (A > B)
     if ( A > C)
      printf (“
 A is largest”);
     else
      printf (“
 C is largest”);
     else
     if (B > C)
      printf (“
 B is largest”);
     else
  printf (“
 C is largest”);
           /* end of ladder */
  }

Example 4: Write a program that prints all perfect numbers between 2 and 9999, inclusive. A perfect number is a positive integer such that the number is equal to the sum of its proper divisors. A proper divisor is any divisor whose value is less than the number.

Solution: The remainder operator ‘%’ would be used to find whether a number is divisor of another or not. The maximum value of perfect divisor cannot be more than the half the value of the number.

The required program is given below:

  /* This program finds out all the perfect numbers between 2 and 9999 both
  inclusive */
  #include <stdio.h>
  main()
  {
    int num, divisor;
    int sum;
    char ch;
    
    for (num = 2; num , = 9999; num++)
    {
        sum = 1; /* 1 is proper divisor of all positive integers   */
  
        for (divisor = 2; divisor < = num/2; divisor++)
        {
            if (num % divisor == 0)
            sum = sum + divisor;
        }
        if ( sum == num )
         printf (“
 %d is a perfect number”, num);
      }
    }
1.11 INPUT–OUTPUT FUNCTIONS (I/O)

Most of the programs read and write data through input/output devices such as screen, keyboard, printer, and disk devices, etc. Obviously, the programmer has to learn how to perform correct I/O operations so that efficient programs can be written. We have already used two C functions printf() and scanf() in the previous examples. In the following sections, we will discuss some of the following input output functions:

 

Function Type Description
(1) getchar() stream reads a character from a stream
(2) putchar() stream writes a character to the stream
(3) getc() stream reads a character from a stream
(4) putc() stream writes a character to a stream
(5) gets() stream reads a string from a stream
(6) puts() stream writes a string to a stream
(7) cgets() console reads a string from system consol
(8) getche() console reads a character from system consol
(9) putch() console writes a character on system consol
(10) cputs() console writes a string on system consol

In order to use the above functions, the programmer must include the ‘stdio.h’ header file at the beginning of his program. The ‘C’ or ‘C environment’ assumes keyboard as the standard input device and VDU as standard output device. A consol comprises both keyboard and VDU.

By default, all stream I/Os are buffered. At this point, it is better that we understand the term buffered I/O before we proceed to discuss the stream I/O functions.

1.11.1 Buffered I/O

Whenever we read from the keyboard or from a file stored on a device, a block of data is stored in a buffer called input buffer. The input stream, therefore, reads from the buffer with the help of a pointer until the input buffer is empty (see Figure 1.7). As soon as the buffer becomes empty, the next block of data is transferred into the buffer from the I/O device.

 

Buffered I/O

 

Fig. 1.7 Buffered I/O

Similarly, data written by an output stream pointer is not directly written onto the device but into an output buffer. As soon as the output buffer becomes full, a block of data is written on to the I/O device making output buffer empty.

When the header file stdio.h is included in a program, the following standard stream pointers are automatically opened:

Name Meaning
stdin standard input
stdout standard output
stderr standard error
stdaux auxiliary storage
stdprn printer

In the computer, ‘stdin’ and ‘stdout’ refer to the user’s console, i.e., input device as keyboard and output device as VDU (screen). The stream pointers ‘stdprn’ and ‘stdaux’ refer to the printer and auxiliary storage, respectively. The error messages generated by the stream are sent to standard error (stderr).

In order to clear the buffers, a function called ‘fflush()’ can be used. For example, input buffer of standard input device can be cleared by invoking the function: ‘fflush(stdin)’.

1.11.2 Single Character Functions

‘C’ supports many input and output functions based on character. These functions read or write one character at a time. ‘C’ supports both stream and consol I/O character-based functions. We will discuss them in the following sections.

  1. getchar() and putchar() Functions: The getchar() function reads a single character from the standard input device. For example, if it is desired to read a character from keyboard in a character variable ch then the following statements can be used:
          :
        char ch;
        ch = getchar();
          :

    Since the function getchar() is a stream I/O function, it is buffered in the sense that the character typed by the user is not passed to the variable ch until the user hits the enter or return key, i.e., ↵. The enter key is itself a character and it also gets stored in the buffer along with the character typed by the user. The entry of ‘enter key’ character into the buffer creates problems in the normal functioning of getchar() function. Therefore, it is suggested that after an input operation from the standard input device (i.e., keyboard) the input buffer should be cleared. This operation is required to avoid interference with subsequent input operations. The function call for this activity is: fflush (stdin). The usage is shown below:

         :
       char ch;
       ch = getchar();
       fflush (stdin);
         :

    The function putchar() is used to send a single character to the standard output device. The character to be displayed on the VDU screen is included as an argument to the putchar() function as shown below:

         :
       ch = ’A’;
       putchar (ch);
         :

    Once the above program segment is executed, the character ‘A’ will be displayed on the screen.

    The putchar() function is also buffered. The function call for clearing the output buffer is fflush (stdout). The output buffer is cleared on its own only when a new line character ‘ ’ is used.

  2. getc() and putc() Functions: The getc() and putc() functions are also character-based functions. They have been basically designed to work with files. However, these functions can also be used to read and write data from standard input and output devices by specifying stdin and stdout as input and output files, respectively.

    For example, the function getc(stdin) is equivalent to the function getchar(). Both will get a character from the standard input device (keyboard). The function getchar() by default reads from keyboard whereas the argument stdin of function getc(stdin) makes it read from a file represented by the standard input device which is nothing but the keyboard.

    Similarly, the function putc(ch, stdout) is equivalent to the function putchar(ch). Both the functions send the character ch to the standard output device, i.e., VDU screen.

  3. getche() and putch() Functions: These two functions are character-based versions of console I/O functions. Therefore, the header file conio.h has to be included. In fact, these functions act as an extension to the stream I/O functions. The console I/O functions read from the keyboard and write to the screen directly.
    • getche(): This function directly reads a character from the console as soon as it is typed without waiting for the enter key (↵) to be pressed. There is another similar function getch() which also reads a character from the keyboard exactly in the same manner but does not show it on the screen. This function is useful in menu selections where the programmer does not want to display the character typed by the user. In fact, the extra ‘e’ in the getche() function stands for echo, i.e., display the character.

      Examples of usage of these functions are:

      1. ch = getche();
      2. ch = getch();
    • putch(): This function directly writes a character on the console. It takes character as an argument.

      Examples of usage of this function are:

      1. putch (’ ’); //It takes the cursor to next line of the screen.
      2. putch (ch); //It displays the character stored in the variable ch on the screen.
      3. putch (’A’); //It displays the character ‘A’ on the screen.

Note: These functions cannot read special keys from the keyboard such as function keys.

1.11.3 String-based Functions

String-based functions read or write a string of characters at a time. ‘C’ supports both stream and console I/O string-based functions.

  1. gets() and puts() functions: These functions are string-based I/O functions. The function gets() reads a string from the standard input device (keyboard). It is also buffered and, therefore, the return or enter key has to be typed to terminate the input. The fflush() function should also be used after each gets() to avoid interference. For example, the program segment given below reads a string in a variable name from keyboard.
        :
      name = gets() ;
      fflush (stdin);
        :

Similarly, the function puts() is used to send a string to the standard output device. The string to be displayed on the VDU screen is included as an argument to the puts function as shown below:

    :
  city = "New Delhi”;
  puts (city);
    :

Once this program segment is executed, the following message will be displayed on the screen:

  New Delhi
1.12 ARRAYS

A detailed discussion on arrays as data structure is given in Chapter 3.

1.13 STRUCTURES

Arrays are very useful for list and table processing. However, the elements of an array must be of the same data type. In certain situations, we require a construct that can store data items of mixed data types. C supports structures for this purpose. The basic concept of a structure comes from day-to-day life. We observe that certain items are made up of components or sub-items of different types. For example, a date is composed of three parts: day, month, and year as shown in Figure 1.8.

 

Composition of ‘date’

 

Fig. 1.8 Composition of ‘date’

 

Similarly, the information about a student is composed of many components such as name, age, roll number., and class; each belonging to different types (see Figure 1.9).

 

Student

 

Fig. 1.9 Student

 

The collective information about the student as shown above is called a structure. It is similar to a record construct supported by other programming languages. Similarly, the date is also a structure. The term structure can be precisely defined as ‘a group of related data items of arbitrary types’. Each member of a structure is, in fact, a variable that can be referred to through the name of the structure.

1.13.1 Defining a Structure in ‘C’

A structure can be defined in C by the keyword struct followed by its name and a body enclosed in curly braces. The body of the structure contains the definition of its members and each member must have a name. The declaration ends by a semicolon. The general format of structure declaration in C is given below:

    struct <name> {
      member 1
      member 2
      :
      member n
      };
where               struct: is the keyword.
              <name>: is the name of the structure.
   member 1, 2 ... n: are the individual member declarations.

Let us now define the following ‘C’ structure to describe the information about the student given in Figure 1.9.

  struct student
  {
    
     char Name [20];
     int age;
     int roll;
     char class[5];
  };

The above declaration means that the student is a structure consisting of data members: Name, age, roll, and class. A variable of this type can be declared as given below:

  struct student x;

Once the above declaration is obeyed, we get a variable x of type student in the computer memory which can be visualized as shown in Figure 1.10.

 

Memory space allocated to variable x of type student

 

Fig. 1.10 Memory space allocated to variable x of type student

 

The programmer is also allowed to declare one or more structure variables along with the structure declaration as shown below:

  struct student
  {
     char name [20];
     int age;
     int roll;
     char class [5];
  }
    stud1, stud2;

In the above declaration, the structure declaration and the variable declaration of the structure type have been clubbed, i.e., the structure declaration is followed by two variable names stud1 and stud2 and the semicolon.

1.13.2 Referencing Structure Elements

The structure variable x has four members: name, age, roll, and class. These members can be designated as: x.name, x.age, x.roll, and x.class, respectively. In this notation, an individual member of the structure is designated or qualified by the structure variable name followed by a period and the member name. The period is called a structure member operator or simply a dot operator.

However, the information of a student (Figure 1.10) can be stored in structure variable x in either of the following ways:

  1. Initialize the elements of the structure
           strcpy (x.name, “SACHIN KUMAR”);
           x.age = 18;
           x.roll = 10196;
           strcpy (x.class, “CE41”);
  2. The variable x can be read in a C program by the I/O statements as shown below:
           gets(x.name);
           ffush(stdin);
           scanf(“% d %d”, & x age., & x.roll);
           gets(x.class);

1.13.3 Arrays of Structures

An array of structures can be declared just like an ordinary array. However, the structure has to be defined before an array of its type is declared. For example, a 50-element array of type student called stud_list can be defined as shown below:

   struct student {
     char name [20];
     int roll;
     int sub1, sub2, sub3, sub4;
     int total;
     };
  struct student stud_list [50];   /* declaration of an array of structures*/

1.13.4 Initializing Structures

When a structure variable is declared, its data members are not initialized and, therefore, contain undefined values. Similar to arrays, the structure variables can also be initialized. For instance, the structure shown in Figure 1.10 can be declared and initialized as shown below:

  struct student
  {
    char name[20];
    int age;
    int roll;
    char class[5];
  };
                    /* Initialize variable of type student*/
                    
  struct student stud1 = {"SACHIN KUMAR”, 18, 10196,"   CE41"};

Please notice that the values are enclosed within curly braces. The values are assigned to the members of the structure in the order of their appearance, i.e., first value is assigned to the first member, second to second, and so on.

1.13.5 Assignment of Complete Structures

It has been appreciated that the individual fields of a structure can be treated as simple variables. The main benefit of a structure, however, is that it can be treated as a single entity. For example, if two structure variables stud1 and stud2 have been declared as shown below

  student stud1, stud2;

then the following assignment statement is perfectly valid.

  stud1 = stud2;

This statement will perform the necessary internal assignments. The concept of structure assignment can be better understood by the following example program. In this program, a structure variable stud1 is initialized with certain values and it is assigned to another structure variable stud2. The contents of the variable stud2 are displayed.

  /* This program illustrates copying of complete   structures */
  #include <stdio.h>
  main()
  {
    struct student {
      char name[20];
      int roll;
      int age;
      char class[6];
      };
                        /* initialize a variable of type student */
      struct student stud1 = {"Sachin Kumar”, 101, 16,   "CE_IV"};
      struct student stud2;
                   /* assign stud1 to stud2 */
      stud2 = stud1;
                   /* Display contents of stud2 */
      printf (“
 The copied contents are....”);
      printf (“
 Name: %s”, stud2.name);
      printf (“
 Roll: %d”, stud2.roll);
      printf (“
 Age : %d" , stud2.age);
      printf (“
 class: %s”, stud2.class);
  }

1.13.6 Nested Structures

Nested structures are structures as member of another structure. For instance, the date of birth (DOB) is a structure within the structure of a student as shown in figure below. These types of structures are known as nested structures.

 

image

 

The nested structure shown in Figure 16.4 can be declared in a program as shown below:

  /* Nested structures /*
  struct date
  {
       int dd;
       int mm;
       int yy;
  };
  struct student
  {
       char name[20];
       int roll;
       struct date dob;
       int marks;
  };

It may be noted here that the member of a nested structure is referenced from the outermost to inner most with the help of dot operators. Let us declare a variable stud of type student:

  struct student stud;

The following statement illustrates the assignment of value 10 to the member mm of this nested structure stud:

  stud.dob.mm = 10;

The above statement means: store value 10 in mm member of a structure dob which itself is a member of structure variable called stud.

1.14 USER-DEFINED DATA TYPES

In addition to the simple data types such as integer, float, char, etc., ‘C’ allows the users to declare new data types called user-defined data types. These data types can be declared with the help of a keyword called typedef whose general form is given below:

     typedef <type> <new_type>
where     <typedef>: is a reserved word
       <type>: is an existing data type.
   <new_type>: is the desired user-defined data type.

For example, consider the following declaration:

  typedef float xyz;

In this declaration, an existing data type (float) has been redefined as xyz. Now, the user can use xyz as a synonym for the type float as a new type as shown below.

  xyz x1, x2;

In fact, the above declaration is equivalent to the following declaration:

  float x1, x2;

Apparently, it looks as if we have not achieved anything great because the user will have to remember xyz as a new type whereas its equivalent float type is already available. Nevertheless, the utility of typedef lies in a situation where the name of a particular type is very long. The user can also self document his code as shown in the following declaration:

  typedef float salary;   :
  salary wages-of-month;

In the above declaration, the variable wages-of-month has been declared of type salary, where salary itself is of float type. Thus, we can see that readability of a program can be enhanced by self documenting the variables and their data types with the help of typedef.

For example, the declaration:

  typedef int age;

can be used to increase the clarity of code as shown below :

  age boy, girl, child;

The above statement clearly suggests as to what data the variables boy, girl, and child are going to store.

Similarly, typedef can also be used to define arrays.

  typedef float lists [20];
  lists BP, SAL, GSAL;

These statements are equivalent to the following:

  float BP [20], SAL [20], GSAL [20]

typedef is also extremely useful for shortening the long and inconvenient declarations of structures.

For instance, the structure struct can be declared as a typedef as shown below:

   typedef struct {
     char name [20];
     int age;
     int roll;
     char class[6];
     } student;

Now the structure student has become the type and a variable of this type can be defined as:

  student stud1, stud2;

The above declaration means that stud1 and stud2 are variables of type student.

1.14.1 Enumerated Data Types

A user can define a set of integer type identifiers in the form of new data types called enumerated data types. For instance, the user can create a new data type called color with the help of enum definition as shown below:

  enum color {
    Blue,
    Yellow,
    White,
    Black
    };

where enum is the keyword that defines an enumerated data type.

The enum declaration given above means that a new type, color, has been defined. This type contains the constant values: Blue, Yellow, White, and Black. Each of these symbols stands for an integer value. By default, the value of the first symbol (i.e., Blue) is 0, the value of the second symbol is 1, and so on. Once the type color has been defined, then variables of that type can be defined in the following manner:

  enum color A, B;

Now, the variable A of type color can use the enumerations (blue, yellow, etc.) in a program.

Thus, the following operations on variable A are valid:

    A = red;
         :
    if (A == red)
      x = x + 10;
    else
      x = x – 5;

Enumerated data type can be precisely defined as the ordered set of distinct constant values defined as a data type in a program.

Examples of some valid enumerated data types are:

  1. enum furniture
      {
        chair,
        table,
        stool,
        desk
      };
  2. enum car
      {
        Maruti,
        Santro,
        Micra,
        Indigo
      }

It may be noted here that the ordering of elements in enumerated data type is specified by their position in the enum declaration. Thus for furniture type, the following relations hold good:

Expression Value
Chair<Table True
Stool>Desk True
Table==Desk False
Chair<Desk True

The enumerated types can also be used in a switch construct. Consider the following program segment.

  :
                          /* Enumerated type declaration */
  enum furniture
  {
    chair,
    table,
    stool,
    desk
  };
main()
{
                        /* Enumerated variable declaration */
    enum furniture item;
    float cost;
    :
    switch item
  {
    case chair : cost = 250; break;
    case table : cost = 700; break;
    case stool : cost = 120; break;
    case desk : cost = 1500; break;
  }
  :

Similarly, enumerated data types can also be used as a control variable in a for loop as shown below:

     :
     for (item = chair; item <= desk; item++)
     {
       :
       :
     }

The enumerations are also called symbolic constants because an enumeration has a name and an integer value assigned to it which cannot be changed in the program. Therefore, enumerated data types cannot be plainly used in I/O statements. As a result, the statements scanf, printf, gets, puts, etc. cannot be directly applied to these data types because the results will not be as desired.

1.15 UNIONS

Suppose in a fete, every visitor is assured to win any one of the items listed below:

  1. Wall clock
  2. Toaster
  3. Electric Iron
  4. DVD player

Obviously, a visitor to the fete must carry a bag large enough to carry the largest item so that any one of the items won by him can be held in that bag. With the same philosophy in mind, the designers of ‘C’ introduced a special variable called union which may hold objects of different sizes and types but one at a time. Though a union is a variable and can hold only one item at a time, it looks like a structure. The general format of a union is given below:

       union <name> {
       member 1
       member 2
        :
       member
       };
where                 union: is a keyword.
               <name>: is the name of the union.
   member 1, 2, ... n: are the individual member declarations.
1.16 FUNCTIONS

A function is a subprogram that can be defined by the user in his program. It is a complete program in itself in the sense that its structure is similar to main() function except that the name main is replaced by the name of the function. The general form of a function is given below:

     <type> <name> (arguments)
Where    <type>: is the type of value to be returned by the function. If no value is returned, then keyword void should be used.
   <name>: is a user-defined name of the function. The function can be called from another function by this name.
 arguments: is a list of parameters (parameter is the data that the function may receive when called from another function). This list can be omitted by leaving the parameters empty.

The program segment enclosed within the opening brace and closing brace is known as the function body. For example, the main function in C is written as shown below:

  main()
  {
  }

Let us write a function tri_area() which calculates the area of a triangle. Two variables base and height will be used to read the values from the keyboard. The function is given below:

  float tri_area()
  {
    float base, height, area;
    printf (“
 Enter Base and Height”);
    scanf (“%f %f”, &base, &height);
    area = (0.5)*base*height;
    return (area);
  }

It may be noted here that the function tri_area() has defined its own variables. These are known as local variables. The advantage of their usage is that once the execution of the function is over these variables are disposed off by the system, freeing the memory for other things.

Let us write another function clear () which clears the screen of the VDU

  /* This function clears the screen by writing blank lines   on the screen */
  void clear()
  {
    int i;
    for (i = 0; i< = 30; i++)
    	printf (“
”);
  }

Similarly, let us write a function add which receives two parameters x and y of type integer from the calling function and returns the sum of x and y.

  int add (int x, int y)
  {
    int temp;
    temp = x + y;
    return temp;
  }

In the above function, we have used a local variable temp to obtain the sum of x and y. The value contained in temp is returned through return statement. In fact, variable temp has been used to enhance the readability of the function only, otherwise it is unnecessary. The function can be optimized as shown below:

  ind add (int x, int y)
  {
    return (x + y);
  }

Thus, a function has following four elements:

  1. A name
  2. A body
  3. A return type
  4. An argument list

The name of the function has to be unique so that the compiler can identify it. The body of the function contains the C statements which define the task performed by the function. The return type is the type of value that the function is able to return to the calling function. The argument or parameter list contains the list of values of variables from outside required by the function to perform the given task. For example, the function given above has a name add. It has a body enclosed between the curly braces. It can return a value of type int. The argument list is x and y.

1.16.1 Function Prototypes

Similar to variables, all functions must be declared before they are used in a program. ‘C’ allows the declaration of a function in the calling program with the help of a function prototype. The general form of a function prototype in the calling program is given below:

      <type> <name> (arguments);
where    <type>: is the type of value to be returned by the function
   <name>: is a user-defined name of the function.
arguments: is a list of parameters.
        ;: the semicolon is necessary.

For example, the prototype declarations for the functions tri_area(), clear(), and add() can be written as shown below:

        void tri_area();
        void clear();
  int add(int x, int y);

It may be noted that a function prototype ends with a semicolon. In fact, the function prototype is required for those functions which are intended to be called before they are defined. In absence of a prototype, the compiler will stop at the function call because it cannot do the type checking of the arguments being sent to the function. Therefore, the main purpose of function prototype is to help the compiler in static type checking of the data requirement of the function.

1.16.2 Calling a Function

A function can be called or invoked from another function by using its name. The function name must be followed by a set of actual parameters, enclosed in parentheses and separated by commas. A function call to function tri_area from the main program can be written as:

  tri_area();

This statement will transfer the control to function tri_area. Since this function does not require any parameter, the argument list is empty. Similarly, in order to call the function ‘clear’, the following statement will be sufficient:

  clear();

A complete C program involving the two functions tri_area and clear is given below:

  #include <stdio.h>
                 /* Function ptototypes */
  float tri_area();
  void clear();

  main()
  {
    char ch;
    int flag;
    float Area;
    clear();   /* Clear the screen */
    flag = 0;
    while (flag == 0)
    {
      Area = tri_area(); /* call tri_area to compute area */
       printf (“
 Area of Triangle = %5.2f”, Area);
  
       printf (“
 Want to calculate again: Enter Y/N”);
      fflush(stdin);
      ch = getchar();
      if (ch == ’N’ || ch == ’n’)
       flag = 1;
      clear();
    }
  }
  
  float tri_area()
  {
    float base, height, area;
      printf (“
 Enter Base and Height”);
    scanf (“%f %f”, &base, &height);
    area = (0.5)*base*height;
    return (area);
  }
  
  /* This function clears the screen by writing blank lines on the screen */
  void clear()
  {
    int i;
    for (i = 0; i< = 30; i++)
     printf(“
”);
  }

It may be noted here that when this program is executed, the first statement to be executed is the first executable statement of the function main() of the program (i.e., clear() in this case). A function will be executed only after it is called from some other function or itself.

The variables base, height, and area are local to function tri_area and they are not available in the main() function. Similarly, the variable flag declared in function main() is also not available to functions tri_area() and clear().

However, the variables declared outside any function can be accessed by all the functions. Such variables are called global variables.

Let us consider the following program which declares the variables flag and area outside the main function instead of declaring them inside the functions main() and tri_area (), respectively.

  #include <stdio.h>
  /* Function prototypes */
  void tri_area();
  void clear();
  /* Global Variables */
  int flag;
  float area;
  main()
  {
    char ch; /* Local Variable */
    clear(); /* Clear the screen */
    flag = 0;
    while (flag == 0)
    {
      tri_area(); /* call tri_area to compute area */
      printf (“
 Area of Triangle = %5.2f”, area);
      printf (“
 Want to calculate again: Enter Y/N”);
      fflush(stdin);
      ch = getchar();
      if (ch == ’N’ || ch == ’n’)
       flag = 1;
       clear();
    }
  }
  /* Function Definitions */
  void tri_area()
  {
    float base, height;
      printf (“
 Enter Base and Height”);
    scanf (“%f %f”, &base, &height);
    area = (0.5)*base*height;
  }
  /* This function clears the screen by writing blank lines on the screen */
  void clear()
  {
    int i;
    for (i = 0; i< = 30; i++)
     printf (“
”);
  }

It may be noted in the above program that the variable area is available to both the functions tri_area() and main(). On the other hand, the local variables base and height are available to function tri_area only. They are neither available to main() function nor to the function clear(). Similarly, variable i is also local to function clear().

In our previous programs, we have used our own function clear() to clear the screen. C also provides a function called clrscr() that clears the screen. From now onwards, we will use this function. However, in order to use clrscr() in a program we will have to include conio.h, a header file at the beginning of the program.

Note: We should not use global variables in our programs as they make the program or function insecure and error prone.

1.16.3 Parameter Passing in Functions

We have seen that two-way communication between functions can be achieved through global variables. This technique has its own limitations and drawbacks. Let us now see how this communication between the calling function and the called function can be improved and made fruitful.

The two-way communication between the various functions can be achieved through parameters and return statement as done in previous section. The set of parameters defined in a function are called formal or dummy parameters whereas the set of corresponding parameters sent by the calling function are called actual parameters. For instance, the variables x and y in the argument list of function add() are formal parameters. The parameters included in the function call, i.e., val1 and val2 of main() are actual parameters.

The function that receives parameters can be called in one of the following two ways:

  1. Call by value.
  2. Call by reference.
  1. Call by value: For better understanding of the concept of parameter passing, let us consider the function big() given below. It receives two values as dummy arguments x and y and returns the bigger of the two through a return statement.
      /* This function compares two variables and returns the bigger of the two */
      int big (int x, int y)
      {
        if (x > y)
        return x;
        else
        return y;
      }

    The function big() can be called from the function main() by including the variables a and b as the actual arguments of the function call as shown below.

      main()
      {
        int a = 30;
        int b = 45;
        int c;
        c = big (a, b);
        printf (“
     The bigger = %d ”, c);
      }

    The output of the above program would be:

      The bigger = 45

    Let us now write a program which reads the values of two variables a and b. The values of a and b are sent as parameters to a function exchange(). The function exchanges the contents of the parameters with the help of a variable temp. The changed values of a and b are printed.

      #include <stdio.h>
      #include <conio.h>
      void exchange( int x, int y);
      main()
      {
        int a, b;
        clrscr(); /* clear screen */
         printf (“
     Enter two values”);
        scanf (“%d %d”, &a, &b);
        exchange(a,b);
                 /* print the exchanged contents */
         printf (“
     The exchanged contents are: %d and %d”, a,   b);
      }
      void exchange (int x, int y)
      {
        int temp;
        temp = x;
        x = y;
        y = temp;
      }

    The above program seems to be wonderful but it fails down badly because variables a and b do not get any values back from the function exchange(). The reason is that although all values of actual parameters (i.e., a and b) have been passed on to formal parameters (i.e., x and y) correctly, the changes done to the values in the formal parameters are not reflected back into the calling function.

    Once the above program is executed for input value (say 30 and 45), the following output is produced:

    The exchanged contents are: 30 and 45

    The reason for this behaviour is that at the time of function call, the values of actual parameters a and b get copied into the memory locations of the formal parameters x and y of the function exchange().

    It may be noted that the variables x and y have entirely different memory locations from variables a and b. Therefore any, changes done to the contents of x and y are not reflected back to the variables a and b. Thus, the original data remains unaltered. In fact, this type of behaviour is desirable from a pure function.

    Since in this type of parameter passing, only the values are passed from the calling function to the called function, the technique is called call by value.

  2. Call by reference: If the programmer desires that the changes made to the formal parameters be reflected back to their corresponding actual parameters, then he should use call by reference method of parameter passing. This technique passes the addresses or references of the actual parameters to the called function. Let us rewrite the function exchange(). In fact, in the called function, the formal arguments receive the addresses of the actual arguments by using pointers to them.

For instance, in order to receive the addresses of actual parameters of int type the exchange () function can be rewritten as shown below:

  void exchange (int *val1, int *val2)
  {
    int temp;
    temp = *val1;
    *val1 = *val2;
    *val2 = temp;
  }

It may be noted that the above function has used two pointers called val1 and val2 to receive the addresses of two int type actual parameters. However, initially, these are dangling pointers as shown below:

 

image

 

The exchange() function would be called from the main() function by sending the addresses of the actual arguments as shown below:

  exchange (& a, & b);

Note: Kindly refer to Chapter 5 before reading the text of this section.

After the exchange() function is called by the above statement, the addresses of the actual parameters a and b would be assigned to pointers val1 and val2, respectively as shown below:

 

image

 

Since the function exchanges the contents of variables being pointed by the pointers val1 and val2, the contents of variables a and b get exchanged which is the goal of this exercise.

The complete program is given below:

  #include <stdio.h>
  #include <conio.h>
  void exchange( int *val1, int *val2);
  main()
  {
    int a, b;
    clrscr(); /* clear screen */
     printf (“
 Enter two values”);
    scanf (“%d %d”, &a, &b);
    exchange(&a,&b);
             /* print the exchanged contents */
     printf (“
 The exchanged contents are: %d and %d”, a, b);
  }
  void exchange (int *val1, int *val2)
  {
    int temp;
    temp = *val1;
    *val1 = *val2;
    *val2 = temp;
  }

After the above program is executed for input values (say 30 and 45), the following output is produced:

  The exchanged values are: 45 30

Now, we can see that the program has worked correctly in the sense that changes made inside the function exchange() have been available to corresponding actual parameters a and b in the function main(). Thus, the address operator ‘&’ has done the required task.

The main advantage of call by reference method is that more than one value can be received back from the called function.

Note:

  1. As far as possible, we should use ‘pass by value’ technique of parameter passing. If some value is to be received back from the function, it should be done through a return statement of the function.
  2. A function call can use both the methods, i.e., call by value and call by reference simultaneously. For example, the following is a valid function prototype:
    void calc (int a, float *b, float *c);
  3. When actual parameters are passed from the calling function to the called function by call by value method, the names of the corresponding dummy parameters could be the same or different. However, it is suggested that they may be named different in order to make the program more elegant.
  4. Array parameters: Arrays can also be passed as parameters to functions. This is always done through call by reference method. In ‘C’, the name of the array represents the address of the first element of the array and, therefore, during the function call only the name of the array is passed from the calling function. For example, if an array xyz of size 10000 is to be passed to a function some() then the function call will be as given below:
  some (xyz);

The formal parameters can be declared in the called function in three ways. The different ways are illustrated with the help of a function some() that receives an array xyz of size 100 of integer type.

Method I:

In this method, the array is declared without subscript, i.e., of an known size as shown below:

  void some (int xyz [ ])
  {
  }

The C compiler automatically computes the size of the array.

Method II:

In this method, an array of same size and type is declared as shown below:

  void some (int xyz [100])
  {
  }

Method III:

In this method, the operator * is applied on the name of the array indicating that it is a pointer.

  void some (int *xyz)
  {
  }

All the three methods are equivalent and the function some() can be called by the following statement:

  some (xyz);

Note:

  1. The arrays are never passed by value and cannot be used as the return type of a function.
  2. In ‘C’, the name of the array represents the address of the first element or the zeroth element of the array. So when an array is used as an argument to a function, only the address of the array gets passed and not the copy of the entire array. Hence, any changes made to the array inside the function are automatically reflected in the main function. You do not have to use ampersand (&) with array name even though it is a call by reference method. The ampersand (&) is implied in the case of array.

1.16.4 Returning Values from Functions

Earlier in this chapter, we have used functions which either return no value or integer values. The functions that return no value are declared as void. We have been prefixing int to functions which return integer values. This is valid but unnecessary because the default return value of a function in C is of type int. Thus, the following two declarations are equivalent in the sense that we need not prefix int to a function which returns an integer value.

  int add (int a, int b);
  add (int a, int b);

On the other hand, whenever a function returns non-integer values, the function must be prefixed with the appropriate type. For example, a function xyz that returns a value of type float can be declared as shown below:

  float xyz (.....)
  {  float a;
      :
      return a
  }

Similarly, a function ABC that returns a value of type char can be declared as shown below:

  char ABC ( ..... )
  {  char ch;
      :
      return ch;
  }

1.16.5 Passing Structures to Functions

Similar to variables, the structures can also be passed to other functions as arguments both by value and by reference.

  1. Call by value: In this method of passing the structures to functions, a copy of the actual argument is passed to the function. Therefore, the changes done to the contents of the structures inside the called function are not reflected back to the calling function.

    The following program uses a structure variable called stud of type student and passes the structure variable by value to a function print_data(). The function print_data() displays the contents of the various members of the structure variables.

      /* This program illustrates the passing of the structures by value to a
      function */
      #include <<stdio.h>>
      struct student
      {
        char name [20];
        int age;
        int roll;
        char class [5];
      };
      /* Prototype of the function */
      void print_data (struct student Sob);
      main()
      {
        struct student stud;
         printf (“
     Enter the student data”);
         printf (“
    Name:”); fflush(stdin);
        gets (stud.name);
         printf (“
    Age:”); scanf(“%d”, &stud.age);
         printf (“
    Roll:”); scanf(“%d”, &stud.roll);
         printf (“
    Class:”); fflush(stdin);
        gets (stud.class);
         print_data(stud); /*The structure is being passed by value*/
      }
      void print_data (struct student Sob)
      {
         printf (“
     The student data..”);
         printf (“
    Name:”); fflush(stdout);
        puts (Sob.name);
         printf (“Age: %d”,Sob.age);
         printf (“
    Roll: %d”,Sob.roll);
         printf („
    Class:”); fflush(stdout);
        puts (Sob.class);
      }
  2. Call by reference: In this method of passing the structures to functions, the address of the actual structure variable is passed. The address of the structure variable is obtained with the help of address operator ‘&’. Thus, the changes done to the contents of such a variable inside the function are reflected back to the calling function. The program given below illustrates the usage of call by reference method.

    This program reads the data of a student in the function main() and passes the structure by reference to the function called print_data().

      /* This program illustrates the passing of the structures by reference to
      a function */
      #include <stdio.h>
      struct student
      {
        char name [20];
        int age;
        int roll;
        char class [5];
      };
      /* Prototype of the function */
      void print_data (struct student &Sob);
      main()
      {
        struct student stud;
         printf (“
     Enter the student data”);
         printf (“
    Name:”); fflush(stdin);
        gets (stud.name);
         printf (“
    Age:”); scanf(“%d”,&stud.age);
         printf (“
    Roll:”); scanf(“%d”,&stud.roll);
         printf (“
    Class:”); fflush(stdin);
        gets (stud.class);
       	 print_data(&stud); /*The structure is being passed by reference*/
      }
      void print_data (struct student &Sob)
      {
        struct student *ptr;
        ptr = sob;
         printf (“
     The student data..”);
         printf (“
    Name:”); fflush(stdout);
        puts (ptr−>name);
         printf (“Age: %d”,ptr->age);
         printf (“
    Roll: %d”,ptr->roll);
         printf (“
    Class:”); fflush(stdout);
        puts (ptr->class);
      }

    It may be noted here that structures are usually passed by reference in order to prevent the overheads associated with the technique of passing structures by value. The overheads are extra memory space and CPU time used to pass bigger structures.

  3. Returning structures from functions: It is possible to supply a structure as a return value of a function. This can be done by specifying structure as the return type of the function. This feature of C is helpful in a situation where a structure has been passed by value to a function and the changes done to the contents of the structure are needed by the calling function without disturbing the original contents. This concept is illustrated in the example given below:

Example 5: Write a program that reads the data of a students whose structure is given in the figure shown below. The structure is then passed by value to a function called change-data() where the name of the student is capitalized. The changed contents of the student data are returned by the function to the function main().

 

image

 

Solution: We will use the function toupper() in this program to capitalize the name of the student inside the function change-data(). The required program is given below:

  /* This program illustrates the process of returning a structure from a
  function */
  #include <stdio.h>
  #include <ctype.h>
  struct student
  {
    char name [20];
    int age;
    int roll;
    char class [5];
  };
                       /* Prototype of the function */
  void print_data (struct student *ptr);
  struct student change_data (struct student Sob);
  main()
  {
    struct student stud, newstud;
     printf (“
 Enter the student data”);
     printf (“
Name:”); fflush(stdin);
    gets (stud.name);
     printf (“
Age:”);scanf(“%d”,&stud.age);
     printf (“
Roll:”);scanf(“%d”,&stud.roll);
     printf (“
Class:”); fflush(stdin);
    gets (stud.class);
                     /* call function to change data */
    newstud = change_data(stud);
     printf (“
 The changed data ..”);
     print_data(&newstud); /*The structure is being passed by value*/
  }
                    /* This function changes the data of a student */
    struct student change_data (struct student Sob)
  {
    int i = 0;
    while (Sob.name[i] != ’’)
    {              /* Capitalize the letters */
      Sob.name[i] = toupper (Sob.name[i]);
      i++;
    }
      return (Sob);
  }
  void print_data (struct student *ptr)
  {
      printf (“
 The student data..”);
    puts (ptr->name);
       printf (“Age: %d”, ptr->age);
       printf (“
Roll: %d”, ptr->roll);
       printf (“
Class:”); fflush(stdout);
    puts (ptr->class);
  }
TEST YOUR SKILLS
  1. What would be the output of following program?
      #include <stdio.h>
      main()
      {
        printf(“Compu”);
        printf (“ter”);
      }

    Ans. The output would be: Computer

  2. What would be the output of following program?
      #include <stdio.h>
      main()
      {
        printf(“Compuuter”);
      }

    Ans. The output would be: Computer

  3. What would be the output of following program?
    void main()
    {
      int k = 30;
      /*
      printf (“k = %d”, k);
      */
      printf (“value of k = %d”, k);
    }

    Ans. The output would be: value of k = 30

  4. Write four equivalent ‘C’ statements each of which subtracts 1 from a variable called Val.

    Ans. The required statements are:

    • Val = Val -1;
    • Val--;
    • --Val;
    • Val - = 1;
  5. Write the following expressions without using relational operators:
    1. if (Val == 0)
    2. if (Val != 0)

    Ans Since in ‘C’ 1 represents true and 0 represents false, the following statements can be used instead of above:

    1. if(!Val)
    2. if(Val)
  6. Write a single statement that increments the value of a variable Val by 1 and then adds it to a variable called num.

    Ans. The required statement is: num = num + (++Val);

  7. What will be the output of the following statements?
    1. ch = ‘A’ 1 10;

      printf (“%c”, ch);

    2. int a = 5;

      printf (“%d”, a < 10);

    Ans. The output would be: (i) K, (ii) 1

  8. What would be the output of following program?
      #include <stdio.h>
      main()
      {
       int k = 10;
       k = ++k == 11;
       printf (“
     %d”, k);
      }

    Ans. The output would be: 1

  9. What would be the output of following program?
      #include <stdio.h>
      main()
      {
        int i =8 > 5?100:150;
        printf(“
     %d”,i);
      }

    Ans. The output would be: 100

  10. What would be the output of the following program?
        enum furniture { Chair,
         Table,
         Bed
         Almirah
         };
      #include <stdio.h>
      main()
      {
          printf (“
     %d %d %d %d”, Chair, Table, Bed, Almirah);
      }

    Ans. The output would be: 0 1 2 3

  11. What would be the output of the following program?
      #include <stdio.h>
      int first (int, int);
      int second (int);
      void main()
      {
        int x = 10, y = 5, z;
        z = first (x,y);
         printf (“
     z = %d”, z);
      }
      int first (int x, int y)
      {
        return (x + second (y));
      }
      int second (int y)
      {
        return ++y;
      }

    Ans. The output would be: 16

EXERCISES
  1. Define the terms: token, keyword, identifier, variable, constant and const correct.
  2. What is meant by basic data types? Explain in brief.
  3. What would be the appropriate data type for the following?
    • Length of a cloth
    • Age of a student
    • An exclamation mark
  4. What is meant by a backslash character? What is the utility of these characters in a program?
  5. What would be the output of the following program?
      #include <stdio.h>
      {
         int k;
          printf (“k = %d”, k );
      }
    1. an error
    2. unpredictable
    3. 34216
    4. 0
  6. Write a program that inputs a value in inches and prints in centimeters.
  7. Write a program that converts degree Celsius temperature into its degree Fahrenheit equivalent using the following formula:

     

    F = 9/5 C + 32

     

  8. What is the purpose of ‘else’ clause in an ‘if’ statement of ‘C’?
  9. Write a program that computes ab where a and b are of real and integer types, respectively.
  10. Describe the function of break and continue statements in ‘C’.
  11. Write a program that reverses and sums the digits of an integer number.
  12. Write a program that prints the following output on the screen.
      A
      B B
      C C C
      D D D D
      E E E E E
  13. Write a program that implements a menu of the following type:
    Menu
    Option1 ‘a’
    Option2 ‘b’
    Option3 ‘c’
    Option4 ‘d’

    Enter your choice:

    In response to user’s selection, it prints the following messages:

    Option Message
    1 ‘One is alone’
    2 ‘Two is a company’
    3 ‘Three is a crowd’
    4 ‘Quitting’

     

  14. Define the terms: arrays, subscript, subscripted variables, and strings.
  15. Write a program that removes duplicates from a list.
  16. Write a program that computes the sum of diagonal elements of a square matrix.
  17. Write a ‘C’ structure for the record structure given in figure shown below.

     

    image

     

  18. Define the terms: structure and member variables.
  19. Using the structure of following figure, write a program that maintains a list of computer books available in the library.
  20. What is meant by enumerated data types? Explain the concept with the help of suitable examples.
  21. What is meant by a function prototype and why is it needed?
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.4.174