0% found this document useful (0 votes)
10 views71 pages

19.Chapter22 Input and Output-精简简版

Chapter 22 of 'Programming in C' focuses on input/output operations, detailing the use of streams, file operations, and formatted I/O functions. It introduces essential functions from the <stdio.h> library, including file management, reading/writing data, and handling text versus binary files. The chapter emphasizes the importance of understanding file modes, error handling, and the differences between standard input/output streams.

Uploaded by

raimovamirbek
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views71 pages

19.Chapter22 Input and Output-精简简版

Chapter 22 of 'Programming in C' focuses on input/output operations, detailing the use of streams, file operations, and formatted I/O functions. It introduces essential functions from the <stdio.h> library, including file management, reading/writing data, and handling text versus binary files. The chapter emphasizes the importance of understanding file modes, error handling, and the differences between standard input/output streams.

Uploaded by

raimovamirbek
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 71

Programing in C

Chapter 22 Input/Output
Outlines
• 22.1 Streams
• 22.2 File Operations
• 22.3 Formatted I/O
• 22.4 Character I/O
• 22.5 Line I/O
• 22.6 Block I/O
• 22.7 File Positioning

2
Introduction
• C’s input/output library is the biggest and most
important part of the standard library.
• The <stdio.h> header is the primary
repository of input/output functions, including
printf, scanf, putchar, getchar, puts,
and gets.
• This chapter provides more information about
these six functions.
• It also introduces many new functions, most of
which deal with files.

3
22.1 Streams
• In C, the term stream means any source of input
or any destination for output.
• Many small programs obtain all their input from
one stream (the keyboard) and write all their
output to another stream (the screen).
• Larger programs may need additional streams.
• Streams often represent files stored on various
media.
• However, they could just as easily be associated
with devices such as network ports and printers.

4
22.1 Streams
• Standard Streams and Redirection
– <stdio.h> provides three standard streams:

File Pointer StreamDefault Meaning


stdin Standard input Keyboard
stdout Standard output Screen
stderr Standard errorScreen

– These streams are ready to use—we don’t declare


them, and we don’t open or close them.
– The I/O functions discussed in previous chapters obtain
input from stdin and send output to stdout.

5
22.1 Streams
• Standard Streams and Redirection
– Many operating systems allow these default
meanings to be changed via a mechanism known
as redirection.

6
22.1 Streams
• File Pointers
– Accessing a stream is done through a file pointer,
which has type FILE *.
– The FILE type is declared in <stdio.h>.
– Certain streams are represented by file pointers with
standard names.
– Additional file pointers can be declared as needed:
FILE *fp1, *fp2;

7
22.1 Streams
• Text Files versus Binary Files
– <stdio.h> supports two kinds of files: text and
binary.
– The bytes in a text file represent characters, allowing
humans to examine or edit the file.
• The source code for a C program is stored in a text file.
– In a binary file, bytes don’t necessarily represent
characters.
• Groups of bytes might represent other types of data,
such as integers and floating-point numbers.
• An executable C program is stored in a binary file.

8
22.1 Streams
• Text Files versus Binary Files
– When data is written to a file, it can be stored in text
form or in binary form.
– One way to store the number 32767 in a file would
be to write it in text form as the characters 3, 2, 7, 6,
and 7:

9
22.1 Streams
• Text Files versus Binary Files
– The other option is to store the number in binary,
which would take as few as two bytes:

– Storing numbers in binary can often save space.

10
22.1 Streams
• Text Files versus Binary Files
– Text files have two characteristics that binary files
don’t possess.
– Text files are divided into lines. Each line in a text file
normally ends with one or two special characters.
• Windows: carriage-return character ('\x0d')
followed by line-feed character ('\x0a')
• UNIX and newer versions of Mac OS: line-feed
character
• Older versions of Mac OS: carriage-return character

11
22.1 Streams
• Text Files versus Binary Files
– Text files may contain a special “end-of-file”
marker.
• In Windows, the marker is '\x1a' (Ctrl-Z), but it
is not required.
• Most other operating systems, including UNIX,
have no special end-of-file character.
– In a binary file, there are no end-of-line or end-of-
file markers; all bytes are treated equally.

12
22.1 Streams
• Text Files versus Binary Files
– Programs that read from a file or write to a file must
take into account whether it’s text or binary.
– A program that displays the contents of a file on the
screen will probably assume it’s a text file.
– A file-copying program, on the other hand, can’t
assume that the file to be copied is a text file.
• If it does, binary files containing an end-of-file
character won’t be copied completely.
– When we can’t say for sure whether a file is text or
binary, it’s safer to assume that it’s binary.

13
22.2 File Operations
• Simplicity is one of the attractions of input and
output redirection.
• Unfortunately, redirection is too limited for many
applications.
– When a program relies on redirection, it has no control
over its files; it doesn’t even know their names.
– Redirection doesn’t help if the program needs to read
from two files or write to two files at the same time.
• When redirection isn’t enough, we’ll use the file
operations that <stdio.h> provides.

14
22.2 File Operations
• Opening a File
– Opening a file for use as a stream requires a call of the
fopen function.
– Prototype for fopen:
FILE *fopen(const char * filename,
const char * mode);
– filename is the name of the file to be opened.
• This argument may include information about the file’s
location, such as a drive specifier or path.
– mode is a “mode string” that specifies what operations
we intend to perform on the file.

15
22.2 File Operations
• Opening a File
– In Windows, be careful when the file name in a call of
fopen includes the \ character.
– The call fopen("c:\project\test1.dat", "r")
will fail, because \t is treated as a character escape.
– One way to avoid the problem is to use \\ instead
of \:
fopen("c:\\project\\test1.dat", "r")
– An alternative is to use the / character instead of \:
fopen("c:/project/test1.dat", "r")

16
22.2 File Operations
• Opening a File
– fopen returns a file pointer that the program can
(and usually will) save in a variable:
fp = fopen("in.dat", "r");
/* opens in.dat for reading */
– When it can’t open a file, fopen returns a null
pointer.

17
22.2 File Operations
• Modes
– Factors that determine which mode string to pass
to fopen:
• Which operations are to be performed on the file
• Whether the file contains text or binary data
– Mode strings for text files:
String Meaning
"r" Open for reading
"w" Open for writing (file need not exist)
"a" Open for appending (file need not exist)
"r+" Open for reading and writing, starting at beginning
"w+" Open for reading and writing (truncate if file exists)
"a+" Open for reading and writing (append if file exists)

18
22.2 File Operations
• Modes
– Mode strings for binary files:

String Meaning
"rb" Open for reading
"wb" Open for writing (file need not exist)
"ab" Open for appending (file need not exist)
"r+b" or "rb+" Open for reading and writing, starting at
beginning
"w+b" or "wb+" Open for reading and writing (truncate if file
exists)
"a+b" or "ab+" Open for reading and writing (append if file
exists)

19
22.2 File Operations
• Modes
– Note that there are different mode strings for writing data
and appending data.
– When data is written to a file, it normally overwrites what
was previously there.
– When a file is opened for appending, data written to the file
is added at the end.
– Special rules apply when a file is opened for both reading
and writing.
• Can’t switch from reading to writing without first calling a
file-positioning function unless the reading operation
encountered the end of the file.
• Can’t switch from writing to reading without either calling
fflush or calling a file-positioning function.
20
22.2 File Operations
• Closing a File
– The fclose function allows a program to close a file
that it’s no longer using.
– The argument to fclose must be a file pointer
obtained from a call of fopen or freopen.
– fclose returns zero if the file was closed
successfully.
– Otherwise, it returns the error code EOF (a macro
defined in <stdio.h>).

21
22.2 File Operations
• Closing a File
– The outline of a program that opens a file for reading:
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "example.dat"
int main(void)
{
FILE *fp;
fp = fopen(FILE_NAME, "r");
if (fp == NULL) {
printf("Can't open %s\n", FILE_NAME);
exit(EXIT_FAILURE);
}

fclose(fp);
return 0;
}
22
22.2 File Operations
• Closing a File
– It’s not unusual to see the call of fopen combined
with the declaration of fp:
FILE *fp = fopen(FILE_NAME, "r");
or the test against NULL:
if ((fp = fopen(FILE_NAME, "r")) == NULL)

23
22.2 File Operations
• Miscellaneous File Operations
– The remove and rename functions allow a program
to perform basic file management operations.
– Unlike most other functions in this section, remove
and rename work with file names instead of file
pointers.
– Both functions return zero if they succeed and a
nonzero value if they fail.

24
22.2 File Operations
• Miscellaneous File Operations
– remove deletes a file:
remove("foo");
/* deletes the file named "foo" */
– If a program uses fopen (instead of tmpfile)
to create a temporary file, it can use remove to
delete the file before the program terminates.
– The effect of removing a file that’s currently open
is implementation-defined.

25
22.2 File Operations
• Miscellaneous File Operations
– rename changes the name of a file:
rename("foo", "bar");
/* renames "foo" to "bar" */
– rename is handy for renaming a temporary file
created using fopen if a program should decide to
make it permanent.
• If a file with the new name already exists, the effect
is implementation-defined.
– rename may fail if asked to rename an open file.

26
22.3 Formatted I/O
• The next group of library functions use format strings
to control reading and writing.
• printf and related functions are able to convert
data from numeric form to character form during
output.
• scanf and related functions are able to convert
data from character form to numeric form during
input.

27
22.3 Formatted I/O
• The …printf Functions
– The fprintf and printf functions write a variable
number of data items to an output stream, using a format
string to control the appearance of the output.
– The prototypes for both functions end with the ... symbol
(an ellipsis), which indicates a variable number of additional
arguments:
int fprintf(FILE * restrict stream,
const char * restrict format, ...);
int printf(const char * restrict format, ...);
– Both functions return the number of characters written; a
negative return value indicates that an error occurred.

28
22.3 Formatted I/O
• The …printf Functions
– printf always writes to stdout, whereas fprintf
writes to the stream indicated by its first argument:
printf("Total: %d\n", total);
/* writes to stdout */
fprintf(fp, "Total: %d\n", total);
/* writes to fp */
– A call of printf is equivalent to a call of fprintf
with stdout as the first argument.

29
22.3 Formatted I/O
• The …printf Functions
– fprintf works with any output stream.
– One of its most common uses is to write error
messages to stderr:
fprintf(stderr, "Error: data file can't
be opened.\n");
– Writing a message to stderr guarantees that it will
appear on the screen even if the user redirects
stdout.

30
22.3 Formatted I/O
• The …scanf Functions
– fscanf and scanf read data items from an input
stream, using a format string to indicate the layout
of the input.
– After the format string, any number of pointers—
each pointing to an object—follow as additional
arguments.
– Input items are converted (according to conversion
specifications in the format string) and stored in
these objects.

31
22.3 Formatted I/O
• The …scanf Functions
– scanf always reads from stdin, whereas fscanf
reads from the stream indicated by its first argument:
scanf("%d%d", &i, &j);
/* reads from stdin */
fscanf(fp, "%d%d", &i, &j);
/* reads from fp */
– A call of scanf is equivalent to a call of fscanf with
stdin as the first argument.

32
22.3 Formatted I/O
• The …scanf Functions
– Errors that cause the …scanf functions to return
prematurely:
• Input failure (no more input characters could be read)
• Matching failure (the input characters didn’t match the
format string)

33
22.3 Formatted I/O
• The …scanf Functions
– The …scanf functions return the number of data
items that were read and assigned to objects.
– They return EOF if an input failure occurs before any
data items can be read.
– Loops that test scanf’s return value are common.
– A loop that reads a series of integers one by one,
stopping at the first sign of trouble:
while (scanf("%d", &i) == 1) {

}

34
22.3 Formatted I/O
• Detecting End-of-File and Error Conditions
– If we ask a …scanf function to read and store n data
items, we expect its return value to be n.
– If the return value is less than n, something went
wrong:
• End-of-file. The function encountered end-of-file before
matching the format string completely.
• Read error. The function was unable to read characters
from the stream.
• Matching failure. A data item was in the wrong format.

35
22.3 Formatted I/O
• Detecting End-of-File and Error Conditions
– Every stream has two indicators associated with it:
an error indicator and an end-of-file indicator.
– These indicators are cleared when the stream is
opened.
– Encountering end-of-file sets the end-of-file
indicator, and a read error sets the error indicator.
• The error indicator is also set when a write error
occurs on an output stream.
– A matching failure doesn’t change either indicator.

36
22.3 Formatted I/O
• Detecting End-of-File and Error Conditions
– Once the error or end-of-file indicator is set, it
remains in that state until it’s explicitly cleared,
perhaps by a call of the clearerr function.
– clearerr clears both the end-of-file and error
indicators:
clearerr(fp);
/*clears eof and error indicators for fp */
– clearerr isn’t needed often, since some of the
other library functions clear one or both indicators as
a side effect.

37
22.3 Formatted I/O
• Detecting End-of-File and Error Conditions
– The feof and ferror functions can be used to test
a stream’s indicators to determine why a prior
operation on the stream failed.
– The call feof(fp) returns a nonzero value if the
end-of-file indicator is set for the stream associated
with fp.
– The call ferror(fp) returns a nonzero value if the
error indicator is set.

38
22.3 Formatted I/O
• Detecting End-of-File and Error Conditions
– When scanf returns a smaller-than-expected value,
feof and ferror can be used to determine the
reason.
• If feof returns a nonzero value, the end of the input
file has been reached.
• If ferror returns a nonzero value, a read error
occurred during input.
• If neither returns a nonzero value, a matching failure
must have occurred.
– The return value of scanf indicates how many data
items were read before the problem occurred.

39
22.3 Formatted I/O
• Detecting End-of-File and Error Conditions
– The find_int function is an example that shows
how feof and ferror might be used.
– find_int searches a file for a line that begins with
an integer:
n = find_int("foo");
– find_int returns the value of the integer that it
finds or an error code:
–1 File can’t be opened
–2 Read error
–3 No line begins with an integer

40
int find_int(const char *filename)
{
FILE *fp = fopen(filename, "r");
int n;

if (fp == NULL)
return -1; /* can't open file */
while (fscanf(fp, "%d", &n) != 1) {
if (ferror(fp)) {
fclose(fp);
return -2; /* read error */
}
if (feof(fp)) {
fclose(fp);
return -3; /* integer not found */
}
fscanf(fp, "%*[^\n]"); /* skips rest of line */
}

fclose(fp);
return n;
}
41
22.4 Character I/O
• The next group of library functions can read and
write single characters.
• These functions work equally well with text streams
and binary streams.
• The functions treat characters as values of type int,
not char.
• One reason is that the input functions indicate an
end-of-file (or error) condition by returning EOF,
which is a negative integer constant.

42
22.4 Character I/O
• Output Functions
– putchar writes one character to the stdout
stream:
putchar(ch); /* writes ch to stdout */
– fputc writes a character to an arbitrary stream:
fputc(ch, fp); /* writes ch to fp */

43
22.4 Character I/O
• Input Functions
– getchar reads a character from stdin:
ch = getchar();
– fgetc reads a character from an arbitrary stream:
ch = fgetc(fp);
– All functions treat the character as an unsigned
char value (which is then converted to int type
before it’s returned).
– As a result, they never return a negative value other
than EOF.

44
22.4 Character I/O
• Input Functions
– The fgetc and getchar functions behave the same
if a problem occurs.
– At end-of-file, they set the stream’s end-of-file
indicator and return EOF.
– If a read error occurs, they set the stream’s error
indicator and return EOF.
– To differentiate between the two situations, we can
call either feof or ferror.

45
22.4 Character I/O
• Input Functions
– One of the most common uses of fgetc and
getchar is to read characters from a file.
– A typical while loop for that purpose:
while ((ch = fgetc(fp)) != EOF) {

}
– Always store the return value in an int variable, not
a char variable.
– Testing a char variable against EOF may give the
wrong result.

46
22.4 Character I/O
• Input Functions
– The ungetc function “pushes back” a character read
from a stream and clears the stream’s end-of-file
indicator.
– A loop that reads a series of digits, stopping at the
first nondigit:
while (isdigit(ch = fgetc(fp))) {

}
ungetc(ch, fp);
/* pushes back last character read */

47
22.4 Character I/O
• Input Functions
– The number of characters that can be pushed back by
consecutive calls of ungetc varies; only the first call
is guaranteed to succeed.
– Calling a file-positioning function (fseek, fsetpos,
or rewind) causes the pushed-back characters to be
lost.
– ungetc returns the character it was asked to push
back.
• It returns EOF if an attempt is made to push back EOF
or to push back more characters than allowed.

48
22.5 Line I/O
• Library functions in the next group are able to
read and write lines.
• These functions are used mostly with text
streams, although it’s legal to use them with
binary streams as well.

49
22.5 Line I/O
• Output Functions
– The puts function writes a string of characters to stdout:
puts("Hi, there!");/* writes to stdout*/
– After it writes the characters in the string, puts always adds
a new-line character.
– fputs is a more general version of puts.
– Its second argument indicates the stream to which the
output should be written:
fputs("Hi, there!", fp);/*writes to fp*/
– Unlike puts, the fputs function doesn’t write a new-line
character unless one is present in the string.
– Both functions return EOF if a write error occurs; otherwise,
they return a nonnegative number.
50
22.5 Line I/O
• Input Functions
– The gets function reads a line of input from stdin:
gets(str); /* reads a line from stdin
*/
– gets reads characters one by one, storing them in
the array pointed to by str, until it reads a new-line
character (which it discards).
– fgets is a more general version of gets that can
read from any stream.
– fgets is also safer than gets, since it limits the
number of characters that it will store.

51
22.5 Line I/O
• Input Functions
– Both gets and fgets return a null pointer if a read
error occurs or they reach the end of the input stream
before storing any characters.
– Otherwise, both return their first argument, which
points to the array in which the input was stored.
– Both functions store a null character at the end of the
string.

52
22.6 Block I/O

• The fread and fwrite functions allow a program


to read and write large blocks of data in a single step.
• fread and fwrite are used primarily with binary
streams, although—with care—it’s possible to use
them with text streams as well.

53
22.6 Block I/O
• fwrite is designed to copy an array from memory to a stream.
• Arguments in a call of fwrite:
– Address of array
– Size of each array element (in bytes)
– Number of elements to write
– File pointer
• A call of fwrite that writes the entire contents of the array a:
fwrite(a, sizeof(a[0]),
sizeof(a) / sizeof(a[0]), fp);
• fwrite returns the number of elements actually written.
• This number will be less than the third argument if a write error
occurs.

54
22.6 Block I/O
• fread will read the elements of an array from a
stream.
• A call of fread that reads the contents of a file into
the array a:
n = fread(a, sizeof(a[0]),
sizeof(a) / sizeof(a[0]), fp);
• fread’s return value indicates the actual number of
elements read.
• This number should equal the third argument unless
the end of the input file was reached or a read error
occurred.

55
22.6 Block I/O
• fwrite is convenient for a program that needs to
store data in a file before terminating.
• Later, the program (or another program) can use
fread to read the data back into memory.
• The data doesn’t need to be in array form.
• A call of fwrite that writes a structure variable s
to a file:
fwrite(&s, sizeof(s), 1, fp);

56
22.7 File Positioning
• Every stream has an associated file position.
• When a file is opened, the file position is set at the
beginning of the file.
– In “append” mode, the initial file position may be
at the beginning or end, depending on the
implementation.
• When a read or write operation is performed, the file
position advances automatically, providing sequential
access to data.

57
22.7 File Positioning
• Although sequential access is fine for many
applications, some programs need the ability to jump
around within a file.
• If a file contains a series of records, we might want to
jump directly to a particular record.
• <stdio.h> provides five functions that allow a
program to determine the current file position or to
change it.

58
22.7 File Positioning
• The fseek function changes the file position
associated with the first argument (a file pointer).
• The third argument is one of three macros:
SEEK_SET Beginning of file
SEEK_CUR Current file position
SEEK_END End of file
• The second argument, which has type long
int, is a (possibly negative) byte count.

59
22.7 File Positioning
• Using fseek to move to the beginning of a file:
fseek(fp, 0L, SEEK_SET);
• Using fseek to move to the end of a file:
fseek(fp, 0L, SEEK_END);
• Using fseek to move back 10 bytes:
fseek(fp, -10L, SEEK_CUR);
• If an error occurs (the requested position doesn’t
exist, for example), fseek returns a nonzero value.

60
22.7 File Positioning
• The file-positioning functions are best used with
binary streams.
• C doesn’t prohibit programs from using them with
text streams, but certain restrictions apply.
• For text streams, fseek can be used only to move
to the beginning or end of a text stream or to
return to a place that was visited previously.
• For binary streams, fseek isn’t required to
support calls in which the third argument is
SEEK_END.

61
22.7 File Positioning
• The ftell function returns the current file
position as a long integer.
• The value returned by ftell may be saved and
later supplied to a call of fseek:
long file_pos;

file_pos = ftell(fp);
/* saves current position */

fseek(fp, file_pos, SEEK_SET);
/* returns to old position */

62
22.7 File Positioning
• If fp is a binary stream, the call ftell(fp)
returns the current file position as a byte count,
where zero represents the beginning of the file.
• If fp is a text stream, ftell(fp) isn’t necessarily
a byte count.
• As a result, it’s best not to perform arithmetic on
values returned by ftell.

63
22.7 File Positioning
• The rewind function sets the file position at
the beginning.
• The call rewind(fp) is nearly equivalent to
fseek(fp, 0L, SEEK_SET).
– The difference? rewind doesn’t return a value
but does clear the error indicator for fp.

64
22.7 File Positioning
• fseek and ftell are limited to files whose
positions can be stored in a long integer.
• For working with very large files, C provides two
additional functions: fgetpos and fsetpos.
• These functions can handle large files because they
use values of type fpos_t to represent file
positions.
– An fpos_t value isn’t necessarily an integer; it
could be a structure, for instance.

65
22.7 File Positioning
• The call fgetpos(fp, &file_pos) stores the
file position associated with fp in the file_pos
variable.
• The call fsetpos(fp, &file_pos) sets the file
position for fp to be the value stored in file_pos.
• If a call of fgetpos or fsetpos fails, it stores an
error code in errno.
• Both functions return zero when they succeed and a
nonzero value when they fail.

66
22.7 File Positioning
• An example that uses fgetpos and fsetpos to
save a file position and return to it later:
fpos_t file_pos;

fgetpos(fp, &file_pos);
/* saves current position */

fsetpos(fp, &file_pos);
/* returns to old position */

67
22.7 File Positioning
• Program: Modifying a File of Part Records
– Actions performed by the invclear.c
program:
• Opens a binary file containing part structures.
• Reads the structures into an array.
• Sets the on_hand member of each structure to 0.
• Writes the structures back to the file.
– The program opens the file in "rb+" mode,
allowing both reading and writing.

68
invclear.c
/* Modifies a file of part records by setting the
quantity on hand to zero for all records */

#include <stdio.h>
#include <stdlib.h>

#define NAME_LEN 25
#define MAX_PARTS 100

struct part {
int number;
char name[NAME_LEN+1];
int on_hand;
} inventory[MAX_PARTS];

int num_parts;
69
int main(void)
{ FILE *fp;
int i;

if ((fp = fopen("inventory.dat", "rb+")) == NULL) {


fprintf(stderr, "Can't open inventory file\n");
exit(EXIT_FAILURE);
}

num_parts = fread(inventory, sizeof(struct part),


MAX_PARTS, fp);

for (i = 0; i < num_parts; i++)


inventory[i].on_hand = 0;

rewind(fp);
fwrite(inventory, sizeof(struct part), num_parts,
fp);
fclose(fp);

return 0;
}
70
The End

71

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy