跳转到内容

C++ 编程/代码/标准 C 库/IO

来自 Wikibooks,开放书籍,开放世界

标准 C I/O

[编辑 | 编辑源代码]

标准 C 库包含一些过时的例程,但由于 C++ 语言的历史 以及保持兼容性的目标,这些例程包含在软件包中。

C I/O 调用仍然出现在旧代码中(不仅是 ANSI C 89,甚至旧的 C++ 代码)。它在今天的使用可能取决于许多因素,例如代码库的年龄、项目复杂程度,甚至程序员的经验。如果你精通 C,为什么要使用你不熟悉的东西呢?在某些情况下,C 样式的 I/O 例程优于它们的 C++ I/O 对应物,例如,它们更紧凑,并且可能足够用于不需要类的简单项目。

注意
如果你正在学习 I/O,你可能应该使用 C++ I/O 系统进行编程,而不是将旧的 I/O 系统混合在一起。只有在必须使用 C 样式的 I/O 时,才学习它。

语法
#include <cstdio>
void clearerr( FILE *stream );

clearerr 函数重置给定流的错误标志和 EOF 指示器。如果发生错误,你可以使用 perror()strerror() 来找出实际发生的错误,或者从全局变量 errno 中读取错误。

相关主题
feof - ferror - perror - strerror
语法
#include <cstdio>
int fclose( FILE *stream );

fclose() 函数关闭给定的文件流,释放与该流关联的任何缓冲区。fclose() 在成功时返回 0,否则返回 EOF

相关主题
fflush - fopen - freopen - setbuf
语法
#include <cstdio>
int feof( FILE *stream );

feof() 函数在遇到文件结尾时返回 TRUE,否则返回 FALSE

相关主题
clearerr - ferror - getc - perror - putc
语法
#include <cstdio>
int ferror( FILE *stream );

ferror() 函数检查流是否有错误,如果未发生错误,则返回零,如果发生错误,则返回非零值。在发生错误的情况下,使用 perror() 来确定发生了哪个错误。

相关主题
clearerr - feof - 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();
相关主题
fclose - fopen - fread - fwrite - getc - putc
语法
#include <cstdio>
int fgetc( FILE *stream );

fgetc() 函数从流中返回下一个字符,如果遇到文件结尾或发生错误,则返回 EOF

相关主题
fopen - fputc - fread - fwrite - getc - getchar - gets - putc
语法
#include <cstdio>
int fgetpos( FILE *stream, fpos_t *position );

fgetpos() 函数将给定文件流的文件位置指示器存储到给定的位置变量中。位置变量的类型为 fpos_t(在 cstdio 中定义),是一个可以保存 FILE 中所有可能位置的对象。fgetpos() 在成功时返回零,在失败时返回非零值。

相关主题
fseek - fsetpos - ftell
语法
#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

相关主题
fputs - fscanf - gets - scanf
语法
#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 );
相关主题
fclose - fflush - fgetc - fputc - fread - freopen - fseek - fwrite - getc - getchar - setbuf
语法
#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 );
相关主题
fputc - fputs - fscanf - printf - sprintf
语法
#include <cstdio>
int fputc( int ch, FILE *stream );

fputc() 函数将给定的字符 ch 写入给定的输出流。返回值是该字符,除非出现错误,在这种情况下返回值为 EOF

相关主题
fgetc - fopen - fprintf - fread - fwrite - getc - getchar - putc
语法
#include <cstdio>
int fputs( const char *str, FILE *stream );

fputs() 函数将 str 指向的字符数组写入给定的输出流。返回值在成功时是非负的,在失败时为 EOF

相关主题
fgets - fprintf - fscanf - gets - getc - puts
语法
#include <cstdio>
int fread( void *buffer, size_t size, size_t num, FILE *stream );

fread() 函数读取 num 个对象(每个对象大小为 size 字节),并将它们放入 buffer 指向的数组中。数据来自给定的输入流。函数的返回值是读取的项数。可以使用 feof() 或 ferror() 来确定是否出现错误。

相关主题
fflush - fgetc - fopen - fputc - fscanf - fwrite - getc
语法
#include <cstdio>
FILE *freopen( const char *fname, const char *mode, FILE *stream );

freopen() 函数用于将现有的流重新分配到不同的文件和模式。调用此函数后,给定的文件流将引用 fname,并具有 mode 给定的访问权限。freopen() 的返回值是新的流,如果出现错误,则为 NULL

相关主题
fclose - fopen

fscanf

[edit | edit source]
语法
#include <cstdio>
int fscanf( FILE *stream, const char *format, ... );

fscanf() 函数从给定的文件流中读取数据,其方式与 scanf() 完全相同。fscanf() 的返回值是实际分配值的变量数量,包括零,如果没有任何匹配项。如果在第一次匹配之前出现读取错误,则返回 **EOF**。

相关主题
fgets - fprintf - fputs - fread - fwrite - scanf - sscanf

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 标志。

相关主题
fgetpos - fopen - fsetpos - ftell - rewind

fsetpos

[edit | edit source]
语法
#include <cstdio>
int fsetpos( FILE *stream, const fpos_t *position );

fsetpos() 函数将给定流的文件位置指示器移动到位置对象指定的位置。fpos_t 在 cstdio 中定义。fsetpos() 的返回值在成功时为零,在失败时为非零值。

相关主题
fgetpos - fseek - ftell

ftell

[edit | edit source]
语法
#include <cstdio>
long ftell( FILE *stream );

ftell() 函数返回流的当前文件位置,如果出现错误则返回 -1。

相关主题
fgetpos - fseek - fsetpos

fwrite

[edit | edit source]
语法
#include <cstdio>
int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

fwrite() 函数从数组缓冲区写入 count 个大小为 size 的对象到流。返回值是写入的对象数量。

相关主题
fflush - fgetc - fopen - fputc - fread - fscanf - getc
语法
#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 );
}
相关主题
feof - fflush - fgetc - fopen - fputc - fgetc - fread - fwrite - putc - ungetc

getchar

[edit | edit source]
语法
#include <cstdio>
int getchar( void );

getchar() 函数从 **stdin** 返回下一个字符,如果到达文件末尾则返回 **EOF**。

相关主题
fgetc - fopen - fputc - putc
语法
#include <cstdio>
char *gets( char *str );

gets() 函数从 stdin 读取字符并将其加载到 str 中,直到遇到换行符或 **EOF**。换行符被转换为 null 终止符。gets() 的返回值是读取的字符串,如果出现错误则为 **NULL**。

注意
gets() 不执行边界检查,因此存在溢出 str 的风险。对于包含边界检查的类似(更安全)函数,请参阅 fgets()。

相关主题
fgetc - fgets - fputs - puts

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。

相关主题
clearerr - feof - ferror

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() 的返回值是打印的字符数,如果发生错误,则为负数。

相关主题
fprintf - puts - scanf - sprintf
语法
#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 的副本。

相关主题
feof - fflush - fgetc - fputc - getc - getchar - putchar - puts

putchar

[edit | edit source]
语法
#include <cstdio>
int putchar( int ch );

putchar() 函数将 ch 写入 stdout。代码

putchar( ch );

putc( ch, stdout );

相同。putchar() 的返回值是写入的字符,或者如果出现错误则为 EOF

相关主题
putc
语法
#include <cstdio>
int puts( char *str );

puts() 函数将 str 写入 stdout。puts() 在成功时返回非负值,或者在失败时返回 EOF

相关主题
fputs - gets - printf - putc

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 );
相关主题
fgets - fscanf - printf - sscanf

setbuf

[edit | edit source]
语法
#include <cstdio>
void setbuf( FILE *stream, char *buffer );

setbuf() 函数将流设置为使用 buffer,或者如果 buffer 为 NULL,则关闭缓冲。此函数预期缓冲区长度为 BUFSIZ 个字符 - 由于此函数不支持指定缓冲区大小,因此大于 BUFSIZ 的缓冲区将部分未被使用。

相关主题
fclose - fopen - setvbuf
语法
#include <cstdio>
int setvbuf( FILE *stream, char *buffer, int mode, size_t size );

函数 setvbuf() 将stream的缓冲区设置为buffer,大小为size。mode可以是以下之一:

  • _IOFBF,表示全缓冲
  • _IOLBF,表示行缓冲
  • _IONBF,表示不缓冲
相关主题
fflush - setbuf
语法
#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 );
相关主题
fprintf - printf
(标准 C 字符串和字符) atof - atoi - atol
语法
#include <cstdio>
int sscanf( const char *buffer, const char *format, ... );

sscanf() 函数与 scanf() 类似,区别在于输入从buffer读取。

相关主题
fscanf - scanf
语法
#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

相关主题
getc
(C++ I/O) putback

vprintf、vfprintf 和 vsprintf

[编辑 | 编辑源代码]
语法
#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 );
}
华夏公益教科书