动态顺序表实现通讯录

news2024/7/6 19:36:20

系列文章目录

【数据结构】顺序表


文章目录

  • 系列文章目录
  • 前言
  • 一、通讯录的功能要求
  • 二、通讯录的代码实现
    • 1. 新建文件
    • 2. 创建通讯录的结构体
    • 3. 对顺序表文件进行修改
    • 4. 通讯录具体功能实现
      • 4.1. 通讯录的初始化和销毁
      • 4.2. 增加联系人信息(尾插)
      • 4.3. 查找指定联系人(通过姓名查找)
      • 4.4. 删除指定联系人
      • 4.5. 修改指定联系人
      • 4.6. 显示联系人信息
  • 三、完整代码
  • 四、效果展示
  • 总结


前言

回顾上文,我们初步了解了顺序表,顺序表的本质就是数组,但相比于单纯的数组,顺序表多出了一些功能——增删查改。那么顺序表究竟有什么用呢?接下来为大家使用顺序表实现一个简易的通讯录。(使用动态顺序表实现)


正文开始

一、通讯录的功能要求

  1. 至少能够存储100个人的通讯信息
  2. 能够保存用户信息:名字、性别、年龄、电话、地址等
  3. 增加联系人信息
  4. 删除指定联系人
  5. 查找指定联系人
  6. 修改指定联系人
  7. 显示联系人信息

二、通讯录的代码实现

1. 新建文件

顺序表作为一种数据结构,只是一个工具,当我们要使用它去实现具体的东西时还需要对其进行包装。所以,我们这里在原来顺序表的基础上新建了两个文件——Contact.h和Contact.c。
在这里插入图片描述
Contact.h中存放通讯录所需的函数的声明和结构体的声明。
Contact.c中存放通讯录中函数的定义。

2. 创建通讯录的结构体

接下来我们就需要在Contact.h中创建一个通讯录的结构体,要包含的信息有:名字、性别、年龄、电话、地址。所以我们的顺序表中的元素的类型要是结构体,该结构体有5个成员。

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 20

typedef struct personinform
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}perinfo;

由于我们要实现通讯录,我们的顺序表的结构体的结构体名要更改为Contact,且要在该头文件中就要实现,因为后面有对应函数的声明,所以我们要在Contact.h中使用前置声明。

typedef struct Sepline Contact; // 只有前置声明才能更改顺序表的结构体名。

3. 对顺序表文件进行修改

我们在Contact.h中把套在顺序表上的外壳写完,我们还要对原来的顺序表进行小幅度修改,使其与我们要实现的功能匹配。
首先就要包含Contact.h这个头文件,然后将typedef后的int改为perinfo

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
typedef perinfo SLtype;
//动态顺序表
typedef struct Sepline
{
	SLtype* arr;
	int size;//有效数字大小
	int capacity;//动态内存大小
}SL;

最后,我们要将顺序表的函数实现进行修改,原本是实现int的,现在要改为实现结构体形式。

void SLshow(SL* sl)
{
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");

	for (int i = 0; i < sl->size; i++)
		printf("%3s  %3s  %3d  %3s  %3s\n", 
			sl->arr[i].name, 
			sl->arr[i].gender,
			sl->arr[i].age,
			sl->arr[i].tel,
			sl->arr[i].addr);
}

顺序表的修改和查找,我选择删除重新实现,要修改与重写没什么区别。

4. 通讯录具体功能实现

4.1. 通讯录的初始化和销毁

//初始化
void Con_init(Contact* con);

//销毁
void Con_des(Contact* con);
void Con_init(Contact* con)
{
	SLinit(con);
}

void Con_des(Contact* con)
{
	SLdestory(con);
}

这就是使用了顺序表后的情况,在具体实现函数时只需要套用之前的函数就可以了。

4.2. 增加联系人信息(尾插)

//插入(后插)
void Con_insert(Contact* con);
void Con_insert(Contact* con)
{
	perinfo x = { 0 };
	printf("请输入联系人姓名:");
	scanf("%s", x.name);
	printf("请输入联系人性别:");
	scanf("%s", x.gender);
	printf("请输入联系人年龄:");
	scanf("%d", &x.age);
	printf("请输入联系人电话:");
	scanf("%s", x.tel);
	printf("请输入联系人地址:");
	scanf("%s", x.addr);

	SL_in_back(con, x);
}

4.3. 查找指定联系人(通过姓名查找)

int Con_find_name(Contact* con, char name[]);
int Con_find_name(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(name, con->arr[i].name))
			return i;
	}
	return -1;
}

4.4. 删除指定联系人

//指定删除
void Con_del(Contact* con);
void Con_del(Contact* con)
{
	char name[20];
	printf("请输入需要删除的联系人:");
	scanf("%s", name);
	int find = Con_find_name(con, name);

	if (find != -1)
	{
		SLindel(con, find);
		printf("删除成功\n");
	}
	else
	{
		printf("需要删除的联系人不存在\n");
	}
}

4.5. 修改指定联系人

//修改
void Con_fix_name(Contact* con);
void Con_fix_name(Contact* con)
{
	char name[20];
	printf("请输入需要修改的联系人姓名:");
	scanf("%s", name);
	int find = Con_find_name(con, name);

	perinfo x = { 0 };
	printf("请输入修改后的姓名:");
	scanf("%s", x.name);
	printf("请输入修改后的性别:");
	scanf("%s", x.gender);
	printf("请输入修改后的年龄:");
	scanf("%d", &x.age);
	printf("请输入修改后的电话:");
	scanf("%s", x.tel);
	printf("请输入修改后的地址:");
	scanf("%s", x.addr);
	con->arr[find] = x;
}

4.6. 显示联系人信息

//展示
void Con_show(Contact* con);
void Con_show(Contact* con)
{
	SLshow(con);
}

这些通讯录的函数的实现基本都通过调用了顺序表的函数,大大减少了我们需要写的代码量,而且还不用考虑数据是如何增加,删除等。当然,前提是顺序表的函数没有写错。

三、完整代码

Contact.h

#pragma once

#define NAME_MAX 20
#define GENDER_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 20

typedef struct personinform
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}perinfo;

typedef struct Sepline Contact; // 只有前置声明才能更改顺序表的结构体名。

//初始化
void Con_init(Contact* con);

//销毁
void Con_des(Contact* con);

//插入(后插)
void Con_insert(Contact* con);

//指定删除
void Con_del(Contact* con);

//展示
void Con_show(Contact* con);

//查找
int Con_find_name(Contact* con, char name[]);

//修改
void Con_fix_name(Contact* con);

Sepline.h

#pragma once
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "Contact.h"
typedef perinfo SLtype;
//动态顺序表
typedef struct Sepline
{
	SLtype* arr;
	int size;//有效数字大小
	int capacity;//动态内存大小
}SL;

//顺序表初始化
void SLinit(SL* sl);

//顺序表销毁
void SLdestory(SL* sl);

//后插
void SL_in_back(SL* sl, SLtype x);

//前插
void SL_in_front(SL* sl, SLtype x);

//后删
void SL_out_back(SL* sl);

//前删
void SL_out_front(SL* sl);

//展示
void SLshow(SL* sl);

//查找
int SLfind(SL* sl, SLtype n);

//修改
void SLfix(SL* sl, int n);

//指定位置增加
void SLinsert(SL* sl, int n, SLtype x);

//指定位置删除
void SLindel(SL* sl, int n);

//扩展空间
void SLapply(SL* sl);

Contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Sepline.h"
#include "Contact.h"

void Con_init(Contact* con)
{
	SLinit(con);
}

void Con_des(Contact* con)
{
	SLdestory(con);
}

void Con_insert(Contact* con)
{
	perinfo x = { 0 };
	printf("请输入联系人姓名:");
	scanf("%s", x.name);
	printf("请输入联系人性别:");
	scanf("%s", x.gender);
	printf("请输入联系人年龄:");
	scanf("%d", &x.age);
	printf("请输入联系人电话:");
	scanf("%s", x.tel);
	printf("请输入联系人地址:");
	scanf("%s", x.addr);

	SL_in_back(con, x);
}

int Con_find_name(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(name, con->arr[i].name))
			return i;
	}
	return -1;
}

void Con_del(Contact* con)
{
	char name[20];
	printf("请输入需要删除的联系人:");
	scanf("%s", name);
	int find = Con_find_name(con, name);

	if (find != -1)
	{
		SLindel(con, find);
		printf("删除成功\n");
	}
	else
	{
		printf("需要删除的联系人不存在\n");
	}
}

void Con_show(Contact* con)
{
	SLshow(con);
}

void Con_fix_name(Contact* con)
{
	char name[20];
	printf("请输入需要修改的联系人姓名:");
	scanf("%s", name);
	int find = Con_find_name(con, name);

	perinfo x = { 0 };
	printf("请输入修改后的姓名:");
	scanf("%s", x.name);
	printf("请输入修改后的性别:");
	scanf("%s", x.gender);
	printf("请输入修改后的年龄:");
	scanf("%d", &x.age);
	printf("请输入修改后的电话:");
	scanf("%s", x.tel);
	printf("请输入修改后的地址:");
	scanf("%s", x.addr);
	con->arr[find] = x;
}

Sepline.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Sepline.h"
void SLinit(SL* sl)
{
	sl->arr = NULL;
	sl->size = sl->capacity = 0;
}

void SLdestory(SL* sl)
{
	free(sl->arr);
	sl->arr = NULL;
	sl->size = sl->capacity = 0;
}


void SLapply(SL* sl)
{
	if (sl->size == sl->capacity)
	{
		sl->capacity = sl->capacity == 0 ? 4 : 2 * sl->capacity;
		SLtype* tmp = (SLtype*)realloc(sl->arr, sl->capacity * sizeof(SLtype));
		if (tmp == NULL)
		{
			perror("realloc");
			exit(1);
		}
		sl->arr = tmp;
		tmp = NULL;
	}
}

void SL_in_back(SL* sl, SLtype x)
{
	assert(sl);
	SLapply(sl);
	sl->arr[sl->size++] = x;
}

void SL_in_front(SL* sl, SLtype x)
{
	assert(sl);
	SLapply(sl);
	for (int i = sl->size; i > 0; i--)
	{
		sl->arr[i] = sl->arr[i - 1];
	}
	sl->arr[0] = x;
	sl->size++;
}

void SL_out_back(SL* sl)
{
	assert(sl);
	assert(sl->size);
	sl->size--;
}

void SLshow(SL* sl)
{
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");

	for (int i = 0; i < sl->size; i++)
		printf("%3s  %3s  %3d  %3s  %3s\n", 
			sl->arr[i].name, 
			sl->arr[i].gender,
			sl->arr[i].age,
			sl->arr[i].tel,
			sl->arr[i].addr);
}

void SL_out_front(SL* sl)
{
	assert(sl);
	assert(sl->size);
	for (int i = 0; i < sl->size - 1; i++)
		sl->arr[i] = sl->arr[i + 1];
	sl->size--;
}

//int SLfind(SL* sl, SLtype n)
//{
//	assert(sl);
//	//assert(n >= 0 && n < sl->size);
//	for (int i = 0; i < sl->size; i++)
//	{
//		if (n == sl->arr[i])
//			return i;
//	}
//	return -1;
//}

//void SLfix(SL* sl, int n)
//{
//	assert(sl);
//	assert(n >= 0 && n < sl->size);
//	int num = 0;
//	printf("请输入修改后的数:");
//	scanf("%d", &num);
//	sl->arr[n] = num;
//}

void SLinsert(SL* sl, int n, SLtype x)
{
	assert(sl);
	assert(n >= 0 && n <= sl->size);
	SLapply(sl);
	for (int i = sl->size; i > n; i--)
	{
		sl->arr[i] = sl->arr[i - 1];
	}
	sl->arr[n] = x;
	sl->size++;
}

void SLindel(SL* sl, int n)
{
	assert(sl);
	assert(n >= 0 && n < sl->size);
	for (int i = n; i < sl->size - 1; i++)
	{
		sl->arr[i] = sl->arr[i + 1];
	}
	sl->size--;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Sepline.h"
#include "Contact.h"

void menu()
{
	printf("\n");
	printf("***********通讯录**********\n");
	printf("**** 1. 增加   2. 删除 ****\n");
	printf("**** 3. 查找   4. 展示 ****\n");
	printf("**** 5. 修改   0. 退出 ****\n");
	printf("***************************\n");
}
void test()
{
	
	Contact con;
	char name[20];
	int choose = 0;
	Con_init(&con);
	
	do
	{
		menu();
		printf("请输入你要进行的操作(输入前面数字):");
		scanf("%d", &choose);
		switch (choose)
		{
		case 1: Con_insert(&con);
			break;
		case 2: Con_del(&con);
			break;
		case 3:
			printf("请输入你要查找的联系人姓名:");
			scanf("%s", name);
			int find = Con_find_name(&con, name);
			if (find < 0)
				printf("没找到\n");
			else
				printf("找到了,在第%d个\n", find);
			break;
		case 4: Con_show(&con);
			break;
		case 5: Con_fix_name(&con);
			break;
		case 0: printf("退出应用\n");
			break;
		default: printf("请输入0~6之间的数\n");
			break;
		}
	} while (choose);
	

	Con_des(&con);
}

int main()
{
	test();
	return 0;
}

四、效果展示

增加联系人
在这里插入图片描述
修改联系人
在这里插入图片描述
删除联系人
在这里插入图片描述
展示联系人
在这里插入图片描述
查找联系人
在这里插入图片描述


总结

通讯录的实现实际十分简单,我们只要能熟练掌握顺序表的功能的实现,再在顺序表上套一个外壳就变成了通讯录。我们这个通讯录还有点小问题——无法一直保存数据。如果想要一直保存可以使用文件来操作,将每次修改的数据保存到一个文件里,每次进入程序先从该文件中读取数据,结束时将数据传回文件中。大家可以试着实现以下。
这里是我的解决方法:
test.c

void test()
{
	FILE* pf = fopen("Contact.txt", "r");
	Contact con;
	char name[20];
	int choose = 0;
	Con_init(&con);
	Con_insert_file(&con, pf);
	do
	{
		menu();
		printf("请输入你要进行的操作(输入前面数字):");
		scanf("%d", &choose);
		switch (choose)
		{
		case 1: Con_insert(&con);
			break;
		case 2: Con_del(&con);
			break;
		case 3: 
			printf("请输入你要查找的联系人姓名:");
			scanf("%s", name);
			int find = Con_find_name(&con, name);
			if (find < 0)
				printf("没找到\n");
			else
				printf("找到了,在第%d个\n", find);
			break;
		case 4: Con_show(&con);
			break;
		case 5: Con_fix_name(&con);
			break;
		case 0: printf("退出应用\n");
			break;
		default: printf("请输入0~6之间的数\n");
			break;
		}
	} while(choose);
	fclose(pf);
	pf = NULL;
	pf = fopen("Contact.txt", "w");
	for (int i = 0; i < con.size; i++)
	{
		fprintf(pf, "%s %s %d %s %s\n",
			con.arr[i].name,
			con.arr[i].gender,
			con.arr[i].age,
			con.arr[i].tel,
			con.arr[i].addr);
	}
	fclose(pf);
	pf = NULL;

	Con_des(&con);
}

Contact.c

void Con_insert_file(Contact* con, FILE* pf)
{
	int ret = 0;
	int i = 0;
	while (ret != EOF)
	{
		SLapply(con);
		ret = fscanf(pf, "%s %s %d %s %s",
			con->arr[i].name,
			con->arr[i].gender,
			&con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr);
		if (ret != EOF)
		{
			con->size++;
			i++;
		}
	}
}

Contact.h

//文件插入
void Con_insert_file(Contact* con, FILE* pf);

感谢观看!!!

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

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

相关文章

无污染的独立海域-第13届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第90讲。 无污染的独立海域…

余承东在母校西工大毕业典礼演讲:定位决定地位,眼界决定境界。

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 【6月29日&#xff0c;西北工业大学2024届本科生毕业典礼暨学位授予仪式隆重举行。典礼上&#xff0c;华为常务董事、终端BG 董事长、智能汽车解决方案BU 董事长余承东作为校友代表致辞&#xff0c;为毕业生…

项目实战--Spring Boot实现三次登录容错功能

一、功能描述 项目设计要求输入三次错误密码后&#xff0c;要求隔段时间才能继续进行登录操作&#xff0c;这里简单记录一下实现思路 二、设计方案 有几个问题需要考虑一下&#xff1a; 1.是只有输错密码才锁定&#xff0c;还是账户名和密码任何一个输错就锁定&#xff1f;2…

gz格式文件16进制分析

接上篇长虹55D3P (海思平台)kernel分区解包ramdisk重新打包-CSDN博客深入研究下gz格式 上篇说到分割得到的ramdisk会有垃圾数据&#xff0c;对于ramdisk无用的垃圾数据可能有其他用途。我们只需要修改ramdisk&#xff0c;就必须准确知道ramdisk的起始地址和结束地址&#xff0…

刚入行的测试新人,应该如何规划自己的职业发展路径?

作为一个刚入行的测试新人&#xff0c;应该如何规划自己的职业发展路径&#xff1f;如何规划自己的技术路线&#xff1f;软件测试的段位都有哪些&#xff1f;他们之间的薪资差异如何&#xff1f; 听说这些问题&#xff0c;是目前想要入行软件测试的同学们最关心的。那么我们今天…

钡铼BL104智慧环保多个485采集转MQTT无线传输

PLC物联网关BL104是一款专为工业环境设计的先进协议转换网关&#xff0c;其集成了钡铼智能技术和环保多个485采集转MQTT无线传输功能&#xff0c;为工业控制系统提供了高效的数据采集、传输和管理解决方案。 技术规格与功能特点 PLC物联网关BL104采用钡铼智能技术&#xff0c…

k8s部署单节点redis

一、configmap # cat redis-configmap.yaml apiVersion: v1 kind: ConfigMap metadata:name: redis-single-confignamespace: redis data:redis.conf: |daemonize nobind 0.0.0.0port 6379tcp-backlog 511timeout 0tcp-keepalive 300pidfile /data/redis-server.pidlogfile /d…

顺序表实现——通讯录

前言&#xff1a; 通过对数据结构--顺序表的学习&#xff0c;了解了顺序表的增加数据&#xff0c;删除数据等功能&#xff1b;我们就可以基于顺序表来实现通讯录&#xff0c;接下来就一起来实现通讯录。 首先我们需要存储通讯录中联系人信息&#xff0c;这里创建一个结构体&…

Vue报错:Module not found: Error: Can‘t resolve ‘less-loader‘ in ‘文件地址‘

原因&#xff1a;Webpack无法找到 less-loader 模块&#xff0c;但在<style langless></style>中进行使用。less-loader 是一个Webpack的加载器&#xff0c;它用于将less文件编译成CSS。如果Webpack无法解析这个加载器&#xff0c;它就无法处理less文件&#xff0c…

【C语言内存函数】

目录 1.memcpy 使用 模拟实现 2.memmove 使用 模拟实现 3.memset 使用 4.memcmp 使用 1.memcpy 使用 void * memcpy ( void * destination, const void * source, size_t num );目的地址 源地址 字节数 destination&#xff1a;指向要复制内…

EDA 虚拟机 Synopsys Sentaurus TCAD 2017.09 下载

下载地址&#xff08;制作不易&#xff0c;下载使用需付费&#xff0c;不能接受的请勿下载&#xff09;&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1327I58gvV1usWSqSrG7KXw?pwdo03i 提取码&#xff1a;o03i

heic图片怎么转成jpg格式,这6个方法亲测有用(超简单)

heic图片怎么转成jpg&#xff1f;现在我们都喜欢用手机来拍摄记录生活中的美好瞬间&#xff0c;照片太多的话我们为了不占用手机内存&#xff0c;会把照片导入电脑进行储存。但是苹果手机用户在导入相册照片时可能会遇到以下问题&#xff1a;因为苹果手机拍摄照片格式默认为hei…

友思特应用 | 多接口的智驾无忧:GigE相机在自动驾驶数据采集系统的稳定应用

导读 GigE接口相机为自动驾驶数据采集提供了高性价比的选择。在此基础上&#xff0c;友思特搭建了多GigE接口支持PTP的采集设备系统级方案 BRICK2&#xff0c;为多传感器数据记录测试提供了完整的解决方案。 GigE接口相机与智能驾驶数据采集 智能驾驶技术的发展已经成为当今科…

【前端vue3】TypeScrip-元组类型和枚举类型

元组类型 元组就是数组的变形 元组&#xff08;Tuple&#xff09;是固定数量的不同类型的元素的组合。 元组与集合的不同之处在于&#xff0c;元组中的元素类型可以是不同的&#xff0c;而且数量固定。元组的好处在于可以把多个元素作为一个单元传递。如果一个方法需要返回多个…

day03-主页模块-修改密码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.获取用户资料在Vuex中共享登录成功跳转到主页之后&#xff0c;可以获取用户资料&#xff0c;获取的资料在Vuex中共享&#xff0c;这样用户就可以很方便的获取该信…

【基础算法总结】分治—快排

分治—快排 1.分治2.颜色分类3.排序数组4.数组中的第K个最大元素5.库存管理 III 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 1.分治 分治…

Node.js安装及配置

文章目录 1.安装Node.js2.创建目录3.配置环境变量4.配置全局安装路径和缓存路径(可选)配置Webstorm 1.安装Node.js https://registry.npmmirror.com/binary.html?pathnode 推荐安装18.x版本 2.创建目录 下载解压后进入目录&#xff0c;创建node_global和node_cache两个空文…

在嵌入式商用里面哪款RTOS(实时操作系统)比较多人用?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 传统的RTOS和嵌入式Linu…

【氮化硼】 h-BN薄膜的控制辐射损伤和边缘结构

摘要: 本文展示了通过化学剥离法合成的六方氮化硼(h-BN)膜在80 kV电子束辐照下表现出比石墨烯更高的抗辐射损伤能力。研究表明,即使在长时间电子束辐照下,单层h-BN也不会形成空位缺陷或发生非晶化。实验观察到在h-BN薄膜中,锯齿形边缘结构占主导地位,且这些边缘主要由氮…

6个操作简单又好用的实用办公工具

分享6个操作简单又好用的实用办公工具&#xff0c;手机和电脑上的都有&#xff0c;好好使用可以让工作效率翻倍&#xff01; 1.方方格子 一个大型的的【Excel工具箱】&#xff0c;支持32位和64位Office&#xff0c;可直接作为插件使用&#xff0c;功能覆盖非常全面&#xff0c…