Data Input and Output in C, Part 2

    Surabhi Saxena
    Share

    The previous article on input and output functions dealt with the functions getchar(), putchar() and scanf(). This article will discuss the functions printf() and puts() that are used to display data on a standard output device. It will also discuss some basic programs which demonstrate the use of input/output functions.

    Writing Output Data: the printf Function

    The printf function is used to output any combination of numerical values, single characters and strings. The general form of the printf function is:

                          printf(control string, arg1, arg2, … , argN)

    The control string consists of one or more of the following items:

    • Characters that are simply printed as they are; ie, messages or prompts
    • Conversion Specifications — the field width and the format specifier
    • Escape Sequences — used to print certain non-printing characters like newline, tab and bell alert

    The control string indicates the type of arguments that follow. The arguments  arg1, arg2, … , argN are the variables whose values are formatted and printed according to the specifications of the control string. The arguments must match in number, order and type with the format specifications.

    Example:

    #include<stdio.h>
    
    int main()
    
    {
    
    int marks=412;
    
    float percent=85.4;
    
    printf("n Marks= %d,n Percentage=%f ",marks, percent);
    
    return 0;
    
    }
    
    Output:
    
    Marks= 412
    
    Percentage= 85.4

    In the above program, the escape sequence n has been used to print the output on multiple lines. The format specifiers %d and %f are used to indicate that the arguments marks and percent are integer type and floating type arguments respectively. The arguments to a printf function represents the actual values and not the addresses as was the case in scanf.

    Specifying Field Width in printf

    A minimum field width can be specified  by preceding the conversion character with an unsigned integer. If the number of characters in the corresponding data item is less than the specified field width, the data item will be preceded by enough leading blanks to fill the specified field. If the number of characters exceeds the field width, additional space will be allocated to the data item, so that the entire data item can be displayed. This is just the opposite of the scanf function where a maximum field width is specified.

    The following program illustrates the use of the minimum field width feature.

    #include<stdio.h>
    
    int main()
    
    {
    
    int i = 1234;
    
    float x= 348.45;
    
    char a[];
    
    printf( " %3d %5d %8d" , i, i, i);
    
    printf("%7f  %7.1f  %7.3f ", x,x,x);
    
    printf ("%10s %13s %10.5s",a,a,a);
    
    return 0;
    
    }

    The first printf statement displays a decimal integer with different minimum field width specifications. The entire integer value will be displayed in each field, even if the specified field width is less (as with the first field).

    The output of the first printf statement is:

    1234    _1234  _ _ _ _1234

    The underscore marks are not actually printed. They have been used to show the number of leading blank spaces that are printed to conform to the minimum field width specifications.

    The second printf statement displays a floating point number with different field width specifications. The maximum number of decimal places that can be printed define the precision of the field. The precision is an unsigned integer that is specified after the decimal point that follows the minimum field width specification. For example, in the second printf statement, the second field has a minimum field width of seven places and the number of decimal places that can be printed is one.

    The output of the second printf statement is:

    348.450000    _ _348.5    348.450

    Notice that in the second field the value has been rounded off to conform to the precision specification.

    A precision specification can also be applied to strings. The precision will determine the maximum number of characters that can be displayed. If the precision specification is less than the total number of characters in the string, the excess rightmost characters will not be displayed. This will occur even if the minimum field width is larger than the entire string, resulting in the addition of leading blanks to the truncated string.

    Suppose that the character array a stores the string “precision”. Therefore the output of the third printf statement is:

    _precision  _ _ _ _precision _ _ _ _ _preci

    Specifying Flags in printf:

    In addition to the field width, the precision and the conversion character, each character group within the control string can include a flag which affects the appearance of the output.

    Some of the most commonly used flags are:

    • -  Data item is left justified within the field (blank spaces required to fill the minimum field width will be added after the data item. By default, numbers are printed right justified.
    • +  A sign (either + or -) will precede each signed numerical data item. Without this flag only negative data items are preceded by a sign.
    • 0  Causes leading zeros to appear instead of leading blanks. Applies only to those data items that are right justified within a field whose minimum field width is larger than the data item.
    • '  '  A blank space will precede each positive number. This flag is overridden by the + flag if both are present.
    • #  with o and x type conversion) Causes octal and hexadecimal data items to be preceded by 0 and 0x respectively.
    • #  (with e, f, and g type conversion) Causes a decimal point to be present in all floating point numbers even if it is a whole number. Also prevents the truncation of trailing zeros in g-type conversion.

    The following example illustrates the use of flags with floating point and integer quantities.

    #include<stdio.h>
    
    int main()
    
    {
    
    int i= 123;
    
    float x=12.0, y= -3.3;
    
    // Default right justified printing of numbers without flags
    
    printf (": %6d %7.0f  %10.1e:");
    
    //Left justified display through - flag
    
    printf("n :%-6d %-7.0f %-10.1e:");
    
    //Addition of sign with default right justified display
    
    printf("n :%+6d %+7.0f %+10.1e:");
    
    //addition of sign(through + flag)  and left justification(through - flag)
    
    printf(n :%-+6d %-+7.0f %-+10.1e:");
    
    //prints floating point number without decimal and truncates 0s in g type conversion
    
    printf(n :%7.0f %7g:");
    
    // Including a decimal point in the floating point number and including trailing zeros in g type conversion:
    
    printf("n : %#7.0f   %#7g:");
    
    return 0;
    
    }

    The output is self-explanatory. The colons indicate the beginning and end of the first field and the last field respectively for each line.

    :        123            12      -3.3e+00:

    :123         12            -3.3e+00     :

    :    +123           +12     -3.3e+00:

    :+123    +12          -3.3e+00      :

    :               12            -3.3:

    :                12.         -3.30000:

     

    The – and + flags can also be used to justify strings.

    Character String Output: the puts Function

    The puts function writes its string argument to the screen followed by a newline.

    The general form of puts is:

    puts(arrayname)

    where arrayname is a character type array that may include whitespace characters. The puts function returns EOF if a write error occurs; otherwise it returns a non-negative value.

    The puts function offers a convenient way of printing strings. Even though when the % s format specifier is used with printf it allows the printing of strings, puts offers a convenient and compact way to perform the same job.

    Similar to the puts function, there used to be a gets function. It was used to read a character type array that included whitespace characters. However, after the C11 standards came into effect, the gets function is no longer used.

    Apart from these basic input/output functions, there are many other input/output functions that are used to read and write data files. Error-checking mechanisms are also incorporated in file input/output functions. These functions involve the use of file pointers, and will be discussed later when we discuss how to create and process files in C.

    The following programs illustrate the use of the basic input/output functions that we have discussed so far:

    Example 1

    Let a and b be two integer quantities where a=10 and b=20. The following program exchanges or swaps the values of the two variables.

    #include<stdio.h>
    int main()
    {
      int a=10;
      int b=20;
      int c;
      c=a;
      a=b;
      b=c;
      printf("After swapping values are:n");
      printf("A=%d",a);
      printf("nB=%d",b);
      return 0;
    }
    Output:
    
    After swapping values are:
    A=20
    B=10

    The above program uses a temporary variable to swap the two values. The following program does the same job without using a third variable.

    Example 2

    Swapping values without using a third variable:

    #include<stdio.h>
    int main()
    {
      int a=10;
      int b=20;
    
      a=a+b; //a=30
      b=a-b;//b=30-10=20
      a=a-b; //a=30-20=10
      printf("A=%d",a);
      printf("nB=%d",b);
      return 0;
    }
    
    Output: 
    A=20
    B=10

    The above program can also be implemented by using the multiplication (*) and division (/) operators.

    Example 3

    Printing ASCII  code of a character and vice versa:

    #include<stdio.h>
    int main()
    {
      char letter='a';
      int number=97;
      printf("%d",letter);
      printf("n%c",number);
      return 0;
    }
    Output:
    97
    a

    Explanation

    We have already seen that every character has an equivalent ASCII code and that character and integer types are compatible. Therefore, in the above program, the %d format specifier prints the equivalent ASCII code of the letter a.

    Similarly, the %c format specifier prints the character whose equivalent ASCII code is 97. This  knowledge can be used to convert a letter from uppercase to lowercase. The same has been demonstrated in the following example.

    Example 4

    Converting a lowercase alphabet to uppercase:

    #include<stdio.h>
    int main()
    {
      char c='a';
      int d;
      d=c-32; //d=97-32=65 (ASCII of 'A')
      printf("%c",d); //prints character equivalent of the integer value stored in d
      return 0;
    }
    Output:
    A

    The above program can be modified to change the case of an entire line of text. This can be accomplished by using a loop.

    The next article in this series will begin with the discussion of control structures, which include decision-making statements, selection statements and iteration statements (loops).