Commit | Line | Data |
---|---|---|
8340f87c BJ |
1 | .NH |
2 | THE STANDARD I/O LIBRARY | |
3 | .PP | |
4 | The ``Standard I/O Library'' | |
5 | is a collection of routines | |
6 | intended to provide | |
7 | efficient | |
8 | and portable | |
9 | I/O services | |
10 | for most C programs. | |
11 | The standard I/O library is available on each system that supports C, | |
12 | so programs that confine | |
13 | their system interactions | |
14 | to its facilities | |
15 | can be transported from one system to another essentially without change. | |
16 | .PP | |
17 | In this section, we will discuss the basics of the standard I/O library. | |
18 | The appendix contains a more complete description of its capabilities. | |
19 | .NH 2 | |
20 | File Access | |
21 | .PP | |
22 | The programs written so far have all | |
23 | read the standard input and written the standard output, | |
24 | which we have assumed are magically pre-defined. | |
25 | The next step | |
26 | is to write a program that accesses | |
27 | a file that is | |
28 | .ul | |
29 | not | |
30 | already connected to the program. | |
31 | One simple example is | |
32 | .IT wc , | |
33 | which counts the lines, words and characters | |
34 | in a set of files. | |
35 | For instance, the command | |
36 | .P1 | |
37 | wc x.c y.c | |
38 | .P2 | |
39 | prints the number of lines, words and characters | |
40 | in | |
41 | .UL x.c | |
42 | and | |
43 | .UL y.c | |
44 | and the totals. | |
45 | .PP | |
46 | The question is how to arrange for the named files | |
47 | to be read \(em | |
48 | that is, how to connect the file system names | |
49 | to the I/O statements which actually read the data. | |
50 | .PP | |
51 | The rules are simple. | |
52 | Before it can be read or written | |
53 | a file has to be | |
54 | .ul | |
55 | opened | |
56 | by the standard library function | |
57 | .UL fopen . | |
58 | .UL fopen | |
59 | takes an external name | |
60 | (like | |
61 | .UL x.c | |
62 | or | |
63 | .UL y.c ), | |
64 | does some housekeeping and negotiation with the operating system, | |
65 | and returns an internal name | |
66 | which must be used in subsequent | |
67 | reads or writes of the file. | |
68 | .PP | |
69 | This internal name is actually a pointer, | |
70 | called a | |
71 | .IT file | |
72 | .IT pointer , | |
73 | to a structure | |
74 | which contains information about the file, | |
75 | such as the location of a buffer, | |
76 | the current character position in the buffer, | |
77 | whether the file is being read or written, | |
78 | and the like. | |
79 | Users don't need to know the details, | |
80 | because part of the standard I/O definitions | |
81 | obtained by including | |
82 | .UL stdio.h | |
83 | is a structure definition called | |
84 | .UL FILE . | |
85 | The only declaration needed for a file pointer | |
86 | is exemplified by | |
87 | .P1 | |
88 | FILE *fp, *fopen(); | |
89 | .P2 | |
90 | This says that | |
91 | .UL fp | |
92 | is a pointer to a | |
93 | .UL FILE , | |
94 | and | |
95 | .UL fopen | |
96 | returns a pointer to | |
97 | a | |
98 | .UL FILE . | |
99 | .UL FILE \& ( | |
100 | is a type name, like | |
101 | .UL int , | |
102 | not a structure tag. | |
103 | .PP | |
104 | The actual call to | |
105 | .UL fopen | |
106 | in a program | |
107 | is | |
108 | .P1 | |
109 | fp = fopen(name, mode); | |
110 | .P2 | |
111 | The first argument of | |
112 | .UL fopen | |
113 | is the | |
114 | name | |
115 | of the file, | |
116 | as a character string. | |
117 | The second argument is the | |
118 | mode, | |
119 | also as a character string, | |
120 | which indicates how you intend to | |
121 | use the file. | |
122 | The only allowable modes are | |
123 | read | |
124 | .UL \&"r" ), ( | |
125 | write | |
126 | .UL \&"w" ), ( | |
127 | or append | |
128 | .UL \&"a" ). ( | |
129 | .PP | |
130 | If a file that you open for writing or appending does not exist, | |
131 | it is created | |
132 | (if possible). | |
133 | Opening an existing file for writing causes the old contents | |
134 | to be discarded. | |
135 | Trying to read a file that does not exist | |
136 | is an error, | |
137 | and there may be other causes of error | |
138 | as well | |
139 | (like trying to read a file | |
140 | when you don't have permission). | |
141 | If there is any error, | |
142 | .UL fopen | |
143 | will return the null pointer | |
144 | value | |
145 | .UL NULL | |
146 | (which is defined as zero in | |
147 | .UL stdio.h ). | |
148 | .PP | |
149 | The next thing needed is a way to read or write the file | |
150 | once it is open. | |
151 | There are several possibilities, | |
152 | of which | |
153 | .UL getc | |
154 | and | |
155 | .UL putc | |
156 | are the simplest. | |
157 | .UL getc | |
158 | returns the next character from a file; | |
159 | it needs the file pointer to tell it what file. | |
160 | Thus | |
161 | .P1 | |
162 | c = getc(fp) | |
163 | .P2 | |
164 | places in | |
165 | .UL c | |
166 | the next character from the file referred to by | |
167 | .UL fp ; | |
168 | it returns | |
169 | .UL EOF | |
170 | when it reaches end of file. | |
171 | .UL putc | |
172 | is the inverse of | |
173 | .UL getc : | |
174 | .P1 | |
175 | putc(c, fp) | |
176 | .P2 | |
177 | puts the character | |
178 | .UL c | |
179 | on the file | |
180 | .UL fp | |
181 | and returns | |
182 | .UL c . | |
183 | .UL getc | |
184 | and | |
185 | .UL putc | |
186 | return | |
187 | .UL EOF | |
188 | on error. | |
189 | .PP | |
190 | When a program is started, three files are opened automatically, | |
191 | and file pointers are provided for them. | |
192 | These files are the standard input, | |
193 | the standard output, | |
194 | and the standard error output; | |
195 | the corresponding file pointers are | |
196 | called | |
197 | .UL stdin , | |
198 | .UL stdout , | |
199 | and | |
200 | .UL stderr . | |
201 | Normally these are all connected to the terminal, | |
202 | but | |
203 | may be redirected to files or pipes as described in | |
204 | Section 2.2. | |
205 | .UL stdin , | |
206 | .UL stdout | |
207 | and | |
208 | .UL stderr | |
209 | are pre-defined in the I/O library | |
210 | as the standard input, output and error files; | |
211 | they may be used anywhere an object of type | |
212 | .UL FILE\ * | |
213 | can be. | |
214 | They are | |
215 | constants, however, | |
216 | .ul | |
217 | not | |
218 | variables, | |
219 | so don't try to assign to them. | |
220 | .PP | |
221 | With some of the preliminaries out of the way, | |
222 | we can now write | |
223 | .IT wc . | |
224 | The basic design | |
225 | is one that has been found | |
226 | convenient for many programs: | |
227 | if there are command-line arguments, they are processed in order. | |
228 | If there are no arguments, the standard input | |
229 | is processed. | |
230 | This way the program can be used stand-alone | |
231 | or as part of a larger process. | |
232 | .P1 | |
233 | #include <stdio.h> | |
234 | ||
235 | main(argc, argv) /* wc: count lines, words, chars */ | |
236 | int argc; | |
237 | char *argv[]; | |
238 | { | |
239 | int c, i, inword; | |
240 | FILE *fp, *fopen(); | |
241 | long linect, wordct, charct; | |
242 | long tlinect = 0, twordct = 0, tcharct = 0; | |
243 | ||
244 | i = 1; | |
245 | fp = stdin; | |
246 | do { | |
247 | if (argc > 1 && (fp=fopen(argv[i], "r")) == NULL) { | |
248 | fprintf(stderr, "wc: can't open %s\n", argv[i]); | |
249 | continue; | |
250 | } | |
251 | linect = wordct = charct = inword = 0; | |
252 | while ((c = getc(fp)) != EOF) { | |
253 | charct++; | |
254 | if (c == '\n') | |
255 | linect++; | |
256 | if (c == ' ' || c == '\t' || c == '\n') | |
257 | inword = 0; | |
258 | else if (inword == 0) { | |
259 | inword = 1; | |
260 | wordct++; | |
261 | } | |
262 | } | |
263 | printf("%7ld %7ld %7ld", linect, wordct, charct); | |
264 | printf(argc > 1 ? " %s\n" : "\n", argv[i]); | |
265 | fclose(fp); | |
266 | tlinect += linect; | |
267 | twordct += wordct; | |
268 | tcharct += charct; | |
269 | } while (++i < argc); | |
270 | if (argc > 2) | |
271 | printf("%7ld %7ld %7ld total\n", tlinect, twordct, tcharct); | |
272 | exit(0); | |
273 | } | |
274 | .P2 | |
275 | The function | |
276 | .UL fprintf | |
277 | is identical to | |
278 | .UL printf , | |
279 | save that the first argument is a file pointer | |
280 | that specifies the file to be | |
281 | written. | |
282 | .PP | |
283 | The function | |
284 | .UL fclose | |
285 | is the inverse of | |
286 | .UL fopen ; | |
287 | it breaks the connection between the file pointer and the external name | |
288 | that was established by | |
289 | .UL fopen , | |
290 | freeing the | |
291 | file pointer for another file. | |
292 | Since there is a limit on the number | |
293 | of files | |
294 | that a program may have open simultaneously, | |
295 | it's a good idea to free things when they are no longer needed. | |
296 | There is also another reason to call | |
297 | .UL fclose | |
298 | on an output file | |
299 | \(em it flushes the buffer | |
300 | in which | |
301 | .UL putc | |
302 | is collecting output. | |
303 | .UL fclose \& ( | |
304 | is called automatically for each open file | |
305 | when a program terminates normally.) | |
306 | .NH 2 | |
307 | Error Handling \(em Stderr and Exit | |
308 | .PP | |
309 | .UL stderr | |
310 | is assigned to a program in the same way that | |
311 | .UL stdin | |
312 | and | |
313 | .UL stdout | |
314 | are. | |
315 | Output written on | |
316 | .UL stderr | |
317 | appears on the user's terminal | |
318 | even if the standard output is redirected. | |
319 | .IT wc | |
320 | writes its diagnostics on | |
321 | .UL stderr | |
322 | instead of | |
323 | .UL stdout | |
324 | so that if one of the files can't | |
325 | be accessed for some reason, | |
326 | the message | |
327 | finds its way to the user's terminal instead of disappearing | |
328 | down a pipeline | |
329 | or into an output file. | |
330 | .PP | |
331 | The program actually signals errors in another way, | |
332 | using the function | |
333 | .UL exit | |
334 | to terminate program execution. | |
335 | The argument of | |
336 | .UL exit | |
337 | is available to whatever process | |
338 | called it (see Section 6), | |
339 | so the success or failure | |
340 | of the program can be tested by another program | |
341 | that uses this one as a sub-process. | |
342 | By convention, a return value of 0 | |
343 | signals that all is well; | |
344 | non-zero values signal abnormal situations. | |
345 | .PP | |
346 | .UL exit | |
347 | itself | |
348 | calls | |
349 | .UL fclose | |
350 | for each open output file, | |
351 | to flush out any buffered output, | |
352 | then calls | |
353 | a routine named | |
354 | .UL _exit . | |
355 | The function | |
356 | .UL _exit | |
357 | causes immediate termination without any buffer flushing; | |
358 | it may be called directly if desired. | |
359 | .NH 2 | |
360 | Miscellaneous I/O Functions | |
361 | .PP | |
362 | The standard I/O library provides several other I/O functions | |
363 | besides those we have illustrated above. | |
364 | .PP | |
365 | Normally output with | |
366 | .UL putc , | |
367 | etc., is buffered (except to | |
368 | .UL stderr ); | |
369 | to force it out immediately, use | |
370 | .UL fflush(fp) . | |
371 | .PP | |
372 | .UL fscanf | |
373 | is identical to | |
374 | .UL scanf , | |
375 | except that its first argument is a file pointer | |
376 | (as with | |
377 | .UL fprintf ) | |
378 | that specifies the file from which the input comes; | |
379 | it returns | |
380 | .UL EOF | |
381 | at end of file. | |
382 | .PP | |
383 | The functions | |
384 | .UL sscanf | |
385 | and | |
386 | .UL sprintf | |
387 | are identical to | |
388 | .UL fscanf | |
389 | and | |
390 | .UL fprintf , | |
391 | except that the first argument names a character string | |
392 | instead of a file pointer. | |
393 | The conversion is done from the string | |
394 | for | |
395 | .UL sscanf | |
396 | and into it for | |
397 | .UL sprintf . | |
398 | .PP | |
399 | .UL fgets(buf,\ size,\ fp) | |
400 | copies the next line from | |
401 | .UL fp , | |
402 | up to and including a newline, | |
403 | into | |
404 | .UL buf ; | |
405 | at most | |
406 | .UL size-1 | |
407 | characters are copied; | |
408 | it returns | |
409 | .UL NULL | |
410 | at end of file. | |
411 | .UL fputs(buf,\ fp) | |
412 | writes the string in | |
413 | .UL buf | |
414 | onto file | |
415 | .UL fp . | |
416 | .PP | |
417 | The function | |
418 | .UL ungetc(c,\ fp) | |
419 | ``pushes back'' the character | |
420 | .UL c | |
421 | onto the input stream | |
422 | .UL fp ; | |
423 | a subsequent call to | |
424 | .UL getc , | |
425 | .UL fscanf , | |
426 | etc., | |
427 | will encounter | |
428 | .UL c . | |
429 | Only one character of pushback per file is permitted. |