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:where:int printf(const char *format_string, ...);
Another look at the general form:
format_string A string (character array) ... An optional list of expressions to print.
| <------------ 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);
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
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
Fortunately, some compilers (gcc) will alert you to these errors: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
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:
Output: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) */
Common printf conversion specifiers:GPA is 3.78 GPA is 3.780000e+000 PI is 3.14159 PI is 3.141593e+000
%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:
where%[flags][width][.precision]type
flags Optional characters to (among other things) control justification (left/right) and characters used for padding. Default is right justification. A minus sign indicates left justification. width Optional number that controls the minimum number of characters to output. .precision Optional 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).
Also, how do you exactly represent 1/3 in decimal? You can't:
Same value Same value 21 021 0021 00021 3.14 3.140 3.1400 3.14000
A few examples will explain this better:1.333333333333....
Output: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);
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.|21|···21|21···|·0021|21| |165.889999|···165.890|·1.659e+02|165.89····|166·······|
The first two format specifiers below use the precision for leading zeros and the second two use a leading zero in the format specifier:
Output:printf("|%5.3i|%5.5i|%03i|%05i|\n", age, age, age, age);
It will also work with floating point numbers:| 021|00021|021|00021|
Output:printf("|%010.3f|%010.3e|\n", wt, wt);
|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 charactersOther escape sequences: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
Keep in mind these sequences are considered single characters.Sequence Meaning ------------------------- \0 NUL character \" double quote \\ backslash
The percent sign is special. To display that, you must use two of them: %%
Example:
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.)printf("\"\\%%\t%%\t%%\\\"\n");
"\% % %\"
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:where:int scanf(const char *format_string, ...); int printf(const char *format_string, ...);
Another look at the general forms:
format_string A string (character array) ... A list of memory locations (addresses) to store the values that were read in (from the keyboard).
and an example. After the value is input into age, it is displayed by the printf function:int scanf(string, location1, location2, location3, ... ); int printf(string, expression1, expression2, expression3, ... );
Although scanf looks a lot like printf, their behavior is quite different.int age; scanf("%d", &age); printf("Your age is %d\n", age);
Incorrect way to read in the same four integers:int a, b, c, d; scanf("%d%d%d%d", &a, &b, &c, &d); printf("%d %d %d %d\n", a, b, c, d);
Fortunately, most compilers today will recognize the fatal mistake and warn you about it:scanf("%d%d%d%d", a, b, c, d);
You might see this with Microsoft's compilers: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)
Another example: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
The user could enter the data in this fashion:int i1, i2; float f1, f2; scanf("%d%f%d%f", &i1, &f1, &i2, &f2);
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 (with dots showing the spaces: 1·3.14-15·2.71e2)
or this:1 3.14 -15 2.71e2
Another example:1 3.14-15 2.71e2
Input:int i1, i2; float f1, f2; scanf("%d%d%f%f", &i1, &i2, &f1, &f2);
The program will print this:5-30.7-3.14e2
Usually, you will pair up calls to scanf and printf. Otherwise, the user has no idea what the computer is waiting for.5 -30 0.700000 -314.000000
#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.)
A full example with proper documentation (comments):What is your age? 21 What is your GPA? 3.478 Your age is 21 and your GPA is 3.48
|
|
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?
Additional points: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.