深入详解标准C语言 IO

                                     标准 C I/O

函数列表:
clearerr() 清除错误
fclose() 关闭一个文件
feof() 如果到达文件尾(end-of-file)返回"True"(真)
ferror() 检查一个文件错误
fflush() 书写输出缓存的内容
fgetc() 从流获取一个字符
fgetpos() 获取文件位置指针
fgets() 从一个流获取一串字符
fopen() 打开一个文件
fprintf() 打印格式化的输出到一个文件
fputc() 写一个字符到一个文件
fputs() 写一个字符串到一个文件
fread() 从一个文件读取
freopen() 用一个不同的名称打开一个存在的流
fscanf() 从一个文件读取一个格式化的输入
fseek() 在文件中移动到一个指定的位置
fsetpos() 在一个文件中移动到一个指定的位置
ftell() 返回当前文件的位置指针
fwrite() 写入一个文件
getc() 从一个文件读取一个字符
getchar() 从STDIN(标准输入)读取一个字符
gets() 从STDIN(标准输入)读取一个字符串
perror() 显示当前错误的一个字符串版本到STDERR(标准错误输出)
printf() 写格式化的输出到STDOUT(标准输出)
putc() 写一个字符到一个流
putchar() 写一个字符到STDOUT(标准输出)
puts() 写一个字符串到STDOUT(标准输出)
remove() 清除一个文件
rename() 重命名一个文件
rewind() 移动文件位置指针到一个文件的开始处
scanf() 从STDIN(标准输入)读取格式化输入
setbuf() 设置一个指定流的缓冲区
setvbuf() 设置一个指定流的缓冲区和大小
sprintf() 写格式化的输出到缓冲区
sscanf() 从一个缓冲区读取格式化的输入
tmpfile() 返回一个到一个临时文件的指针
tmpnam() 返回一个独特的文件名
ungetc() 把一个字符放回一个流
vprintf, vfprintf, vsprintf 写用参数列表格式化输出

/////////////////////////////////////////////////////////////////////////////////////////

clearerr
语法:
  #include <stdio.h>
  void clearerr( FILE *stream );
clearerr函数重置错误标记和给出的流的EOF指针. 当发生错误时,你可以使用perror()判断实际上发生了何种错误.
ferror
语法:
  #include <stdio.h>
  int ferror( FILE *stream );
ferror()函数检查stream(流)中的错误, 如果没发生错误返回0,否则返回非零. 如果发生错误, 使用perror()检测发生什么错误.
perror
语法:   #include <stdio.h>
  void perror( const char *str );
1.perror()函数打印str(字符串)和一个相应的执行定义的错误消息到全局变量errno中.
2.perror ( )用来将上一个函数发生错误的原因输出到标准错误 (stderr) 。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno 的值来决定要输出的字符串。
3.在库函数中有个error变量,每个error值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了error的值。perror函数只是将你输入的一些信息和现在的error所对应的错误一起输出。
示例:
#include <stdio.h>
void main( void )
{
   int c;
   /* Create an error by writing to standard input. */
   putc('c', stdin );
   if( ferror( stdin ) )
   {
      perror( "Write error");
      clearerr(stdin);
   }
   /* See if read causes an error. */
   printf( "Will input cause an error? " );
   c = getc( stdin );
   if( ferror(stdin))
   {
      perror( "Read error" );
      clearerr(stdin);
   }
}
输出结果:
Write error: No error
Will input cause an error? n

fclose
语法:
  #include <stdio.h>
  int fclose( FILE *stream );
函数fclose()关闭给出的文件流, 释放已关联到流的所有缓冲区. fclose()执行成功时返回0,否则返回EOF.
feof
语法:
  #include <stdio.h>
  int feof( FILE *stream );
函数feof()在到达给出的文件流的文件尾时返回一个非零值.
fflush
语法:
  #include <stdio.h>
  int fflush( FILE *stream );
如果给出的文件流是一个输出流,那么fflush()把输出到缓冲区的内容写入文件. 如果给出的文件流是输入类型的,那么fflush()会清除输入缓冲区. fflush()在调试时很实用,特别是对于在程序中输出到屏幕前发生错误片段时. 直接调用 fflush( STDOUT )输出可以保证你的调试输出可以在正确的时间输出.
示例:
fflush的一个简单应用。
#include <stdio.h>
void main( void )
{
   int integer,temp=2;
   for( integer = 0; integer <5; integer++ )
   {
      puts("请输入一个正数:");
   scanf( "%d",&temp);
      printf( "%d/n",temp);
   }
}
输出结果:
请输入一个正数:
a
2
请输入一个正数:
2
请输入一个正数:
2
请输入一个正数:
2
请输入一个正数:
2

出现这种情况的原因是,这个程序首先会提示用户输入一个整数,然后等待用户输入,如果用户输入的是整数,程序会输出刚才输入的整数,并且再次提示用户输入一个整数,然后等待用户输入。但是若用户输入的不是整数(如小数或者字母),那么程序会不停地输出"请输入一个正数:"。这是因为 scanf("%d", &temp) 只能接受整数,如果用户输入了字母,则这个字母会遗留在“输入缓冲区”中。因为缓冲中有数据,故而 scanf 函数不会等待用户输入,直接就去缓冲中读取,可是缓冲中的却是字母,这个字母再次被遗留在缓冲中,如此反复,从而导致不停地输出“请输入一个正数:2”。解决的方法是在printf()语句后面加人fflush(stdin);语句即可。
fgetc
语法:
#include <stdio.h>
int fgetc( FILE *stream );
int _fgetchar( void );//从stdin中获取字符,然后指向下一个要获取的字符。
fgetc()函数返回来自stream(流)中的下一个字符,如果到达文件尾或者发生错误时返回EOF.
getc
语法:
#include <stdio.h>
int getc( FILE *stream );
getc()函数从stream(流)获取并返回下一个字符,如果到达文件尾返回EOF. getc()和fgetc()是一样的. 例如:

    char ch;
    FILE *input=fopen( "stuff", "r" );
   
    ch = getc( input );
    while( ch != EOF ) {
      printf( "%c", ch );
      ch = getc( input );
    }
1.fgetc和getc的区别在于调用getc函数时所用的参数fp不能是有副作用的表达式,而fgetc函数则可以,也就是说,getc可以被当作宏来调用,而fgetc只能作为函数来调用。 一般来说宏产生较大的代码,但是避免了函数调用的堆栈操作,因此,调用getc比调用fgetc耗费的时间少。
2.有副作用的表达式,指的是表达式执行后,会改变表达式中某些变量的值最简单的如++i,这个表达式执行后,i的值会改变,这样的表达式是不应该在宏调用里出现的,例如:
#define MACRO_SQRT(x) (x)*(x)
int func_sqrt(int x)
{
  return x * x;
}
上面是两个计算平方的方法,一个用宏,一个用函数
int i=2;
int a,b;
a=MACRO_SQRT(++i);
b=func_sqrt(++i);
cout < <a < <endl < <b;

a=16
b=25
在stdio.h中有以下定义:
#define getchar()         getc(stdin)//宏定义
_CRTIMP int __cdecl getc(FILE *);//函数定义
_CRTIMP int __cdecl fgetc(FILE *);//函数定义
因此getc有宏定义版本,而fgetc是函数。

getchar
语法:
  #include <stdio.h>
  int getchar( void );
getchar()函数从STDIN(标准输入)获取并返回下一个字符,如果到达文件尾返回EOF.

总结一下:_fgetchar(void)等同于fgetc(stdin),也等同于getchar(void),但_fgetchar是函数.

 int  getch(void);
 int  getche(void);
 int  _getch(void);
 int  _getche(void);
这四个函数都定义在conio.h中。
getch()函数从控制台(即你看见的那个黑色窗口)读取一个字符,但不会将该字符显示出来。
它的返回值:读取到的字符的ASCII。
关于这个函数,它和 getchar() 的区别是,假如你使用 getchar(),那么你可以输入 'a'+回车,此时它读到的是 'a';但你同样可以输入'a' 'b' 'c' 'd'.....+回车,意思就是你也可以输入好几个字符再按下回车,此时它读到的是第一个输入的字符;而 getch() 只要你输入一个字符,它就立即接收而不会等到你输入第2个字符;换句话说,getchar()是以回车换行符为结束标志,而 getch() 是直接从控制台接收字符,且 getchar() 会回显该字符而 getch() 不会。

fgets
语法:
  #include <stdio.h>
  char *fgets( char *str, int num, FILE *stream );
函数fgets()从给出的文件流中读取[num - 1]个字符并且把它们转储到str(字符串)中. fgets()在到达行末时停止,在这种情况下,str(字符串)将会被一个新行符结束. 如果fgets()达到[num - 1]个字符或者遇到EOF, str(字符串)将会以null结束.fgets()成功时返回str(字符串),失败时返回NULL.
gets
语法:
  #include <stdio.h>
  char *gets(char *str);
1.gets()函数从STDIN(标准输入)读取字符并把它们加载到str(字符串)里,直到遇到新行(/n)或到达EOF. 新行字符翻译为一个null中断符(/n转化为/0后,被存储到str中作为字符串的结束符). gets()的返回值是读入的字符串,如果错误返回NULL.
2.该函数可以无限读取,不会判断上限,所以程序员应该确保str的空间足够大,以便在执行读操作时不发生溢出。
示例:
#include <stdio.h>
#include <conio.h>
void main( void )
{
   int integer;
   char string[255];
    /* Read each word as a string. */
   printf( "Enter a sentence of two words with scanf: " );
   for( integer = 0; integer <2; integer++ )
   {
      scanf( "%s", string );
      printf( "%s/n", string );
   }
    /* You must flush the input buffer before using gets. */
   fflush( stdin );
   printf( "Enter the same sentence with gets: " );
   gets( string );
   printf( "%s/n", string );
   fflush(stdin);
   fgets(string,8,stdin);
   printf( "%s/n", string );
}
输出结果:
Enter a sentence of two words with scanf: how are you?
how
are
Enter the same sentence with gets: how are you?
how are you?
confident
confide

fgetpos
语法:
  #include <stdio.h>
  int fgetpos( FILE *stream, fpos_t *position );
  int fsetpos( FILE *stream, const fpos_t *pos );
fgetpos()函数保存给出的文件流(stream)的位置指针到给出的位置变量(position)中. position变量是fpos_t类型的(它在stdio.h中定义)并且是可以控制在FILE中每个可能的位置对象. fgetpos()执行成功时返回0,失败时返回一个非零值.
示例:
//test.cpp
#include <stdio.h>
void main( void )
{
   FILE   *stream;
   fpos_t pos;
   char   buffer[20];
   stream = fopen( "test.cpp", "rb" );
   fread( buffer, sizeof( char ), 10, stream );
   fgetpos( stream, &pos );
   printf( " %.10s/n", buffer );
  
   pos = 50;
   fsetpos( stream, &pos );
   fread( buffer, sizeof( char ), 10, stream );
   fgetpos( stream, &pos );
   printf( "%.10s/n",buffer );
   fclose( stream );
}
输出结果:
 #include <
  *stream;

fopen
语法:
  #include <stdio.h>
  FILE *fopen( const char *fname, const char *mode );
fopen()函数打开由fname(文件名)指定的文件, 并返回一个关联该文件的流.如果发生错误, fopen()返回NULL. mode(方式)是用于决定文件的用途(例如 用于输入,输出,等等)

Mode(方式) 意义
"r" 打开一个用于读取的文本文件
"w" 创建一个用于写入的文本文件
"a" 附加到一个文本文件
"rb" 打开一个用于读取的二进制文件
"wb" 创建一个用于写入的二进制文件
"ab" 附加到一个二进制文件
"r+" 打开一个用于读/写的文本文件
"w+" 创建一个用于读/写的文本文件
"a+" 打开一个用于读/写的文本文件
"rb+" 打开一个用于读/写的二进制文件
"wb+" 创建一个用于读/写的二进制文件
"ab+" 打开一个用于读/写的二进制文件
示例:
    char ch;
    FILE *input = fopen( "stuff", "r" );
    ch = getc( input );

fprintf
语法:
  #include <stdio.h>
  int fprintf( FILE *stream, const char *format [, argument ]...);
fprintf()函数根据指定的format(格式)(格式)发送信息(参数)到由stream(流)指定的文件. fprintf()只能和printf()一样工作. fprintf()的返回值是输出的字符数,发生错误时返回一个负值.

示例:

    char name[20] = "Mary";
    FILE *out;
    out = fopen( "output.txt", "w" );
    if( out != NULL )
      fprintf( out, "Hello %s/n", name );


使用feof()或ferror()判断到底发生哪个错误.
freopen
语法:
  #include <stdio.h>
  FILE *freopen( const char *fname, const char *mode, FILE *stream );
freopen()函数常用于再分配一个以存在的流给一个不同的文件和方式(mode).在调用本函数后,给出的文件流将会用mode(方式)指定的访问模式引用fname(文件名). freopen()的返回值是新的文件流,发生错误时返回NULL.
fscanf
语法:
  #include <stdio.h>
  int fscanf( FILE *stream, const char *format, ... );
函数fscanf()以scanf()的执行方式从给出的文件流中读取数据. fscanf()的返回值是事实上已赋值的变量的数,如果未进行任何分配时返回EOF.
rewind
语法:
  #include <stdio.h>
  void rewind( FILE *stream );
函数rewind()把文件指针移到由stream(流)指定的开始处, 同时清除和流相关的错误和EOF标记.
fseek
语法:
  #include <stdio.h>
  int fseek( FILE *stream, long offset, int origin );
函数fseek()为给出的流设置位置数据. origin的值应该是下列值其中之一(在stdio.h中定义):
名称 说明
SEEK_SET 从文件的开始处开始搜索
SEEK_CUR 从当前位置开始搜索
SEEK_END 从文件的结束处开始搜索
fseek()成功时返回0,失败时返回非零. 你可以使用fseek()移动超过一个文件,但是不能在开始处之前. 使用fseek()清除关联到流的EOF标记.
ftell
语法:
  #include <stdio.h>
  long ftell( FILE *stream );
ftell()函数返回stream(流)当前的文件位置,如果发生错误返回-1.
注意:fseek函数与ftell函数常常综合应用。
示例:
//test.cpp
#include <stdio.h>
void main( void )
{
   FILE *stream;
   char line[81];
   stream = fopen( "test.cpp", "r" );
   fseek( stream, 20L, SEEK_SET);
   fgets( line, 80, stream );
   printf( "%s", line );
   long temp=ftell(stream);
   printf("%ld/n",temp);
}
输出结果:
void main( void )
39

fwrite
语法:
  #include <stdio.h>
  int fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
fwrite()函数从数组buffer(缓冲区)中, 写count个大小为size(大小)的对象到stream(流)指定的流. 返回值是已写的对象的数量.
语法:
  #include <stdio.h>
  int fread( void *buffer, size_t size, size_t num, FILE *stream );
函数fread()读取[num]个对象(每个对象大小为size(大小)指定的字节数),并把它们替换到由buffer(缓冲区)指定的数组. 数据来自给出的输入流. 函数的返回值是读取的内容数量...
注意:fwrite 和fread常综合使用。
示例:
#include <stdio.h>
#include <memory.h>
void main( void )
{
   FILE *stream;
   char list[30];
   char temp[30];
   memset(list,0,sizeof(list));
   memset(temp,0,sizeof(temp));
   int  i, numread, numwritten;
   /* Open file in text mode: */
   if( (stream = fopen( "fread.out", "w+" )) != NULL )
   {
      for ( i = 0; i < 25; i++ )
         list[i] = (char)('z' - i);
      /* Write 25 characters to stream */
      numwritten = fwrite( list, sizeof( char ), 25, stream );
      printf( "Wrote %d items/n", numwritten );
      fclose( stream );

   }
   else
      printf( "Problem opening the file/n" );

   if( (stream = fopen( "fread.out", "r+" )) != NULL )
   {
      /* Attempt to read in 25 characters */
      numread = fread( temp, sizeof( char ), numwritten, stream );
      printf( "Number of items read = %d/n", numread );
      printf( "Contents of buffer = %s/n",temp );
      fclose( stream );
   }
   else
      printf( "File could not be opened/n" );
}
输出结果:
Wrote 25 items
Number of items read = 25
Contents of buffer = zyxwvutsrqponmlkjihgfedcb


printf
语法:
  #include <stdio.h>
  int printf( const char *format, ... );
printf()函数根据format(printf()格式转换的一般形式如下 %(flags)(width)(.prec)type )给出的格式打印输出到STDOUT(标准输出)和其它参数中.
printf()的返回值是打印的字符数,如果发生错误则返回一个负值.
字符串format(格式)由两类项目组成 - 显示到屏幕上的字符和定义printf()显示的其它参数. 基本上, 你可以指定一个包含文本在内的format(格式)字符串,也可以是映射到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 表示第二个参数(一个整数)应该放置在那里. 不同的"%-codes"表示不同的变量类型, 也可以限制变量的长度.
----------------------------------------------------------------------------------------
Code 格式
%a         浮点数、十六进制数字和p-记数法(C99)
%A     浮点数、十六进制数字和p-记法(C99)
%c     一个字符 
%d     有符号十进制整数 
%e     浮点数、e-记数法
%E     浮点数、E-记数法
%f       浮点数、十进制记数法  
%g     使用%e或%f中较短的一个
%G     使用%E或%f中较短的一个
%i         有符号十进制数(与%d相同)
%o     无符号八进制整数
%p     指针    
%s     字符串
%u     无符号十进制整数
%x     无符号十六进制数, 用小写字母
%X     无符号十六进制数, 用大写字母
%%     打印一个百分号
-----------------------------------------------------------------------------------------
%% 一个'%'符号
一个位于一个%和格式化命令间的整数担当着一个最小字段宽度说明符,并且加上足够多的空格或0使输出足够长. 如果你想填充0,在最小字段宽度说明符前放置0. 你可以使用一个精度修饰符,它可以根据使用的格式代码而有不同的含义.
用%e, %E和 %f,精度修饰符让你指定想要的小数位数. 例如,
               %12.6f
将会至少显示12位数字,并带有6位小数的浮点数.
用%g和 %G, 精度修饰符决定显示的有效数的位数最大值.
用%s,精度修饰符简单的表示一个最大的最大长度, 以补充句点前的最小字段长度.
所有的printf()的输出都是右对齐的,除非你在%符号后放置了负号. 例如,
     %-12.4f
将会显示12位字符,4位小数位的浮点数并且左对齐. 你可以修改带字母l和h%d, %i, %o, %u和 %x 等类型说明符指定长型和短型数据类型 (例如 %hd 表示一个短整数). %e, %f和 %g 类型说明符,可以在它们前面放置l指出跟随的是一个double. %g, %f和 %e 类型说明符可以置于字符'#'前保证出现小数点, 即使没有小数位. 带%x类型说明符的'#'字符的使用, 表示显示十六进制数时应该带'0x'前缀. 带%o类型说明符的'#'字符的使用, 表示显示八进制数时应该带一个'0'前缀.

示例:
#include<cstdio>
#include<stdlib.h>
int main()
{
    //for int
    int i=30122121;
    long i2=309095024l; //最后一位为小写 L
    short i3=30;
    unsigned i4=2123453;
    //输出30122121,162720211,1cba089,1CBA089,309095024,30,2123453
    //对于long型和为%ld,而short为%hd,unsigned为%u
    printf("%d,%o,%x,%X,%ld,%hd,%u/n",i,i,i,i,i2,i3,i4);//如果是:%l,%h,则输不出结果
    //输出30122121,309095024
    printf("%d,%ld/n",i,i2);//试验不出%ld和%d之间的差别,因为long和int都是4bytes
    //输出-24439,30
    printf("%hd,%hd/n",i,i3);//试验了%hd和%d之间的差别,因为short是2bytes,int为4bytes

    //for string and char
    char ch1='d'; //char一个字节
    unsigned char ch2=160; //还是一个字节
    char *str="Hello everyone!";
    //输出d,160,Hello everyone!
    printf("%c,%u,%s/n/n/n",ch1,ch2,str);//unsigned char超过128的没有字符对应
   
    //for float and double,unsigned and signed can not be used with double and float
    //float后面加 f/F
    float fl=2.566545445F;//or 2.566545445f 4个字节
    double dl=265.5651445; //8个字节
    long double dl2=2.5654441454;
    /*
      2.566545,2.655651e+002,265.565,265.5651445
      2.566545,2.655651E+002,265.565,265.565144
      2.56654549,2.6556514450e+002
      2.56654549e+000,265.5651445000
    */
    //%g没有e格式,默认6位包括小数点前面的数,
    //%f没有e格式,默认6位仅只小数点后面包含6位
    //%e采用e格式,默认6位为转化后的小数点后面的6位
    printf("%f,%e,%g,%.7f/n",fl,dl,dl,dl);
    printf("%f,%E,%G,%f/n",fl,dl,dl,dl);//%F is wrong
    printf("%.8f,%.10e/n",fl,dl);
    printf("%.8e,%.10f/n/n/n",fl,dl);


    //for point
    int *iP=&i;
    char *iP1=new char;
    void *iP2;//dangerous!
    printf("%p,%p,%p/n/n/n",iP,iP1,iP2);
   
    //其他知识:负号,表示左对齐(默认是右对齐);%6.3,6表示宽度,3表示精度
    char *s="Hello world!";
    printf(":%s: /n:%10s: /n:%.10s: /n:%-10s: /n:%.15s: /n:%-15s: /n:%15.10s: /n:%-15.10s:/n/n/n",
        s,s,s,s,s,s,s,s);
    double ddd=563.908556444;
    printf(":%g: /n:%10g: /n:%.10g: /n:%-10g: /n:%.15g: /n:%-15g: /n:%15.10g: /n:%-15.10g:/n/n/n",
        ddd,ddd,ddd,ddd,ddd,ddd,ddd,ddd);

    //还有一个特殊的格式%*.* ,这两个星号的值分别由第二个和第三个参数的值指定
    printf("%.*s /n", 8, "abcdefgggggg");
    printf("%*.*f   /n", 3,3, 1.25456f);
    system("pause");
    return 0;
}
输出结果:
30122121,162720211,1cba089,1CBA089,309095024,30,2123453
30122121,309095024
-24439,30
d,160,Hello everyone!


2.566545,2.655651e+002,265.565,265.5651445
2.566545,2.655651E+002,265.565,265.565144
2.56654549,2.6556514450e+002
2.56654549e+000,265.5651445000


0012FF7C,003830B8,CCCCCCCC


:Hello world!:
:Hello world!:
:Hello worl:
:Hello world!:
:Hello world!:
:Hello world!   :
:     Hello worl:
:Hello worl     :


:563.909:
:   563.909:
:563.9085564:
:563.909   :
:563.908556444:
:563.909        :
:    563.9085564:
:563.9085564    :


abcdefgg
1.255


putc
语法:
  #include <stdio.h>
  int putc( int ch, FILE *stream );
putc()函数把字符ch写到stream(流)中. 返回值是写入的字符, 发生错误时返回EOF. 例如:

    char ch;
    FILE *input;
    input = fopen( "temp.cpp", "r" );
    ch = getc( input );
    while( ch != EOF ) {
      printf( "%c", ch );
      ch = getc( input );
    }
显示"temp.cpp"的内容到屏幕.

putchar
语法:
  #include <stdio.h>
  int putchar( int ch );
#define putchar(_c)       putc((_c),stdout)
putchar()函数把ch写到STDOUT(标准输出). 代码putchar( ch )和 putc( ch, STDOUT )作用一样.
putchar()的返回值是被写的字符, 发生错误时返回EOF.

fputc
语法:
  #include <stdio.h>
  int fputc( int ch, FILE *stream );
函数fputc()把给出的字符ch写到给出的输出流. 返回值是字符, 发生错误时返回值是EOF.
注意:fputc只当做函数使用,而putc除有函数定义外,还有宏定义。
int _fputchar( int c );
_fputchar等同于putchar.
puts
语法:
  #include <stdio.h>
  int puts( char *str );
函数puts()把str(字符串)写到STDOUT(标准输出)上,puts()会自动换行. puts() 成功时返回非负值, 失败时返回EOF.
fputs
语法:
  #include <stdio.h>
  int fputs( const char *str, FILE *stream );
fputs()函数把str(字符串)指向的字符写到给出的输出流,fputs不会自动换行. 成功时返回非负值, 失败时返回EOF.
示例:
#include<stdio.h>
#include<conio.h>
void main()
{
    char ch;
    FILE *input;
    input = fopen( "test.cpp", "r" );
    ch = getc( input );
    while( ch != EOF )
 {
      //printf("%c",ch);
  // putc(ch,stdout);
  // putchar(ch);
 // _fputchar(ch);
    fputc(ch,stdout);
       ch = getc( input );
    }
 fclose(input);
 puts("How are you?");
 fputs("fine/n",stdout);
}
输出结果:
#include<stdio.h>
#include<conio.h>
void main()
{
    char ch;
    FILE *input;
    input = fopen( "test.cpp", "r
    ch = getc( input );
    while( ch != EOF )
        {
      //printf("%c",ch);
         // putc(ch,stdout);
         // putchar(ch);
        //      _fputchar(ch);
           fputc(ch,stdout);
       ch = getc( input );
    }
        fclose(input);
        puts("How are you?");
        fputs("fine/n",stdout);
}


How are you?
fine

remove
语法:
  #include <stdio.h>
  int remove( const char *fname );
remove()函数删除由fname(文件名)指定的文件. remove()成功时返回0,如果发生错误返回非零.
rename
语法:
  #include <stdio.h>
  int rename( const char *oldfname, const char *newfname );
函数rename()更改文件oldfname的名称为newfname. rename()成功时返回0,错误时返回非零.

scanf
语法:
  #include <stdio.h>
  int scanf( const char *format, ... );
 类似函数有
       int scanf(const char *format, ...);
       int fscanf(FILE *stream, const char *format, ...);//指定输入流
       int sscanf(const char *str, const char *format, ...);//指定缓存区
scanf()函数根据由format(格式)指定的格式从stdin(标准输入)读取,并保存数据到其它参数. 它和printf()有点类似. format(格式)字符串由控制字符,空白字符和非空白字符组成. 控制字符以一个%符号开始,如下:

控制字符 说明
%c 一个单一的字符
%d 一个十进制整数
%i 一个整数
%e, %f, %g 一个浮点数
%o 一个八进制数
%s 一个字符串
%x 一个十六进制数
%p 一个指针
%n 一个等于读取字符数量的整数
%u 一个无符号整数
%[] 一个字符集
%% 一个精度符号

1.scanf()读取匹配format(格式)字符串的输入. 当读取到一个控制字符, 它把值放置到下一个变量. 空白(tabs, 空格等等)会跳过. 非空白字符和输入匹配, 然后丢弃. 如果是一个在%符号和控制符间的数量, 那么只有指定数量的字符转换到变量中. 如果scanf()遇到一个字符集(用%[]控制字符表示), 那么在括号中的任意字符都会读取到变量中. scanf()的返回值是成功赋值的变量数量, 发生错误时返回EOF.
2.scanf()函数的一般格式为:scanf("格式字符串",输入项首地址表)
3.scanf的格式控制的一般形式为:%[*][宽度][F|N][h|l]类型字符
[]中的控制字符为可选项
4."*"表示该输入项读入后不赋予任何变量,即跳过该输入值。
5."宽度"表示输入读入字符的长度,对于整型表示截取相应宽度的数字赋给后面列表中的相应变量;对于字符型表示读入相应长度的字符后把第一个字符赋给相应的变量,其余的自动舍弃。例如scanf("%2d%3d",&a, &b);如果输入为12345则将12赋给a,将45赋给b;scanf("%2c%3c",&a, &b);如果输入为12345则将'1'赋给a,将'3'赋给b .
"%s" 整个输入作为一个串,并设置末尾的'/0'
"%ns",n为整数,读入的串最长不超过n,然后在末尾补'/0'
%nf 读入的浮点数最多有n位整数,位数多于n,会截断。
"%n[a-z]" 读入最多n个字符,如果遇到非a-z的字符,停止
"%[^=]" 读入任意多的字符,直到遇到"="停止
"%n[^=]" 读入"="号前的至多n 个字符
6.F 、N、h、l分别表示远指针、近指针、短整和长整型。
7.对于输入字符串还有一些比较有用的控制。
    例如经常需要读入一行字符串,而这串字符里面可能有空格、制表符等空白字符,如果直接用%s是不可以的,于是有些人就想到用gets(),当然这也是一种选择,但是懂C的人基本上都知道gets()是一个很危险的函数,而且很难控制,特别是与scanf()交替使用时前者的劣势更是一览无余,所以gets()一般是不推荐用的,其实用%[^/n]就可以很好的解决这个问题了,^表示"非",即读入其后面的字符就结束读入。这样想读入一行字符串直接用scanf("%[^/n]%*c",str);就可以了,
%*c的作用是读入/n,否则后面读入的将一直是/n。
所有对%s起作用的控制都可以用%[],比如%[0-9]表示只读入'0'到'9'之间的字符,%[a-zA-Z]表示只读入字母,
'-'是范围连接符,当然也可以直接列出你需要读入的字符。
如果你只需要读"abc"里面的字符就可以用%[abc] (或者%[cab]、%[acb]、%[a-c]、%[c-a].....),
如果想读入某个范围之外的字符串就在前面加一个'^',如:%[^a-z]就表示读入小写字母之外的字符。
例如从键盘输入的"1235ab86"中读取1235、86给n,有如下方法:
#include <stdio.h>
bool skip(){
     scanf("%*[^0-9]");
     return true;
}
void main()
{
      int n;
      while(skip() && scanf("%d", &n)!=EOF)
        printf("%d/n", n);
}
输出为:1235
        86

再重复一下几个注意:
1.scanf()函数中没有精度控制。如: scanf("%5.2f",&a); 是非法的。不能企图用此语句输入小数为2位的实数。
2.scanf中要求给出变量地址,如给出变量名则会出错如 scanf("%d",a);是非法的,应改为scnaf("%d",&a);才是合法的。
3.在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔则可用空格,TAB或回车作间隔。C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束。
4.在输入字符数据(%c)时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。例如:scanf("%c%c%c",&a,&b,&c);输入为:d e f则把'd'赋予a, ' (空格)'赋予b,'e'赋予c。因为%c 只要求读入一个字符,后面不需要用空格作为两个字符的间隔,因此把' '作为下一个字符送给b。只有当输入为:def 时,才能把'd'赋于a,'e'赋予b,'f'赋予c。 如果在格式控制中加入空格作为间隔,如 scanf ("%c %c %c",&a,&b,&c);则输入时各数据之间可加空格。我们用一些例子来说明一些规则:#include <stdio.h>
    void main()
    {      
       char a,b;      
       printf("input character a,b/n");     
       scanf("%c%c",&a,&b);   /*注意两个%c之间没有任何符号*/      
       printf("%c%c/n",a,b);
    }
由于scanf函数"%c%c"中没有空格,输入M N,结果输出只有M。而输入改为MN时则可输出MN两字符.
   #include <stdio.h>
   void main()
  { 
      char a,b;      
      printf("input character a,b/n");      
      scanf("%c %c",&a,&b); /*注意两个%c之间有个空格*/    
      printf("/n%c%c/n",a,b);
}
本例表示scanf格式控制串"%c %c"之间有空格时, 输入的数据之间可以有空格间隔。
5.如果格式控制串中有非格式字符则输入时也要输入该非格式字符。例如:scanf("%d,%d,%d",&a,&b,&c); 其中用非格式符“ , ”作间隔符,故输入时应为: 5,6,7 (与scanf 双引号之间的格式必须一样)又如: scanf("a=%d,b=%d,c=%d",&a,&b,&c);则输入应为 a=5,b=6,c=7如输入的数据与输出的类型不一致时,虽然编译能够通过,但结果将不正确。
6.#include<stdio.h>
void   main()
{    
 static int a[2][3]={{1,3,4},{7,9,6}};     
 int i,j,k;      
 for(k=1;k<=2;k++)      
 {
     printf("Please input num:");    
     scanf("%d %d",&i,&j);    
     if(i<2&&j<3)               
  printf("num=%d/n",a[i][j]);   
            else printf("Input is error,/n");     
 }       
 printf("programm is complete./n");
}
该程序运行时没有错误,但当把scanf("%d %d",&i,&j) 改为scanf("i=%d j=%d",&i,&j) 时,运行结果为:
Please input num:i=1 j=2
num=6
Please input num:num=6
programm is complete.
原本希望能重复第一行再输入,但程序已执行完了。
原因是:
第一次输入后没有象正常情况一样清除输入缓冲区,这样第二次执行scanf时,程序并没有让你输入而是直接读入上次输入的结果。解决方法是,在scanf之前加上fflush(stdin)清楚掉键盘缓冲区。

setbuf
语法:
  #include <stdio.h>
  void setbuf( FILE *stream, char *buffer );
setbuf()函数设置stream(流)使用buffer(缓冲区),如果buffer(缓冲区)是null,关闭缓冲. 如果使用非标准缓冲尺寸, 它应该由BUFSIZ字符决定长度.
setvbuf
语法:
  #include <stdio.h>
  int setvbuf( FILE *stream, char *buffer, int mode, size_t size );
函数setvbuf()设置用于stream(流)的缓冲区到buffer(缓冲区),其大小为size(大小). mode(方式)可以是:

_IOFBF, 表示完全缓冲
_IOLBF, 表示线缓冲
_IONBF, 表示无缓存
sprintf
语法:
  #include <stdio.h>
  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" );
sscanf
语法:
  #include <stdio.h>
  int sscanf( const char *buffer, const char *format, ... );
函数sscanf()和scanf()类似, 只是输入从buffer(缓冲区)中读取.
tmpfile
语法:
  #include <stdio.h>
  FILE *tmpfile( void );
函数tempfile()用一个独特的文件名打开一个临时文件,并返回一个到该文件的指针.如果发生错误则返回null.
tmpnam
语法:
  #include <stdio.h>
  char *tmpnam( char *name );
tmpnam()函数创建一个独特的文件名并保存在name中. tmpnam()最多可以调用TMP_MAX指定的次数.
ungetc
语法:
  #include <stdio.h>
  int ungetc( int ch, FILE *stream );
函数ungetc()把字符ch放回到stream(流)中.
vprintf, vfprintf和 vsprintf
语法:
  #include <stdarg.h>
  #include <stdio.h>
  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在STDARG.H中定义,并且也可以被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 );
    }

 

你可能感兴趣的:(c,Stream,File,buffer,input,语言)