D.1 - Hochschule Ravensburg

Transcription

D.1 - Hochschule Ravensburg
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
Contents
D
C-BASED INPUT/OUTPUT..........................................................................................................................D-2
D.1
THE C I/O-SYSTEM ..................................................................................................................................D-2
D.2
C I/0 USES STREAMS ...............................................................................................................................D-3
D.2.1 Streams................................................................................................................................................D-4
D.2.2 Text Streams and Binary Streams......................................................................................................D-5
D.3
UNDERSTANDING PRINTF( ) AND SCANF( )..............................................................................................D-6
D.3.1 printf( )................................................................................................................................................D-6
D.3.1.1
Printf Control String and Conversion Specifiers......................................................................................D-9
D.3.1.1.1
Modifier Tables.................................................................................................................................D-10
D.3.1.1.2
Flags...................................................................................................................................................D-10
D.3.1.1.3
Conversions .......................................................................................................................................D-11
D.3.1.2
Example of printf() usage........................................................................................................................D-12
D.3.2
scanf( ) ..............................................................................................................................................D-13
D.3.2.1
Scanf Control String and Conversion Specifiers....................................................................................D-17
D.3.2.2
Length Modifiers And Conversion Specifiers For Formatted Input Functions....................................D-17
D.3.2.2.1
Length Specifiers ..............................................................................................................................D-17
D.3.2.2.2
Conversion Specifiers .......................................................................................................................D-18
D.3.2.2.3
Scanset ...............................................................................................................................................D-18
D.3.2.3
Example of scanf() usage ........................................................................................................................D-20
D.4
THE C FILE SYSTEM...............................................................................................................................D-21
D.4.1 fopen( )..............................................................................................................................................D-22
D.4.1.1
D.4.2
Example of fopen() usage .......................................................................................................................D-24
fputc( )...............................................................................................................................................D-25
D.4.2.1
D.4.3
Example of fputc() usage ........................................................................................................................D-25
fgetc( ) ...............................................................................................................................................D-26
D.4.3.1
D.4.4
Example of fgetc() usage.........................................................................................................................D-26
feof( ).................................................................................................................................................D-27
D.4.4.1
D.4.5
Example of feof() usage ..........................................................................................................................D-27
fclose( ) .............................................................................................................................................D-28
D.4.5.1
D.4.6
Example of fclose() usage.......................................................................................................................D-28
ferror( ) and rewind( ) ......................................................................................................................D-29
D.4.6.1
D.4.6.2
D.4.7
Example of ferror() usage. ......................................................................................................................D-29
Example of rewind() usage .....................................................................................................................D-30
fread( ) and fwrite( ).........................................................................................................................D-31
D.4.7.1
D.4.8
The use of fwrite() and fread()................................................................................................................D-32
fseek( ) and Random-Access I/O......................................................................................................D-33
D.4.8.1
D.4.9
Example of fseek() usage ........................................................................................................................D-34
fprintf( ) and fscanf( ) .......................................................................................................................D-35
D.4.9.1
D.4.9.2
D.4.10
Example of fprintf() usage ......................................................................................................................D-35
Example of fscanf() usage.......................................................................................................................D-36
fflush()..........................................................................................................................................D-37
D.4.10.1
Example of fflush() usage .......................................................................................................................D-38
D.5
ERASING FILES .......................................................................................................................................D-39
D.6
MORE EXAMPLES TO C-BASED I/O .......................................................................................................D-40
D.6.1 The use of EOF during keyboard input ...........................................................................................D-40
DPM_C_I/O.doc
Page D-1 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D C-Based Input/Output
D.1 The C I/O-System
This appendix presents a brief overview of the C I/O system. Even though you will
normally use the C++ I/O system, there are several reasons why you may need to
understand the fundamentals of C-based I/O. First, if you will be working on C code
(especially if you are converting it to C++), then you will need to understand how
the C I/O system works. Second, it is common to find both C and C++ I/O within the same
program. This is true especially when the program is very large and has been written by
multiple programmers over a long period of time. Third, a great number of existing C
programs continue to be used and maintained. Finally, many books and periodicals contain
programs written in C. To understand these programs, you need to understand the basics of the
C l/O system.
For C++ programs, you should use the C++ object oriented I/O system.
This appendix covers the most commonly used C-based I/O functions. However, the C
standard library contains a very rich and diverse assortment of I/O functions-more than can be
covered here. If you will be doing extensive work in C, you will want to explore its I/O
system in detail.
The C-based I/O system requires either the header file stdio.h or the new-style header
<cstdio>. A C program must use the stdio.h since C does not support C++-style headers. A
C++ program uses either one. The header <cstdio> puts its contents into the std namespace.
The header file stdio.h puts its contents into the global namespace, which is in keeping with
C. The examples in this appendix are C programs, so they use the C-style header stdio.h, and
no namespace statement is required.
C-Based I/O
command line
arguments
int main (int argc, char **argv)
fpr
printf, putchar, puts
stdin / stdout
stderr
scanf, getchar, gets
Application
-program
(-software)
i
tc
, pu
ntf
, ge
anf
fsc
tc,
text file
ts
fge
fopen, fclose, fgetpos
fsetpos, ftell, fseek
fre
sscanf
uts
, fp
fw
rit
e
ad
sprintf
physical records
String
(r.siol) 09.01.2007
DPM_C_I/O.doc
Hochschule Ravensburg-Weingarten
Technik | Wirtschaft | Sozialwesen
Page D-2 of 40
106
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
The C language standard was updated in 1999, resulting in the C99 standard for C. At
that time, a few enhancements were made to the C I/O system. However, because C++ is built
on C89, it does not support any features added by C99. (Furthermore, at the time of this
writing, no widely available compiler supports C99, nor is there any widely distributed code
that uses the C99 features.) Thus, none of the features added to the C I/O system by C99 are
described here. If you are interested in the C language, including a complete description of its
I/O system and those features added by the C99 standard, I recommend my1 book C: The
Complete Reference, 4th edition, McGraw-Hill/Osborne.
D.2 C I/0 Uses Streams
Like the C++ I/O system, the C-based I/O system operates on streams. At the beginning
of a program's execution, three predefined text streams are opened. They are stdin, stdout,
and stderr. (Some compilers also open other, implementation-dependent streams.) These
streams are the C versions of cin, cout, and cerr, respectively. They each refer to a standard
I/O device connected to the system, as shown here:
Stream
stdin
stdout
stderr
Device
keyboard
screen
screen
Remember that most operating systems, including Windows, allow I/O redirection, so
functions that read or write to these streams may be redirected to other devices. You should
never try to explicitly open or close these streams.
Each stream that is associated with a file has a file control structure of type FILE.
This structure is defined in stdio.h. You must not make modifications to this file control
block.
1
Herbert Schildt
DPM_C_I/O.doc
Page D-3 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.2.1 Streams2
A stream is a logical abstraction that isolates input and output operations from the
physical characteristics of terminals and structured storage devices. They provide a mapping
between a program’s data and the data as actually stored on the external devices. Two forms
of mapping are supported, for text streams and for binary streams.
Streams also provide buffering, which is an abstraction of a file designed to reduce
hardware I/O requests.Without buffering, data on an I/O device must be accessed one item at
a time. This inefficient I/O processing slows program execution considerably. The stdio.h
functions use buffers in primary storage to intercept and collect data as it is written to or read
from a file. When a buffer is full its contents are actually written to or read from the file,
thereby reducing the number of I/O accesses. A buffer's contents can be sent to the file
prematurely by using the fflush() function.
The stdio.h header offers three buffering schemes:
o unbuffered
o block buffered
o line buffered.
The setvbuf() function is used to change the buffering scheme of any output stream.
When an output stream is unbuffered, data sent to it are immediately read from or
written to the file.
When an output stream is block buffered, data are accumulated in a buffer in primary
storage. When full, the buffer's contents are sent to the destination file, the buffer is cleared,
and the process is repeated until the stream is closed. Output streams are block
buffered by default if the output refers to a file.
A line buffered output stream operates similarly to a block buffered output stream.
Data are collected in the buffer, but are sent to the file when the line is completed with a
newline character ('\n').
A stream is declared using a pointer to a FILE. There are three FILE
pointers that are automatically opened for a program:
o FILE *stdin
o FILE *stdout
o FILE *stderr
The FILE pointers stdin and stdout are the standard input and output files, respectively, for
interactive console I/O. The stderr file pointer is the standard error output file, where error
messages are written to. The stderr stream is written to the console. The stdin and stdout
streams are line buffered while the stderr stream is unbuffered.
2
Metroworks Corporation; some parts out of the documentation.
DPM_C_I/O.doc
Page D-4 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.2.2 Text Streams and Binary Streams
In a binary stream, there is no transformation of the characters during input or output
and what is recorded on the physical device is identical to the program’s internal data
representation.
A text stream consists of sequences of characters organized into lines, each line
terminated by a new-line character. To conform to the host system’s convention for
representing text on physical devices, characters may have to be added altered or deleted
during input and output. Thus, there may not be a one-to-one correspondence between the
characters in a stream and those in the external representation. These changes occur
automatically as part of the mapping associated with text streams. Of course, the input
mapping is the inverse of the output mapping and data that are output and then input through
text streams will compare equal with the original data.
In MSL3, the text stream mapping affects only the linefeed (LF) character, ‘\n’ and the
carriage return (CR) character, ‘\r’. The semantics of these two control characters are:
\n Moves the current print location to the start of the next line.
\r Moves the current print location to the start of the current line.
where “current print location “is defined as “that location on a display device where the next
character output by the fputc function would appear”.
The ASCII character set defines the value of LF as 0x0a and CR as 0x0d and these are
the values that these characters have when they are part of a program's data. On physical
devices in the Macintosh operating system, newline characters are represented by 0x0d and
CR as 0x0a; in other words, the values are interchanged. To meet this requirement, the MSL
C library for the Mac, interchanges these values while writing a file and again while reading
so that a text stream will be unchanged by writing to a file and then reading back. MPW chose
0x0a for the newline character in its text file, so, when the MPW switch is on, this interchange
of values does not take place. However, if you use this option, you must use the MSL C and
C++ libraries that were compiled with this option on.
These versions of the libraries are marked with an N (on 68k) or NL (on PPC), for
example ANSI (N/2i) C.68k.Lib or ANSI (NL) C.PPC.Lib. See the notes on the
mpwc_newline pragma in the CodeWarrior C Compilers Reference.
On Windows, the situation is different. There, lines are terminated with the character
pair CR/LF. As a consequence, in the Windows implementation of MSL, when a text stream
is written to a file, a single newline character is converted to the character pair CR/LF
and the reverse transformation is made during reading.
The library routines that read a file have no means of determining the mode in which
text files were written and thus some assumptions have to be made. On the Mac, it is assumed
that the Mac convention is used. Under MPW, it is assumed that the MPW convention is to be
used and on Windows, the DOS convention.
3
MSL – Metroworks Standard Library
DPM_C_I/O.doc
Page D-5 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3 Understanding printf( ) and scanf( )
The two most commonly used C-based I/O functions are printf() and scanf(). The
printf( ) function writes data to the console; scanf( ), its complement, reads data from the
keyboard. Because the C language does not support operator overloading, or the use of <<
and >> as I/O operators, it relies on printf( ) and scanf( ) for console I/O. Both printf( ) and
scanf( ) can operate on any of the built-in data types, including characters, strings, and
numbers. However, since these functions are not object-oriented, they cannot operate directly
upon class types that you create.
D.3.1 printf( )
The printf( ) function has this prototype:
int printf(const char *fmt_string, ... );
The first argument, fmt_string, defines the way any subsequent arguments are
displayed. This argument is often called the format string. It contains two things: text and
format specifiers. Text is printed on the screen and has no other effect. The format specifiers
define the way arguments that follow the format string are displayed. A format specifier
begins with a percent sign, and is followed by the format code. The format specifiers are
shown in Format Table. There must be exactly the same number of arguments as there are
format specifiers, and the format specifiers and the arguments are matched in order.
Text and format specifiers in printf
The printf() function has the prototype:
int printf (const char * format, … );
%[Flag][Width][.Precision][Length modifier]Conversion Specifier
%[F][W][P][L]C
%
F
W
P
L
C
=
=
=
=
=
=
A percent sign
[Flag]
[Width]
[Precision]
[Length modifier]
Conversion Specifier
-, +, 0, # or space
decimal digit string
. or .* or . decimal digit string
h, l, hh, ll, j, z or t
c,d,e,E,f,F,g,G,i,n,o,p,s,u,x,X or %
Options are shown in [].
(r.siol) 17.01.2007
Hochschule Ravensburg-Weingarten
Technik | Wirtschaft | Sozialwesen
111
For example, this printf( ) call, printf("Hi %c %d %s", 'c', 10, "there!");
displays: Hi c 10 there!.
The printf( ) function returns the number of characters output. It returns a negative
value if an error occurs.
DPM_C_I/O.doc
Page D-6 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
The format specifiers
The format specifiers may have modifiers that specify the field width, the number of
decimal places, and a left-justification flag. An integer placed between the % sign and the
format specifier acts as a minimum-field-width specifier.
Code
%c
%d
%i
%e
%E
%f
%g
%G
%o
%s
%u
%x
%X
%p
%n
%%
Format
Character
Signed decimal integers
Signed decimal integers
Scientific notation (lowercase e)
Scientific notation (uppercase E)
Decimal floating point
Uses %e or %f, whichever is shorter
Uses %E or %F, whichever is shorter
Unsigned octal
String of characters
Unsigned decimal integers
Unsigned hexadecimal (lowercase letters)
Unsigned hexadecimal (uppercase letters)
Displays a pointer
The associated argument is a pointer to an integer
into which the number of characters written so far is placed
Displays a % sign
This pads the output with spaces to ensure that it is at least a certain minimum length.
If the string or number is greater than that minimum, it will be printed in full, even if it
overruns the minimum. If you want to pad with 0s, place a 0 before the field-width specifier.
For example, %05d will pad a number of less than five digits with 0s so that its total length is
five.
To specify the number of decimal places printed for a floating-point number, place
a decimal point after the field-width specifier, followed by the number of decimal places you
want to display. For example, %10.4f will display a number at least ten characters wide, with
four decimal places. When this is applied to strings or integers, the number following the
period specifies the maximum field length. Far example, %5.7s will display a string that is at
least five characters long, but that does not exceed seven characters. lf the string is longer than
the maximum field width, the characters will be truncated from the end.
By default, all output is right-justified: If the field width is larger than the data printed,
the data will be placed on the right edge of the field. You can force the information to be leftjustified by placing a minus sign directly after the %. For example, %-10.2f will left-justify a
floating-point number, with two decimal places in a ten-character field.
DPM_C_I/O.doc
Page D-7 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
Here is a program that demonstrates field-width specifiers and left-justification:
#include <stdio.h>
int main()
{
printf("|%10.5f|\n", 123.23);
printf("|%-10.5f|\n", 123.23);
printf("|%10.5s|\n", "Hello there");
printf("|%-10.5s|\n", "Hello there");
return 0;
}
This program displays the following output:
| 123.23000|
|123.23000 |
| Hello|
|Hello |
There are two format specifier modifiers that allow printf( ) to display short and long
integers. These modifiers can be applied to the d, i, o, u and x type specifiers. The l (ell)
modifier tells printf( ) that a long data type follows. For example, %ld means that a long int
is to be displayed. The h modifier instructs printf( ) to display a short int. Therefore, %hu
indicates that the data is of the short, unsigned integer type.
The l and h modifiers can also be applied to the n specifier, to indicate that the
corresponding argument is a pointer to a long or short integer, respectively.
If your compiler fully complies with Standard C++, then you can use the l modifier
with the c format to indicate a wide character. You can also use the l modifier with the s
format to indicate a wide-character string.
The L modifier can prefix the floating-point specifiers e, f and g. In this context, it
indicates that a long double follows.
DPM_C_I/O.doc
Page D-8 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.1.1 Printf Control String and Conversion Specifiers
The format character array contains normal text and conversion specifications.
Conversion specifications must have matching arguments in the same order in which they
occur in format.
The various elements of the format string is specified in the ANSI standards to be in
this order from left to right.
o
o
o
o
o
o
Apercent sign
Optional flags -,+,0,# or space
Optional minimum field width specification
Optional precision specification
Optional size specification
Conversion specifier c,d,e,E,f,F,g,G,i,n,o,p,s,u,x,X or %
A conversion specification describes the format its associated argument is to be
converted to. A specification starts with a percent sign (%), optional flag characters, an
optional minimum width, an optional precision width, and the necessary, terminating
conversion type. Doubling the percent sign (%%) results in the output of a single
%.
An optional flag character modifies the formatting of the output; it can be left or right
justified, and numerical values can be padded with zeroes or output in alternate forms. More
than one optional flag character can be used in a conversion specification. “Length Modifiers
And Conversion Specifiers For Formatted Output Functions” see following tables, describes
the flag characters.
The optional minimum width is a decimal digit string. If the converted value has more
characters that the minimum width, it is expanded as required. If the converted value has
fewer characters than the minimum width, it is, by default, right justified (padded on the left).
If the - flag character is used, the converted value is left justified (padded on the right).
NOTE The maximum minimum field width allowed in MSL Standard Libraries is 509
characters.
The optional precision width is a period character (.) followed by decimal digit string.
For floating point values, the precision width specifies the number of digits to print after the
decimal point. For integer values, the precision width functions identically to, and cancels, the
minimum width specification. When used with a character array, the precision width indicates
the maximum width of the output.
A minimum width and a precision width can also be specified with an asterisk (*)
instead of a decimal digit string. An asterisk indicates that there is a matching argument,
preceding the conversion argument, specifying the minimum width or precision width.
The terminating character, the conversion type, specifies the conversion applied to the
conversion specification's matching argument “Length Modifiers And Conversion Specifiers
For Formatted Output Functions” see following tables, describes the conversion type
characters.
DPM_C_I/O.doc
Page D-9 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.1.1.1 Modifier Tables
Length Modifiers And Conversion Specifiers For Formatted Output Functions
Modifier Description
Size
The h flag followed by d, i, o, u, x, or X conversion specifier indicates
h
that the corresponding argument is a short int or unsigned short int.
l
ll
L
The lower case L followed by d, i, o, u, x, or X conversion specifier
indicates the argument is a long int or unsigned long int.
The lower case L followed by a c conversion specifier, indicates that
the argument is of type wint_t.
The lower case L followed by an s conversion specifier, indicates that
the argument is of type wchar_t.
The double l followed by d, i, o, u, x, or X conversion specifier
indicates the argument is a long long or unsigned long long
The upper case L followed by e, E, f, g, or G conversion specifier
indicates a long double.
D.3.1.1.2 Flags
Modifier Description
Flags
+
space
#
0
The conversion will be left justified.
The conversion, if numeric, will be prefixed with a sign
(+ or -). By default, only negative numeric values are prefixed with a
minus sign (-).
If the first character of the conversion is not a sign character, it is
prefixed with a space. Because the plus sign flag character (+) always
prefixes a numeric value with a sign, the space flag has no effect
when combined with the plus flag.
For c, d, i, and u conversion types, the # flag has no effect. For s
conversion types, a pointer to a Pascal string, is output as a character
string. For o conversion types, the # flag prefixes the conversion with
a 0. For x conversion types with this flag, the conversion is prefixed
with a 0x. For e, E, f, g, and G conversions, the # flag forces a
decimal point in the output. For g and G conversions with this flag,
trailing zeroes after the decimal point are not removed.
This flag pads zeroes on the left of the conversion. It applies to d, i, o,
u, x, X, e, E, f, g, and G conversion types. The leading zeroes follow
sign and base indication characters, replacing what would normally be
space characters. The minus sign flag character overrides the 0 flag
character. The 0 flag is ignored when used with a precision width for
d, i , o, u, x, and X conversion types.
DPM_C_I/O.doc
Page D-10 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.1.1.3 Conversions
Modifier Description
Conversions
d
i
o
u
x, X
n
f, F
e, E
g, G
c
s
p
#s
The corresponding argument is converted to a signed decimal.
The corresponding argument is converted to a signed decimal.
The argument is converted to an unsigned octal.
The argument is converted to an unsigned decimal.
The argument is converted to an unsigned hexadecimal. The x
conversion type uses lowercase letters (abcdef) while X uses
uppercase letters (ABCDEF).
This conversion type stores the number of items output by printf() so
far. Its corresponding argument must be a pointer to an int.
The corresponding floating point argument (float, or double) is
printed in decimal notation. The default precision is 6 (6 digits after
the decimal point). If the precision width is explicitly 0, the decimal
point is not printed.
For the f conversion specifier, a double argument representing infinity
produces [-]inf; a double argument representing a NaN (Not a
number) produces [-]nan.
For the F conversion specifier, [-]INF or [-]NAN are produced
instead.
The floating point argument (float or double) is output in scientific
notation: [-]b.aaae±Eee. There is one digit (b) before the decimal
point. Unless indicated by an optional precision width, the default is 6
digits after the decimal point (aaa).
If the precision width is 0, no decimal point is output. The exponent
(ee) is at least 2 digits long.
The e conversion type uses lowercase e as the exponent prefix. The E
conversion type uses uppercase E as the exponent prefix.
The g conversion type uses the f or e conversion types and the G
conversion type uses the F or E conversion types. Conversion type e
(or E) is used only if the converted exponent is less than -4 or
greater than the precision width. The precision width indicates the
number of significant digits. No decimal point is output if there are no
digits following it.
The corresponding argument is output as a character.
The corresponding argument, a pointer to a character array, is output
as a character string. Character string output is completed when a null
character is reached. The null character is not output.
The corresponding argument is taken to be a pointer.
The argument is output using the X conversion type format.
The corresponding argument, a pointer to a Pascal string, is output as
a character string. A Pascal character string is a length byte followed
by the number characters specified in the length byte.
Note: This conversion type is an extension to the ANSI C library but
applied in the same manner as for other format variations.
DPM_C_I/O.doc
Page D-11 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.1.2 Example of printf() usage
#include <stdio.h>
int main(void)
{
int i = 25;
char c = 'M';
short int d = 'm';
static char s[] = "Metrowerks!";
static char pas[] = "\pMetrowerks again!";
float f = 49.95;
double x = 1038.11005;
int count;
printf("%s printf() demonstration:\n%n", s, &count);
printf("The last line contained %d characters\n",count);
printf("Pascal string output: %#20s\n", pas);
printf("%-4d %x %06x %-5o\n", i, i, i, i);
printf("%*d\n", 5, i);
printf("%4c %4u %4.10d\n", c, c, c);
printf("%4c %4hu %3.10hd\n", d, d, d);
printf("$%5.2f\n", f);
printf("%5.2f\n%6.3f\n%7.4f\n", x, x, x);
printf("%*.*f\n", 8, 5, x);
return 0;
}
The output is:
Metrowerks! printf() demonstration:
The last line contained 36 characters
Pascal string output:
Metrowerks again!
25
19 000019 31
25
M
77 0000000077
m 109 0000000109
$49.95
1038.11
1038.110
1038.1101
1038.11005
DPM_C_I/O.doc
Page D-12 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.2 scanf( )
C's general-purpose console input function is scanf( ). It can read all the built-in data
types and automatically convert numbers into the proper internal format. It is much like the
reverse of printf( ). The general form of scanf( ) is
int scanf(const char *fmt_string, ... );
The format string consists of three classifications of characters:
o Format specifiers
o Whitespace characters
o Non-whitespace characters
The scanf( ) function returns the number of fields that are input. It returns EOF
(defined in stdio.h) if an error occurs.
Text and format specifiers in scanf
The scanf() function has the prototype:
int scanf (const char * format, … );
%[*][Width] [Length modifier] Conversion specifier
%[S][W][L]C
%
S
W
=
=
=
L
C
=
=
A percent sign
[*]
skip the argument.
[Width]
maximum field length monifier; a whitespace character in the contral string
causes scanf( ) to skip over one or more whitespace characters in the input stream.
[Length]
length specifiers: h, l, hh or ll
Conversion specifier
Options are shown in []
(r.siol) 17.01.2007
Hochschule Ravensburg-Weingarten
Technik | Wirtschaft | Sozialwesen
113
The input format specifiers are preceded by a % sign. They tell scanf( ) what type of
data is to be read next. For example, %s reads a string, while %d reads an integer. These
codes are listed in the Meaning Table below.
A whitespace character in the contral string causes scanf( ) to skip over one or more
whitespace characters in the input stream. A whitespace character is either a space, a tab, or a
newline. In essence, one whitespace character in the contral string will cause scanf( ) to read,
but not store, any number (including zero) of whitespace characters up to the first nonwhitespace character.
A non-whitespace character causes scanf( ) to read and discard a matching character.
For example, "%d, %d" causes scanf( ) to first read an integer, then read and discard a
comma, and finally read another integer. If the specified character is not found, scanf( ) will
terminate.
DPM_C_I/O.doc
Page D-13 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Code
%c
%d
%i
%e
%f
%g
%o
%s
%x
%p
%n
%u
%[ ]
%%
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
Meaning
Read a single character
Read a decimal integer
Read an integer in either decimal, octal, or hexadecimal format.
Read a floating-point number
Read a floating-point number
Read a floating-point number
Read an octal number
Read astring
Read a hexadecimal number
Read a pointer
Receives an integer value equal to the number of characters read so far
Read an unsigned decimal integer
Scan for a set of characters
Read a percent sign
All the variables used to receive values through scanf( ) must be passed by their
addresses. This means that all arguments must be pointers to the variables used as arguments.
(C does not support references or the reference parameter.) Passing pointers allows scanf( ) to
alter the contents of an argument. For example, if you want to read an integer into the variable
count, use the following scanf( ) call:
scanf ( "%d", &count);
Strings will be read into character arrays, and the array name, without any index, is the
address of the first element in an array. So, to read a string into the character array address,
you would use
char address[80];
scanf ( "%s", address);
In this case, address is already a pointer, and need not be preceded by the & operator.
The data items read by scanf( ) must be separated by spaces, tabs, or newlines. Punctuation
such as commas, semicolons, and the like do not count as separators.
This means that
scanf("%d%d", &r, &c);
will accept an input of 10 20, but will fail with 10,20. As in printf( ), the scanf( ) format
codes are matched, in order, with the variables receiving input in the argument list.
An * placed after the % and before the format code will read data of the specified type,
but will not assign it to any variable. Thus,
scanf("%d%*c%d", &x, &y);
when given the input 10/20, will place the value 10 into x, discard the division sign, and give
y the value 20.
DPM_C_I/O.doc
Page D-14 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
The format specifiers can specify a maximum-field-length modifier. This is an integer
number placed between the % and the format-specifier code that limits the number of
characters read for any field. For example, if you want to read no more than 20 characters into
str, then you would write
scanf("%20s", str);
If the input stream is greater than 20 characters, then a subsequent call to input begins
where this call leaves off. For example, if
ABCDEFGHIJKLMNOPQRSTUVWXYZ
is entered as the response to the scanf( ) call in this example, then only the first 20 characters,
or up to the 'T,' are placed into str, because of the maximum-size specifier. This means that
the remaining characters, "UVWXYZ," have not yet been used.
If another scanf( ) call is made, such as
scanf("%s", str);
then the characters "UVWXYZ" are placed into str. If a whitespace is encountered, input for
a field may terminate before the maximum field length is reached. In this case, scanf( ) will
move on to the next field.
Although spaces, tabs, and newlines are used as field separators, they are read like any
other characters when single characters are being read. For example, with an input stream of
"x y,"
scanf("%c%c%c", &a, &b, &c);
will return with the character 'x' in a, a space in b, and the character 'y' in c. Another feature of
scanf( ) is the scanset. A scanset defines a set of characters that will be matched by scanf( )
and stored in a character-array. The scanf( ) function continues to input characters as long as
they are members of the scanset. When a character is entered that does not match any in the
scanset, scanf( ) null-terminates the corresponding array and moves on to the next (if any)
field.
You define a scanset by putting a list of the characters you want to scan for inside
square brackets. The beginning square bracket must be prefixed by a percent sign. For
example, this scanset tells scanf( ) to read only the letters X, Y, and Z.
% [XYZ]
The argument corresponding to the scanset must be a pointer to a character array.
Upon return fram scanf( ), the array will contain a null-terminated string composed of the
characters read. For example, the following program uses a scanset to read digits into s1. As
soon as a non-digit is entered, s1 is null-terminated, and characters are read into s2 until the
next whitespace character is entered.
DPM_C_I/O.doc
Page D-15 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
/* A simple scanset example. */
#include <stdio.h>
int main()
{
char s1[80], s2[80];
printf("Enter numbers, then some letters\n");
scanf("%[0123456789]%s", s1, s2);
printf("%s %s", s1, s2);
return 0;
}
In most implementations, you can specify a range inside a scanset by using a hyphen.
For example, the foIlowing scanset tells scanf( ) to accept the characters A through Z:
% [A-Z]
You can specify more than one range within a scanset.
For example, this program reads digits and then letters:
/* A scanset example using ranges. */
#include <stdio.h>
int main()
{
char s1[80], s2[80];
printf("Enter numbers, then some letters\n");
scanf("%[0-9]%[a-zA-Z]", s1, s2);
printf("%s %s", s1, s2);
return 0;
}
You can specify an inverted set if the first character in the set is a ^. When the ^ is
present, it tells scanf( ) to accept any character that is not defined by the scanset. The
foIlowing modification of the preceding example uses the ^ to invert the type of characters the
scanset will read:
/* A scanset example using inverted ranges. */
#include <stdio.h>
int main()
{
char s1[80], s2[80];
printf("Enter non-numbers, then some non-letters\n");
scanf4("%[^0-9]%[^a-zA-Z]", s1, s2);
printf("%s %s", s1, s2);
return 0;
}
One important point to remember is that the scanset is case-sensitive. Therefore, if you
want to scan for both uppercase and lowercase letters, they must be specified individuaIly.
Several of the format specifiers can take modifiers which precisely specify the type of
variable that receives the data. To assign data to a long integer, put an l (ell) in front of the
format specifier. To assign data to a short integer, put an h in front of the format specifier.
These modifiers can be used with the d, i, o, u, x and n format codes.
By default, the f, e, and g specifiers tell scanf( ) to assign data to a float. If you put an l
(ell) in front of one of these specifiers, scanf( ) assigns the data to a double. Using an L tells
scanf( ) that the variable receiving the data is a long double.
4
Doesn’t run correctly !
DPM_C_I/O.doc
Page D-16 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
The l (ell) modifier can also be used with the c and s format codes as long as your
compiler fully complies with Standard C++. Preceding c with an l indicates a pointer to an
object of type wchar_t. Preceding s with an l indicates apointer to a wchar_t array. The l can
also be used to modify a scanset for use with wide characters.
D.3.2.1 Scanf Control String and Conversion Specifiers
The format argument is a character array containing normal text, white space (space,
tab, newline), and conversion specifications. The normal text specifies literal characters that
must be matched in the input stream. A white space character indicates that white space
characters are skipped until a non-white space character is reached. The conversion
specifications indicate what characters in the input stream are to be converted and stored.
The conversion specifications must have matching arguments in the order they appear
in format. Because scanf() stores data in memory, the matching conversion specification
arguments must be pointers to objects of the relevant types.
A conversion specification consists of the percent sign (%) prefix, followed by an
optional maximum width or assignment suppression, and ending with a conversion type. A
percent sign can be skipped by doubling it in format; %% signifies a single % in the
input stream.
An optional width is a decimal number specifying the maximum width of an input
field. scanf() will not read more characters for a conversion than is specified by the width.
An optional assignment suppression character (*) can be used to skip an item by
reading it but not assigning it. A conversion specification with assignment suppression must
not have a corresponding argument.
The last character, the conversion type, specifies the kind of conversion requested.
“Length Modifiers And Conversion Specifiers For Formatted Input Functions”, describes the
conversion type characters.
D.3.2.2 Length Modifiers And Conversion Specifiers For Formatted Input Functions
D.3.2.2.1 Length Specifiers
Modifier Description
Length Specifiers
hh
The hh flag indicates that the following d, i, o, u, x, X or n conversion specifier
applies to an argument that is of type char or unsigned char.
h
Theh flag indicates that the following d, i, o, u, x, X or n conversion specifier
applies to an argument that is of type short int or unsigned short int.
l
When used with integer conversion specifier, the l flag indicates long int or an
unsigned long int type. When used with floating point conversion specifier, the l
flag indicates a double. When used with a c or s conversion specifier, the l flag
indicates that the corresponding argument with type pointer to wchar_t.
ll
When used with integer conversion specifier, the ll flag indicates that the
corresponding argument is of type long long or an unsigned long long.
L
TheL flag indicates that the corresponding float conversion specifier corresponds
to an argument of type long double.
DPM_C_I/O.doc
Page D-17 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.2.2.2 Conversion Specifiers
Modifier Description
Conversion Specifiers
d
A decimal integer is read.
i
A decimal, octal, or hexadecimal integer is read. The integer can be prefixed with a
plus or minus sign (+, - ), 0 for octal numbers, 0x or 0X for hexadecimal numbers.
o
An octal integer is read.
u
An unsigned decimal integer is read.
x, X
A hexadecimal integer is read.
e, E
A floating point number is read. The number can be in plain decimal format (e.g.
3456.483) or in scientific notation ([-]b.aaae[-]dd
f
g, G
s
A character string is read. The input character string is considered terminated when
a white space character is reached or the maximum width has been reached. The
null character is appended to the end of the array.
c
A character is read. White space characters are not skipped, but read using this
conversion specifier.
p
A pointer address is read. The input format should be the same as that output by
the p conversion type in printf().
n
This conversion type does not read from the input stream but stores the number of
characters read in ist corresponding argument.
[scanset] Input stream characters are read and filtered determined by the scanset.
D.3.2.2.3 Scanset
The conversion specifier %[ allows you to specify a scanset, which is a sequence of
characters that will be read and stored in the string pointed to by the scanset's corresponding
argument. The characters between the [ and the terminating ] define the scanset. A null
character is appended to the end of the character sequence.
Input stream characters are read until a character is found that is not in the scanset. If
the first character of scanset is a circumflex5 (^) then input stream characters are read until a
character from the scanset is read. A null character is appended to the end of the character
array.
Thus, the conversion specifier %[abcdef] specifies that the scanset is abcdef and any
of the characters ‘a’ through ‘f’ are to be accepted and stored. As soon as any character
outside this set is encountered, reading and storing will cease.
Thus, for example, assuming we have the declaration:
char str[20];
the execution of
sscanf("acdfxbe", "%[abcdef]", str);
will store acdf in str; the ‘x’ and following characters will not be stored because the ‘x’ is not
in the scanset.
5
„caret“ is the better expression for ^
DPM_C_I/O.doc
Page D-18 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
If the first character of the scanset is the circumflex, ^, then the following characters
will define a set of characters such that encountering any one of them will cause reading and
storing to stop; any character outside a scanset defined in this way will be accepted, we will
call this an exclusionary scanset.
Thus execution of
sscanf("stuvawxyz", "%[^abcdef]", str);
will store stuv in str. If you want ^ to be part of the scanset, you cannot list it as the
first character otherwise it will be interpreted as introducing the members of an exclusionary
scanset. Thus %[^abc] defines the exclusionary scanset abc whereas %[a^bc] defines the
scanset abc^.
%[^a^bc] defines the exclusionary scanset abc^, as does %[^^abc].
If you want ] to be in the scanset, it must be the first character of the scanset,
immediately following the %[ or, to be in an exclusionary scanset, immediately after the ^, for
example,
%[]abc] or %[^]abc].
In any other position, the ] will be interpreted as terminating the scanset.
To include the - character in the scanset, it must be either listed first (possibly after an
initial ^ or last, thus for example, %[-abc], %[abc-], %[^-abc], or%[^abc-]. The C Standard
explicitly states:
If a - character is in the scanlist and is not the first, nor the second where the first
character is a ^, nor the last character, the behavior is implementation-defined.
MSL interprets such a use of - in a scanlist as defining a range of characters; thus, the
specification %[a-z] as being the equivalent of %[abcdefghijklmnopqrstuvwxyz]. You should
bear in mind that this is MSL’s interpretation and such usage may be interpreted differently in
other C library implementations. Note also that it is assumed that the numeric value of the
character before the - is less than that of the one after. If this relationship does not hold
undefined and probably unwanted effects may be experienced.
DPM_C_I/O.doc
Page D-19 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.3.2.3 Example of scanf() usage
#include <stdio.h>
int main(void)
{
int i, k;
unsigned int j;
char c;
char s[40];
double x;
printf("Enter an integer surrounded by ! marks\n");
scanf("!%d!", &i);
printf("Enter three integers\n");
printf("in hexadecimal, octal, or decimal.\n");
/*
note that 3 integers are read, but only the last two
are assigned to i and j */
scanf("%*i %i %ui", &i, &j, &k);
printf("Enter a character and a character string.\n");
scanf("%c %10s", &c, s);
printf("Enter a floating point value.\n");
scanf("%lf", &x);
return 0;
}
The dialog is:
Enter an integer surrounded by ! marks
!24405!
Enter three integers
in hexadecimal, octal, or decimal.
0xabc 0234 456
Enter a character and a character string.
g string
Enter a floating point value.
3e-5
DPM_C_I/O.doc
Page D-20 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4 The C File System
Although the C file system differs from that used by C++, it largely parallels it. The C
file system is composed of several interrelated functions. The most commonly used are listed
in the Function and Purpose Table listed below.
The common thread that ties the C I/O system tagether is the file pointer. A file pointer
is a pointer to information that defines various things about the file, including its name, status,
and current position. In essence, the file pointer identifies a specific disk file, and is used by
the stream to tell each of the C I/O functions where to perform operations. A file pointer is a
pointer variable of type FILE, which is defined in stdio.h.
The remainder of this appendix discusses the basic file functions.
Function
fopen( )
fclose( )
fputc( )
fgetc( )
fwrite( )
fread( )
fseek( )
fprintf( )
fscanf( )
feof( )
ferror( )
rewind( )
remove( )
Purpose
Opens a stream
Closes a stream
Writes a character to a stream
Reads a character from a stream
Writes a block of data to a stream
Reads a block of data from a stream
Seeks to specified byte in a stream
Is to a stream what printf( ) is to the console
Is to a stream what scanf( ) is to the console
Returns true if end-of-file is reached
Returns true if an error has occurred
Resets the file position indicator to the beginning of the file
Erases a file
Highlevel file access
open a file
I/O
fprintf
fscanf
fopen
putc, fputc
getc, fgetc
formatted character mode
fputs
fgets
string mode
fwrite
fread
binary
fseek
ftell
rewind
positioning
write buffer
fflush
close the file
fclose
erase the file
remove
ferror
feof
clearerr
error
handling
operations on files
(r.siol) 10.01.2007
DPM_C_I/O.doc
Hochschule Ravensburg-Weingarten
Technik | Wirtschaft | Sozialwesen
Page D-21 of 40
107
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.1 fopen( )
fopen( ) serves three functions:
o It opens a stream for use
o It links a file with that stream
o It returns a FILE pointer to that stream
Most often, and for the rest of this discussion, the file is a disk file. The fopen( )
function has this prototype:
FILE *fopen(const char *filename, const char *mode);
where filename points to the name of the file that is being opened, and mode points to a string
containing the desired open status. The legal values for mode are shown in the Mode Table.
The filename must be a string of characters that comprise a filename valid in the operating
system; it may also include a path specification.
The fopen( ) function returns a pointer of type FILE. This pointer identifies the file,
and is used by most other file system functions. It should never be altered by your code. On
failure, fopen( ) returns null.
As the Mode Table shows, a file can be opened in either text mode or binary mode. In
text mode, carriage-return/linefeed sequences are translated into newline characters on input.
On output, the reverse occurs: newlines are translated into carriage-return/ linefeeds. No such
translations occur on binary files.
Mode
"r"
"w"
"a"
"rb"
"wb"
"ab"
"r+"
"w+"
"a+"
"r+b"
"w+b"
"a+b"
Meaning
Open a text file for reading
Create a text file for writing
Append to a text file
Open a binary file for reading
Create a binary file for writing
Append to a binary file
Open a text file for read/write
Create a text file for read/write
Append to or create a text file for read/write
Open a binary file for read/write
Create a binary file for read/write
Append to or create a binary file for read/write
DPM_C_I/O.doc
Page D-22 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
If you want to open a file for writing with the name test, then you could write
fp = fopen( "test", "w");
where fp is a variable of type FILE *. However, you will usually see it written like this:
if ( (fp = fopen (" test", "w")) ==NULL)
{
printf("Cannot open file.");
exit (1) ;
}
This method detects any error in opening a file, such as a write-protected or full disk,
before attempting to write to it. NULL is a macro defined in stdio.h.
If you use fopen( ) to open a file for output, then any preexisting file by that name will
be erased and a new file started. If no file by that name exists, then one will be created. If you
want to add to the end of an existing file, then you must use mode "a". If the file does not
exist, it will be created. Opening a file for read operations requires that the file exists. If it
does not, an error will be returned. Finally, if a file is opened for read/write operations, it will
not be erased if it exists; however, if it does not exist, it will be created.
DPM_C_I/O.doc
Page D-23 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.1.1 Example of fopen() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int count;
/* create a new file for output */
if (( f = fopen("today_2", "w")) == NULL)
{
printf("Can't create file.\n");
exit(1);
}
/* output numbers 0 to 9 */
for (count = 0; count < 10; count++)
fprintf(f, "%5d", count);
/* close the file */
fclose(f);
/* open the file to append */
if (( f = fopen("today_2", "a")) == NULL)
{
printf("Can't append to file.\n");
exit(1);
}
/* output numbers 10 to 19 */
for (; count < 20; count++)
fprintf(f, "%5d\n", count);
/* close file */
fclose(f);
return 0;
}
Created the file foofoo
0
1
11
12
13
14
15
16
17
18
19
2
3
DPM_C_I/O.doc
4
5
6
7
8
9 10
Page D-24 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.2 fputc( )
The fputc( ) function is used to write characters to a stream that was previously
opened für writing by using the fopen( ) function. Its prototype is:
int fputc(int ch, FILE *fp);
Here, fp is the file pointer returned by fopen( ), and ch is the character to be output.
The file pointer tells fputc( ) which disk file to write to. Although ch is an int, only the loworder byte is used.
If an fputc( ) operation is a success, then it will return the character written. Upon
failure, an EOF is returned.
D.4.2.1 Example of fputc() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int letter;
/* create a new file for output
*/
if (( f = fopen("foofoo", "w")) == NULL)
{
printf("Can't create file.\n");
exit(1);
}
/* output the alphabet to the file one letter */
/* at a time
*/
for (letter = 'A'; letter <= 'Z'; letter++)
fputc(letter, f);
fclose(f);
return 0;
}
Output to file foofoo
ABCDEFGHIJKLMNOPQRSTUVWXYZ
DPM_C_I/O.doc
Page D-25 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.3 fgetc( )
The fgetc( ) function is used to read characters from a stream opened in read mode by
fopen( ). Its prototype is
int fgetc(FILE *fp);
Here, fp is a file pointer of type FILE returned by fopen( ). Although fgetc( ) returns
an integer, the high-order byte is zero.
The fgetc( ) function will return EOF when an error occurs or the end of the file has
been reached. Therefore, to read to the end of a text file you could use the following code:
ch = fgetc (fp) ;
while(ch!=EOF)
{
( ch = fgetc (fp) ;
}
D.4.3.1 Example of fgetc() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
char filename[80], c;
/* get a filename from the user
printf("Enter a filename to read.\n");
gets(filename);
*/
/* open the file for input
*/
if (( f = fopen(filename, "r")) == NULL)
{
printf("Can't open %s.\n", filename);
exit(1);
}
/* read the file one character at a time until
/* end-of-file is reached
*/
while ( (c = fgetc(f)) != EOF)
putchar(c); /* print the character
*/
/* close the file
fclose(f);
return 0;
*/
*/
}
Dialog and output:
Enter a filename to read.
foofoo
ABCDEFGHIJKLMNOPQRSTUVWXYZ
DPM_C_I/O.doc
Page D-26 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.4 feof( )
The C file system can also operate on binary data. When a file is opened for binary
input, it is possible that an integer value equal to EOF may be read. This would cause the
code shown above to indicate an end-of-file condition, even though the physical end of the
file had not been reached. To solve this problem, C includes the function feof( ), which is
used to determine end-of-file when reading binary data. It has the prototype
int feof(FILE *fp);
where fp identifies the file. The feof( ) function returns non-zero if the end of the file has been
reached; otherwise, zero is returned. Therefore, the following reads a binary file until end-offile is encountered:
while(!feof(fp)) ch = fgetc(fp);
Of course, this same method can be applied to text files, as well.
D.4.4.1 Example of feof() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
static char filename[80], buf[80] = "";
/* get a filename from the user
printf("Enter a filename to read.\n");
gets(filename);
*/
/* open the file for input
*/
if (( f = fopen(filename, "r")) == NULL)
{
printf("Can't open %s.\n", filename);
exit(1);
}
/* read text lines from the file until
/* feof() indicates the end-of-file
for (; feof(f) == 0 ; fgets(buf, 80, f) )
printf(buf);
/* close the file
fclose(f);
return 0;
*/
*/
*/
}
Dialog and output
Enter a filename to read.
myfoo
myfoo 483.5820 56
DPM_C_I/O.doc
Page D-27 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.5 fclose( )
The fclose( ) function closes a stream that was opened by a call to fopen( ). It writes
any data still remaining in the disk buffer to the file, and does a formal operating-system-level
close on the file. A call to fclose( ) frees the file control block associated with the stream and
makes it available for reuse. As you probably know, there is an operating system limit to the
number of open files you can have at any one time, so it may be necessary to close one file
before opening another.
The fclose( ) function has the following prototype:
int fclose(FILE *fp);
where fp is the file pointer returned by the call to fopen( ). A return value of zero signifies a
successful close operation; EOF is returned if an error occurs. Generally, the only time
fclose( ) will fail is when a disk has been prematurely removed from the drive or there is no
more space on the disk.
D.4.5.1 Example of fclose() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
static char name[] = "myfoo";
/* create a new file for output
if ( (f = fopen(name, "w")) == NULL)
{
printf("Can't open %s.\n", name);
exit(1);
}
/* output text to the file
fprintf(f, "pizza sushi falafel\n");
fprintf(f, "escargot sprocket\n");
*/
*/
/* close the file
*/
if (fclose(f) == -1) {
printf("Can't close %s.\n", name);
exit(1);
}
return 0;
}
Output to file myfoo:
pizza sushi falafel
escargot sprocket
DPM_C_I/O.doc
Page D-28 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.6 ferror( ) and rewind( )
The ferror( ) function is used to determine whether a file operation has produced an
error. It has the prototype
int ferror(FILE *fp);
where fp is a valid file pointer. ferror( ) returns true if an error has occurred during the last
file operation; it returns false otherwise. Because each file operation sets the error condition,
ferror( ) should be called immediately after each file operation; otherwise, an error may be
lost.
The rewind( ) function will reset the file position indicator to the beginning of the file
specified as its argument. The prototype is
void rewind(FILE *fp);
where fp is a valid file pointer.
D.4.6.1 Example of ferror() usage.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
char filename[80], buf[80];
int ln = 0;
/* get a filename from the user
printf("Enter a filename to read.\n");
gets(filename);
*/
/* open the file for input
*/
if (( f = fopen(filename, "r")) == NULL)
{
printf("Can't open %s.\n", filename);
exit(1);
}
/* read the file one line at a time until end-of-file
do
{
fgets(buf, 80, f);
printf("Status for line %d: %d.\n", ln++, ferror(f));
} while (feof(f) == 0);
/* close the file
fclose(f);
return 0;
*/
*/
}
Dialog and output
Enter a filename to read.
foofoo
Status for line 0: 0.
DPM_C_I/O.doc
Page D-29 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.6.2 Example of rewind() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
char filename[80], buf[80];
/* get a filename from the user
printf("Enter a filename to read.\n");
gets(filename);
*/
/* open a file for input
*/
if (( f = fopen(filename, "r")) == NULL)
{
printf("Can't open %s.\n", filename);
}
printf("Reading first line twice.\n");
/* move the file position indicator to the beginning of the file
rewind(f);
/* read the first line
fgets(buf, 80, f);
printf("Once: %s\n", buf);
*/
/* move the file position indicator to the beginning of the file
rewind(f);
/* read the first line again
fgets(buf, 80, f);
printf("Twice: %s\n", buf);
/* close the file
fclose(f);
return 0;
*/
*/
*/
*/
}
Dialog and output
Enter a filename to read.
myfoo
Reading first line twice.
Once: pizza sushi falafel
Twice: pizza sushi falafel
DPM_C_I/O.doc
Page D-30 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.7 fread( ) and fwrite( )
The C file system provides two functions, fread( ) and fwrite( ), that allow the reading
and writing of blocks of data. These functions are similar to C++'s read( ) and write( )
functions. Their prototypes are
size_t fread(void *buffer, size_t num_bytes, size_t count, FILE *fp);
size_t fwrite(const void *buffer, size_t num_bytes, size_t count, FILE *fp);
In the case of fread( ), buffer is a pointer to a region of memory that will receive the
data read from the file. The function reads count number of objects, each object being
num_bytes in length, from the stream pointed to by fp. fread( ) returns the number of objects
read, which may be less than count if an error or the end of the file is encountered.
For fwrite( ), buffer is a pointer to the information that will be written to the file. The
function writes count number of objects, each object being num_bytes in length, to the stream
pointed to by fp.fwrite( ) returns the number of objects written, which will be equal to count,
unless an error occurs.
As long as the file has been opened for binary operations, fread( ) and fwrite( ) can
read and write any type of information. For example, this program writes a float to a disk file:
/* Write a floating point number to a disk file. */
#include <stdio.h>
int main ()
{
FILE *fp;
float f = l2.23F;
if ( (fp=fopen ("test" , "wb") ) ==NULL)
{
printf("Cannot open file.\n");
return 1;
}
fwrite(&f, sizeof(float), 1, fp);
fclose (fp) ;
return 0;
}
As this program illustrates, the buffer can be, and often is, simply a variable.
One of the most useful applications of fread( ) and fwrite( ) involves the reading and
writing of arrays or structures. For example, the following program writes the contents of the
floating-point array balance to the file "balance" by using a single fwrite( ) statement. Next,
it reads the array, using a single fread( ) statement, and displays its contents.
DPM_C_I/O.doc
Page D-31 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.7.1 The use of fwrite() and fread()
#include <stdio.h>
int main()
{
register int i;
FILE *fp;
float balance[100];
/* open for write */
if ( (fp=fopen ("balance" , "w") ) ==NULL)
{
printf ("Cannot open file. \n");
return 1;
}
for(i = 0; i < 100; i++) balance[i] = (float) i;
/* This saves the entire balance array in one step. */
fwrite(balance, sizeof balance, 1, fp);
fclose(fp) ;
/* zero array */
for(i = 0; i < 100; i++) balance[i] = 0.0;
/* open for read */
if ( (fp = fopen ("balance" , "r") ) ==NULL)
{
printf ("Cannot open file. \n") ;
return 1;
}
/* This reads the entire balance array in one step. */
fread(balance, sizeof balance, 1, fp);
/* display
for(i = 0;
printf("%f
fclose(fp)
return 0;
contents of array */
i < 100; i++)
", balance[i]);
;
}
The program shows as output:
0.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000 11.000000
12.000000 13.000000 14.000000 15.000000 16.000000 17.000000 18.000000 19.000000 20.000000 21.000000 22.000000
23.000000 24.000000 25.000000 26.000000 27.000000 28.000000 29.000000 30.000000 31.000000 32.000000 33.000000
34.000000 35.000000 36.000000 37.000000 38.000000 39.000000 40.000000 41.000000 42.000000 43.000000 44.000000
45.000000 46.000000 47.000000 48.000000 49.000000 50.000000 51.000000 52.000000 53.000000 54.000000 55.000000
56.000000 57.000000 58.000000 59.000000 60.000000 61.000000 62.000000 63.000000 64.000000 65.000000 66.000000
67.000000 68.000000 69.000000 70.000000 71.000000 72.000000 73.000000 74.000000 75.000000 76.000000 77.000000
78.000000 79.000000 80.000000 81.000000 82.000000 83.000000 84.000000 85.000000 86.000000 87.000000 88.000000
89.000000 90.000000 91.000000 92.000000 93.000000 94.000000 95.000000 96.000000 97.000000 98.000000 99.000000
Using fread( ) and fwrite( ) to read or write blocks of data is more efficient than using
repeated calls to fgetc( ) and fputc( ).
DPM_C_I/O.doc
Page D-32 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.8 fseek( ) and Random-Access I/O
You can perform random read and write operations using the C I/O system with the
help of fseek( ), which sets the file position indicator. Its prototype is
int fseek(FILE *fp, long numbytes, int origin);
where fp is a file pointer returned by a call to fopen( ), numbytes is the number of bytes from
origin to seek to, and origin is one of the following macros (defined in stdio.h):
Origin
Beginning of file
Current position
End of file
Macro
SEEK_SET
SEEK_CUR
SEEK_END
Therefore, to seek numbytes from the start of the file, origin should be SEEK_SET.
To seek from the current position, use SEEK_CUR, and from the end of the file, use
SEEK_END.
The fseek( ) function returns zero on success, and non-zero if a failure occurs.
As a general rule, the use of fseek( ) on files opened in text mode is not recommended,
because the character translations will cause position errors to result. Therefore, its use is
suggested only for files opened in binary mode. For example, if you want to read the 234th
byte in a file called test, you could use the following code:
int func1 ()
{
FILE *fp;
if ( (fp = fopen ("
test", "rb")) ==
NULL)
{
printf ("cannot
open file\n");
exit (1) ;
}
fseek(fp, 234L,
SEEK_SET);
return getc(fp);
/* read one
character */
/* at 234th
position */
}
DPM_C_I/O.doc
Page D-33 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.8.1 Example of fseek() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
long int pos1, pos2, newpos;
char filename[80], buf[80];
/* get a filename from the user
printf("Enter a filename to read.\n");
gets(filename);
*/
/* open a file for input
*/
if (( f = fopen(filename, "r")) == NULL)
{
printf("Can't open %s.\n", filename);
exit(1);
}
printf("Reading last half of first line.\n");
/* get the file position indicator before and after
/* reading the first line
*/
pos1 = ftell(f);
fgets(buf, 80, f);
pos2 = ftell(f);
printf("Whole line: %s\n", buf);
/* calculate the middle of the line
newpos = (pos2 - pos1) / 2;
fseek(f, newpos, SEEK_SET);
fgets(buf, 80, f);
printf("Last half: %s\n", buf);
/* close the file
fclose(f);
return 0;
*/
*/
*/
}
The dialog:
Enter a filename to read.
myfoo
Reading last half of first line.
Whole line: myfoo 483.5820 56
Last half: 5820 56
Another call:
Enter a filename to read.
foofoo
Reading last half of first line.
Whole line: 0 1 2 3 4
Last half: 5
DPM_C_I/O.doc
6
7
8
5
6
7
8
9 10
9 10
Page D-34 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.9 fprintf( ) and fscanf( )
In addition to the basic I/O functions discussed above, the C I/O system includes
fprintf( ) and fscanf( ). These functions behave exactly like printf( ) and scanf( ), except that
they operate on files. For this reason, these functions are commonly found in C programs. The
prototypes of fprintf( ) and fscanf( ) are
int fprintf(FILE *fp, const char *fmt_string, ... );
int fscanf(FILE *fp, const char *fmt_string, ... );
where fp is a file pointer returned by a call to fopen( ). Except for directing their focus to the
file defined by fp, they operate exactly like printf( ) and scanf( ), respectively.
D.4.9.1 Example of fprintf() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
static char filename[] = "myfoo";
int a = 56;
char c = 'M';
double x = 483.582;
/* create a new file for output
if (( f = fopen(filename, "w")) == NULL)
{
printf("Can't open %s.\n", filename);
exit(1);
}
*/
/* output formatted text to the file
*/
fprintf(f, "%10s %4.4f %-10d\n%10c", filename, x, a, c);
/* close the file
fclose(f);
return 0;
*/
}
With the output to the file myfoo
myfoo 483.5820 56
M
DPM_C_I/O.doc
Page D-35 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.9.2 Example of fscanf() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int i;
double x;
char c;
/* create a new file for output and input
if (( f = fopen("foobar", "w+")) == NULL)
{
printf("Can't create new file.\n");
exit(1);
}
*/
/* output formatted text to the file
fprintf(f, "%d\n%f\n%c\n", 45, 983.3923, 'M');
*/
/* go to the beginning of the file
rewind(f);
*/
/* read from the stream using fscanf()
fscanf(f, "%d %lf %c", &i, &x, &c);
*/
/* close the file
*/
fclose(f);
printf("The integer read is %d.\n", i);
printf("The floating point value is %f.\n", x);
printf("The character is %c.\n", c);
return 0;
}
Output:
The integer read is 45.
The floating point value is 983.392300.
The character is M.
DPM_C_I/O.doc
Page D-36 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.10 fflush()
Empty a stream's buffer to its host environment.
Prototype
#include <stdio.h>
int fflush(FILE *stream);
Parameters
Parameters for this facility are:
stream FILE *
A pointer to a FILE stream
Remarks
The fflush() function empties stream's buffer to the file associated with stream.
If the stream points to an output stream or an update stream in which the most
recent operation was not input, the fflush function causes any unwritten data
for that stream to be
delivered to the host environment to be written to the file; otherwise the
behavior is undefined.
NOTE
The fflush() function should not be used after an input operation.
NOTE
Using fflush() for input streams especially the standard input
stream (stdin) is undefined and is not supported and will not flush
the input buffer.
NOTE
On embedded/ RTOS systems this function only is implemented for
stdin, stdout and stderr files.
Return
The function fflush() returns EOF if a write error occurs, otherwise it returns
zero.
DPM_C_I/O.doc
Page D-37 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.4.10.1 Example of fflush() usage
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int count;
/* create a new file for output
*/
if (( f = fopen("file_070117", "w")) == NULL)
{
printf("Can't open file.\n");
exit(1);
}
for (count = 0; count < 100; count++)
{
fprintf(f, "%5d", count);
if( (count % 10) == 9 )
{
fprintf(f, "\n");
fflush(f); /* flush buffer every 10 numbers */
}
}
fclose(f);
return 0;
}
Generated data in file_070117
0
1
10
20
30
40
50
60
70
80
90
2
11
21
31
41
51
61
71
81
91
3
12
22
32
42
52
62
72
82
92
DPM_C_I/O.doc
4
13
23
33
43
53
63
73
83
93
5 6 7 8
14 15 16
24 25 26
34 35 36
44 45 46
54 55 56
64 65 66
74 75 76
84 85 86
94 95 96
9
17
27
37
47
57
67
77
87
97
18
28
38
48
58
68
78
88
98
19
29
39
49
59
69
79
89
99
Page D-38 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.5 Erasing Files
The remove( ) function erases the specified file. Its prototype is
int remove(const char *filename);
It returns zero upon success, and non-zero if it fails.
DPM_C_I/O.doc
Page D-39 of 40
Rüdiger Siol
11.12.2009 15:24
Hochschule
Ravensburg-Weingarten
Fakultät Elektrotechnik und Informatik
Mechatronik
Information Processing
Elementary C/C++ Programming
D.6 More Examples to C-Based I/O
D.6.1 The use of EOF during keyboard input
/*
DPM_Example_c
*/
#include <stdio.h>
int main (void)
{
int zeichen;
while ((zeichen = getchar()) != EOF)
putchar(zeichen);
printf("\nSie haben Strg + D bzw. Strg + Z getippt um End of file (EOF) zu erzeugen.\n");
return 0;
}
DPM_C_I/O.doc
Page D-40 of 40
Rüdiger Siol
11.12.2009 15:24

Documents pareils