最全怒肝1,2024年最新谈谈我认为的高级C C++开发到底应该是怎样的

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

if (pf == NULL)
{
	perror("fopen");//perror函数显示错误信息
	return -1;
}
//写文件
fputc('b', pf);
fputc('i', pf);
fputc('t', pf);
fclose(pf);
pf = NULL;
return 0;

}


运行完上述代码后,相关文件自动出现fputc函数写入的三个字  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ec709e2c95a346e483723fb3c8907495.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **fgetc函数示例:**



//int fgetc(FILE *filename);函数声明
int main()
{
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “r”);//以“只读r”的模式打开文件
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//读文件
int ch1=fgetc(pf);
printf(“%c\n”, ch1);

int ch2 = fgetc(pf);
printf("%c\n", ch2);

int ch3 = fgetc(pf);
printf("%c\n", ch3);
fclose(pf);
pf = NULL;
return 0;

}


假设我们现在相关文件里有3个字母abc  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/dd97c0d341154802a72570f833412aed.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 我们运行上述程序,程序自动从文件里获取三个字母abc  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8175d44d405e4939aeafd3a84dc273e4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)


### 4.2文本行输入输出函数


我们再来看一看文本行输入/输出函数  
 **fputs函数示例:**



//int fputs(const char *s, FILE *stream);函数声明
//s 代表要输出的字符串的首地址,可以是字符数组名或字符指针变量名。
//stream 表示向何种流中输出,可以是标准输出流 stdout,也可以是文件流。标准输出流即屏幕输出,printf 其实也是向标准输出流中输出的。
int main()
{
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “w”);//以“只写W”的模式打开文件
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//写文件(写一行)
fputs(“hello world\n”, pf);
fputs(“hello bit\n”, pf);
fclose(pf);
pf = NULL;
return 0;
}


和fputc差不多,fputc是写一个字母,fputs是写一行,运行完上述程序,相关文件夹出现hello world 和hello bit  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/5ee105d98ee444168b40d3e360c8bb59.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **fgets函数示例:**



//char *fgets(char *buf, int bufsize, FILE *stream);
//*buf: 字符型指针,指向用来存储所得数据的地址。
//bufsize: 整型数据,指明存储数据的大小。
//*stream: 文件结构体指针,将要读取的文件流。
int main()
{
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “r”);//以“只读r”的模式打开文件
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//读文件(读一行)
char arr[20] = { 0 };
fgets(arr,5,pf);
printf(“%s\n”, arr);//打印hell,说是最多读5个其实是读到第四个,然后第五个补\0
fclose(pf);
pf = NULL;
return 0;
}


我们原先文件里有hello world 和hello bit,我们读一行中的5个字符到arr里  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/41c360a88dcc4047a95fd487b96e5841.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/86376295d1b74d31b1ae771a377fc9c8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 说是打印5个字符,其实是打印4个字符,第五个字符是自动补\0


### 4.3格式化输入输出函数


格式化输入输出也就是按某种格式写入或读取  
 **fprintf函数示例:**



struct S
{
int n;
double d;
};
int main()
{ //int fprintf(FILE *filename, const char *string, . . . .);函数声明
//看起来函数声明有点麻烦,我们再来看一下常见的printf函数声明
//int printf( const char *format, … );
//对比一下很容易发现也就是比printf函数多一个指针参数而已,其他的都按printf来即可
struct S s = { 100,3.14 };
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “w”);//以“只写w”的模式打开文件
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//写文件
fprintf(pf,“%d %lf”, s.n, s.d);
fclose(pf);
pf = NULL;
return 0;
}


fprintf就是printf函数多一个pf指针,其他的和printf都是一样的,上述代码运行一下,相关文件出现100,和3.140000(浮点型默认6位小数)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e59d1868d18e4be7a250235a0e7ebcf1.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 **fscanf函数示例:**



struct S
{
int n;
double d;
};
int main()
{
//int fscanf(FILE *stream, char *format,[argument…]);函数声明
//和fprintf一样,就是scanf函数前面多一个pf指针参数
struct S s = { 0};
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “r”);//以“只读r”的模式打开文件
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//读文件
fscanf(pf,“%d %lf”, &(s.n), &(s.d));
printf(“%d %lf\n”, s.n, s.d);
fclose(pf);
pf = NULL;
return 0;
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/fb4796df3bd6497ab250cd2d45235b74.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 原先文件里有100 3.140000,运行程序后读取出这两个数  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2887c7e01f534652a496dee82e700d07.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)


### 4.4二进制输入输出函数


fwrite函数声明如下  
 size\_t fwrite(const void \*ptr, size\_t size, size\_t nmemb, FILE \*stream)  
 ptr-- 这是指向要被写入的元素数组的指针。  
 size-- 这是要被写入的每个元素的大小,以字节为单位。  
 nmemb-- 这是元素的个数,每个元素的大小为 size 字节。  
 stream-- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。  
 **fwrite函数示例:**



//size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
//ptr-- 这是指向要被写入的元素数组的指针。
//size-- 这是要被写入的每个元素的大小,以字节为单位。
//nmemb-- 这是元素的个数,每个元素的大小为 size 字节。
//stream-- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。
struct S
{
int n;
double d;
char name[20];
};
int main()
{
struct S s = { 100,3.14,“zhangsan” };
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “wb”);//以“只写wb”的模式打开文件
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//写文件-二进制方式写
fwrite(&s, sizeof(s), 1, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}


这里要注意的是,我们以二进制fwrite写入,产生的是二进制文件,所以我们以二进制的wb模式打开,文件里的内容如下  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/31f6ff5870dc476ab0bd9801163a9e10.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 因为是二进制文件,我们直接看是看不懂的,但是我们知道可以二进制读,也就是下面的fread函数  
 函数声明:size\_t fread( void \*buffer, size\_t size, size\_t count, FILE \*stream )  
 buffer 是读取的数据存放的内存的指针(可以是数组,也可以是新开辟的空间,buffer就是一个索引)  
 size 是每次读取的字节数  
 count 是读取次数  
 strean 是要读取的文件的指针  
 **fread函数示例:**



struct S
{
int n;
double d;
char name[20];
};
int main()
{
struct S s = {0};
FILE*pf = fopen(“E:\c-language-notes\test.21.10.9\data.txt”, “rb”);//以“只写wb”的模式打开文件
//wb
if (pf == NULL)
{
perror(“fopen”);//perror函数显示错误信息
return -1;
}
//读文件-二进制方式读
fread(&s, sizeof(struct S), 1, pf);
//打印
printf(“%d %lf %s\n”, s.n, s.d, s.name);
fclose(pf);
pf = NULL;
return 0;
}


![在这里插入图片描述](https://img-blog.csdnimg.cn/60adb890c2e14b1bb6780c62a14e1496.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 我们现在文件里是这些东西,我们运行程序读一下  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/be4baed1455b43e2b11ec181608ad74d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 可以读出之前写入的东西


## 五、文件的随机读写


### 5.1fseek


函数声明:int fseek(FILE \*stream, long offset, int fromwhere);  
 **函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere为基准,偏移offset个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。执行成功返回0,否则返回其他数。**


fromwhere有三个值:  
 SEEK\_CUR 文件指针当前位置  
 SEEK\_END 文件的末尾  
 SEEK\_SET 文件的起始  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4974d6a11f9d499ab4e42decf8909411.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 比如a的地址就是文件的起始,f就是文件的末尾,假如我现在fgetc读了一个,指针从a往后移动一位,指针指向b,那b所在位置就是SEEK\_CUR,也就是文件指针当前位置


注意:随机读写不是乱读,而是想读哪里读哪里,比如我想读文件第三个字母,我就可以直接用随机读写读取第三个字母。我们仍以上面这个文本文档为例:  
 现在我要读第三个,按照常规的顺序读写,是有一个指针指向a,然后每读一个,指针往后移一位,读第三个要移动2次。fseek函数就是可以快速根据指针的位置和偏移量来定位文件指针,大白话讲就是fseek函数可以快速找到第三个字母的指针。



#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//fseek函数
int main()
{
//1.打开文件
FILE*pf=fopen(“E:\c-language-notes\test.21.10.11\data.txt”, “r”);
if (pf == NULL)
{
perror(“fopen”);
return -1;
}
//2.读文件(随机读写)
//读c
fseek(pf, 2, SEEK_SET);//现在我要读c,刚开始cur和set都是起始位置,用cur也可
int ch = fgetc(pf);
printf(“%c\n”, ch);
//读b
fseek(pf, -2, SEEK_CUR);
ch = fgetc(pf);
printf(“%c\n”, ch);
//3.关闭文件
return 0;
}


关于读b,因为我们读c之后,指针会自动往后移一位,所以cur是指向d的,b关于d的偏移量是-2,所以我们用fseek(pf, -2, SEEK\_CUR);读取


### 5.2ftell


函数声明:long int ftell(FILE\*filenname);


**返回文件指针相对起始位置的偏移量**



#include<stdio.h>
//fseek函数
int main()
{
//1.打开文件
FILE*pf=fopen(“E:\c-language-notes\test.21.10.11\data.txt”, “r”);
if (pf == NULL)
{
perror(“fopen”);
return -1;
}
//2.读文件(随机读写)
//读c
fseek(pf, 2, SEEK_SET);//现在我要读c,刚开始cur和set都是起始位置,用cur也可
int ch = fgetc(pf);
printf(“%c\n”, ch);
//读b
fseek(pf, -2, SEEK_CUR);
ch = fgetc(pf);
printf(“%c\n”, ch);
int a=ftell(pf);//b读完之后指针自动往后一位到c,c相对a偏移量为2
printf(“%d”, a);//打印2
//3.关闭文件
return 0;
}


继上一段代码,我们读完b之后指针自动往后移动一位指向c,c相对起始位置a的偏移量为2,所以ftell会返回2


### 5.3rewind


函数声明:void rewind(FILE \*stream);  
 不管pf现在在什么位置,传过去,pf重新指向文件起始位置


## 六、文本文件和二进制文件


根据数据的组织形式,数据文件被称为**文本文件**或者**二进制文件**  
 数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是**二进制文件**


如果要求在外存上以ASCII码的形式存储,则需要在存储前进行转换。以ASCII码的形式存储的文件就是**文本文件**


一个数据在内存中是怎么存储的呢?  
 字符一律以ASCII码的形式进行存储,数值型的数据即可用ASCII码的形式存储,也可以用二进制形式存储,如下,我们进行10000的存储  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/37ebdb3c970e485e8a2a236438082ad4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 (图片来自比特就业课)  
 如果我们按ASCII形式存储,把10000共5位,我们把每位上的数字看做一个字符,共要5个字节


如果我们直接按二进制形式进行存储,二进制的10000,是  
 00000000 00000000 00100111 00010000共需占4个字节(1个整形)


## 七、文件读取结束的判断


### 7.1被错误使用的feof


牢记:在文件读取过程中,不能使用feof函数的返回值直接来判断文件的结束与否,而是**应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束**


**1.文本文件读取是否结束,判断返回值是否为EOF(fgetc),或者NULL(fgets)**


\*fgetc判断是否为EOF  
 fgetc读到一个字符返回int,如果文件结束没读到或者遇到错误,返回EOF


原文件里有abcdef5个字符,现在我们怎么利用fgetc进行打印,并判断是否结束呢?  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/552a8224aa1b4beb92cbdc4422365adb.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)  
 代码如下:



#include<stdio.h>
int main()
{
//打开文件
FILE*pf=fopen(“E:\c-language-notes\test.21.10.11\data.txt”, “r”);
if (pf == NULL)
{
perror(“fopen”);
return -1;
}
//打印文件内容
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c ", ch);
}

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;

}


![在这里插入图片描述](https://img-blog.csdnimg.cn/17b4f240cc72423687620bec30de1829.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6auY6YKu5ZC05bCR,size_20,color_FFFFFF,t_70,g_se,x_16)


\*fgets判断返回值是否为NULL  
 函数声明: char \*fgets(char \*string, int n, FILE \*stream);  
 fgets会从流stream里读n个字符到string这个字符串首元素地址里,如果遇到错误,或者遇到文件结尾,函数会返回一个空指针


**2.二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。**  
 eg:fread判断返回值是否小于实际要读的个数



![img](https://img-blog.csdnimg.cn/img_convert/acaa36c4ae378aacd074f32ba67f8edb.png)
![img](https://img-blog.csdnimg.cn/img_convert/ee99ad033e2d83f98d83729bb2ac3a0d.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

E \*stream);  
 fgets会从流stream里读n个字符到string这个字符串首元素地址里,如果遇到错误,或者遇到文件结尾,函数会返回一个空指针


**2.二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。**  
 eg:fread判断返回值是否小于实际要读的个数



[外链图片转存中...(img-RfWWNI1G-1715827353265)]
[外链图片转存中...(img-cwFuTluW-1715827353265)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值