一、Xmind整理:
二、课上练习:
练习1:全缓冲
//由于编译器优化,只打开不操作,此时不会真正申请缓冲区。
fputc('a', fp);
printf("%ld\n", fp->_IO_buf_end - fp->_IO_buf_base );
刷新条件:
1.缓冲区满 (要多写一个后才能刷新前4096个)
2.fflush函数,强制刷新输出流缓冲区
#include <stdio.h>
int fflush(FILE *stream);3.关闭流指针 fclose
4.主函数调用return
5.调用exit函数退出程序6.输入输出转换
7.……
功能:目前只要理解能退出程序即可
原型:
#include <stdlib.h>
void exit(int status);
参数:
int status:目前随便填一个int类型整数即可,例如 1 2 0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./fullbuf.txt","w");
if(NULL==fp)
{
perror("fopen");
return -1;
}
/*由于编译器优化,只打开不操作,此时不会真正申请缓冲区。
fputc('a',fp);
printf("%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);
*/
int i=0;
while(i<4096+1)
{
fputc('a',fp);//先放到缓存区中
i++;
}
while(1)
{
}
fclose(fp);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./fullbuf.txt","w");
if(NULL==fp)
{
perror("fopen");
return -1;
}
/*由于编译器优化,只打开不操作,此时不会真正申请缓冲区。
fputc('a',fp);
printf("%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);
*/
/*
int i=0;
while(i<4096+1)
{
fputc('a',fp);//先放到缓存区中
i++;
}
fputc('b',fp);
fflush(fp);
fputc('c',fp);
fflush(fp);
fputc('d',fp);
fflush(fp);
*/
fputc('e',fp);
exit(0);
while(1)
{
}
fclose(fp);
return 0;
}
练习2:行缓冲
printf("size=%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);
刷新条件:
1.缓冲区满 (要多写一个后才能刷新前4096个)
2.fflush函数,强制刷新输出流缓冲区
#include <stdio.h>
int fflush(FILE *stream);3.关闭流指针 fclose
4.主函数调用return
5.调用exit函数退出程序6.遇到\n字符
7.输入输出转换
功能:目前只要理解能退出程序即可
原型:
#include <stdlib.h>
void exit(int status);
参数:
int status:目前随便填一个int类型整数即可,例如 1 2 0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
char s1[20]="";
scanf("%s",s1);//从终端获取字符串,默认使用的就是stdin流指针
printf("s1=%s\n",s1);//将数据打印到终端,默认使用的就是stdout流指针
char s2[20]="";
fscanf(stdin,"%s",s2);//stdin代表从终端获取数据,此时与scanf完全等价
fprintf(stdout,"s2=%s\n",s2);//stdout代表将数据输出到终端,此时与printf完全等价
return 0;
}
练习3:无缓冲
无刷新条件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
/*
fputc('b',stderr);
printf("size=%ld\n",stderr->_IO_buf_end - stderr->_IO_buf_base);
*/
fputc('d',stderr);
perror("aaaa");
while(1);
return 0;
}
练习4:fputs
功能:将字符串输出到指定的文件中; fputs不会自动补充\n
原型:
#include <stdio.h>
int fputs(const char *s, FILE *stream);
int puts(const char *s);
char str[20] = "hello";
puts(str);
参数:
char *s:指定要输出的字符串的首地址;
FILE *stream:流指针;
返回值:
成功,返回非负数>=0;
失败,返回EOF;
练习5:fgets
功能:从指定文件中获取字符串
1.最多获取size-1个字节,因为fgets函数在停止读取后,会在有效字符的最后一个字节补\0
2.会获取空格;会获取\n字符
3.遇到\n字符后停止读取,且会获取\n字符
原型:
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
参数:
char *s:存储获取到的字符串;
int size:size-1
FILE *stream:流指针;
返回值:
成功,返回存储数据空间的首地址;
失败,返回NULL;
当读取到文件结尾,且没有任何数据被读取出来,返回NULL;
在文件中有如下数据:123456789, char str[9]; 会出现什么情况:A D
fgets(str, 10, fp);
printf("str=%s", str);
A. 123456789 B.123456789乱码 C.12345678 D.段错误
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
//打开文件,以读的方式打开文件
FILE* fp=fopen("./fputs.txt","r");
if(NULL==fp)
{
perror("fopen");
return -1;
}
char buf[20]="";
fgets(buf,20,fp);
printf("buf=%s\n",buf);
fgets(buf,20,fp);
printf("buf=%s\n",buf);
fclose(fp);
return 0;
}
1.使用fgets和fputs实现文件拷贝
2.使用fgets实现计算一个文件的大小
第一题:
#include <stdio.h>
#include <head.h>
int main(int argc, const char *argv[])
{
FILE* fp_r = fopen("./01_fopen.c", "r");
if(NULL == fp_r)
{
ERR_MSG("fopen");
return -1;
}
FILE* fp_w = fopen("./copy.c", "w");
if(NULL == fp_w)
{
ERR_MSG("fopen");
return -1;
}
//读一次,写一次,直到文件读取完毕
char buf[128] = "";
while(1)
{
if(fgets(buf, sizeof(buf), fp_r) == NULL)
break;
fputs(buf, fp_w);
}
printf("拷贝完毕\n");
if(fclose(fp_r) < 0)
{
ERR_MSG("fclose");
return -1;
}
fclose(fp_w);
return 0;
}
第二题:
#include <stdio.h>
#include <head.h>
int main(int argc, const char *argv[])
{
FILE* fp_r = fopen("./01_fopen.c", "r");
if(NULL == fp_r)
{
ERR_MSG("fopen");
return -1;
}
//循环读取,统计字节数
char str[20] = "";
int count = 0;
while(1)
{
if(fgets(str, sizeof(str), fp_r) == NULL)
break;
count+=strlen(str); //fgets停止读取后会自动在结尾补充\0
}
printf("count = %d\n", count);
if(fclose(fp_r) < 0)
{
ERR_MSG("fclose");
return -1;
}
return 0;
}
练习6:fwrite
功能:将数据的二进制形式写入到指定的文件中;
二进制形式--> 将数据拆分成一个一个的字节并转换成字符形式写入文件中
原型:
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
参数:
void *ptr:指定要输出的数据的首地址,是void*类型,代表任意类型,所以可以输出任意类型数据;
例如字符串char* 整型数组int* 构造类型
size_t size:每个数据所占的字节数大小;例如:
要输出的数据为int类型,则size==4
要输出的数据为short类型,则size==2
要输出的数据为char类型,则size==1
要输出的数据为构造类型,则size==sizeof(struct 结构体名);
size_t nmemb:指定要输出的数据个数,注意是个数,不是字节数
总大小为size*nmemb; 具体以什么作为整体无所谓,只要输出的结果总大小相同即可;
FILE *stream:流指针;
返回值:
成功,返回成功输出的数据个数,即nmemb;
失败, =0或者<nmemb
注意:
总大小为size*nmemb; 具体以什么作为整体无所谓,只要输出的结果总大小相同即可;
1.将整个数据作为整体,输出/输入一个数据 -->size = sizeof(数据), nmemb=1;
2.将一个字节作为整体,输出/输入sizeof个数据 -->size =1, nmemb = sizeof(数据)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./fwrite.txt","w");
if(NULL==fp)
{
perror("fopen");
return -1;
}
printf("fopen success\n");
int arr[3]={48,49,50};
//fprintf(fp,"%d",a);
size_t res=0;
res=fwrite(arr,4,3,fp);
printf("res=%ld\n",res);
fclose(fp);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
typedef struct a
{
char name[18];
int score;
}_A;
int main(int argc, const char *argv[])
{
FILE* fp=fopen("fwrite.txt","w");
if(NULL==fp)
{
perror("fopen");
return -1;
}
printf("fopen success\n");
_A t;
strcpy(t.name,"zhangsan");
t.score=48;
size_t res=fwrite(&t,sizeof(_A),1,fp);
printf("res=%ld\n",res);
_A brr[2]={
{"zahngsan",65},
{"wangwu",66}
};
//将数组中的单个元素作为整体,共输出两个数据,每个数据大小为sizeof(_A)
res=fwrite(brr,sizeof(_A),2,fp);
printf("res=%ld\n",res);
/*
//将brr当做整体,输出一个数据,每个数据的大小为sizeof(brr)
res=fwrite(brr,sizeof(brr),1,fp);
printf("res=%ld\n",res);
*/
/*
int arr[3]={48,49,50};
//fprintf(fp."%d",a);
size_t res=0;
res=fwrite(arr,4,3,fp);
printf("res=%ld\n",res);
*/
fclose(fp);
return 0;
}
练习7:fread
功能:将数据的二进制形式从指定文件中读取出来,转换成对应的数据
原型:
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
void *ptr:指定要将数据存储到什么位置,填对应位置的首地址。void*类型;
size_t size:每个数据所占的字节数大小;例如:
要输出的数据为int类型,则size==4
要输出的数据为short类型,则size==2
要输出的数据为char类型,则size==1
要输出的数据为构造类型,则size==sizeof(struct 结构体名);
size_t nmemb:指定要读取的数据个数,注意是个数,不是字节数
总大小为size*nmemb; 具体以什么作为整体无所谓,只要输出的结果总大小相同即可;
FILE *stream:流指针;
返回值:
成功,返回成功读取的数据个数,即nmemb;
失败或者读取到文件结尾的时候, =0或者<nmemb
练习8:fseek
功能:修改文件偏移量,到指定位置
原型:
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
参数:
FILE *stream:指定要修改哪个文件的偏移量;
long offset: 距离whence参数指定的偏移量。往前偏移填负数, 往后偏移填正数
int whence:
SEEK_SET, 文件开头位置
SEEK_CUR, 文件当前位置
SEEK_END 文件结尾位置
返回值:
成功,返回0;
失败,返回-1,更新errno;
//修改偏移量到文件开头
int res = fseek(fp, 0, SEEK_SET);
将文件偏移量修改到开头:
void rewind(FILE *stream); --->等价于 fseek(fp, 0, SEEK_SET);
注意:
任务1:若偏移量在文件开头,能否继续往前偏移 ---> 不行
任务2:若偏移量在文件结尾,能否继续往后偏移 ---> 可以
①若是以w w+ r+的方式打开,往结尾后偏移10个字节后写入,则会从第10个字节写入数据,且前面空余部分会自动补充^@
2.若是以a a+方式打开,往后偏移10个字节后写入,从文件结尾的最后一个有效字符的后面写入。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./fseek.txt","w+");
if(NULL==fp)
{
perror("fopen");
return -1;
}
fputc('a',fp);
fputc('b',fp);
fputc('c',fp);
int res=fseek(fp,0,SEEK_SET);
printf("res=%d\n",res);
int c=0;
c=fgetc(fp);
printf("c=%c %d\n",c,c);
return 0;
}
练习9:ftell
功能:获取文件当前位置距离文件开头的偏移量
原型:
#include <stdio.h>
long ftell(FILE *stream);
返回值:
成功,返回文件当前位置距离文件开头的偏移量;
失败,返回-1,更新errno;
将文件偏移量修改到结尾,获取文件偏移量的值,就是文件大小。
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
三、课后作业:
1. 使用fgets实现计算一个文件有几行
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE* fp=fopen("./fgets.txt","r");
if(NULL==fp)
{
perror("fopen");
return -1;
}
fseek(fp, 0, SEEK_END);
if(ftell(fp) == 0)
return 0;
fseek(fp, 0, SEEK_SET);
char buf[32] = "";
int count = 0;
while(1)
{
if(fgets(buf, sizeof(buf), fp) == NULL)
{
break;
}
if('\n' == buf[strlen(buf)-1])
count++;
}
if(buf[strlen(buf)-1] != '\n')
count++;
printf("文件共有%d行\n",count);
return 0;
}
2. 用fread和fwrite实现文件拷贝
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
FILE *fp = fopen("copy1.txt","r");
if(NULL == fp)
{
fprintf(stderr,"__%d__",__LINE__);
perror("fopen");
return -1;
}
FILE *fp_w = fopen("copy2.txt","w");
if(NULL == fp_w)
{
fprintf(stderr,"__%d__",__LINE__);
perror("fopen");
return -1;
}
char str[10];
while(1)
{
memset(str,0,sizeof(str));
if(fread(str,1,1,fp) == 0)
break;
fwrite(str,1,1,fp_w);
}
fclose(fp);
fclose(fp_w);
return 0;
}