既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
流——一种高度抽象的概念
生活中存在多种外部设备,比如:文件、屏幕、磁盘等等,每种设备输入输出数据的方式都不一样,为了统一,我们用“流”的方式,来输入输出数据。我们只需要关注流就可以了,不需要关注每种外设的读写,因为底层都是大同小异,经过封装之后显得不同而已,同时也减少了程序猿的负担。
C语言程序只要运行起来,操作系统就默认打开了三个“流”:
分别对应的物理设备有这些
标准输出流:stdout
->屏幕
标准输入流:stdin
->键盘
标准错误流:stderr
->屏幕
它们三个的类型都是FILE*
所以我们可以把信息打印到屏幕上:
//也可以直接输出到屏幕上
int main()
{
//打印在屏幕上
fputc('h', stdout);
fputc('e', stdout);
fputc('l', stdout);
fputc('l', stdout);
fputc('o', stdout);
printf("\n");
return 0;
}
读取数据举例
fgetc
单个字符读取:
//读取数据
int main()
{
//打开文件
FILE\* pf = fopen("data.txt","r");//修改为r,只读的方式
if (pf == NULL)
{
perror("fopen");
return -1;
}
//读写文件
char ch = fgetc(pf);
printf("%c\n",ch);
ch = fgetc(pf);
printf("%c\n", ch);
ch = fgetc(pf);
printf("%c\n", ch);
//将结果打印打屏幕上面去
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
结果展示:
fgets
行字符读取:
int main()
{
//打开文件
FILE\* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
//写文件
char arr[20] = { 0 };
fgets(arr,5,pf);
printf("%s\n",arr);
fgets(arr, 5, pf);
printf("%s\n", arr);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
奇怪的现象:
奇怪的现象:就是本来读取5个字符,但是却只打印了4个?
原因:我们第五个位置默认填上\0,所以相当于只有4个字符被读了
ps:原来的arr被第二次的读取给覆盖了!
fscanf 格式化输入函数
它只不过比scanf多了一个文件指针参数
//函数原型
int fscanf( FILE \*stream, const char \*format [, argument ]... );
//fscanf
int main()
{
//打开文件
FILE\* pf = fopen("data.txt", "r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
//写文件
int a =0;
double d =0;
fscanf(pf, "%d %lf", &a, &d);
printf("%d\n",a);
printf("%lf\n",d);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
结果展示:
fprintf 格式化输出函数
它只不过比printf多了一个文件指针参数
//函数原型
int fprintf( FILE \*stream, const char \*format [, argument ]...);
//fscnaf
int main()
{
//打开文件
FILE\* pf = fopen("data.txt", "w");
if (pf == NULL)
{
perror("fopen");
return -1;
}
//写文件
int a = 100;
double d = 3.14;
fprintf(pf, "%d %lf", a, d);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
上面我们展示的全部都是文本文件,数据文件分为文本文件和二进制文件
文本文件:就是我们能够看懂的
二进制文件:就是计算机能够看懂的,我们在电脑上显示出来是看不懂的
下面来介绍一下二进制文件的读写:
//函数原型
size_t fwrite( const void \*buffer, size_t size, size_t count, FILE \*stream );
fwrite 二进制输出
//fwrite 二进制写
int main()
{
//打开文件
FILE\* pf = fopen("data.txt", "wb");//以wb 二进制的方式写
if (pf == NULL)
{
perror("fopen");
return -1;
}
//写文件
int arr[5] = { 1,2,3,4,5 };
fwrite(arr,4,5,pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
结果展示:
fread 二进制输入
size_t fread( void \*buffer, size_t size, size_t count, FILE \*stream );
虽然二进制文件我们看不懂,但是可以把刚刚写入的数据读出来
//fread 二进制写
int main()
{
//打开文件
FILE\* pf = fopen("data.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return -1;
}
int buf[20] = { 0 };
fread(buf,sizeof(buf),1,pf);
for (int i = 0; i < sizeof(buf) / sizeof(int); i++)
{
printf("%d ",buf[i]);
}
printf("\n");
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
结果展示:
sprintf函数
//sprintf
struct S
{
int a;
double d;
char name[10];
};
int main()
{
char arr[100] = { 0 };
struct S s = { 100, 3.14,"zhangsan" };
//把一个格式化的数据转换为字符串
sprintf(arr,"%d %lf %s",s.a,s.d,s.name);
printf("%s\n",arr);
return 0;
}
sscanf函数
//sscanf
struct S
{
int a;
double d;
char name[10];
};
int main()
{
char arr[100] = { 0 };
struct S s = { 100, 3.14,"zhangsan" };
//把一个格式化的数据转换为字符串
sprintf(arr, "%d %lf %s", s.a, s.d, s.name);
printf("%s\n", arr);
struct S tmp = { 0 };
//把一个字符串的数据(arr中)转换为格式化的数据
sscanf(arr, "%d %lf %s", &(tmp.a), &(tmp.d), tmp.name);
printf("%d %lf %s\n",tmp.a,tmp.d,tmp.name);
return 0;
}
一共有两次打印,第一次打印是按照字符串打印的,第二次是按照结构体数据化的格式打印的。
对比这两组函数:
输入
函数名称 | 功能 |
---|---|
scanf | 从标准输入流(键盘)读取格式化的数据 |
fsacnf | 从所有的输入流读取格式化的数据 |
sscanf | 从字符串中读取一个格式化的数据 或者说把一个字符串转换成一个格式化的数据 |
输出
函数名称 | 功能 |
---|---|
printf | 把格式化的数据输出到标准输出(屏幕)上 |
fprintf | 把格式化的数据输出到所有输出流(屏幕/文件)上 |
sprintf | 把格式化的数据转换成对应的字符串 |
五、文件的随机读写
5.1 fseek
根据文件指针的位置和偏移量来定位文件指针
//函数原型
int fseek( FILE \*stream, long offset, int origin );
函数名称 | fseek |
---|---|
函数功能 | 新定位文件指针的位置 |
头文件 | #include<stdio.h> |
函数原型 | int fseek( FILE *stream, long offset, int origin ); |
参数 | 第一个参数:文件指针第二个参数:偏移量(这个要看origin)第三个参数:起始位置(设置了三个宏 SEEK_CUR SEEK_END SEEK_SET) |
返回值 | 如果成功,fseek 返回 0。否则,它将返回非零值。 |
int main()
{
FILE\* pf = fopen("data.txt","r");//先人为写入hello数据
if (pf == NULL)
{
perror("fopen");
return -1;
}
//随机读写
fseek(pf,4,SEEK\_CUR);//定位文件指针
int ch=fgetc(pf);//读取偏移量为4的字符
printf("%c\n",ch);
fclose(pf);
pf = NULL;
return 0;
}
结果展示:
5.2 ftell
返回文件指针相对于起始位置的偏移量
//函数原型
long ftell( FILE \*stream );
int main()
{
FILE\* pf = fopen("data.txt","r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
//随机读写
fseek(pf,4,SEEK\_CUR);//定位文件指针
int ch=fgetc(pf);//读取偏移量为4的字符
printf("%c\n",ch);
int a=ftell(pf);//返回偏移量
printf("%d\n",a);
fclose(pf);
pf = NULL;
return 0;
}
5.3 rewind
让文件指针的位置回到起始位置
void rewind( FILE \*stream );
int main()
{
FILE\* pf = fopen("data.txt","r");
if (pf == NULL)
{
perror("fopen");
return -1;
}
//随机读写
fseek(pf,4,SEEK\_CUR);//定位文件指针
int ch=fgetc(pf);//读取偏移量为4的字符
printf("%c\n",ch);
int a=ftell(pf);//返回相对于起始位置的偏移量
printf("%d\n",a);
rewind(pf);//让文件指针回到起始位置
a = ftell(pf);//返回相对于起始位置的偏移量
printf("%d\n", a);
fclose(pf);
pf = NULL;
return 0;
}
六、文本文件和二进制文件
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节
字符1的ASCII码49,对应的码值是00110001
字符0的ASCII码是48,对应的码值是00110000
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节
字符1的ASCII码49,对应的码值是00110001
字符0的ASCII码是48,对应的码值是00110000
[外链图片转存中…(img-Jhba07l9-1715602059711)]
[外链图片转存中…(img-DzJgldjP-1715602059711)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!