C语言实现通讯录 (附完整代码)

C语言实现通讯录

  • 🍀实现一个通讯录:
  • 🍀通讯录的功能:
  • 🍀多文件实现
  • 💮设计结构体——保存人的信息
  • 💮初始通讯录
  • 💮封装通讯录
  • 💮define宏定义修改通讯录的最大容量
  • 初始化通讯录
  • 💐💐大致框架
  • 💐改进--枚举 提高代码的可读性
  • 🌼🌼定义函数实现功能
    • 🌼AddContact
    • 🌼ShowContact
    • 🌼DelContact
    • 🌼进一步改进
    • 🌼SearchContact
    • 🌼ModifyContact
    • 🌼Sort Contact
  • 🎆🎆🎆完整代码

🍀实现一个通讯录:

通讯录中保存人的信息:
名字
年龄
性别
电话
住址

🍀通讯录的功能:

1.通讯录可以存放100个人的信息
2.显示所有联系人的信息
3.排序功能
4.增:增加联系人
5.删:删除指定联系人
6.查:查找指定联系人
7.改:修改指定联系人

🍀多文件实现

test.c 测试通讯录
contact.h 函数和类型的声明
contact.c 函数的实现

💮设计结构体——保存人的信息

初级:

struct PeoInfo
{char name[20];int age;char sex[5];//一个汉字占两个字符char tele[12];char addr[30];
};

结构体的引用:

struct PeoInfo num1 ;
struct PeoInfo num2;
struct PeoInfo data[50];

改进:
考虑到每次使用结构体都需要写 struct PeoInfo比较繁琐,能不能直接把struct自己省略掉呢?
这时候就需要对改结构体进行重命名typedef

typedef struct PeoInfo
{char name[20];int age;char sex[5];char tele[12];char addr[30];
}PeoInfo;

这样,当我们使用结构体时,就不用用 struct PeoInfo了,直接使用PeoInfo就可以了。

💮初始通讯录

因为我们刚刚定义了结构体用来存储人的信息,但一个通讯录中有很多人,我们上面设置了该通讯录可以存放100个人的信息,所以我们需要用结构体数组将每一个类型都是结构体的元素存储起来。
C语言定义结构体数组一般形式:

结构体类型 数组名[数组长度];

所以我们定义 通讯录:

PeoInfo data[100];

同时,我们需要一个变量,来判断通讯录里已经存放数据的个数。(以防止在增添联系人时,超过了定义的通讯录的最大容量)

int sz=0;

💮封装通讯录

在上面考虑到通讯录PeoInfo data[100]和变量 sz是一种封锁的关系。即,sz等于几,PeoInfo data里面就有几个数据元素。sz加1,则PeoInfo data数组里会再存放一个元素。
所以,我们考虑将通讯录进行进一步的封装,构建一个结构体

typedef struct Contact
{PeoInfo data[100];int sz;
}Contact;

这时,我们的通讯录就为 con

Contact con;

💮define宏定义修改通讯录的最大容量


在这里插入图片描述
同样我们也可以对 我们刚开始定义的 姓名、地址、联系方式等 以同样的宏定义进行转变。

初始化通讯录

将通讯录初始化为0。可以定义一个函数,用来初始化通讯录。

void InitContact(Contact* pc)
{memset(pc->data, 0, sizeof(pc->data);pc->sz = 0;
}

因为我们要改变通讯录的内部,所以函数参数是一个地址值,类型是我们定义的通讯录结构体 Contact类型。
利用memset函数,将结构体中数组所有元素全部赋值为0.同时将pc所指向的sz也初始化为0.

void InitContact(Contact* pc)
{memset(pc->data, 0, sizeof(pc->data);pc->sz = 0;
}

💐💐大致框架

接下来,我们在void test ()函数中写一下大概的框架:
(因为要尽可能避免在主函数中太过冗长,所以我们把通讯录的具体实现——增删查找等等都放在test函数中,之后我们就只需要在主函数中进行调用即可。)

首先,我们可以用do...while循环 打印一个菜单。
定义一个函数 void menu()完成打印。在()函数中调用即可。
之后我们利用switch,对输入的input进行判断,进行相应的操作。对于下面的七种情况,我们可以写七个函数分别实现其相应的功能。

在这里插入图片描述
我们进行的所有操作都是对于通讯录而言的,所以在test函数中必须有通讯录。所以我们将我们已经初始化的通讯录放在函数中。
在这里插入图片描述
不要忘了包含头文件contact.h
(在contact.h头文件中,包含着本身已经封装好的常见的头文件 比如 <stdio.h><string.h>等,还有我们自己对于结构体或者函数的一些声明和定义,比如定义人的信息的结构体 PeoInfo、定义通讯录的 Contact,以及我们函数的声明,完成Contact初始化的函数InitContact等,还有之后,我们要对通讯录进行操作的一系列增删查找函数等函数的声明都会放在都文件中。)
(要注意,函数的定义不是放在头文件中的,而是在contat.c中)

在这里插入图片描述

💐改进–枚举 提高代码的可读性

在这里插入图片描述
在这里插入图片描述

🌼🌼定义函数实现功能

🌼AddContact

在这里插入图片描述

//增加联系人的信息
void AddContact(Contact* pc)
{//判断数组是否可以增添?if (pc->sz == 100){printf("通讯录已满,无法添加\n");return;}//通讯录没满else{printf("请输入名字:>");scanf("%s", pc->data[pc->sz].name);//pc->data 指向的是结构体数组 数组名本身就是地址,不用用取地址符号printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入住址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("增加联系人成功!");}
}

🌼ShowContact

//显示所有联系人的信息
void ShowContact(const Contact* pc)//仅仅是显示,而不修改 所以用const限制修饰
{int i;for (i = 0; i < pc->sz; i++){printf("姓名:%-20s\t", pc->data[i].name);//根据联系人结构体信息printf("年龄:%-4d\t", pc->data[i].age);printf("性别:%-5s\t", pc->data[i].sex);printf("电话:%-12s\t", pc->data[i].tele);printf("住址:%-13s\t", pc->data[i].addr);//统一左对齐printf("\n");}
}


但是,当显示的数据变多的时候,尽管是左对齐,还是不够美观。
接下来,我们采用打印标题的形式,更好的打印出数据。

//显示所有联系人的信息
void ShowContact(const Contact* pc)//仅仅是显示,而不修改 所以用const限制修饰
{int i;//打印列标题printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\t\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}

🌼DelContact

//删除指定联系人
void DelContact(Contact* pc)
{int i = 0;char name[20];int pos = 0;int flag = 0;//输入要删除的人删除printf("请输入要删除人的名字:>");scanf("%s", name);//将要删除的人的名字放入name中(name本就是一个地址值)//查找有没有这个人for (i = 0; i < pc->sz; i ++){if (strcmp(name, pc->data[i].name) == 0) //字符串比较函数{pos = i;//找到了,记下位置flag = 1;}	}if (flag == 0){printf("要删除的人不存在\n");return;}//进行删除for (i = pos; i <pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!");
}

🌼进一步改进

当我们写后面的函数时,我们发现后面的查找函数 还是 修改函数 都需要像 删除函数一样 先在通讯录类进行查找。
为了更高效完成整个工程,提高效率,我们可以来写一个通过名字进行查找的函数FindByName
当我们写 删除 查找 修改函数时,首先可以直接调用这个函数。

int FindByName(Contact* pc, char name[])
{int flag = 0;int i = 0;int pos;for (i = 0; i < pc->sz; i++){if (strcmp(name, pc->data[i].name) == 0) //字符串比较函数{pos = i;//找到了,记下位置return pos;}}if (flag == 0){printf("要删除的人不存在\n");return -1;}}

DelContact函数改进为:

//删除指定联系人
void DelContact(Contact* pc)
{int i = 0;char name[20];int pos = 0;int flag = 0;//输入要删除的人删除printf("请输入要删除人的名字:>");scanf("%s", name);//将要删除的人的名字放入name中(name本就是一个地址值)//查找有没有这个人if ((FindByName(pc, name) == -1)){printf("找不到要删除的联系人");}elsepos = FindByName(pc, name); //记下位置//进行删除for (i = pos; i <pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!");
}

🌼SearchContact

在这里插入图片描述

//查找指定联系人
void SearchContact(const Contact* pc)
{int pos = 0;char name[20] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);//查找有没有指定联系人if (FindByName(pc, name) == -1)printf("没有找到要查找的联系人\n");else{pos = FindByName(pc, name);printf("找到了!\n");printf("该联系人的下标为%d", pos);//打印数据printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\t\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}
}

🌼ModifyContact

在这里插入图片描述


//修改指定联系人
void ModifyContact(Contact* pc)
{int pos = 0;char name[20] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);//查找有没有要修改的联系人if (FindByName(pc, name) == -1)printf("没有找到要修改的联系人\n");else {printf("找到了要修改的联系人!\n");pos = FindByName(pc, name);//修改 (修改可以理解为再次录入一遍信息)printf("请输入名字:>");scanf("%s", pc->data[pos].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos].sex);printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("请输入住址:>");scanf("%s", pc->data[pos].addr);printf("成功修改联系人!");}
}

🌼Sort Contact

//按照名字进行排序
//排序int cmp_name(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
void SortContact(Contact* pc)
{int i = 0;//利用qsort 函数qsort(pc->data, pc->sz, sizeof((pc->data)[0]), cmp_name);//打印列标题printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\t\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}}

🎆🎆🎆完整代码

contact.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#define MAX 100//声明结构体--保存人的信息
typedef struct PeoInfo
{char name[20];int age;char sex[5];//一个汉字占两个字符char tele[12];char addr[30];
}PeoInfo;
//声明结构体通讯录
typedef struct Contact
{PeoInfo data[MAX];int sz;
}Contact;
int FindByName(Contact* pc, char name[]);
void AddContact(Contact* pc);
void ShowContact(const Contact* pc);
void DelContact(Contact* pc);
void SearchContact( Contact* pc);
void SearchContact(Contact* pc);
void SortContact(Contact* pc);enum OPTION
{EXIT,//0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW,//5SORT//6
};//函数的声明--初始化通讯录
void InitContact(Contact* pc);

contact.c

#include "contact.h"void InitContact(Contact* pc)
{memset(pc->data, 0, sizeof(pc->data));pc->sz = 0;
}//增加联系人的信息
void AddContact(Contact* pc)
{//判断数组是否可以增添?if (pc->sz == 100){printf("通讯录已满,无法添加\n");return;}//通讯录没满else{printf("请输入名字:>");scanf("%s", pc->data[pc->sz].name);//pc->data 指向的是结构体数组 数组名本身就是地址,不用用取地址符号printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);printf("请输入住址:>");scanf("%s", pc->data[pc->sz].addr);pc->sz++;printf("增加联系人成功!");}
}//显示所有联系人的信息
void ShowContact(const Contact* pc)//仅仅是显示,而不修改 所以用const限制修饰
{int i;//打印列标题printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\t\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}int FindByName(Contact* pc, char name[])
{int flag = 0;int i = 0;int pos;for (i = 0; i < pc->sz; i++){if (strcmp(name, pc->data[i].name) == 0) //字符串比较函数{pos = i;//找到了,记下位置return pos;}}if (flag == 0){printf("要删除的人不存在\n");return -1;}}//删除指定联系人
void DelContact(Contact* pc)
{int i = 0;char name[20];int pos = 0;int flag = 0;//输入要删除的人删除printf("请输入要删除人的名字:>");scanf("%s", name);//将要删除的人的名字放入name中(name本就是一个地址值)//查找有没有这个人if ((FindByName(pc, name) == -1)){printf("找不到要删除的联系人");}elsepos = FindByName(pc, name); //记下位置//进行删除for (i = pos; i <pc->sz-1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人!");
}//查找指定联系人
void SearchContact( Contact* pc)
{int pos = 0;char name[20] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);//查找有没有指定联系人if (FindByName(pc, name) == -1)printf("没有找到要查找的联系人\n");else{pos = FindByName(pc, name);printf("找到了!\n");printf("该联系人的下标为%d", pos);//打印数据printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\t\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].tele,pc->data[pos].addr);}
}//修改指定联系人
void ModifyContact(Contact* pc)
{int pos = 0;char name[20] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);//查找有没有要修改的联系人if (FindByName(pc, name) == -1)printf("没有找到要修改的联系人\n");else {printf("找到了要修改的联系人!\n");pos = FindByName(pc, name);//修改 (修改可以理解为再次录入一遍信息)printf("请输入名字:>");scanf("%s", pc->data[pos].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos].sex);printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("请输入住址:>");scanf("%s", pc->data[pos].addr);printf("成功修改联系人!");}
}//按照名字进行排序
//排序int cmp_name(const void* p1, const void* p2)
{return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}
void SortContact(Contact* pc)
{int i = 0;//利用qsort 函数qsort(pc->data, pc->sz, sizeof((pc->data)[0]), cmp_name);//打印列标题printf("%-20s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-12s\t%-30s\t\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}}

test.c


#include"contact.h"void menu()
{printf("\n");printf("******************\n");printf("******请选择******\n");printf("******1.增添******\n");printf("******2.删除******\n");printf("******3.查找******\n");printf("******4.修改******\n");printf("******5.显示******\n");printf("******6.排序******\n");printf("******0.退出******\n");}void test()
{Contact con;  //定义结构体变量-通讯录InitContact(&con);//对通讯录进行初始化int input = 0;do{menu();scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelContact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("退出通讯录\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);}
int main()
{test();return 0;
}

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

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

相关文章

Gitlab仓库部署

Gitlab仓库部署 一、Gitlab的概述1、gitlab介绍2、gitlab主要功能3、gitlab和github的区别 二、部署环境1、安装依赖环境2、安装Postfix邮箱3、Gitlab优势4、Gitlab工作流程 三、Gitlab部署过程1、Yum安装Gitlab2、配置gitlab站点URL3、启动并访问Gitlab 四、Gitlab具体操作1、…

C++中的导入include,头文件,extern,main函数入口及相关编译流程

结论&#xff1a; 1&#xff1a;#include就是复制粘贴 2&#xff1a;C编译的时候&#xff0c;在链接之前&#xff0c;各个文件之间实际上没有联系&#xff0c;只有到了链接的阶段&#xff0c;系统才会到各个cpp文件中去找需要的文件&#xff1b; 一&#xff1a;include的作用…

详解混合类型文件(Polyglot文件)的应用生成与检测

1. 引入 混合类型文件&#xff08;Polyglot文件&#xff09;&#xff0c;是指一个文件&#xff0c;既可以是合法的A类型&#xff0c;也可以是合法的B类型。 比如参考3中的文件&#xff0c;是一个html文件&#xff0c;可以用浏览器正常打开&#xff1b;它也是一个一个.jar文件&…

OpenCV之怀旧色、冰冻滤镜、熔铸滤镜

怀旧色 源码&#xff1a; void huaijiu(Mat& src,Mat& dst) {for (int h 0;h < src.rows;h ){uchar *d1 src.ptr<uchar>(h);uchar *d2 dst.ptr<uchar>(h);for (int w 0;w < src.cols;w ){int w3 3*w;int r d1[w3 2];int g d1[w3 1];int …

民用大中型无人直升机系统飞行性能飞行试验要求

声明 本文是学习GB-T 42856-2023 民用大中型无人直升机系统飞行性能飞行试验要求. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了民用大中型无人直升机系统飞行性能飞行试验的内容、目的、条件、实施、数据处理和 结果评定等要…

linux相关知识以及有关指令3

在linux的世界中我们首先要有万物皆文件的概念&#xff0c;那么在系统中有那么多的文件&#xff0c;我们该怎么区分呢&#xff1f;文章目录 1. 文件分类2. 文件的权限1). 拥有者和所属组以及other2). 文件的权限3). 粘滞位4). 对于权限修改的拓展知识点a.修改权限b.修改拥有者所…

【MySQL进阶】SQL性能分析

一、SQL性能分析 1.SQL执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [session|global] status 命令可以提供服务器状态信 息。通过如下指令&#xff0c;可以查看当前数据库的 INSERT 、 UPDATE 、 DELETE 、 SELECT 的访问频次&#xff1a; -- session 是查看当…

Linux学习之基础工具二

经过学习我们已经大致的学会了vim的使用&#xff0c;可以利用vim进行代码的编写了&#xff0c;在学习c语言的时候我们就知道&#xff0c;编译完成一个代码需要进行四个步骤&#xff1a; 1. 预处理&#xff08;进行宏替换) 2. 编译&#xff08;生成汇编) 3. 汇编&#xff08;生…

Java实现计算两个日期之间的工作日天数

需求&#xff1a; 需要在后端实现 计算当前日期与数据库内保存的日期数据之间相隔的工作日数目 实现 import java.time.DayOfWeek; import java.time.LocalDateTime;public class WorkdaysCalculator {public static void main(String[] args) {String givenDateTimeStr &q…

HTTPS Tomcat Servlet 博客系统 软件测试的概念 Linux

第 1 题&#xff08;多选题&#xff09; 题目名称&#xff1a; 以下关于http和https说法正确的是 题目内容&#xff1a; A .http是超文本传输协议 B .https是超文本传输安全协议 C .http是明文传输 D .https是加密传输 第 2 题&#xff08;单选题&#xff09; 题目名称…

【计算机视觉】Image Feature Extractors方法介绍合集(一)

文章目录 一、Convolution二、1x1 Convolution三、Depthwise Convolution四、Pointwise Convolution五、Depthwise Separable Convolution六、Grouped Convolution七、Dilated Convolution八、3D Convolution九、Non-Local Operation十、Deformable Convolution十一、Switchabl…

UI自动化测试神器Playwright(Java版)(保存登录cookie,解决免登录)

&#x1f3ad; Playwright在称为浏览器上下文的隔离环境中执行测试。该隔离模型提高了可重复性并防止相关联的测试脚本执行失败。测试可以加载现有的已验证状态&#xff0c;比如获取已登录的状态&#xff08;Cookie&#xff09;&#xff0c;在后续脚本中复用。这消除了在每个测…

【论文笔记】Perception, Planning, Control, and Coordination for Autonomous Vehicles

单纯作为阅读笔记&#xff0c;文章内容可能有些混乱。 文章目录 1. Introduction2. Perception3. Planning3.1. Autonomous Vehicle Planning Systems3.2. Mission Planning3.3. Behavioral Planning3.4. Motion Planning3.4.1. Combinatorial Planning3.4.2. Sampling-Based P…

web安全漏洞-SQL注入攻击实验

实验目的 学习sql显注的漏洞判断原理掌握sqlmap工具的使用分析SQL注入漏洞的成因 实验工具 sqlmap是用python写的开源的测试框架&#xff0c;支持MySQL&#xff0c;Oracle&#xff0c;PostgreSQL&#xff0c;Microsoft SQL Server&#xff0c;Microsoft Access&#xff0c;I…

解决mybatis-plus不能俩表联查分页之手动写分页

public class MyPageHelper {// 调用pageInfo插件内的方法 开启分页 需要传入一个起始页的值和每页显示的条数public static void startPage(PageRequest pageRequest) {PageHelper.startPage(pageRequest.getPageNum(),pageRequest.getPageSize());}// 封装结果集public stati…

【CMU15-445 Part-11】Join Algorithms

Part11-Join Algorithms Why Do We Need to Join? Join其实是关系数据库和范式化表时候所产生的副产物。 也就是说我们范式化表是为了减少冗余信息&#xff0c;而我们使用join就是为了去重建reconstruct 这些原本的tuple Join Algorithms 主要关注两表的inner equijoin a…

01_网络编程_传统IO

网络编程 1.什么是网络编程 在网络通信协议下&#xff0c;不同计算机上运行的程序&#xff0c;进行的数据传输。 如果想把一个计算的结果&#xff0c;或者是电脑上的文件通过网络传递给你的朋友&#xff0c;就需要用到网络编程。 在实际生活中&#xff0c;网络通信无处不在…

Windows 10 Enterprise LTSC 2021 (x86) - DVD (Chinese-Simplified)文件分享

Windows 10 Enterprise LTSC 2021 (x64) - DVD (Chinese-Simplified) SW_DVD9_WIN_ENT_LTSC_2021_64BIT_ChnSimp_MLF_X22-84402.ISO 镜像文件&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/2f8f61ec4a98 Windows 10 Enterprise LTSC 2021 (x86) - DVD (Chinese-Simpli…

python selenium 爬虫教程

Python和Selenium是很强大的爬虫工具&#xff0c;可以用于自动化地模拟浏览器行为&#xff0c;从网页中提取数据。下面是一个简单的使用Python和Selenium进行爬虫的案例。 入门&#xff1a; 1. 安装和配置&#xff1a; 首先&#xff0c;你需要安装Python和Selenium。可以使用…

Postman的高级用法一:重新认识postman核心模块

本请求示例来自于免费天气API&#xff1a; 实况天气接口API开发指南 未来一天天气预报api - 天气API 关于Postman的核心模块 全局变量请求接口请求体预处理脚本 类似beforeTest&#xff0c;在发起请求前的预执行逻辑&#xff0c;通常是生成一些动态变量值 测试用例模块 测试者…