C++string类使用大全

 

目录

温馨提示:这篇文章有约两万字

什么是string类?

一. 定义和初始化string对象

1.string的构造函数的形式:

2.拷贝赋值运算符 

3.assign函数

二.string对象上的操作

1.读写string对象

2.读取未知数量的string对象

3.使用getline 读取一整行

 4.string对象的大小和容量:

​编辑

4.1string::size_type类型

5.string的字符串比较

5.1用关系运算符

5.2用compare函数

​编辑

6.string的加法

6.1两个string对象相加

6.2字面值和string对象相加

7 元素访问

7.1下标访问

7.2at函数

8.substr操作

9.insert函数

10.append 和replace函数

11.string的搜索操作

12 string的遍历:借助迭代器 或者 下标法

13. string的删除:erase()

14、 string的字符替换:

15. string的大小写转换:

16、 string的查找:find

17、 string的排序:sort(s.begin(),s.end())

18、 string的分割/截取字符串:strtok() & substr()

数值的转换

string 和数值之间的转换


温馨提示:这篇文章有约两万字

什么是string类?

在C++中,string是一个用于处理字符串的类,它属于C++标准库中的一部分。

string类提供了一种方便且安全的方式来处理字符序列,相比于C语言中的字符数组(即C-style strings)或字符指针,C++的string类提供了更多的功能和更好的安全性。

为标准库的一部分,string定义在命名空间std中。接下来的示例都假定已包含了下述代码:

#include <string>
using std::string;

一. 定义和初始化string对象

string对象可通过构造函数和拷贝赋值运算符来初始化string对象

我们可以先看看string的构造函数是如何初始化string对象的

1.string的构造函数的形式:

string str;//生成空字符串string s(str);//字符串s为str的副本string s(str, strbegin,strlen);
//将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值string s(cstr, char_len);
//以C_string类型cstr的前char_len个字符串作为字符串s的初值string s(num ,c);
//生成num个c字符的字符串string s(str, stridx);
//将字符串str中从下标stridx开始到字符串结束的位置作为字符串初值

我们看个例子


#include <iostream>
#include <string>
using namespace std;void test1()
{string str1;               //生成空字符串string str2("123456789");  //生成"1234456789"的复制品string str3("12345", 0, 3);//结果为"123"string str4("0123456", 5);  //结果为"01234"string str5(5, '1');       //结果为"11111"string str6(str2, 2);      //结果为"3456789"cout<<"str2:"<<str2<<endl;cout<<"str3:"<<str3<<endl;cout<<"str4:"<<str4<<endl;cout<<"str5:"<<str5<<endl;cout<<"str6:"<<str6<<endl;
}int main()
{test1();return 0;
}

2.拷贝赋值运算符 

string s1;
string s2=s1;//s2是s1的副本
string s3="hello";//s3是字面值"helo"的副本,除了那个空字符之外

3.assign函数

在C++的std::string类中,assign()函数用于给字符串赋值。这个函数有多种重载形式,可以接受不同类型的参数,以便从其他字符串、字符数组、单个字符或子字符串来分配内容。

以下是assign()函数的一些常见用法:

从另一个std::string对象赋值:

 std::string str1 = "Hello";  std::string str2;  str2.assign(str1); // str2 现在包含 "Hello" 

从C风格的字符串(字符数组)赋值:

 const char* cstr = "World";  std::string str;  str.assign(cstr); // str 现在包含 "World"

 从单个字符赋值,并指定重复次数:

 char ch = 'a';  std::string str;  str.assign(5, ch); // str 现在包含 "aaaaa" 

从另一个std::string的子字符串赋值:

 std::string str = "Hello, World!";  std::string subStr;  subStr.assign(str, 7, 5); // 从索引7开始,长度为5的子字符串,subStr 现在包含 "World" 

注意,在上面的例子中,子字符串的索引是从0开始的,并且长度参数指定了要复制的字符数(不包括结束的空字符)。

从迭代器范围赋值:

如果你的数据来自标准库容器(如std::vector或std::list),你可以使用迭代器来指定要复制的范围。但是,由于std::string本身不是基于迭代器的容器,这种用法并不常见。但如果你有一个字符类型的容器,并且想将其内容转换为std::string,这种方法可能会有用。

 std::vector<char> vec = {'H', 'e', 'l', 'l', 'o'};  std::string str;  str.assign(vec.begin(), vec.end()); // str 现在包含 "Hello" 

从初始化列表赋值(C++11及更高版本):

 std::string str;  str.assign({'a', 'b', 'c'}); // str 现在包含 "abc"  // 或者直接使用初始化列表构造函数  std::string anotherStr = {'d', 'e', 'f'}; // anotherStr 现在包含 "def" 

使用assign()函数可以灵活地给字符串分配新的内容,同时替换掉字符串中原有的内容。如果assign()函数接收的参数会导致新字符串的长度超过当前字符串的容量,那么std::string可能会重新分配内存以存储新的内容。

二.string对象上的操作

一个类除了要规定初始化其对象的方式外,还要定义对象上所能执行的操作。

其中,类既能定义通过函数名调用的操作,下面列举了string的大多数操作。

os<<s
//从is中读取字符串赋给s,字符串以空白分隔,返回isis>>s
//从is中读取一行赋给s,返回isgetline(is,s)
//从is中读取一行赋值给s,返回iss.empty()
//s为空返回true,否则返回falses.size()
//返回s中字符的个数s[n]
//返回s中第n个字符的引用,位置n从0计起s1+s2 
//返回s1和s2连接后的结果sl=s2 
//用s2的副本代替s1中原来的字符s1==s2 
s1!=s2
//如果s1和s2中所含的字符完全一样,则它们相等;string对象的相等性判断对字母的大小写敏感<,<=,>,
//利用字符在字典中的顺序进行比较,且对字母的大小写敏感

1.读写string对象

我们可以使用标准库中的iostream来读写int、double等内置类型的值。同样,也可以使用IO操作符读写string对象:

注意:要想编译下面的代码还需要适当的#include 语句和using声明

int main()
{
string s;//空字符串cin >>s;//将string对象读入s,遇到空白停止cout << s << endl;//输出s
return 0;
}

这段程序首先定义一个名为s的空string,然后将标准输入的内容读取到s中。在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。

如上所述,如果程序的输入是

    Hello World!

则输出将是

 Hello

输出结果中没有任何空格。

和内置类型的输入输出操作一样,string对象的此类操作也是返回运算符左侧的运算对象作为其结果。因此,多个输入或者多个输出可以连写在一起:

string s1, s2;
cin >>s1 >> s2;// 把第一个输入读到 s1中,第二个输入读到 s2中
cout << sl << s2 << endl;
//输出两个string对象

假设给上面这段程序输入与之前一样的内容

      Hello World!

输出将是

HelloWorld!

2.读取未知数量的string对象

下面编写一个类似的程序用了读取string对象:

#include<iostream
#include<string>
int main()
{
string word;
//反复读取,直至到达文件末尾
while (cin >> word)
{
//逐个输出单词,每个单词后面紧跟一个换行
cout << word << endl;
}
return 0;
}

在该程序中,读取的对象是string。

该条件负责在读取时检测流的情况,如果流有效,也就是说没遇到文件结束标记或非法输入,那么执行while语句内部的操作。

此时,循环体将输出刚刚从标准输入读取的内容。重复若干次之后,一旦遇到文件结束标记或非法输入循环也就结束了。

3.使用getline 读取一整行

有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用getline函数代替原来的>>运算符。

getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)。

getline只要一遇到换行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此。如果输入真的一开始就是换行符,那么所得的结果是个空string。

和输入运算符一样,getline 也会返回它的流参数。因此既然输入运算符能作为判断的条件,我们也能用getline的结果作为条件。

例如,可以通过改写之前的程序让它一次输出一整行,而不再是每行输出一个词了:

int main()
{
string line;
//每次读入一整行,直至到达文件末尾
while (getline(cin, line))
cout << line << endl;
return 0;
}


因为line中不包含换行符,所以我们手动地加上换行操作符。和往常一样,使用endl结束当前行并刷新显示缓冲区。

触发getline函数返回的那个换行符实际上被丢弃掉了,得到的string对象中并不包含该换行符。

 4.string对象的大小和容量:

  1. size()和length():返回string对象的字符个数,他们执行效果相同。
  2. max_size():返回string对象最多包含的字符数,超出会抛出length_error异常
  3. capacity():重新分配内存之前,string对象能包含的最大字符数
void test2()
{string s("1234567");cout << "size=" << s.size() << endl;cout << "length=" << s.length() << endl;cout << "max_size=" << s.max_size() << endl;cout << "capacity=" << s.capacity() << endl;}

4.1string::size_type类型

对于size函数来说,返回一个int或者返回一个 unsigned 似乎都是合情合理的。

但其实 size 函数返回的是一个string::size_type类型的值,下面就对这种新的类型稍作解释。

string类及其他大多数标准库类型都定义了几种配套的类型。这些配套类型体现了标准库类型与机器无关的特性,类型size_type 即是其中的一种。在具体使用的时候,通过作用域操作符来表明名字size_type 是在类string中定义的。

尽管我们不太清楚string::size_type 类型的细节,但有一点是肯定的:它是个无符号类型的值而且能足够存放下任何string对象的大小。所有用于存放 string 类的size 函数返回值的变量,都应该是string::size_type类型的。

过去,string::size_type 这种类型有点儿神秘,不太容易理解和使用。在C++11新标准中,允许编译器通过auto或者decltype来推断变量的类型:

auto len = line.size();// len的类型是string::size_type

由于size函数返回的是一个无符号整型数,因此切记,如果在表达式中混用了带符号数和无符号数将可能产生意想不到的结果。

例如,假设n是一个具有负值的int,则表达式s.size()<n的判断结果几乎肯定是true。这是因为负值n会自动地转换成一个比较大的无符号值。

如果一条表达式中已经有了size()函数就不要再使用int了,这样可以避免混用int和unsigned可能带来的问题。

5.string的字符串比较

5.1用关系运算符

string类定义了几种用于比较字符串的运算符。这些比较运算符逐一比较string对象中的字符,并且对大小写敏感,也就是说,在比较时同一个字母的大写形式和小写形相等性运算符(==和!=)分别检验两个string对象相等或不相等,string对象相等意味着它们的长度相同而且所包含的字符也全都相同。

关系运算符<、<=、>、>=分别检验一个string对象是否小于、小于等于、大于、大于等于另外一个string对象。上述这些运算符都依照(大小写敏感的)字典顺序:

  1. 如果两个string 对象的长度不同,而且较短string对象的每个字符都与较长string 对象对应位置上的字符相同,就说较短string 对象小于较长string对象。
  2. 如果两个string 对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。

下面是string 对象比较的一个示例:

string str ="Hello";
string phrase = "Hello World"
string slang = "Hiya";

根据规则1可判断,对象str小于对象phrase;根据规则2可判断,对象slang 既大于str也大于phrase。

5.2用compare函数

  另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。 
  他返回一个整数来表示比较结果,返回值意义如下:0:相等 1:大于 -1:小于 (A的ASCII码是65,a的ASCII码是97)

void test3()
{// (A的ASCII码是65,a的ASCII码是97)  // 前面减去后面的ASCII码,>0返回正值,<0返回负值,相同返回0  std::string A("aBcd");std::string B("Abcd");std::string C("123456");std::string D("123dfg");// "aBcd" 和 "Abcd"比较------ a < A  std::cout << "A.compare(B):" << A.compare(B) << std::endl;// "cd" 和 "Abcd"中的"bc"比较------- c > b  std::cout << "A.compare(2, 2, B, 1, 2):" << A.compare(2, 2, B, 1, 2) << std::endl;// "cd" 和 "Abcd"中的"cd"比较------- 相等  std::cout << "A.compare(2, 2, B, 2, 2):" << A.compare(2, 2, B, 2, 2) << std::endl;// "123" 和 "123dfg"中的"123"比较------- 相等  std::cout << "C.compare(0, 3, D, 0, 3):" << C.compare(0, 3, D, 0, 3) << std::endl;
}

6.string的加法

6.1两个string对象相加

两个string 对象相加得到一个新的string对象,其内容是把左侧的运算对象与右侧的运算对象串接而成。

也就是说,对string 对象使用加法运算符(+)的结果是一个新的string对象,它所包含的字符由两部分组成:前半部分是加号左侧string对象所含的字符、后半部分是加号右侧string对象所含的字符。

另外,复合赋值运算符(+=)】负责把右侧string 对象的内容追加到左侧string对象的后面:

string sl="hello,",s2 = "world\n";//s3的内容是hello,world\n
string s3 = sl + s2;s1+=s2;
// 等价于s1=s1+s2

6.2字面值和string对象相加

即使一种类型并非所需,我们也可以使用它,不过前提是该种类型可以自动转换成所需的类型。

因为标准库允许把字符字面值和字符串字面值转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。

利用这一点将之前的程序改写为如下形式:

string sl = "hello",s2= "world";//在s1和s2中都没有标点符号
string s3=s1+","+s2+'\n';

当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string:

string s4=s1+",";
//正确:把一个string对象和一个字面值相加string s5 ="hello"+",";
// 错误:两个运算对象都不是string//正确:每个加法运算符都有一个运算对象是string
string s6= s1 +","+ "world";string s7="hello"+","+s2;//错误:不能把字面值直接相加

s4和s5初始化时只用到了一个加法运算符,因此很容易判断是否合法。

s6的初始化形式之前没有出现过,但其实它的工作机理和连续输入连续输出是一样的,可以用如下的形式分组:

string s6 = (sl + ",")+ "world";

其中子表达式s1+“,”的结果是一个string 对象,它同时作为第二个加法运算符的左侧运算对象,因此上述语句和下面的两个语句是等价的:

string tmp = s1 +",”;//正确:加法运算符有一个运算对象是strings6 = tmp + "world";
// 正确:加法运算符有一个运算对象是string

另一方面,s7的初始化是非法的,根据其语义加上括号后就成了下面的形式

string s7=("hello"+",")+ s2;//错误:不能把字面值直接相加

很容易看到,括号内的子表达式试图把两个字符串字面值加在一起,而编译器根本没法做到这一点,所以这条语句是错误的。

因为某些历史原因,也为了与C兼容,所以C++语言中的字符串字面值并不是标准库类型string的对象。切记,字符串字面值与string是不同的类型。

7 元素访问

7.1下标访问

在C++中,std::string 类型的对象提供了类似数组的下标访问(也称为索引访问)来直接访问字符串中的字符。你可以使用下标操作符 [] 或者 at() 函数来访问字符串中指定位置的字符。

使用下标操作符 [] 进行随机访问非常简单,但需要注意的是,如果你访问了字符串范围之外的索引,程序不会报错(即不会进行范围检查),这可能会导致未定义行为(如访问无效内存)。

下面是一个使用下标操作符 [] 访问 std::string 中字符的示例:

 #include <iostream>  #include <string>  int main() {  std::string str = "Hello, World!";  // 访问字符串中的第一个字符  char firstChar = str[0]; // 访问索引为0的字符,即'H'  std::cout << "First character: " << firstChar << std::endl;  // 访问字符串中的随机位置的字符(确保索引在范围内)  size_t randomIndex = 7; // 假设我们随机选择了索引7  if (randomIndex < str.size()) {  char randomChar = str[randomIndex]; // 访问索引为7的字符,即'W'  std::cout << "Random character at index " << randomIndex << ": " << randomChar << std::endl;  } else {  std::cout << "Index out of range!" << std::endl;  }  return 0;  } 

7.2at函数

在C++的std::string类中,at()函数是一个成员函数,它提供了对字符串中字符的带范围检查的访问。当你使用at()函数访问字符串中的字符时,如果提供的索引超出了字符串的有效范围(即小于0或大于等于字符串的长度),那么at()函数会抛出一个std::out_of_range异常。
这是使用at()函数的一个基本示例:

 #include <iostream>  #include <string>  #include <stdexcept>  int main() {  std::string str = "Hello, World!";  // 使用at()访问索引为0的字符  char firstChar = str.at(0);  std::cout << "First character: " << firstChar << std::endl;  // 尝试访问索引为字符串长度(或更大)的字符,这将抛出异常  try {  char invalidChar = str.at(str.length()); // 注意:索引是从0开始的,所以str.length()是无效的索引  std::cout << "Invalid character: " << invalidChar << std::endl;  } catch (const std::out_of_range& e) {  std::cout << "Caught an out_of_range exception: " << e.what() << std::endl;  }  // 尝试访问一个负数索引,这也将抛出异常  try {  char invalidChar = str.at(-1);  std::cout << "Invalid character: " << invalidChar << std::endl;  } catch (const std::out_of_range& e) {  std::cout << "Caught an out_of_range exception: " << e.what() << std::endl;  }  return 0;  } 

在这个示例中,我们尝试使用at()函数访问字符串str中索引为str.length()和-1的字符。由于这两个索引都是无效的(一个在字符串末尾之后,一个在字符串开始之前),因此at()函数会抛出std::out_of_range异常。我们使用try-catch块来捕获这些异常并输出一条错误消息。

请注意,与下标操作符[]不同,at()函数总是进行范围检查,因此使用at()函数可以提供更安全的字符串访问方式。然而,由于范围检查的开销,使用at()函数可能会比使用下标操作符[]稍微慢一些(尽管在现代处理器和编译器优化下,这种差异通常可以忽略不计)。
 

8.substr操作

substr操作返回一个string,它是原始string的一部分或者全部的拷贝。可以传递给substr一个可选的开始位置和计数值

s.substr(pos,n)string s("hello world");string s2 = s.substr(0,5);// s2 = hellostring s3 = s.substr(6);// s3 = worldstring s4 = s.substr(6, 11);// s3 = worldstring s5 =s.substr(12);//抛出一个out_of_range异常


如果开始位置超过了string的大小,则substr函数抛出一个out_of_range异常。如果开始位置加上计数值大于string的大小,则substr会调整计数值,只拷贝到string的末尾。

表9.12:子字符串操作
返回一个string,包含s中从pos开始的n个字符的拷贝。pos的默认值为0。n的默认值为s.size()-pos,即拷贝从pos开始的所有字符

9.insert函数

在C++的std::string类中,insert()函数用于在字符串的指定位置插入一个或多个字符。这个函数有多种重载形式,可以接受不同类型的参数,以便从其他字符串、字符数组、单个字符或子字符串来插入内容。

以下是insert()函数的一些常见用法:
在指定位置插入一个字符:

 std::string str = "Hello";  str.insert(1, 'i'); // 在索引1的位置插入'i',str现在包含"Hiello" 

在指定位置插入一个字符串:

 std::string str = "Hello";  std::string ins = "World";  str.insert(5, ins); // 在索引5的位置插入"World",str现在包含"HelloWorld" 

在指定位置插入指定次数的字符:

 std::string str = "Hello";  str.insert(5, 3, '!'); // 在索引5的位置插入3个'!',str现在包含"Hello!!!" 

在指定位置插入另一个字符串的子串:

 std::string str = "Hello";  std::string ins = "World, World!";  str.insert(5, ins, 7, 5); // 在索引5的位置插入ins从索引7开始的5个字符,即"World",str现在包含"HelloWorld" 

注意,在上面的例子中,子字符串的索引是从0开始的,并且长度参数指定了要插入的字符数(不包括结束的空字符)。

使用迭代器插入字符序列:

如果你的数据来自标准库容器(如std::vector或std::list),并且你想在std::string中插入这些容器的元素,你可以使用迭代器来指定要插入的范围。但是,由于std::string存储的是字符,所以迭代器应该是指向字符的迭代器。

 std::vector<char> vec = {'i', 'n', 's', 'e', 'r', 't'};  std::string str = "Hello";  str.insert(str.begin() + 1, vec.begin(), vec.end()); // 在索引1的位置插入vec的所有元素,str现在包含"Hinsertello" 

使用insert()函数可以灵活地在字符串的任意位置插入新的内容。如果insert()函数接收的参数会导致新字符串的长度超过当前字符串的容量,那么std::string可能会重新分配内存以存储新的内容。

用于c风格字符串

 std::string str = "Hello";  const char* cstr = "World"; // C风格字符串  // 在str的末尾插入cstr  str.insert(str.length(), cstr); // 现在str包含"HelloWorld"  // 在str的指定位置插入cstr的子串  str.insert(5, cstr + 1, 3); // 从cstr的第1个字符开始插入3个字符,即"orl",现在str包含"HelloWorldorl"  


10.append 和replace函数

string类定义了两个额外的成员函数:append和replace,这两个函数可以改变string的内容。

ppend 操作是在string末尾进行插入操作的一种简写形式:

string s("C++ Primer"), s2= s: // 将s和s2初始化为"Ct+ Primer"s.insert(s.size(),"4th Ed.");// s =="C++ Primer 4th Ed."s2.append(" 4th Ed.");
//等价方法:将"4th Ed."追加到s2;S ==s2

replace 操作是调用erase和insert的一种简写形式:

//将"4th“替换为"5th"的等价方法
s.erase(11, 3);// s =="C++ Primer Ed."
s.insert(11, "5th");// s == "C++ Primer 5th Ed."//从位置11开始,删除3个字符并插入"5th"
s2.replace(11,3,"5th"); //等价方法:s==s2

此例中调用replace时,插入的文本恰好与删除的文本一样长。这不是必须的,可以插入一个更长或更短的string:

s.replace(11, 3, "Fifth");
// s == "C++ Primer Fifth Ed."

在此调用中,删除了3个字符,但在其位置插入了5个新字符。

11.string的搜索操作

在C++的std::string类中,有多种搜索操作可以用来查找子字符串或字符在字符串中的位置。以下是一些常用的搜索函数:
find():
这个函数用于在字符串中查找子字符串或字符首次出现的位置。如果找到,它返回子字符串或字符首次出现的位置的索引;如果未找到,则返回std::string::npos。

 std::string str = "Hello, World!";  size_t pos = str.find("World"); // pos现在是7  pos = str.find(','); // pos现在是5  pos = str.find('o'); // pos现在是4(找到第一个'o')  pos = str.find("NotPresent"); // pos现在是std::string::npos 

rfind():

这个函数与find()类似,但它是从字符串的末尾开始搜索,返回子字符串或字符最后一次出现的位置的索引。

 std::string str = "banana";  size_t pos = str.rfind('a'); // pos现在是5(找到最后一个'a') 

find_first_of():

这个函数在字符串中查找参数中任何一个字符首次出现的位置。

 std::string str = "Hello, World!";  size_t pos = str.find_first_of("ld"); // pos现在是2(找到'l')  pos = str.find_first_of("XYZ"); // pos现在是std::string::npos(没找到) 

find_first_not_of():

这个函数在字符串中查找第一个不属于参数中任何字符的字符的位置。

std::string str = "Hello, 123 World!";  size_t pos = str.find_first_not_of("0123456789"); // pos现在是7(找到',')  pos = str.find_first_not_of("abcdefghijklmnopqrstuvwxyz"); // pos现在是7(找到',')

 find_last_of():

这个函数在字符串中查找参数中任何一个字符最后一次出现的位置。

 std::string str = "banana";  size_t pos = str.find_last_of("an"); // pos现在是5(找到最后一个'a') 

find_last_not_of():

这个函数在字符串中查找最后一个不属于参数中任何字符的字符的位置。

 std::string str = "Hello, 123 World!";  size_t pos = str.find_last_not_of("0123456789"); // pos现在是12(找到' ') 

这些函数都接受一个可选的起始位置参数,允许你从字符串的某个特定位置开始搜索。例如:

 std::string str = "Hello, World!";  size_t pos = str.find("o", 5); // 从索引5开始查找'o',pos现在是7(找到第二个'o') 

请注意,所有的位置索引都是从0开始的,而std::string::npos是一个特殊的常量,表示“未找到”。 

12 string的遍历:借助迭代器 或者 下标法

void test6()
{string s1("abcdef"); // 调用一次构造函数// 方法一: 下标法for( int i = 0; i < s1.size() ; i++ ){cout<<s1[i];}cout<<endl;// 方法二:正向迭代器string::iterator iter = s1.begin();for( ; iter < s1.end() ; iter++){cout<<*iter;}cout<<endl;// 方法三:反向迭代器string::reverse_iterator riter = s1.rbegin();for( ; riter < s1.rend() ; riter++){cout<<*riter;}cout<<endl;
}

13. string的删除:erase()
 

1. iterator erase(iterator p);//删除字符串中p所指的字符2. iterator erase(iterator first, iterator last);//删除字符串中迭代器区间[first,last)上所有字符3. string& erase(size_t pos = 0, size_t len = npos);//删除字符串中从索引位置pos开始的len个字符4. void clear();//删除字符串中所有字符
void test6()
{string s1 = "123456789";// s1.erase(s1.begin()+1);              // 结果:13456789// s1.erase(s1.begin()+1,s1.end()-2);   // 结果:189s1.erase(1,6);                       // 结果:189string::iterator iter = s1.begin();while( iter != s1.end() ){cout<<*iter;*iter++;}cout<<endl;}


14、 string的字符替换:

1. string& replace(size_t pos, size_t n, const char *s);//将当前字符串从pos索引开始的n个字符,替换成字符串s2. string& replace(size_t pos, size_t n, size_t n1, char c); //将当前字符串从pos索引开始的n个字符,替换成n1个字符c3. string& replace(iterator i1, iterator i2, const char* s);//将当前字符串[i1,i2)区间中的字符串替换为字符串s
void test7()
{string s1("hello,world!");cout<<s1.size()<<endl;                     // 结果:12s1.replace(s1.size()-1,1,1,'.');           // 结果:hello,world.// 这里的6表示下标  5表示长度s1.replace(6,5,"girl");                    // 结果:hello,girl.// s1.begin(),s1.begin()+5 是左闭右开区间s1.replace(s1.begin(),s1.begin()+5,"boy"); // 结果:boy,girl.cout<<s1<<endl;
}


15. string的大小写转换:

tolower()和toupper()函数 或者 STL中的transform算法
方法一:使用C语言之前的方法,使用函数,进行转换

#include <iostream>
#include <string>
using namespace std;int main()
{string s = "ABCDEFG";for( int i = 0; i < s.size(); i++ ){s[i] = tolower(s[i]);}cout<<s<<endl;return 0;
}


方法二:通过STL的transform算法配合的toupper和tolower来实现该功能

#include <iostream>
#include <algorithm>
#include <string>using namespace std;int main()
{string s = "ABCDEFG";string result;transform(s.begin(),s.end(),s.begin(),::tolower);cout<<s<<endl;return 0;
}

16、 string的查找:find

1. size_t find (constchar* s, size_t pos = 0) const;//在当前字符串的pos索引位置开始,查找子串s,返回找到的位置索引,-1表示查找不到子串2. size_t find (charc, size_t pos = 0) const;//在当前字符串的pos索引位置开始,查找字符c,返回找到的位置索引,-1表示查找不到字符3. size_t rfind (constchar* s, size_t pos = npos) const;//在当前字符串的pos索引位置开始,反向查找子串s,返回找到的位置索引,-1表示查找不到子串4. size_t rfind (charc, size_t pos = npos) const;//在当前字符串的pos索引位置开始,反向查找字符c,返回找到的位置索引,-1表示查找不到字符5. size_tfind_first_of (const char* s, size_t pos = 0) const;//在当前字符串的pos索引位置开始,查找子串s的字符,返回找到的位置索引,-1表示查找不到字符6. size_tfind_first_not_of (const char* s, size_t pos = 0) const;//在当前字符串的pos索引位置开始,查找第一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到字符7. size_t find_last_of(const char* s, size_t pos = npos) const;//在当前字符串的pos索引位置开始,查找最后一个位于子串s的字符,返回找到的位置索引,-1表示查找不到字符8. size_tfind_last_not_of (const char* s, size_t pos = npos) const;//在当前字符串的pos索引位置开始,查找最后一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到子串1
void test8()
{string s("dog bird chicken bird cat");//字符串查找-----找到后返回首字母在字符串中的下标// 1. 查找一个字符串cout << s.find("chicken") << endl;        // 结果是:9// 2. 从下标为6开始找字符'i',返回找到的第一个i的下标cout << s.find('i',6) << endl;            // 结果是:11// 3. 从字符串的末尾开始查找字符串,返回的还是首字母在字符串中的下标cout << s.rfind("chicken") << endl;       // 结果是:9// 4. 从字符串的末尾开始查找字符cout << s.rfind('i') << endl;             // 结果是:18-------因为是从末尾开始查找,所以返回第一次找到的字符// 5. 在该字符串中查找第一个属于字符串s的字符cout << s.find_first_of("13br98") << endl;  // 结果是:4---b// 6. 在该字符串中查找第一个不属于字符串s的字符------先匹配dog,然后bird匹配不到,所以打印4cout << s.find_first_not_of("hello dog 2006") << endl; // 结果是:4cout << s.find_first_not_of("dog bird 2006") << endl;  // 结果是:9// 7. 在该字符串最后中查找第一个属于字符串s的字符cout << s.find_last_of("13r98") << endl;               // 结果是:19// 8. 在该字符串最后中查找第一个不属于字符串s的字符------先匹配t--a---c,然后空格匹配不到,所以打印21cout << s.find_last_not_of("teac") << endl;            // 结果是:21}


17、 string的排序:sort(s.begin(),s.end())

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;void test9()
{string s = "cdefba";sort(s.begin(),s.end());cout<<"s:"<<s<<endl;     // 结果:abcdef
}



18、 string的分割/截取字符串:strtok() & substr()

strtok():分割字符串

void test10()
{char str[] = "I,am,a,student; hello world!";const char *split = ",; !";char *p2 = strtok(str,split);while( p2 != NULL ){cout<<p2<<endl;p2 = strtok(NULL,split);}
}


 


void test11()
{string s1("0123456789");string s2 = s1.substr(2,5); // 结果:23456-----参数5表示:截取的字符串的长度cout<<s2<<endl;
}

数值的转换

字符串中常常包含表示数值的字符。

例如,我们用两个字符的string 表示数值15-字符'1'后跟字符'5'。

一般情况,一个数的字符表示不同于其数值。数值15如果保存为16位的short 类型,则其二进制位模式为0000000000001111,而字符串"15”存为两个Latin-1 编码的char,二进制位模式为0011000100110101。第一个字节表示字符'1,其八进制值为:061,第二个字节表示151,其Latin-1编码为八进制值065。

新标准引入了多个函数,可以实现数值数据与标准库string之间的转换:

int i =42
string s = to_ string(i);;// 将整数i转换为字符表示形式
double d = stod(s);//将字符串 s转换为浮点数

此例中我们调用to_string 将42转换为其对应的string表示,然后调用stod将此string转换为浮点值。

要转换为数值的string中第一个非空白符必须是数值中可能出现的字符:

string s2 = "pi = 3.14";//转换s中以数字开始的第一个子串,结果d=3.14
d= stod(s2.substr(s2.find_first _of("+-.0123456789")));

在这个stoa调用中,我们调用了find first_of来获得s中第一个可能是数值的一部分的字符的位置。我们将s中从此位置开始的子串传递给stodestod函数读取此参数,处理其中的字符,直至遇到不可能是数值的一部分的字符,然后它就将找到的这个数值的字符串表示形式转换为对应的双精度浮点值。

string 参数中第一个非空白符必须是符号(+或-)或数字。

它可以以0x或0x开头来表示干六进制数。对那些将字符串转换为浮点值的函数,string参数也可以以小数点(.)开头,并可以包含e或E来表示指数部分。

对于那些将字符串转换为整型值的函数,根据基数不同,string参数可以包含字母字符,对应大于数字9的数。

如果string不能转换为一个数值,这些函数抛出一个invalid_argument异常。如果转换得到的数值无法用任何类型来表示,则抛出一个out_of_range异常。

string 和数值之间的转换

to_string(val);
//一组重载函数,返回数值val的string 表示。val可以是任何算术类型。
//对每个浮点类型和int或更大的整型,都有相应版本的to_string。
//与往常一样,小整型会被提升stoi(s,p,b);    //返回s的起始子串(表示整数内容)的数值,
stol(s,p,b);    //返回值类型分别是int、long, unsigned long,
stoul(s,p,b);    // long long unsigned long long.
stoll(s,p,b);    //b表示转换所用的基数,默认值为10。
stoull(s,p,b);stof(s,p,b);    //p是size_t指针,用来保存s中第一个非数值字符的下标,P默认为0,
stod(s,p,b);    //即,函数不保存下标返回s的起始子串(表示浮点数内容)的数值,
stold(s,p,b);    //返回值类型分别是float、double或long double。参数p的作用与整数转换函数中一样

举个例子

std::stol(string to long):将字符串转换为长整数。

long num = std::stol("123456789012345");

std::stof(string to float):将字符串转换为浮点数。

float num = std::stof("123.45");

使用 std::to_string:将整数、浮点数或长整数转换为字符串。

#include <string>  int main() {  int num = 123;  std::string str = std::to_string(num); // str现在是"123"  double dnum = 123.45;  std::string dstr = std::to_string(dnum); // dstr现在是"123.45"(可能包含更多小数位)  return 0;  
}

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

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

相关文章

windows ubuntu sed,awk,grep篇:10.awk 变量的操作符

目录 62. 变量 64. 算术操作符 65. 字符串操作符 66. 赋值操作符 67. 比较操作符 68. 正则表达式操作符 62. 变量 Awk 变量以字母开头&#xff0c;后续字符可以是数字、字母、或下划线。关键字不能用作 awk 变量。 不像其他编程语言&#xff0c; awk 变量可以直接使…

实习面试之算法准备:数学题

目录 1 技巧2 例题2.1 Nim 游戏2.2 石子游戏2.3 灯泡开关 1 技巧 稍加思考&#xff0c;找到规律 2 例题 2.1 Nim 游戏 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。 你们轮流进行自己的回合&#xff0c; 你作为先手 。 每一回合&#xf…

SpringBoot 打包所有依赖

SpringBoot 项目打包的时候可以通过插件 spring-boot-maven-plugin 来 repackage 项目&#xff0c;使得打的包中包含所有依赖&#xff0c;可以直接运行。例如&#xff1a; <plugins><plugin><groupId>org.springframework.boot</groupId><artifact…

2024五一杯数学建模B题思路代码文章教学-交通需求规划与可达率问题

交通需求规划与可达率问题 问题总结&#xff1a; 问题一&#xff1a;在一个小型交通网络中&#xff0c;给定的起点和终点之间的交通需求需分配到相应路径上。目标是最大化任意一条路段出现突发状况时的交通需求期望可达率。 问题二&#xff1a;在一个较大的交通网络中&#xff…

负债56亿,购买理财产品遭违约,操纵虚假粉丝,流量在下滑,客户数量减少,汽车之家面临大量风险(三)

本文由猛兽财经历时5个多月完成。猛兽财经将通过以下二十二个章节、8万字以上的内容来全面、深度的分析汽车之家这家公司。 由于篇幅限制&#xff0c;全文分为&#xff08;一&#xff09;到&#xff08;十&#xff09;篇发布。 本文为全文的第七章、第八章、第九章。 目录 …

【Linux—进程间通信】共享内存的原理、创建及使用

什么是共享内存 共享内存是一种计算机编程中的技术&#xff0c;它允许多个进程访问同一块内存区域&#xff0c;以此作为进程间通信&#xff08;IPC, Inter-Process Communication&#xff09;的一种方式。这种方式相对于管道、套接字等通信手段&#xff0c;具有更高的效率&…

一文入门交叉编译

前言: 在阅读本文之前&#xff0c;你哦需要了解makefile文件的编写规则&#xff0c;这里我们推荐两篇入门: Makefile 规则-CSDN博客 Makefile 快速入门-CSDN博客 编译定义 编译是指将源代码文件&#xff08;如C/C文件&#xff09;经过预处理、编译、汇编和链接等步骤&#x…

如何从0深入PostgreSQL内核写一个执行器算子?

如何从0深入PostgreSQL内核写一个执行器算子&#xff1f; 大家好&#xff0c;我叫光城&#xff0c;昨天分享了一个主题&#xff1a;如何从0深入PostgreSQL内核写一个执行器算子&#xff1f;今天来总结一下&#xff0c;本篇文章的直播回放可以在b站观看&#xff0c;点击原文或者…

[PS小技能学习]抠图和切图

详情见视频教程&#xff1a;PS小技巧--抠图与切图 今天我们来学习如何使用PS对表情包合辑进行抠图和裁剪保存 1、首先&#xff0c;将图片导入&#xff0c;双击图层新建一个图层 2、然后点击工具栏的魔棒工具&#xff0c;再点击顶部菜单栏的添加到选区 3、点击图片的空白区域即…

IMU状态预积分功能实现与测试

IMU状态预积分功能实现与测试 前言实现IMU状态预积分类测试程序验证预积分与直接积分的效果结果 前言 预积分&#xff1a;是一种十分常见的IMU数据处理方法。 与传统的IMU运动学积分不同&#xff0c;预积分可以将一段时间内的IMU测量数据累积&#xff0c;建立预积分测量&#…

两院院士泌尿外科专家吴阶平教授

吴阶平&#xff08;1917-2011&#xff09;&#xff0c;男&#xff0c;江苏常州人&#xff0c;1933年天津汇文中学毕业&#xff0c;保送到北平燕京大学医预科&#xff0c;1937年毕业于北平燕京大学获理学士学位&#xff0c;1942年毕业于北平协和医学院获医学博士学位&#xff0c…

银行卡归属地查询API接口快速对接

银行卡归属地查询API接口指的是通过银行卡号查询该银行卡详细信息&#xff0c;包括银行卡名称、卡种、卡品牌、发卡行、编号以及归属地等信息&#xff0c;支持一千多家银行返回归属地信息&#xff0c;那么银行卡归属地查询API接口如何快速对接呢&#xff1f; 首先找到有做银行…

SpringBoot集成Kafka开发

4.SpringBoot集成Kafka开发 4.1 创建项目 4.2 配置文件 application.yml spring:application:name: spring-boot-01-kafka-basekafka:bootstrap-servers: 192.168.2.118:90924.3 创建生产者 package com.zzc.producer;import jakarta.annotation.Resource; import org.spri…

Thread类及常见方法

目录 1.Thread类概念 2.Thread的常见构造方法 3.Thread的几个常见属性 4.启动一个线程—start( ) 5.中断一个线程 1.使用自定义的变量来作为标志位 2.使用interrupt() 3.观察标志位是否被清除 6.等待一个线程-join() 7.获取当前线程引用 8.休眠当前线程 1.Thread类概…

GitHub Copilot 简单使用

因为公司安全原因&#xff0c;并不允许在工作中使用GitHub Copilot&#xff0c;所以&#xff0c;一直没怎么使用。最近因为有一些其它任务&#xff0c;所以&#xff0c;试用了一下&#xff0c;感觉还是很不错的。&#xff08;主要是C和Python编程&#xff09; 一&#xff1a;常…

探索洗牌算法的魅力与杨辉三角的奥秘:顺序表的实际运用

目录 目录 前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 洗牌算法 准备工作 买一副牌 洗牌 发牌 测试整体 &#x1f3af;&#x1f3af;很重要的一点 杨辉三角 总结 前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ …

06_电子设计教程基础篇(学习视频推荐)

文章目录 前言一、基础视频1、电路原理3、模电4、高频电子线路5、电力电子技术6、数学物理方法7、电磁场与电磁波8、信号系统9、自动控制原理10、通信原理11、单片机原理 二、科普视频1、工科男孙老师2、达尔闻3、爱上半导体4、华秋商城5、JT硬件乐趣6、洋桃电子 三、教学视频1…

分布式与一致性协议之Raft算法与一致哈希算法(一)

Raft算法 Raft与一致性 有很多人把Raft算法当成一致性算法&#xff0c;其实它不是一致性算法而是共识算法&#xff0c;是一个Multi-Paxos算法&#xff0c;实现的是如何就一系列值达成共识。并且&#xff0c;Raft算法能容忍少数节点的故障。虽然Raft算法能实现强一致性&#x…

相机知识的补充

一&#xff1a;镜头 1.1MP的概念 相机中MP的意思是指百万像素。MP是mega pixel的缩写。mega意为一百万&#xff0c;mega pixel 指意为100万像素。“像素”是相机感光器件上的感光最小单位。就像是光学相机的感光胶片的银粒一样&#xff0c;记忆在数码相机的“胶片”&#xff…

如何使用Go语言进行并发安全的数据访问?

文章目录 并发安全问题的原因解决方案1. 使用互斥锁&#xff08;Mutex&#xff09;示例代码&#xff1a; 2. 使用原子操作&#xff08;Atomic Operations&#xff09;示例代码&#xff1a; 3. 使用通道&#xff08;Channels&#xff09; 在Go语言中&#xff0c;进行并发编程是常…