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

目录

〇、概念

一、string类的构造函数

二、赋值运算符重载

三、有关容量的操作

四、string对象的访问

五、遍历string对象的字符数组

六、string对象的修改

七、string对象的常用操作

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

拓展】

练习】

源代码】



〇、概念

1. string类是什么?

string类的底层是一个支持动态增长的char数组,它用new来动态分配内存,因此string也被称为变长字符串。

 

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()来提前开好一片空间,就不需要频繁的扩容了。

        当所给值小于容器当前的 capacity时,什么也不做(不会缩小容量)。

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. operator [ ] 和 at()

        operator [ ] 和 at() 返回的都是string对象的字符数组的i下标处的引用,所以可以用来修改string对象的字符数组。


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

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


string a("abcdefghijklmn");cout << "使用[]遍历string对象的字符串" << endl;
for (int i = 0; i < a.size(); i++)
{//operator [ ]是string对象的字符数组的i下标处的引用。a[i]++;cout << a[i];
}	
putchar(10);cout << "使用at()遍历string对象的字符串" << endl;
for (int i = 0; i < a.size(); i++)
{// at() 返回的也是string对象的字符数组的i下标处的引用a.at(i)++;cout << a.at(i);
}
putchar(10);

3. string::iterator

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


五、遍历string对象的字符数组

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

1. 使用[ ]遍历string对象的字符数组

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

//operator [ ] 和 at() 返回的都是string对象的字符数组的i下标处的引用,所以可以用来修改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";
a.append("lmn");
string c("opq");
a.append(c);
cout << a << endl;a.append("rstuvw", 3); // 尾插一个字符串,取其前n个字符
cout << a << endl;
a.append("rstuvwxyz123", 3, 8); // 尾插一个字符串,从下标n开始,取其前i个字符
cout << a << endl;
a.append(3, ' '); //尾插n个相同的字符
cout << a << endl;

2. 插入

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

插入:
insert在指定下标处插入一个字符串。
string a = "abcdefghijklmnopqrstuvwxyz  ";
a.insert(0, "123"); // 在n下标处插入一个字符串
cout << a << endl;
a.insert(3, "456789", 3); // 在n下标处插入,一个字符串的前n个字符
cout << a << endl;
a.insert(6, "7891011", 3, 5); //在n下标处插入,一个字符串从下标n开始的n个字符
cout << a << endl;

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个位置开始从后往前查找子串。

3. substr() 

从下标pos开始,截取len个字符,不传len就默认截取到结尾。然后返回一个string对象。      


string a = "abcdefgdefg";
cout << a.substr(1) << endl;        //从下标1的字开始截取到结尾
cout << a.substr(1).size() << endl; cout << a.substr(0, 3) << endl;     //从下标0的字开始截取3个字符

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

以下函数都是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%";elses2 += 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类对cout << "----------string类的构造函数---------" << endl;string a; //string a(); 不是在调用构造器创建一个空的string对象,而是在声明一个返回值为string的无参函数。string b("abcd");  //使用字符数组构造string c(b);  //拷贝构造string d(3, 'a');const char* e = "abcdefg";string f(e);char g[] = { 'a', 'b' }; //char数组结尾一定要加一个'\0'string h(g);cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;cout << e << endl;cout << f << endl;cout << g << endl;cout << h << endl;}// 赋值运算符重载{//string& operator= (const string & str);//string & operator= (const char* s);//string& operator= (char c);cout << "----------赋值运算符重载---------" << endl;string a("abcdefg");string b = a;  //区分构造和赋值,这里b还没有创建所以调用的是构造函数b = a;  //这里b已经创建,所以调用的是赋值运算符重载cout << b << endl;b = "abcd";cout << b << endl;b = 'a';cout << b << 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;// 判空:根据size()判断cout << a.empty() << endl;// 不同于字符数组是以'\0'来判断结尾,stirng对象判断字符串的结尾是根据size属性。// 清空字符串:修改size()a.clear();cout << "a.clear();" << endl;cout << a.size() << endl;cout << a.empty() << endl;// 为stirng对象预留空间,修改capacity = n + 1;a.reserve(30);cout << "a.reserve(30);" << endl;cout << a.capacity() << endl;cout << a.size() << endl;// 设置string对象的有效长度,多出来的长度默认用'\0'填充cout << a << " 的长度: " << a.size() << endl;a.resize(10);cout << "a.resize(20);" << endl;cout << a << " 的长度: " << a.size() << endl;a.resize(20, '.');cout << "a.resize(20, '.');" << endl;cout << a << " 的长度: " << a.size() << endl;cout << "string对象是以size来判断结尾的,看不到的字符可能是'\0'";}//访问string对象的字符数组{cout << "---------访问string对象的字符数组--------" << endl;string a;a = "abcd";cout << a << endl; //重载<< 让我们能自己打印string对象的内容。cout << a[0] << endl;cout << a.at(1) << endl;cout << *a.begin() << endl;cout << *(a.begin() + 2) << endl;string::iterator it = a.end()-1;cout << *it << endl;}//遍历string对象的字符数组{cout << "---------遍历string对象的字符数组--------" << endl;string a("abcdefghijklmn");cout << "operator [ ]和at() 返回的是string对象的字符数组的i下标处的引用。" << endl;cout << "使用[]遍历string对象的字符串" << endl;for (int i = 0; i < a.size(); i++){//operator [ ]返回的是string对象的字符数组的i下标处的引用。a[i]++;cout << a[i];}	putchar(10);cout << "使用at()遍历string对象的字符串" << endl;for (int i = 0; i < a.size(); i++){// at() 返回的也是string对象的字符数组的i下标处的引用a.at(i)++;cout << a.at(i);}putchar(10);cout << "使用迭代器遍历string对象的字符串" << endl;for (string::iterator i = a.begin(); i != a.end(); i++){(*i)++; //++的优先级大于*,所以要使用()cout << *i;}putchar(10);string::iterator it = a.begin();while (it != a.end()){(*it)++;cout << *it;it++;    //如果会忘记写it++,建议使用for循环}putchar(10);cout << "使用范围for+迭代器遍历string对象的字符串" << endl;//不使用&的范围for是无法修改原数组的cout << "a. 使用范围for访问,不用加&" << endl;for (auto e : a){e++; //这里的e不过是一个临时变量。cout << e;}putchar(10);cout << a << endl;//使用&的范围for才能修改原数组的cout << "b. 使用范围for修改,要加&" << endl;for (auto& e : a){e++;cout << e;}putchar(10);cout << a << endl;}//string对象的修改{cout << "-----------string对象的修改-----------" << endl;//追加//operator+=(重点)	在字符串后追加字符串/string对象/字符//push_back	        在字符串后尾插字符//append(重点)     	在字符串后追加一个字符串cout << "-----------追加-----------" << endl;string a("abc");a += 'd';a += "efg";string b("hij");a += b;cout << a << endl;a.push_back('k'); // 只能尾插一个字符。//a.push_back("lmn");a.append("lmn");string c("opq");a.append(c);cout << a << endl;a.append("rstuvw", 3); // 尾插一个字符串,取其前3个字符cout << a << endl;a.append("rstuvwxyz123", 3, 6); // 尾插一个字符串,从下标3开始,取其前6个字符cout << a << endl;a.append(3, ' '); //尾插3个' '字符cout << a << endl;//插入 insertcout << "-----------插入-----------" << endl;a = "abcdefghijklmnopqrstuvwxyz  ";a.insert(0, "123"); // 在0下标处插入一个字符串cout << a << endl;a.insert(3, "456789", 3); // 在3下标处插入,一个字符串的前3个字符cout << a << endl;a.insert(6, "4567891011", 3, 5); //在6下标处插入,一个字符串从下标3开始的5个字符cout << a << endl;//删除 erasecout << "-----------删除-----------" << endl;a = "12345678910abcdefghijklmnopqrstuvwxyz   .";a.erase(37, 3); //删除下标37开始的3个字符cout << a << endl;a.erase(10); //删除下标10后的所有字符cout << a << endl;a.erase(a.begin() + 9); //删除下标为9的字符cout << a << endl;}//string对象的常用操作{//c_str(重点) 返回C格式字符串//find(重点)	  从前往后查找子串,返回起始位置的下标//rfind	      从后往前查找子串,返回起始位置的下标//substr	  截取子串,并返回一个string对象cout << "---------------------------" << endl;string a;a = "abcdefgdefg";cout << a.c_str() << endl;cout << a.find("defg") << endl; //找到就返回在主串中起始位置的下标if (a.find("defgh") == string::npos) //找不到返回string::npos(约为42亿9千万)cout << "未找到" << endl;cout << a.rfind("defg") << endl; //从后往前找。cout << a.rfind("defg", 3) << endl; //从第4个字符开始,从后往前找。cout << a.rfind("defg", 2) << endl; //从第3个字符开始,从后往前找。a = "abcdefgdefg";cout << a.substr(1) << endl;        //从下标1的字开始截取到结尾cout << a.substr(1).size() << endl; cout << a.substr(0, 3) << endl;     //从下标0的字开始截取3个字符}//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%";elses2 += 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.hqwc.cn/news/681980.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IP地址证书的详细申请步骤

IP地址证书申请的条件有两个&#xff0c;一个是此IP必须是公网IP&#xff0c;另一个是IP的80和443端口必须允许短暂开放。满足这两个条件才能为其部署SSL证书。 IP地址ssl证书申请网址链接https://www.joyssl.com/certificate/select/ip_certificate.html?nid16 1 访问提供IP…

Hadoop3:HDFS的Shell操作(常用命令汇总)

一、简介 什么是HDFS的Shell操作&#xff1f; 很简单&#xff0c;就是在Linux的终端&#xff0c;通过命令来操作HDFS。 如果&#xff0c;你们学习过git、docker、k8s&#xff0c;应该会发现&#xff0c;这些命令的特点和shell命令非常相似 二、常用命令 1、准备工作相关命令…

哈迪斯2发售时间 哈迪斯游戏攻略 苹果电脑怎么玩《哈迪斯2》

这两年肉鸽游戏大爆发&#xff0c;只要不是美女抽卡养成那基本上就是肉鸽了&#xff0c;但是真正让玩家口服心服的肉鸽游戏不多&#xff0c;《哈迪斯》绝对算是其中一款。 近日让玩家期待已久的肉鸽大作&#xff0c;晶体管工作室制作的《哈迪斯》正统续作《哈迪斯2》终于开卖了…

关于模型参数融合的思考

模型参数融合通常指的是在训练过程中或训练完成后将不同模型的参数以某种方式结合起来&#xff0c;以期望得到更好的性能。这种融合可以在不同的层面上进行&#xff0c;例如在神经网络的不同层之间&#xff0c;或者是在完全不同的模型之间。模型参数融合的目的是结合不同模型的…

代码随想录第四十三天|最后一块石头的重量 II 、目标和

题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 代码如下&#xff1a; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 代码如下&#xff1a;

ABAP 删除销售订单增强 MV45AFZB

1.业务背景 SAP的订单删除&#xff0c;是直接从数据库里面物理删除&#xff0c;这个设计有点恶心&#xff0c;我要查询这个单&#xff0c;都没有办法查询了。业务上要求&#xff0c;如何限制VA02上对销售订单的删除。 2.增强点&#xff1a;MV45AFZB SE38进入到MV45AFZB&#x…

小红书流量机制解析

小红书流量机制解析 前言 大家好&#xff0c;我自2020年5月起&#xff0c;开始专注于小红书平台&#xff0c;帮助品牌商家在小红书上经营。在这段时间里&#xff0c;我深入研究了小红书的流量机制&#xff0c;并结合自己的实践经验&#xff0c;为大家带来了这份全网最硬核的小…

springboot+vue实现登录注册,短信注册以及微信扫描登录

说明&#xff1a;微信扫描登录需要微信注册--要钱&#xff0c;感谢尚硅谷提供的免费接口&#xff1b;短信注册需要阿里云的注册很麻烦并且短信费&#xff0c;没有接口&#xff0c;所以不打算实现&#xff0c;不过能做出效果。 目录 一、建立数据库 二、后端idea实现接口 1.…

【MySQL数据库开发设计规范】之基础规范

欢迎点开这篇文章&#xff0c;自我介绍一下哈&#xff0c;本人笔名姑苏老陈&#xff0c;是一个JAVA开发老兵。 本文收录于 《MySQL数据库开发设计规范》专栏中&#xff0c;该专栏主要分享一些关于MySQL数据库开发设计相关的技术规范文章&#xff0c;定期更新&#xff0c;欢迎关…

【图书推荐】《图神经网络基础、模型与应用实战》

本书目的 详解PyTorch 图神经网络基础理论、模型与十多个应用案例&#xff0c;带领读者掌握图神经网络在自然语言处理、计算机视觉、推荐系统、社交网络4个领域的应用开发方法&#xff0c;丰富读者利用深度学习算法解决实际问题的能力。 本书案例 图卷积网络实现图注意力网络…

马蹄集oj赛(双周赛第二十六次)

目录 斐波那契数列的组合 三国杀 数列分段 小码哥的跳棋游戏新编 能量供应 小码哥爱数字 最小串 小船过河 摘果子 泼墨淋漓 很重的枪 小码哥的布阵指挥 斐波那契数列的组合 #include<bits/stdc.h> using namespace std;// 斐波那契数列 1 1 2 3 5 8 13 21 34…

##08 数据加载与预处理:PyTorch的心脏

文章目录 前言深入理解`torch.utils.data`数据集(Dataset)数据加载器(DataLoader)实战演练:创建自定义数据集数据转换(Transform)数据加载总结前言 在深度学习的宇宙中,数据是燃料,模型是发动机。而在PyTorch的世界中,torch.utils.data是加注燃料的机器,保证了数据能够高…