【C++杂货铺】string使用指南

news2024/11/18 19:50:39

在这里插入图片描述

文章目录

  • 前言
  • 一、介绍
  • 二、string类的常用接口说明
    • 2.1 常见的构造接口
    • 2.2 与容量有关的接口
    • 2.3 与对象访问及遍历有关的操作
    • 2.4 与对象修改有关的操作
    • 2.5 与查找有关的接口
    • 2.6 string类的非成员函数
    • 2.7 与类型转换有关的接口

前言

在C语言中,字符串是以\0结尾的一些字符的集合,为了方便操作,C标准库中提供了一些str系列的库函数。但是这些库函数与字符串是分离开的,不太符合面向对象(OOP)的思想,而且底层空间需要用户自己去管理,稍不留神可能就会出现越界访问。为了解决上面的这些问题,C++中引入了string类,它给我们带来了极大的便利。

一、介绍

  • string是表示字符串的字符串类。

  • 该类的接口与常规容器(vector、list等)的接口基本相同,再添加了一些专门用来操作string的常规操作。

  • string在底层实际是:用basic_string模板类实例化出来的一个类,typedef basic_string<char> string;

  • 不能操作多字节或者变长字符的序列。

小Tips:在使用string类时,需要包含头文件#include <string>,以及使用using namespace std展开命名空间。

二、string类的常用接口说明

2.1 常见的构造接口

📖string()
该类的默认构造函数,用于构造空的string类对象,即空字符串。

int main()
{
	string s1;
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述
小Tipsstring类对象支持流插入和流提取,下文将进行介绍,这里大家直接使用即可。

📖string(const char* s)
C-string来构造string类对象,即用一个C的字符串(或字符数组)来构造一个string类的对象。

int main()
{
	string s1("Hello C++!");
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述

📖string(size_t n, char c)
用n个字符c来构建一个string类对象。

int main()
{
	string s1(5, 'x');
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述

📖string(const string& s)
string类的拷贝构造,用于构建一个和已存在的string类对象s一模一样的对象。

int main()
{
	string s1(5, 'x');
	string s2(s1);
	cout << s1 << endl;
	cout << s2 << endl;
	return 0;
}

在这里插入图片描述

📖string (const string& str, size_t pos, size_t len = npos)
复制str中从字符位置pos开始并跨越len字符的部分(如果 str 太短或 len 是字符串npos,则直到 str 的末尾)。简单来说就是使用一个已存在的string类对象的一部分来创建一个新的string类对象。

小Tipsnopsstring类里面的一个静态成员变量,它是size_t类型,初始化为-1,即表示整型的最大值。此值如果在string的成员函数中作为形参len的缺省值,表示到字符串结束。如果作为string类中成员函数的返回值,一般表示没有匹配项。

int main()
{
	string s1("Hello C++!");
	string s2(s1, 0, 5);//用s1的部分来初始化创建s2
	cout << s1 << endl;
	cout << s2 << endl;
	return 0;
}

在这里插入图片描述

注意:对一个string类对象来说,它的第一个有效字符的下标是0。

📖string (const char* s, size_t n)
s所指向字符串(或字符数组)的前n个来初始化创建一个string类对象。

int main()
{
	char str[] = "Hello C++!";
	string s1(str, 5);//用字符数组str的前5个字符来构建一个string类对象
	cout << str << endl;
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述

2.2 与容量有关的接口

📖size()
返回字符串的有效字符长度。

int main()
{
	string s1("Hello C++!");
	string s2("Good morning!");
	cout << "s1的size:" << s1.size() << endl;
	cout << "s2的size:" << s2.size() << endl;
	return 0;
}

在这里插入图片描述
📖length()
返回字符串的有效字符长度。

int main()
{
	string s1("Hello C++!");
	string s2("Good morning!");
	cout << "s1的length:" << s1.length() << endl;
	cout << "s2的length:" << s2.length() << endl;
	return 0;
}

在这里插入图片描述
小Tips:从上面的打印结果可以看出,size()length()接口的功能一模一样,甚至底层实现原理也完全相同,都是返回字符串的有效字符个数,最初只有length()接口,引入size()接口的原因是为了与其他容器的接口保持以致,一般情况下基本都使用size()接口。这也从侧面说明string诞生的时间比STL要早。

📖capacity()
返回一个string对象中空间的大小。

int main()
{
	string s1("Hello C++!");
	string s2("Good morning chunren!");
	cout << "s1的capacity:" << s1.capacity() << endl;
	cout << "s2的capacity:" << s2.capacity() << endl;
	return 0;
}

在这里插入图片描述
小Tips:同一个string对象,在不同平台下的capacity()(空间容量)可能不同,因为string在底层就是一个存储字符的动态顺序表,空间不够了要进行扩容,而不同平台底层的扩容机制可能有所不同,这就导致了最终capacity()的结果不同。将上面的代码放到Linux环境下使用g++编译器再来试试:

在这里插入图片描述
小Tipscapacity()返回一个string对象中空间的大小,这个空间指的是可以存储有效字符的空间,底层实际上的空间会多一个,因为还要存储\0

📖VS下的扩容机制

int main()
{
	string s1("Hello!");
	size_t old = s1.capacity();
	cout << s1.capacity() << endl;
	for (size_t i = 0; i < 100; i++)
	{
		s1 += 'v';
		if (old != s1.capacity())
		{
			cout << "扩容:" << s1.capacity() << endl;
			old = s1.capacity();
		}
	}
	return 0;
}

在这里插入图片描述
VS下一上来会有15个空间用来存储数据(本质上是开16个空间,因为还要存\0),第一次扩容是2倍,后面都是以1.5倍的大小去扩容。

在这里插入图片描述
📖Linux下的扩容机制

int main()
{
	string s1("Hello!");
	size_t old = s1.capacity();
	cout << s1.capacity() << endl;
	for (size_t i = 0; i < 100; i++)
	{
		s1 += 'v';
		if (old != s1.capacity())
		{
			cout << "扩容:" << s1.capacity() << endl;
			old = s1.capacity();
		}
	}
	return 0;
}

将上面的代码放到Linux环境下使用g++编译器再来试试:

在这里插入图片描述
可见在Linux下,最初对象需要多少空间就开多少,后面一次按照2倍的大小进行扩容。

📖empty()
检测字符串是否为空串,是返回true,否则返回false

int main()
{
	string s1;//
	if (s1.empty())
	{
		cout << "s1是一个空串" << endl;
	}
	return 0;
}

在这里插入图片描述
📖clear()
清空有效字符。

int main()
{
	string s1("Hello C++!");
	cout << "清空之前的size:" << s1.size() << endl;
	cout << "清空之前的capacity:" << s1.capacity() << endl;
	s1.clear();//清空
	cout << "清空之后的size:" << s1.size() << endl;
	cout << "清空之后的capacity:" << s1.capacity() << endl;
	return 0;
}

在这里插入图片描述
小Tips:从打印结果可以看出,clear()清空操作不会影响capacity()容量,也就是说string对象并不会主动的去缩容。

📖reserve (size_t n = 0)
为字符串预留空间。直接一次申请n个空间,可以用来存储n个有效字符,避免了每次都要去扩容。大部分的扩容都是异地扩容,扩容次数过多会影响效率。

int main()
{
	string s1;
	s1.reserve(100);//知道要尾插100个字符就先直接申请100个,避免后面再去扩容
	size_t old = s1.capacity();
	cout << s1.capacity() << endl;
	for (size_t i = 0; i < 100; i++)
	{
		s1 += 'v';
		if (old != s1.capacity())
		{
			cout << "扩容:" << s1.capacity() << endl;
			old = s1.capacity();
		}
	}
	s1.reserve(20);
	cout << "第二次执行reserve(20):" << s1.capacity() << endl;
	return 0;
}

在这里插入图片描述

小Tips:实际申请到的有效空间可能比我们需要的多,但是一定不可能比我们需要的少,如s1.reserve(100)去申请100个有效空间,但实际上申请了111个有效空间。当n小于当前对象的容量时,一般的编译器都不会执行缩容。(视具体情况而定)

📖resize
在这里插入图片描述
将字符串大小调整为n个长度的大小,当n小于当前字符串的长度size(),会保留前n个字符,将第n个字符后面的所以字符删除;当n大于当前字符串的长度size(),先会进行扩容,以满足存储n个有效字符的需求,如果指定了字符c,会将新元素初始化为c的副本,否则全部初始化为空字符,即\0

int main()
{
	string s1("Hello C++!");
	cout << "最初的s1.size():" << s1.size() << endl;
	cout << "最初的s1.capacity():" << s1.capacity() << endl;
	string s2 = s1;//将s1拷贝一份

	s1.reserve(100);
	cout << "reserve(100)后的s1.size():" << s1.size() << endl;
	cout << "reserve(100)后的s1.capacity():" << s1.capacity() << endl;

	s2.resize(100);
	cout << "resize(100)后的s1.size():" << s2.size() << endl;
	cout << "resize(100)后的s1.capacity():" << s2.capacity() << endl;
	return 0;
}

在这里插入图片描述
小Tipsreserveresize的区别可总结为:前者只会影响容量,负责申请空间,不会改变字符串的有效字符个数,即会改变capacity,不会改变size;后者在申请空间的基础上还会对空间进行初始化,这样就会对有效字符的个数产生影响,所以它即会改变capacity也会改变size

📖shrink_to_fit()
capacity容量缩至合适,一般不会缩小到和size一样大,可能会比size大一点。

int main()
{
	string s2("Hello C++!");
	cout << "最初的s2.size():" << s2.size() << endl;
	cout << "最初的s2.capacity():" << s2.capacity() << endl;

	s2.reserve(100);//扩容
	cout << "reserve(100)后的s2.size():" << s2.size() << endl;
	cout << "reserve(100)后的s2.capacity():" << s2.capacity() << endl;

	s2.shrink_to_fit();//缩容
	cout << "缩容后的s2.size():" << s2.size() << endl;
	cout << "缩容后的s2.capacity():" << s2.capacity() << endl;
	return 0;
}

在这里插入图片描述

2.3 与对象访问及遍历有关的操作

📖operator[ ]
在这里插入图片描述

int main()
{
	string s1("Hello C++!");//普通对象
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i];
	}
	cout << endl << "修改后:";
	for (size_t i = 0; i < s1.size(); i++)
	{

		cout << ++s1[i];//因为返回值是引用所以可以用[]对其进行修改
	}
	cout << endl;
	const string s2("Hello World!");
	for (size_t i = 0; i < s2.size(); i++)
	{
		cout << s2[i];
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
小Tips:因为operator[]的返回值是一个引用,所以可以通过[]加下标的方式去访问和修改string类对象,和内置类型的数组不同,这里的s1[i]本质上是去调用函数,而内置类型的数组使用[]本质是解引用。如果发生越界访问,程序会直接报错,at接口和operator[]接口的功能类似,只不过at接口在发生越界访问的时候会抛出异常。

📖迭代器
迭代器是一种抽象的设计概念,它提供一种方法,使之能够依序巡访某个容器所含的各种元素,而又无需暴露该容器的内部表述方式。迭代器是一种行为类似指针的对象,它是容器与算法的桥梁,算法需要去访问容器中的数据,但是容器的数据都是私有的,并且有多种容器,针对不同的容器,某一算法的具体实现可能不同,例如对链表逆置和对顺序表逆置,具体过程当然是不同的,但是迭代器的出现却将它们统一了起来,对于一个算法,无论是什么容器,只需要将它的迭代器区间传过来即可,算法只使用统一的逻辑。因此任何容器的迭代器类型都用iterator来表示,它是一个类的内置类型,通过typedef得到,关于迭代器更具体地内容我将在后续模拟实现的文章中为给大家分享,今天我们只需要知道如何使用即可。

📖begin、end
在这里插入图片描述
在这里插入图片描述

int main()
{
	string s1("Hello C++!");//普通对象
	string::iterator it = s1.begin();
	while (it < s1.end())
	{
		cout << *it;//解引用迭代器
		it++;//++迭代器,让迭代器向后走
	}
	cout << endl;
	it = s1.begin();
	while (it < s1.end())
	{
		++(*it);//通过迭代器去修改
		it++;
	}
	it = s1.begin();
	while (it < s1.end())
	{
		cout << *it;
		it++;
	}
	cout << endl;
	return 0;
}

在这里插入图片描述

从上面的代码可以看出,一个迭代器对象和一个指针类型的变量十分相似,都可以通过*解引用,并且都可以++,还可以解引用后去修改。但本质上对迭代器的这些操作都是通过运算符重载来实现的,具体实现我将在后续文章中为大家介绍。

小Tips:迭代器区间永远都是左闭右开,迭代器类型作为类的内置类型可以直接通过类名::iterator访问,例如:string::iterator就表示string类里面的迭代器类型。普通迭代器可读可写,const迭代器限制的是其指向的内容,只能读不能写,而const迭代器本身可以修改。

📖rbegin、rend
在这里插入图片描述
在这里插入图片描述

int main()
{
	string s1("Hello C++!");//普通对象
	string::reverse_iterator it = s1.rbegin();
	while (it < s1.rend())
	{
		cout << *it;//解引用迭代器
		it++;//++迭代器,让迭代器向后走
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
小Tipsreverse_iterator一般被叫做反向迭代器,因为它可以倒着去遍历。

📖范围for

int main()
{
	string s1("Hello C++!");//普通对象
	for (auto it : s1)
	{
		cout << it;
	}
	cout << endl;
	for (auto& it : s1)//用引用就可以进行修改
	{
		it--;
	}
	for (auto it : s1)
	{
		cout << it;
	}
	cout << endl;
	return 0;
}

在这里插入图片描述
小Tips:范围for就是基于迭代器实现的,在底层范围for会转化成正向迭代器。换言之,一个容器如果不支持迭代器,那它必定也不支持范围for。

2.4 与对象修改有关的操作

📖operator=
赋值运算符重载是string类的一个默认成员函数,该函数有三个重载形式,如下图所示:

在这里插入图片描述

int main()
{
	string s1("Hello C++!");
	string s2("你好,C++!");
	cout << s2 << endl;//原始的s2
	s2 = s1;//string类对象
	cout << s2 << endl;//第一次赋值后的s2
	s2 = "春人.";
	cout << s2 << endl;//第二次赋值后的s2
	s2 = 'a';
	cout << s2 << endl;//第三次赋值后的s2
	return 0;
}

在这里插入图片描述
📖void push_back (char c)
将一个字符c追加到string类对象的末尾,它的长度增加1。

int main()
{
	string s1("Hello C++!");
	cout << "追加前:" << s1 << endl;
	s1.push_back('s');
	cout << "追加后:" << s1 << endl;
	return 0;
}

在这里插入图片描述
📖append
append是在源字符串的后面进行追加操作的成员函数,它有七种重载实现形式,如下图所示:

在这里插入图片描述

int main()
{
	string s1("Hello C++!");
	string s2("aaaa");
	cout << "追加前:" << s2 << endl;
	s2.append(s1);
	cout << "追加一个string对象:" << s2 << endl;
	s2 = "aaaa";
	s2.append(s1, 6, 3);
	cout << "追加一个string对象的一部分:" << s2 << endl;
	s2 = "aaaa";
	s2.append("你好");
	cout << "追加一个C类型的字符串:" << s2 << endl;
	s2 = "aaaa";
	s2.append("Hello!", 2);
	cout << "追加一个C类型字符串的前两个字符:" << s2 << endl;
	s2 = "aaaa";
	s2.append(5, 'b');
	cout << "追加五个字符b:" << s2 << endl;
	s2 = "aaaa";
	s2.append(s1.begin()+2, s1.begin()+4);
	cout << "追加一个迭代器区间:" << s2 << endl;
	return 0;
}

在这里插入图片描述
📖operator+=
通过重载运算符+=实现追加,该运算符重载有三种重载实现形式,如下图所示:

在这里插入图片描述

int main()
{
	string s1("Hello C++!");
	string s2("aaaa");
	cout << "追加前:" << s2 << endl;
	s2 += s1;
	cout << "追加一个string类对象:" << s2 << endl;
	s2 = "aaaa";
	s2 += "bcde";
	cout << "追加一个C类型的字符串:" << s2 << endl;
	s2 = "aaaa";
	s2 += 'o';
	cout << "追加一个字符:" << s2 << endl;
	return 0;
}

在这里插入图片描述
小Tips:除了上面介绍的一些常用的字符串修改接口外,还有一些不太常用的,例如:assign(内容替换)、insert(指定位置插入)、erase(删除)、replace(部分替换)、swap(交换两个字符串)。它们的使用方法都大同小异。

2.5 与查找有关的接口

📖c_str()
该接口的返回值类型是const char*,即返回一个C格式的字符串,该接口起到桥梁作用。

int main()
{
	string s2("Hello C++!");
	const char* str = s2.c_str();
	cout << str << endl;
	return 0;
}

在这里插入图片描述
📖find
从字符串的pos位置开始往后查找字符或字符串,返回其在当前字符串中的位置。

在这里插入图片描述

int main()
{
	string s1("https://www.csdn.net/?spm=1011.2124.3001.4476");
	size_t pos1 = s1.find("csdn");
	cout << pos1 << endl;
	size_t pos2 = s1.find("www.csdn.net", 7, 3);
	cout << pos2 << endl;
	return 0;
}

在这里插入图片描述
小Tips:一般在没有找到的情况下会返回npos,即整型最大值。

📖rfind
在字符串pos位置开始往前查找字符或字符串,返回其在当前字符串中的位置。

在这里插入图片描述

int main()
{
    std::string str("The sixth sick sheik's sixth sheep's sick.");
    std::string key("sixth");

    std::size_t found = str.rfind(key);
    if (found != std::string::npos)
        str.replace(found, key.length(), "seventh");

    std::cout << str << '\n';

    return 0;
}

在这里插入图片描述
📖substr (size_t pos = 0, size_t len = npos)
在源字符串中,从pos位置开始,截取n个字符,以string的形式返回。

int main()
{
	string s1("https://www.csdn.net/?spm=1011.2124.3001.4476");
	size_t pos1 = s1.find("csdn");
	string s2 = s1.substr(pos1, 8);
	cout << s2 << endl;
	return 0;
}

在这里插入图片描述
小Tips:除了上面介绍的一些常用接口,还有一些不常用的,比如:find_first_of(在字符串中搜索与其参数中指定的任何字符匹配的第一个字符)、find_last_of(查找最后一个匹配的)、find_first_not_of(查找第一个不匹配的)、find_last_not_of(查找最后一个不匹配的)。

2.6 string类的非成员函数

有些运算符重载函数存在竞争左操作数的问题,所以它们写在string类的外面,是类的非成员函数,主要有下面几种:

函数功能说明
operator+尽量少用,因为是传值返回,会进行深拷贝导致效率降低
operator>>输入运算符重载
operator<<输出运算符重载
relational operators大小比较运算符重载
getline获取一行字符串

小Tipsoperator>>getline的区别在于,前者遇到空格' '和换行\n会截止,而后者默认只有遇到换行\n才截止,因此当我们需要从键盘读取一个含有空格的字符串是,只能用getline

2.7 与类型转换有关的接口

📖string类型转成其他内置类型
在这里插入图片描述
📖to_string将内置类型转成string类型
在这里插入图片描述


🎁结语:
 今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下,您的支持就是春人前进的动力!
在这里插入图片描述

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

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

相关文章

Win10、11集体翻车,祖传Bug连关机都不能

基本可以确定的是&#xff0c;微软将在2024年推出或名为 Win12 的下一代 Windows 。 Win10、11 的更新跨度肉眼可见放缓&#xff0c;可频率嘛&#xff0c;仍然一月几更。 如果你没有禁用更新&#xff0c;应该和小蝾一样&#xff0c;下班关机时经常有熟悉的选项。 不过在大多数…

分享之python 线程

Threading用于提供线程相关的操作&#xff0c;线程是应用程序中工作的最小单元。 1、threading模块 threading 模块建立在 _thread 模块之上。thread 模块以低级、原始的方式来处理和控制线程&#xff0c;而 threading 模块通过对 thread 进行二次封装&#xff0c;提供了更方…

ansible常见模块的运用

ansible常见模块的运用 一&#xff1a;Ansible简介二&#xff1a;ansible 环境安装部署管理端安装 ansibleansible 目录结构配置主机清单配置密钥对验证 三&#xff1a;ansible 命令行模块1&#xff0e;command 模块在远程主机执行命令&#xff0c;不支持管道&#xff0c;重定向…

这所国字头双一流,根本招不满,学硕都没人报!

一、学校及专业介绍 中国民航大学&#xff0c;位于天津市&#xff0c;是民航局、天津市、教育部共建高校&#xff0c;是天津市“双一流”建设高校和高水平特色大学建设高校。 1.1 招生情况 2023年中国民航大学电子信息与自动化学院&#xff0c;初试考806信号与系统的一共有两…

Windows环境下创建定时任务执行Python脚本

一、环境 以下演示使用的环境说明 Windows 操作系统&#xff1a;Win10 Python 环境&#xff1a;Python 3.7.7 二、脚本 准备Python脚本如下&#xff1a; import sys import datetimeformat_time datetime.datetime.now()with open(file"forpy.log",mode"a&qu…

单月涨粉345万,7月抖音爆款技巧是什么?

近期&#xff0c;抖音电商官方发布「七夕好礼季」的玩法攻略&#xff0c;助力商家抢跑七夕。如今&#xff0c;各类营销节点&#xff0c;成为商家实现生意爆发的关键。 那么&#xff0c;在没有营销节点加持的7月&#xff0c;那些表现突出的主播&#xff0c;持续畅销的商品&#…

解决elementUI图标按钮调整宽高后图标没有居中的问题

解决elementUI图标按钮调整宽高后图标没有居中的问题 1.情景再现2.解决2.1 重新设置新的padding2.2 flex布局 1.情景再现 我是用elementui的图标按钮组件&#xff0c;但是我想要的大小和官方给到的大小不一致。所以我给图标设置了一个width: 16px;height: 16px;的属性值&#…

开学在即,这个超好用的中小学新生录取查询系统制作方法值得借鉴

即将开学&#xff0c;中小学负责招生的老师面临着新学年的招生工作。这是一项紧迫且重要的任务&#xff0c;需要老师们迅速而有效地应对。在新生录取过程中&#xff0c;有几个关键任务需要尽快完成。 首先&#xff0c;老师们需要录入新生的成绩信息。这包括学生的考试成绩、综…

算法通关村—二叉树处理每层元素的题目

1. 在每个树行中找最大值 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9] 依然先写出层序遍历&#xff0c;只不过遍历的过程中需要保存当前一层的最大值。 public List<Integer> largestVa…

VLT:Vision-Language Transformer用于引用的视觉语言转换和查询生成分割

摘要 在这项工作中&#xff0c;我们解决了引用分割的挑战性任务。引用分割中的查询表达式通常通过描述目标对象与其他对象的关系来表示目标对象。因此&#xff0c;为了在图像中的所有实例中找到目标实例&#xff0c;模型必须对整个图像有一个整体的理解。为了实现这一点&#…

【Java】Springboot脚手架生成初始化项目代码

Springboot配置生成初始化项目代码可以通过mvn的mvn archetype:generate 和阿里云原生应用脚手架&#xff08;地址&#xff09;、spring官方提供的start初始化生成页面(地址&#xff09;。 1、mvn archetype:generate 通过mvn选择对应的脚手架可以快速生成初始化代码&#xf…

【网络安全】网络安全威胁实时地图 - 2023

文章目录 [TOC] ① 360 安全大脑360 APT全景雷达 ② 瑞星杀毒瑞星云安全瑞星网络威胁态势感知平台 ③ 比特梵德 Bitdefender④ 飞塔防火墙 FortiGuard⑤ 音墙网络 Sonicwall⑥ 捷邦 Check Point⑦ AO卡巴斯基实验室全球模拟隧道模拟 ⑧ 数字攻击地图⑨ Threatbutt互联网黑客攻击…

Ansys Lumerical | GPU,超透镜,铌酸锂调制器等重磅来袭!

Ansys Lumerical 2023R2新版本正式发布&#xff01;主要集中在光子学多物理场求解器增强&#xff0c;FDTD GPU 加速支持&#xff0c;超透镜流程优化&#xff0c;铌酸锂调制器支持&#xff0c;光子集成电路仿真能力增强&#xff0c; GUI增强和云计算支持等。 光子学核心技术 1、…

【Clion 2】多行TODO使用

一、TODO: 说明&#xff1a; 有时需要标记部分代码以供将来参考&#xff1a; 优化和改进的领域、可能的更改、要讨论的问题等等。 支持&#xff1a; TODO和FIXME小写和大写。这些模式可以在任何受支持的文件类型的行注释和块注释内使用。 创建TODO项 在要添加注释的代码行中…

问道管理:房地产政策调控新信号出现,南京有二手房东连夜跳价100万

最近几天&#xff0c;国家发改委、住建部、北上广深住建部门表态挺楼市&#xff0c;放宽房地产方针。一夜之间&#xff0c;地产股大涨&#xff0c;多地商场情绪恢复。 诸葛找房数据显现&#xff0c;自7月29日起&#xff0c;南京万科金域缇香、紫园、后标营、翠屏诚园等小区的部…

云道资本:2023中国氢能源产业-氢制备深度研究报告(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 中国可再生能源消纳能力提升远远滞后于发电占比的提升。大规模的可再生能源发电是实现碳中和的关键一步&#xff0c;但风电、光伏发电间歌性、波动性强&#xff0c;电网消纳压力较大&#xff0c;且电…

【图论】强连通分量进阶

一.作用 强连通分量可以判断环和进行缩点。还有一系列作用.... 这篇文章介绍缩点 二.题目 https://www.luogu.com.cn/problem/P2341 三.思路 我们分析可以知道当一个点没有出度时&#xff0c;则为最受欢迎的牛。但如果有多个出度&#xff0c;则没有最受欢迎的牛。 这是只有…

【Docker】部署 mysql8.0 无法访问

文章目录 &#x1f5fd;先来说我的是什么情况&#x1fa81;问题描述&#x1fa81;解决方法&#xff1a;✔️1 重启iptables✔️2 重启docker &#x1fa81;其他有可能连不上的原因✔️1 客户端不支持caching_sha2_password的加密方式✔️2 my.conf 配置只有本机可以访问 &#…

第一章-JavaScript基础进阶part1:DOM

文章目录 前言一、DOM简介1.1 DOM树 二、获取DOM元素1、根据元素id获取-getElementById2、根据元素名称获取元素对象-getElementsByTagName3、H5新增API获取元素4、获取body和html元素 三、DOM元素事件四、操作DOM元素1、改变元素内容2、常用元素的属性操作3、实践案例4、操作D…

Linux操作系统3-项目部署

手动部署 步骤 1.在idea中将文件项目进行打包 2.自定义一个文件目录&#xff0c;上传到Linux 3.使用 java -jar jar包名就可以进行运行 注意,如果需要启动该项目&#xff0c;需要确定所需的端口是否打开 采用这种方式&#xff0c;程序运行的时候会出现霸屏&#xff0c;并且会…