C语言结构体,枚举,联合

系列文章目录

第一章 C语言基础知识

第二章 C语言控制语句

第三章 C语言函数详解

第四章 C语言数组详解

第五章 C语言操作符详解

第六章 C语言指针详解

第七章 C语言结构体详解

第八章 详解数据在内存中的存储

第九章 C语言指针进阶


文章目录

1. 结构体

1.1 声明结构体

2.2 自引用结构

1. 单链表

2. 双链表

3. 二叉树

2.3 结构体变量的定义和初始化

2.4 结构体内存对齐

2.5 修改默认对齐数

2.6 结构体传参

1. 通过值传递结构体

2. 通过指针传递结构体

2. 位段

2.1 定义位段

2.2 位段的内存分配

3. 枚举

3.1 枚举类型的定义

3.2 使用枚举

4. 联合

4.1 联合类型的定义

4.2 使用联合

4.3 联合大小的计算


1. 结构体

1.1 声明结构体

struct Tag {type member1;type member2;...type memberN;
};
  • struct:关键字,用于定义结构体。
  • Tag:结构体的标签(可选),可以用来声明该类型的变量。
  • member1, member2, ..., memberN:结构体成员,可以是任意数据类型,包括整型、浮点型、字符型、数组、甚至其他结构体。

代码示例:定义一个表示人的结构体:

struct Person {char name[50];int age;float height;
};

2.2 自引用结构

自引用结构是指在结构体定义中包含至少一个指向同类型结构体的指针。这个指针可以用来指向具有相同结构的其他实例,从而形成一个链式或树形结构。

示例:定义自引用结构体

链表结构,其中每个节点包含一个整数数据和指向列表中下一个节点的指针。

struct Node {int data;       // 存储的数据struct Node *next;  // 指向下一个节点的指针
};
1. 单链表

在单链表中,每个节点包含数据和一个指向下一个节点的指针。这种结构可以用来实现队列、栈或其他动态数据集合。

void printList(struct Node *node) {while (node != NULL) {printf("%d ", node->data);node = node->next;}
}
2. 双链表

在双链表中,每个节点除了有指向下一个节点的指针外,还有一个指向前一个节点的指针,允许在两个方向上遍历列表。

struct DNode {int data;struct DNode *prev;struct DNode *next;
};
3. 二叉树

在二叉树的实现中,每个节点包含数据和两个指向子节点的指针(左子节点和右子节点)。这种结构用于实现高效的搜索、插入和删除操作。

struct TreeNode {int value;struct TreeNode *left;struct TreeNode *right;
};

2.3 结构体变量的定义和初始化

定义结构体类型

struct Person {char name[100];int age;float height;
};

定义结构体变量

struct Person person1;
//定义了一个名为 person1 的变量,其类型为 struct Person

初始化结构体变量

struct Person person1 = {"TENET", 20, 2};

初始化结构体数组

结构体数组可以在定义时初始化

struct Person team[2] = {{"TENET", 20, 2},{"VENOM", 21, 2.1}
};

动态初始化

结构体的初始化也可以在程序执行中进行,尤其是当结构体的值需要在运行时确定时.

struct Person person3;
strcpy(person3.name, "TENET");  // 使用 strcpy 来复制字符串
person3.age = 20;
person3.height = 2.1;

完整代码示例:

#include <stdio.h>// 定义一个名为 Point 的结构体,包含两个整数成员:x 和 y
struct Point
{int x; // x坐标int y; // y坐标
} p1; // 在定义类型的同时,声明了一个 Point 类型的变量 p1// 单独声明一个 Point 类型的变量 p2
struct Point p2;// 初始化:定义变量的同时赋初值
struct Point p3 = {1, 2}; // 使用列表初始化的方式初始化 p3,将 x 设置为 1,y 设置为 2// 定义一个名为 Stu 的结构体,包含一个字符数组和一个整数
struct Stu // 类型声明
{char name[15]; // 存储名字的字符数组int age;       // 存储年龄的整型
} s = {"zhangsan", 20}; // 定义并初始化 Stu 类型的变量 s// 定义一个名为 Node 的结构体,该结构体嵌套了 Point 结构体并包含一个指向自己类型的指针
struct Node
{int data; // 存储一个整数数据struct Point p; // 嵌套一个 Point 结构体struct Node* next; // 指向下一个 Node 结构体的指针
} n1 = {10, {4,5}, NULL}, // 初始化 n1,设置 data 为 10, p 的 x 和 y 分别为 4 和 5,next 为 NULLn2 = {20, {5, 6}, NULL}; // 同样初始化 n2,数据设置类似但不同于 n1int main() {// 打印 n1 和 n2 的内容以验证初始化是否成功printf("n1 data: %d, point: (%d, %d)\n", n1.data, n1.p.x, n1.p.y);printf("n2 data: %d, point: (%d, %d)\n", n2.data, n2.p.x, n2.p.y);return 0;
}

2.4 结构体内存对齐

为什么需要内存对齐

内存对齐的主要目的是为了优化数据访问速度。大多数硬件平台对特定类型的数据访问有最佳的自然边界。例如,某些处理器访问一个整型数(通常是4字节)更有效率,如果它位于一个4字节的边界上。如果数据没有对齐,处理器可能需要多次访问内存来读取或写入单个数据项,这会降低程序的性能。

结构体对齐的规则

每个结构体成员相对于结构体起始的偏移量应该是该成员大小的整数倍。例如,如果一个成员是4字节整数,则其偏移量应该是4的倍数。

结构体的总大小也应该是其最宽基本类型成员大小的整数倍。如果不是,编译器会在结构体的末尾添加填充字节(padding),使其总大小符合这一规则。总的来说,就是让占用空间小的成员尽量集中在一起。

结构体示例:

struct Example {char a;    // 1 字节int b;     // 4 字节char c;    // 1 字节
};

内存布局是:

  • char a 直接放在起始位置。
  • 为了确保 int b 对齐到4字节边界,编译器在 char a 后面添加3字节的填充。
  • int b 放在第4字节位置。
  • char c 放在 int b 后面,紧接着是额外的填充字节,以确保整个结构体的大小是4的倍数(如果需要的话)。

练习:

struct S1
{char c1; // 占用 1 字节int i;   // 占用 4 字节,但因为对齐需求,c1 后面会有 3 字节的填充char c2; // 占用 1 字节
};
printf("%d\n", sizeof(struct S1)); // 输出结构体大小
  • 内存对齐:int 类型通常需要按 4 字节对齐。因此,char c1 后会有 3 字节的填充,以使 int i 在 4 字节边界上对齐。
  • 总大小:1字节 (c1) + 3字节 (填充) + 4字节 (i) + 1字节 (c2) = 9字节。但整个结构体也可能要对齐到 4 字节边界,因此实际大小可能为 12 字节(取决于具体的编译器和平台设置)。
struct S2
{char c1; // 占用 1 字节char c2; // 紧接着 c1,占用 1 字节int i;   // 需要对齐到 4 字节边界,因此 c2 后有 2 字节填充
};
printf("%d\n", sizeof(struct S2)); // 输出结构体大小
  • 内存对齐:为了让 int i 对齐到 4 字节边界,char c2 后需要填充 2 个字节。
  • 总大小:1字节 (c1) + 1字节 (c2) + 2字节 (填充) + 4字节 (i) = 8字节。
struct S3
{double d; // 占用 8 字节char c;   // 占用 1 字节,后面需要 7 字节填充以对齐 `int`int i;    // 占用 4 字节,需要对齐到 4 字节边界
};
printf("%d\n", sizeof(struct S3)); // 输出结构体大小
  • 内存对齐:double 类型通常需要按 8 字节对齐。为了让 int i 对齐到 4 字节边界,char c 后需要 7 字节的填充。
  • 总大小:8字节 (d) + 1字节 (c) + 7字节 (填充) + 4字节 (i) = 20字节。
struct S4
{char c1;   // 占用 1 字节struct S3 s3; // 嵌套结构体 S3,前面有 7 字节填充double d;  // 占用 8 字节,按 8 字节对齐
};
printf("%d\n", sizeof(struct S4)); // 输出结构体大小
  • 内存对齐:struct S3 已经分析为需要 20 字节,且需要按 8 字节对齐。char c1 后需要填充 7 字节,以确保 struct S3 s3 正确对齐。
  • 总大小:1字节 (c1) + 7字节 (填充) + 20字节 (s3, 嵌套结构体的大小) + 8字节 (d) = 36字节。

2.5 修改默认对齐数

#pragma 这个预处理指令,可以改变默认对齐数。

#include <stdio.h>#pragma pack(8) // 设置默认对齐数为 8
struct S1
{char c1; // 1 字节int i;   // 4 字节,但由于对齐设置为 8,c1 后将填充 7 字节,使 i 对齐到 8 字节边界char c2; // 1 字节,由于对齐设置,c2 后可能填充至 8 字节边界
};
#pragma pack() // 取消设置的默认对齐数,还原为默认#pragma pack(1) // 设置默认对齐数为 1
struct S2
{char c1; // 1 字节int i;   // 4 字节,紧接 c1,无需添加填充char c2; // 1 字节,紧接 i
};
#pragma pack() // 取消设置的默认对齐数,还原为默认int main()
{// 输出结构体的大小printf("%d\n", sizeof(struct S1)); // 根据对齐规则和成员定义,预期的大小printf("%d\n", sizeof(struct S2)); // 根据对齐规则和成员定义,预期的大小return 0;
}

对于 struct S1,其对齐设置为 8 字节:

  • char c1 占用 1 字节,后面紧跟 7 字节填充,使得 int i 对齐到下一个 8 字节边界。
  • int i 占用 4 字节。
  • char c2 占用 1 字节,可能跟随 7 字节的填充,以确保整个结构体的大小为最大成员对齐(8 字节的倍数)。
  • sizeof(struct S1) 通常为 16 字节(1 字节 c1 + 7 字节填充 + 4 字节 i + 1 字节 c2 + 3 字节填充以达到8的倍数)。

对于 struct S2,其对齐设置为 1 字节:

  • char c1 占用 1 字节。
  • int i 紧接 c1,占用 4 字节,不需要填充因为对齐要求已经是 1 字节。
  • char c2 紧接 i,占用 1 字节。
  • 因此,sizeof(struct S2) 为 6 字节(1 字节 c1 + 4 字节 i + 1 字节 c2)。

2.6 结构体传参

1. 通过值传递结构体

当结构体通过值传递给函数时,实际上是传递结构体的一个副本。这意味着函数内部对结构体成员的任何修改都不会影响原始结构体。

代码示例

#include <stdio.h>struct Point {int x, y;
};// 函数接收结构体副本
void movePoint(struct Point p) {p.x += 1;p.y += 1;printf("Inside function: x = %d, y = %d\n", p.x, p.y);
}int main() {struct Point pt = {10, 20};movePoint(pt);  // 传递副本printf("Outside function: x = %d, y = %d\n", pt.x, pt.y);  // 原始数据未改变return 0;
}

2. 通过指针传递结构体

当结构体通过指针传递给函数时,传递的是结构体的地址,允许函数直接访问并修改原始结构体的数据。

代码示例:

#include <stdio.h>struct Point {int x, y;
};// 函数接收结构体指针
void movePoint(struct Point *p) {p->x += 1;p->y += 1;printf("Inside function: x = %d, y = %d\n", p->x, p->y);
}int main() {struct Point pt = {10, 20};movePoint(&pt);  // 传递指针printf("Outside function: x = %d, y = %d\n", pt.x, pt.y);  // 数据已被修改return 0;
}

2. 位段

位段(Bit-fields)是一种数据结构,用于访问结构体中的对象的指定数目的位。

位段的声明和结构是类似的,但有两个不同:
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。

2.1 定义位段

位段在结构体中定义,每个位段成员后面需要指定它所占用的位数。位段的声明通常涉及一个整数类型(如 int、unsigned int 或 signed int),后面紧跟冒号和位数。

struct TEST {unsigned int a : 1;  // 占用 1 位unsigned int d : 5;  // 填充 5 位
};
// TEST是一个位段类型

2.2 位段的内存分配

位段是连续存储的,并尽可能紧凑地放在一起,但它们的布局和总占用空间大小依赖于特定的编译器实现和对齐规则。

代码示例:

struct S
{char a:3;  // 定义一个位段 a,占用 3 位char b:4;  // 定义一个位段 b,占用 4 位char c:5;  // 定义一个位段 c,占用 5 位char d:4;  // 定义一个位段 d,占用 4 位
};
struct S s = {0};  // 使用列表初始化将所有位段初始化为 0
s.a = 10;  // 给位段 a 赋值为 10
s.b = 12;  // 给位段 b 赋值为 12
s.c = 3;   // 给位段 c 赋值为 3
s.d = 4;   // 给位段 d 赋值为 4
  • 位段定义:a, b, c, 和 d 分别占用 3, 4, 5, 和 4 位。尽管它们被定义为 char 类型,这仅仅意味着这些位段是从一个 char 类型的存储单元中分配的,实际上它们占用的是指定的位数。
  • 初始化:初始化时,所有位段被设为 0。这是通过 {0} 完成的,确保结构体开始时所有位都是清零的。
  • 赋值:之后,为每个位段赋予了一个新值。注意赋值时要考虑位段的溢出。例如,a:3 表示 a 可以存储的最大值是 23−1=723−1=7(因为是无符号值)。因此,赋值 10 实际存储的是 10 % 8 = 2。

3. 枚举

3.1 枚举类型的定义

枚举就是把可能的取值一一列举,枚举通过关键字 enum 定义。枚举的定义会创建一个新的数据类型名称,可以列举出所有可能的枚举值。每个枚举值都是一个整数(通常是 int 类型),默认从 0 开始,每个后续的值递增 1。你也可以显式指定枚举值的数值。
enum enum_name {constant1,constant2,constant3,...
};

示例:定义一个枚举

enum Day {Sunday,    // 默认为 0Monday,    // 默认为 1Tuesday,   // 默认为 2Wednesday, // 默认为 3Thursday,  // 默认为 4Friday,    // 默认为 5Saturday   // 默认为 6
};

也可以指定特定的数值:

enum Day {Sunday = 1,Monday,Tuesday = 5,Wednesday,Thursday = 10,Friday,Saturday
};

在这个例子中,Monday 将自动被赋值为 2(因为它紧跟在值为 1 的 Sunday 后面),Wednesday 为 6(紧跟在值为 5 的 Tuesday 后面),Friday 为 11(紧跟在值为 10 的 Thursday 后面)。

3.2 使用枚举

枚举类型可以用来声明变量。这些变量可以存储任何在枚举中定义的值:

enum Day today;
today = Monday;if (today == Monday) {printf("Start of work week.\n");
}

枚举与整数的关系

枚举在 C 语言中本质上是整数。你可以在不进行显式类型转换的情况下,将枚举值赋给整数变量:

int day = today;        
enum Day tomorrow = 3;  // 隐含星期四,如果从星期日开始 = 0

4. 联合

4.1 联合类型的定义

联合(共用体)是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。联合可以包含多个不同类型的成员,但任何时候只能存储其中一个成员的值。

联合通过关键字 union 定义,与结构体定义相似。联合体的定义创建了一个可以存储多个不同类型数据,但每次只能使用其中一个的数据类型。

union UnionName {type1 member1;type2 member2;type3 member3;...
};

代码示例:

定义一个联合,这个联合可以用来存储整数、浮点数和字符指针。不管哪种类型的数据被存储,它们都使用同一块内存区域。

union Data {int i;float f;char *str;
};

4.2 使用联合

联合的使用类似于结构体,但需要记住的关键是联合存储的是同一块内存区域。因此,更改一个成员的值将影响到其他成员。

#include <stdio.h>// 定义一个联合 Data,可以存储一个整数、一个浮点数或一个字符指针
union Data {int i;    // 可存储整数float f;  // 可存储浮点数char *str; // 可存储字符指针
};int main() {union Data data;  // 声明一个 Data 类型的联合变量data.i = 10;  // 将整数 10 存储在联合的内存中printf("data.i : %d\n", data.i);  // 打印整数字段,输出 "data.i : 10"data.f = 220.5;  // 将浮点数 220.5 存储在同一块内存中,这会覆盖之前存储的整数printf("data.f : %.1f\n", data.f);  // 打印浮点数字段,输出 "data.f : 220.5"printf("data.i (corrupted) : %d\n", data.i);  // 再次打印整数字段,但由于内存已被浮点数覆盖,输出的值是未定义的(corrupted)data.str = "Hello World";  // 将字符串 "Hello World" 的指针存储在同一块内存中,这会覆盖之前存储的浮点数printf("data.str : %s\n", data.str);  // 打印字符串字段,输出 "data.str : Hello World"printf("data.f (corrupted) : %.1f\n", data.f);  // 再次打印浮点数字段,但由于内存已被字符串指针覆盖,输出的值也是未定义的(corrupted)return 0;
}

联合 Data 允许其成员 i、f 和 str 共享同一内存区域。该内存区域的大小等于其最大成员的大小,这里是 float 或 char*(具体取决于平台,通常这两种类型在现代架构上大小相同,都是 4 或 8 字节)。

当联合的一个成员被赋值时,它会覆盖联合内存中的当前内容。如果随后访问同一联合的另一个成员,得到的将是一个不确定的值,这是因为存储的位模式对于其他类型可能没有意义。这在程序中体现为给 data.f 赋值后访问 data.i,以及给 data.str 赋值后访问 data.f。

4.3 联合大小的计算

联合体的大小取决于其最大成员的大小,因为所有成员共用同一块内存空间。

union Un1 {char c[5]; // char 类型数组,占用 5 字节int i;     // int 类型,大小通常为 4 字节
};
union Un2 {short c[7]; // short 类型数组,每个 short 占用 2 字节,总共占用 14 字节int i;      // int 类型,大小通常为 4 字节
};
  • Un1 的大小将是其最大成员的大小,即 char 数组 c 的大小(5 字节)。不过,由于 int 类型可能需要按照特定的边界对齐(比如 4 字节对齐),联合体的实际大小可能需要向上取整到更大的对齐边界。具体的大小取决于编译器和平台,但如果 int 需要 4 字节对齐,Un1 的大小应该是 8 字节。
  • Un2 的大小将是其最大成员的大小,即 short 数组 c 的大小(14 字节)。和 Un1 一样,如果 int 需要 4 字节对齐,那么 Un2 的大小可能需要增加额外的填充,以满足对齐要求。然而,因为 14 已经是 2 的倍数(short 类型的自然对齐边界),Un2 不需要额外的填充就可以保证 int 成员对齐,所以 Un2 的大小应该是 14 字节。

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

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

相关文章

kubebuilder(2)创建项目及初始化

一个demo项目来了解kubebuilder的项目结构 初始化项目 mkdir demo-operator cd demo-operator kubebuilder init --domain demo.com --repo demo.com/tutorial 这一步创建了 Go module 工程基本的模板文件&#xff0c;引入了必要的依赖 如果不用--repo参数&#xff0c;也可…

【Qt 学习笔记】Qt常用控件 | 按钮类控件 | Push Button的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 按钮类控件 | Push Button的使用及说明 文章编号&#x…

mysql基础6——多表查询

外键 把分散在多个不同表里面的数据查询出来的操作&#xff0c;就是多表查询 把两个表连接&#xff1a;使用外键(foreign key)和连接(join) 外键在表创建的阶段定义也可以通过修改表定义&#xff0c;连接在查询字段把相同意义的字段连接起来 外键就是从表中用来引用主表中数…

C# 开源SDK 工业相机库 调用海康相机 大恒相机

C# MG.CamCtrl 工业相机库 介绍一、使用案例二、使用介绍1、工厂模式创建实例2、枚举设备&#xff0c;初始化3、启动相机4、取图5、注销相机 三、接口1、相机操作2、启动方式3、取图4、设置/获取参数 介绍 c# 相机库&#xff0c;含海康、大恒品牌2D相机的常用功能。 底层采用回…

ai扩写软件有哪些免费的?分享4款扩写好用的!

随着人工智能技术的飞速发展&#xff0c;AI扩写软件逐渐成为了内容创作者们的得力助手。它们能够迅速将简短的文案扩写成内容丰富、结构完整的文章&#xff0c;大大提高了创作效率。本文将为您盘点几款免费的AI扩写软件&#xff0c;助您在今日头条、百家号等自媒体平台上轻松打…

P8837 [传智杯 #3 决赛] 商店(贪心加双指针)

题目背景 思路解析:很经典的贪心问题,把物品按照从便宜到贵的顺序排好序,然后按照富贵程度排人,直接暴力会tle所以这里采用双指针. #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<string> using namesp…

quill富文本编辑器中文汉化和高度设置操作

quill文档&#xff1a;Installation - Quill Rich Text Editor quill仓库&#xff1a;GitHub - quilljs/quill: Quill is a modern WYSIWYG editor built for compatibility and extensibility. quill默认是英文的&#xff0c;并且高度也是只有一行&#xff0c;所以想自定义高…

C++——类和对象练习(日期类)

日期类 1. 构造函数和析构函数2. 拷贝构造和赋值运算符重载3. 运算符重载3.1 日期的比较3.2 日期加减天数3.3 日期减日期3.4 流插入和流提取 4. 取地址和const取地址重载5. 完整代码Date.hDate.c 对日期类进行一个完善&#xff0c;可以帮助我们理解六个默认成员函数&#xff0c…

软件行业中的蓝海领域有哪些?

一、什么是蓝海&#xff1f; 蓝海&#xff0c;指的是未知的市场空间。这个概念相对于“红海”而言&#xff0c;红海则是指已知的市场空间。 企业要启动和保持获利性增长&#xff0c;就必须超越产业竞争&#xff0c;开创全新市场&#xff0c;这其中包括两块&#xff1a;一块是…

【软件测试】Selenium实战技巧-多页面和Windows控件处理

01 多页面处理 做UI自动化的时候常常会遇到浏览器弹出新的Tab页&#xff0c;或者需要在多个网页服务之间来回取数据的情况。 比如在首页点击文章“Jmeter使用&#xff1f;”的链接&#xff0c;浏览器会弹出一个新的页面显示“Jmeter使用&#xff1f;”这篇文章的详情。此时如…

Python多线程与多进程编程

一、引言 随着计算机技术的飞速发展&#xff0c;程序运行的速度和效率成为了人们关注的焦点。为了提高程序的执行效率&#xff0c;多线程与多进程编程技术应运而生。Python作为一种通用编程语言&#xff0c;在支持多线程与多进程编程方面有着独特的优势。本文将详细探讨Python…

书生·浦语大模型实战营之 XTuner 微调 Llama 3 个人小助手认知

书生浦语大模型实战营之 XTuner 微调 Llama 3 个人小助手认知 Llama 3 近期重磅发布,发布了 8B 和 70B 参数量的模型,XTuner 团队对 Llama 3 微调进行了光速支持!!!开源同时社区中涌现了 Llama3-XTuner-CN 手把手教大家使用 XTuner 微调 Llama 3 模型。 XTuner:http://…

牛客NC238 加起来和为目标值的组合【中等 DFS C++、Java、Go、PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/172e6420abf84c11840ed6b36a48f8cd 思路 本题是组合问题&#xff0c;相同元素不同排列仍然看作一个结果。 穷经所有的可能子集&#xff0c;若和等于target&#xff0c;加入最终结果集合。 给nums排序是为了方便…

计算机网络【CN】Ch4 网络层

总结 一台主机可以有多个IP地址&#xff0c;但是必须属于多个逻辑网络【不同的网络号】。 解决IP地址耗尽&#xff1a; IP地址结构&#xff1a; 划分子网&#xff1a;&#x1d43c;&#x1d443;地址<网络号>,<子网号>,<主机号> CIDR&#xff1a;IP地址{&…

智能算法 | Matlab基于CBES融合自适应惯性权重和柯西变异的秃鹰搜索算法

智能算法 | Matlab基于CBES融合自适应惯性权重和柯西变异的秃鹰搜索算法 目录 智能算法 | Matlab基于CBES融合自适应惯性权重和柯西变异的秃鹰搜索算法效果一览基本介绍程序设计参考资料效果一览 基本介绍 Matlab基于CBES融合自适应惯性权重和柯西变异的秃鹰搜索算法 融合自适应…

pycharm爬虫模块(scrapy)基础使用

今天学了个爬虫。在此记录 目录 一.通过scrapy在命令行创建爬虫项目 二.判断数据为静态还是动态 三.pycharm中的设置 三:爬虫主体 四.pipelines配置&#xff08;保存数据的&#xff09; 五.最终结果 一.通过scrapy在命令行创建爬虫项目 1.首先需要在cmd中进入到python文…

华为od机试真题——智能成绩表

题目描述 算法结果 3 3 math chinese english z3 71 81 91 l4 81 71 93 w5 21 91 95 math l4 81 71 93 245 z3 71 81 91 243 w5 21 91 95 207 算法详情 public class SmartScoreTable {public static void main(String[] args) {// 输入Scanner scanner new Scanner(Syste…

一款pdf工具

下载链接&#xff1a;点击跳转&#xff1b; 它是一个installer&#xff0c;下好它之后&#xff0c;把网断掉&#xff0c;然后双击它&#xff0c;他会默认安装在C盘&#xff0c;安装时&#xff0c;浏览器可能会有一个弹窗&#xff0c;直接关掉并进入任务管理器杀掉所有smallerp…

小清新思维题

CF521D shop Problem Solution 首先如果确定了执行的操作&#xff0c;执行顺序一定为赋值、加、乘。赋值操作只保留最大的&#xff0c;并可以转化为加法。每个数的加法操作按从大到小顺序排序后可以转化为乘法。最后将所有乘法操作从大到小排序选前&#x1d45a;个即可。 先…

VMware 15 虚拟机网络遇到的问题

剧情提要 通过Cent os7 的镜像文件&#xff0c;创建了一个虚拟机A&#xff08;后面简称A&#xff09;&#xff0c;事后发现&#xff0c;宿主机无法ping通A 在虚拟机中通过IP a 看到的IP信息也没有只管的ip信息如图 然后执行&#xff0c;宿主机才能访问A。 sudo dhclient ens…