cstdio,在C语言中称为stdio.h。该库使用所谓的流与物理设备(如键盘、打印机、终端)或系统支持的任何其他类型的文件一起操作。
在本文将会通过介绍函数参数,举出实际的简单例子来帮助大家快速上手使用函数。
目录
3、Formatted input/output(格式化的输入/输出)
4、Character input/output:(字符输入/输出)
5、Direct input/output(直接输入/输出)
一、流
在C语言的标准库stdio.h中,流(stream)是一个抽象的概念,用于表示输入和输出流。在C语言中,流是用来处理文件输入和输出的抽象实体,它可以是标准输入流(stdin)、标准输出流(stdout)或者文件流(file stream)。
、、stdio.h中定义了一系列函数和宏来操作流,例如fopen()用于打开文件流,fclose()用于关闭文件流,fread()和fwrite()用于读写文件流等。此外,还有一些用于控制流的函数和宏,如fflush()用于刷新输出缓冲区,feof()和ferror()用于检查文件结束符和错误标志等。
通过使用流,程序可以方便地进行文件的输入输出操作,无论是从键盘读取输入,还是向文件写入数据,都可以通过流来实现。流的使用使得文件操作变得更加灵活和方便,同时也提供了一种统一的接口来处理输入输出操作。
在程序运行时一般会使用以下三个流:
二、库函数
1、File access(文件访问)
fclose:
用于关闭文件与流的联系
/* fclose example */
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt","wt");
fprintf (pFile, "fclose example");
fclose (pFile);//成功返回0,失败返回EOF
return 0;
}
----------------------------------------------------我是分割线-------------------------------------------------------------
fflush :
在C语言中,当你向文件写入数据时,数据通常首先被存储在内存中的缓冲区中,而不是立即写入文件。fflush函数可以强制将缓冲区中的数据写入文件,以确保数据被及时保存。这在某些情况下特别重要,比如在程序终止之前需要确保所有数据都已经写入文件时。
/* fflush example */
#include <stdio.h>
char mybuffer[80];
int main()
{
FILE * pFile;
pFile = fopen ("example.txt","r+");
if (pFile == NULL) perror ("Error opening file");
else {
fputs ("test",pFile);
fflush (pFile); // flushing or repositioning required
fgets (mybuffer,80,pFile);
puts (mybuffer);
fclose (pFile);
return 0;
}
}
----------------------------------------------------我是分割线-------------------------------------------------------------
fopen:
打开文件
FILE * fopen ( const char * filename, const char * mode )
打开其名称在参数 filename 中指定的文件,并将其与流相关联,该流可在将来的操作中通过返回的 FILE 指针进行标识。文件名应该包含要打开的文件的名称的 C 字符串。其值应遵循运行环境的文件名规范。
对流执行的操作以及如何执行这些操作由 mode 参数定义。
以下为mode参数:
返回值:如果文件已成功打开,该函数将返回指向 FILE 对象的指针,该对象可用于在将来的操作中标识流。否则,将返回 null 指针。
/* fopen example */
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt","w");
if (pFile!=NULL)
{
fputs ("fopen example",pFile);
fclose (pFile);
}
return 0;
}
----------------------------------------------------我是分割线-------------------------------------------------------------
freopen:
在C语言中,freopen()函数用于重新指定一个已经打开的文件流的文件名和访问模式。这个函数可以用来重新定向一个已经打开的文件流,从而改变该文件流对应的文件。
FILE * freopen ( const char * filename, const char * mode, FILE * stream )
使用freopen()函数可以实现一些文件操作的功能,例如:
- 重新打开一个文件,从而关闭当前的文件流并将其重新指向另一个文件。
- 改变文件流的访问模式,例如从只读模式改为只写模式。
总之,freopen()函数提供了一种方便的方式来重新指定一个已经打开的文件流,从而改变其对应的文件和访问模式。
----------------------------------------------------我是分割线-------------------------------------------------------------
setbuf :
用于为流指定缓冲区,可以提高输入/输出操作的性能。该函数通常用于设置标准输入、标准输出或标准错误流的缓冲区。它接受三个参数:正在设置缓冲区的流、指向缓冲区的指针和缓冲区的大小。setbuf函数对于优化输入/输出操作的性能特别有用,特别是在处理大量数据时。
void setbuf ( FILE * stream, char * buffer )
/* setbuf example */
#include <stdio.h>
int main ()
{
char buffer[BUFSIZ];
FILE *pFile1, *pFile2;
pFile1=fopen ("myfile1.txt","w");
pFile2=fopen ("myfile2.txt","a");
setbuf ( pFile1 , buffer );
fputs ("This is sent to a buffered stream",pFile1);
fflush (pFile1);
setbuf ( pFile2 , NULL );
fputs ("This is sent to an unbuffered stream",pFile2);
fclose (pFile1);
fclose (pFile2);
return 0;
}
在此示例中,打开两个文件进行写入。与文件 myfile1.txt 关联的流设置为用户分配的缓冲区;对它执行写入操作;数据在逻辑上是流的一部分,但在调用 fflush 函数之前,它尚未写入设备。
示例中与文件 myfile2.txt 关联的第二个缓冲区设置为无缓冲,因此后续输出操作将尽快写入设备。
但是,一旦文件关闭,缓冲流和无缓冲流的最终状态是相同的(关闭文件会刷新其缓冲区)。
----------------------------------------------------我是分割线------------------------------------------------------------
setvbuf :
用于设置文件流的缓冲方式,使用 setvbuf
可以控制文件流的缓冲行为,这对于低级 I/O 或对性能有严格要求的程序非常有用。
int setvbuf ( FILE * stream, char * buffer, int mode, size_t size )
详细mode:
返回值:如果成功,函数返回 0;否则,返回一个非零值。
/* setvbuf example */
#include <stdio.h>
int main ()
{
FILE *pFile;
pFile=fopen ("myfile.txt","w");
setvbuf ( pFile , NULL , _IOFBF , 1024 );
// File operations here
fclose (pFile);
return 0;
}
在此示例中,将创建一个名为 myfile.txt 的文件,并为关联的流请求 1024 字节的完整缓冲区,因此,只有在每次填充 1024 字节缓冲区时,才应将输出到此流的数据写入文件。
2、Operations on files(对文件的操作)
remove:
删除文件
int remove ( const char * filename );
返回值:如果文件已成功删除,则返回零值。失败时,将返回非零值
#include <stdio.h>
int main ()
{
if( remove( "myfile.txt" ) != 0 )
perror( "Error deleting file" );
else
puts( "File successfully deleted" );
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
rename:
将 oldname 指定的文件或目录的名称更改为 newname。
int rename ( const char * oldname, const char * newname );
返回值:如果文件重命名成功,则返回零值。失败时,将返回非零值。
#include <stdio.h>
int main ()
{
int result;
char oldname[] ="oldname.txt";
char newname[] ="newname.txt";
result= rename( oldname , newname );
if ( result == 0 )
puts ( "File successfully renamed" );
else
perror( "Error renaming file" );
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
tmofile:
打开临时文件。创建一个临时二进制文件,打开以供更新(“wb+”模式,有关详细信息,请参见 fopen),其文件名保证与任何其他现有文件不同。当流关闭 (fclose) 或程序正常终止时,创建的临时文件会自动删除。如果程序异常终止,是否删除文件取决于具体的系统和库实现。
FILE * tmpfile ( void )
返回值:如果成功,该函数将返回指向创建的临时文件的流指针。失败时,返回 NULL。
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer [256];
FILE * pFile;
pFile = tmpfile ();
do {
if (!fgets(buffer,256,stdin)) break;
fputs (buffer,pFile);
} while (strlen(buffer)>1);
rewind(pFile);
while (!feof(pFile)) {
if (fgets (buffer,256,pFile) == NULL) break;
fputs (buffer,stdout);
}
fclose (pFile);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
tmpnam:
生成临时文件名。返回一个字符串,其中包含与任何现有文件的名称不同的文件名,因此适合安全地创建临时文件,而不会有覆盖现有文件的风险。
char * tmpnam ( char * str );
#include <stdio.h>
int main ()
{
char buffer [L_tmpnam];
char * pointer;
tmpnam (buffer);
printf ("Tempname #1: %s\n",buffer);
pointer = tmpnam (NULL);
printf ("Tempname #2: %s\n",pointer);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
3、Formatted input/output(格式化的输入/输出)
fprintf:
将按格式指向的 C 字符串写入流。如果 format 包含格式说明符(以 % 开头的子序列),则格式后面的附加参数将格式化并插入到生成的字符串中,以替换它们各自的说明符。
int fprintf ( FILE * stream, const char * format, ... );
/* fprintf example */
#include <stdio.h>
int main ()
{
FILE * pFile;
int n;
char name [100];
pFile = fopen ("myfile.txt","w");
for (n=0 ; n<3 ; n++)
{
puts ("please, enter a name: ");
gets (name);
fprintf (pFile, "Name %d [%-10.10s]\n",n+1,name);
}
fclose (pFile);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
fscanf:
从流中读取数据,并根据参数格式将其存储到其他参数所指向的位置。
int fscanf ( FILE * stream, const char * format, ... );
/* fscanf example */
#include <stdio.h>
int main ()
{
char str [80];
float f;
FILE * pFile;
pFile = fopen ("myfile.txt","w+");
fprintf (pFile, "%f %s", 3.1416, "PI");
rewind (pFile);
fscanf (pFile, "%f", &f);
fscanf (pFile, "%s", str);
fclose (pFile);
printf ("I have read: %f and %s \n",f,str);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
snprintf :
将C 字符串存储在 s 指向的缓冲区中(将 n 作为要填充的最大缓冲区容量)。
int snprintf ( char * s, size_t n, const char * format, ... );
/* snprintf example */
#include <stdio.h>
int main ()
{
char buffer [100];
int cx;
cx = snprintf ( buffer, 100, "The half of %d is %d", 60, 60/2 );
if (cx>=0 && cx<100) // check returned value
snprintf ( buffer+cx, 100-cx, ", and the half of that is %d.", 60/2/2 );
puts (buffer);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
sprintf:
功能与snprintf相似,但是没有snprintf安全。
int sprintf ( char * str, const char * format, ... );
/* sprintf example */
#include <stdio.h>
int main ()
{
char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
printf ("[%s] is a string %d chars long\n",buffer,n);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
sscanf:
从字符串中读取格式化数据,从 s 读取数据,并根据参数格式将它们存储到附加参数给出的位置,就像使用 scanf 一样,但从 s 读取数据而不是标准输入 (stdin)。
int sscanf ( const char * s, const char * format, ...);
/* sscanf example */
#include <stdio.h>
int main ()
{
char sentence []="Rudolph is 12 years old";
char str [20];
int i;
sscanf (sentence,"%s %*s %d",str,&i);//添加了*的部分会被忽略,不会被参数获取
printf ("%s -> %d\n",str,i);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vfprintf:
将格式化数据从变量参数列表写入流
int vfprintf ( FILE * stream, const char * format, va_list arg );
/* vfprintf example */
#include <stdio.h>
#include <stdarg.h>
void WriteFormatted (FILE * stream, const char * format, ...)
{
va_list args;
va_start (args, format);
vfprintf (stream, format, args);
va_end (args);
}
int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt","w");
WriteFormatted (pFile,"Call with %d variable argument.\n",1);
WriteFormatted (pFile,"Call with %d variable %s.\n",2,"arguments");
fclose (pFile);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vfscanf:
将格式化数据从流读取到变量参数列表中,从流中读取数据,并根据参数格式将它们存储到 arg 标识的变量参数列表中元素所指向的位置。
int vfscanf ( FILE * stream, const char * format, va_list arg );
/* vfscanf example */
#include <stdio.h>
#include <stdarg.h>
void ReadStuff (FILE * stream, const char * format, ...)
{
va_list args;
va_start (args, format);
vfscanf (stream, format, args);
va_end (args);
}
int main ()
{
FILE * pFile;
int val;
char str[100];
pFile = fopen ("myfile.txt","r");
if (pFile!=NULL) {
ReadStuff ( pFile, " %s %d ", str, &val );
printf ("I have read %s and %d", str, val);
fclose (pFile);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vprintf:
将格式化数据从变量参数列表打印到 stdout,将 format 指向的 C 字符串写入标准输出 (stdout),以与 printf 相同的方式替换任何格式说明符,但使用 arg 标识的变量参数列表中的元素,而不是其他函数参数。
int vprintf ( const char * format, va_list arg );
/* vprintf example */
#include <stdio.h>
#include <stdarg.h>
void WriteFormatted ( const char * format, ... )
{
va_list args;
va_start (args, format);
vprintf (format, args);
va_end (args);
}
int main ()
{
WriteFormatted ("Call with %d variable argument.\n",1);
WriteFormatted ("Call with %d variable %s.\n",2,"arguments");
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vscanf:
将格式化数据读入变量参数列表,从标准输入 (stdin) 读取数据,并根据参数格式将其存储到由 arg 标识的变量参数列表中的元素所指向的位置。
int vscanf ( const char * format, va_list arg )
/* vscanf example */
#include <stdio.h>
#include <stdarg.h>
void GetMatches ( const char * format, ... )
{
va_list args;
va_start (args, format);
vscanf (format, args);
va_end (args);
}
int main ()
{
int val;
char str[100];
printf ("Please enter a number and a word: ");
fflush (stdout);
GetMatches (" %d %99s ", &val, str);
printf ("Number read: %d\nWord read: %s\n", val, str);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vsnprintf:
将格式化数据从变量参数列表写入大小缓冲区,使用在 printf 上使用 format 时打印的相同文本组成一个字符串,但使用 arg 标识的变量参数列表中的元素而不是其他函数参数,并将生成的内容作为 C 字符串存储在由 s 指向的缓冲区中(将 n 作为要填充的最大缓冲区容量)。
int vsnprintf (char * s, size_t n, const char * format, va_list arg );
/* vsnprintf example */
#include <stdio.h>
#include <stdarg.h>
void PrintFError ( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsnprintf (buffer,256,format, args);
perror (buffer);
va_end (args);
}
int main ()
{
FILE * pFile;
char szFileName[]="myfile.txt";
pFile = fopen (szFileName,"r");
if (pFile == NULL)
PrintFError ("Error opening '%s'",szFileName);
else
{
// file successfully open
fclose (pFile);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vsprintf:
将格式化数据从变量参数列表写入字符串,使用在 printf 上使用 format 时打印的相同文本组成一个字符串,但使用 arg 标识的变量参数列表中的元素而不是其他函数参数,并将生成的内容作为 C 字符串存储在 s 指向的缓冲区中。
int vsprintf (char * s, const char * format, va_list arg );
/* vsprintf example */
#include <stdio.h>
#include <stdarg.h>
void PrintFError ( const char * format, ... )
{
char buffer[256];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
perror (buffer);
va_end (args);
}
int main ()
{
FILE * pFile;
char szFileName[]="myfile.txt";
pFile = fopen (szFileName,"r");
if (pFile == NULL)
PrintFError ("Error opening '%s'",szFileName);
else
{
// file successfully open
fclose (pFile);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
vsscanf:
将格式化数据从字符串读取到变量参数列表中,从 s 读取数据,并根据参数格式将它们存储到 arg 标识的变量参数列表中元素所指向的位置。
int vsscanf ( const char * s, const char * format, va_list arg );
/* vsscanf example */
#include <stdio.h>
#include <stdarg.h>
void GetMatches ( const char * str, const char * format, ... )
{
va_list args;
va_start (args, format);
vsscanf (str, format, args);
va_end (args);
}
int main ()
{
int val;
char buf[100];
GetMatches ( "99 bottles of beer on the wall", " %d %s ", &val, buf);
printf ("Product: %s\nQuantity: %d\n", buf, val);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
4、Character input/output:(字符输入/输出)
fgetc:
从流中获取字符。
int fgetc ( FILE * stream );
/* fgetc example: money counter */
#include <stdio.h>
int main ()
{
FILE * pFile;
int c;
int n = 0;
pFile=fopen ("myfile.txt","r");
if (pFile==NULL) perror ("Error opening file");
else
{
do {
c = fgetc (pFile);
if (c == '$') n++;
} while (c != EOF);
fclose (pFile);
printf ("The file contains %d dollar sign characters ($).\n",n);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
fgets:
从流中获取字符串。
char * fgets ( char * str, int num, FILE * stream );
/* fgets example */
#include <stdio.h>
int main()
{
FILE * pFile;
char mystring [100];
pFile = fopen ("myfile.txt" , "r");
if (pFile == NULL) perror ("Error opening file");
else {
if ( fgets (mystring , 100 , pFile) != NULL )
puts (mystring);
fclose (pFile);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
fputc:
将字符写入流。
int fputc ( int character, FILE * stream );
/* fputc example: alphabet writer */
#include <stdio.h>
int main ()
{
FILE * pFile;
char c;
pFile = fopen ("alphabet.txt","w");
if (pFile!=NULL) {
for (c = 'A' ; c <= 'Z' ; c++)
fputc ( c , pFile );
fclose (pFile);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
fputs:
将字符串写入流。
int fputs ( const char * str, FILE * stream );
/* fputs example */
#include <stdio.h>
int main ()
{
FILE * pFile;
char sentence [256];
printf ("Enter sentence to append: ");
fgets (sentence,256,stdin);
pFile = fopen ("mylog.txt","a");
fputs (sentence,pFile);
fclose (pFile);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
getc:
从流中获取字符
int getc ( FILE * stream );
/* getc example: money counter */
#include <stdio.h>
int main ()
{
FILE * pFile;
int c;
int n = 0;
pFile=fopen ("myfile.txt","r");
if (pFile==NULL) perror ("Error opening file");
else
{
do {
c = getc (pFile);
if (c == '$') n++;
} while (c != EOF);
fclose (pFile);
printf ("File contains %d$.\n",n);
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
getchar:
从 stdin 获取字符,返回读取的字符。
int getchar ( void );
/* getchar example : typewriter */
#include <stdio.h>
int main ()
{
int c;
puts ("Enter text. Include a dot ('.') in a sentence to exit:");
do {
c=getchar();
putchar (c);
} while (c != '.');
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
gets:
从 stdin 获取字符串,返回获取的字符串(终止 null 字符会自动追加到复制到 str 的字符之后)
char * gets ( char * str );
- [注意:此函数在 C 或 C++ 中不再可用(从 C11 和 C++14 开始)]
/* gets example */
#include <stdio.h>
int main()
{
char string [256];
printf ("Insert your full address: ");
gets (string); // warning: unsafe (see fgets instead)
printf ("Your address is: %s\n",string);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
putc:
将字符写入流(字符被写在流的内部位置指示器指示的位置,然后自动前进一个)
int putc ( int character, FILE * stream );
/* putc example: alphabet writer */
#include <stdio.h>
int main ()
{
FILE * pFile;
char c;
pFile=fopen("alphabet.txt","wt");
for (c = 'A' ; c <= 'Z' ; c++) {
putc (c , pFile);
}
fclose (pFile);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
putchar:
将字符写入 stdout(等价于使用 stdout 作为第二个参数调用 putc)
int putchar ( int character );
/* putchar example: printing the alphabet */
#include <stdio.h>
int main ()
{
char c;
for (c = 'A' ; c <= 'Z' ; c++) putchar (c);
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
puts:
将字符串写入 stdout
int puts ( const char * str );
/* puts example : hello world! */
#include <stdio.h>
int main ()
{
char string [] = "Hello world!";
puts (string);
}
----------------------------------------------------我是分割线------------------------------------------------------------
ungetc:
从流中取消获取字符
int ungetc(int c, FILE *stream);
/* ungetc example */
#include <stdio.h>
int main ()
{
FILE * pFile;
int c;
char buffer [256];
pFile = fopen ("myfile.txt","rt");
if (pFile==NULL) perror ("Error opening file");
else while (!feof (pFile)) {
c=getc (pFile);
if (c == EOF) break;
if (c == '#') ungetc ('@',pFile);
else ungetc (c,pFile);
if (fgets (buffer,255,pFile) != NULL)
fputs (buffer,stdout);
else break;
}
return 0;
}
----------------------------------------------------我是分割线------------------------------------------------------------
5、Direct input/output(直接输入/输出)
fread:
从流中读取 count 元素的数组,每个元素的大小为 bytes,并将它们存储在 ptr 指定的内存块中。
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
/* fread example: read an entire file */
#include <stdio.h>
#include <stdlib.h>
int main () {
FILE * pFile;
long lSize;
char * buffer;
size_t result;
pFile = fopen ( "myfile.bin" , "rb" );
if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
/* the whole file is now loaded in the memory buffer. */
// terminate
fclose (pFile);
free (buffer);
return 0;
}
将 myfile.bin 加载到动态分配的内存缓冲区中,该缓冲区可用于将文件的内容作为数组进行操作。
----------------------------------------------------我是分割线------------------------------------------------------------
fwrite:
从 ptr 指向的内存块写入一个 count 元素数组,每个元素的大小为 Bytes 字节。
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
/* fwrite example : write buffer */
#include <stdio.h>
int main ()
{
FILE * pFile;
char buffer[] = { 'x' , 'y' , 'z' };
pFile = fopen ("myfile.bin", "wb");
fwrite (buffer , sizeof(char), sizeof(buffer), pFile);
fclose (pFile);
return 0;
}
创建一个名为 myfile.bin 的文件,并将缓冲区的内容存储到其中。char类型元素是1字节,所以直接用sizeof计算得到的就是数组的大小。
6、Error-handling(错误处理)
clearerr:
清除错误指示器。
void clearerr ( FILE * stream );
#include <stdio.h>
int main() {
FILE *pFile;
pFile = fopen("myfile.txt", "r"); // 尝试以只读方式打开文件
if (pFile == NULL) {
perror("Error opening file"); // 如果打开文件失败,输出错误信息
} else {
fputc('x', pFile); // 向文件中写入字符 'x'
if (ferror(pFile)) {
printf("Error Writing to myfile.txt\n"); // 如果写入文件时发生错误,输出错误信息
clearerr(pFile); // 清除文件错误标志
}
fgetc(pFile); // 从文件中读取一个字符
if (!ferror(pFile)) {
printf("No errors reading myfile.txt\n"); // 如果读取文件时没有发生错误,输出成功信息
}
fclose(pFile); // 关闭文件
}
return 0;
}
程序打开一个名为 myfile.txt 的现有文件进行读取,并导致尝试在其上写入时出现 I/O 错误。使用 clearerr 清除该错误,因此第二次错误检查返回 false。这段代码主要演示了文件操作中的错误处理方式,包括文件打开失败的处理、写入错误的处理、读取错误的处理以及关闭文件。
----------------------------------------------------我是分割线------------------------------------------------------------
feof:
检查是否设置了与流关联的文件结束指示符,如果设置了,则返回与零不同的值。
int feof ( FILE * stream );
/* feof example: byte counter */
#include <stdio.h>
int main ()
{
FILE * pFile;
int n = 0;
pFile = fopen ("myfile.txt","rb");
if (pFile==NULL) perror ("Error opening file");
else
{
while (fgetc(pFile) != EOF) {
++n;
}
if (feof(pFile)) {
puts ("End-of-File reached.");
printf ("Total number of bytes read: %d\n", n);
}
else puts ("End-of-File was not reached.");
fclose (pFile);
}
return 0;
}
该程序中打开名为 myfile.txt 的文件,并通过逐个读取所有字符来计算它包含的字符数。程序检查是否已到达文件末尾,如果是,则打印读取的总字节数。
----------------------------------------------------我是分割线------------------------------------------------------------
ferror:
检查是否设置了与流关联的错误指示器,如果设置了,则返回与零不同的值。通常由对失败的流的先前操作设置,并通过调用 clearerr、rewind 或 freopen 来清除。
ferror
函数用于检查文件流的错误标志。在 C 语言中,文件流通常是通过 FILE
结构指针进行操作的。ferror
函数的返回值表示了文件流的错误标志
/* ferror example: writing error */
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile=fopen("myfile.txt","r");
if (pFile==NULL) perror ("Error opening file");
else {
fputc ('x',pFile);
if (ferror (pFile))
printf ("Error Writing to myfile.txt\n");
fclose (pFile);
}
return 0;
}
尝试打开一个名为 "myfile.txt" 的文件,并向文件中写入字符 'x'。然后使用 ferror
函数来检查文件流的错误标志,以确定文件操作是否发生了错误。如果发生了错误,则输出相应的错误信息。最后关闭文件并返回 0。
(这段代码的作用是尝试向只读模式打开的文件中写入数据,这是一个错误的操作。因为文件以只读模式打开,所以写入操作会失败,ferror
函数会检测到错误,并输出相应的错误信息。)
下面是对该代码的详细讲解:
----------------------------------------------------我是分割线------------------------------------------------------------
perror:
打印错误消息,将 errno 的值解释为错误消息,并将其打印到 stderr(标准错误输出流,通常是控制台),如果参数 str 不是空指针,则打印 str,后跟冒号 (:) 和空格。然后,无论 str 是否为 null 指针,都会打印生成的错误描述,后跟换行符 ('\n')。
perror 应在产生错误后立即调用,否则可能会被调用其他函数覆盖。
void perror ( const char * str );
/* perror example */
#include <stdio.h>
int main ()
{
FILE * pFile;
pFile=fopen ("unexist.ent","rb");
if (pFile==NULL)
perror ("The following error occurred");
else
fclose (pFile);
return 0;
}
7、Types(类型)
FILE:
FILE
类型是 C 语言中用于表示文件流的结构类型。它通常用于打开、读取、写入和关闭文件。FILE
类型是通过 <stdio.h>
头文件定义的,它提供了一组函数来操作文件流。
以下是一个简单的例子,演示了如何使用 FILE
类型来打开、读取和关闭文件:
#include <stdio.h>
int main() {
FILE *pFile;
char buffer[100];
pFile = fopen("example.txt", "r"); // 以只读模式打开文件
if (pFile == NULL) {
perror("Error opening file");
} else {
if (fgets(buffer, 100, pFile) != NULL) { // 从文件中读取内容到 buffer
printf("Read from file: %s", buffer);
} else {
perror("Error reading from file");
}
fclose(pFile); // 关闭文件
}
return 0;
}
我们首先声明了一个 FILE
类型的指针 pFile
,用于表示文件流。然后使用 fopen
函数以只读模式打开名为 "example.txt" 的文件,如果打开失败则输出错误信息。接着使用 fgets
函数从文件中读取内容到 buffer
,并输出到控制台。最后使用 fclose
函数关闭文件。
----------------------------------------------------我是分割线------------------------------------------------------------
fpos_t:
fpos_t
是 C 语言标准库中用来表示文件位置的类型。它通常用于存储文件流的位置,并且可以在文件的定位和操作中使用。
fpos_t
类型的具体实现可能因平台而异,但通常是一个结构或者整数类型。
#include <stdio.h>
int main() {
FILE *pFile;
fpos_t position;
pFile = fopen("example.txt", "r"); // 以只读模式打开文件
if (pFile == NULL) {
perror("Error opening file");
} else {
fgetpos(pFile, &position); // 获取当前文件位置
printf("Current position: %lld\n", (long long)position);
fseek(pFile, 10, SEEK_SET); // 设置文件位置到偏移量为 10 的位置
fgetpos(pFile, &position); // 获取新的文件位置
printf("New position: %lld\n", (long long)position);
fclose(pFile); // 关闭文件
}
return 0;
}
在这个例子中,我们首先声明了一个 fpos_t
类型的变量 position
,用于存储文件位置。然后使用 fopen
函数以只读模式打开名为 "example.txt" 的文件,如果打开失败则输出错误信息。接着使用 fgetpos
函数获取当前文件位置,并输出到控制台。然后使用 fseek
函数将文件位置设置到偏移量为 10 的位置,并再次使用 fgetpos
函数获取新的文件位置,并输出到控制台。最后使用 fclose
函数关闭文件。
----------------------------------------------------我是分割线------------------------------------------------------------
size_t:
无符号整形的别名,相当于unsigned int 。
二、小结
在本篇博客中,我们深入探讨了 <stdio.h>
头文件在 C 语言中的重要性以及它所提供的丰富功能。我们首先介绍了该头文件中定义的一些常见函数,例如 fopen
、fclose
、fread
、fwrite
等,这些函数为我们提供了对文件的打开、关闭、读取和写入等操作。接着我们讨论了 FILE
类型和 fpos_t
类型,它们分别用于表示文件流和文件位置,为我们在文件操作中提供了更多的灵活性和控制。
通过本篇博客的学习,我们不仅对 <stdio.h>
头文件有了更深入的了解,还学会了如何使用它提供的函数和类型来进行文件的操作。文件操作在实际的编程工作中是非常常见的,因此对于 <stdio.h>
头文件的掌握将有助于我们更好地处理文件相关的任务。
希望本篇博客能够帮助读者更好地理解 <stdio.h>
头文件,并在日后的编程工作中能够更加熟练地运用其中提供的函数和类型。关于stdio.h中关于C语言中的宏定义将会在之后的文章进行讲解。如果你有任何关于 C 语言文件操作或者其他编程相关的问题,都可以随时留言交流。感谢阅读!