C++ 编程/代码/标准 C 库/IO
标准 C 库包含一些过时的例程,但由于 C++ 语言的历史 以及保持兼容性的目标,这些例程包含在软件包中。
C I/O 调用仍然出现在旧代码中(不仅是 ANSI C 89,甚至旧的 C++ 代码)。它在今天的使用可能取决于许多因素,例如代码库的年龄、项目复杂程度,甚至程序员的经验。如果你精通 C,为什么要使用你不熟悉的东西呢?在某些情况下,C 样式的 I/O 例程优于它们的 C++ I/O 对应物,例如,它们更紧凑,并且可能足够用于不需要类的简单项目。
语法 |
#include <cstdio>
void clearerr( FILE *stream );
|
clearerr 函数重置给定流的错误标志和 EOF 指示器。如果发生错误,你可以使用 perror()
或 strerror()
来找出实际发生的错误,或者从全局变量 errno
中读取错误。
语法 |
#include <cstdio>
int fclose( FILE *stream );
|
fclose() 函数关闭给定的文件流,释放与该流关联的任何缓冲区。fclose() 在成功时返回 0,否则返回 EOF。
语法 |
#include <cstdio>
int feof( FILE *stream );
|
feof() 函数在遇到文件结尾时返回 TRUE,否则返回 FALSE。
语法 |
#include <cstdio>
int ferror( FILE *stream );
|
ferror() 函数检查流是否有错误,如果未发生错误,则返回零,如果发生错误,则返回非零值。在发生错误的情况下,使用 perror() 来确定发生了哪个错误。
语法 |
#include <cstdio>
int fflush( FILE *stream );
|
如果给定的文件流是输出流,则 fflush() 会将输出缓冲区写入文件。如果给定的流是输入类型,则 fflush() 的行为取决于使用的库(例如,某些库会忽略操作,其他库会报告错误,而其他库会清除待处理的输入)。
fflush() 在调试时非常有用(例如,如果程序在缓冲区发送到屏幕之前发生段错误),或者它可以用于在长时间处理之前确保部分输出显示。
默认情况下,大多数实现都会在每行结束时传输 stdout 的缓冲区,而 stderr 则在每次输出时都会刷新。如果存在重定向或管道,则此行为会发生变化,在这种情况下,调用 fflush(stdout) 可以帮助维护输出流。
printf( "Before first call\n" );
fflush( stdout );
shady_function();
printf( "Before second call\n" );
fflush( stdout );
dangerous_dereference();
语法 |
#include <cstdio>
int fgetc( FILE *stream );
|
fgetc() 函数从流中返回下一个字符,如果遇到文件结尾或发生错误,则返回 EOF。
语法 |
#include <cstdio>
int fgetpos( FILE *stream, fpos_t *position );
|
fgetpos() 函数将给定文件流的文件位置指示器存储到给定的位置变量中。位置变量的类型为 fpos_t(在 cstdio 中定义),是一个可以保存 FILE 中所有可能位置的对象。fgetpos() 在成功时返回零,在失败时返回非零值。
语法 |
#include <cstdio>
char *fgets( char *str, int num, FILE *stream );
|
fgets()
函数从给定文件流中读取最多 num
- 1 个字符,并将它们转储到 str
中。fgets()
生成的字符串始终以 null 结尾。fgets()
将在到达行尾时停止,在这种情况下,str
将包含该换行符。否则,fgets()
将在到达 num
- 1 个字符或遇到 EOF
字符时停止。fgets()
在成功时返回 str
,在错误时返回 NULL
。
语法 |
#include <cstdio>
FILE *fopen( const char *fname, const char *mode );
|
fopen() 函数打开由 fname 指定的文件,并返回与该文件关联的流。如果出现错误,fopen() 返回 NULL。mode 用于确定如何处理文件(即用于输入、输出等)。
mode 包含最多三个字符。第一个字符是 "r"、"w" 或 "a",它指示文件是如何打开的。为读取打开的文件从文件开头开始允许输入。对于写入,文件将被擦除。对于追加,文件将被保留,写入文件将从末尾开始。第二个字符是 "b",是一个可选标志,它以二进制形式打开文件 - 省略任何来自不同文本格式的转换。第三个字符 "+" 是一个可选标志,它允许对文件执行读写操作(但文件本身以相同的方式打开)。
模式 | 意义 | 模式 | 意义 |
---|---|---|---|
"r" | 以读取模式打开文本文件 | "r+" | 以读写模式打开文本文件 |
"w" | 以写入模式创建文本文件 | "w+" | 以读写模式创建文本文件 |
"a" | 追加到文本文件 | "a+" | 以读写模式打开文本文件 |
"rb" | 以读取模式打开二进制文件 | "rb+" | 以读写模式打开二进制文件 |
"wb" | 以写入模式创建二进制文件 | "wb+" | 以读写模式创建二进制文件 |
"ab" | 追加到二进制文件 | "ab+" | 以读写模式打开二进制文件 |
一个例子
int ch;
FILE *input = fopen( "stuff", "r" );
ch = getc( input );
语法 |
#include <cstdio>
int fprintf( FILE *stream, const char *format, ... );
|
fprintf() 函数根据指定的格式将信息(参数)发送到 stream 指示的文件。fprintf() 在格式方面与 printf() 一样。fprintf() 的返回值是输出的字符数,如果出现错误,则为负数。一个例子
char name[20] = "Mary";
FILE *out;
out = fopen( "output.txt", "w" );
if( out != NULL )
fprintf( out, "Hello %s\n", name );
语法 |
#include <cstdio>
int fputc( int ch, FILE *stream );
|
fputc() 函数将给定的字符 ch 写入给定的输出流。返回值是该字符,除非出现错误,在这种情况下返回值为 EOF。
语法 |
#include <cstdio>
int fputs( const char *str, FILE *stream );
|
fputs() 函数将 str 指向的字符数组写入给定的输出流。返回值在成功时是非负的,在失败时为 EOF。
语法 |
#include <cstdio>
int fread( void *buffer, size_t size, size_t num, FILE *stream );
|
fread() 函数读取 num 个对象(每个对象大小为 size 字节),并将它们放入 buffer 指向的数组中。数据来自给定的输入流。函数的返回值是读取的项数。可以使用 feof() 或 ferror() 来确定是否出现错误。
语法 |
#include <cstdio>
FILE *freopen( const char *fname, const char *mode, FILE *stream );
|
freopen() 函数用于将现有的流重新分配到不同的文件和模式。调用此函数后,给定的文件流将引用 fname,并具有 mode 给定的访问权限。freopen() 的返回值是新的流,如果出现错误,则为 NULL。
fscanf
[edit | edit source]语法 |
#include <cstdio>
int fscanf( FILE *stream, const char *format, ... );
|
fscanf() 函数从给定的文件流中读取数据,其方式与 scanf() 完全相同。fscanf() 的返回值是实际分配值的变量数量,包括零,如果没有任何匹配项。如果在第一次匹配之前出现读取错误,则返回 **EOF**。
fseek
[edit | edit source]语法 |
#include <cstdio>
int fseek( FILE *stream, long offset, int origin );
|
fseek() 函数设置给定流的文件位置数据。origin 值应该具有以下值之一(在 cstdio 中定义)
名称 | 解释 |
---|---|
SEEK_SET | 从文件开头开始查找 |
SEEK_CUR | 从当前位置开始查找 |
SEEK_END | 从文件结尾开始查找 |
fseek() 在成功时返回零,在失败时返回非零值。可以使用 fseek() 移动到文件之外,但不能移动到开头之前。使用 fseek() 将清除与该流关联的 EOF 标志。
fsetpos
[edit | edit source]语法 |
#include <cstdio>
int fsetpos( FILE *stream, const fpos_t *position );
|
fsetpos() 函数将给定流的文件位置指示器移动到位置对象指定的位置。fpos_t 在 cstdio 中定义。fsetpos() 的返回值在成功时为零,在失败时为非零值。
ftell
[edit | edit source]语法 |
#include <cstdio>
long ftell( FILE *stream );
|
ftell() 函数返回流的当前文件位置,如果出现错误则返回 -1。
fwrite
[edit | edit source]语法 |
#include <cstdio>
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
|
fwrite() 函数从数组缓冲区写入 count 个大小为 size 的对象到流。返回值是写入的对象数量。
getc
[edit | edit source]语法 |
#include <cstdio>
int getc( FILE *stream );
|
getc() 函数从流中返回下一个字符,如果到达文件末尾则返回 **EOF**。getc() 与 fgetc() 相同。例如
int ch;
FILE *input = fopen( "stuff", "r" );
ch = getc( input );
while( ch != EOF ) {
printf( "%c", ch );
ch = getc( input );
}
getchar
[edit | edit source]语法 |
#include <cstdio>
int getchar( void );
|
getchar() 函数从 **stdin** 返回下一个字符,如果到达文件末尾则返回 **EOF**。
gets
[edit | edit source]语法 |
#include <cstdio>
char *gets( char *str );
|
gets() 函数从 stdin 读取字符并将其加载到 str 中,直到遇到换行符或 **EOF**。换行符被转换为 null 终止符。gets() 的返回值是读取的字符串,如果出现错误则为 **NULL**。
perror
[edit | edit source]语法 |
#include <cstdio>
void perror( const char *str );
|
perror() 函数将 str
、一个 ":"、一个空格、一个与全局变量 errno 相对应的实现定义和/或语言相关的错误消息以及一个换行符写入 stderr。例如
char* input_filename = "not_found.txt";
FILE* input = fopen( input_filename, "r" );
if( input == NULL ) {
char error_msg[255];
sprintf( error_msg, "Error opening file '%s'", input_filename );
perror( error_msg );
exit( -1 );
}
如果找不到名为 not_found.txt 的文件,这段代码将生成以下输出
Error opening file 'not_found.txt': No such file or directory
如果 "str" 是一个空指针或指向空字节,则只将与 errno 相对应的错误消息和一个换行符写入 stderr。
printf
[edit | edit source]语法 |
#include <cstdio>
int printf( const char *format, ... );
cout<<printf;
|
printf() 函数根据传递给 printf() 的格式和其他参数将输出打印到 **stdout**。格式字符串由两种类型的项目组成 - 将打印到屏幕上的字符,以及定义 printf() 的其他参数如何显示的格式命令。基本上,您指定一个包含文本的格式字符串,以及映射到 printf() 的其他参数的 "特殊" 字符。例如,这段代码
char name[20] = "Bob";
int age = 21;
printf( "Hello %s, you are %d years old\n", name, age );
显示以下输出
Hello Bob, you are 21 years old
%s 表示 "在适当位置插入第一个参数,一个字符串"。%d 表示应该将第二个参数(一个整数)放置在那里。有不同的 %-代码用于不同的变量类型,以及用于限制变量长度等的选项。
控制字符 | 解释 |
---|---|
%c | 单个字符 |
%d | 十进制整数 |
%i | 整数 |
%e | 科学计数法,使用小写 "e" |
%E | 科学计数法,使用大写 "E" |
%f | 浮点数 |
%g | 使用 %e 或 %f,以较短者为准 |
%G | 使用 %E 或 %f,以较短者为准 |
%o | 八进制数 |
%x | unsigned 十六进制数,使用小写字母 |
%X | unsigned 十六进制,使用大写字母 |
%u | 一个 unsigned 整数 |
%s | 一个字符串 |
%ls | 一个宽字符串 |
%x | 一个十六进制数 |
%p | 一个指针 |
%n | 参数应该是一个指向整数的指针,该整数用于存储到目前为止写入的字符数 |
%% | 一个百分号 |
字段长度说明符可以出现在最终控制字符之前,用于指示字段的宽度
- h,当插入到 %d 中时,会导致参数成为一个短整型。
- l,当插入到 %d 中时,会导致参数成为一个长整型。
- l,当插入到 %f 中时,会导致参数成为一个双精度浮点数。
- L,当插入到 %d 或 %f 中时,会导致参数分别成为一个长长整型或长双精度浮点数。
在 % 符号和格式命令之间放置的整数充当最小字段宽度说明符,并使用空格或零填充输出,使其足够长。如果要使用零填充,请在最小字段宽度说明符之前放置一个零
%012d
您还可以包含精度修饰符,形式为 .N,其中 N 是某个数字,位于格式命令之前
%012.4d
精度修饰符根据使用的格式命令具有不同的含义
- 对于 %e、%E 和 %f,精度修饰符允许您指定所需的十进制位数。例如,%12.6f 将显示一个至少 12 位宽的浮点数,具有六位小数。
- 对于 %g 和 %G,精度修饰符决定显示的有效数字的最大数量。
- 对于 %s,精度修饰符只是一个最大字段长度,用于补充在句点之前的最小字段长度。
所有 printf() 的输出都是右对齐的,除非您在 % 符号后立即放置一个减号。例如,
%-12.4f
将显示一个浮点数,最小为 12 个字符,4 位小数,并左对齐。您可以使用字母 l 和字母 h 修改 %d、%i、%o、%u 和 %x 类型说明符以指定长数据类型和短数据类型(例如 %hd 表示短整型)。%e、%f 和 %g 类型说明符可以在它们之前具有字母 l 以指示后面跟着一个双精度浮点数。%g、%f 和 %e 类型说明符可以在前面加上字符 '#' 以确保即使没有小数位也会显示小数点。在 %x 类型说明符中使用 '#' 字符表示应使用 '0x' 前缀打印十六进制数。在 %o 类型说明符中使用 '#' 字符表示应使用 0 前缀显示八进制值。
在类型说明符中插入加号 '+' 将强制正值以 '+' 符号开头。在其中放置一个空格字符 ' ' 将强制正值以单个空格字符开头。
您还可以包含输出字符串中的常量转义序列。
printf() 的返回值是打印的字符数,如果发生错误,则为负数。
putc
[edit | edit source]语法 |
#include <cstdio>
int putc( int ch, FILE *stream );
|
putc() 函数将字符 ch 写入流。返回值是写入的字符,或者如果出现错误则为 EOF。例如
int ch;
FILE *input, *output;
input = fopen( "tmp.c", "r" );
output = fopen( "tmpCopy.c", "w" );
ch = getc( input );
while( ch != EOF ) {
putc( ch, output );
ch = getc( input );
}
fclose( input );
fclose( output );
生成名为 tmpCopy.c 的文件 tmp.c 的副本。
putchar
[edit | edit source]语法 |
#include <cstdio>
int putchar( int ch );
|
putchar() 函数将 ch 写入 stdout。代码
putchar( ch );
与
putc( ch, stdout );
相同。putchar() 的返回值是写入的字符,或者如果出现错误则为 EOF。
- 相关主题
- putc
puts
[edit | edit source]语法 |
#include <cstdio>
int puts( char *str );
|
puts() 函数将 str 写入 stdout。puts() 在成功时返回非负值,或者在失败时返回 EOF。
remove
[edit | edit source]语法 |
#include <cstdio>
int remove( const char *fname );
|
remove() 函数擦除由 fname 指定的文件。remove() 的返回值在成功时为零,如果出现错误则为非零。
- 相关主题
- rename
rename
[edit | edit source]语法 |
#include <cstdio>
int rename( const char *oldfname, const char *newfname );
|
rename() 函数将文件 oldfname 的名称更改为 newfname。rename() 的返回值在成功时为零,在错误时为非零。
- 相关主题
- remove
rewind
[edit | edit source]语法 |
#include <cstdio>
void rewind( FILE *stream );
|
rewind() 函数将文件位置指示器移到指定流的开头,还会清除与该流相关的错误和 EOF 标志。
- 相关主题
- fseek
scanf
[edit | edit source]语法 |
#include <cstdio>
int scanf( const char *format, ... );
|
scanf() 函数根据给定的格式从 stdin 读取输入,并将数据存储在其他参数中。它的工作原理与 printf() 非常类似。格式字符串由控制字符、空格字符和非空格字符组成。控制字符以 % 符号开头,如下所示
控制字符 | 解释 |
---|---|
%c | 单个字符 |
%d | 十进制整数 |
%i | 整数 |
%e, %f, %g | 浮点数 |
%lf | 一个双精度浮点数 |
%o | 八进制数 |
%s | 一个字符串 |
%x | 一个十六进制数 |
%p | 一个指针 |
%n | 一个等于到目前为止读取的字符数的整数 |
%u | 一个 unsigned 整数 |
%[] | 一组字符 |
%% | 一个百分号 |
scanf() 读取输入,匹配来自 format 的字符。当读取控制字符时,它将值放入下一个变量中。空格(制表符、空格等)将被跳过。非空格字符将与输入匹配,然后丢弃。如果在 % 符号和控制字符之间有一个数字,那么只有这么多字符会被转换为变量。如果 scanf() 遇到一组字符,由 %[] 控制字符表示,那么括号内找到的任何字符都会被读入变量。scanf() 的返回值是成功分配值的变量数,或者如果出现错误则为 EOF。
此代码段使用 scanf() 从用户处读取一个 int、一个 float 和一个 double。请注意,传递给 scanf() 的变量参数是按地址传递的,如每个变量之前的取地址符 (&) 所示
int i;
float f;
double d;
printf( "Enter an integer: " );
scanf( "%d", &i );
printf( "Enter a float: " );
scanf( "%f", &f );
printf( "Enter a double: " );
scanf( "%lf", &d );
printf( "You entered %d, %f, and %f\n", i, f, d );
setbuf
[edit | edit source]语法 |
#include <cstdio>
void setbuf( FILE *stream, char *buffer );
|
setbuf() 函数将流设置为使用 buffer,或者如果 buffer 为 NULL,则关闭缓冲。此函数预期缓冲区长度为 BUFSIZ 个字符 - 由于此函数不支持指定缓冲区大小,因此大于 BUFSIZ 的缓冲区将部分未被使用。
语法 |
#include <cstdio>
int setvbuf( FILE *stream, char *buffer, int mode, size_t size );
|
函数 setvbuf() 将stream的缓冲区设置为buffer,大小为size。mode可以是以下之一:
- _IOFBF,表示全缓冲
- _IOLBF,表示行缓冲
- _IONBF,表示不缓冲
语法 |
#include <cstdio>
int sprintf( char *buffer, const char *format, ... );
|
sprintf() 函数与 printf() 类似,区别在于输出被发送到buffer。返回值是写入的字符数。例如
char string[50];
int file_number = 0;
sprintf( string, "file.%d", file_number );
file_number++;
output_file = fopen( string, "w" );
请注意,sprintf() 与 atoi() 这样的函数作用相反 - atoi() 将字符串转换为数字,而 sprintf() 可以用于将数字转换为字符串。
例如,以下代码使用 sprintf() 将整数转换为字符数组
char result[100];
int num = 24;
sprintf( result, "%d", num );
这段代码类似,区别在于它将浮点数转换为字符数组
char result[100];
float fnum = 3.14159;
sprintf( result, "%f", fnum );
语法 |
#include <cstdio>
int sscanf( const char *buffer, const char *format, ... );
|
sscanf() 函数与 scanf() 类似,区别在于输入从buffer读取。
语法 |
#include <cstdio>
FILE *tmpfile( void );
|
tmpfile() 函数打开一个具有唯一文件名的临时文件,并返回指向该文件的指针。如果出错,则返回 NULL。
- 相关主题
- tmpnam
语法 |
#include <cstdio>
char *tmpnam( char *name );
|
tmpnam() 函数创建一个唯一的文件名,并将它存储在 name 中。tmpnam() 可以最多调用 TMP_MAX 次。
- 相关主题
- tmpfile
语法 |
#include <cstdio>
int ungetc( int ch, FILE *stream );
|
ungetc() 函数将字符ch放回stream。
语法 |
#include <cstdarg>
#include <cstdio>
int vprintf( char *format, va_list arg_ptr );
int vfprintf( FILE *stream, const char *format, va_list arg_ptr );
int vsprintf( char *buffer, char *format, va_list arg_ptr );
|
这些函数与 printf()、fprintf() 和 sprintf() 非常类似。区别在于参数列表是指向参数列表的指针。va_list 在 cstdarg 中定义,也由 (其他标准 C 函数) va_arg() 使用。
例如
void error( char *fmt, ... ) {
va_list args;
va_start( args, fmt );
fprintf( stderr, "Error: " );
vfprintf( stderr, fmt, args );
fprintf( stderr, "\n" );
va_end( args );
exit( 1 );
}