当前位置: 首页 > news >正文

用c语言实现通讯录

目录

静态简易通讯录

代码:

功能模块展示:

设计思路:

动态简易通讯录(本质顺序表)

代码:

扩容模块展示:

设计思路:

文件版本通讯录

代码:

文件模块展示:

设计思路:


静态简易通讯录

代码:

//头文件内容#pragma once#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>//声明一个枚举类型增加主程序代码(switch部分)可读性
enum method
{EXIT,ADD,DELETE,FIND,MODIFY,SHOW,DESTROY,SORT
};//定义标识符常量便于对数据大小修改
#define  MAX_NAME 20
#define  MAX_SEX 6
#define  MAX_TELEPHONE 12
#define  MAX_ADDRESS 20
#define  Max_PEOINFO 1000//定义一个联系人信息结构体类型
typedef struct PeoInfo
{char name[MAX_NAME];char sex[MAX_SEX];int age;char Telephone[MAX_TELEPHONE];char address[MAX_ADDRESS];
}PeoInfo;//创建一个联系人信息结构体数组和计数联系人个数的变量组成联系人结构体
typedef struct Contact
{PeoInfo data[Max_PEOINFO];int sz;
}Contact;//初始化通讯录
void InitContact(Contact* pc);//增加联系人函数
void AddContact(Contact* pc);//展示所有联系人函数
void ShowContact(Contact* pc);//删除联系人函数
void DeleteContact(Contact* pc);//查找联系人函数
void FindContact(Contact* pc);//修改联系人函数
void ModifyContact(Contact* pc);//清空联系人函数
void DestroyContact(Contact* pc);//对联系人排序函数
void SortContact(Contact* pc);//函数实现源文件内容//初始化函数
void InitContact(Contact* pc)
{assert(pc);//利用库函数将整个数组所有元素初始化为0memset(pc->data, 0, sizeof(pc->data));//通讯录没有联系人pc->sz = 0;
}//增加联系人函数
void AddContact(Contact* pc)
{assert(pc);//通讯录已满情况if (pc->sz == Max_PEOINFO){printf("通讯录已满\n");return;}//通讯录未满情况printf("请输入联系人的姓名:>");scanf("%s", pc->data[pc->sz].name);printf("请输入联系人的性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入联系人的年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入联系人的电话:>");scanf("%s", pc->data[pc->sz].Telephone);printf("请输入联系人的地址:>");scanf("%s", pc->data[pc->sz].address);//每增加一个联系人,计数变量加1pc->sz = pc->sz + 1;printf("增加联系人成功\n");
}//为了便于局部调试程序,先实现显示函数
//显示所有联系人
void ShowContact(Contact* pc)
{assert(pc);int i = 0;//打印内容左对齐printf("%-20s\t%-6s\t%-4s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");for (i = 0; i < pc->sz; i++){printf("%-20s\t%-6s\t%-4d\t%-12s\t%-20s\n",pc->data[i].name,pc->data[i].sex,pc->data[i].age,pc->data[i].Telephone,pc->data[i].address);}
}//删除联系人时我们需要知道联系人在数组中的位置(以名字删除联系人)
//名字检索函数(不需要在头文件中声明)
//此函数无法在有同名联系人时精确找到联系人
int ModifyName(char* str, Contact* pc)
{assert(pc && str);int i = 0;//遍历已经存储了联系人的数组元素寻找第一个名字相符的联系人并返回下标for (i = 0; i < pc->sz; i++){if (0 == strcmp(str, pc->data[i].name))return i;}//找不到return -1;
}//删除指定联系人
//此函数无法在有同名联系人时精确删除联系人
void DeleteContact(Contact* pc)
{assert(pc);//以名字查找指定联系人char name[MAX_NAME] = { 0 };printf("请输入要删除的联系人的名字\n");scanf("%s", name);int num = ModifyName(name, pc);//找到了if (num != -1){int i = 0;for (i = num; i < pc->sz; i++){memcpy(pc->data + i, pc->data + (i + 1), sizeof(PeoInfo));}//删除后计数变量减1pc->sz = pc->sz - 1;printf("删除成功\n");}//没找到elseprintf("删除失败,找不到指定联系人\n");
}//查找指定联系人
//此函数无法在有同名联系人时精确查找联系人
void FindContact(Contact* pc)
{assert(pc);//以名字查找指定联系人char name[MAX_NAME] = { 0 };printf("请输入要查找的联系人的名字\n");scanf("%s", name);//调用上面定义的名字检索函数int num = ModifyName(name, pc);//找到了打印此联系人信息if (num != -1){printf("%-20s\t%-6s\t%-4s\t%-12s\t%-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-20s\t%-6s\t%-4d\t%-12s\t%-20s\n",pc->data[num].name,pc->data[num].sex,pc->data[num].age,pc->data[num].Telephone,pc->data[num].address);}//找不到elseprintf("找不到指定联系人\n");
}//修改指定联系人
void ModifyContact(Contact* pc)
{assert(pc);//以名字查找指定联系人char name[MAX_NAME] = { 0 };printf("请输入要修改的联系人的名字\n");scanf("%s", name);//调用名字检索函数int num = ModifyName(name, pc);//找到后重新输入此联系人信息if (num != -1){printf("请输入新的姓名\n");scanf("%s", pc->data[num].name);printf("请输入新的性别\n");scanf("%s", pc->data[num].sex);printf("请输入新的年龄\n");scanf("%d", &(pc->data[num].age));printf("请输入新的电话\n");scanf("%s", pc->data[num].Telephone);printf("请输入新的地址\n");scanf("%s", pc->data[num].address);printf("修改联系人成功\n");}//找不到elseprintf("找不到指定联系人\n");
}//清空所有联系人
void DestroyContact(Contact* pc)
{assert(pc);//调用初始化函数将联系人结构体初始化InitContact(pc);printf("联系人已清空\n");
}//拓展功能
//以名字对所有联系人升序排序
void SortContact(Contact* pc)
{assert(pc);int i = 0;//选择排序for (i = 0; i < pc->sz -  1; i++){int j = i;for (j = i; j < pc->sz; j++){if (strcmp(pc->data[i].name, pc->data[j].name) > 0){PeoInfo tmp;memcpy(&tmp, pc->data[i].name, sizeof(PeoInfo));memcpy(pc->data[i].name, pc->data[j].name, sizeof(PeoInfo));memcpy(pc->data[j].name, &tmp, sizeof(PeoInfo));}}}printf("排序完成\n");
}//主程序源文件内容//菜单
void menu()
{printf("****** 1.ADD      2.DELETE ********\n");printf("****** 3.FIND     4.MODIFY ********\n");printf("****** 5.SHOW     6.DESTROY********\n");printf("****** 7.SORT     0.EXIT   ********\n");
}void test()
{//定义一个通讯录结构体变量Contact con;//初始化InitContact(&con);enum method input = 0;do{menu();printf("请选择你的操作\n");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DELETE:DeleteContact(&con);break;case FIND:FindContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case DESTROY:DestroyContact(&con);break;case SORT:SortContact(&con);break;case EXIT:printf("程序已退出\n");break;default:printf("输入错误,请重新输入:>\n");break;}} while (input);
}
int main()
{test();return 0;
}

功能模块展示:

增加功能:

删除功能:

查找功能:

修改功能:

拓展功能:

设计思路:

要实现一个简易版静态通讯录,无非是在实现增删查改的基础上进行进一步的功能拓展,因此设计的重点是在增删查改的功能实现上,静态版本存储通讯录内容的是定长数组,因此要实现这些功能,我们需要围绕数组下标和已经存储的联系人个数作为文章。

只要知道已经存储的联系人个数,增加联系人就会变得轻而易举。而删除,查找,修改联系人时都必须先找到要操作的联系人,因此我们需要先实现一个检索联系人接口供它们调用,此接口实现的越精确,删查改就会越精确。

为了方便对数组下标进行操作,将计数联系人个数的变量和记录联系人信息的数组都作为通讯录结构体的成员,计数变量从0开始,每增加一个联系人就加1,删除减1,这样我们就会得到通讯录的实时大小从而可以非常容易的操作通讯录,实现通讯录的功能也就变的非常简单。

动态简易通讯录(本质顺序表)

代码:

动态版本的代码只需在静态版本上稍作修改即可。

//头文件增加和修改的内容//初始容量
#define  INIT_SZ 3
//每次扩容增加容量
#define  ADD_SZ 2//修改后通讯录结构体
typedef struct Contact
{//PeoInfo data[Max_PEOINFO];//用结构体指针代替结构体数组PeoInfo* data;int sz;//增加一个记录通讯录容量的变量int capacity;
}Contact;//函数实现源文件增加和修改的内容//动态版本初始化函数
void InitContact(Contact* pc)
{assert(pc);//先开辟INIT_SZ个空间pc->data = (PeoInfo*)malloc(INIT_SZ * sizeof(PeoInfo));//开辟失败if (pc->data == NULL){perror("InitContact");return;}pc->sz = 0;//记录容量pc->capacity = INIT_SZ;
}//增加联系人时需要先检查容量是否已满,若满则增加容量
//空间动态增长(无需在头文件中声明)
int mallocContact(Contact* pc)
{assert(pc);//已满if (pc->sz == pc->capacity){//扩容PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + ADD_SZ) * sizeof(PeoInfo));//扩容失败if (ptr == NULL){perror("mallocContact");return 0;}//扩容成功else{pc->data = ptr;pc->capacity += ADD_SZ;printf("扩容成功\n");return 1;}}//未满return 1;
}//动态版本增加函数
void AddContact(Contact* pc)
{assert(pc);//扩容失败if (0 == mallocContact(pc)){return;}//未满或扩容成功printf("请输入联系人的姓名\n");scanf("%s", pc->data[pc->sz].name);printf("请输入联系人的性别\n");scanf("%s", pc->data[pc->sz].sex);printf("请输入联系人的年龄\n");scanf("%d", &(pc->data[pc->sz].age));printf("请输入联系人的电话\n");scanf("%s", pc->data[pc->sz].Telephone);printf("请输入联系人的地址\n");scanf("%s", pc->data[pc->sz].address);pc->sz = pc->sz + 1;printf("增加联系人成功\n");}//动态版本清空函数
void DestroyContact(Contact* pc)
{assert(pc);free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;printf("联系人已清空\n");
}

扩容模块展示:

设计思路:

静态版本的通讯录十分死板,需要存储的数据少了就会存在空间浪费,多了又会不够,因此衍生出动态版本来解决这一问题,当存储空间不够时就向内存申请新的空间来增加容量,更加灵活。

为了实现实时向内存申请空间,需要一个变量用来记录通讯录结构体的容量,当存储的联系人个数等于容量时就需要进行扩容,同时由于通讯录的大小是动态变化的,因此用结构体指针替代结构体数组来维护存储空间。

由于每次扩容后的存储空间依然是连续的,因此在没有发生访问越界时可以像操作数组一样操作指针,静态版本的大多数代码都无需修改。

文件版本通讯录

代码:

在动态版本上稍作修改。

//函数实现源文件增加和修改的内容//容量检查函数声明
int mallocContact(Contact* pc);//初始化时需要先读取文件contact.dat的内容到data中去
void LoadContact(Contact* pc)
{//打开文件FILE* pf = fopen("contact.dat", "rb");//若路径下没有此文件,则打开文件失败if (pf == NULL){perror("LoadContact");return;}PeoInfo tmp = { 0 };//读文件while (fread(&tmp, sizeof(PeoInfo), 1, pf)){//扩容判断if (0 == mallocContact(pc))return;pc->data[pc->sz] = tmp;//每读取一个计数变量加1pc->sz++;}//关闭文件fclose(pf);pf = NULL;
}//动态版本初始化函数
void InitContact(Contact* pc)
{assert(pc);pc->data = (PeoInfo*)malloc(INIT_SZ * sizeof(PeoInfo));if (pc->data == NULL){perror("InitContact");return;}pc->sz = 0;pc->capacity = INIT_SZ;//载入文件内容LoadContact(pc);
}//将通讯录信息以二进制形式保存到contact.dat文件中
void SaveContact(Contact* pc)
{//打开文件(若路径下没有此文件,则新建一个此文件)FILE* pf = fopen("contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}int i = 0;for (i = 0; i < pc->sz; i++){//写入文件fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf == NULL;printf("通讯录内容已保存到contact.dat文件中\n");
}//主程序源文件修改内容case EXIT://在退出程序时将内存中的信息保存到文件中去SaveContact(&con);printf("程序已退出\n");break;

文件模块展示:

设计思路:

无论是静态版本还是动态版本,联系人信息都是存储在内存中的,一旦程序退出运行,这些信息也会随之消失,为了长久存储这些信息,衍生出了文件版本的通讯录,即利用文件操作函数将存储在内存中的信息存储到文件中长久保存。

我们只需要在动态版本的基础上增加一个读取文件函数和写入文件函数,在程序开始时先将文件中的信息读取到内存中,在程序退出时再将内存中的数据写回文件中即可。

相关文章:

用c语言实现通讯录

目录 静态简易通讯录 代码&#xff1a; 功能模块展示&#xff1a; 设计思路&#xff1a; 动态简易通讯录&#xff08;本质顺序表&#xff09; 代码&#xff1a; 扩容模块展示&#xff1a; 设计思路&#xff1a; 文件版本通讯录 代码&#xff1a; 文件模块展示&#x…...

AI大模型技术揭秘-参数,Token,上下文和温度

深入理解 AI 大模型:参数、Token、上下文窗口、上下文长度和温度 人工智能技术的飞速发展使AI大模型大放异彩,其中涉及的“参数”、“Token”、“上下文窗口”、“上下文长度”及“温度”等专业术语备受瞩目。这些术语背后究竟蕴含何意?它们如何影响AI大模型的性能?一起揭开…...

攻防世界-fakebook题目__详解

1.打开题目先用dirsearch工具扫描一波&#xff0c;扫出来了robots.php目录&#xff0c;然后访问robots.txt 目录&#xff0c;发现了有一个备份文件 &#xff0c;访问备份文件&#xff0c;下载内容 文件的大致内容如下 里面有一个curl_exec这个函数容易造成ssrf攻击的漏洞 我…...

Ubuntu 18.04下普通用户的一次提权过程

Ubuntu 18.04下普通用户的一次提权过程 一.背景介绍:二.主要调试过程:三.相关命令:1.设置BMC密码,获取BMC IP2.找一台ubuntu搭建TFTP服务,用来替换grub.cfg文件3.从调试服务器的/boot/grub/grub.cfg中提取出recovery mode的配置,简化并生成新的配置文件grub.cfg,放在tftp服务的…...

接口和抽象类:如何使用普通类模拟接口和抽象类

目录 1.引言 2.抽象类和接口的定义与区别 3.抽象类和接口存在的意义 4.模拟实现抽象类和接口 5.抽象类和接口的应用场景 1.引言 在面向对象编程中&#xff0c;抽象类和接口是两个经常被提及的语法概念&#xff0c;也是面向对象编程的四大特性&#xff0c;以及很多设计模式…...

【文档智能】实践:基于Yolo三行代码极简的训练一个版式分析模型

一、数据集 本文以开源的CDLA数据集做为实验&#xff0c;CDLA是一个中文文档版面分析数据集&#xff0c;面向中文文献类&#xff08;论文&#xff09;场景。包含以下10个label&#xff1a; 数据集下载地址&#xff1a;https://github.com/buptlihang/CDLA 数据集是labelme格式…...

聚观早报 | 深蓝G318价格发布;比亚迪方程豹豹3官图发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 6月15日消息 深蓝G318价格发布 比亚迪方程豹豹3官图发布 夸克App升级高考AI搜索 iOS 18卫星通信实测 Redmi K70…...

如何实现内网穿透?快解析-免费内网穿透工具

在现如今的ipv4时代&#xff0c;随着上网电脑及其他智能设备越来越多&#xff0c;公网IP地址出现了枯竭的情况。近几年&#xff0c;内网穿透这个词被不断提及&#xff0c;这也是在无公网IP环境下实现异地访问的一种可行办法&#xff0c;下面我就给大家介绍一下内网穿透的原理。…...

【python-AI篇】人工智能技能树思维导图

大致总结一下得出如下思维导图&#xff0c;如不完善日后迭代更新 1. python基础三方库 1.1 科学计算库 ---- numpy库 1.2 科学计算库 ---- Scipy库 1.3 数据分析处理库 ---- pandas库 1.4 可视化库 ---- matplotlib库 1.5 可视化库 ---- seaborn库 1.6 机器学习和数据挖掘库 …...

Vue的computed大致细节

computed computed具体实现流程computer的执行顺序 computed 具体实现流程 computer内部首先是标准化参数然后调用runner函数进行依赖收集设置dirty为true创建副作用函数&#xff0c;具体如下 const runner effect(getter,{//延迟执行lazy:true,//标记为computed effect 用…...

第5章:模型预测控制(MPC)的代码实现

1. 建立 QP 模型&#xff1a; 1.1 车辆模型&#xff1a; 注&#xff1a;使用车辆横向动力学模型 纵向动力学模型&#xff08;误差模型&#xff09; 1.2 QP 问题模型&#xff1a; 注&#xff1a;详细推导见 笔记100&#xff1a;使用 OSQP-Eigen 对 MPC 进行求解的方法与代码-…...

论文学习day01

1.自我反思的检索增强生成&#xff08;SELF-RAG&#xff09; 1.文章出处&#xff1a; Chan, C., Xu, C., Yuan, R., Luo, H., Xue, W., Guo, Y., & Fu, J. (2024). RQ-RAG: Learning to Refine Queries for Retrieval Augmented Generation. ArXiv, abs/2404.00610. 2.摘…...

Github入门教程,适合新手学习(非常详细)

前言&#xff1a;本篇博客为手把手教学的 Github 代码管理教程&#xff0c;属于新手入门级别的难度。教程简单易操作&#xff0c;能够基本满足读者朋友日常项目寄托于 Github 平台上进行代码管理的需求。Git 与 Github 是一名合格程序员 coder 必定会接触到的工具与平台&#x…...

C# OpenCvSharp 代数运算-add、scaleAdd、addWeighted、subtract、absdiff、multiply、divide

在C#中使用OpenCvSharp进行图像处理时,理解和合理使用各种图像操作函数可以帮助我们实现许多实际应用中的需求。下面,我将详细介绍每个函数的使用,并给出与实际应用项目相关的示例,包括运算过程和运算结果。 1. add 函数 作用 将两幅图像进行相加,可以达到图像融合的目的…...

为什么说Python 是胶水语言?

​ "Python 是胶水语言"这一说法是指它很擅长将不同的程序或代码库连接在一起&#xff0c;能够让来自不同编程语言或框架的组件无缝协作。Python 具有丰富的库和简单的语法&#xff0c;使得它可以轻松调用其他语言编写的程序或使用不同技术栈的模块。 ​ 以下是几个…...

GitLab教程(二):快速上手Git

文章目录 1.将远端代码克隆到本地2.修改本地代码并提交到远程仓库3.Git命令总结git clonegit statusgit addgit commitgit pushgit log 首先&#xff0c;我在Gitlab上创建了一个远程仓库&#xff0c;用于演示使用Gitlab进行版本管理的完整流程&#xff1a; 1.将远端代码克隆到本…...

结构体知识点

基本概念 结构体是一种自定义变量类型&#xff0c;类似于枚举需要自己定义。 它是数据和函数的集合。 在结构体中&#xff0c;可以声明各种变量和方法。 基本语法 1.结构体一般写在namespace语句块中。 2.结构体关键字struct struct 自定义结构体名 {//第一部分//变量//…...

C# —— 显示转换

显示转换: 通过一些方法可以将其他数据类型转换为我们想要的数据类型 1.括号强转 作用: 一般情况下 将高精度的类型转换为低精度 // 语法: 变量类型 变量名 (转换的变量类型名称) 变量; // 注意: 精度问题 范围问题 sbyte sb 1; short s 1; int …...

zip加密txt文件后,暴力破解时会有多个解密密码可以打开的疑问??

最近在做一个关于zip压缩文件解密的测试&#xff0c;发现通过暴力解密时&#xff0c;会有多个解密密码可以打开&#xff0c;非常疑惑&#xff0c;这里做个问题&#xff0c;希望能有大佬解惑。 1、首先在本地创建一个113449.txt的文件&#xff0c;然后右键txt文件选择压缩&…...

css入门宝典

3.1.4 通配符选择器 语法 : *{} 作用 : 让页面中所有的标签执行该样式,通常用来清除间距 例子 : *{ margin: 0; //外间距 padding: 0; //内间距 } 一 CSS基本语法 1基础知识 1.1概述 Css (层叠样式表)是种格式化网页的标准方式&#xff0c; 用于控制设置网页的样式&#xff…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...