Formatted Input/Output

The input and output facilities provided by printf and scanf are both simple and powerful. You will NOT learn these functions by reading and taking notes alone. You MUST practice with examples on your own. Also, there are many different ways to format output. If you are interested in finding out, then YOU must experiment with them. (I'm not going to play the what if... game.)

Simple Formatted Output

The most common facility used to output information is the printf function (print formatted). The general form of the function is:
int printf(const char *format_string, ...);
where:
format_string A string (character array)
... An optional list of expressions to print.
Another look at the general form:
                   |  <------------ Optional ------------>  |
int printf(string, expression1, expression2, expression3, ...  );

printf can only print strings (characters/words). If you wish to print a number, you have to convert it to a string first. Fortunately, printf makes this very easy. Within string, there are usually one or more conversion specifiers that determine how to print numeric values. You can think of these specifiers as placeholders for the actual value that will be formatted and printed.

Examples:

#include <stdio.h> /* printf */

int main(void)
{
  int age = 18;           /* Some student's age     */
  float gpa = 3.78F;      /* Some student's GPA     */
  double pi = 3.14159265; /* PI to 8 decimal places */

    /* Print out the values in various formats */
  printf("Hello\n");
  printf("John's age is %i\n", age);
  printf("John's age is %d\n", age);
  printf("His GPA is %f\n", gpa);
  printf("The value of PI is %f\n", pi);
  printf("John is %i years old and his GPA is %f\n", age, gpa);

  return 0;
}
Output:
Hello
John's age is 18
John's age is 18
His GPA is 3.780000
The value of PI is 3.141593
John is 18 years old and his GPA is 3.780000


Incorrect usage:

printf("John is %f years old\n", age);
printf("His GPA is %i\n", gpa);
printf("John is %i years old\n", age, gpa);
printf("John is %i years old and his GPA is %f\n", age);

Output when compiled with gcc:
John is -0.000000 years old
His GPA is -1610612736
John is 18 years old
John is 18 years old and his GPA is 0.000000

Output from Borland's C compiler:
John is +NAN years old
His GPA is -1610612736
John is 18 years old
John is 18 years old and his GPA is 0.000000

Output when compiled with Microsoft's C compiler:
John is 79648294434967839000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000.000000 years old
His GPA is -1610612736
John is 18 years old
John is 18 years old and his GPA is 7978913599429028900000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000.000000
Fortunately, some compilers (gcc) will alert you to these errors:

printf("John is %f years old\n", age);                  /* warning: double format, different type arg (arg 2) */
printf("His GPA is %i\n", gpa);                         /* warning: int format, double arg (arg 2)            */
printf("John is %i years old\n", age, gpa);              /* warning: too many arguments for format             */
printf("John is %i years old and his GPA is %f\n", age); /* warning: too few arguments for format              */

printf(5);                                               /* warning: format not a string literal               */   
printf();                                                /* error: too few arguments to function 'printf'      */   

An example using a larger expression:

int a = 3;  
int b = 5;

printf("The sum of a and b is %i\n", a + b);
printf("a = %i and b = %i, so 2 * (a + b) - 3 = %i\n", a, b, 2 * (a + b) - 3);
The sum of a and b is 8
a = 3 and b = 5, so 2 * (a + b) - 3 = 13


More examples:

float gpa = 3.78F;
double pi = 3.14159265;

printf("GPA is %g\n", gpa); /* Significant digits                     */
printf("GPA is %e\n", gpa); /* Scientific notation (default 6 places) */
printf("PI is %g\n", pi);   /* Significant digits (default 6 digits)  */
printf("PI is %e\n", pi);   /* Scientific notation (default 6 places) */
Output:
GPA is 3.78
GPA is 3.780000e+000
PI is 3.14159
PI is 3.141593e+000
Common printf conversion specifiers:
%c - characters
%s - strings (NUL terminated C strings)
%d - integers
%i - integers
%f - floating point (float and double)
%e - scientific notation
%g - floating point (minimum digits)
%p - pointers (displays in hex)
%x - hexadecimal integers
%u - unsigned
%ld, %li - long integers
%lu - unsigned long integers

Controlling Size and Precision

The conversion specifiers determine the type of the data to display. If you want to have more control over the output, you need to specify additional information in the format string.

The general form is this:

%[flags][width][.precision]type
where
flagsOptional characters to (among other things) control justification (left/right) and characters used for padding. Default is right justification. A minus sign indicates left justification.
widthOptional number that controls the minimum number of characters to output.
.precisionOptional number that controls whether or not to print a decimal point and how many digits to the right of the point to print.
For integers, it specifies the minimum number of digits to print.

Leading zeros (to the left of the decimal point) do not change the value of the number, nor do trailing zeros (to the right).

Same valueSame value
   21
  021
 0021
00021
      
   3.14
   3.140
   3.1400
   3.14000

Also, how do you exactly represent 1/3 in decimal? You can't:
1.333333333333....
A few examples will explain this better:
int age = 21;
float wt = 165.89F;

printf("|%i|%5i|%-5i|%5.4i|%1i|\n", age, age, age, age, age);
printf("|%f|%10.3f|%10.3e|%-10g|%-10.3g|\n", wt, wt, wt, wt, wt);
Output:
|21|   21|21   | 0021|21|
|165.889999|   165.890| 1.659e+02|165.89    |166       |
Showing with a dot · for each space:
|21|···21|21···|·0021|21|
|165.889999|···165.890|·1.659e+02|165.89····|166·······|
By default, if the width is greater than the number of digits printed, the field is padded with leading spaces. If you want to pad with leading zeros, you can use the precision (as shown above) or you can use a leading zero in the format specifier.

The first two format specifiers below use the precision for leading zeros and the second two use a leading zero in the format specifier:

printf("|%5.3i|%5.5i|%03i|%05i|\n", age, age, age, age);
Output:
|  021|00021|021|00021|
It will also work with floating point numbers:
printf("|%010.3f|%010.3e|\n", wt, wt);
Output:
|000165.890|01.659e+02|

Escape Sequences

Certain characters are not printable, meaning nothing is displayed on the screen (or printer) when you output them with printf. Some of them are print control codes (special values that the display or printer interpret differently). Common non-printing control characters
ASCII
Value   Sequence       Meaning
-----------------------------------
  7        \a         bell (alarm)
  8        \b         backspace
  9        \t         horiz. tab
 10        \r         line feed
 11        \v         vert. tab
 12        \f         form feed
 13        \n         new line 
Other escape sequences:
Sequence     Meaning 
-------------------------
  \0       NUL character
  \"       double quote
  \\       backslash
Keep in mind these sequences are considered single characters.

The percent sign is special. To display that, you must use two of them: %%

Example:

printf("\"\\%%\t%%\t%%\\\"\n");
Output: (10 characters. There is a TAB character between each percent sign and depending on the environment that's printing the characters, the output may look different.)
"\%     %       %\"

The TAB character may seem to exhibit unusual behavior. The distance between the percent symbols above is the not the same. This is the difference between a TAB character expanding to a fixed number of spaces and the TAB character moving to the next TAB stop.

Simple Input

A common way to input information is the scanf function (scan formatted). The general form of the function is very similar to printf:
int  scanf(const char *format_string, ...);
int printf(const char *format_string, ...);
where:
format_string A string (character array)
... A list of memory locations (addresses) to store the values that were read in (from the keyboard).
Another look at the general forms:
int  scanf(string, location1, location2, location3, ...  );
int printf(string, expression1, expression2, expression3, ...  );
and an example. After the value is input into age, it is displayed by the printf function:
int age;
scanf("%d", &age);
printf("Your age is %d\n", age);
Although scanf looks a lot like printf, their behavior is quite different. Any of these characters are considered whitespace characters: Reading in four integers and printing them out to the screen:
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
printf("%d %d %d %d\n", a, b, c, d);
Incorrect way to read in the same four integers:
scanf("%d%d%d%d", a, b, c, d);
Fortunately, most compilers today will recognize the fatal mistake and warn you about it:
main.c:30: warning: format argument is not a pointer (arg 2)
main.c:30: warning: format argument is not a pointer (arg 3)
main.c:30: warning: format argument is not a pointer (arg 4)
main.c:30: warning: format argument is not a pointer (arg 5)
You might see this with Microsoft's compilers:
main.c(30) : warning C4700: local variable 'd' used without having been initialized
main.c(30) : warning C4700: local variable 'c' used without having been initialized
main.c(30) : warning C4700: local variable 'b' used without having been initialized
main.c(30) : warning C4700: local variable 'a' used without having been initialized
Another example:
int i1, i2;
float f1, f2;
scanf("%d%f%d%f", &i1, &f1, &i2, &f2);
The user could enter the data in this fashion:
1 3.14   -15     2.71e2        (with dots showing the spaces: 1·3.14···-15·····2.71e2)
or like this:
1 3.14-15 2.71e2       (with dots showing the spaces: 1·3.14-15·2.71e2)
or this:
1
3.14
-15
2.71e2       
or this:
1
  3.14-15
  
  
    2.71e2       
Another example:
int i1, i2;
float f1, f2;
scanf("%d%d%f%f", &i1, &i2, &f1, &f2);
Input:
5-30.7-3.14e2
The program will print this:
5 -30 0.700000 -314.000000	
Usually, you will pair up calls to scanf and printf. Otherwise, the user has no idea what the computer is waiting for.

#include <stdio.h> /* printf, scanf */

int main(void)
{
  int age;   /* Student's age */
  float gpa; /* Student's GPA */

    /* Ask for and read in student's age */
  printf("What is your age? ");
  scanf("%d", &age);

    /* Ask for and read in student's GPA */
  printf("What is your GPA? ");
  scanf("%f", &gpa);

    /* Format and print out both values */
  printf("Your age is %d and your GPA is %.2f\n", age, gpa);

  return 0;
}
Sample session: (The characters in red were typed in by the user.)
What is your age? 21
What is your GPA? 3.478
Your age is 21 and your GPA is 3.48
A full example with proper documentation (comments):
#include <stdio.h> /* printf, scanf */
	
int main(void)
{
  float celsius;    /* To hold the original celsius value      */
  float fahrenheit; /* To hold the converted fahrenheit value. */

    /* Ask user for the Celsius temperature */
  printf("Enter a temperature in Celsius: ");

    /* Read the input into the variable */
  scanf("%f", &celsius);

    /* Calculate fahrenheit from celsius. */
  fahrenheit = (9.0F * celsius / 5.0F) + 32;

    /* Display fahrenheit with 2 decimal places. */
  printf("The temperature in Fahrenheit is %.2f\n", fahrenheit);
  
    /* Return value to the OS. */
  return 0;
}
#include <stdio.h> /* printf, scanf */
	
int main(void)
{
  float celsius;    /* To hold the original celsius value      */
  float fahrenheit; /* To hold the converted fahrenheit value. */

    /* Ask user for the Celsius temperature and save it */
  printf("Enter a temperature in Celsius: ");
  scanf("%f", &celsius);

    /* Calculate fahrenheit from celsius. */
  fahrenheit = (9.0F * celsius / 5.0F) + 32;

    /* Display fahrenheit with 2 decimal places. */
  printf("The temperature in Fahrenheit is %.2f\n", fahrenheit);
  
    /* Return value to the OS. */
  return 0;
}

Sample runs:

Enter a temperature in Celsius: 41.5
The temperature in Fahrenheit is 106.70

Enter a temperature in Celsius: 100
The temperature in Fahrenheit is 212.00

Enter a temperature in Celsius: 0
The temperature in Fahrenheit is 32.00

Enter a temperature in Celsius: -40
The temperature in Fahrenheit is -40.00

Side Question: Why were these numbers chosen to "test" the program?

Note: You will vary rarely (if ever) use scanf in a real, live, production setting. It's just too error-prone. Any time you allow the user to type whatever they want into your program, you are asking for trouble. scanf is better used with computer-generated (read: perfect and exact) input. There are safer ways to get input. However, for trivial and toy programs (e.g. CS 120), scanf will be OK.

Additional points: