前面介绍了通过字符数组保存字符串,然后对字符数组中的字符串做各种操作;

为了更加简单方便,在C++中,又增加了 string 来处理字符串string 使用的好,慢慢你就不想使用字符数组来存放字符串了。

一. string 概念

string 字符串其实是⼀种更加高级的封装,string 字符串中包含大量的方法,这些方法使得字符串的操作变得更加简单。那到底什么是string呢? 而C++中将字符串直接作为⼀种类型,也就是 string 类型,使用C++的字符串。

string就是一种更加高级的分装

string s1;
string s2 = "abc";

使用C++中提供的 string 时,必须添加头文件

二. string 的常见操作

string ⽂档:https://legacy.cplusplus.com/reference/string/string

1. string字符串的创建和初始化

string s1---创建空字符串

string s2 = "hello world"--创建字符串(常用)

1.1.string s1 表示创建空字符串,相当于创建整型 int a ,但未给 a ⼀个初始值。

1.2.string s2 = "hello world" 表示创建⼀个字符串 s2,它的内容是" hello world ",要 注意 s2 中的字符串不再以 \0 作为结束标志了。(C语言中的字符串是以 \0 作为结束标志 的)。

除了以上创建字符串的写法外,C++中还有一些其他的创建字符串方式。如

	string s("hello world"); //等同于
    string s1 = "hello world"; 
    string s1 = s; 
	//用个现成的字符串s,初始化另外?个字符串s1
	

当然C++中的string 创建的字符串和char类型的数组所表示的字符串还有⼀个区别,string类型的字符串对象可以直接赋值,比如:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s1("hello world");
    string s2("hehe");
    s2 = s1;
    cout << s2 << endl;
    return 0;
 }

2. string字符串的输⼊

2.1.cin的输入

可以直接使用cin给string类型的字符串中输入⼀个字符串的数据。

 
#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s;
 
    cin >> s;
 
    cout << s << endl;
 
 
    return 0 
}

输入不带空格的字符串:abcdef---输出abcdef

输入带空格的: abc def  ---输出abc

这里我们可以发现,其实 cin 的方式给 string 类型的字符串中输入数据的时候,可以输入不带空 格的字符串。但是如果带有空格,遇到空格也就读取结束了,没有办法正常读取,那怎么办呢?解决 办法就是使用 getline

2.2.getine

getline 是C++标准库中的一个函数,用于从输入流中读取一行文本,并将其存储为字符串。 getline 函数有两种不同的形式,分别对应着字符串的结束方式。

istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);

小提示

istream 是输入流类型, cin 是 istream 类型的标准输入流对象。 ostream 是输出流类型, cout 是 ostream 类型的标准输出流对象。 getline 函数是输入流中读取一行文本信息,所有如果是在标准输入流(键盘)中读取数 据,就可以传 cin 给第一个参数。

第⼀种 getline 函数以换行符('\n')作为字符串的结束标志,它的一般格式是

 getline(cin, string str)
 //cin -- 表示从输?流中读取信息
 
//str -- 是存放读取到的信息的字符串

这种形式的getlinee 函数从输入流(例如cin)中读取文本,直到遇到换行符(‘\n'))为止,然后将读取到的文本(不包括换行符)存储到指定的string 类型的变量str 中.

#include<iostream>
#include <string>
using namespace std;

int main ()
{
    string name;
    getline (cin, name);
    
    cout << name << endl;
    //输入 abc defghi
	//输出 abc defghi 
    
    return 0;
 }

第二种 getline 函数允许用户自定义结束标志,它的一般格式是:

getline(cin, string str, char delim)
 //cin -- 表示从输入流中读取信息
 
//str 是存放读取到的信息的字符串
 
//delim 是自定义的结束标志

这种形式的getline函数从输入中读取文本,直到遇到用户指定的结束标志字符(delim)为止,然后将读取到的文本(不包括结束标志字符)存储到指定的string 类型的变量str 中。

#include<iostream>
#include <string>
using namespace std;

int main ()
{
    string name;
    getline (cin, name, 'q');
    
    cout << name << endl;
    //输入 abc defqwer
	//输出 abc def 
 }

在使用C++中的 string 字符串时,想要输入的字符串中包含空格,通常会使⽤ getline 函数就 string 类型的字符串,所以在字符串输⼊的时 tline 就很常见,建议认真学习。

3. size()

string 中提供了 size() 函数用于获取字符串长度。

在C++中关于字符串的操作函数都是包含在 string 中的,所以需要调用这些函数时,通常用 . 点运 算符。

比如

#include <iostream>

#include <string>      
using namespace std;
 
int main()
{
    string s;
    string s1 = "hello";
    string s2 = "hello world";
    string s3 = "12ab!~        "; 
    
    cout << s.size() << endl;
    cout << s1.size() << endl;
    cout << s2.size() << endl;
    cout << s3.size() << endl;
    //输出0  5  11 14 
    
    return 0;
 }
#include <iostream> 
#include <cstring>

using namespace std;

int main()
{
    string s;
	cin >> s;
	//输入 abc 
	cout << s << endl;
	cout << s.size() << endl; 
    //输出  abc  
	//      3 
    
    return 0;
 }

前⾯我们学到的像用  . 操作符的。 char 、 int 、 double 等内置类型的数据在操作的时候,不会使用  . 操作符来使用这些函数

string 是C++提供的⼀种更加复杂的封装类型,在 string 类型的变量中加入了操作这 个字符串的各种方法(函数),比如求字符串长度、字符串末尾插入⼀个字符等操作。所以要 对 string 类型的变量进行各种操作,就可以使用  . 操作符来使用这些函数。

我们可以看下⾯的例子,大家可以仔细体会。

通过 size() 能获得字符串的长度,顺便就可以使用这个长度遍历字符串的,注意string类型的字符串是可以通过下标访问的,比如:

#include <iostream> 
#include <cstring>

using namespace std;

int main()
{
    string s = "abcdef";
    int i = 0;
    for(i = 0; i < s.size(); i++)
    {
        cout << s[i] << " ";
    }
    //输出a b c d e f  
    
    return 0;
 }

4. 迭代器

迭代器是⼀种对象,它可以用来遍历容器(比如我们现在学习的 类似于指针,或者数组下标。

❗不过访问迭代器指向的值,需要解引⽤(*)。

C++中的 string 提供了多种迭代器,用于遍历和操作字符串中的内容。这里给大家介绍一种最常 用的迭代器。

4.1begin() 和 end()

be gin() :返回指向字符串第一个字符的迭代器,需要一个迭代器的变量来接收。

end() :返回指向字符串最后一个字符的下一个位置的迭代器(该位置不属于字符串)。

st ring 中 begin()和end() 返回的迭代器的类型是 string::iterator

 string s = "abcdef";

• 迭代器是可以进行大小比较,也可以进行 + 或者 整数运算的。 比如: i t++ ,就是让迭代器前进一步, 就是让迭代器退后一步。

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s = "abcdef";
    string::iterator it1 = s.begin();
    string::iterator it2 = s.end();
    
    if(it1 < it2)
        cout << "<" << endl;
    else
        cout << ">=" << endl;
    //输出< 
    
    return 0;
 }

• 同一个容器的两个迭代器也可以相减,相减结果的绝对值,是两个迭代器中间元素的个数

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s = "abcdef";
    string::iterator it1 = s.begin();

    string::iterator it2 = s.end();
    
    cout << (it1 < it2) << endl;
    cout << it1 - it2 << endl;
    //输出  -1
	//       6 
    
    return 0;
 }

使用迭代器可以便历字符串,可以正序便历或者逆序便历

正序

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s = "abcdef";
    for(string::iterator it = s.begin(); it < s.end();it++) 
//it 类型不知道时可以写为auto
    {
    	cout << *it;
	}
	//输出abcdef
	 
    return 0;
 }

倒序

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s = "abcdef";
    for(string::iterator it = s.end()-1; it >= s.begin();--it) 
    {
    	cout << *it;
	}
	//输出fedcba
	 
    return 0;
 }

❗通过迭代器找到元素后,改变迭代器指向的元素,是可以直接改变字符串内容的。


#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s = "abcdef";
    cout << s << endl;
    
    for(string::iterator it = s.end()-1; it >= s.begin();--it) 
    {
        *it = 'x';
	}
	cout << s << endl;
	//输出abcdef
	 //   xxxxxx
	 
    return 0;
 }

5. push_back()

push_back() 用于在字符串尾部插一个字符。

即,最后一个字符的下一个位置插入一个新的字符

比如


#include <iostream>
#include<string>     
using namespace std;
 //添加string头文件
 
int main()
 {
 //向空字符串中尾插字符
 

    string s;
    s.push_back('h');
    s.push_back('e');
    s.push_back('l');
    s.push_back('l');
    s.push_back('o');
    cout << s << endl;
 //向非空字符串中尾插字符
 
    string s1 = "hello ";
    s1.push_back('w');
    s1.push_back('o');
    s1.push_back('r');
    s1.push_back('l');
    s1.push_back('d');
    cout << s1 << endl;
 //批量插入字符
 
    string s2;//a~z
	char c = 0; 
    for (char c = 'a'; c <= 'z'; c++)
    {
        s2.push_back(c);
    }
    cout << s2 << endl;
 
    return 0;
 
}

6. string的+=和+运算

push_back() 是⽤于在字符串后添加⼀个字符,然⽽部分情况下我们需要向原有的字符串后继续添 加字符串。 其实 s tring 类型的字符串是⽀持 + 和 += 运算的。这⾥的本质是 operator+= 这个操作符。

具体使用请看下面的示例:

+=运算


#include <iostream>
#include<string>     
using namespace std;
 
int main()
 {
 	string s = "hello";
 	s += "world";
 	
 	cout << s << endl;
 	
    //输出  hello world 
 
    return 0;
 
}

+运算

#include <iostream>
#include<string>     
using namespace std;
 
int main()
 {
 	string s1 = "hello ";
 	
 	cout << s1 + "world" << endl;
 	cout << s1 << endl;
 	s1 += "world";
 	cout << s1 <<endl;
 	
    //输出  hello world 
    //      hello
    //      hello world
 
    return 0;
 
}

前后都可以加字符

#include <iostream>
#include<string>     
using namespace std;
 
int main()
 {
 	string s2 = "hello ";
 	s2 = "world" + s2;
 	
 	cout << s2 <<endl;
 	
    //输出  worldhello
 
    return 0;
 
}

7. pop_back() 

pop_back() 用于删除字符串中尾部的一个字符。这个成员函数是在 C++11 标准中引入的,有的编 译器可能不支持。

#include <iostream>
#include<string>     
using namespace std;
 
int main()
 {
 	string s = "hello";
	s.pop_back();
	//devc++不支持s.pop_back()
	//需要在工具-编译选项添加(-std=c++11)代码令 
	cout << s << endl;
	cout << s.size() << endl;
	
	//输出 hello
	//     4 
 
    return 0;
 
}

s.pop_back(); 函数可以连用

注意:

当字符串中没有字符的时候,再调用pop_back() 时,程序会出现异常。这种行为也是未定义行为,要避免这么使用。

为避免循环删除导致对空字符串进行尾删,可以将代码改写成

#include <iostream>
#include<string>     
using namespace std;
 
int main()
{
	string s = "hello";
	while(s.size() >= 1)
	    s.pop_back() ;
	    
	cout <<s.size() << endl; 
      //输出  0 
 
    return 0;
 
}

不可对空字符串继续进行pop_back()操作,否则程序出现异常

8. insert()

如果我们需要在字符串中间的某个位置插入一个字符串,怎么办呢?这时候我们得掌握一个函数就是 insert

函数原型如下:

string& insert (size_t pos, const string& str); 
 //pos位置前面插入一个string字符串
 string& insert (size_t pos, const char* s); 
 //pos位置前面插入一个C风格的字符串
string& insert (size_t pos, size_t n, char c);
//pos位置前面插入n个字符c 

eg

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s = "abcdefghi";
	string str = "xxx";
	
	cout << s << endl;
	s.insert(3,str);
	cout << s << endl;
	//输出
	// abcdefghi
    // abcxxxdefghi 
	
	return 0;
 } 
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s = "abcdefghi";
	
	cout << s << endl;
	s.insert(3,"xxx");
	cout << s << endl;
	//输出
	// abcdefghi
    // abcxxxdefghi 
	
	return 0;
 } 

9. find()

find() 函数用于查找字符串中指定子串/字符,并返回子串/字符在字符串中第一次出现的位置

 size_t find (const string& str, size_t pos = 0) const;
 //查找string类型的字符串str,默认是从头开始查找,
 //pos可以指定位置开始
size_t find (const char* s, size_t pos = 0) const;
 //查找C风格的字符串s,默认是从头开始查找,
  //pos可以指定位置开始
size_t find (const char* s, size_t pos, size_t n) const;
 //在字符串的pos这个位置开始查找C?格的字符串
//s中的前n个字符,
 
size_t find (char c, size_t pos = 0) const;
 //查找字符c,默认是从头开始,
//pos可以指定位置开始

返回值:

若找到。返回子串/字符在字符串中第一次出现的起始下标位置。

• 若未找到。返一个整数值 的返回值是否等于 npos (针对 npos 的介绍会在下⾯给出)。通常判断 find() 函数 npos 就能知道是否查找到子串或者字符。


#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s = "hello world hellp everyone";
	string str = "llo";
	size_t n = s.find(str);
	cout << n << endl;
	//输出2 
	
	n = s.find(str,n+1); 
	cout << n << endl;
	
	return 0;
 } 

在字符串中查找字符或者字符串时,有可能查找不到,这时候 字并不是一个随机的数字,而是 find 函数会返回 string 中定义的⼀个静态常量 数的返回值是否等于 npos 这个值,该数 npos 。我们通常会判断 find 函 npos 来判断,查找是否成功。

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s = "hello world hellp everyone";
	
	size_t n = s.find("one");
	if(n == string::npos)
	    cout << "找不到" <<endl;
	else
	cout <<"找到了,位置是:" << n << endl; 
	//输出  找到了,位置是:23 
	
	return 0;
 } 

10.substr()

substr() 函数用于截取字符串中指定位置指定长度的子串。函数原型如下:

 string substr (size_t pos = 0, size_t len = npos) const;
 //pos 的默认值是0,也就是从下标为0的位置开始截取
 
//len 的默认值是npos,意思是一直截取到字符串的末尾

substr() :如果函数不传参数,就是从下标为0的位置开始截取,直到结尾,得到的是整个字符串;

substr(pos) :从指定下标 pos 位置开始截取子串,直到结尾;

substr(pos, len) :从指定下标 pos 位置开始截取长度为 len 的子串。

#include <iostream>
#include<string>    

using namespace std;
 
int main()
{
    string s = "hello world hello everyone";
    string s1 = s.substr();
    cout << s1 << endl;
    //输出  hello world hello everyone
    string s2 = s.substr(7);
    cout << s2 <<endl;
    //输出 orld hello everyone
	
	string s3 = s.substr(7,6);
	cout << s3 << endl;
	//输出   orld h
    
    return 0;
}

substr() 和 find() 经常是配合使用的,find 负责找到位置, substr 从这个位置向后获得字符串。

#include <iostream>
#include<string>    

using namespace std;
 
int main()
{
	string s = "hello world hello everyone";
	//           0123456
	size_t n = s.find("world");
	
	string s1 = s.substr(n, 10);
    cout << s1 << endl; 
    //输出 world hell 
    
    return 0;
}

11. string的关系运算

在实际写代码的过程中经常会涉及到两个字符串比较大小,比如:判断你输入的密码是否正确,就得 将输入的密码和数据库中正确的密码比较。 那么两个 string 类型字符串是否可以比较大小呢?其实是可以的,C++中为string提供了一系列的关系运算。

支持的关系运算

 string s1 = "abc";
 string s2 = "abcd";
 char s3[] = "abcdef";
  //C风格的字符串
 
(1) s1 == s2
 bool operator== (const string& lhs, const string& rhs);
 //使用方式:s1 == s2 
bool operator== (const char*   lhs, const string& rhs);
//使用方式:s3 == s1 
bool operator== (const string& lhs, const char*   rhs);
//使用方式:s1 == s3 
(2) s1 != s2
 bool operator!= (const string& lhs, const string& rhs);
 //使用方式:s1 != s2 
bool operator!= (const char*   lhs, const string& rhs);
//使用方式:s3 != s1 
bool operator!= (const string& lhs, const char*   rhs);
//使用方式:s1 != s3 
(3) s1 < s2
 (4) s1 <= s2
 (5) s1 > s2
 (6) s1 >= s2
 bool operator<  (const string& lhs, const string& rhs);
 //使用方式:s1 < s2 
bool operator<  (const char*   lhs, const string& rhs);
//使用方式:s3 < s1 
bool operator<  (const string& lhs, const char*   rhs);
//使用方式:s1 < s3 
bool operator<= (const string& lhs, const string& rhs);
//使用方式:s1 <= s2 
bool operator<= (const char*   lhs, const string& rhs);
//使用方式:s3 <= s1 
bool operator<= (const string& lhs, const char*   rhs);
//使用方式:s1 <= s3 
bool operator>  (const string& lhs, const string& rhs);
//使用方式:s1 > s2 
bool operator>  (const char*   lhs, const string& rhs);
//使用方式:s3 > s1 
bool operator>  (const string& lhs, const char*   rhs);
//使用方式:s1 > s3 
bool operator>= (const string& lhs, const string& rhs);
//使用方式:s1 >= s2 
bool operator>= (const char*   lhs, const string& rhs);
//使用方式:s3 >= s1 
bool operator>= (const string& lhs, const char*   rhs);
//使用方式:s1 >= s3

上述的关系运算符的重载看着复杂,但是使用起来是非常简单的。

注: 关于操作符的重载,只有深入学习C++的类和对象,才能深入理解和掌握,在竞赛的课程中不需要深入挖掘,会使用就行,但是要使用C++进行工程性开发的时候这部分知识一定要补上。

字符串的比较是基于字典序进行的,比较是对应位置上字符的ASCII值的大小;比较的不是字符串的长度。

比如

"abc" < "aq"     
//'b'的ascii码值是?于'q'的
 
"abcdef" < "ff"  
//'a'的ASCII码值是?于'f'的
 
"100" < "9"
#include <iostream>
#include<string>
using namespace std;

int main()
{
    string s1 = "hello world";
    string s2 = "hello";
    if (s1 == (s2 + " world")) 
    {
       cout << "s1 == s2" << endl;
    }
    else
    {
        cout << "s1 != s2" << endl;
    }
    //输出 s1 =s2
    return 0;
 }
#include <iostream>
#include <string>    
using namespace std;

int main()
{
    string s1 = "abcd";
    string s2 = "abbcdef";
    char s3[] = "bbc";
    if (s1 > s2)
        cout << "s1 > s2" << endl;
    else
        cout << "s1 <= s2" << endl;
    if (s1 == s2)
        cout << "s1 == s2" << endl;
    else
        cout << "s1 != s2" << endl;
    if (s1 <= s3)
        cout << "s1 <= s3" << endl;
    else
        cout << "s1 > s3" << endl;
        //输出s1 > s2
        //s1 != s2
        //s1 <= s3 
        
    return 0;
 }

12. string和数字的转换函数

2.12.1 stoi/stol

• stoi 是将字符串转换成 int 类型的值

• stol 是将字符串转换成 long int 类型的值,这⾥以 stoi 为例讲解⼀下这里函数的使用方式。

stoi 函数其实可以将⼀个 string 类型的字符串,转化为整型,函数原型如下:

int stoi (const string&  str, size_t* idx = 0, int base = 10);
long stol (const string&  str, size_t* idx = 0, int base = 10);

参数解读:

• str 表示被转换的 string 类型的字符串

• idx 是一个输出型参数,也就是这个通过这个参数会带回一个值。 边创建一个 size_t 类型的值,传递它的地址给 idx 是一个指针,需要在外 idx ,这个参数将会带回 数字的第一个字符的位置。

• base 表示被解析的字符串中数字的进制值,可能是 2 , 8 , str 中无法正确匹配 10 , 16 或者 0  默认情况下这个值是 10 ,表示 10 进制数字

◦ 如果传递的是  2 ,表示被解析的字符串中是 2 进制的数字,最终会转换成 10 进制

◦ 如果传递的是 8 ,表示被解析的字符串中是 8 进制的数字,最终会转换成 10 进制

◦ 如果传递的是 16 ,表示被解析的字符串中是 16 进制的数字,最终会转换成 10 进制

◦ 如果传递的是 0 ,会根据字符串的内容的信息自动推导进制,比如:字符串中有0x,就认为 是 16 进制, 0 开头会被认为是 8 进制,最终会转换成 10 进制。 

#include <iostream>
#include<string>    
using namespace std;

int main()
{
    size_t pos = 0;
    string s1 = "11x34";
    int ret1 = stoi(s1, &pos, 16);
    cout << ret1 << endl;
    cout << "pos:" << pos << endl;
    string s2 = "11x34";
    int ret2 = stoi(s2, &pos, 2);
    cout << ret2 << endl;
    cout << "pos:" << pos << endl;
    string s3 = "0x11x34";
    int ret3 = stoi(s3, &pos, 0);
    cout << ret3 << endl;
    cout << "pos:" << pos << endl;
    //输出
	//17
    //pos:2
    //3
    //pos:2
    //17
    //pos:4
 
    
 return 0;
 }

2.12.2 stod/stof

 stod 是将字符串转换成 double 类型的值,函数原型如下,和 字符串中数字进制的参数,其他参数⼀致。  stoi 函数的⽐较的话,少了描述 stof 是将字符串转换成 flaot 类型的值。


 double stod (const string&  str, size_t* idx = 0);
 float stof (const string&  str, size_t* idx = 0);
#include <iostream>
#include<string>  
  
using namespace std;

int main()
{
    string s = "3.14x456";
    double ret = stod(s, NULL);
    cout << ret << endl;
    //输出 3.14 
    
    return 0;
 }

 to_string

函数原型如下:

    string to_string (int val);
    string to_string (long val);
    string to_string (long long val);
    string to_string (unsigned val);
    string to_string (unsigned long val);
    string to_string (unsigned long long val);
    string to_string (float val);
    string to_string (double val);
    string to_string (long double val);

tostring 函数可以将数字转换成字符串,从上述函数原型的角度看的话,可以将整型、浮点型的数 字转换成字符串的,使⽤起来也非常简单。

#include <iostream>
#include <string>    
using namespace std;

int main()
{
    string pi = "pi is " + to_string(3.14159);
    cout << pi << endl;
    //输出 pi is 3.141590 
    
    return 0;
 }

小提示

好咯,各位uu,这一篇就到这里完美结束啦~

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐