利用可变参数模板,可打印任意参数和参数值。(C++很好的调式函数)

很酷的应用:

(1) 如何获取可变参数名

代码例子:

#define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))

template<typename... Args>
void test_t(const char* names, Args... args)
{
	std::cout << names << "\n";
}

__VA_ARGS__ 是 C/C++ 宏定义中的一个特殊标识符,用于表示 可变参数宏(Variadic Macros)中的参数包。它允许宏接受任意数量的参数。

详细说明

  1. 可变参数宏

    • 在宏定义中,使用 ... 表示可变参数。

    • 使用 __VA_ARGS__ 来引用这些可变参数。

  2. #__VA_ARGS__

    • # 是字符串化运算符,将宏参数转换为字符串。

    • #__VA_ARGS__ 将可变参数包中的所有参数转换为一个字符串。

#define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))

这条语句定义了一个宏 _test,它接受可变数量的参数(通过 ... 表示),并将这些参数传递给一个函数 test_t

1. 宏定义的基本结构

  • _test 是宏的名称。

  • (...) 表示宏可以接受任意数量的参数。

  • test_t(#__VA_ARGS__, __VA_ARGS__) 是宏的展开内容。

2. __VA_ARGS__ 的作用

  • __VA_ARGS__ 是 C/C++ 中的特殊标识符,用于表示可变参数宏中的参数包。

  • 它允许宏接受任意数量的参数。

3. #__VA_ARGS__ 的作用

  • # 是字符串化运算符,将宏参数转换为字符串。

  • #__VA_ARGS__ 将可变参数包中的所有参数转换为一个字符串。

4. 宏的展开逻辑

假设调用 _test(a, b, c),宏会展开为:

(test_t("a, b, c", a, b, c))

  • #__VA_ARGS__ 将 a, b, c 转换为字符串 "a, b, c"

  • __VA_ARGS__ 展开为 a, b, c

5. test_t 函数的作用

test_t 是一个函数,它至少接受两个参数:

  1. 第一个参数是字符串 "a, b, c",表示变量名。

  2. 后续参数是变量值 a, b, c

test_t 的具体实现需要根据需求编写。例如,它可以用于打印变量名和变量值,或者进行其他处理。

下面看一下例子:

#define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))

template<typename... Args>
void test_t(const char* names, Args... args)
{
	std::cout << names << "\n";
}


int main(int argc, char* argv[])
{
	QApplication a(argc, argv);  //注意,这里是QApplication	 
	ga.setStdLocaleForUTF8();
	 
	 
	int i = 5;
	double c = 3.14;

	std::string s = "abcd";

	_test(i, c,s);
	 


	return a.exec();
}

运行结果:

请注意变量 i 和 c 中间是有一个空格的,这跟你的书写格式有关:

例如:

(2)如何展开参数包。

 
#define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))

template<typename... Args>
void test_t(const char* names, Args... args)
{
	auto arrNames = _string(names).split(','); //拆分变量列表

	for (auto s : arrNames) {
		std::wcout << _t("s=") << s << _t("\n");
	}
}


int main(int argc, char* argv[])
{
	QApplication a(argc, argv);  //注意,这里是QApplication	 
	ga.setStdLocaleForUTF8();	 
	 
	int i = 5;
	double c = 3.14;
	std::string s = "abcd";
	 
	_test(i,c,s);
	 
	return a.exec();
}

输出结果:

(3)如何获取变量的值,这里只介绍C++17及其以上的写法。

#define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))

template<typename... Args>
void test_t(const char* names, Args... args)
{
	auto arrNames = _string(names).split(','); //拆分变量列表
	int i = 0;
	// 使用折叠表达式展开参数包,只支持C++17及其以上
	//-------------------------------------------------------------------------
	(
		    (

			std::wcout << arrNames[i],
			std::cout << "=",
			std::cout << args << "\n", 
			++i //下一个参数

		    ),

	...);

}


int main(int argc, char* argv[])
{
	QApplication a(argc, argv);  //注意,这里是QApplication	 
	ga.setStdLocaleForUTF8();	 
	 
	int i = 5;
	double c = 3.14;
	std::string s = "abcd";
	 
	_test(i,c,s);
	 
	return a.exec();
}

运行结果:

(4)应用例子:

//在控制台打印出n个变量名和变量值
#define _pns(...) (_cout << _generateString(#__VA_ARGS__, __VA_ARGS__))
//在窗口中显示n个变量名和变量值
#define _pnw(...) (qt.showText(_generateString(#__VA_ARGS__, __VA_ARGS__)))
int main(int argc, char* argv[])
{
	QApplication a(argc, argv);  //注意,这里是QApplication	 
	ga.setStdLocaleForUTF8();	 
	 
	QWidget w;
	w.resize(500, 800);

	int i = 5;
	double d = 3.14;
	std::string s = "abcd";
	 
	_Color  c;

	_Font f;

	_pns(i, d, s, w.geometry(), c, f);
	_pnw(i, d, s, w.geometry(), c, f);
	 
	return a.exec();
}

结果:

下面是代码:



#if _c17_
/*-------------------------------------------- - 源程序(由DeepSeek提供)
// 辅助函数,生成变量名和值的字符串
template<typename... Args>
std::string _generateString(const char* names, Args... args) {
	std::string result;

	std::ostringstream oss;
	std::istringstream iss(names);
	std::string name;
	((oss << (iss >> name ? name : "") << " = " << args << "<br>"), ...);
	return oss.str();
}
*/

/// <summary>
/// 参数名 = 参数值
/// </summary>
/// <typeparam name="...Args"></typeparam>
/// <param name="names"></param>
/// <param name="...args"></param>
/// <returns></returns>
/// 创建时间:2025-03-07    最后一次修改时间:2025-03-07 (已测试)
template<typename... Args>
_string _generateString(const char* names, Args... args) {
	_string result;

	using namespace lf;

	auto arrNames = _string(names).split(','); //拆分变量列表

	int i = 0;
	const char* namePtr = names;
 

	//std::cout << "names=" << names << "\n";

	// 使用折叠表达式展开参数包
	//((result += std::string(namePtr) + " = " + std::to_string(args) + "<br>", namePtr = nullptr), ...);

	// 使用折叠表达式展开参数包,只支持C++17及其以上
	//-------------------------------------------------------------------------
	(
		(
			// names = i, d, f, w.geometry(),用逗号和一个空格分隔,是固定的。
			//result.append(_string(typeid(args).name())),
			//result.append(_t("<br>")),
			//result.append(_t("----------")),
			//result.append(_t("<br>")),
			//name = _string(namePtr).left(_t(", ")),

			result.add(arrNames[i].trim()),			
			result.append(_t("=")),
			result.append(_tostr(args)),
			//result.append(_t("<br>")),  //如果是纯文本 <br> 替代成  \n
			result.append(_t("\n")),
			++i //下一个参数

			),

		...);
	//-------------------------------------------------------------------------

	return result;
}
#else
/*---------------------------------------------源程序(由DeepSeek提供)
// 递归终止条件
std::string _generateStringHelper(const char* namePtr) {
	return "";
}

// 递归展开参数包
template<typename T, typename... Args>
std::string _generateStringHelper(const char* namePtr, T arg, Args... args) {
	std::string result;

	// 提取变量名
	std::string name;
	while (*namePtr && *namePtr != ',') {
		name += *namePtr++;
	}
	if (*namePtr == ',') namePtr++; // 跳过逗号
	while (*namePtr == ' ') namePtr++; // 跳过空格

	// 拼接变量名和值
	result += name + " = " + std::to_string(arg) + "<br>";

	// 递归处理剩余参数
	result += _generateStringHelper(namePtr, args...);

	return result;
}

template<typename... Args>
std::string _generateString(const char* names, Args... args) {
	return _generateStringHelper(names, args...);
}
*/

// 递归终止条件
_string _generateStringHelper(const char* namePtr) {
	return _t("");
}

// 递归展开参数包
template<typename T, typename... Args>
_string  _generateStringHelper(const char* namePtr, T arg, Args... args) {
	_string result;

	_pn(namePtr);

	// 提取变量名
	_string name;
	while (*namePtr && *namePtr != ',') {
		name.append(*namePtr++);
	}
	if (*namePtr == ',') namePtr++; // 跳过逗号
	while (*namePtr == ' ') namePtr++; // 跳过空格

	// 拼接变量名和值
	result += name + _t(" = ") + _tostr(arg) + _t("<br>");

	// 递归处理剩余参数
	result += _generateStringHelper(namePtr, args...);

	return result;
}

template<typename... Args>
_string _generateString(const char* names, Args... args) {
	return _generateStringHelper(names, args...);
}

#endif

这里有个关键函数,_tostr上次已介绍过:

_tostr


/// <summary>
/// 
/// </summary>
/// <param name="pt"></param>
/// <param name="sTypeName"></param>
/// <returns></returns>
/// 创建时间:2025-02-16    最后一次修改时间:2025-02-16
_string _tostr(void* pt, const char* sTypeName);

/// <summary>
/// 
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
/// 创建时间:2025-02-16    最后一次修改时间:2025-02-16
template<class T>
inline _string _tostr(const T& t) {
	return _tostr((void*)(&t), typeid(t).name());
}
_string  _tostr(void* pt, const char* sTypeName)
{
	_StrA  sType = sTypeName;
	_string sResult(_t(""), 100);

	if (sType == typeid(char*).name() || sType == typeid(const char*).name()) {
		char** ppC = ((char**)(pt)); //指向指针的指针
		sResult.add(_string::qt_fromUtf8(*ppC));
	}
	else if (sType == typeid(wchar_t*).name() || sType == typeid(const wchar_t*).name()) {
		wchar_t** ppC = ((wchar_t**)(pt)); //指向指针的指针
		sResult.add(*ppC);
	}
#ifdef _QT_  //---------------------------------------------------------_QT_	 
	else if (sType == typeid(QStringList).name()) {

		QStringList* data = (QStringList*)pt;


		if (data->size() == 0)
			sResult.add(_t("{}"));
		else {
			sResult.add(_t("{"));
			for (int i = 0; i < data->size() - 1; ++i) {
				sResult.add(_t("\""));
				sResult.add(data->at(i).toStdWString());
				sResult.add(_t("\","));
			}
			sResult.add(_t("\""));
			sResult.add(data->last().toStdWString());
			sResult.add(_t("\""));

			sResult.add(_t("}"));
		}
	}
	else if (sType == typeid(QString).name()) {
		sResult.add(_t("\""));
		sResult.add((*((QString*)(pt))).toStdWString());
		sResult.add(_t("\""));
	}
	else if (sType == typeid(QDateTime).name()) {
		return QtDateTimeToString((QDateTime*)pt);
	}
	else if (sType == typeid(QFont).name()) {
		QFont* pf = (QFont*)(pt);
		sResult.add(pf->toString().toStdWString());
	}
	else if (sType == typeid(QByteArray).name()) {
		QByteArray* pb = (QByteArray*)(pt);
		sResult.add(_string::fromOnlyData(pb->data(), pb->size()));
	}
	else if (sType == typeid(QColor).name()) {
		QColor* pc = (QColor*)(pt);
		//sResult.add(_string::fromOnlyData(pb->data(), pb->size()));
		/*
		alpha:透明度。

		red:红色分量。

		green:绿色分量。

		blue:蓝色分量。

		pad:填充字段。
		*/
		_Color c;
		c._a = pc->alpha();
		c._r = pc->red();
		c._g = pc->green();
		c._b = pc->blue();

		sResult.add(c.toString());
	}
	else if (sType == typeid(QSize).name()) {
		QSize* ps = (QSize*)(pt);
		sResult.add(_t("("));
		sResult.add(_Math::intToStrForBaseN(ps->width()));
		sResult.add(_t(","));
		sResult.add(_Math::intToStrForBaseN(ps->height()));
		sResult.add(_t(")"));
	}
	else if (sType == typeid(QRect).name()){
		QRect* pr = (QRect*)(pt);
		sResult.add(_t("("));
		sResult.add(_Math::intToStrA(pr->left()));
		sResult.add(_t(","));
		sResult.add(_Math::intToStrA(pr->top()));
		sResult.add(_t(","));
		sResult.add(_Math::intToStrA(pr->bottom()));
		sResult.add(_t(","));
		sResult.add(_Math::intToStrA(pr->right()));
		sResult.add(_t(")"));
	}
#endif // ---------------------------------------------------------_lf_	 
	else if (sType == typeid(_StrListW).name()) {

		_StrListW* data = (_StrListW*)pt;

		if (data->size() == 0)
			sResult.add(_t("{}"));
		else {
			sResult.add(_t("{"));
			for (int i = 0; i < data->size() - 1; ++i) {
				sResult.add(_t("\""));
				sResult.add(data->at(i).qt_toStdWString());
				sResult.add(_t("\","));
			}

			sResult.add(_t("\""));
			sResult.add(data->last()->data.qt_toStdWString());
			sResult.add(_t("\""));
			sResult.add(_t("}"));
		}
	}
	else if (sType == typeid(_Color).name()) {
		_Color* pc = ((_Color*)(pt));
		sResult.add(pc->toString());
	}
	else if (sType == typeid(_Font).name()) {
		_Font* pf = ((_Font*)(pt));
		sResult.add(pf->toString());
	}
	else if (sType == typeid(_GuiTreeNodeEncryptionType).name()) {
		_GuiTreeNodeEncryptionType* ptnt = ((_GuiTreeNodeEncryptionType*)(pt));
		 if (*ptnt == _GuiTreeNodeEncryptionType::noEncryption) {
			sResult.add(_t("_GuiTreeNodeEncryptionType::noEncryption"));
			}
		else if (*ptnt == _GuiTreeNodeEncryptionType::simpleEncryption) {
			sResult.add(_t("_GuiTreeNodeEncryptionType::simpleEncryption"));
		}
		else if (*ptnt == _GuiTreeNodeEncryptionType::aesEncryption) {
			sResult.add(_t("_GuiTreeNodeEncryptionType::aesEncryption"));
		}
		else if (*ptnt == _GuiTreeNodeEncryptionType::desEncryption) {
			sResult.add(_t("_GuiTreeNodeEncryptionType::desEncryption"));
		}
	}
	else if (sType == typeid(int).name()) {
		int *pNum = ((int*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(float).name()) {
		float* pNum = ((float*)(pt));
		sResult.add(_Math::doubleToStr(*pNum));
	}
	else if (sType == typeid(double).name()) {
		double *pNum = ((double*)(pt));
		sResult.add(_Math::doubleToStr(*pNum));
	}
	else if (sType == typeid(__int64).name()) {
		__int64 *pNum = ((__int64*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_byte).name()) {
		_byte *pNum = ((_byte*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_int8).name()) {
		_int8 *pNum = ((_int8*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_int16).name()) {
		_int16 *pNum = ((_int16*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_int32).name()) {
		_int16 *pNum = ((_int16*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_int64).name()) {
		_int64 *pNum = ((_int64*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_uint8).name()) {
		_uint8 *pNum = ((_uint8*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_uint16).name()) {
		_uint16 *pNum = ((_uint16*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_uint32).name()) {
		_uint32 *pNum = ((_uint32*)(pt));
		sResult.add(_Math::intToStr(*pNum));
	}
	else if (sType == typeid(_uint64).name()) {
		_uint64* pNum = ((_uint64*)(pt));
		sResult.add(std::to_wstring(*pNum));
	}
	else if (sType == typeid(std::string).name()) {
		std::string* ps = ((std::string*)(pt));
		sResult.add(_string::qt_fromStdString(*ps));
	}
	else if (sType == typeid(std::wstring).name()) {
		std::wstring* ps = ((std::wstring*)(pt));
		sResult.add(_string::qt_fromStdWString(*ps));
	}
	else if (sType == typeid(_string).name()) {
		_string* ps = ((_string*)(pt));
		sResult.add(*ps);
	}
	else if (sType.indexOf("char const [") != -1) {//char const [9]
		const char* ps = (char*)(pt);
		sResult.add(_string::qt_fromUtf8(ps));
	}
	else if (sType.indexOf("wchar_t const [") != -1) {//char const [9]
		const wchar_t* ps = (wchar_t*)(pt);
		sResult.add(ps);
	}
	else if (sType == typeid(bool).name()) {
		bool* pb = (bool*)(pt);

		if (*pb)
			sResult.add(_t("true"));
		else
			sResult.add(_t("false"));
	}
	else if (sType.indexOf("lf::_DList") != -1)  //class lf::_DList<class lf::_StrW>
	{
		_Object* po = (_Object*)(pt);
		 
		return po->toString();
	}
	else if (sType == typeid(_Object).name()) 
	{
		_Object* po = (_Object*)(pt);

		return po->toString();
	}
	else {
		sResult.add(sType);
	}
	return sResult;
}

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

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

相关文章

HarmonyOS 应用程序包结构 (编译态)

不同类型的Module编译后会生成对应的HAP、HAR、HSP等文件&#xff0c;开发态视图与编译态视图的对照关系如下&#xff1a; 从开发态到编译态&#xff0c;Module中的文件会发生如下变更&#xff1a; ets目录&#xff1a;ArkTS源码编译生成.abc文件。resources目录&#xff1a;A…

After Effects的图钉与关键帧动画

姜 子 博 引言 在数字媒体时代&#xff0c;动态图形和视觉效果在信息传播和表达中扮演着越来越重要的角色。After Effects 作为行业领先的软件&#xff0c;提供了丰富的工具和功能&#xff0c;帮助用户创作出令人惊叹的视觉作品。图钉工具和关键帧动画是 AE 中实现复杂动画效…

共享模型之管程(悲观锁)

共享模型之管程&#xff08;悲观锁&#xff09; 文章目录 共享模型之管程&#xff08;悲观锁&#xff09;一、常见线程安全的类二、对象头三、Monitor&#xff08;监视器 / 管程&#xff09;四、偏向锁偏向锁的实现原理撤销偏向锁 五、轻量级锁轻量级锁的释放 六、重量级锁七、…

upload-labs详解(13-20)文件上传分析

目录 upload-labs-env upload-labs-env第十三关 文件包含漏洞 代码 测试 上传一个.jpg图片 上传一个.png文件 上传一个.gif图片 upload-labs-env第十四关 代码 思路 upload-labs-env第十五关 代码 思路 upload-labs-env第十六关 代码 思路 测试 上传gif格式…

探索高性能AI识别和边缘计算 | NVIDIA Jetson Orin Nano 8GB 开发套件的全面测评

随着边缘计算和人工智能技术的迅速发展&#xff0c;性能强大的嵌入式AI开发板成为开发者和企业关注的焦点。NVIDIA近期推出的Jetson Orin Nano 8GB开发套件&#xff0c;凭借其40 TOPS算力、高效的Ampere架构GPU以及出色的边缘AI能力&#xff0c;引起了广泛关注。本文将从配置性…

字典树(trie树)详解

【本文概要】本文主要介绍了字典树的概念&#xff0c;字典树的一般算法&#xff0c;包括初始化&#xff0c;插入&#xff0c;查找等&#xff0c;最后举了比较典型的案例来辅助理解字典树这种特殊的数据结构。 1、什么是字典树 字典树&#xff0c;是一种特殊的树状数据结构&…

从CL1看生物计算机的创新突破与发展前景:技术、应用与挑战的多维度剖析

一、引言 1.1 研究背景与意义 随着科技的飞速发展&#xff0c;计算机技术已经成为推动现代社会进步的核心力量之一。从最初的电子管计算机到如今的大规模集成电路计算机&#xff0c;计算机的性能得到了极大的提升&#xff0c;应用领域也不断拓展。然而&#xff0c;传统计算机…

小兔鲜Vue3

counterStore里面包含着对象返回的东西。 getters就是conputer git initgit add .git commit -m " " jsconfig进行路径提示。vite.config.js进行实际路径转化。 第一个文件做好就是一个axios实例了&#xff0c;可以直接调用方法。 在第二个文件是实例.get 写好路…

驱动 AI 边缘计算新时代!高性能 i.MX 95 应用平台引领未来

智慧浪潮崛起&#xff1a;AI与边缘计算的时代 正悄然深植于我们的日常生活之中&#xff0c;无论是火热的 ChatGPT 与 DeepSeek 语言模型&#xff0c;亦或是 Meta 智能眼镜&#xff0c;AI 技术已经无形地影响着我们的生活。这股变革浪潮并未停歇&#xff0c;而是进一步催生了更高…

STM32之软件SPI

SPI传输更快&#xff0c;最大可达80MHz&#xff0c;而I2C最大只有3.4MHz。输入输出是分开的&#xff0c;可以同时输出输入。是同步全双工。仅支持一主多从。SS是从机选择线。每个从机一根。SPI无应答机制的设计。 注意&#xff1a;所有设备需要共地&#xff0c;时钟线主机输出&…

深度学习系列79:Text2sql调研

参考 https://github.com/topics/text-to-sql 这里是一些资源&#xff1a;https://github.com/eosphoros-ai/Awesome-Text2SQL/blob/main/README.zh.md 这里是综述文章&#xff1a;https://zhuanlan.zhihu.com/p/647249972 1. 数据集 Spider: 一个跨域的复杂text2sql数据集&a…

【Unity】 HTFramework框架(六十一)Project窗口文件夹锁定器

更新日期&#xff1a;2025年3月7日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 Project窗口文件夹锁定器框架文件夹锁定自定义文件夹锁定限制条件 Project窗口文件夹锁定器 在Project窗口中&#xff0c;文件夹锁定器能够为任何文件夹加…

nginx服务器实现上传文件功能_使用nginx-upload-module模块

目录 conf文件内容如下html文件内容如下上传文件功能展示 conf文件内容如下 #user nobody; worker_processes 1;error_log /usr/logs/error.log; #error_log /usr/logs/error.log notice; #error_log /usr/logs/error.log info;#pid /usr/logs/nginx.pid;even…

基于云的内容中台核心优势是什么?

弹性云架构赋能资源整合 现代企业通过弹性云架构实现多源数据资源的深度整合&#xff0c;其动态扩展能力可自动适配业务流量波动。基于分布式存储与容器化部署&#xff0c;系统能够无缝对接CRM、ERP等企业软件集成&#xff0c;实现跨平台数据实时同步。值得注意的是&#xff0…

*图论基础(5)

持续更新... 1.图的基本概念 不写了&#xff0c;网上有好多资料ovo 2.图的存储和遍历 2.1存储&#xff1a; 3.最小生成树 3.2Kruskal算法 4.拓扑排序 拓扑排序的⽬标是将有向⽆环图中的所有结点排序&#xff0c;使得排在前⾯的结点不能依赖于排在后⾯的结 点。在课程问题中…

DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)示例3: 行选择

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

DevSecOps CI/CD 管道中数字供应链安全的集成策略

前言&#xff1a; 在敏捷开发的模式下&#xff0c;应用程序会通过 DevSecOps 的敏捷软件开发生命周期&#xff08;SDLC&#xff09;范式进行开发&#xff0c;并使用持续集成/持续交付&#xff08;CI/CD&#xff09;管道的流程。 然而&#xff0c;在软件开发、供应和交付运营中…

JmeterHttp请求头管理出现Unsupported Media Type问题解决

JmeterHttp请求头管理出现Unsupported Media Type问题解决 大多数的app与pc端压测的时候都会出现这种情况 当我们在jemter测试当中当中遇见Unsupported Media Type&#xff0c;有一种可能就是我们请求的网页的content-Type的类型与我们测试的时候的类型不一致 解决方法 可以添…

STM32 子设备通过CAN发送数据到主设备

采集ADC、GPS经纬坐标、温湿度数据、大气压数据通过CAN方式发送给主设备端&#xff0c;帧ID按照如下定义&#xff1a; 我尼玛一个标准帧ID位数据是11位&#xff0c;扩展帧才是111829位&#xff0c;它说最开头的是四位是真类型&#xff0c;并给我如下解释&#xff1a; 它把帧的定…

基于深度学习的青花瓷图像检索系统开发与实现

目录 1.研究背景与目的 1.1课题背景 1.2研究目的 二、调研资料情况 2.1图像分割研究现状 2.2图像检索调研 2.2.1选择深度学习进行检索的原因及优势 2.2.2基于深度学习的图像检索技术的发展 2.2.3基于深度学习的图像检索的研究重点 2.3基于深度学习的图像检索方法调研 …