【MFC实践】基于MFC向导C++制作计算器(附文件)

news2024/12/26 15:12:35

  • 一、写在前面
    • 1.1 什么是MFC向导?
    • 1.2 使用MFC向导制作计算器
    • 1.3安装visual studio 2022和MFC插件
  • 二、设计计算器界面
    • 1.1 新创建MFC项目
    • 1.2 设计计算器界面
    • 1.3 添加相关变量
    • 1.4 算法的一些问题及解决方式
    • 1.5 计算功能的实现
    • 1.6 其它功能的实现
      • 1.6.1 DEL功能
      • 1.6.2 C置零功能
      • 1.6.3 Ce清除一段字符
      • 1.6.4 %百分号功能
      • 1.6.5 倒数功能
      • 1.6.6 平方功能
      • 1.6.7 开根号功能
      • 1.6.8 说明功能

一、写在前面

1.1 什么是MFC向导?

MFC(Microsoft Foundation Classes)向导是一套用于简化Windows应用程序开发的工具集。 它建立在Microsoft Foundation Classes(MFC)之上,为开发人员提供了一种更直观、高效的方式来构建图形用户界面(GUI)应用程序。MFC向导通过提供可视化设计工具、代码生成器等功能,使得开发者能够更专注于业务逻辑的实现,而不必过多关注繁琐的界面布局和控件创建。

1.2 使用MFC向导制作计算器

计算器项目相对简单,但涉及到了UI设计、事件处理、C++编程等方面,是一个适合初学者的实践项目。通过使用MFC向导,能够快速创建一个具有良好界面和基本功能的计算器,同时学会如何使用可视化工具来简化开发过程。以下是计算器项目示例图:
在这里插入图片描述

1.3安装visual studio 2022和MFC插件

对于未安装visual studio,下载地址:visual studio 2022 下载传送门,正常安装后,点击继续但无需代码的方式打开,在工具栏点击工具->获取工具和功能->已安装->修改
在这里插入图片描述
点击单个组件,找到图示两项并勾选,最后点击窗口右下方的修改即可
在这里插入图片描述

二、设计计算器界面

1.1 新创建MFC项目

首先基于MFC向导生成对话框文档(也可以选择单文件文档,但需要另建并加载对话框资源,看个人需求),对于初学者,建议可以取消勾选高级功能中的“公共控件清单、支持重启管理器”(不用增加额外非必要的代码),对于“文档模板属性”和“用户界面功能”默认即可。默认生成主要有主类的头文件MFCApplication1对话框资源文件IDD_MFCAPPLICATION1_DIALOG。文件名可根据需要修改,这里只是默认文件名为例子。
在这里插入图片描述

1.2 设计计算器界面

工具栏选择Button、Edit Control分别添加按钮、文本框等控件,鼠标选中拖动进行布局,以下是一些简单的布局技巧

布局方式描述
Shift多选对齐使用MFC的设计器,你可以通过按住Shift键选择多个控件,然后在属性窗口中设置它们的位置和大小,以实现对齐。
工具栏描述
MFC设计器Visual Studio自带的MFC设计器是一个强大的工具,可用于直观地设计和布局界面。
控件对齐工具MFC设计器中的对齐工具可用于快速将选定的控件水平或垂直对齐,确保它们在界面上整齐排列。
网格布局在MFC中,你可以使用网格布局管理器来自动调整控件的大小和位置,使它们在窗口中均匀分布。
代码编辑器通过在代码中手动编辑控件的位置和大小,你可以更精细地控制布局。
调整控件层次结构通过在层次结构视图中调整控件的嵌套关系,可以影响它们在窗口中的布局。

布局方式就不在这赘述,懂得如何画就行,使用工具栏和工具箱完成布局和控件的添加,示例样式如下
在这里插入图片描述

1.3 添加相关变量

都知道,计算器需要一个变量来存储用户输入的表达式,输入的对象是文本编辑器,故此,应需要为文本编辑器添加一个变量,且该变量的类型应是CString(字符串类,MFC对C++标准库中的字符串类的一个扩展),但变量在类文件声明,所以在这之前应该为对话框资源添加对应的类文件MFCApplication1Dlg(类名可修改):右键对话框->添加类
在这里插入图片描述

创建类之后,点击工具栏的项目->类向导->成员变量,找到编辑框的那项(本例中ID默认为IDC_Edit2),选中该项右键->添加变量,变量名和类型如下图
在这里插入图片描述
变量添加完成后,就可以在对话框类文件MFCApplication1Dlg看到变量m_data
在这里插入图片描述

1.4 算法的一些问题及解决方式

接下来就是针对每个按钮写入相应消息事件,双击每个按钮跳转对话框实现文件MFCApplication1Dlg.cpp并生成对应函数(函数名与控件ID同名)。m_data变量用于存储用户输入的表达式,对于0-9和运算符按钮控件,事件分别对应不同的值输入,并且m_data是CString类型,那么可以使用下标法在字符串表达式的末尾增字符,简单示例如下:

m_data+='0'
m_data+='1'
m_data+='2'
m_data+='3'
m_data+='4'
m_data+='5'
m_data+='6'
m_data+='7'
m_data+='8'
m_data+='9'
m_data+='.'
m_data+='+'
m_data+='-'
m_data+='*'
m_data+='/'

每次在m_data末尾增设字符,首先需要更新编辑框的内容到变量m_data

UpdateData();

然而有以下几个问题以及应对解决代码(这里新建数组a作中间变量,i作下标),带着这些问题来设计算法,以便理解。

  • 问题1:计算器默认m_data值为0,那么在0之后的第一个字符若为数字字符,则应该覆盖0,比如控件按钮1的代码示例
UpdateData();
if (m_data == "0")
{
	i--;//下标向前指向0的位置
	a[i] = "1";
	m_data = a[i];//覆盖0
}
else
{
	a[i] = "1";
	m_data += a[i];//直接追加
}
i++
  • 问题2:若表达式最后一个字符是运算符的一种(+、- 、*、/),则一个字符不能是运算符。对于该问题可以设置一个控制变量f,置初值为1,表示可以追加运算符。
//当点击运算符按钮,置f为0。
f=0;
//当点击除运算符以外的按钮,则重新置f为1。
f=1;
  • 问题3:对于运算符’.'也有同样的问题即不能连用,这里设置控制变量pd来互斥。
//当点击小数点按钮,置pd为1。
f=1;
//当点击除小数点按钮以外的按钮,则重新置f为0。
f=0;
  • 问题4:小数点按钮和运算符按钮事件也应该相互制约
//当表达式最后一个字符是运算符,若要添加小数点则应先追加0
if (a[i - 1] == "+" || a[i - 1] == "-" || a[i - 1] == "*" || a[i - 1] == "/")
{

	a[i] = "0";
	m_data += a[i];//先追加0
	i++;
	a[i] = ".";
	m_data += a[i];//再追加小数点
}
else
{
	a[i] = ".";
	m_data += a[i];//直接追加小数点
}
i++;
f = 0;
//当表达式最后一个字符是小数点,若要添加运算符则应覆盖小数点
//比如加法,其它运算符按钮响应事件也如此
if (a[i - 1] == ".")
{
	i--;
	a[i] = "+";
	// 获取最后一个字符的索引
	int lastIndex = m_data.GetLength() - 1;
	// 替换最后一个字符为 '+'
	m_data.SetAt(lastIndex, _T('+'));//覆盖
}
else
{
	a[i] = "+";
	m_data += a[i];//直接追加
}
f = 1;
i++;

1.5 计算功能的实现

变量m_data是CString类型,用于存储计算表达式,包含加减乘除运算符和小数点符号,对于运算优先级的处理方式:首先定义三个变量用于下标取值p、left、right。外循环p获取m_data字符串的乘除运算符,内循环left和right分别指向p所指向运算符左右两侧的运算符,用m_data.Mid()函数截取p所指运算符两侧的数字,根据判断p指向的运算符进行乘法或者除法运算,最后使用m_data.Delete()和 m_data.Insert()函数替换运算结果。

void CMFCApplication1Dlg::OnBnClickedEqual()
{
	int length = m_data.GetLength();
	int left = 0, right = 0, p = 0;
	//先乘除
	for (p = 0; p < length; p++)
	{
		if (m_data.GetAt(p) != '+' && m_data.GetAt(p) != '-' && m_data.GetAt(p) != '.' && m_data.GetAt(p) < '0' || m_data.GetAt(p) > '9')
		{
			left = p - 1;
			right = p + 1;
			while (left >= 0)
			{
				if (m_data.GetAt(left) == '0' || m_data.GetAt(left) == '1' || m_data.GetAt(left) == '2' || m_data.GetAt(left) == '3' || m_data.GetAt(left) == '4' || m_data.GetAt(left) == '5' || m_data.GetAt(left) == '6' || m_data.GetAt(left) == '7' || m_data.GetAt(left) == '8' || m_data.GetAt(left) == '9' || m_data.GetAt(left) == '.')
				{
					left--;
				}
				else break;
			}
			while (right < length)
			{
				if (m_data.GetAt(right) == '0' || m_data.GetAt(right) == '1' || m_data.GetAt(right) == '2' || m_data.GetAt(right) == '3' || m_data.GetAt(right) == '4' || m_data.GetAt(right) == '5' || m_data.GetAt(right) == '6' || m_data.GetAt(right) == '7' || m_data.GetAt(right) == '8' || m_data.GetAt(right) == '9' || m_data.GetAt(right) == '.')
				{
					right++;
				}
				else break;
			}
		}
		else continue;
		CString a = m_data.Mid(left + 1, p - left - 1);
		CString b = m_data.Mid(p + 1, right - p - 1);
		double temp = 0.0;
		if (m_data.GetAt(p) == '*')
		{
			temp = _ttof(a) * _ttof(b);//类型转换
			CString t;
			t.Format(_T("%0.4f"), temp);
			m_data.Delete(left + 1, right - left - 1);
			m_data.Insert(left + 1, t);
			UpdateData(false);
			UpdateData();
			length = m_data.GetLength();
			p = 0;
		}
		if (m_data.GetAt(p) == '/')
		{
			temp = _ttof(a) / _ttof(b);//类型转换
			CString t;
			t.Format(_T("%0.4f"), temp);
			m_data.Delete(left + 1, right - left - 1);
			m_data.Insert(left + 1, t);
			UpdateData(false);
			UpdateData();
			length = m_data.GetLength();
			p = 0;
		}

		AfxMessageBox(a + "和" + b);

	}
	//后加减
	for (p = 0; p < length; p++)
	{
		if (m_data.GetAt(p) != '*' && m_data.GetAt(p) != '/' && m_data.GetAt(p) != '.' && m_data.GetAt(p) < '0' || m_data.GetAt(p) > '9')
		{
			left = p - 1;
			right = p + 1;
			while (left >= 0)
			{
				if (m_data.GetAt(left) == '0' || m_data.GetAt(left) == '1' || m_data.GetAt(left) == '2' || m_data.GetAt(left) == '3' || m_data.GetAt(left) == '4' || m_data.GetAt(left) == '5' || m_data.GetAt(left) == '6' || m_data.GetAt(left) == '7' || m_data.GetAt(left) == '8' || m_data.GetAt(left) == '9' || m_data.GetAt(left) == '.')
				{
					left--;
				}
				else break;
			}
			while (right < length)
			{
				if (m_data.GetAt(right) == '0' || m_data.GetAt(right) == '1' || m_data.GetAt(right) == '2' || m_data.GetAt(right) == '3' || m_data.GetAt(right) == '4' || m_data.GetAt(right) == '5' || m_data.GetAt(right) == '6' || m_data.GetAt(right) == '7' || m_data.GetAt(right) == '8' || m_data.GetAt(right) == '9' || m_data.GetAt(right) == '.')
				{
					right++;
				}
				else break;
			}
		}
		else continue;
		CString a = m_data.Mid(left + 1, p - left - 1);
		CString b = m_data.Mid(p + 1, right - p - 1);
		double temp = 0;
		if (m_data.GetAt(p) == '+')
		{
			temp = _ttof(a) + _ttof(b);//类型转换
			CString t;
			t.Format(_T("%0.4f"), temp);
			m_data.Delete(left + 1, right - left - 1);
			m_data.Insert(left + 1, t);
			UpdateData(false);
			UpdateData();
			length = m_data.GetLength();
			p = 0;
		}
		if (m_data.GetAt(p) == '-')
		{
			temp = _ttof(a) - _ttof(b);//类型转换
			CString t;
			t.Format(_T("%0.4f"), temp);
			m_data.Delete(left + 1, right - left - 1);
			m_data.Insert(left + 1, t);
			UpdateData(false);
			UpdateData();
			length = m_data.GetLength();
			p = 0;
		}

		AfxMessageBox(a + "和" + b);
	}
}

1.6 其它功能的实现

1.6.1 DEL功能

作用删除表达式的上一个字符

void CMFCApplication1Dlg::OnBnClickedDel()
{
	UpdateData();  // 更新 m_data 长度
	// 获取当前的字符串长度
	int length = m_data.GetLength();

	// 检查字符串是否为空
	if (length > 0)
	{
		// 如果字符串长度大于1,删除最后一个字符
		if (length > 1)
		{
			a[i] = '\0';
			m_data.Delete(length - 1, 1);
		}
		else
		{
			// 如果字符串只剩最后一个字符,将m_data设置为"0"
			a[i] = '0';
			m_data = _T("0");
		}

		// 更新界面上的文本框等显示
		UpdateData(FALSE);
	}

	f = 0;
	pd = 0;

	UpdateData(false);
}

1.6.2 C置零功能

void CMFCApplication1Dlg::OnBnClickedC()
{
	m_data = "0";//置零
	UpdateData(false);
}

1.6.3 Ce清除一段字符

void CMFCApplication1Dlg::OnBnClickedCe()
{
	// TODO: 在此添加控件通知处理程序代码
	int p = m_data.GetLength()-1;
	while (p>=0)
	{
		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
		{
			break;
		}
		p--;
	}
	m_data.Delete(p+1, m_data.GetLength() - 1-p);
	UpdateData(false);
}

1.6.4 %百分号功能

void CMFCApplication1Dlg::OnBnClickedFeature6()
{
	int p = m_data.GetLength() - 1;
	while (p >= 0)
	{
		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
		{
			break;
		}
		p--;
	}
	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
	double b = _ttof(a) * 0.01;
	a.Format(_T("%f"), b);
	m_data.Insert(p + 1, a);
	UpdateData(false);
}

1.6.5 倒数功能

void CMFCApplication1Dlg::OnBnClickedFeature3()
{
	int p = m_data.GetLength() - 1;
	while (p >= 0)
	{
		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
		{
			break;
		}
		p--;
	}
	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
	double b =1/ _ttof(a) ;
	a.Format(_T("%f"), b);
	m_data.Insert(p + 1, a);
	UpdateData(false);
}

1.6.6 平方功能

void CMFCApplication1Dlg::OnBnClickedFeature4()
{
	// TODO: 在此添加控件通知处理程序代码
	int p = m_data.GetLength() - 1;
	while (p >= 0)
	{
		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
		{
			break;
		}
		p--;
	}
	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
	double b = _ttof(a) * _ttof(a);
	a.Format(_T("%f"), b);
	m_data.Insert(p + 1, a);
	UpdateData(false);
}

1.6.7 开根号功能

void CMFCApplication1Dlg::OnBnClickedFeature5()
{
	// TODO: 在此添加控件通知处理程序代码
	int p = m_data.GetLength() - 1;
	while (p >= 0)
	{
		if (m_data.GetAt(p) == '+' || m_data.GetAt(p) == '-' || m_data.GetAt(p) == '/' || m_data.GetAt(p) == '*')
		{
			break;
		}
		p--;
	}
	CString a = m_data.Mid(p + 1, m_data.GetLength() - 1 - p);
	m_data.Delete(p + 1, m_data.GetLength() - 1 - p);
	double b = sqrt(_ttof(a)) ;
	a.Format(_T("%f"), b);
	m_data.Insert(p + 1, a);
	UpdateData(false);
}

1.6.8 说明功能

void CMFCApplication1Dlg::OnBnClickedFeature1()
{
	MessageBox("1. 百分比计算(%)\n输入一个数字,然后使用百分号(% )进行百分比计算。计算器将返回输入数的百分之一。\n2. 删除字符或运算符(del)\n通过按下“del”按钮,可以删除最后一个输入的字符或运算符。这有助于纠正输入错误。\n3. 清零(C)\n按下“C”按钮将清空当前输入的所有内容,使计算器重置为零状态。\n4. 清除最后一个数(CE)\n使用“CE”按钮可以清除输入的最后一个数字,保留其他输入和运算符。");
}

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

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

相关文章

生活自来水厂污水处理设备需要哪些

生活自来水厂是确保我们日常用水质量安全的重要设施。在自来水的生产过程中&#xff0c;污水处理设备是不可或缺的环节。那么&#xff0c;生活自来水厂的污水处理设备都有哪些呢&#xff1f;本文将为您详细介绍。 首先&#xff0c;生活自来水厂的污水处理设备主要包括预处理设备…

小白进公司快速熟悉环境和代码的方法

1.企业开发模式 企业开发模式里&#xff0c;我们的项目模块可能非常多此时我们是不能将所有模块都拉取到本地的&#xff0c;主要原因如下&#xff1a; 我们很可能并没有全部工程代码的权限 微服务集群部署非常复杂&#xff0c;本地部署成本太高 微服务模块众多&#xff0c;本…

2024,AI Agent的密集爆发之年

最近这几天&#xff0c;相信已经有很多朋友看到了关于GPT Store、Vision Pro、Rabbit R1、AI pin、英伟达ACE&#xff08;Avatar Cloud Engine&#xff09;、钉钉个人助理、荣耀MagicOS 8.0等各类和AI技术深度结合的AI Agent或者承载AI Agent的平台。有些是和个人应用相关&…

Linux 上 Nginx 上传文件报错:413 request entity too large

目录 一、前言二、解决思路三、解决方案四、结尾 一、前言 最近在自己折腾 Blog&#xff0c;把项目部署到服务器上后&#xff0c;发现上传文件的接口居然报错了&#xff1a;413 request entity too large&#xff0c;一看这错误&#xff0c;发现是 nginx 配置的原因&#xff0c…

【Spring 篇】基于XML的Spring事务控制详解

Spring框架作为Java开发中的瑞士军刀&#xff0c;提供了许多方便而强大的功能&#xff0c;其中之一就是事务管理。事务是数据库操作中的关键概念&#xff0c;它确保一系列操作要么全部成功&#xff0c;要么全部失败。今天我们将深入探讨基于XML配置的Spring事务控制&#xff0c…

网安入门13-文件上传(htaccess,其他绕过)

空格绕过&#xff0c;点号绕过 Pass-07 直接上传肯定是失败的 把文件名1.php改成1.php.或1.php_(下划线为空格)&#xff0c;这种命名方式在windows系统里是不被允许的&#xff0c;所以需要在burp之类里进行修改&#xff0c;然后绕过验证后&#xff0c;会被windows系统自动去掉…

Graphpad Prism10.1.2(324) 安装教程 (含Win/Mac版)

GraphPad Prism GraphPad Prism是一款非常专业强大的科研医学生物数据处理绘图软件&#xff0c;它可以将科学图形、综合曲线拟合&#xff08;非线性回归&#xff09;、可理解的统计数据、数据组织结合在一起&#xff0c;除了最基本的数据统计分析外&#xff0c;还能自动生成统…

服务器部署项目,访问验证码出现Handler dispatch failed....InvocationTargeException

场景&#xff1a; 部署ruoyi-vue的jar。访问验证码接口时&#xff0c;出现异常。本地测试没有问题&#xff0c;起初使用的jdk8&#xff0c;怀疑jdk版本问题&#xff0c;但是本地使用11.0.15版本也没问题&#xff0c;后面也就没管&#xff0c;初步排除jdk版本的问题。之前项目也…

C语言程序设计(数据类型)

C 数据类型 在 C 语言中&#xff0c;数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间&#xff0c;以及如何解释存储的位模式。 C 中的类型可分为以下几种&#xff1a; 序号类型与描述1基本数据类型 它们是算术类型&#x…

20240113斐波那切数列

代码 def fibonacci(n):fib_list [0, 1] # 初始的斐波那契数列&#xff0c;包含0和1while len(fib_list) < n:next_number fib_list[-1] fib_list[-2]fib_list.append(next_number)return fib_list[:n]# 示例&#xff1a;计算前10个斐波那契数 n 10 result fibonacci…

C++学习笔记——多态与静态联编和动态联编

目录 一、多态 二、静态联编&#xff08;Static Binding&#xff09;和动态联编&#xff08;Dynamic Binding&#xff09; 2.1静态联编 2.2动态联编 一、多态 是C中面向对象编程的一个核心概念&#xff0c;它允许派生类对象替代其基类对象&#xff0c;从而实现代码重用和扩…

鸿蒙APP的设备适配

鸿蒙&#xff08;HarmonyOS&#xff09;是华为推出的一种分布式操作系统&#xff0c;用于支持多种设备类型&#xff0c;包括智能手机、平板电脑、智能电视、智能穿戴等。在进行鸿蒙APP的设备适配时&#xff0c;需要注意以下几个方面&#xff0c;希望对大家有所帮助。北京木奇移…

使用AutoDL云计算平台训练并测试Pytorch版本NeRF代码

文章目录 前言一、数据集及代码获取二、租用并设置服务器三、Pycharm远程开发四、训练并测试代码 前言 因为第一次在云服务器上跑代码&#xff0c;所以在这里记录一下。 一、数据集及代码获取 nerf-pytorch项目是 NeRF 的忠实 PyTorch 实现&#xff0c;它在运行速度提高 1.3 倍…

使用ArduinoMqttClient库连接阿里云,并实现发送接收数据(ESP8266)

文章目录 引言一、MQTT理论部分二、使用MQTT.fx接入物联网设备三、使用ESP8266连接阿里云四、参考例程 引言 阿里云物联网平台的接入方式有很多种&#xff0c;从阿里云提供的开发文档可以看到&#xff0c;支持的接入协议有MQTT、HTTPS、CoAP、JT/808、GB/32960协议等等&#x…

STL之map

目录 map(常用) map的函数 multimap(几乎不用-时间复杂度不稳定) mutimap的函数 unordered_map(一般不用) unordered_map的函数 代码示例 1.map 2、multimap 3、unordered_map map(常用) map是一种关联容器&#xff0c;用于存储一组键值对(key-value pairs)&#xf…

运用3d技术建立数字化模型---模大狮模型网

随着科技的不断进步和发展&#xff0c;3D技术已经被广泛运用于各个领域。其中&#xff0c;建立数字化模型是3D技术的一个重要应用方向。本文将从3D技术的概念、数字化模型的定义、数字化模型的建立方法、应用领域等方面介绍运用3D技术建立数字化模型的相关知识。 一、3D技术的概…

【论文阅读】Non-blocking Lazy Schema Changes in Multi-Version

Non-blocking Lazy Schema Changes in Multi-Version Database Management Systems 1. Intro 1.1 Motivation 一个是online能够提供不停机的更新的能力&#xff0c;在很多业务系统里面是必要的。第二个是满足高可用&#xff0c;SaaS、PaaS要提供高可用的系统给用户&#xff…

你的编程能力什么时候开始有了质的飞跃?

建议看看计算机科学速成课&#xff0c;一门很全面的计算机原理入门课程&#xff0c;短短10分钟可以把大学老师十几节课讲不清楚的东西讲清楚&#xff01;整个系列一共41个视频&#xff0c;B站上有中文字幕版。 每个视频都是一个特定的主题&#xff0c;例如软件工程、人工智能、…

Goby 漏洞发布|用友 NC registerServlet 反序列化远程代码执行漏洞

漏洞名称&#xff1a;用友 NC registerServlet 反序列化远程代码执行漏洞 English Name&#xff1a;Yonyou NC registerServlet Deserialize Remote Code Execute Vulnerability CVSS core: 9.8 影响资产数&#xff1a; 21320 漏洞描述&#xff1a; 用友 NC Cloud 是一种商…

最新靠谱可用的-Mac-环境下-FFmpeg-环境搭建

最近在尝试搭建 FFmpeg 开发环境时遇到一个蛋疼的事&#xff0c;Google 了 N 篇文章竟然没有一篇是可以跑起来的&#xff01; 少部分教程是给出了自我矛盾的配置&#xff08;是的&#xff0c;按照贴出来的代码和配置&#xff0c;他自己都跑不起来&#xff09;&#xff0c;大部…