前文补充

#include <iostream>
using namespace std;int main()
{int a = 10;int c = 20; // 将变量c定义在switch语句之前switch(a){case 1:{cout << ".........." << endl;cout << c << endl;}break;default:cout << ".........." << endl;break;}return 0;
}

这段代码存在一些问题,以下是代码的分析和问题说明:

代码分析

  1. switch语句的结构问题

    • switch语句的语法要求case标签必须位于switch语句块的最外层,而不能嵌套在其他语句(如printf)之后。在你的代码中,printf("..........\n");int c = 20;以及printf("..........\n");出现在case标签之前,这是不符合C++语法的。

    • switch语句的执行流程是从匹配的case标签开始执行,直到遇到breakswitch语句结束。因此,case标签不能嵌套在其他语句中。

  2. 变量c的作用域问题

    • switch语句中,case标签后的代码块(用大括号{}括起来的部分)会创建一个新的作用域。在你的代码中,int c = 20;定义在switch语句块的外面,但在case 1中尝试访问c。由于c的作用域问题,这会导致编译错误。

修改后的代码

以下是修改后的代码,修复了上述问题:

#include <iostream>
using namespace std;int main()
{int a = 10;int c = 20; // 将变量c定义在switch语句之前switch(a){case 1:{cout << ".........." << endl;cout << c << endl;}break;default:cout << ".........." << endl;break;}return 0;
}

修改说明

  1. 变量c的定义位置

    • int c = 20;定义在switch语句之前,确保在switch语句中可以正确访问c

  2. switch语句的结构

    • printf语句和case标签的顺序调整为符合C++语法的结构。case标签必须位于switch语句块的最外层。

  3. 使用cout代替printf

    • 为了保持代码风格的一致性,将printf替换为C++标准库中的cout

输出结果

假设a的值为10,程序的输出将是:

..........

如果将a的值改为1,程序的输出将是:

..........
20

本章重点

  • 循环的语法理解

  • breakcontinue 的作用

  • goto 真的没人用吗

  • void 的理解

  • void 修饰函数和函数参数的作用

  • void 指针的用途

1.9 do、while、for 关键字

三种循环各自语法 - 补充内容

while 循环

// while
条件初始化
while(条件判定){// 业务更新条件更新
}

for 循环

// for
for(条件初始化;条件判定;条件更新){// 业务代码
}

do while 循环

条件判定是放在后面的,是直接先执行代码块中的代码逻辑的!--- 至少会跑一遍

// do while
条件初始化
do{条件更新
}while(条件判定);do{}while(0);

三种循环对应的死循环写法 - 补充内容

while(1){
}for(;;){}do{}while(1);

书中代码,优化后

#include <stdio.h>
#include <windows.h>int main()
{while (1){char c = getchar();if ('#' == c){break;}printf("echo: %c\n", c);}system("pause");return 0;
}

在C语言中,使用 int c 而不是 char c 来接收 getchar() 的返回值是一个常见的最佳实践,原因主要与 getchar() 函数的返回值类型以及字符和整数的表示范围有关。下面详细解释为什么使用 int c 更好:

getchar() 的返回值类型

getchar() 函数的返回值类型是 int,而不是 char。其原型定义为:

int getchar(void);

这意味着 getchar() 返回的是一个整数(int 类型),而不是一个字符(char 类型)。返回的整数值可以表示一个字符的ASCII码,也可以是一个特殊的值 EOF(表示文件结束)。

EOF 的值

EOF 是一个特殊的值,用于表示输入流的结束。在标准C中,EOF 的值通常定义为 -1。由于 char 类型的范围通常是 0 到 255(对于无符号字符)或 -128 到 127(对于有符号字符),而 EOF 的值是 -1,这可能会导致问题。

如果使用 char c 来接收 getchar() 的返回值,可能会出现以下问题:

  • 有符号字符问题 :如果 char 是有符号类型(这是默认情况,但具体取决于编译器和平台),EOF 的值 -1 可以被正确存储在 char 中。但是,当 char 被用作条件表达式时,可能会出现意外的行为。例如,if (c == EOF) 可能不会按预期工作,因为 c 的值可能会被隐式转换为 int,导致比较失败。

  • 无符号字符问题 :如果 char 是无符号类型(可以通过编译器选项或平台设置来改变),EOF 的值 -1 会被解释为一个非常大的正数(通常是 255)。这会导致 if (c == EOF) 的比较永远失败,因为 c 的值永远不会等于 -1

使用 int c 的好处

使用 int c 来接收 getchar() 的返回值可以避免上述问题。int 类型的范围足够大,可以正确表示所有可能的字符值以及 EOF。这样可以确保 if (c == EOF) 的比较总是按预期工作。

以下是修改后的代码,使用 int c 来接收 getchar() 的返回值:

#include <stdio.h>
#include <windows.h>int main()
{int c; // 使用int来接收getchar()的返回值while (1){c = getchar();if ('#' == c){break;}printf("echo: %c\n", c);}system("pause");return 0;
}

使用 int c 而不是 char c 来接收 getchar() 的返回值,可以确保程序能够正确处理 EOF 的值,避免因字符类型范围问题导致的错误。这是C语言编程中的一个常见最佳实践,有助于提高代码的健壮性和可移植性。

我们的1234的数字,可以打印出来,我们也就可以发现 printf 的价值,有作用,就是将一个整型转化成一个一个字符,显示到显示器当中(程序运行会默认打开三个文件:输入输出错误)

对于 ASCLL码表,在后面,我们会谈论到,这也就是机器不是只认识二进制吗?为什么还认识abcd这样的字符,更多详情,后续会介绍!

补充:

与getchar:从键盘上获取一个字符的操作相对应的是putchar,往标准输出上显示一个字符!

1.9.1 break & continue 区别

在C语言中,breakcontinue 都是用于控制循环流程的语句,但它们的作用和使用场景有很大区别。

1. break

  • 作用 :用于完全终止最内层的循环(forwhiledo-while ),跳出循环体,继续执行循环体之后的代码。

  • 使用场景 :当你在循环中遇到了某种条件,使得你不再需要继续执行循环,就可以使用 break 。比如在一个查找算法中,一旦找到了目标元素,就可以用 break 跳出循环,避免无意义的继续循环。

  • 示例代码

#include <stdio.h>int main() {for (int i = 0; i < 10; i++) {if (i == 5) {break; // 当i等于5时,跳出循环}printf("%d ", i);}printf("\nLoop ended.\n");return 0;
}
0 1 2 3 4
Loop ended.

因为当 i 等于 5 时,break 语句执行,循环被终止,直接跳到循环体之后的代码。

2. continue

  • 作用 :用于跳过当前循环体中的剩余代码,直接进入下一次循环迭代。也就是说,continue 只是中断当前这一次循环的执行,而不是整个循环。直接跳到条件判定,而不是内部代码块!do while 也是如此!!!也是先到while的条件判定!都是跳转到条件判定!!!

但是对于for来说:我们有一个示例代码:也是证明代码:

int main()
{int i = 10;for( ; i < 10; ++i){printf("continue before\n");if(i == 5){printf("continue\n");continue;}printf("continue after\n");}return 0;
}

这就不是跳转到1了,想想,如果跳转到1,就会造成死循环了,所以,这个应该是跳到2,即++i!

#include <stdio.h>int main()
{int i = 0;for( ; i < 10; ){if(i == 5){printf("%d\n", i);continue;}++i;}return 0;
}

但是我们这么写的话就是会造成死循环!

continue 语句在 for 循环中的行为是:跳过当前迭代中 continue 之后的所有代码,然后执行 for 循环的第三部分(即增量表达式 ++i,最后再进行条件判断开始下一次循环;而在您第二个没有增量表达式的 for 循环中,由于 continue 跳过了 ++i 语句,导致 i 的值永远停留在 5 无法增加,从而造成了死循环。

简单来说:

  • 有增量表达式continue → 执行 ++i → 条件判断 → 下一次循环

  • 无增量表达式continue → 条件判断 → 下一次循环(i 不变)→ 死循环



  • 使用场景 :当你在循环中遇到某些情况,不想执行当前循环体中的剩余代码,但仍然希望循环能够继续进行,就可以使用 continue 。例如在筛选数据时,跳过不符合条件的数据,继续处理符合条件的数据。

  • 示例代码

#include <stdio.h>int main() {for (int i = 0; i < 10; i++) {if (i % 2 == 0) {continue; // 当i为偶数时,跳过当前循环的剩余代码}printf("%d ", i);}printf("\nLoop ended.\n");return 0;
}

输出结果为:

1 3 5 7 9
Loop ended.

i 为偶数时,continue 语句执行,跳过了当前循环的 printf 语句,直接进入下一次循环迭代。

  • 作用范围break 是终止整个循环,而 continue 只是中断当前这一次循环的执行。

  • 代码执行流程 :使用 break 后,循环直接结束,执行循环体之后的代码;使用 continue 后,会跳过当前循环的剩余代码,直接进入下一次循环迭代。

  • 适用场景break 适用于你确定不需要继续循环的情况;continue 适用于你只是不想执行当前循环的某些代码,但仍然希望循环继续进行的情况。

break 的细节补充

  • 在嵌套循环中的表现break 只能终止它所在的最内层循环。如果你有嵌套循环(即一个循环体内部还有另一个循环),break 只会终止最内层的循环,不会影响外层循环。例如:

#include <stdio.h>int main() {for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {if (j == 1) {break; // 只终止内层循环}printf("i=%d, j=%d\n", i, j);}printf("Inner loop ended.\n");}printf("Outer loop ended.\n");return 0;
}

输出结果为:

i=0, j=0
Inner loop ended.
i=1, j=0
Inner loop ended.
i=2, j=0
Inner loop ended.
Outer loop ended.

可以看到,break 只终止了内层循环,外层循环仍然继续执行。

  • switch 语句中的使用break 也可以用在 switch 语句中,用于防止代码的“穿透”。在 switch 语句中,如果没有 break,程序会从匹配的 case 开始执行,直到遇到 break 或者 switch 语句结束。例如:

#include <stdio.h>int main() {int num = 2;switch (num) {case 1:printf("One\n");case 2:printf("Two\n");break;case 3:printf("Three\n");break;default:printf("Default\n");}return 0;
}

输出结果为:

Two

如果没有在 case 2 后面加 break,程序会继续执行 case 3default,这就是所谓的“穿透”。

continue 的细节补充

  • 对循环控制变量的影响continue 语句不会影响循环控制变量的更新。例如在 for 循环中,continue 之后循环控制变量仍然会按照正常的逻辑更新。例如:

#include <stdio.h>int main() {for (int i = 0; i < 5; i++) {if (i == 2) {continue; // 跳过当前循环的剩余代码}printf("i = %d\n", i);}return 0;
}

输出结果为:

i = 0
i = 1
i = 3
i = 4

可以看到,i 仍然按照正常的逻辑从 0 增加到 4,continue 只是跳过了 i == 2 时的 printf 语句。

  • 在嵌套循环中的表现 :和 break 一样,continue 也只影响它所在的最内层循环。例如:

#include <stdio.h>int main() {for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {if (j == 1) {continue; // 只影响内层循环}printf("i=%d, j=%d\n", i, j);}}return 0;
}

输出结果为:

i=0, j=0
i=0, j=2
i=1, j=0
i=1, j=2
i=2, j=0
i=2, j=2

可以看到,当 j == 1 时,continue 语句跳过了内层循环中 j == 1 的那次迭代,但外层循环仍然正常进行。

3. 其他细节

  • 可读性 :在使用 breakcontinue 时,要注意代码的可读性。过度使用这些语句可能会使代码逻辑变得复杂,难以理解。例如,如果一个循环中有多个 breakcontinue,可能会让人难以跟踪程序的执行流程。在一些情况下,可以通过调整循环条件或者使用标志变量来避免使用 breakcontinue,使代码更加清晰。

  • 性能影响 :在大多数情况下,breakcontinue 对性能的影响可以忽略不计。它们只是改变了程序的控制流,并没有进行复杂的计算。但是,在一些极端情况下(例如在非常大的循环中频繁使用 breakcontinue ),可能会对性能产生一定的影响。不过,这种影响通常比代码的可读性和逻辑正确性要次要得多。

  • 与其他控制语句的配合breakcontinue 可以与其他控制语句(如 ifelseswitch 等)配合使用,以实现复杂的控制逻辑。在使用时,要注意它们的优先级和作用范围,确保程序的逻辑符合预期。例如,在一个 if 语句中使用 breakcontinue,要清楚它们会终止或跳过的是哪个循环。

总之,breakcontinue 是C语言中非常有用的控制语句,但要根据具体的情况合理使用,避免滥用导致代码难以理解和维护。

1.9.2 循环语句的注意点

推荐书中的内容

  • [规则1 - 36] 思想推荐,但是不强制。另外书中代码严重不推荐,外小内大,一般效率是会高一些,但是差别不会特别大,实际测试的时候,出现效率现象出现反直觉现象,也不要意外。

  • [建议1 - 37] 推荐,给两个理由:循环次数明确,便于进行十数计算

  • [规则1 - 38] 推荐,代码量问题要结合场景

  • [规则1 - 39] 部分推荐,代码量问题要结合场景

  • [规则1 - 40] 推荐,实际工作中,也基本很少遇到

  • [规则1 - 41] 推荐

1.10 goto 关键字

基本使用

// 使用goto模拟实现循环
#include <stdio.h>
#include <windows.h>int main()
{int i = 0;START:printf("[\xad]goto running .... \n", i);Sleep(1000);++i;if (i < 10){goto START;}printf("goto end ....\n");system("pause");return 0;
}

可以根据goto关键字,直接跳转到goto后面所指定的标签所对应的位置处,也就是说如果START:放在后面,goto到标签的中间的部分就不会执行了!其实我们想要怎么跳转就怎么跳转!

goto只能在本代码块内进行使用,函数的都不能跨越,文件间就更不用说了!

有什么问题

[规则1 - 42] 推荐

我的建议

很多公司确实禁止使用goto,不过,这个问题我们还是灵活对待,goto在解决很多问题是有有效的。我们可以认为goto引用场景较少,一般不使用,但是必须得知道goto,需要的时候,也必须会用

有人用吗

Linux内核源代码中充满了大量的goto,只能说我们目前,或者很多公司的业务逻辑不是那么复杂


1.11 void 关键字

1.11.1 void a

// 问是否可以定义变量
#include <stdio.h>
#include <windows.h>int main()
{void a;system("pause");return 0;
}

为何 void 不能定义变量

定义变量的本质:开辟空间

void作为空类型,理论上是不应该开辟空间的。即使开了空间,也仅仅作为一个占位符看待

所以,既然无法开辟空间,那么也就无法作为正常变量使用,既然无法使用,编译器干脆就不让他定义变量了。

  • 在vs2013中,sizeof(void)=1(但编译器依旧理解成,无法定义变量)
  • 在Linux中,sizeof(void)=1(但编译器依旧理解成,无法定义变量)

1.11.2 void修饰函数返回值和参数

场景1:void作为函数返回值

// void修饰函数返回值和参数
#include <stdio.h>
#include <windows.h>void show()
{printf("no return value!\n");
}
int main()
{show();system("pause");return 0;
}

如果自定义函数,或者库函数不需要返回值,那么就可以写成void

那么问题来了,可以不写吗?不可以,自定义函数的默认返回值是int!!!

所以,没有返回值,如果不是void,会让阅读你代码的人产生误解:他是不是忘了写,还是想默认int?

结论:void作为函数返回值,代表不需要,这里是一个“占位符”的概念,是告知编译器和给阅读源代码的工程师看的。

【规则1 - 43】推荐

场景2:void 作为函数参数

// void 作为函数参数
// 如果一个函数没有参数,我们可以不写,如test10
#include <stdio.h>
#include <windows.h>int test1() // 函数默认不需要参数
{return 1;
}
int test2(void) // 明确函数不需要参数
{return 1;
}
int main()
{printf("%d\n", test1(10)); // 依旧传入参数,编译器不会告警或者报错printf("%d\n", test2(10)); // 依旧传入参数,编译器会告警(vs)或者报错(gcc)system("pause");return 0;
}

结论:如果一个函数没有参数,将参数列表设置成void,是一个不错的习惯,因为可以将错误明确提前发现

另外,阅读你代码的人,也一眼看出,不需要参数。相当于“自解释”。

阅读书中内容,【规则1-44】推荐

题外话,尽管如此,如果这点你不习惯,也不勉强。

1.11.3 void指针

void不能定义变量,那么void*呢?

#include <stdio.h>#include <windows.h>int main()
{void *p = NULL; // 可以system("pause");return 0;
}

为什么void可以呢?因为void是指针,是指针,空间大小就能明确出来

场景:void* 能够接受任意指针类型

#include <stdio.h>
#include <windows.h>int main()
{void *p = NULL;int *x = NULL;double *y = NULL;p = x; // 同上p = y; // 同上system("pause");return 0;
}

反过来,在vs/gcc中也没有报错。书中编译器很老了,我们严重不推荐

结论:但是我们依旧认为,void*的作用是用来接受任意指针类型的。这块在后面如果想设计出通用接口,很有用

比如:

void *memset ( void * ptr, int value, size_t num );

void * 定义的指针变量可以进行运算操作吗

【规则1 - 45】现场验证,各种标准我们了解一下

//在vs2013中
#include <stdio.h>
#include <windows.h>int main()
{void *p = NULL;p++; // 报错p += 1; // 报错system("pause");return 0;
}
//在gcc4.8.5中
#include <stdio.h>
#include <stdio.h>int main()
{void *p = NULL; // NULL在数值层面,就是0p++; // 能通过printf("%d\n", p); // 输出1p += 1; // 能通过printf("%d\n", p); // 输出2return 0;
}

为什么在不同的平台下,编译器会表现出不同的现象呢?

根本原因是因为使用的c标准版本的问题。具体阅读书。

void * 用来设计通用接口

【规则1 - 46】推荐

1.11.4 void不能代表一个真实的变量

已经讲过,此处略过

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96838.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96838.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/96838.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux相关概念和易错知识点(43)(数据链路层、ARP、以太网、交换机)

目录1.从网络层到数据链路层&#xff08;1&#xff09;MAC地址&#xff08;2&#xff09;IP地址和MAC地址的区别&#xff08;3&#xff09;ARP&#xff08;4&#xff09;不同层之间的关系2.以太网&#xff08;1&#xff09;以太网的帧格式&#xff08;2&#xff09;数据分片的原…

【科研绘图系列】R语言绘制多拟合曲线图

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍 加载R包 数据下载 函数 导入数据 数据预处理 画图 总结 系统信息 介绍 本文通过R语言对海洋微生物群落的动态变化进行了深入分析,并通过可视化技术直观展示了不同环境条件下微…

【React】React 哲学

1. 声明式&#xff08;Declarative&#xff09; React 鼓励开发者 描述 UI 应该是什么样子&#xff0c;而不是逐步操作 DOM。 // 声明式 function Greeting({ name }) {return <h1>Hello, {name}</h1>; }不用手动操作 DOM&#xff08;document.getElementById / in…

一、Python开发准备

目录 一、前言 1、什么是python&#xff0c;为什么学习python? 2、python语言的特点&#xff0c;以及应用场景是什么&#xff1f; 二、前期准备 1、下载python 2、右键管理员身份安装 3、将Python环境配置到环境变量中 三、开发工具 1、开发工具介绍 一、前言 1、什么…

Visual Studio 发布项目 win-86 win-64 win-arm win-arm64 osx-64 osx-64 osx-arm64 ...

Visual Studio 发布项目时&#xff0c;常见的目标平台标识符代表不同的操作系统和处理器架构组合[TOC]( Visual Studio 发布项目时&#xff0c;常见的目标平台标识符代表不同的操作系统和处理器架构组合) 以下是详细解释及对比列表&#xff1a;一、基础概念解析二、各平台标识符…

Redis数据结构之Hash

一、Hash类型简介 Redis的Hash类型是 Redis 3.2 版本引入的一个数据结构,它允许你在一个键下面存储多个字段和值。在 Redis 内部,Hash 类型可以有多种底层数据结构来实现,这取决于存储的数据量和特定的使用模式。哈希类型适用于存储对象,例如用户信息、商品详情等。通过使…

【Linux系统】初见线程,概念与控制

前言&#xff1a; 上文我们讲到了进程间信号的话题【Linux系统】万字解析&#xff0c;进程间的信号-CSDN博客 本文我们再来认识一下&#xff1a;线程&#xff01; Linux线程概念 什么是线程 概念定义&#xff1a; 进程内核数据结构代码和数据&#xff08;执行流&#xff09; 线…

计算机视觉与深度学习 | 具身智能研究综述:从理论框架到未来图景

具身智能研究综述:从理论框架到未来图景 文章目录 具身智能研究综述:从理论框架到未来图景 一、定义与核心特征 二、关键技术体系 2.1 感知-运动融合技术 2.2 认知架构 2.3 强化学习进展 三、发展历程与里程碑 3.1 理论奠基期(1990-2005) 3.2 技术探索期(2006-2015) 3.3 …

玩转deepseek之自动出试卷可直接导出word

小伙伴们&#xff0c;最近有新同事入职&#xff0c;经理让我出一个关于sqlserver相关的试卷&#xff0c;想着既然有deepseek&#xff0c;我们就偷懒下直接用deepseek给我们自动生成出来。打开deepseek官网&#xff0c;输入提示词&#xff1a;出一套SQL的试题要有基础考察&#…

Flutter 语聊房项目 ----- 礼物特效播放

在语聊房项目中&#xff0c;礼物特效播放是一个常见的需求&#xff0c;通常包括动画、声音等多种媒体形式。为了处理不同的礼物类型&#xff0c;我们可以采用抽象的设计方法&#xff0c;使得系统易于扩展和维护。设计架构思路&#xff1a;抽象礼物特效接口&#xff1a;定义一个…

如何实现文件批量重命名自动化

在编程、设计、数据处理等工作中&#xff0c;脚本或软件往往要求文件名符合特定格式。 批量重命名可快速将文件调整为所需命名规则&#xff0c;避免手动操作出错。 它的体积不到300KB&#xff0c;解压后直接运行&#xff0c;完全绿色无安装。 界面清爽&#xff0c;操作直观&a…

【数据结构——图与邻接矩阵】

引入 树的遍历方式可分为深搜和广搜&#xff0c;这同样适用于图&#xff0c;不过有些地方会有出入。 树的节点结构从根到叶子节点都是1&#xff1a;n,到叶子节点后就没有了。而对于图来说&#xff0c;如果到了最底下的节点&#xff0c;它可能除了连接已经记录过的上层节点&am…

Quarkus - 超音速亚原子Java,开启云原生应用新视界!

Quarkus - 超音速亚原子Java框架 Quarkus 是一个以云为中心、优先考虑&#xff08;Linux&#xff09;容器的框架&#xff0c;专为编写 Java 应用而设计。它旨在帮助开发者更轻松地构建和部署大规模的容器化 Java 应用&#xff0c;采用了一系列现代开发理念和标准。 核心特点 …

如何查看GPU运行情况:使用 Conda 安装 nvitop 新手指南

文章目录 🔍 1. 为什么推荐使用 Conda 环境安装 📥 2. 安装步骤 步骤 1: 安装 Miniconda 或 Anaconda (如果你还没有安装的话) 步骤 2: 创建并激活一个专门的 Conda 环境 步骤 3: 在 Conda 环境中安装 nvitop 步骤 4: 验证安装 ⚠️ 3. 疑难解答 📖 4. nvitop 的基本使用…

遥感机器学习专栏简介

专栏定位与受众本专栏聚焦「机器学习 遥感应用」的落地实践&#xff0c;专为遥感相关专业大学生、刚入门的遥感工程师、机器学习爱好者打造。避开纯理论堆砌&#xff0c;以「实验课式实操」为核心&#xff0c;帮你解决 “懂理论但不会用代码落地”“遥感数据处理与模型结合难”…

【更新至2024年】1996-2024年各省农业总产值数据(无缺失)

【更新至2024年】1996-2024年各省农业总产值数据&#xff08;无缺失&#xff09; 1、时间&#xff1a;1996-2024年 2、来源&#xff1a;国家统计局、各省年检 3、指标&#xff1a;农业总产值 4、范围&#xff1a;31省 5、缺失情况&#xff1a;无缺失 6、指标解释&#xf…

大语言模型预训练流程

大语言模型训练流程 Pre-training → SFT → RLHF阶段1&#xff1a;预训练Pre-training 海量无标注文本数据训练自监督学习机制学习语言基础知识掌握语法、语义、常识形成语言表示能力 核心目标&#xff1a;建立模型的语言理解和文本生成基础能力 阶段2&#xff1a;监督微调Sup…

Zookeeper:分布式协调服务

一、概念ZooKeeper 是一个分布式的、开源的分布式应用程序协调服务&#xff0c;为分布式应用提供一致性、配置管理、命名服务、分布式同步和组服务等。可以把它想象成一个为分布式系统提供的“文件系统”“通知机制”&#xff0c;但它存储的不是普通的文件&#xff0c;而是少量…

海盗王客户端BMP纹理图片解密

海盗王客户端的纹理贴图bmp文件有些是加密&#xff0c;很多人想解密并修改替换&#xff0c;现在给出解密的python代码&#xff1a; import os import struct import copy from pathlib import Pathclass TexEncode:def __init__(self):self.MAGIC_BYTES bmp.x # 魔法字节标识…

《链式二叉树常用操作全解析》

目录 一.求链式二叉树节点个数 二.求链式二叉树叶子节点个数 三.求链式二叉树第k层节点个数 四.求链式二叉树的深度/高度 五.链式二叉树查找值为x的节点 六.链式二叉树的销毁 七. 测试函数 八. 总结: 前言: 在学习链式二叉树的常用操作之前 我们需要手动创建一个二叉树 在…