C Programming/Simple output
Machines process things. We feed stuff into a machine and get different stuff out. A saw turns trees into planks. An internal combustion engine turns gasoline into rotational energy. A computer is no different. But instead of physical materials, computers process information for us.
We feed information into the computer, tell the computer what do with it, and then get a result back out. The information we put into a computer is called input and the information we receive from the computer is called output. Input can come from just about anywhere. Keystrokes on a keyboard, data from an internet connection, or sound waves converted to electrical signals are examples of input. Output can also take many forms such as video played on a monitor, a string of text displayed in a terminal, or data we save onto a hard drive. The collection of input and generation of output is known under the general term, input/output, or I/O for short, and is a core function of computers.
We have already used an output library function in the Hello, World! example at the beginning of this text: puts(). You may recall this function resided in the stdio.h library file. As that file's name implies, stdio.h contains standardized I/O functions for adding input and output capability to our programs. This section of the text will explore its basic functions for outputting text to the screen.
Simple output
[edit | edit source]Recall from the beginning of this text the demonstration program duplicated below:
#include <stdio.h> int main(void) { puts("Hello, World!"); return 0; } |
If you compile and run this program, you will see the sentence below show up on your screen:
Hello, World!
This amazing accomplishment was achieved by using the function puts(). A function is like a "black box" that does something for you without exposing the internals inside. We can write functions ourselves in C, but we will cover that later.
You have seen that to use puts() one puts text, surrounded by quotes, in between the parentheses. We call the text surrounded by quotes a literal string (or just a string), and we call that string an argument to puts.
As a note of explanation, it is sometimes convenient to include the opening and closing parentheses after a function name to remind us that it is, indeed, a function. However usually when the name of the function we are talking about is understood, it is not necessary.
As you can see in the example above, using puts() can be as simple as typing in some text, surrounded by double quotes (note that these are double quotes and not two single quotes). So, for example, you can print any string by placing it as an argument to the puts() function:
puts("This sentence will print out exactly as you see it..."); And once it is contained in a proper main() function, it will show:
This sentence will print out exactly as you see it...
Formatted output
[edit | edit source]The printf() function is a powerful function, and is probably the most-used function in command-line C programs.
For example, let us look at a problem. Say we want to calculate: 19 + 31. Let's use C to get the answer.
We start writing:
#include <stdio.h> // this is important, since printf // can't be used without this header int main(void) { printf("19+31 is"); But here we are stuck! printf() only prints strings! Thankfully, printf has methods for printing numbers. What we do is put a placeholder format code in the string. We write:
printf("19+31 is %d", 19+31); The placeholder %d literally "holds the place" for the actual number that is the result of adding 19 to 31.
Format specifiers
[edit | edit source]These placeholders are called format specifiers. Many other format specifiers work with printf(). If we have a floating-point number, we can use %f to print out a floating-point number, decimal point and all. Other format specifiers are:
%d,%i-int%ld,%li-long int%f-float%lf,%g-double[1]%c-char%s- string%x-int, but shown in hexadecimal instead of decimal
A complete listing of all the format specifiers for printf() is in the standard library reference of this book.
If you want to literally have a % in the format string, write it as %%. The first % will make printf think this is the start of a format specifier, but the second % tells it otherwise.
Multiple arguments
[edit | edit source]You can print multiple values with the same printf call. Every time you add a format specifier to the format string, add another argument to the printf call. For example:
printf("The quick %s fox jumped over %d lazy dogs", "brown", 3); Functions like printf that can take varying numbers of arguments are called variadic.
Escape characters
[edit | edit source]What if, we want to achieve some output that will look like:
1905 + 312 ----- 2217
printf() will not put line breaks in at the end of each statement: we must do this ourselves. But how?
What we can do is use the newline escape character. An escape character is a special character that we can write but will do something special onscreen, such as make a beep, write a tab, and so on. To write a newline we write \n. All escape characters start with a backslash.
So to achieve the output above, we write:
printf(" 1905\n+ 312\n-----\n %d\n", 1905 + 312); or to be a bit clearer, we can break this long printf statement over several lines. So our program will be:
#include <stdio.h> int main(void) { printf(" 1905\n"); printf("+ 312\n"); printf("-----\n"); printf(" %d\n", 1905 + 312); return 0; } |
There are other escape characters we can use. Another common one is to use \t to write a tab. You can use \a to ring the computer's bell, but you should not use this very much in your programs, as excessive use of sound is not very friendly to the user.
Escape sequences work outside of printf, too! They can be used anywhere a string literal can be used. |
Controlling formatting
[edit | edit source]Format specifiers are great—we can print all of the text and numbers that we want, and in the places we want too. But, what if we need to cut off a too-long string, or have thousands separators in large integers, or round decimals for display? We can be more specific in formatting data by placing more information in the format string between the % and the letter(s) that identifies the type.
A full format specifier has this pattern, with optional parts in [square brackets]:
% | [argument$] | [flags] | [width] | [.precision] | type |
Let's break down what these optional parts do.
argument$
[edit | edit source]By default, printf matches the first format specifier with the first argument, the second with the second, the third with the third, and so on. We must pass it as many arguments as there are format specifiers. This is inconvenient if we want to use the same piece of data multiple times in our program's output.
However, if we put an integer (starting from 1) and a $ after the %, we can tell printf to use the same argument multiple times. In this example:
// Calculate the square of a number. printf("%d * %d = %d", 4, 4, 16); printf("%1$d * %1$d = %2$d", 4, 16); Both these calls output 4 * 4 = 16.
| This feature, while widely available, is nonstandard, unlike the other optional parts of the format string. |
flags
[edit | edit source]The way that numbers are displayed can be controlled by adding any of these flags to the format string:
', to add thousands separators to numbers+, to put a plus sign before positive numbers- Negative numbers already get a negative sign!
(a space) to put a leading space before positive numbers#, which does something different depending on the type of our data:- for a
%g/%G(automatically choose between fixed-point and exponential format for decimals), keep trailing zeroes - for any decimal, always have a decimal point
- for hexadecimal and octal output, add a
0x,0X, or0before the output
- for a
Two other flags interact with width, which we'll look at next:
-, to left-align something if its output won't be wide enough- Normally, small items are right-aligned.
0, which pads a number with zeroes if its output won't be wide enough- Normally, small items are padded with spaces.
width
[edit | edit source]Width is the minimum number of characters something should take up when output to the screen. Anything too small will be padded with spaces and right-aligned, unless a flag has overridden it, while anything too large will be output as-is.
printf("[%3d]", 5); printf("[%-3d]", 5); printf("[%03d]", 5); printf("[%3d]", 1000); Output: [ 5] [5 ] [005] [1000] |
.precision
[edit | edit source]For most types, this is the opposite of width: a maximum limit on size, but not a minimum limit. For decimal types, this is how many digits to output after the decimal point.
Taking everything together, a format specifier of %2$ '3.4lf means to format:
- the second parameter (
2$) - with leading spaces for positive numbers (
) - with thousands separators (
') - at least three characters wide (
3) - with four digits after the decimal point (
.4) - for a
double(lf)
Gosh, wouldn't it be nice to output something that isn't hardcoded into our program? In the next page, we'll cover variables.
Notes
[edit | edit source]- ↑ Actually
%fprintsdoubles as well, but the use of%ffor input is different. For more details, see the Wikipedia article on C data types.