通讯录项目实现
引言:通过顺序表的逻辑实现通讯录。这里就不讲关于顺序表的函数了。如果有不明白的可以看我写的顺序表的博客。
目录
顺序表与通讯录的比较
各源文件文件大榄
Contact.c中通讯录相关函数的定义
初始化和销毁通讯录
添加联系人:
删除联系人:
打印通讯录中存储的所有的联系人的信息
查找联系人(通过名字)
修改联系人的信息
保存顺序表的内容
将文件的内容读入顺序表
将通讯录中的联系人的信息写入文件
优化后的的通讯录初始化和销毁函数
test.c
SeqList.h
SeqList.c
Contact.h
Contact.c
结语:
顺序表与通讯录的比较
通讯录的底层逻辑就是顺序表,与存储int数据的顺序表相比,通讯录这个结构体存储的每个元素的类型为结构体,并且这个结构体定义的是每个联系人的基本信息。
图解:
各源文件文件大榄
SeqList.h | 顺序表的结构的声明,顺序表相关函数的声明,#define定义的符号 |
SeqList.c | 顺序表函数的定义 |
Contact.h | 通讯录中每个联系人的结构的定义,通讯录相关函数的声明 |
Contact.c | 通讯录相关函数的定义 |
test.c | 可以测试,通讯录的流程实现 |
Contact.h
#pragma once
#define NAME_MAX 20
#define GENDER_MAX 20
#define TEL_MAX 20
#define ADRR_MAX 20//联系人的信息的结构
typedef struct personInfo
{char name[NAME_MAX];//姓名char gender[GENDER_MAX];//性别int age;//年龄char tel[TEL_MAX];//电话char addr[ADRR_MAX];//家庭地址
}peoInfo;typedef struct SeqList Contact;//前置声明,将顺组表中的struct SeqList 改为 Contact 增加代码的可读性
//初始化和销毁
void ContactInit(Contact* ps);
void ContactDestory(Contact* ps);//添加和删除
void ContactAdd(Contact* ps);
void ContactDel(Contact* ps);//打印通讯录中的联系人
void ContactPrint(Contact* ps);//修改联系人的信息
void ContactModify(Contact* ps);//查找想要查找的联系人
void ContactFind(Contact* ps);//将文件的信息加载进通讯录
void ContactLoad(Contact* ps);
//销毁通讯录前将通讯录中的信息写入文件
void ContactSave(Contact* ps);
SeqList.h
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"//顺序表中存储的元素的类型为定义的联系人的结构体
#define SLDataType peoInfo
typedef struct SeqList
{SLDataType* arr;int size;int capacity;
}SL;//初始化
void SLInit(SL* ps);
void SLDestory(SL* ps);
//打印
//void SLPrint(SL ps);
//尾插,尾删
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
//尾删,头删
void SLPopFront(SL* ps);
void SLPopBack(SL* ps);
//任意插,任意删
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
Contact.c中通讯录相关函数的定义
初始化和销毁通讯录
//初始化
void ContactInit(Contact* ps)
{SLInit(ps);
}
//销毁
void ContactDestory(Contact* ps)
{SLDestory(ps);
}
直接通过顺序表的初始化和销毁实现就可以了。
添加联系人:
void ContactAdd(Contact* ps)
{peoInfo s;//先定义一个联系人的变量存储要添加的联系人的信息printf("请输入要添加的联系人姓名:\n");scanf("%s", s.name);printf("请输入要添加联系人的性别:\n");scanf("%s", s.gender);printf("请输入要添加联系人的年龄:\n");scanf("%d", &s.age);printf("请输入要添加联系人的电话:\n");scanf("%s", s.tel);printf("请输入要添加联系人的地址:\n");scanf("%s", s.addr);SLPushFront(ps, s);//顺序表的头插,这里用尾插也可以
}
注意:用顺序表的头插或尾插将联系人的信息插入进通讯录.
删除联系人:
//通过名字在通讯录中找到要删除的人
int FindByName(Contact* ps, char* name)
{for (int i = 0; i < ps->size; i++){if (strcmp(ps->arr[i].name, name) == 0)return i;}return -1;
}//删除一个联系人
void ContactDel(Contact* ps)
{char name[NAME_MAX];printf("请输入你要删除的联系人的姓名:\n");scanf("%s",name);//如果通过名字找到联系人则返回存储该联系人的下标int find = FindByName(ps, name);if (find < 0){printf("你的通讯录中没有您要删除的人\n");return;}//通过顺序表的任意删除函数删除SLErase(ps, find);
}
问题:如何删除一个联系人呢?
首先,你需要给出这个联系人的名字或手机号,或家庭地址,通过这些信息找到这个联系人在顺序表中存储的位置;然后,在通过下标,利用顺序表的任意删除顺序表中的数据,删除该联系人。
这里再讲一下FindByName 函数,如果顺序表中存储的联系人的结构体的名字中有这个名字,则返回在顺序表中存储该联系人的下标;若没找到,则返回一个比0小的数。
打印通讯录中存储的所有的联系人的信息
预期结果:
实现代码:
void ContactPrint(Contact* ps)
{printf("%-5s%-5s%-5s%-5s%-5s\n", "姓名", "性别", "年龄", "电话", "家庭地址");for (int i = 0; i < ps->size; i++){printf("%-5s%-5s%-5d%-5s%-5s\n",ps->arr[i].name,ps->arr[i].gender,ps->arr[i].age,ps->arr[i].tel,ps->arr[i].addr);}}
这里代码比较简单,就不多说了。
查找联系人(通过名字)
//通过名字在顺序表中查询
int FindByName(Contact* ps, char* name)
{for (int i = 0; i < ps->size; i++){if (strcmp(ps->arr[i].name, name) == 0)return i;}return -1;
}//查找联系人
void ContactFind(Contact* ps)
{char name[NAME_MAX];printf("请输入想要查找的联系人的姓名:\n");scanf("%s", name);int find = FindByName(ps, name);//通过名字查找if (find < 0){printf("你想要查找的联系人的姓名不在通讯录中\n");return;}//找到了该联系人则打印一下这个联系人的信息printf("%-5s%-5s%-5s%-5s%-5s\n","姓名", "性别", "年龄", "电话", "家庭地址");printf("%-5s%-5s%-5d%-5s%-5s\n",ps->arr[find].name,ps->arr[find].gender,ps->arr[find].age,ps->arr[find].tel,ps->arr[find].addr);
}
这里的查找只是通过名字查找,你也可以通过电话,或家庭地址查找。
修改联系人的信息
void ContactModify(Contact* ps)
{char name[NAME_MAX];printf("请输入想要修改的联系人的姓名:\n");scanf("%s", name);int find = FindByName(ps, name);if (find < 0){printf("你想要修改的联系人的姓名不在通讯录中\n");return;}printf("请输入要添加的联系人姓名:\n");scanf("%s", ps->arr[find].name);printf("请输入要添加联系人的性别:\n");scanf("%s", ps->arr[find].gender);printf("请输入要添加联系人的年龄:\n");scanf("%d", &ps->arr[find].age);printf("请输入要添加联系人的电话:\n");scanf("%s", ps->arr[find].tel);printf("请输入要添加联系人的地址:\n");scanf("%s", ps->arr[find].addr);
}
实现思路:通过名字找到你想要修改的联系人在顺序表中存储的下标,有了下标就可以直接对这个位置的数据进行修改。
保存顺序表的内容
每次程序运行完,通讯录中的数据就会丢失,如何在下次运行程序时,继续使用上次的程序呢?
在每次销毁顺序表之前将通讯录中联系人的信息写入一个文件,每次初始化通讯录后将文件的内容读入通讯录就可以了。
将文件的内容读入顺序表
void ContactLoad(Contact* ps)
{FILE* pf = fopen("test.txt", "rb");if (pf == NULL){perror("fopen");return;}peoInfo s;//定义一个联系人的变量存储每次从文件中读出的联系人的信息while (fread(&s, sizeof(peoInfo), 1, pf))//每次读一个联系人的信息直至没有联系人的信息可以读{SLPushFront(ps, s);//将联系人的信息写入通讯录}fclose(pf);pf = NULL;
}
将通讯录中的联系人的信息写入文件
void ContactSave(Contact* ps)
{assert(ps);FILE* pf = fopen("test.txt", "wb");if (pf == NULL){perror("fopen");return;}fwrite(ps->arr, sizeof(peoInfo), ps->size, pf);//将通讯录中size个联系人的数据,也就是所有联系人的数据写入文件fclose(pf);pf = NULL;
}
优化后的的通讯录初始化和销毁函数
void ContactInit(Contact* ps)
{SLInit(ps);ContactLoad(ps);
}void ContactDestory(Contact* ps)
{ContactSave(ps);SLDestory(ps);
}
test.c
void menu()
{printf("************************************\n");printf("****1.添加联系人****2.删除联系人****\n"); printf("****3.修改联系人****4.查找联系人****\n");printf("****5.展示联系人****0. 退出 ****\n");}
int main()
{//ContactTest1();Contact s;ContactInit(&s);//初始化并载入文件中的联系人数据int op;do{menu();printf("请输入你的操作:\n");scanf("%d", &op);switch (op){case 1:ContactAdd(&s);break;case 2:ContactDel(&s);break;case 3:ContactModify(&s);break;case 4:ContactFind(&s);break;case 5:ContactPrint(&s);break;case 0:printf("退出.....emo\n");break;default:printf("你在干什么?请输入正确的操作数:\n");break;}} while (op);//销毁并肩现在通讯录中联系人的信息写入文件ContactDestory(&s);return 0;
}
SeqList.h
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"#define SLDataType peoInfo
typedef struct SeqList
{SLDataType* arr;int size;int capacity;
}SL;//初始化
void SLInit(SL* ps);
void SLDestory(SL* ps);
//打印
//void SLPrint(SL ps);
//尾插,尾删
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
//尾删,头删
void SLPopFront(SL* ps);
void SLPopBack(SL* ps);
//任意插,任意删
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
SeqList.c
#include "SeqList.h"void CheckSLCapacity(SL* ps)
{if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc");exit(-1);}//开辟成功ps->arr = tmp;ps->capacity = newcapacity;}
}void SLInit(SL* ps)
{assert(ps);ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}void SLDestory(SL* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}//void SLPrint(SL s)
//{
// for (int i = 0; i < s.size; i++)
// printf("%d ", s.arr[i]);
// printf("\n");
//}void SLPushBack(SL* ps, SLDataType x)
{assert(ps != NULL);CheckSLCapacity(ps);ps->arr[ps->size] = x;ps->size++;
}void SLPushFront(SL* ps, SLDataType x)
{assert(ps != NULL);CheckSLCapacity(ps);for (int i = ps->size; i>0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}void SLPopBack(SL* ps)
{assert(ps != NULL);assert(ps->size > 0);ps->size--;
}void SLPopFront(SL* ps)
{assert(ps != NULL);assert(ps->size > 0);for (int i = 0; i <ps->size-1 ; i++)ps->arr[i] = ps->arr[i + 1];ps->size--;
}void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);CheckSLCapacity(ps);for (int i = ps->size; i>pos ; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;ps->size++;
}void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}
Contact.h
#pragma once
#define NAME_MAX 20
#define GENDER_MAX 20
#define TEL_MAX 20
#define ADRR_MAX 20typedef struct personInfo
{char name[NAME_MAX];char gender[GENDER_MAX];int age;char tel[TEL_MAX];char addr[ADRR_MAX];
}peoInfo;typedef struct SeqList Contact;
//初始化和销毁
void ContactInit(Contact* ps);
void ContactDestory(Contact* ps);//添加和删除
void ContactAdd(Contact* ps);
void ContactDel(Contact* ps);//打印通讯录中的联系人
void ContactPrint(Contact* ps);//修改联系人的信息
void ContactModify(Contact* ps);//查找想要查找的联系人
void ContactFind(Contact* ps);//将文件的信息加载进通讯录
void ContactLoad(Contact* ps);
//销毁通讯录前将通讯录中的信息写入文件
void ContactSave(Contact* ps);
Contact.c
#include "SeqList.h"//这个文件中有Contact的定义void ContactInit(Contact* ps)
{SLInit(ps);ContactLoad(ps);
}void ContactDestory(Contact* ps)
{ContactSave(ps);SLDestory(ps);
}void ContactAdd(Contact* ps)
{peoInfo s;printf("请输入要添加的联系人姓名:\n");scanf("%s", s.name);printf("请输入要添加联系人的性别:\n");scanf("%s", s.gender);printf("请输入要添加联系人的年龄:\n");scanf("%d", &s.age);printf("请输入要添加联系人的电话:\n");scanf("%s", s.tel);printf("请输入要添加联系人的地址:\n");scanf("%s", s.addr);SLPushFront(ps, s);
}int FindByName(Contact* ps, char* name)
{for (int i = 0; i < ps->size; i++){if (strcmp(ps->arr[i].name, name) == 0)return i;}return -1;
}void ContactDel(Contact* ps)
{char name[NAME_MAX];printf("请输入你要删除的联系人的姓名:\n");scanf("%s",name);int find = FindByName(ps, name);if (find < 0){printf("你的通讯录中没有您要删除的人\n");return;}SLErase(ps, find);
}void ContactPrint(Contact* ps)
{printf("%-5s%-5s%-5s%-5s%-5s\n", "姓名", "性别", "年龄", "电话", "家庭地址");for (int i = 0; i < ps->size; i++){printf("%-5s%-5s%-5d%-5s%-5s\n",ps->arr[i].name,ps->arr[i].gender,ps->arr[i].age,ps->arr[i].tel,ps->arr[i].addr);}}void ContactModify(Contact* ps)
{char name[NAME_MAX];printf("请输入想要修改的联系人的姓名:\n");scanf("%s", name);int find = FindByName(ps, name);if (find < 0){printf("你想要修改的联系人的姓名不在通讯录中\n");return;}printf("请输入要添加的联系人姓名:\n");scanf("%s", ps->arr[find].name);printf("请输入要添加联系人的性别:\n");scanf("%s", ps->arr[find].gender);printf("请输入要添加联系人的年龄:\n");scanf("%d", &ps->arr[find].age);printf("请输入要添加联系人的电话:\n");scanf("%s", ps->arr[find].tel);printf("请输入要添加联系人的地址:\n");scanf("%s", ps->arr[find].addr);
}void ContactFind(Contact* ps)
{char name[NAME_MAX];printf("请输入想要查找的联系人的姓名:\n");scanf("%s", name);int find = FindByName(ps, name);if (find < 0){printf("你想要查找的联系人的姓名不在通讯录中\n");return;}printf("%-5s%-5s%-5s%-5s%-5s\n","姓名", "性别", "年龄", "电话", "家庭地址");printf("%-5s%-5s%-5d%-5s%-5s\n",ps->arr[find].name,ps->arr[find].gender,ps->arr[find].age,ps->arr[find].tel,ps->arr[find].addr);
}void ContactLoad(Contact* ps)
{FILE* pf = fopen("test.txt", "rb");if (pf == NULL){perror("fopen");return;}peoInfo s;while (fread(&s, sizeof(peoInfo), 1, pf)){SLPushFront(ps, s);}fclose(pf);pf = NULL;
}void ContactSave(Contact* ps)
{assert(ps);FILE* pf = fopen("test.txt", "wb");if (pf == NULL){perror("fopen");return;}fwrite(ps->arr, sizeof(peoInfo), ps->size, pf);fclose(pf);pf = NULL;
}
最终结果展示:
第一次写:
写完之后文件中有一个联系人: 22 22 22 22 22 22
文件的内容:
第二次使用程序:
结语:
总算写完了,现在脑袋还是昏昏的,哈哈哈哈.
下次的项目就是贪吃蛇了。
相关文章:

通讯录项目实现
引言:通过顺序表的逻辑实现通讯录。这里就不讲关于顺序表的函数了。如果有不明白的可以看我写的顺序表的博客。 目录 顺序表与通讯录的比较 各源文件文件大榄 Contact.c中通讯录相关函数的定义 初始化和销毁通讯录 添加联系人: 删除联系人…...
xss相关知识点与绕过思路总结
前言 对xss的绕过进行了系统的学习与实践后,重新审视一下xss,对他的绕过进行一个总结。 (当然我也是个小白,这些也是我当时瞎鸡儿乱搞绕过了几个xss自己做的小总结) 可能有点丑陋,献丑了。 好博客推荐 …...
深入解析语言模型:原理、实战与评估
引言 随着人工智能的飞速发展,语言模型作为自然语言处理(NLP)的核心技术之一,日益受到业界的广泛关注。本文旨在深入探讨语言模型的原理、实战应用以及评估方法,帮助读者更好地理解和应用这一技术。 一、语言模型原理…...
Elasticsearch 的索引优化常规项
优化常规项 https://blog.csdn.net/bairo007/article/details/132019575 1、按实际情况适当调整主分片的数量 如果主分片数量太少,会导致每个分片中的数据量过大,而且无法利用集群中所有节点的计算资源。如果主分片数量太多,会导致索引过度…...
【JavaParser笔记01】JavaParser解析Java源代码中的类信息(javadoc注释、类名称)
这篇文章,主要介绍如何使用JavaParser解析Java源代码中的类信息(javadoc注释、类名称)。 目录 一、JavaParser依赖库 1.1、引入依赖 1.2、获取类注释信息...

Stable Diffusion扩散模型【详解】小白也能看懂!!
文章目录 1、Diffusion的整体过程2、加噪过程2.1 加噪的具体细节2.2 加噪过程的公式推导 3、去噪过程3.1 图像概率分布 4、损失函数5、 伪代码过程 此文涉及公式推导,需要参考这篇文章: Stable Diffusion扩散模型推导公式的基础知识 1、Diffusion的整体…...
关于rabbitmq的prefetch机制
消息预取机制(Prefetch Mechanism)是RabbitMQ中用于控制消息传递给消费者的一种机制。它定义了在一个信道上,消费者允许的最大未确认的消息数量。一旦未确认的消息数量达到了设置的预取值,RabbitMQ就会停止向该消费者发送更多消息…...
机器学习介绍
机器学习是人工智能(AI)的一个分支,它使计算机系统能够从数据中学习并改进它们的性能。机器学习的核心在于开发算法,这些算法可以从大量数据中识别模式和特征,并用这些信息来做出预测或决策,而无需进行明确…...

OpenCV4.9开发之Window开发环境搭建
1.打开OpenCV所在github地址 2.点击opencv仓库,进入仓库详情,点击右下方的OpenCV 4.9.0进入下载页面 3.点击opencv-4.9.0-windows.exe下载 开始下载中... 下载完成 下载完成后,双击运行解压,默认解压路径,修改为c:/...
DDD 中的实体和值对象有什么区别?
在DDD中,实体 Entity 和值对象 Value Object 是两个基本的概念,它们之间有一些重要的区别。 唯一性:实体是唯一的,每个实体都有一个唯一的标识符,即使它的属性在一段时间内发生了变化,它仍然是这个实体。与…...

算法-最值问题
#include<iostream> using namespace std; int main() {int a[7];//上午上课时间int b[7];//下午上课时间int c[7];//一天总上课时间for (int i 0; i < 7; i) {cin >> a[i] >> b[i];c[i] a[i] b[i];}int max c[0];//max记录最长时间int index -1;//索…...
Go 性能压测工具之wrk介绍与使用
在项目正式上线之前,我们通常需要通过压测来评估当前系统能够支撑的请求量、排查可能存在的隐藏bug;压力测试(压测)是确保系统在高负载情况下仍能稳定运行的重要步骤。通过模拟高并发场景,可以评估系统的性能瓶颈、可靠…...
数学思想论(有目录)
数学思想是数学发展过程中的重要指导原则,它涉及对数学概念、方法和理论的理解和认识,以及如何利用这些工具来解决实际问题。数学思想的形成和演进是随着数学的发展而逐渐深化的,它体现了人类对数学本质和应用的不断探索和思考。 一些主要的数学思想包括: 函数与方程思想…...

C++的并发世界(五)——线程状态切换
0.线程状态 初始化:该线程正在被创建; 就绪:该线程在列表中就绪,等待CPU调度; 运行:该线程正在运行; 阻塞:该线程被阻塞挂机,Blocked状态包括:pendÿ…...

C语言——指针
地址是由物理的电线上产生的,能够标识唯一一个内存单元。在C语言中,地址也叫做指针。 在32位机器中,有32根地址线。地址是由32个0/1组成的二进制序列,也就是用4个字节来存储地址。 在64位机器中,有64根地址线。地址是…...
手搓二分查找
第一种: 该种方法是若a[mid]目标数,则让r一直等于mid,让l往右移动,一直移动到rl,这时候跳出循环,在循环外判断 但是不能写成让lmid,让r往左移动,比如a[2]key,这时&#x…...

pycharm调试(步过(Step Over)、单步执行(Step Into)、步入(Step Into)、步出(Step Out))
pycharm调试 pycharm调试 pycharm调试为什么要学会调试?1. 步过 (Step Over)2. 单步执行 (Step Into)3. 步入(Step Into)4. 步出(Step Out) 为什么要学会调试? 调试可以帮助初学者更深入地理解编程基础&am…...

Linux是什么,该如何学习
🐇明明跟你说过:个人主页 🏅个人专栏:《Linux :从菜鸟到飞鸟的逆袭》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、Linux的起源与发展 2、Linux在现代计算机领域…...

C++ | Leetcode C++题解之第7题整数反转
题目: 题解: class Solution { public:int reverse(int x) {int rev 0;while (x ! 0) {if (rev < INT_MIN / 10 || rev > INT_MAX / 10) {return 0;}int digit x % 10;x / 10;rev rev * 10 digit;}return rev;} };...

Linux------一篇博客了解Linux最常用的指令
🎈个人主页:靓仔很忙i 💻B 站主页:👉B站👈 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:Linux 🤝希望本文对您有所裨益,如有不足之处&#…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...