顺序表的应用-通讯录

顺序表的应用-通讯录

  • 1.操作
  • 2.功能要求
    • 2.1.功能要求
    • 2.2.思路小结
    • 2.3.文件梳理
    • 2.4.代码实现
      • "SeqList.h"
      • "Contact.h"
      • "SeqList.c"
      • "Contact.c"
      • "test.c"

1.操作

链接: 顺序表专题
这篇文章介绍了顺序表的概念与基本操作。
本文将在此基础上进行一定的拓展,完成应用通讯表。

2.功能要求

2.1.功能要求

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

2.2.思路小结

简单来说,通讯录与之前的最典型顺序表的区别在于数组存储的类型.

最典型顺序表存储的就是整数类型,是一个个数字.
在这里插入图片描述

在这里插入图片描述
而通讯录则是在数组中存储相关结构体,包含功能要求的信息.
在这里插入图片描述

除此之外,基本操作思路与代码都如出一辙.

  1. 定义通讯录信息存储结构体类型
#define NAME_MAX 20
#define GENDER_MAX 10 
#define TEL_MAX 20
#define ADDR_MAX 100
//定义联系人数据 结构
//姓名 性别 年龄 电话 地址
typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}peoInfo;
  1. 定义动态顺序表基本结构
typedef peoInfo SLDataType;
//动态顺序表
typedef struct SeqList
{
	SLDataType* arr;
	int size; //有效数据个数
	int capacity; //空间大小
}SL;
  1. 各种操作
//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDesTroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);
  1. 菜单显示
int main()
{
	int op = -1;
	Contact con;
	ContactInit(&con);

	do {
		menu();
		printf("请选择您的操作:\n");
		scanf("%d", &op);

		//要根据对应的op执行不同的操作
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("退出通讯录....\n");
			break;
		default:
			printf("输入错误,请重新选择您的操作!\n");
			break;
		}
	} while (op != 0);

	ContactDesTroy(&con);
	return 0;
}

在这里插入图片描述

2.3.文件梳理

主要有5个文件,

2个.h头文件:
“SeqList.h”

主要是基本顺序表操作的罗列

“Contact.h”

主要是通讯录操作的罗列

“Contact.h"是在"SeqList.h"的基础上发展而来的.
部分通用的代码按照"SeqList.h”
需要调整的代码主要写于"Contact.h"

3个.c源文件.
“SeqList.c”

顺序表操作的具体代码实现

“Contact.c”

通讯录操作的具体代码实现

“test.c”

调试测试

2.4.代码实现

“SeqList.h”

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"
//定义顺序表的结构

//#define N 100
//
静态顺序表
//struct SeqList
//{
//	int arr[N];
//	int size;//有效数据个数
//};

//typedef int SLDataType;//方便后续类型的替换
typedef peoInfo SLDataType;
//动态顺序表
typedef struct SeqList
{
	SLDataType* arr;
	int size; //有效数据个数
	int capacity; //空间大小
}SL;

//typedef struct SeqList SL;

//顺序表初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
void SLPrint(SL s);

//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);

void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
//查找指定位置
int SLFind(SL* ps, SLDataType x);

“Contact.h”

#pragma once


#define NAME_MAX 20
#define GENDER_MAX 10 
#define TEL_MAX 20
#define ADDR_MAX 100
//定义联系人数据 结构
//姓名 性别 年龄 电话 地址
typedef struct personInfo
{
	char name[NAME_MAX];
	char gender[GENDER_MAX];
	int age;
	char tel[TEL_MAX];
	char addr[ADDR_MAX];
}peoInfo;


//要用到顺序表相关的方法,对通讯录的操作实际就是对顺序表进行操作
//给顺序表改个名字,叫做通讯录
typedef struct SeqList Contact; //前置声明+改名字成Contact
//不能直接用SL  原因是SL是struct SeqList定义之后取得新名字,如果是用当前顺序表这个结构,必须用struct SeqList
// 或者说,写SL不能直接找到顺序表这个结构体


//通讯录相关的方法

//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDesTroy(Contact* con);
//通讯录添加数据
void ContactAdd(Contact* con);
//通讯录删除数据
void ContactDel(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
//展示通讯录数据
void ContactShow(Contact* con);

“SeqList.c”

#define _CRT_SECURE_NO_WARNINGS

#include"SeqList.h"
void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{
	if (ps->arr) //等价于  if(ps->arr != NULL)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}
void SLCheckCapacity(SL* ps)
{
	//插入数据之前先看空间够不够
	if (ps->capacity == ps->size)
	{
		//申请空间
		//malloc calloc realloc  int arr[100] --->增容realloc
		//三目表达式
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要申请多大的空间
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);//直接退出程序,不再继续执行
		}
		//空间申请成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	温柔的解决方式
	//if (ps == NULL)
	//{
	//	return;
	//}
	assert(ps); //等价与assert(ps != NULL)

	//ps->arr[ps->size] = x;
	//++ps->size;
	SLCheckCapacity(ps);
	ps->arr[ps->size++] = x;
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	//先让顺序表中已有的数据整体往后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[1] = arr[0]
	}
	ps->arr[0] = x;
	ps->size++;
}

//void SLPrint(SL s)
//{
//	for (int i = 0; i < s.size; i++)
//	{
//		printf("%d ", s.arr[i]);
//	}
//	printf("\n");
//}
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	//顺序表不为空
	//ps->arr[ps->size - 1] = -1;
	--ps->size;
}
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);

	//数据整体往前挪动一位
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1]; //arr[size-2] = arr[size-1]
	}
	ps->size--;
}
//在指定位置之前插入数据
// 1 2   size = 2
//pos 0 -1 100000
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	//插入数据:空间够不够
	SLCheckCapacity(ps);
	//让pos及之后的数据整体往后挪动一位
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//arr[pos+1] = arr[pos]
	}
	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--;
}
//查找
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			//找到啦
			return i;
		}
	}
	//没有找到
	return -1;
}

“Contact.c”

#define _CRT_SECURE_NO_WARNINGS

#include"Contact.h"
#include"SeqList.h"

//通讯录的初始化
void ContactInit(Contact* con)//sl
{
	//实际上要进行的是顺序表的初始化
	//顺序表的初始化已经实现好了
	SLInit(con);
}
//通讯录的销毁
void ContactDesTroy(Contact* con)
{
	SLDestroy(con);
}
//通讯录添加数据
void ContactAdd(Contact* con)
{
	//获取用户输入的内容:姓名+性别+年龄+电话+地址
	peoInfo info;
	printf("请输入要添加的联系人姓名:\n");
	scanf("%s", info.name);

	printf("请输入要添加的联系人性别:\n");
	scanf("%s", info.gender);

	printf("请输入要添加的联系人年龄:\n");
	scanf("%d", &info.age);

	printf("请输入要添加的联系人电话:\n");
	scanf("%s", info.tel);

	printf("请输入要添加的联系人住址:\n");
	scanf("%s", info.addr);

	//往通讯录中添加联系人数据
	SLPushBack(con, info);
}

int FindByName(Contact* con, char name[])
{
	for (int i = 0; i < con->size; i++)
	{
		if (0 == strcmp(con->arr[i].name, name))
		{
			//找到了
			return i;
		}
	}
	//没有找到
	return -1;
}

//通讯录删除数据
void ContactDel(Contact* con)
{
	//要删除的数据必须要存在,才能执行删除操作
	//查找
	char name[NAME_MAX];
	printf("请输入要删除的联系人姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要删除的联系人数据不存在!\n");
		return;
	}
	//要删除的联系人数据存在--->知道了要删除的联系人数据对应的下标
	SLErase(con, find);
	printf("删除成功!\n");
}
//展示通讯录数据
void ContactShow(Contact* con)
{
	//表头:姓名  性别 年龄 电话  地址
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	//遍历通讯录,按照格式打印每个联系人数据
	for (int i = 0; i < con->size; i++)
	{
		printf("%3s %3s %3d %3s %3s\n", //手动调整一下格式
			con->arr[i].name,
			con->arr[i].gender,
			con->arr[i].age,
			con->arr[i].tel,
			con->arr[i].addr
		);
	}
}
//通讯录的修改
void ContactModify(Contact* con)
{
	//要修改的联系人数据存在
	char name[NAME_MAX];
	printf("请输入要修改的用户姓名:\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要修改的联系人数据不存在!\n");
		return;
	}
	//直接修改
	printf("请输入新的姓名:\n");
	scanf("%s", con->arr[find].name);

	printf("请输入新的性别:\n");
	scanf("%s", con->arr[find].gender);

	printf("请输入新的年龄:\n");
	scanf("%d", &con->arr[find].age);

	printf("请输入新的电话:\n");
	scanf("%s", con->arr[find].tel);

	printf("请输入新的住址:\n");
	scanf("%s", con->arr[find].addr);

	printf("修改成功!\n");
}
//通讯录查找
void ContactFind(Contact* con)
{
	//11

	char name[NAME_MAX];
	printf("请输入要查找的联系人姓名\n");
	scanf("%s", name);

	int find = FindByName(con, name);
	if (find < 0)
	{
		printf("要查找的联系人数据不存在!\n");
		return;
	}
	// 姓名 性别 年龄 电话  地址
	// 11   11   11   11   11
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
	printf("%3s %3s %3d %3s %3s\n", //手动调整一下格式
		con->arr[find].name,
		con->arr[find].gender,
		con->arr[find].age,
		con->arr[find].tel,
		con->arr[find].addr
	);
}

“test.c”

#define _CRT_SECURE_NO_WARNINGS

#include"SeqList.h"

//void SLTest01()
//{
//	SL sl;
//	SLInit(&sl);
//	//增删查改操作
//	//测试尾插
//	SLPushBack(&sl, 1);
//	SLPushBack(&sl, 2);
//	SLPushBack(&sl, 3);
//	SLPushBack(&sl, 4);
//	SLPrint(sl);//1 2 3 4
//
//	//SLPushFront(&sl, 5);
//	//SLPushFront(&sl, 6);
//
//	//测试尾删
//	SLPopBack(&sl);
//	SLPrint(sl);//1 2 3 
//	SLPopBack(&sl);
//	SLPrint(sl);
//	SLPopBack(&sl);
//	SLPrint(sl);
//	SLPopBack(&sl);
//	SLPrint(sl);
//	SLPopFront(&sl);
//	SLPrint(sl);
//	//...........
//	SLDestroy(&sl);
//}

//void SLTest02()
//{
//	SL sl;
//	SLInit(&sl);
//	SLPushBack(&sl, 1);
//	SLPushBack(&sl, 2);
//	SLPushBack(&sl, 3);
//	SLPushBack(&sl, 4);
//	SLPrint(sl);//1 2 3 4
//	//测试指定位置之前插入数据
//	//SLInsert(&sl, 1, 99);
//	//SLInsert(&sl, sl.size, 88);
//
//	//测试删除指定位置的数据
//	//SLErase(&sl, 1);
//	//SLPrint(sl);//1 3  4
//
//	//测试顺序表的查找
//	int find = SLFind(&sl, 40);
//	if (find < 0)
//	{
//		printf("没有找到!\n");
//	}
//	else {
//		printf("找到了!下标为%d\n",find);
//	}
//	SLDestroy(&sl);
//}

通讯录的测试方法
//void ContactTest01()
//{
//	Contact con;//创建的通讯录对象  实际上就是 顺序表对象,等价于SL sl
//	ContactInit(&con);
//	ContactAdd(&con);
//	ContactAdd(&con);
//	ContactShow(&con);
//
//	//ContactDel(&con);
//	ContactModify(&con);
//	ContactShow(&con);
//	ContactFind(&con);
//
//	ContactDesTroy(&con);
//}
//int main()
//{
//	//SLTest01();
//	//SLTest02();
//	ContactTest01();
//	return 0;
//}


void menu()
{
	printf("******************通讯录******************\n");
	printf("*******1.增加联系人   2.删除联系人********\n");
	printf("*******3.修改联系人   4.查找联系人********\n");
	printf("*******5.展示联系人   0.   退出  *********\n");
	printf("******************************************\n");
}

int main()
{
	int op = -1;
	Contact con;
	ContactInit(&con);

	do {
		menu();
		printf("请选择您的操作:\n");
		scanf("%d", &op);

		//要根据对应的op执行不同的操作
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("退出通讯录....\n");
			break;
		default:
			printf("输入错误,请重新选择您的操作!\n");
			break;
		}
	} while (op != 0);

	ContactDesTroy(&con);
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是 GitHub Wiki 以及如何使用它?

GitHub Wiki 是你项目文档的一个很好的地方。你可以使用 wiki 来创建、管理和托管你的存储库的文档&#xff0c;以便其他人可以使用并为你的项目做出贡献。 GitHub Wiki 很容易开始使用&#xff0c;无需安装任何其他软件。最好的部分是 wiki 与你的 GitHub 存储库集成在一起。…

《九》Qt各种对话框之QColorDialog

前言 QColorDialog类继承于QDialog&#xff0c;是一个设计用来选择颜色的对话框部件。 QColorDialog 在介绍 QColorDialog 之前&#xff0c;我们先简单介绍一下 QColor 类。QColor 类用于表示颜色&#xff0c;支持 RGB&#xff08;红绿蓝&#xff09;三原色表示&#xff0c;也…

【C++】日期计算机

个人主页&#xff1a;救赎小恶魔 欢迎大家来到小恶魔频道 好久不见&#xff0c;甚是想念 今天我们要讲述的是一个日期类计算机的代码实现 引言&#xff1a; 我们日常生活中可能会有一个烦恼。 今天几月几号&#xff1f;过n天后又是几月几号&#xff1f;某年某月某天和x年…

PE文件的导入表,动态链接库中的函数应该如何导入

导入地址表IAT IAT保存的内容与windos操作系统的核心进程、内存、DLL结构有关。IAT是一种表格&#xff0c;用来记录程序正在使用哪些库中的哪些函数。 动态链接库(DLL) 常见的kernel.dll就是一个非常重要的动态链接库&#xff0c;其中包含了运行程序时需要使用到的函数&…

文件操作(1)

为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化的…

再谈C语言——理解指针(四)

assert断⾔ assert.h 头⽂件定义了宏 assert() &#xff0c;⽤于在运⾏时确保程序符合指定条件&#xff0c;如果不符合&#xff0c;就报错终⽌运⾏。这个宏常常被称为“断⾔”。 assert(p ! NULL); 上⾯代码在程序运⾏到这⼀⾏语句时&#xff0c;验证变量 p 是否等于 NULL 。…

JavaScript 数学对象 Math

Math对象其实就是数学对象&#xff0c;它给我们提供了各种各样的数学功能。 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>首页</title> </head><body><script type"text/javascript"&g…

linux的“>”和“>>”

在Linux中&#xff0c;>和>>都是用于文件重定向的操作符&#xff0c;它们用于将命令的输出发送到文件中。 > 用于创建一个新文件或覆盖现有文件的内容。当你执行一个如 command > file.txt 的命令时&#xff0c;如果 file.txt 文件存在&#xff0c;它的内容将被…

【uniapp】引入uni-ui组件库

&#xff08;1&#xff09;新建项目的时候选择 uni-ui项目 &#xff08;2&#xff09;已经创建好的项目去官网单独安装 跳转单独安装组件 https://uniapp.dcloud.net.cn/component/uniui/quickstart.html#%E9%80%9A%E8%BF%87-uni-modules-%E5%8D%95%E7%8B%AC%E5%AE%89%E8%A3%8…

YOLOv9训练损失、精度、mAP绘图功能 | 支持多结果对比,多结果绘在一个图片(消融实验、科研必备)

一、本文介绍 本文给大家带来的是YOLOv9系列的绘图功能&#xff0c;我将向大家介绍YOLO系列的绘图功能。我们在进行实验时&#xff0c;经常需要比较多个结果&#xff0c;针对这一问题&#xff0c;我写了点代码来解决这个问题&#xff0c;它可以根据训练结果绘制损失(loss)和mA…

VBA技术资料MF144:将PDF首页作为对象插入工作表

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

【C++】如何用C++写一个日期计算器

目录 前言 代码的布局 设计数据 方法声明 方法的实现 获取某年某月的天数 *全缺省的构造函数 * 拷贝构造函数 *赋值运算符重载 *析构函数 日期天数 日期天数 日期-天数 日期-天数 前置 后置 后置-- 前置-- 实现比较大小运算符重载思路 >运算符重载 运算…

盲人餐厅点餐:科技之光照亮餐桌上的美食之旅

在现代社会&#xff0c;餐厅不仅是满足口腹之欲的场所&#xff0c;更是一个社交、放松的重要空间。然而&#xff0c;对于视障人士而言&#xff0c;盲人餐厅点餐这一日常行为&#xff0c;却往往伴随着诸多不便与挑战。幸运的是&#xff0c;科技的革新正为这一群体带来前所未有的…

递归神经网络(RNN)在AI去衣技术中的深度应用

在人工智能&#xff08;AI&#xff09;技术飞速发展的今天&#xff0c;图像处理和计算机视觉领域不断取得新的突破。其中&#xff0c;AI去衣技术作为一个具有挑战性的研究方向&#xff0c;引起了广大研究者和公众的关注。递归神经网络&#xff08;RNN&#xff09;作为深度学习的…

【linux】编译器使用

目录 1. gcc &#xff0c;g 编译器使用 a. 有关gcc的指令&#xff08;g同理&#xff09; 2. .o 文件和库的链接方式 a. 链接方式 b. 动态库 和 静态库 优缺点对比 c. debug 版本 和 release 版本 1. gcc &#xff0c;g 编译器使用 a. 有关gcc的指令&#xff08;g同理&…

【第19章】spring-i8n

文章目录 前言一、准备二、Java国际化1.测试类2.测试结果 三、Spring国际化1.配置文件2.测试类3.测试结果4.占位符4.1 准备4.2 测试类4.3 测试结果 总结 前言 在Spring中实现国际化Internationalization&#xff08;i18n&#xff09;其实就是完成语言的切换&#xff0c;类似于…

4.SpringCloud基础项目搭建利用RestTemplate实现远程调用

简单的微服务架构 父pom.xml <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apa…

短信视频提取批量工具,免COOKIE,博主视频下载抓取,爬虫

痛点&#xff1a;关于看了好多市面的软件&#xff0c;必须要先登录自己的Dy号才能 然后找到自己的COOKIE 放入软件才可以继续搜索&#xff0c;并且无法避免长时间使用 会导致无法正常显示页面的问题。 有没有一种方法 直接可以使用软件&#xff0c;不用设置的COOKIE的方法呢 …

Linux驱动开发:掌握SPI通信机制

目录标题 1、SPI简介2、SPI通信机制3、Linux内核中的SPI支持4、SPI核心API5、SPI控制器驱动6、SPI设备驱动 7、编写SPI设备驱动8、调试SPI驱动 在Linux驱动开发中&#xff0c;串行外设接口(SPI)是一种常见的高速全双工通信协议&#xff0c;用于连接处理器和各种外设。本文将深入…

会声会影滤镜怎么用 会声会影滤镜效果怎么调 会声会影视频制作教程

在进行视频剪辑时&#xff0c;合理地运用滤镜效果可以提升视频的观赏性&#xff0c;使你的作品更加出彩。这篇文章便一起来学习会声会影滤镜怎么用&#xff0c;会声会影滤镜效果怎么调。 一、会声会影滤镜怎么用 使用会声会影的滤镜效果非常简单&#xff0c;以下是具体的操作…
最新文章