【C语言】实现通讯录(动态+文件)

目录

  • 前言:
    • 一.创建多文件
    • 二.保存人的通讯录信息
    • 三.构建菜单 - test.c
    • 四.函数的声明
    • 五.函数的实现
      • 1.初始化通讯录
      • 2.增加指定联系人
      • 3.删除指定联系人
      • 4.查找指定联系人
      • 5.修改指定联系人
      • 6.排序联系人信息(排序名字)
      • 7.清理通讯录
      • 8.文件存盘
    • 六.全部代码
      • 1.Contact.h
      • 2.test.c
      • 3.Contact.c

前言:

在之前三子棋和扫雷的基础上,本篇文章博主将给大家逐步分析实现通讯录,介绍通讯录的每个功能(动态增长和文件保存)。
——————————————————————

一.创建多文件

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

以多文件的形式分模块写的好处:
1.方便分工合作
2.方便后续维护
3.方便代码复用

二.保存人的通讯录信息

使用一个结构体来保存个人信息:

名字
年龄
性别
电话号码
地址

typedef struct PerInfo
{char name[10];int age;char sex[5];char tele[12];char addr[10];
}PI;

再设计一个结构体保存通讯录信息:

(个人信息的结构体变量)data - 存放个人信息
通讯录个人信息的个数 - sz
刚开始通讯录只能存放4个人的信息 - capacity(容量)

typedef struct Contact
{PI* data;int sz;int capacity;
}CT;

三.构建菜单 - test.c

刚开始进入通讯录可选择:

1.增加指定联系人——add
2.删除指定联系人——del
3.查找指定联系人——search
4.修改指定联系人信息 ——modify
5.显示所以联系人信息——show
6.排序联系人(以名字排序)——sort
7.退出程序

这里还是用switch来选择每个入口,可以使用之前学过的枚举来实现。

枚举的值默认是从0开始的

enum
{EXIT,//0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW,//5SORT//6
};

test.c文件

#include "Contact.h"
void menu()
{printf("************************************\n");printf("*******  1.add     2.del   *********\n");printf("*******  3.search  4.modify  *******\n");printf("*******  5.show    6.sort  *********\n");printf("*******  0.exit           **********\n");printf("************************************\n");
}
int main()
{int input = 0;CT con;InitContact(&con);do{menu();printf("请选择:");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:SaveContact(&con);//保存通讯录信息到文件DestroyContact(&con);//清理通讯录printf("退出程序\n");break;default:printf("输入有误,请重试\n");break;}} while (input);return 0;
}

四.函数的声明

//初始化通讯录
void InitContact(CT* pc);
//增加联系人
void AddContact(CT* pc);
//显示全部联系人信息
void ShowContact(const CT* pc);
//删除联系人
void DelContact(CT* pc);
//查找联系人
void SearchContact(const CT* pc);
//修改联系人
void ModifyContact(CT* pc);
//排序通讯录
void SortContact(CT* pc);
//清理通讯录
void DestroyContact(CT* pc);
//保存通讯录信息到文件
void SaveContact(CT* pc);

五.函数的实现

1.初始化通讯录

刚开始给指针(pc)指向的数组(data)用malloc函数开辟一块空间。
个数(sz)初始化为0,容量(capacity)为4

//初始化通讯录
void InitContact(CT* pc)
{assert(pc);pc->data = (PI*)malloc(sizeof(PI*) * 4);if (pc == NULL){perror("malloc fail");return;}pc->sz = 0;pc->capacity = 4;
}

2.增加指定联系人

这里要考虑一个问题,我们初始化的时候容量个数为4,也就是说增加到4个人的信息就满了,所以要扩容

扩容的函数——int Capacity(CT * pc)

当返回值为0的时候说明指针为空,打印错误信息
使用realloc函数进行扩容,如果扩容成功,capacity每次等于乘以上次原来的两倍,把扩容成功的变量赋给data

注:realloc函数是扩到多少,不是扩了多少

扩容成功后输入要增加的联系人信息。

//扩容
int Capacity(CT* pc)
{if (pc->sz == pc->capacity){PI* ptr = (PI*)realloc(pc->data, sizeof(PI) * pc->capacity * 2);if (ptr == NULL){perror("realloc fail");return 0;}else{pc->capacity += 2;pc->data = ptr;printf("增容成功\n");return 1;}}return 1;
}
//增加联系人
void AddContact(CT* pc)
{assert(pc);if (0 == Capacity(pc)){return;}printf("请输入联系人姓名:");scanf("%s", &(pc->data[pc->sz].name));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("已成功添加该联系人!\n");
}

3.删除指定联系人

这里可以设置一个函数,找联系人是否存在,如果存在,则返回该联系人的位置。后面的查找和修改也能使用该函数,并且与删除非常类型

//找联系人是否存在
int FindContact(const CT* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}

刚开始输入要删除的联系人姓名,如果通讯录为空,没有可删除的联系人,就返回。
创建一个变量del接收FindContact函数的返回值,如果为-1就返回,否则就删除该位置的联系人信息。

//删除联系人
void DelContact(CT* pc)
{assert(pc);char name[10] = { 0 };printf("请输入要删除的联系人姓名:");scanf("%s", &name);if (pc->sz == 0){printf("没有可删除的联系人\n");return;}int del = FindContact(pc, name);if (del == -1){printf("要删除的联系人不存在\n");return;}int i = 0;for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("已删除该联系人\n");
}

4.查找指定联系人

//查找联系人
void SearchContact(const CT* pc)
{assert(pc);char name[10] = { 0 };printf("请输入要查找的联系人姓名:");scanf("%s", &name);if (pc->sz == 0){printf("没有可查找的联系人\n");return;}int sear = FindContact(pc, name);if (sear == -1){printf("要查找的联系人不存在\n");return;}printf("%-10s\t%-5s\t%-5s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话号码", "地址");printf("%-10s\t%-5d\t%-5s\t%-10s\t%-10s\n",pc->data[sear].name,pc->data[sear].age,pc->data[sear].sex,pc->data[sear].tele,pc->data[sear].addr);printf("查找成功\n");
}

5.修改指定联系人

//修改联系人
void ModifyContact(CT* pc)
{assert(pc);char name[10] = { 0 };printf("请输入要修改的联系人姓名:");scanf("%s", &name);if (pc->sz == 0){printf("没有可修改的联系人\n");return;}int mod = FindContact(pc, name);if (mod == -1){printf("要修改的联系人不存在\n");return;}printf("请输入联系人姓名:");scanf("%s", &(pc->data[mod].name));printf("请输入年龄:");scanf("%d", &(pc->data[mod].age));printf("请输入性别:");scanf("%s", &(pc->data[mod].sex));printf("请输入电话号码:");scanf("%s", &(pc->data[mod].tele));printf("请输入地址:");scanf("%s", &(pc->data[mod].addr));printf("修改成功\n");
}

6.排序联系人信息(排序名字)

使用qsort函数对结构体进行排序

//排序
int cmpname(const void* p1, const void* p2)
{return (strcmp(((PI*)p1)->name, ((PI*)p2)->name));
}
void SortContact(CT* pc)
{assert(pc);qsort(pc->data->name, pc->sz, sizeof(pc->data[0]), cmpname);printf("已排序所以联系人信息\n");printf("%-10s\t%-5s\t%-5s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话号码", "地址");int i = 0;for (i = 0; i < pc->sz; i++){printf("%-10s\t%-5d\t%-5s\t%-10s\t%-10s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}

7.清理通讯录

为了防止内存泄漏,所以后面退出程序前要清理通讯录
使用free释放掉data,然后置为空指针,其他的置为0

//清理
void DestroyContact(CT* pc)
{assert(pc);free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;
}

8.文件存盘

程序结束前要保存通讯录的信息

创建一个文件指针(pf),打开文件;
用fwrite函数写数据;
关闭文件。

//保存通讯录信息到文件
void SaveContact(CT* pc)
{assert(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(PI), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}

再次运行,显示通讯录的所有联系人信息要可以看到上次保存的信息

在初始化通讯录的函数里增加:
把文件保存的数据加载到通讯录的函数
LoadContact(pc);

在这个函数里创建一个个人信息的结构体指针变量tmp,每次循环读里面的信息到tmp里,然后赋给data,sz每次加1

注:因为其中有使用Capacity函数,所以先要声明这个函数

int Capacity(CT* pc);
void LoadContact(CT* pc)
{assert(pc);//打开文件FILE* pf = fopen("contact.dat", "rb");if (pf == NULL){perror("LoadContact");return;}//读文件PI tmp = { 0 };while (fread(&tmp, sizeof(PI), 1, pf)){if (0 == Capacity(pc))return;pc->data[pc->sz] = tmp;pc->sz++;}	//关闭文件fclose(pf);pf = NULL;
}

六.全部代码

1.Contact.h

#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>typedef struct PerInfo
{char name[10];int age;char sex[5];char tele[12];char addr[10];
}PI;
typedef struct Contact
{PI* data;int sz;int capacity;
}CT;
enum
{EXIT,//0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW,//5SORT//6
};
//初始化通讯录
void InitContact(CT* pc);
//增加联系人
void AddContact(CT* pc);
//显示全部联系人信息
void ShowContact(const CT* pc);
//删除联系人
void DelContact(CT* pc);
//查找联系人
void SearchContact(const CT* pc);
//修改联系人
void ModifyContact(CT* pc);
//排序通讯录
void SortContact(CT* pc);
//清理通讯录
void DestroyContact(CT* pc);
//保存通讯录信息到文件
void SaveContact(CT* pc);

2.test.c

#include "Contact.h"
void menu()
{printf("************************************\n");printf("*******  1.add     2.del   *********\n");printf("*******  3.search  4.modify  *******\n");printf("*******  5.show    6.sort  *********\n");printf("*******  0.exit           **********\n");printf("************************************\n");
}
int main()
{int input = 0;CT con;InitContact(&con);do{menu();printf("请选择:");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:SaveContact(&con);//保存通讯录信息到文件DestroyContact(&con);//清理通讯录printf("退出程序\n");break;default:printf("输入有误,请重试\n");break;}} while (input);return 0;
}

3.Contact.c

#include "Contact.h"
int Capacity(CT* pc);
void LoadContact(CT* pc)
{assert(pc);//打开文件FILE* pf = fopen("contact.dat", "rb");if (pf == NULL){perror("LoadContact");return;}//读文件PI tmp = { 0 };while (fread(&tmp, sizeof(PI), 1, pf)){if (0 == Capacity(pc))return;pc->data[pc->sz] = tmp;pc->sz++;}	//关闭文件fclose(pf);pf = NULL;
}
//初始化通讯录
void InitContact(CT* pc)
{assert(pc);pc->data = (PI*)malloc(sizeof(PI*) * 4);if (pc == NULL){perror("malloc fail");return;}pc->sz = 0;pc->capacity = 4;//把文件保存的数据加载到通讯录LoadContact(pc);
}
//扩容
int Capacity(CT* pc)
{if (pc->sz == pc->capacity){PI* ptr = (PI*)realloc(pc->data, sizeof(PI) * pc->capacity * 2);if (ptr == NULL){perror("realloc fail");return 0;}else{pc->capacity += 2;pc->data = ptr;printf("增容成功\n");return 1;}}return 1;
}
//增加联系人
void AddContact(CT* pc)
{assert(pc);if (0 == Capacity(pc)){return;}printf("请输入联系人姓名:");scanf("%s", &(pc->data[pc->sz].name));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("已成功添加该联系人!\n");
}
//显示全部联系人信息
void ShowContact(const CT* pc)
{assert(pc);printf("%-10s\t%-5s\t%-5s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话号码", "地址");int i = 0;for (i = 0; i < pc->sz; i++){printf("%-10s\t%-5d\t%-5s\t%-10s\t%-10s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}
//找联系人是否存在
int FindContact(const CT* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}
//删除联系人
void DelContact(CT* pc)
{assert(pc);char name[10] = { 0 };printf("请输入要删除的联系人姓名:");scanf("%s", &name);if (pc->sz == 0){printf("没有可删除的联系人\n");return;}int del = FindContact(pc, name);if (del == -1){printf("要删除的联系人不存在\n");return;}int i = 0;for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("已删除该联系人\n");
}
//查找联系人
void SearchContact(const CT* pc)
{assert(pc);char name[10] = { 0 };printf("请输入要查找的联系人姓名:");scanf("%s", &name);if (pc->sz == 0){printf("没有可查找的联系人\n");return;}int sear = FindContact(pc, name);if (sear == -1){printf("要查找的联系人不存在\n");return;}printf("%-10s\t%-5s\t%-5s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话号码", "地址");printf("%-10s\t%-5d\t%-5s\t%-10s\t%-10s\n",pc->data[sear].name,pc->data[sear].age,pc->data[sear].sex,pc->data[sear].tele,pc->data[sear].addr);printf("查找成功\n");
}
//修改联系人
void ModifyContact(CT* pc)
{assert(pc);char name[10] = { 0 };printf("请输入要修改的联系人姓名:");scanf("%s", &name);if (pc->sz == 0){printf("没有可修改的联系人\n");return;}int mod = FindContact(pc, name);if (mod == -1){printf("要修改的联系人不存在\n");return;}printf("请输入联系人姓名:");scanf("%s", &(pc->data[mod].name));printf("请输入年龄:");scanf("%d", &(pc->data[mod].age));printf("请输入性别:");scanf("%s", &(pc->data[mod].sex));printf("请输入电话号码:");scanf("%s", &(pc->data[mod].tele));printf("请输入地址:");scanf("%s", &(pc->data[mod].addr));printf("修改成功\n");
}
//排序
int cmpname(const void* p1, const void* p2)
{return (strcmp(((PI*)p1)->name, ((PI*)p2)->name));
}
void SortContact(CT* pc)
{assert(pc);qsort(pc->data->name, pc->sz, sizeof(pc->data[0]), cmpname);printf("已排序所以联系人信息\n");printf("%-10s\t%-5s\t%-5s\t%-10s\t%-10s\n", "姓名", "年龄", "性别", "电话号码", "地址");int i = 0;for (i = 0; i < pc->sz; i++){printf("%-10s\t%-5d\t%-5s\t%-10s\t%-10s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}
//清理
void DestroyContact(CT* pc)
{assert(pc);free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;
}
//保存通讯录信息到文件
void SaveContact(CT* pc)
{assert(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(PI), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}

~ ~ ~ ~
感谢观看
在这里插入图片描述

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

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

相关文章

supervisor因为依赖安装失败的解决方法

安装FEATA时报错情况 下列软件包有未满足的依赖关系&#xff1a;supervisor : 依赖: python-pkg-resources 但是它将不会被安装依赖: python-meld3 但是它将不会被安装依赖: python:any (< 2.8)依赖: python:any (> 2.7.5-5~) E: 无法修正错误&#xff0c;因为您要求某些…

elasticsearch 基础

ES 搜索技术历史 今天看的是《Elasticsearch实战与原理解析》 第一章 搜索技术发展史 1、搜索技术发展史 宏观而言&#xff0c;搜索引擎的发展经历了五个尖端和两大分类。五个阶段分别是ftp文件检索阶段、分类目录阶段、文本相关性检索阶段、网页链接分析阶段和用户意图识别…

nodejs+vue+elementui健康饮食美食菜谱分享网站系统

本系统采用了nodejs语言的vue框架&#xff0c;数据采用MySQL数据库进行存储。结合B/S结构进行开发设计&#xff0c;功能强大&#xff0c;界面化操作便于上手。本系统具有良好的易用性和安全性&#xff0c;系统功能齐全&#xff0c;可以满足饮食分享管理的相关工作。 语言 node.…

SpringBoot06---前端路由VueRouter

单页面应用&#xff0c;意思是只有一个html&#xff0c;变化的内容是不同组件进行切换&#xff0c;每个组件加载网络请求&#xff0c;渲染对应的数据&#xff0c;这个内容就是学习怎么完成组件切换 以网易云音乐为例&#xff1a; 网易云音乐 (163.com) 现在无需注册&#xf…

分类预测 | Matlab实现基于TSOA-CNN-GRU-Attention的数据分类预测

分类预测 | Matlab实现基于TSOA-CNN-GRU-Attention的数据分类预测 目录 分类预测 | Matlab实现基于TSOA-CNN-GRU-Attention的数据分类预测效果一览基本介绍研究内容程序设计参考资料 效果一览 基本介绍 Matlab实现分类预测 | Matlab实现基于TSOA-CNN-GRU-Attention的数据分类预…

String为什么设计成不可变的?

为什么要把 String 设计成不可变的呢&#xff1f;有什么好处呢&#xff1f; 这个问题&#xff0c;困扰过很多人&#xff0c;甚至有人直接问过 Java 的创始人 James Gosling。 在一次采访中 James Gosling 被问到什么时候应该使用不可变变量&#xff0c;他给出的回答是&#xff…

MySQL分表实现上百万上千万记录分布存储的批量查询设计模式

我们知道可以将一个海量记录的 MySQL 大表根据主键、时间字段&#xff0c;条件字段等分成若干个表甚至保存在若干服务器中。唯一的问题就是跨服务器批量查询麻烦&#xff0c;只能通过应用程序来解决。谈谈在Java中的解决思路。其他语言原理类似。这里说的分表不是 MySQL 5.1 的…

[C++ 网络协议编程] TCP/IP协议

目录 1. TCP/IP协议栈 2. TCP原理 2.1 TCP套接字中的I/O缓冲 2.2 TCP工作原理 2.2.1 三次握手&#xff08;连接&#xff09; 2.2.2 与对方主机的数据交换 2.2.3 四次握手&#xff08;断开与套接字的连接&#xff09; TCP&#xff08;Transmission Control Protocol传输控…

数据结构【第4章】——栈与队列

队列是只允许在一端进行插入操作、而在另-端进行删除操作的线性表。 栈 栈与队列&#xff1a;栈是限定仅在表尾进行插入和删除操作的线性表。 我们把允许插入和删除的一端称为栈顶&#xff08;top&#xff09;&#xff0c;另一端称为栈底&#xff08;bottom&#xff09;&…

yo!这里是STL::list类简单模拟实现

目录 前言 重要接口实现 框架 默认成员函数 迭代器&#xff08;重点&#xff09; 1.引言 2.list迭代器类实现 3.list类中调用实现 增删查改 后记 前言 我们知道&#xff0c;stl中的vector对应数据结构中的顺序表&#xff0c;string类对应字符串&#xff0c;而今天要…

vue3 excel 导出功能

1.安装 xlsx 库 npm install xlsx2.创建导出函数 src/utils/excelUtils.js import * as XLSX from xlsx;const exportToExcel (fileName, datas, sheetNames) > {// 创建工作簿const wb XLSX.utils.book_new()for (let i 0; i < datas.length; i) {let data datas…

【腾讯云 Cloud Studio 实战训练营】使用 Cloud Studio 快速构建 Vue + Vite 完成律师 H5 页面

【腾讯云 Cloud Studio 实战训练营】使用 Cloud Studio 快速构建 Vue Vite 完成律师 H5 页面 前言一、基本介绍1.应用场景2.产品优势 二、准备工作1.注册 Cloud Studio2.进入 Vue 预置开发环境 三、使用 Cloud Studio 快速构建 Vue Vite 完成律师 H5 页面1.安装相关依赖包2.主…

Spring Boot2.xx开启监控 Actuator

spring boot actuator介绍 Spring Boot包含许多其他功能&#xff0c;可帮助您在将应用程序推送到生产环境时监视和管理应用程序。 您可以选择使用HTTP端点或JMX来管理和监视应用程序。 审核&#xff0c;运行状况和指标收集也可以自动应用于您的应用程序。 总之Spring Boot Ac…

【Transformer】自注意力机制Self-Attention | 各种网络归一化Normalization

1. Transformer 由来 & 特点 1.1 从NLP领域内诞生 "Transformer"是一种深度学习模型&#xff0c;首次在"Attention is All You Need"这篇论文中被提出&#xff0c;已经成为自然语言处理&#xff08;NLP&#xff09;领域的重要基石。这是因为Transfor…

【APITable】教程:创建并运行一个自建小程序

1.进入APITable&#xff0c;在想要创建小程序的看板页面点击右上角的【小程序】&#xff0c;进入小程序编辑页面。 2.创建一个新的小程序区。 点击【 添加小程序】 点击创建小程序&#xff0c;选择模板&#xff0c;输入名字。 3.确定后进入小程序部署引导页面。 4.打开Xshell 7…

201、仿真-基于51单片机PT100测温设计铂电阻温度计设计Proteus仿真(程序+Proteus仿真+原理图+流程图+元器件清单+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、设计功能 二、Proteus仿真图 三、原理图 四、程序源码 资料包括&#xff1a; 方案选择 单片机的选择 方案一&#xff1a;STM32系列单片机控制&#xff0c;该型号单片机为LQFP44封装&#xff0c;内部资源足够用于本次设…

【vue+el-table+el-backtop】表格结合返回顶部使用,loading局部加载

效果图: 一. 表格结合返回顶部 二. 局部loading 解决方法: 一 返回顶部 target绑定滚动dom的父元素类名就可以了. 1.如果你的表格是 固定表头 的,那滚动dom的父元素类名就是 el-table__body-wrapper <el-backtop target".el-table__body-wrapper" :visibility…

项目介绍:《WeTalk》网页聊天室 — Spring Boot、MyBatis、MySQL和WebSocket的奇妙融合

目录 引言&#xff1a; 前言&#xff1a; 技术栈&#xff1a; 主要功能&#xff1a; 功能详解&#xff1a; 1. 用户注册与登录&#xff1a; 2. 添加好友 3. 实时聊天 4. 消息未读 5. 删除聊天记录 6. 删除好友 未来展望&#xff1a; 项目地址&#xff1a; 结语&am…

zookeeperAPI操作与写数据原理

要执行API操作需要在idea中创建maven项目 &#xff08;改成自己的阿里仓库&#xff09;导入特定依赖 添加日志文件 上边操作做成后就可以进行一些API的实现了 目录 导入maven依赖&#xff1a; 创建日志文件&#xff1a; 创建API客户端&#xff1a; &#xff08;1&#xff09…

阿里云服务器安装部署Docker使用教程

本文阿里云百科分享如何在云服务ECS实例上&#xff0c;部署并使用Docker。Docker是一款开源的应用容器引擎&#xff0c;具有可移植性、可扩展性、高安全性和可管理性等优势。开发者可将应用程序和依赖项打包到一个可移植的容器中&#xff0c;快速发布到Linux机器上并实现虚拟化…