C语言目录:
1. 概述
2. 数据类型
3. 量
4. 运算符
5. 流程控制
6. 函数
7. C程序编译过程
8. 文件
9. 内存管理
文件流:C语言将文件看做一个字符序列,即文件是由若干字符组成的字符流
文件内容以ASCII码格式存放,一个字节存放一个ASCII码,代表一个字符 ,但占用存储空间较多
.c
文件就是以文本文件形式存放的
文件内容以补码格式存放,占用存储空间少。
数据按其内存中的存储形式原样存放
.exe
文件就是以二进制文件形式存放
#include
int main(){
/*
* 以文本形式存储
* 会将每个字符先转换为对应的ASCII,
* 然后再将ASCII码的二进制存储到计算机中
*/
int num = 666;
FILE *fa = fopen("ascii.txt", "w");
fprintf(fa, "%d", num);
fclose(fa);
/*
* 以二进制形式存储
* 会将666的二进制直接存储到文件中
*/
FILE *fb = fopen("bin.txt", "w");
fwrite(&num, 4, 1, fb);
fclose(fb);
return 0;
}
FILE
结构体C语言中存放文件属性的结构体(缓冲区和文件读写状态),所有的文件操作都是通过
FILE
结构体完成的,只能通过指针访问属性
struct _iobuf {
char *_ptr; //文件输入的下一个位置
int _cnt; //当前缓冲区的相对位置
char *_base; //文件的起始位置)
int _flag; //文件标志
int _file; //文件的有效性验证
int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
int _bufsiz; // 缓冲区大小
char *_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;
建立程序和文件之间的通信通道,并为文件系统建立缓冲
所在文件:stdio.h
FILE *fopen(const char *filename,const char *mode);
//以mode的方式,打开filename命名的文件,返回一个指向该文件缓冲的FILE结构体指针
FILE *fp = fopen("路径","w");
参数/返回值 | 含义 |
---|---|
char *filename |
要打开或者创建文件的路径 |
mode |
打开文件的方式 |
FILE |
返回指向文件缓冲区的指针,用于操作文件 |
mode | 文件类型 | 操作 | 文件不存在 | 文件存在 |
---|---|---|---|---|
r | 文本文件 | 读取 | 出错 | 打开文件 |
w | 文本文件 | 写入 | 创建新文件 | 覆盖原文件 |
a | 文本文件 | 追加 | 创建新文件 | 原文件后追加 |
r+ | 文本文件 | 读取/写入 | 出错 | 打开文件 |
w+ | 文本文件 | 读取/写入 | 创建新文件 | 覆盖原文件 |
a+ | 文本文件 | 读取/追加 | 创建新文件 | 原文件后追加 |
rb | 二进制文件 | 读取 | 出错 | 打开文件 |
wb | 二进制文件 | 写入 | 创建新文件 | 覆盖原文件 |
ab | 二进制文件 | 追加 | 创建新文件 | 原文件后追加 |
rb+ | 二进制文件 | 读取/写入 | 出错 | 打开文件 |
wb+ | 二进制文件 | 读取/写入 | 创建新文件 | 覆盖原文件 |
ab+ | 二进制文件 | 读取/追加 | 创建新文件 | 原文件后追加 |
所在文件:stdio.h
函数功能:fclose()
用来关闭之前 fopen()
打开的文件
函数操作:让缓冲区内的数据写入文件,并释放系统提供的文件资源
int fclose(FILE *filePointer)
参数/返回值 | 含义 |
---|---|
FILE *filePointe | 指向文件缓冲的指针 |
int | 成功则返回0,失败则返回EOF(-1) |
int main(){
FILE *fp;
if(fopen("abc.txt","w")==NULL){
exit(-1);//非0表示异常
}
fclose(fp);
}
需要引入
位置指针
:打开文件,默认指向文件开头
- 所有文件读/写,都是从
位置指针
指示的位置进行读/写
分为
文件使用特殊字符
EOF
作为文件结束标记
int feof(FILE *stream);
:判断是否读到文件结尾
所在文件:stdio.h
参数:FILE *stream
是指向文件缓冲的指针
注意:文件只有读了才会修改 位置指针
,没有打开并读取的文件无法通过 feof(fp)
判断是否读到文件尾,一定要 先读在判断
# include
int main(){
//打开文件
FILE *fp = fopen("test.txt","r+");
//从文件中读取内容
char res = EOF;
while(res = fgetc(fp) && !feof(fp)){
printf("%c",res);
}
//关闭文件
fclose(fp);
return 0;
}
在使用 feof()
判断文件尾时,最后一行没有 \n
会少读一行
#include
int main(){
FILE *fp = fopen("test.txt", "w+");
fputs("asd\n", fp);
fputs("123456", fp);
rewind(fp);
char str[1024];
while(fgets(str, 1024, fp) && !feof(fp)){
printf("str = %s", str);
//输出 str = asd
//若最后一行加上 \n,则输出
//str = asd
//str = 123456
}
fclose(fp);
return 0;
}
读入一个字符 | 输出一个字符 | 所在文件 |
---|---|---|
getchar() |
putchar() |
stdio.h |
fgetc(fp) |
fputc(ch,fp) |
stdio.h |
int fgetc(FILE *fp)
:从文件中读取一个字符,若到文件尾返回EOF
EOF
#include
int main(){
//打开文件
FILE *fp = fopen("test.txt", "r+");
//从文件中读取内容
char res = EOF;
while((res = fgetc(fp)) != EOF){
printf("res = %c\n", res);
}
//关闭打开的文件
fclose(fp);
return 0;
}
int fputc(int ch,FILE *fp)
:将ch字符写入文件
EOF
# include
int main(){
//打开一个文件
FILE *fp = fopen("test.txt","w+");
//向文件中写入内容
for(char ch = 'a';ch <= 'z';++ch){
char res = fputc(ch,fp);
printf("%c",res);
}
//关闭打开的文件
fclose(fp);
return 0;
}
读入字符串 | 输出字符串 | 所在文件 |
---|---|---|
getchar() |
putchar() |
stdio.h |
fgets(fp) |
fputs(s,fp) |
stdio.h |
char *fgets(char *s,int n,FILE *fp)
:从 fp
指向的文件中读取 n-1
个字符,写入s中;如果中间遇到 \0
或者 EOF
,读入结束,且在字符串最后添加 \0
char *str
指针\n
或 EOF
则停止读取NULL
#include
int main(){
FILE *fp = fopen("test.txt", "w+");
fputs("asd\n", fp);
fputs("123456\n", fp);
rewind(fp);
char str[1024];
fgets(str, 1024, fp);//读到 \n 读取一行结束
printf("str = %s", str); // asd
fclose(fp);
return 0;
}
#include
int main(){
FILE *fp = fopen("test.txt", "w+");
fputs("asd\n", fp);
fputs("123456", fp);
rewind(fp);
char str[1024];
while(fgets(str, 1024, fp)){//读到文件尾,停止读
printf("str = %s", str);//asd123456
}
fclose(fp);
return 0;
}
int fputs(char *s,FILE *fp)
:将 s
中的字符串写到 fp
指向的文件中
EOF
# include
int main(){
FILE *fp = fopen("test.txt","w+");
fputs("Hello ",fp);
fputs("World!",fp);
fclose(fp);
return 0;
}
遇到 \0
自动终止写入
# include
int main(){
FILE *fp = fopen("test.txt","w+");
fputs("asd\0asdasd\n",fp);
fclose(fp);
return 0;
}
int fscanf(FILE *fp,char *format)
读/写成功返回整数
int fprintf(FILE *fp,char *fprmat)
二进制文件的读写函数可以读取文本文件
文本文件的读写函数不可读取二进制文件
unsigned fread(void *ptr,unsigned size,unsigned n,FILE *fp)
从文件
fp
中读取n
个size
字节的数据块,存储于ptr
指向的内存空间
n
#include
int main(){
// test.txt中存放的是"Hello\0 World!"
FILE *fr = fopen("test.txt", "rb+");
char buf[1024] = {0};
int n = fread(buf, 1, 1024, fr);
printf("%d\n", n);
for(int i = 0; i < n; i++){
printf("%c", buf[i]);
}
fclose(fr);
return 0;
}
注意:读取时,size
取最小字节,n
可以随便写
若读取时 size
不是最小字节,则会引起读取失败
如存储的 char
类型 0A 1E 1C 2C 66 67 68
size = 1
时,n=1024
,会将文件中内容依次取出
size = 4
时,n=1024
,第一个数据块 0A 1E 1C 2C 会顺利取出,但最后剩下3个字节不足一个数据块,则最后一个块读取不到
unsigned fwrite(void *ptr,unsigned size,unsigned n,FILE *fp)
将
ptr
指向的存储空间的n
个size
字节的数据块写入文件fp
中
n
# include
int main(){
FILE *fp = fopen("test.txt","wb+");
char *str = "Hello\0 World!";
fwrite((void *)str, 13 ,1, fp);
fclose(fp);
return 0;
}
# include
int main(){
FILE *fp = fopen("test.txt","wb+");
int ages[4] = {1,3,5,7};
fwrite(ages,sizeof(ages),1,fp);
rewind(fp);
int t;
while(fread(&t,sizeof(int),1,fp) > 0){
printf("data=%d\n",t);
}
fclose(fp);
return 0;
}
结构体中的数据类型不统一,此时最适合用二进制的方式进行读写
单个结构体
# include
typedef struct{
char *name;
int age;
double height;
}Person;
int main(){
Person p1 = {"A",23,1.7};
FILE *fp = fopen("test.person","wb+");
fwrite(&p1,sizeof(p1),1,fp);
rewind(fp);
Person p2;
fread(&p2,sizeof(p2),1,fp);
fclose(fp);
return 0;
}
读写结构体数组
# include
typedef struct{
char *name;
int age;
double height;
}Person;
int main(){
Person ps[] = {
{"A", 18, 1.65},
{"B", 21, 1.88},
{"C", 33, 1.9}
};
FILE *fp = fopen("test.person","wb+");
fwrite(&ps,sizeof(ps),1,fp);
rewind(fp);
Person p;
while(fread(&p,sizeof(p),1,fp) > 0){
printf("name = %s,age = %d,height = %lf\n"
,p.name,p.age,p.height);
}
fclose(fp);
return 0;
}
long ftell(FILE *fp)
:返回距文件头的字节数
#include
int main(){
char *str = "abcedfg";
FILE *fp = fopen("test.txt", "w+");
long p = ftell(fp);
printf("p = %ld\n", cp); // 0
// 写入一个字节
fputc(str[0], fp);
p = ftell(fp);
printf("p = %ld\n", p); // 1
fclose(fp);
return 0;
}
void rewind()
:使位置指针指向文件头
int fseek(FILE *fp, long offset, int origin );
: 将位置指针移动到指定位置
fp
:文件的指针,指向要操作的文件
offset
:表示要移动的字节数
offset 为正时,向后移动;
offset 为负时,向前移动
origin
:从何处开始计算偏移量。
起始点 | 常量名 | 常量值 |
---|---|---|
文件开头 | SEEK_SET | 0 |
当前位置 | SEEK_CUR | 1 |
文件末尾 | SEEK_END | 2 |
#include
int main(){
FILE *fp = fopen("test.txt", "w+");
fputs("123456789", fp);
// 将文件指针移动到文件结尾
fseek(fp, 0, SEEK_END);
int len = ftell(fp); // 计算文件长度
printf("len = %i\n", len);
fclose(fp);
return 0;
}
#include
int main(){
FILE *fp = fopen("test.txt","w+");
fputs("123456789", fp);
fseek( fp, 7, SEEK_SET );
fputs("Hello", fp);
fclose(fp);
return 0;
}