【C++初阶】第七篇:string的基础接口使用

string类的常用接口说明(只讲解最常用的接口)

一、 string类对象的常见构造

string类实现了多个构造函数的重载,常用的构造函数如下:

函数名称 功能说明
string() 构造一个空字符串
string(const char * s) 用字符串来构造string对象
string (const string& str) 拷贝构造函数
string(size_t n, char c) 用n个字符c来构造string对象
string(const char * s, size_t n) 从s指向的字符数组中复制前n个字符
string(const string& str, size_t pos, size_t len = npos) 复制str中从字符位置pos开始并跨越len个字符的部分

使用示例:

string s1;                     //构造空字符串
string s2("hello string");     //用"hello string"字符串来构造string对象 
string s3(s2);                 //拷贝构造
string s4 = "hello string"		//也是拷贝构造 --- string支持赋值运算符重载
string s5(10, 's');            //生成10个's'字符的字符串
string s6("hello string", 3);  //复制"hello string"的前3个字符给s5
string s7(s2, 0, 4);           //复制s2中从字符位置0开始并跨越4个字符的部分

二、 string类对象的访问及遍历操作

函数名称 功能说明
operator[ ] (重点) 返回pos位置的字符
正向迭代器:begin + end (重点) begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
反向迭代器:rbegin + rend begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
范围for (重点) C++11支持更简洁的范围for的新遍历方式

使用示例:

1. operator[ ]: 重载 [ ] 运算符

void test_string1()
{
    
    
	string s1("1234");
	// 遍历
	// 1、下标 []
	for (size_t i = 0; i < s1.size(); ++i)
	{
    
    
		s1[i]++;
	}
	cout << s1 << endl;
}

2. 范围for:

void test_string2()
{
    
    
	string s1("1234");
	// 2、范围for
	for (auto& ch : s1)
	{
    
    
		ch++;//每个字符加加
	}

	for (auto e : s1)
	{
    
    
		cout << e ;//遍历打印
	}
	cout << endl;
	//cout << s1 << endl;//也可以直接打印,
}

寻常循环遍历:

void test_string2()
{
    
    
	string s1("1234");
	// 反转一下
	size_t begin = 0, end = s1.size() - 1;//size()计算字符串有效字符个数
	while (begin < end)
	{
    
    
		swap(s1[begin++], s1[end--]);
	}
	cout << s1 << endl;

}

3. 迭代器:

1、与正向迭代器相关的函数
begin函数: 返回一个指向字符串第一个字符的迭代器。
在这里插入图片描述

函数原型:
    iterator begin();
 const_iterator begin() const;

end函数: 返回一个指向字符串结束字符的迭代器,即’\0’。
在这里插入图片描述

函数原型:
    iterator end();
 const_iterator end() const;

使用示例:

void test_string3()
{
    
    
	string s1("1234");
	//正向迭代器 --- 关键字:iterator
	string::iterator it1 = s1.begin();
	while (it1 != s1.end())
	{
    
    
		//每个字符加1
		*it1 += 1;
		++it1;
	}

	it1 = s1.begin();
	while (it1 != s1.end())
	{
    
    
		//遍历打印
		cout << *it1 << " ";
		++it1;
	}
	//2 3 4 5
	cout << endl;
}

注意: 正向迭代器用的bigin()和end()要搭配出现!

2、与反向迭代器相关的函数
rbegin函数: 返回指向字符串最后一个字符的反向迭代器。
在这里插入图片描述

函数原型:
    reverse_iterator rbegin();
 const_reverse_iterator rbegin() const;

rend函数: 返回指向字符串第一个字符前面的理论元素的反向迭代器。
在这里插入图片描述

函数原型:
    reverse_iterator rbegin();
 const_reverse_iterator rbegin() const;

使用示例:

void test_string3()
{
    
    
	string s1("1234");
	string::iterator it = s1.begin();
	while (it != s1.end())
	{
    
    
		//每个字符加1
		cout << *it << " ";
		++it;
	}
	cout << endl;
	
	//反向迭代器 --- 关键字:reverse_iterator
	string::reverse_iterator rit = s1.rbegin();
	//若觉得类型过长,书写麻烦,我们可以使用auto自动推导类型
	//auto rit = s1.rbegin();可自动推到类型
	while (rit != s1.rend())
	{
    
    
		//反向遍历
		cout << *rit << " ";
		++rit;
	}
	//5 4 3 2
	cout << endl;
}

注意: 反向迭代器用的rbigin()和rend()要搭配出现!

const 迭代器:
上述所示范的仅仅是非const迭代器,我们可以对字符串进行可读可写操作,而const迭代器只允许我们进行读操作。

在这里插入图片描述
综上我们可以作出迭代器表格总结:

迭代器(都可以用auto推导) 非const const
正向 (正向)可读可写(iterator)begin(),end() (正向)可读不可写(const_iterator)begin(),end()
反向 (反向)可读可写(reverse_iterator)rbegin(),rend() (反向)可读可写(const_reverse_iterator)rbegin(),rend()

4. 使用at访问对象中的元素
因为at函数也是使用的引用返回,所以我们也可以通过at函数修改对应位置的元素。
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");
	for (size_t i = 0; i < s.size(); i++)
	{
    
    
		//at(pos)访问pos位置的元素
		cout << s.at(i);
	}
	cout << endl;

	for (size_t i = 0; i < s.size(); i++)
	{
    
    
		//at(pos)访问pos位置的元素,并对其进行修改
		s.at(i) = 'x';
	}
	cout << s << endl; //xxxx
	return 0;
}

三、string类对象的容量操作

在这里插入图片描述

在这里插入图片描述

1、使用size函数或length函数获取当前有效字符的个数

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");
	cout << s.size() << endl; //4
	cout << s.length() << endl; //4
	return 0;
}

2、使用capacity函数获取当前对象所分配的存储空间的大小

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");
	cout << s.capacity() << endl; //15
	return 0;
}

3、使用max_size函数获取string对象最多可包含的字符数

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");
	cout << s.max_size() << endl; //4294967294
	return 0;
}

4、使用clear清除对象的内容,删除后对象变为空字符串

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");

	//clear()删除对象的内容,该对象将变为空字符串
	s.clear();
	cout << s << endl; //空字符串
	return 0;
}

5、使用empty判断对象是否为空
为空返回true,不为空返回false

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");
	cout << s.empty() << endl; //0

	//clear()删除对象的内容,该对象将变为空字符串
	s.clear();
	cout << s.empty() << endl; //1
	return 0;
}

6、resize功能

在这里插入图片描述
规则:

resize(n)
n<size 如果n小于当前字符串长度,则当前值将缩短到第n个字符,删除第n个字符以外的字符。
size<n<capacity 如果n大于size,且小于capacity,不产生扩容,将大于size的空间,若有给出指定字符c,则使用c填充,若c未给出,则默认为’\0’。
n>capacity 对字符串扩容,若给出的n大于对象当前的capacity,则capacity也会根据自己的增长规则进行扩大。

在这里插入图片描述

7、使用reserve改变当前对象的容量大小
在这里插入图片描述

reserve规则:
 1、当n大于对象当前的capacity时,将capacity扩大到n或大于n。
 2、当n小于对象当前的capacity时,什么也不做。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("CSDN");
	cout << s << endl; //CSDN
	cout << s.size() << endl; //4
	cout << s.capacity() << endl; //15

	//reverse(n)当n大于对象当前的capacity时,将当前对象的capacity扩大为n或大于n
	s.reserve(20); 
	cout << s << endl; //CDSN
	cout << s.size() << endl; //4
	cout << s.capacity() << endl; //31

	//reverse(n)当n小于对象当前的capacity时,什么也不做
	s.reserve(2);
	cout << s << endl; //CDSN
	cout << s.size() << endl; //4
	cout << s.capacity() << endl; //31
	return 0;
}

注意: 此函数对字符串的size没有影响,并且无法更改其内容。

8、shrink_to_fit的功能
在这里插入图片描述

四、 string类对象的修改操作

1. push_back:
  尾插一个字符

void test_string()
{
    
    
	string s1("hello world");
	s1.push_back(' ');
	s1.push_back('!');
	cout << s1 << endl;//hello world !
}

2. append:
  在字符串后追加一个字符串
  常用传参方式:

string& append (const string& str);
string& append (const char* s);
string& append (size_t n, char c);

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s1("I");
	string s2(" like");

	//append(string)完成两个string对象的拼接
	s1.append(s2); //I like

	//append(str)完成string对象和字符串str的拼接
	s1.append(" C++"); //I like C++

	//append(n, char)将n个字符char拼接到string对象后面
	s1.append(3, '!'); //I like C++!!!
	
	cout << s1 << endl; //I like C++!!!
	return 0;
}

3. operator+=(重点):
  string类中对+=运算符进行了重载,重载后的+=运算符支持string类的复合赋值、字符串的复合赋值以及字符复合的赋值
在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s1;
	string s2("hello");

	//支持string类的复合赋值
	s1 += s2;
	cout << s1 << endl; //hello

	//支持字符串的复合赋值
	s1 += " CSDN";
	cout << s1 << endl; //hello CSDN

	//支持字符的复合赋值
	s1 += '!';
	cout << s1 << endl; //hello CSDN!
	return 0;
}

4. insert:
  在pos位置插入
  常用传参方式:

string& insert (size_t pos, const string& str);
string& insert (size_t pos, const char* s);
iterator insert (iterator p, char c);

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("C"); //C

	//insert(pos, str)在pos位置插入字符串str
	s.insert(1, "S"); //CS

	//insert(pos, string)在pos位置插入string对象
	string t("D");
	s.insert(2, t); //CSD

	//insert(pos, char)在pos位置插入字符char
	s.insert(s.end(), 'N'); //CSDN
	
	cout << s << endl; //CSDN
	return 0;
}

5. erase:
  在pos位置删除
  常用传参方式:

string& erase (size_t pos = 0, size_t len = npos);//从pos位置删除len个字符,如果没有传len,则默认删除pos位置以及之后的所有字符
iterator erase (iterator p);
iterator erase (iterator first, iterator last);

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s("I like C++!!!");

	//erase(pos, n)删除pos位置开始的n个字符
	s.erase(8, 5); //I like C
	cout << s << endl; //I like C

	//erase(pos)删除pos位置的字符
	s.erase(s.end() - 1); //I like
	cout << s << endl; //I like

	//erase(pos1, pos2)删除[pos1pos2)上所有字符
	s.erase(s.begin() + 1, s.end()); //I
	cout << s << endl; //I
	return 0;
}

6. assign:
  assign可以理解成将原字符对象清空,重新进行赋值操作。
  常用传参方式:

string& assign (const string& str);
string& assign (const char* s);
string& assign (const char* s, size_t n);
string& assign (size_t n, char c);

void test_string()
{
    
    
	string s1("hello world hello world");
	string s2("CSDN");

	//将s1清空,替换指定string对象
	s1.assign(s2);
	cout << s1 << endl;//CSDN

	//将s1清空,替换指定字符串
	s1.assign("hello C++");
	cout << s1 << endl;//hello C++

	//将s1清空,替换指定字符串的一部分
	s1.assign("hello C++", 5);
	cout << s1 << endl;//hello

	//将s1清空,替换n个指定的字符
	s1.assign(5, '!');
	cout << s1 << endl;//!!!!!
}

7. replace:
  repalce是对字符对象的部分取代。
  常用传参方式:

string& replace (size_t pos, size_t len, const string& str);
string& replace (size_t pos, size_t len, const char* s);

void test_string()
{
    
    
	string s1("hello world hello world");
	string s2("CSDN");

	//从第六个下标位置开始,将五个字符替换成s2对象
	s1.replace(6, 5, s2);
	cout << s1 << endl;//hello CSDN hello world

	//从第六个下标位置开始,将五个字符替换成指定字符串
	s1.replace(6, 5, "C++");
	cout << s1 << endl;//hello C++hello world
}

8. find:
  使用find函数正向搜索第一个匹配项
  常用传参方式:

size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
size_t find (char c, size_t pos = 0) const;

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s1("http://www.cplusplus.com/reference/string/string/find/");

	//find(string)正向搜索与string对象所匹配的第一个位置
	string s2("www");
	size_t pos1 = s1.find(s2);
	cout << pos1 << endl; //7

	//find(str)正向搜索与字符串str所匹配的第一个位置
	char str[] = "cplusplus.com";
	size_t pos2 = s1.find(str);
	cout << pos2 << endl;  //11

	//find(char)正向搜索与字符char所匹配的第一个位置
	size_t pos3 = s1.find(':');
	cout << pos3 << endl; //4
	return 0;
}

9. rfind:
  使用rfind函数反向搜索第一个匹配项
  常用传参方式:

size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;
size_t rfind (char c, size_t pos = npos) const;

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s1("http://www.cplusplus.com/reference/string/string/find/");

	//rfind(string)反向搜索与string对象所匹配的第一个位置
	string s2("string");
	size_t pos1 = s1.rfind(s2);
	cout << pos1 << endl; //42

	//rfind(str)反向搜索与字符串str所匹配的第一个位置
	char str[] = "reference";
	size_t pos2 = s1.rfind(str);
	cout << pos2 << endl;  //25

	//rfind(char)反向搜索与字符char所匹配的第一个位置
	size_t pos3 = s1.rfind('/');
	cout << pos3 << endl; //53
	return 0;
}

10. substr
  使用substr函数提取string中的子字符串

string substr (size_t pos = 0, size_t len = npos) const;//提取pos位置开始的len个字符序列作为返回值

提取文件的后缀

void test_string()
{
    
    
	// "Test.cpp"
	// "Test.cpp.tar"
	string file;
	cin >> file;
	// 要求取后缀
	//应该使用rfind,因为有些文件名可能有两个点
	size_t pos = file.rfind('.');
	if (pos != string::npos)
	{
    
    
		//string suffix = file.substr(pos, file.size() - pos);
		string suffix = file.substr(pos);//提取pos位置开始的len个字符序列作为返回值

		cout << suffix << endl;
	}
}

11.c_str
  获取字符数组首地址,用C字符串的形式遍历

const char* c_str() const;

void TestString()
{
    
    
	//获取字符数组首地址,用C字符串的形式遍历
	string s1("hello world");
	const char* str = s1.c_str();
	while (*str)
	{
    
    
		cout << *str << " ";
		str++;
	}
	cout << endl;
	s1 += '\0';
	s1 += " hello";
	cout << s1 << endl;           //调用的string重载operator<<  将对象数组中所有字符都输出
	cout << s1.c_str() << endl;   //直接输出const char* 遇到\0结束
}

在这里插入图片描述
在这里插入图片描述

五、 string类非成员函数

在这里插入图片描述
1.operator+
string类中对+运算符进行了重载,重载后的+运算符支持以下几种类型的操作:
 string类 + string类
 string类 + 字符串
 字符串 + string类
 string类 + 字符
 字符 + string类
它们相加后均返回一个string类对象。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s;
	string s1("hello");
	string s2("world");
	char str[] = "wyt";
	char ch = '!';

	//string类 + string类
	s = s1 + s2;
	cout << s << endl; //helloworld

	//string类 + 字符串
	s = s1 + str;
	cout << s << endl; //hellowyt

	//字符串 + string类
	s = str + s1;
	cout << s << endl; //wythello

	//string类 + 字符
	s = s1 + ch;
	cout << s << endl; //hello!
	
	//字符 + string类
	s = ch + s1;
	cout << s << endl; //!hello
	return 0;
}

2. operator>> 和 operator<<
string类中也对>>和<<运算符进行了重载,这就是为什么我们可以直接使用>>和<<对string类进行输入和输出的原因。

istream& operator>> (istream& is, string& str);
ostream& operator<< (ostream& os, const string& str);

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s;
	cin >> s; //输入
	cout << s << endl; //输出
	return 0;
}

3. relational operators
string类中还对一系列关系运算符进行了重载,它们分别是==、!=、<、<=、>、>=。重载后的关系运算符支持string类和string类之间的关系比较、string类和字符串之间的关系比较、字符串和string类之间的关系比较。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s1("abcd");
	string s2("abde");
	cout << (s1 > s2) << endl; //0
	cout << (s1 < s2) << endl; //1
	cout << (s1 == s2) << endl; //0
	return 0;
}

注意: 这些重载的关系比较运算符所比较的都是对应字符的ASCII码值。

4. getline
我们知道,使用>>进行输入操作时,当>>读取到空格便会停止读取,基于此,我们将不能用>>将一串含有空格的字符串读入到string对象中。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s;
	cin >> s; //输入:hello CSDN
	cout << s << endl; //输出:hello
	return 0;
}

这时,我们就需要用getline函数完成一串含有空格的字符串的读取操作了。

用法一:

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

getline函数将从is中提取到的字符存储到str中,直到读取到换行符’\n’为止

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s;
	getline(cin, s); //输入:hello CSDN
	cout << s << endl; //输出:hello CSDN
	return 0;
}

用法二:

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

getline函数将从is中提取到的字符存储到str中,直到读取到分隔符delim或换行符’\n’为止。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    
    
	string s;
	getline(cin, s, 'D'); //输入:hello CSDN
	cout << s << endl; //输出:hello CS
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_58124165/article/details/129803689