学生信息管理系统(通讯录)----------通俗易懂、附源码、C语言实现
绪论:
本篇文章使结构体章节后的习题,如果你对C语言有问题,或者结构体有什么问题不妨看看我之前所写的文章(章回体),对于文件管理和内存分配问题我将在后面补上,对于这个学生信息管理系统我用了多种方法和分源管理的形式来写可能内容偏多,但都有着重大意义,可以自行对我的源码进行copy和删减一些用了多种方法的地方,当然直接用也是没什么问题的。
附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要
思维导图
要XMind思维导图的话可以私信哈
逐步实现的目录
1.界面的创建、和功能的选择
1.1分源管理
1.1.1在主函数内
1.1.3在contact.h
1.1.2在contact.c
2.功能的实现
2.1分源管理
2.1.1在主函数内
2.1.2在contact.h
2.1.3在contact.c
3.文件的保存、和文件的调用
3.1分源管理
3.1.1在主函数内
3.1.2在contact.c
3.1.3在contact.h
补充:
对于分源管理:这样做的原因是可以将这个程序的实现,分开来实现,主函数放在了test.c中这里就像一个枢纽(主干)来选择功能,而contact.c 中放着的是这些主干后的分支(他代表着所要实现的功能的具体代码),而contact.h(头文件)这里存放着一些在test.c 和 contact.c 同时需要用到的东西,如头文件的应用、#define 定义的常量 、以及函数的声明 、这样只需在.c(源文件)中引用#include"contact" 即可包含该文件中的内容
下面先上源码:
test.c:
#define _CRT_SECURE_NO_WARNINGS 1#include"contact.h"enum function
{Exit = 0,Add,Del,Search,Modeify,Show,Sort,Refresh
};void menu()
{printf("********************************\n");printf("********************************\n");printf("***** 1. Add 2.Del *****\n");printf("********************************\n");printf("***** 3.Search 4.Modeify *****\n");printf("********************************\n");printf("***** 5.Show 6.Sort *****\n");printf("********************************\n");printf("***** 7.refresh 0.exit *****\n");printf("********************************\n");printf("********************************\n");//1)添加学生信息//2)删除学生信息//3)查询学生信息//4)修改学生信息//5)展示所有学生信息//6)重新排序学生信息//7)刷新学生信息
}int main()
{int input = 0;Info_System con ;
//初始化InitCon(&con);//初始化方法二:Info_System con = {0};直接将全部置成0do{menu();printf("请选择>:");scanf("%d", &input);switch(input){case Add:Add_Stu_message(&con);break;case Del:Del_Stu_message(&con);break;case Search:Search_Stu_message(&con);break;case Modeify:Modeifyh_Stu_message(&con);break;case Show:Show_Stu_message(&con);break;case Sort:Sort_Stu_message(&con);break;case Refresh:Refresh_Stu_message(&con);break;case Exit:printf("退出\n");break;default:printf("选择错误,重新选择:\n");break;}} while (input);return 0;
}
contact.h:
#pragma once#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>#define Name_Max 20
#define Sex_Max 5
#define Class_Max 20
#define Room_Max 20#define PeoMax 100typedef struct PeoInfo
{int ID;// 学号char Name[Name_Max];// 姓名char Sex[Sex_Max];// 性别char Class[Class_Max];// 班级char Room[Room_Max];// 宿舍号int Score;// 成绩}PeoInfo;typedef struct management_System
{PeoInfo Contact[PeoMax];//存放人的信息int sz;//已近存放了多少个人}Info_System;void InitCon(Info_System *con);void Add_Stu_message(Info_System* con);void Show_Stu_message(const Info_System* con);void Del_Stu_message (Info_System* con);void Search_Stu_message(const Info_System* con);void Modeifyh_Stu_message(Info_System* con);void Sort_Stu_message(Info_System* con);void Refresh_Stu_message(Info_System* con);
contact.c:
#define _CRT_SECURE_NO_WARNINGS 1#include"contact.h"//初始化
void InitCon(Info_System* con)
{assert(con);con->sz = 0;memset(con->Contact, 0, sizeof(Info_System));//利用memset将一块连续的空间初始化成0最后要初始化多少个字节
}int FindById(int Id, const Info_System* con)
{int t = con->sz;//不要改变sz,用t来代替需要查找的人while (t--){if (Id == con->Contact[t].ID){return t;}}printf("找不到此人\n");return -1 ;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}
int FindByName(char * name,const Info_System* con)
{int t = con->sz;//不要改变sz,用t来代替需要查找的人while (t--){if (strcmp(name, con->Contact[t].Name) == 0)//--ret 是因为ret表示的是总人数,而总人数-1才能找到最后一个人{return t;}}printf("找不到此人\n");return -1;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}//增加
void Add_Stu_message(Info_System* con)
{assert(con);if (con->sz == PeoMax){printf("信息已满,请删除或刷新后再试\n");return;}printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");scanf("%d %s %s %s %s %d", &con->Contact[con->sz].ID,con->Contact[con->sz].Name,con->Contact[con->sz].Class,con->Contact[con->sz].Sex,con->Contact[con->sz].Room,&con->Contact[con->sz].Score);con->sz += 1;//con->sz++;printf("添加完成\n");
}void Show_Stu_message(const Info_System* con)
{assert(con);printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");for (int i = 0; i < con->sz;i++)//解引用操作符的优先级都很(最)高{printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[i].ID,con->Contact[i].Name,con->Contact[i].Class,con->Contact[i].Sex,con->Contact[i].Room,con->Contact[i].Score);}}void Del_Stu_message(Info_System* con)
{assert(con);if (con->sz == 0){printf("没有学生信息\n");return;}int input = 0;printf("输入学号进行删除;>");scanf("%d", &input);int ret = FindById(input,con);if (ret != -1){for (ret; ret < con-> sz - 1; ret++) //sz -1 也要转化成下标{con->Contact[ret] = con->Contact[ret+1]; //注意返回的就是所对应的下标}con->sz--;printf("删除成功\n");}//if (ret!=-1)//{// memmove(con->Contact + ret, con->Contact + ret + 1, (con->sz)*sizeof(PeoInfo) - (ret) * sizeof(PeoInfo));// con->sz--;// printf("删除成功\n");//}}void Search_Stu_message(const Info_System* con)
{assert(con);int i = 0;printf("1.Id\n2.Name\n选择查找方法:>");scanf("%d", &i);if (i == 1){int input = 0;printf("输入学号进行查找:>");scanf("%d", &input);int ret = FindById(input, con);if (ret != -1){printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,con->Contact[ret].Score);}}else if (i == 2){char name[20] = { 0 };printf("输入姓名进行查找:>");scanf("%s",name);int ret = FindByName(name, con);if (ret != -1){printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,con->Contact[ret].Score);}}else{printf("选择错误\n");}}void Modeifyh_Stu_message(Info_System* con)
{assert(con);int i = 0;printf("1.Id\n2.Name\n选择查找方法:>");scanf("%d", &i);if (i == 1){int input = 0;printf("输入要修改的学生信息的学号:>");scanf("%d", &input);int ret = FindById(input, con);if (ret != -1){printf("修改:>\n");printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,&con->Contact[ret].Score);printf("修改完成\n");}}else if (i == 2){char name[20] = { 0 };printf("输入要修改的学生信息的姓名:>");scanf("%s", name);int ret = FindByName(name, con);if (ret != -1){printf("修改:>\n");printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,&con->Contact[ret].Score);printf("修改完成\n");}}else{printf("选择错误\n");}
}int Sort_Name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->Name, ((PeoInfo*)e2)->Name);}int Sort_age(const void* e1, const void* e2)
{return ((PeoInfo*)e1)->ID - ((PeoInfo*)e2)->ID;
}
void Sort_Stu_message(Info_System* con)
{assert(con);int input = 0;printf("1.以名字排序\n2.以学号排序\n");scanf("%d", &input);switch (input){case 1:qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_Name);printf("排序成功\n");break;case 2:qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_age);printf("排序成功\n");break;default:printf("输入错误\n");break;}
}void Refresh_Stu_message(Info_System* con)
{InitCon(con);printf("刷新成功\n");
}
1.界面的创建、和功能的选择
1.1分源管理
1.1.1在主函数内
- 创建目录(界面)
在main函数内创建一个目录函数
int main() {menu();retrn 0; }
直接通过打印的方法,打印出自己所想要的目录(界面)
void menu() {printf("********************************\n");printf("********************************\n");printf("***** 1. Add 2.Del *****\n");printf("********************************\n");printf("***** 3.Search 4.Modeify *****\n");printf("********************************\n");printf("***** 5.Show 6.Sort *****\n");printf("********************************\n");printf("***** 7.refresh 0.exit *****\n");printf("********************************\n");printf("********************************\n");//1)添加学生信息//2)删除学生信息//3)查询学生信息//4)修改学生信息//5)展示所有学生信息//6)重新排序学生信息//7)刷新学生信息 }
- 创建选择功能,
通过dowhile循环来不断的进行选择并且通过switch语句来控制所选择功能
int main() {int input = 0;do{printf("请选择>:");scanf("%d", &input);switch(input){case Add:Add_Stu_message(&con);break;case Del:Del_Stu_message(&con);break;case Search:Search_Stu_message(&con);break;case Modeify:Modeifyh_Stu_message(&con);break;case Show:Show_Stu_message(&con);break;case Sort:Sort_Stu_message(&con);break;case Refresh:Refresh_Stu_message(&con);break;case Exit:printf("退出\n");break;default:printf("选择错误,重新选择:\n");break;}} while (input);return 0; }
1.1.3在contact.h
- 创建一个结构体存放学生的信息
一个学生的信息可能有 学号、姓名、性别、班级、宿舍、成绩
所以我们可以用一个结构体来存,并且用typedef来将复杂的名字简化
typedef struct PeoInfo {int ID;// 学号char Name[Name_Max];// 姓名char Sex[Sex_Max];// 性别char Class[Class_Max];// 班级char Room[Room_Max];// 宿舍号int Score;// 成绩}PeoInfo;
- 再创建一个结构体来存放每个学生(用数组)以及再通过计数器来计存了几个学生了
同样用到typedef来简化
typedef struct management_System {PeoInfo Contact[PeoMax];//存放人的信息int sz;//已近存放了多少个人}Info_System;
1.1.2在contact.c
- 初始化学生信息
对于已经创建好的结构体,他们此时还是一些随机值需要初始化
所以写一个初始化函数来进行初始化
void InitCon(Info_System* con) {assert(con);con->sz = 0;memset(con->Contact, 0, sizeof(Info_System));//利用memset将一块连续的空间初始化成0最后要初始化多少个字节 }
其中有到了memset来直接对其初始化,
第一个元素放目标地址,第二个元素表示要放东西的整形形式(如0 -> 0 ;而 'a' -> 97),第三个元素表示这个目标的大小(byte),具体用法可以看这篇博客:进阶C语言第三章-------《字符函数和内存函数》 完整思维导图+基本练习题+深入细节+通俗易懂+知识点+建议收藏_溟洵的博客-CSDN博客
附:首先,对于这些进行解释:他是通过枚举的办法实现
的具体可以看看我写的一篇关于自定义类型的blog;其次,是对这个的解释
这是引用contact.h头文件,包含其里面的内容(函数的头文件,和函数声明)
2.功能的实现
2.1分源管理
2.1.1在主函数内
通过目录的选择后进入功能内部
2.1.2在contact.h

2.1.3在contact.c
添加学生信息
对于下面的scanf操作我们需要引用并且存进结构体中 对于数组来说不需要加上&
因为其数组名表示其地址 而对于整形就需要&了
先从con这是Info_System结构体的变量所以通过->访问其里面的成员Contact而其又是PeoInfo结构体的数组变量所以就可以通过访问数组空间再用.操作符来找到学生的信息,
这里不用-> 是因为前面con->Contact[con->sz] 已经表示成Contact[PeoMax]结构体变量了不需要在*解引用了void Add_Stu_message(Info_System* con) { assert(con); if (con->sz == PeoMax) {printf("信息已满,请删除或刷新后再试\n");return; } printf("依次输入%s %s %s %s %s %s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩"); scanf("%d %s %s %s %s %d", &con->Contact[con->sz].ID, con->Contact[con->sz].Name, con->Contact[con->sz].Class, con->Contact[con->sz].Sex, con->Contact[con->sz].Room, &con->Contact[con->sz].Score ); printf("添加完成\n"); }
展示学生信息
void Show_Stu_message(Info_System* con) {assert(con);printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");for (int i = 0; i < con->sz;i++){printf("%-10d %-20s %-20s %-5s %-20s %-10d\n",con->Contact[i].ID,con->Contact[i].Name,con->Contact[i].Class,con->Contact[i].Sex,con->Contact[i].Room,con->Contact[i].Score);} }
对于printf打印只需要满足所给条件(%d)和所写条件(con->Contact[i].ID)对应的类型一致即可。
删除学生信息
void Del_Stu_message(Info_System* con) {assert(con);if (con->sz == 0){printf("没有学生信息\n");return;}int input = 0;printf("输入学号进行删除;>");scanf("%d", &input);int ret = FindById(input,con);if (ret != -1){for (ret; ret < con-> sz - 1; ret++) //sz -1 也要转化成下标{con->Contact[ret] = con->Contact[ret+1]; //注意返回的就是所对应的下标}con->sz--;printf("删除成功\n");}//if (ret!=-1)//{// memmove(con->Contact + ret, con->Contact + ret + 1, (con->sz)*sizeof(PeoInfo) - (ret) * sizeof(PeoInfo));// con->sz--;// printf("删除成功\n");//}}
查找函数:
int FindByName(char * name,const Info_System* con)
{int t = con->sz;//不要改变sz,用t来代替需要查找的人while (t--){if (strcmp(name, con->Contact[t].Name) == 0)//--ret 是因为ret表示的是总人数,而总人数-1才能找到最后一个人{return t;}}printf("找不到此人\n");return -1;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}
int FindById(int Id, const Info_System* con)
{int t = con->sz;//不要改变sz,用t来代替需要查找的人while (t--){if (Id == con->Contact[t].ID){return t;}}printf("找不到此人\n");return -1 ;//返回-1是因为区别于返回0(返回0表示查找的人的下标为0)
}
查找学生信息
void Search_Stu_message(const Info_System* con) {assert(con);int i = 0;printf("1.Id\n2.Name\n选择查找方法:>");scanf("%d", &i);if (i == 1){int input = 0;printf("输入学号进行查找:>");scanf("%d", &input);int ret = FindById(input, con);if (ret != -1){printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,con->Contact[ret].Score);}}else if (i == 2){char name[20] = { 0 };printf("输入姓名进行查找:>");scanf("%s",name);int ret = FindByName(name, con);if (ret != -1){printf("%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,con->Contact[ret].Score);}}else{printf("选择错误\n");}}
修改学生信息
void Modeifyh_Stu_message(Info_System* con) {int i = 0;printf("1.Id\n2.Name\n选择查找方法:>");scanf("%d", &i);if (i == 1){int input = 0;printf("输入要修改的学生信息的学号:>");scanf("%d", &input);int ret = FindById(input, con);if (ret != -1){printf("原信息:\n%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,con->Contact[ret].Score);printf("修改:>\n");printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,&con->Contact[ret].Score);}}else if (i == 2){char name[20] = { 0 };printf("输入要修改的学生信息的姓名:>");scanf("%s", name);int ret = FindByName(name, con);if (ret != -1){printf("原信息:\n%-10s %-20s %-20s %-5s %-20s %-10s\n", "学号", "名字", "班级", "性别", "宿舍", "计算机成绩");printf("%-10d %-20s %-20s %-5s %-20s %-10d\n", con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,con->Contact[ret].Score);printf("修改:>\n");printf("依次输入学号 名字 班级 性别 宿舍 计算机成绩\n并且以空格/回车分隔\n");scanf("%d %s %s %s %s %d", &con->Contact[ret].ID,con->Contact[ret].Name,con->Contact[ret].Class,con->Contact[ret].Sex,con->Contact[ret].Room,&con->Contact[ret].Score);}}else{printf("选择错误\n");} }
排序学生信息
int Sort_Name(const void* e1, const void* e2)
{return strcmp(((PeoInfo*)e1)->Name, ((PeoInfo*)e2)->Name);//注意强转要写成 PeoInfo* 结构体类型//返回大于0的数才交换,即是升序形式
}int Sort_age(const void* e1, const void* e2)
{return ((PeoInfo*)e1)->ID - ((PeoInfo*)e2)->ID;
}
void Sort_Stu_message(Info_System* con)
{assert(con);int input = 0;printf("1.以名字排序\n2.以学号排序\n");scanf("%d", &input);switch (input){case 1://ASCII升序qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_Name);//头文件stdlib,比较函数int compare(const void *elem1, const void *elem2)//此处con->Contact 直接找到了数组名传进去,所以qsort内所接受到的结构体时PeoInfo类型的printf("排序成功\n");break;case 2://升序qsort(con->Contact, con->sz, sizeof(con->Contact[0]), Sort_age);printf("排序成功\n");break;default:printf("输入错误\n");break;}
}
刷新学生信息
void Refresh_Stu_message(Info_System* con)
{InitCon(con);//直接再次调用初始化函数printf("刷新成功\n");
}
3.文件的保存、和文件的调用
3.1分源管理
3.1.1在主函数内
3.1.2在contact.c
3.1.3在contact.h
敬请期待!持续更新,关注喔老铁
相关文章:

学生信息管理系统(通讯录)----------通俗易懂、附源码、C语言实现
绪论: 本篇文章使结构体章节后的习题,如果你对C语言有问题,或者结构体有什么问题不妨看看我之前所写的文章(章回体),对于文件管理和内存分配问题我将在后面补上,对于这个学生信息管理系统我用了多种方法和…...

Python抽奖系统
#免费源码见文末公众号# 抽奖系统① def choujiang1():def write():with open(d:\\抽奖系统\\抽奖1.1.pickle,rb) as file:lst1pickle.load(file)namevar1.get()if name not in lst1 and name!录入成功! and name!录入失败! and name!:lst1.append(name)…...

真实景观渲染技巧【Three.js】
受到一些很棒的 three.js 演示、与 covid 相关的旅行禁令以及可能在 pinterest 上花太多时间看美丽的旅行照片的启发——我开始看看我是否可以使用 three.js 和r3f在浏览器中渲染一个令人信服的风景场景。 推荐:将 NSDT场景编辑器 加入你的3D开发工具链。 在过去一个…...

MySQL知识汇总:MySQL函数CASE WHEN用法详解
Case When的两种简单用法 用法一: CASE seasonWHEN Spring THEN 春天 WHEN Summer THEN 夏天 WHEN autumn THEN 秋天 else 冬天 end 用法二: CASE WHEN season Spring THEN 春天WHEN season Summer THEN 夏天WHEN season autumn THEN 秋天 els…...

Python学习-----模块1.0(模块的简介、定义与使用)
目录 前言: 1.什么是模块 2.模块的分类 (1)内置模块 (2)第三方模块 (3)自定义模块 3.模块的使用 4.自定义模块 5.模块和执行文件的判断 前言: 今天就开始讲Python中的模块篇…...

Linux进程学习【二】
✨个人主页: Yohifo 🎉所属专栏: Linux学习之旅 🎊每篇一句: 图片来源 🎃操作环境: CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…...
我问chatGPT,在JavaScript中构造函数和类的区别
问:构造器函数和面向中的类是同样的东西吗|? 答:构造器函数和面向对象中的类并不是同样的东西,它们之间有些许不同。 在面向对象编程中,类是一种抽象的概念,它描述了一类具有相同属性和行为的对象。类可以…...

软考高级-信息系统管理师之沟通管理(最新版)
项目沟通管理 1、项目沟通管理基础项目沟通管理的重要性项目沟通管理相关理论2、规划沟通管理3、管理沟通4、控制沟通项目沟通管理的技术和工具1、项目沟通管理基础 项目沟通管理的重要性 1、与1T项目成功有关的最重要的四个因素是:主管层的支持、用户参与、有经验的项目经理…...

PyQt5 自定义富文本编辑器
介绍 一款使用PyQt5和网页端框架wangEditor集成的富文本编辑器 代码片段 PyQt5客户端 与网页端建立连接def create_connect(self):self.web_view QWebEngineView()self.bridge JSBridge(self.web_view.page())self.web_view.load(QUrl.fromLocalFile(self.editor_path))w…...

【高可用系统架构设计】SLA服务可用性4个9是什么意思?如何保证服务的高可用性 HA(High Availability)?...
如何保证服务的高可用性 HA(High Availability)?高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。方法论上,高可用是通…...
微服务架构设计模式-(14)面向生产环境
生产环境要求 应用安全 数据权限 服务可配置性 不同环境的配置不一样,不能写死代码,所以要配置 可观测性 需要日志系统 应用安全 四个方面 身份验证 验证主体的身份解决方案 单体 cookie 微服务中 API Gateway 访问令牌 不透明令牌透明令牌ÿ…...
HTML5新增用法
新增语义化标签 并无特殊含义,是语义!语义!语义! <header> 头部区域 <nav> 导航区域 <main> 主体区域 <article> 内部标签 <section> 块级标签 <aside> 侧边栏标签 <footer> 尾部…...

富足金字塔:人的努力是为了扩大选择的范围
人的努力是为了扩大选择的范围,这是熵减的另一种表述。富足金字塔代表着人生的三重境界。第一层是温饱。人需要食物、水、住所。第二层是品质。能源、ICT、教育带来更有品质的生活,如智能门锁、智能马桶、扫地机、洗碗机、洗衣烘衣机。第三层是梦想。包括…...

C++类基础(十七)
类的继承——补充知识 ● public 与 private 继承(C Public, Protected and Private Inheritance) 改变了类所继承的成员的访问权限 //公有继承 struct Base { public:int x; private:int y; protected:int z; }; struct Derive : public Base //公有继承…...

LeetCode刷题复盘笔记—一文搞懂贪心算法之56. 合并区间(贪心算法系列第十四篇)
今日主要总结一下可以使用贪心算法解决的一道题目,56. 合并区间 题目:56. 合并区间 Leetcode题目地址 题目描述: 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间…...

Andriod入门级开发
这学期有个课设,我们组我负责一个手机APP的开发,虽然刚开始说要实现什么智能导航,类似高德地图那种,但最后阉割的只剩一个Socket通信了,因为之前没有接触过(可能之后也不会再接触),记…...

DCL 数据控制语言
1、简介 DCL英文全称是Data Control Language(数据控制语言),用来管理数据库用户、控制数据库的访问权限。 2、管理用户 2.1 查询用户 select * from mysql.user;查询的结果如下: 其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问…...

全网超详细的下载与安装VMware虚拟机以及为什么要安装VMware虚拟机
文章目录1. 文章引言2. 下载VMware3. 安装VMware1. 文章引言 我们使用最多的系统是windows系统,因为,国内电脑厂商的操作系统(os)基本是windows系统,比如华为、联想、华硕等电脑。 但线上的服务器大多是Linux系统,而我们经常使用…...

Python获取zabbix问题触发器
背景:阿里云的ECS服务器因为阿里云升级插件,导致安全防护程序重启,产生不同的端口。导致低自动发现注册的端口 大量报警。 解决:杀掉关于因为非业务 变更的端口检测的触发器。 相关文档: Zabbix监控之主机端口监控自…...

原型链污染
目录 前置知识 原型对象 prototype和__proto__的区别 原型链概念 原型链的继承 原型 链污染 原型链污染原理 javascript中可能会存在原型链污染的危险函数 原型链污染的实际应用 JavaScript中可以触发弹窗的函数 前置知识 原型对象 在JavaScript中,每个函…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...