Previous | Table of Contents | Next |
There is more to the input and output functions than I described in Chapter 2. For one thing, printf and scanf support a wide variety of format specifiers, which are particularly useful with printf. For example, you can use %x to print integers in hexadecimal format. You can also control the spacing and precision of floating-point numbers as well as left-justify or right-justify your output fields. See the topics on printf and scanf in Part III.
Some of the most useful functions declared in STDIO.H support line-oriented input and output. You can use puts, for example, as a more efficient way of printing strings. The statement
printf(%s\n, string);
behaves the same way as
puts(string);
The latter version is more efficient, however, because it avoids the overhead of the more elaborate printf function. At the same time, the puts function is less flexible, because it prints a new line whether or not you want one.
One of the most useful functions declared in STDIO.H is gets (get string). When you call this function, it waits until the user types something and then presses the Enter key. Then the function places the entire line of inputspaces and allinto the string argument. For example:
#include <stdio.h> ... char str[81]; // Allow for max. chars on screen gets (str); // Get line of input and place in str.
I have found using gets far preferable to using scanf in all but the simplest programs. Once you read a line of input into a string, you are free to analyze it or interpret its contents any way you choose. This capability is useful in writing a compiler or other sophisticated tool, because you can lexically analyze the input as you wish. In plain terms, this means that you have total control over which characters divide different fields and how sequences of spaces should be interpreted. When you use scanf or cin, you have no control over how a numeric or string field is defined. The scanf function gives you input when and if it decides that the user has typed something valid.
As a simple example of line input, you might decide that your program accepts input delineated by the at sign (@):
Here is some input@1234@more input@34.0005
The following code uses gets to input this entire line. Then the code assigns each input fielddelineated by @to a different string. Although this example may seem odd, it does show how you could choose to input embedded spaces in strings, something that scanf and cin dont support.
#include <stdio.h> ... char str[81] ; // Allow for max. chars on screen char array [40] [81] ; gets (str); // Get line of input and place in str. int i = 0; char *p = str; char *s; while (*p != \0) { // Set s equal to next string in array. s = array[i++] ; // Read chars into string, up to next @ while (*p != \0 && *p != @) *s++ = *p++; // Stop reading terminate string and advance // pointer past the @. *S = \0 ; p++; }
When you have isolated a numeric field (for example, 1234) as input to one of these strings, you can optionally convert it to a numeric value by calling the atoi or atof function. These library functions are also declared in STDIO.H.
The line-oriented I/O functions of the previous sectiongets and putsare put to good use in the next example, which demonstrates sequential file I/O. This example prompts the user for a file name, but he or she has the option of just pressing Enter. The gets function responds in a reasonable way, inputting an empty string.
File input and output is almost as easy in C++ as it is in any other language. If you use standard library functions declared in STDIO.H, you should follow these four basic steps (which I also outlined in C in Plain English):
Figure 4.3 illustrates the first three steps. This figure is a bit oversimplified. In step 2, the fopen function actively checks the file system. (The function does more than simply associate a file with a name.) If the requested file is not found or for some reason cannot be opened, the program must stop and respond to the error condition.
Figure 4.3 Summary of file I/O programming.
The following example program illustrates each of these steps, although it calls fgetc rather than fprintf. Note that main has a return value in this program. This technique enables main to return a code to the operating system: 0 (for success) or -1 (for error).
// Sample program to print out the contents of a text // file, converting all lowercase to uppercase. // The program prompts for the file name. #include <stdio.h> #include <ctype.h> int main () { int c; FILE *fp; char filename [81] ; printf(Enter file name, please: ); gets (filename); if ((*filename) == \0 ) { // Test for empty string puts (No file name entered.\n); return -1; } /* Open for reading; r specifies read mode. */ fp = fopen (filename, r); if (!fp) { puts (Error: file name not found.\n); return -1; } while ((c = fgetc (fp)) != EOF) putchar (toupper (c)); fclose(fp); return 0; }
In the example, the file is treated as an input file, so it is opened for read mode in line 23. The second argument is a string containing r, for read mode. Write mode is w, and read-write mode is rw.
fp = fopen (filename, r);
Previous | Table of Contents | Next |