「C++ STL篇 0-0」string类的使用

news2025/1/14 1:21:22

目录

〇、概念

1. string类是什么?

2. string类的官方文档

3. 导入string类 

一、string类的构造函数

0. 全部构造函数

1. 常用的四个构造函数

2. 可能用到的构造函数

拓1:npos

二、赋值运算符重载

1. 三个赋值运算符重载函数 

2. 使用赋值运算符重载函数

拓2:构造还是赋值?

三、有关容量的操作

1. 有关容量的操作函数

2. 常用的容量操作函数

a. 获取字符串有效字符长度

b. 获取字符串占用空间总大小

c. 判空和清空字符串

e. 设置有效字符长度

四、string对象的访问

1. string对象的三种访问方法

2. [ ] 和 at()

3. string::iterator

五、遍历string对象

1. 使用[ ]遍历string对象

2. 使用迭代器来遍历string对象

六、string对象的修改

0. string类中有关修改的函数

1. 追加

a. operator +=()

b. append()

2. 插入

​编辑

3. 删除

七、string对象的常用操作

0. string对象的操作函数

1. c_str()

2. find() 和 rfind()

八、字符串和数字间的转换

拓展】

1:operator +

2:重载比较运算符

3:按行输入

4:判断字符是字母还是数字

练习】

1:将字符串中的空格替换为%20

2:获取文件后缀

源代码】



〇、概念

1. string类是什么?

string相当于一个支持动态增长的char数组。

 

string的底层是一个叫 basic_string 的类模板,模板中存的是char。


事实上string库中还用basic_string类模板实现了存储宽字符的wstring,存储16位字符的 u16string(C++11后支持),和存储32位字符的 u32string(C++11后支持):

2. string类的官方文档

        博主在文章中只是讲述了有关string类的常用函数,对于一些不常用,可以查看官方文档: string类的官方文档

3. 导入string类 

要使用官方的string类:

  • 首先我们要引入头文件:#include<string>
  • 其次展开命名空间std中的string类:using std::string;

        严格来说string是属于C++ std标准库的,不在STL中,但是两者有许多相似之处,就放在一起总结了。


一、string类的构造函数

0. 全部构造函数

以下为C++98中string的所有构造函数

1. 常用的四个构造函数

string() (重点)构造空的string类对象,即空字符
string(const char* s) (重点)用字符数组来构造string对象
string(const string & s) (重点)拷贝构造函数
string(size_t n, char c)用n个c字符来构造string对象
string a;  //注意空字符串的创建不是string a(); 这是在声明一个返回值为string 的无参函数。
string b("abc"); //使用字面字符串来构造对象
string c(b);     //拷贝构造
string d(3, 'a');

cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;

        唯一要注意的一点是创建空字符串不是string a(); 这是在声明一个返回值为string 的无参函数。是string a;

2. 可能用到的构造函数

string (const string& str, size_t pos, size_t len = npos);从str的下标 pos 处开始复制 len 个字符,不设置len默认复制到结尾
string e("1abcdefg", 1);     //abcdefg (从下标1开始复制)
string f(e, 1);              //bcdefg  (从下标1开始复制)
string g("1abcdefg", 1, 5);  //abcde   (从下标1开始复制5个字符)
string h(e, 0, 3);           //abc     (从下标0开始复制3个字符)

         唯一要注意的一点是:第二、三个参数的意义是,从下标pos处开始复制len个字符。不是复制它们之间的字符。不传第三个参数则默认复制到结尾。

拓1:string::npos


  • npos是std命名空间中string类下的一个静态成员变量。(std::string::npos)
  • npos用来表示一个非常非常大的数值(约为42亿9千万),因为size_t是无符号的整型,如果将-1的补码转化为无符号的整型将非常非常大,所以一般用string::npos来表示直到字符串的结尾。 

二、赋值运算符重载

1. 三个赋值运算符重载函数 

有三个重载,分别接受字符串,字符数组,字符作为参数。

以上三个运算符重载又互相构成函数重载。 

2. 使用赋值运算符重载函数

string& operator= (const string & str);使用string对象赋值
string& operator= (const char* s);使用字面字符串/字符数组赋值
string& operator= (char c);使用单个字符赋值
string a("abcd");
string b("bcde");
string c = b; // 注意这是在调用构造和拷贝构造函数
a = b;
cout << a << endl;
a = "fghi";
cout << a << endl;
a = 'j';
cout << a << endl;

        唯一一点要注意的就是要区分是在调用构造函数还是在赋值,上面代码中的第三行就是在调用构造函数。


拓2:构造还是赋值?

string a = b; // 注意这是在调用构造而不是赋值
string b("bcde");
a = b; // 这里才是赋值

        要注意第一行代码可不是在赋值,而是在通过隐式类型转换调用构造函数(先构造,再拷贝,编译器可能优化为直接构造)


        如何区分是构造还是赋值?就看对象有没有创建出来,如上面第一行代码中的对象a正在创建,所以这是在调用构造函数;而第三行中使用的是已经创建好的a对象,所以是在赋值,调用了赋值运算符重载函数。

三、有关容量的操作

1. 有关容量的操作函数

2. 常用的容量操作函数

size_t size() const noexcept;返回字符串有效字符长度

size_t length() const noexcept;

返回字符串有效字符长度
size_t capacity() const noexcept;返回字符串占用空间总大小(字节)
bool empty() const noexcept;检测字符串是否为空串,是返回true,否则返回false
void clear() noexcept;清空字符串
void reserve (size_t n = 0);为字符串预留空间
void resize (size_t n);设置有效字符长度,用'\0'填充多出来的位置

void resize (size_t n, char c);

设置有效字符长度,用指定字符填充多出来的位置

a. 获取字符串有效字符长度

        推荐使用size(),少用length()。虽然设计方面两个函数是一样的,但为了在学习后面的容器时不产生混乱(其它容器中都有size()来计算元素个数,但不一定有length()),使用推荐使用size()

b. 获取字符串占用空间总大小

        stirng对象中的字符数组的空间大小不一定等于有效字符长度size,因为扩容是有消耗的,所以一般扩容不是一个一个一个扩,而是以1.5或2倍大小来扩容,我们可以通过capacity()来获取stirng对象中的字符数组的空间大小。

c. 判空和清空字符串

  • empty()通过检查有效字符长度来判断string对象是否为空,为空返回true。
  • clear()通过将有效字符长度置为0来清空字符串。

d. 为字符串预留空间

        当string对象的有效字符长度size等于容量capacity时会触发扩容,扩容是有消耗的,如果我们提前知道有效字符长度size,就可以通过reserve()来提前开好一片空间,就不需要频繁的扩容了。

e. 设置有效字符长度

         resize()通过设置有效字符长度size,来更新字符串的长度,如果新长度比当前字符串有效长度长,默认用'\0'填充。(string对象的打印不是遇到'\0'终止,但'\0'不会被显示)


        我们也可以通过resize()的第二个参数来指定,当新长度比当前字符串有效长度长时的填充字符。

四、string对象的访问

1. string对象的三种访问方法

string对象主要三种访问方法:[ ]、at()、string::iterator


  • [ ]没什么好说的,重载[ ]让string类能像数组一样使用。
  • 成员函数at()用来返回指定下标处的字符,类似于Java中的charAt(),让string类符合封装的思想,但几乎不怎么用。
  • string::iterator就是迭代器,string类的迭代器可以当作指针来用,begin(),end()返回的就是数组下标0和下标size处的迭代器。

2. [ ] 和 at()

  • 重载[ ]让string类能像数组一样使用

  • 成员函数at()用来返回指定下标处的字符 


3. string::iterator

        string类的迭代器可以当作指针来用,begin(),end()相当于指向字符串开头和结尾('\0'处)的指针。通过+/- 能获取下一个或上一个地址。通过*(解引用)能取出地址中的内容。


五、遍历string对象

        上面的三种访问方式都可以用来遍历string对象。这里因为[]和at()区别不大,所以就演示使用[ ] 和 stirng::iterator 来遍历string对象。

1. 使用[ ]遍历string对象

重载[ ]让string对象的访问和数组没有区别:

a = "abcdefg";
for (int i = 0; i < a.size(); ++i)
{
	a[i] += 1;
	cout << a[i];
}

2. 使用迭代器来遍历string对象

string的迭代器可以当指针使用:

a = "abcdefg";
string::iterator it = a.begin();
while (it != a.end())
{
	cout << *it; //string的迭代器可以当指针使用。
	++it;
}


使用迭代器来遍历string对象的最大优势在于:可以使用范围for。

上面代码中auto后面的e是临时变量,不会对原字符串造成改变


只有auto + &才能修改原字符串

六、string对象的修改

0. string类中有关修改的函数

1. 追加

追加:
operator +=()在字符串后追加字符串/string对象/字符。
push_back()在字符串后尾插字符。
append()在字符串后追加一个字符串

a. operator +=()

        重载+=让我们可以在字符串后随意追加字符串/string对象/字符,一般情况下有operator +=即可。


string a("abcdefg");
a += "higk";
a += 'l';
string b("mn");
a += b;
cout << a << endl;

b. append()

        append()主要用于一些特殊情况:追加某个字符串的一部分、追加某个字符n次。


string a = "abcdefghijklmno";
string c("uvw");
a.append(c);
cout << a << endl;
a.append("uvwxy", 3, 4); //尾插一个字符串的一部分,下标从0开始,左闭右闭
a.append("z123", 1);     //尾插一个字符串的一部分,取其n个字符
a.append(3, '1');        //尾插 n个相同的字符 
cout << a << endl; 

2. 插入

一般来说insert只用于要在字符串中间插入内容时。用的比较少。

插入:
insert在指定下标处插入一个字符串。
string a = "abcdefghigklmnopqrstuvwxyz111";
a.insert(2, "123"); //在指定下标处插入一个字符串。
cout << a << endl;
a.insert(5, "123456", 3, 5); //在指定下标处插入一个字符串的一部分,下标从0开始,左闭右闭
cout << a << endl;
a.insert(8, "78910", 3); //在指定下标处插入一个字符串的一部分,取其n个字符

3. 删除

删除:
erase删除指定位置开始的n个字符。
a = "ab123456789cdefghigklmnopqrstuvwxyz111";
a.erase(2, 9); //删除指定下标开始的n个字符。
cout << a << endl;
a.erase(25);    //删除指定下标后的所有字符。
cout << a << endl;
int n = 3;
a.erase(a.begin() + n);    //删除下标为n的字符
cout << a << endl;

七、string对象的常用操作

0. string对象的操作函数

其中copy()完全可以使用 operator =() 来替代,compare()也可以使用operator >()来替代。


常用的操作函数只有四个:

c_str()返回C格式字符串(char* )
find()从前往后查找子串,返回起始位置的下标
rfind() 从后往前查找子串,返回起始位置的下标
substr()截取子串,并返回一个string对象

1. c_str()

        返回一个 const char* 指针,该指针指向一个和string对象有效内容相同的char数组,且是以'\0'结尾。该函数的作用是获取一个适用于C语言库函数的C风格字符串

string a;
a = "abcdefgdefg";
cout << a.c_str() << endl;      // 返回一个char*指向的字符数组

2. find() 和 rfind()

        都是用来查找子串的不过find()是从前往后找,rfind()是从后往前找。找到了就立即返回子串起始位置的下标,没找到就返回string::npos(约为42亿9千万)。

string a = "abcdefgdefg";
cout << a.find("defg") << endl; //查找子串,返回起始位置的下标
if(a.find("defgl") == string::npos) //找不到返回string::npos(约为42亿9千万);
	cout << "未找到该子串" << endl;

cout << a.find("def", 3) << endl;//查找子串,从主串的第n个位置开始找。
cout << a.find("def", 4) << endl;//查找子串,从主串的第n个位置开始找。
cout << a.rfind("def", 4) << endl;//从主串的第n个位置开始从后往前查找子串。

八、字符串和数字间的转换

以下函数都是string的非成员函数,不能通过对象来调用。

to_string()将数字转为字符串
stoi()将string对象转为整数 (只能接受string对象)
stod()将string对象转为浮点数 (只能接受string对象)
atoi()将字面字符串转为整数 (只能接受常量字符串)
atof()将字面字符串转为浮点数(只能接受常量字符串)
		//to_string()函数:将数字转为字符串
		cout << "---------------------------" << endl;
		double a = 1234.5678;
		string s = std::to_string(a);
		cout << s << endl;

		//stoi():将字符串转为整数
		int b = stoi(s);
		cout << b << endl;

		//stod():将字符串转为浮点数
		double c = std::stod(s);
		printf("%lf\n", c);  //注意cout默认输出两位小数,所以在输出浮点数时最好使用printf()

		//atoi():将字面字符串转为整数
		const char* ss = "2345678";
		b = atoi(ss);
		cout << b << endl;
		//atof():将字面字符串转为浮点数
		c = atof("1234.5678");
		printf("%f\n", c);

拓展】

1:operator +

重载+ 让string对象能自由的拼接字符/字符串/其他string对象:

string firstlevel("com");
string secondlevel("cplusplus");
string scheme("http://");
string hostname;
string url;

hostname = "www." + secondlevel + '.' + firstlevel;
url = scheme + hostname;

std::cout << "网址:" + url + '\n';

2:重载比较运算符

重载比较运算符 让string对象能和 字符串字符串/其他string对象 进行字典序比较(逐个按ASCII码比较):

string s1 = "abcd";
string s2 = "abcde";
cout << (s1 == "a") << endl;

cout << (s1 > s2) << endl;
cout << (s1 >= "abcd") << endl;
		
cout << (s1 < s2) << endl;
cout << (s1 <= s2) << endl;

3:按行输入

        cin >> 是以空格进行分隔的,当我们希望输入一句英文时,使用cin >> 却只能接收到一个单词。所以这个时候我们就需要使用按行输入了:getline()


  • 第一个参数是istream对象,传入std::cin即可。
  • 第二个参数是用来接收的string对象。
  • 第三个参数是控制输入结束的字符,不传该参数就默认以回车结束。

string str;
getline(cin, str, '.'); //按行输入,指定以.结束。
cout << str << endl;

4:判断字符是字母还是数字

  • isalpha() :用来判断一个字符是不是字母。

  • isdigit() :用来判断一个字符是不是数字。


        如果记不住,自己写一个也很快,判断是否是字母就比较字符是否大于等于'a'/'A',小于等于'z'/'Z',判断是否是字母就比较字符是否大于等于'0',小于等于'9' 。或用它们的ASCII码:48 65 97 。


练习】

1:将字符串中的空格替换为%20

	{
		// 法一:倒着找到后先删除后插入
		string s1("hello world lin");
		for (int i = s1.size(); i >= 0; i--)
		{
			if (s1[i] == ' ')
			{
				s1.erase(i, 1);
				s1.insert(i, "%20");
			}
		}
		// 法二:开一个新字符串
		string s2;
		for (int i = 0; i < s1.size(); i++)
		{
			if (s1[i] == ' ')
				s2 += "20%";
			else
				s2 += s1[i];
		}
		cout << s1 << endl;
		cout << s2 << endl;
	}

2:获取文件后缀

	{
		// 用find找子串,用substr获取子串。
		string file_path = "test.cpp.zip.tar";
		size_t index = file_path.find(".");
		size_t index1 = file_path.rfind("."); // 从结尾开始找
		string suffix = file_path.substr(index);
		string suffix1 = file_path.substr(index1);
		cout << "使用find获取文件所有后缀:" << suffix << endl;
		cout << "使用rfind获取文件真后缀:" << suffix1 << endl;
	}

源代码】

#include<iostream>
#include<string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	std::ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	// string类的构造函数
	{
		//string() (重点)	构造空的string类对象,即空字符
		//string(const char* s) (重点)	用字符数组来构造string类对象
		//string(const string & s) (重点)	拷贝构造函数
		//string(size_t n, char c)	用n个c字符来构造string类对
		string a;  //注意空字符串的创建不是string a(); 这是在声明一个返回值为string 的无参函数。
		string b("abc"); //使用字面字符串来构造对象
		string c(b);     //拷贝构造
		string d(3, 'a');

		string e("1abcdefg", 1);
		string f(e, 0);
		string g("1abcdefg", 1, 5);
		string h(e, 0, 3);

		cout << a << endl;
		cout << b << endl;
		cout << c << endl;
		cout << d << endl;
		cout << e << endl;
		cout << f << endl;
		cout << e << endl;
		cout << f << endl;
	}

	// 赋值运算符重载
	{
		//string& operator= (const string & str);
		//string & operator= (const char* s);
		//string& operator= (char c);
		cout << "---------------------------" << endl;
		string a("abcd");
		string b("bcde");
		string c = b; // 注意这是在调用构造和拷贝构造函数
		a = b;
		cout << a << endl;
		a = "fghi";
		cout << a << endl;
		a = 'j';
		cout << a << endl;
	}

	// 有关容量的操作
	{
		//	size(重点)	返回字符串有效字符长度
		//	length	        返回字符串有效字符长度
		//	capacity	    返回空间总大小
		//	empty(重点)	检测字符串是否为空串,是返回true,否则返回false
		//	clear(重点)	清空有效字符
		//	reserve(重点)	为字符串预留空间
		//	resize(重点)	设置字符串长度,用指定字符填充多出来的位置
		cout << "---------------------------" << endl;
		string a("abcdefg");
		cout << a.size() << endl;
		cout << a.length() << endl;
		cout << a.capacity() << endl;
		//判空
		cout << "empty? --" << a.empty() << endl;
		//清空字符串
		a.clear(); 
		cout << "a.clear();" << endl;
		cout << "empty? --" << a.empty() << endl;
		cout << "size:" << a.size() << endl;
		cout << "capacity:" << a.capacity() << endl;
		//预留空间
		a.reserve(50);
		cout << "a.reserve(50);" << endl;
		cout << "capacity:" << a.capacity() << endl;
		//设置字符串长度
		a = "abcdefg";
		cout << "size:" << a.size() << " a:" << a << endl;
		a.resize(20);
		cout << "a.resize(20);" << endl;
		cout << "size:" << a.size() << " a:" << a << endl; //string对象的打印不是遇到'\0'终止,但'\0'不会被显示
		//设置字符串长度,用指定字符填充多出来的位置
		a.resize(30, '1');
		cout << "a.resize(30, '1')" << endl;
		cout << "size:" << a.size() << " a:" << a << endl;

	}

	//string对象的访问 遍历字符串
	{
		cout << "---------------------------" << endl;
		string a("abcdefg");
		cout << a << endl; //打印整个字符串(<<的重载)
		cout << a[0] << endl;
		cout << a.at(1) << endl;
		
		cout << *a.begin() << endl;
		cout << *(a.end()-1) << endl; 
		//end()是最后一位的下一个位置,字符串里指向'\0'
		
		// 1. 使用迭代器遍历字符串
		a = "abcdefg";
		string::iterator it = a.begin();
		while (it != a.end())
		{
			cout << *it; //string的迭代器可以当指针使用。
			++it;
		}
		putchar(10);
		
		// 2. 使用[]来遍历字符串
		a = "abcdefg";
		for (int i = 0; i < a.size(); ++i)
		{
			a[i] += 1;
			cout << a[i];
		}
		putchar(10);

		// 3. 使用迭代器+范围for来遍历字符串
		a = "abcdefg";
		for (auto e : a) //注意这里的e是临时变量不会对原字符串造成改变
		{
			e += 1;
			cout << e;
		}
		putchar(10);
		cout << a << endl;

		// auto + &才能修改原字符串
		a = "abcdefg";
		for (auto& e : a) 
		{
			e += 1;
			cout << e;
		}
		putchar(10);
		cout << a << endl;
	}

	//string对象的修改
	{
	//追加
		//operator+=(重点)	在字符串后追加字符串/string对象/字符
		//push_back	        在字符串后尾插字符
		//append(重点)     	在字符串后追加一个字符串
		cout << "---------------------------" << endl;
		string a("abcdefg");
		a += "higk";
		a += 'l';
		string b("mn");
		a += b;
		cout << a << endl;
		a.push_back('o');  //尾插一个字符
		cout << a << endl;
		a.append("pqrst"); //尾插一个字符串
		a = "abcdefghijklmno";
		string c("uvw");
		a.append(c);
		cout << a << endl;
		a.append("uvwxy", 3, 4); //尾插一个字符串的一部分,下标从0开始,左闭右闭
		a.append("z123", 1);     //尾插一个字符串的一部分,取其n个字符
		a.append(3, '1');        //尾插 n个相同的字符 
		cout << a << endl; 
	//插入 insert
		a = "abcdefghigklmnopqrstuvwxyz111";
		a.insert(2, "123"); //在指定下标处插入一个字符串。
		cout << a << endl;
		a.insert(5, "123456", 3, 5); //在指定下标处插入一个字符串的一部分,下标从0开始,左闭右闭
		cout << a << endl;
		a.insert(8, "78910", 3); //在指定下标处插入一个字符串的一部分,取其n个字符
		cout << a << endl;
	//删除 erase
		a = "ab123456789cdefghigklmnopqrstuvwxyz111";
		a.erase(2, 9); //删除指定位置开始的n个字符。
		cout << a << endl;
		a.erase(25);    //删除指定位置后的所有字符。
		cout << a << endl;
		int n = 3;
		a.erase(a.begin() + n);    //删除下标为n的字符
		cout << a << endl;
	}

	//string对象的常用操作
	{
		//c_str(重点) 返回C格式字符串
		//find(重点)	  从前往后查找子串,返回起始位置的下标
		//rfind	      从后往前查找子串,返回起始位置的下标
		//substr	  截取子串,并返回一个string对象
		cout << "---------------------------" << endl;
		string a;
		a = "abcdefgdefg";
		cout << a.c_str() << endl;      // 返回一个char*指向的字符数组
		
		a = "abcdefgdefg";
		cout << a.find("defg") << endl; //查找子串,返回起始位置的下标
		if(a.find("defgl") == string::npos) //找不到返回npos
			cout << "未找到该子串" << endl;

		cout << a.find("def", 3) << endl;//查找子串,从主串的第n个位置开始找。
		cout << a.find("def", 4) << endl;//查找子串,从主串的第n个位置开始找。
		cout << a.rfind("def", 4) << endl;//从主串的第n个位置开始从后往前查找子串。

		cout << a.substr(7) << endl;    //从主串的第n个位置开始截取字符
		cout << a.substr(7, 2) << endl; //从主串的第n个位置开始截取字符,截取i个字符。
	}

	//string对象和数字间的转换
	{
		//to_string()函数:将数字转为字符串
		cout << "---------------------------" << endl;
		double a = 1234.5678;
		string s = std::to_string(a);
		cout << s << endl;

		//stoi():将字符串转为整数
		int b = stoi(s);
		cout << b << endl;

		//stod():将字符串转为浮点数
		double c = std::stod(s);
		printf("%lf\n", c);  //注意cout默认输出两位小数,所以在输出浮点数时最好使用printf()

		//atoi():将字面字符串转为整数
		const char* ss = "2345678";
		b = atoi(ss);
		cout << b << endl;
		//atof():将字面字符串转为浮点数
		c = atof("1234.5678");
		printf("%f\n", c);
	}


	// operator +
	{
		cout << "---------------------------" << endl;
		string firstlevel("com");
		string secondlevel("cplusplus");
		string scheme("http://");
		string hostname;
		string url;

		hostname = "www." + secondlevel + '.' + firstlevel;
		url = scheme + hostname;

		std::cout << "网址:" + url + '\n';
	}
	// 比较运算符:逐个按ASCII码比较
	{
		cout << "---------------------------" << endl;
		string s1 = "abcd";
		string s2 = "abcde";
		cout << (s1 == "a") << endl;

		cout << (s1 > s2) << endl;
		cout << (s1 >= "abcd") << endl;
		
		cout << (s1 < s2) << endl;
		cout << (s1 <= s2) << endl;

	}

	// 按行输入 : getline(cin, str)
	{
		cout << "---------------------------" << endl;
		string str;
		getline(cin, str, '.'); //按行输入,指定以.结束。
		cout << str << endl;
	}

	// 练习1:实现字符串替换函数:
	{
		// 法一:倒着找到后先删除后插入
		string s1("hello world lin");
		for (int i = s1.size(); i >= 0; i--)
		{
			if (s1[i] == ' ')
			{
				s1.erase(i, 1);
				s1.insert(i, "%20");
			}
		}
		// 法二:开一个新字符串
		string s2;
		for (int i = 0; i < s1.size(); i++)
		{
			if (s1[i] == ' ')
				s2 += "20%";
			else
				s2 += s1[i];
		}
		cout << s1 << endl;
		cout << s2 << endl;
	}

	// 练习2:获取文件后缀
	{
		// 用find找子串,用substr获取子串。
		string file_path = "test.cpp.zip.tar";
		size_t index = file_path.find(".");
		size_t index1 = file_path.rfind("."); // 从结尾开始找
		string suffix = file_path.substr(index);
		string suffix1 = file_path.substr(index1);
		cout << "使用find获取文件所有后缀:" << suffix << endl;
		cout << "使用rfind获取文件真后缀:" << suffix1 << endl;
	}

	// C++中涉及到char*的操作以'\0'为结尾,涉及string的操作以size的长度算结尾。
	{
		cout << "---------------------------" << endl;
		string s3 = "asdfg ";
		s3 += '\0';
		s3 += "hjkl";
		cout << s3 << endl;
		cout << s3.c_str() << endl;

		string s4 = s3;
		cout << s4 << endl;
	}
	return 0;
}


------------------------END-------------------------

才疏学浅,谬误难免,欢迎各位批评指正。

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

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

相关文章

最新SpringBoot项目地方废物回收机构管理系统

采用技术 最新SpringBoot项目地方废物回收机构管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 登录页面 后端管理员 管理员首页 员工管理 设…

机器学习批量服务模式优化指南

原文地址&#xff1a;optimizing-machine-learning-a-practitioners-guide-to-effective-batch-serving-patterns 2024 年 4 月 15 日 简介 在机器学习和数据分析中&#xff0c;模型服务模式的战略实施对于在生产环境中部署和操作人工智能模型起着至关重要的作用。其中&…

软考之零碎片段记录(二十九)+复习巩固(十七、十八)

学习 1. 后缀式&#xff08;逆波兰式&#xff09; 2. c/c语言编译 类型检查是语义分析 词法分析。分析单词。如单词的字符拼写等语法分析。分析句子。如标点符号、括号位置等语言上的错误语义分析。分析运算符、运算对象类型是否合法 3. java语言特质 即时编译堆空间分配j…

Linux服务器常用命令总结

view查找日志关键词 注意日志级别&#xff0c;回车后等一会儿&#xff0c;因为文件可能比较大加载完需要时间 当内容显示出来后&#xff0c;使用“/关键词”搜索 回车就能搜到&#xff0c;n表示查找下一个&#xff0c;N表示查找上一个 find 查找 find Family -name book …

文本嵌入的隐私风险:从嵌入向量重建原始文本的探索

随着大型语言模型&#xff08;LLMs&#xff09;的广泛应用&#xff0c;文本嵌入技术在语义相似性编码、搜索、聚类和分类等方面发挥着重要作用。然而&#xff0c;文本嵌入所蕴含的隐私风险尚未得到充分探讨。研究提出了一种控制生成的方法&#xff0c;通过迭代修正和重新嵌入文…

jsp校园商城派送系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 校园商城派送系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用serlvetdaobean mvc 模式&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.…

第12章 消息服务 ❤❤❤❤

第12章 消息服务 12.1 JMS_ActiveMQ1. 简介2. ActiveMQ安装Linux安装命令问题1:网页访问不了问题2: 修改密码 3. 整合SpringBoot3.1 依赖3.2 配置3.3 JmsComponent 组件3.4 测试 12.2 AMQP_RabbitMQ1. 简介2. RabbitMQ2.1 Erlang环境安装(略)2.2 安装RabbitMQ(❤❤❤❤)2.3 启动…

FreeRTOS学习——FreeR TOS队列(下)

本篇文章记录我学习FreeRTOS的队列的相关知识&#xff0c;在此记录分享一下&#xff0c;希望我的分享对你有所帮助。 FreeRTOS学习——FreeRTOS队列&#xff08;上&#xff09;-CSDN博客 一、FreeRTOS队列的创建 &#xff08;一&#xff09;、函数原型 在使用队列之前必须先创…

【大数据】学习笔记

文章目录 [toc]NAT配置IP配置SecureCRT配置PropertiesTerminal Java安装环境变量配置 Hadoop安装修改配置文件hadoop-env.shyarn-env.shslavescore-site.xmlhdfs-site.xmlmapred-site.xmlyarn-site.xml 环境变量配置 IP与主机名映射关系配置hostname配置映射关系配置 关闭防火墙…

OpenCV(四)—— 车牌号识别

本节是车牌识别的最后一部分 —— 车牌字符识别&#xff0c;从一个完整的车牌图片到识别出车牌上的字符大致需要如下几步&#xff1a; 预处理&#xff1a;将车牌图片灰度化、二值化&#xff0c;并去除识别时的干扰因素&#xff0c;比如车牌铆钉字符分割&#xff1a;将整个车牌…

基于springboot+vue+Mysql的影城管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

CATO原理中的数学与魔术(七)——Baby Hummer的拓展二

在上一篇文章中&#xff0c;我们介绍了《Baby Hummer》的两个拓展&#xff0c;从表演的形式台词&#xff0c;到呈现的策略&#xff0c;都有一定的改进&#xff0c;相关内容请戳&#xff1a; CATO原理中的数学与魔术&#xff08;六&#xff09;——Baby Hummer的拓展一 CATO原理…

WebSocket 多屏同显和异显

介绍 多屏同显:通过在一个应用上进行操作之后,另一个应用也能跟着一起发生改变,例如app1播放了晴天这首音乐,那么app2也要同步播放这首音乐,确保所有屏幕显示的内容完全相同。多屏异显:每个屏幕可以显示不同的内容,或者在内容更新时存在一定的延迟,而不需要严格保持同步…

MLP手写数字识别(1)-MNIST数据集下载与可视化(tensorflow)

1.下载与查看MNIST数据集 from keras.datasets import mnist(x_train_image,y_train_label),(x_test_image,y_test_label) mnist.load_data() print("train images:",x_train_image.shape) print("test images:",x_test_image.shape) print("train …

83、动态规划-打家劫舍

思路&#xff1a; 首先使用递归方式求出最优解。从每个房屋开始&#xff0c;分别考虑偷与不偷两种情况&#xff0c;然后递归地对后续的房屋做同样的决策。这种方法确保了可以找到在不触发警报的情况下可能的最高金额。 代码如下&#xff1a; public static int rob(int[] nu…

【多变量控制系统 Multivariable Control System】(2)给定系统转换方程,绘制奈奎斯特图【新加坡南洋理工大学】

一、系统转换方程 系统的转换方程 G(s) 和回馈矩阵 K(s) 由下2式给出&#xff1a; 二、从转换方程推出系统矩阵A和B from scipy.signal import tf2ss# Convert to state-space representation A, B, C, D tf2ss([1], [1, -2, 1])print("A matrix:", A) print(&quo…

【Unity】在空物体上实现 IPointerClickHandler 不起作用

感谢Unity接口IPointerClickHandler使用说明_哔哩哔哩_bilibiliUnity接口IPointerClickHandler使用说明, 视频播放量 197、弹幕量 0、点赞数 3、投硬币枚数 2、收藏人数 2、转发人数 0, 视频作者 游戏创作大陆, 作者简介 &#xff0c;相关视频&#xff1a;在Unity多场景同时编辑…

基于Springboot的教学资源共享平台(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的教学资源共享平台&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

VsCode | 修改首页启动页 Logo

VsCode | 修改首页启动页 Logo 最终效果&#xff1a; 插件的安装 先安装插件 Custom CSS and JS Loader 插件配置 Ctrl Shift P 输入 打开用户设置&#xff0c;在末尾添加 "vscode_custom_css.imports": [""]下载 Logo 下载 Logo 点我下载 引入…

使用D3.js进行数据可视化

D3.js介绍 D3.js是一个流行的JavaScript数据可视化库&#xff0c;全称为Data-Driven Documents&#xff0c;即数据驱动文档。它以数据为核心&#xff0c;通过数据来驱动文档的展示和操作。D3.js提供了丰富的API和工具&#xff0c;使得开发者能够创建出各种交互式和动态的数据可…