【C++】string类的使用

目录

 string类对象的默认成员函数

 string类对象的容量操作

string中元素访问及遍历

 遍历方式1:下标+[]

遍历方式2: 迭代器

遍历方式3: 范围for

string类对象的修改操作

string类非成员函数

总结



string,也就是串或者字符数组,可以扩容,可以增删查改

接下来我们通过对Cplusplus的string的文档阅读来了解string的常见接口~

 string类对象的默认成员函数

string类对象的构造(包括拷贝构造)

其中,常见的函数和功能如下表:

函数名称功能说明
string() 构造空的string类对象,即空字符串
string(const string&str) 拷贝构造函数
string(const char* s) 用C-string来构造string类对象

void test_string()
{

	string s1;
	string s2("hello world");
    string s3(s2);
}

string类对象的赋值运算符重载

 string类对象的容量操作

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty 检测字符串释放为空串,是返回true,否则返回false
clear 清空有效字符
reserve (重要)为字符串预留空间**
resize (重要)将有效字符的个数该成n个,多出的空间用字符c填充

void test_string()
{
	string s1("hello world hello C++");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	cout << s1.max_size() << endl;
}

resize(影响size和capacity)

void test_string()
{
	string s1;
	//s1.resize(5, '0');
	s1.resize(5);
	s1[4] = '3';
	s1[3] = '4';
	s1[2] = '5';
	s1[1] = '6';
	s1[0] = '7';
	// 76543

	// 插入(空间不够会扩容)
	string s2("hello world");
	s2.resize(20, 'x');

	// 删除
	s2.resize(5);
}

reserve(影响capacity)

void test_string()
{
    string s1("111111111");
	cout << s1.capacity() << endl;

	s1.reserve(100);
	cout << s1.capacity() << endl;

	s1.reserve(20);
	cout << s1.capacity() << endl;
}

注意:
1. size()与length()方法底层实现原理完全相同,length的实现是C++发展的历史原因

其他容器的接口的我们都是用size()的,一般情况下基本都是用size()
2. clear()只是将string中有效字符清空,不改变底层空间大小

3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小


string中元素访问及遍历

函数名称功能说明
operator[] 返回pos位置的字符,const string类对象调用
begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭
代器
rbegin + rendbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭
代器
范围forC++11支持更简洁的范围for的新遍历方式

 遍历方式1:下标+[]

void test_string()
{
	string s1("hello world");
	cout << s1.size() << endl;

	for (size_t i = 0; i < s1.size(); i++)
	{
		//cout << s1.operator[](i) << " ";
		cout << s1[i] << " ";
	}
	cout << endl;
}

void test_string()
{	
    const string s("hello world");
	// 不可修改
	//s[0] = 'x';
}

遍历方式2: 迭代器

(正向迭代器和反向迭代器,各两种)

正向迭代器

void test_string()
 {
    string s1("hello world");
	//string::iterator it1 = s1.begin();
	auto it1 = s1.begin();
	while (it1 != s1.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
}
void test_string()
{  
    const string s1("hello world");
	//string::const_iterator it1 = s1.begin();
	auto it1 = s1.begin();
	while (it1 != s1.end())
	{
		// 不能修改
		//*it1 += 3;

		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
}

反向迭代器(反过来遍历):

void test_string()
{
	string s2("hello world");
	//string::reverse_iterator it2 = s2.rbegin();
	auto it2 = s2.rbegin();
	while (it2 != s2.rend())
	{
		cout << *it2 << " ";
		++it2;
	}
	cout << endl;

}

  void test_string()
{
   const string s1("hello world");
   //string::const_reverse_iterator cit1 = s1.rbegin();
	auto cit1 = s1.rbegin();
	while (cit1 != s1.rend())
	{
		// 不能修改
		//*cit1 += 3;

		cout << *cit1 << " ";
		++cit1;
	}
	cout << endl;
}

遍历方式3: 范围for

void test_string()
//底层角度,就是迭代器
{
  for (auto& e : s1)
  {
	cout << e << " ";
  }
  cout << endl;
}

string类对象的修改操作

string中插入和查找等

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+=在字符串后追加字符串str
c_str返回C格式字符串
find + npos从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回


void test_string()
{
	string s1("hello world");
    cout << s1 << endl;

	s1.push_back('x');
	cout << s1 << endl;

	s1.append(" yyyyyy!!");
	cout << s1 << endl;

	string s2("111111");

	s1 += 'y';
	s1 += "zzzzzzzz";
	s1 += s2;
	cout << s1 << endl;
}

接下来看一下insert和erase

void test_string()
{
	string s1("hello world");
	cout << s1 << endl;

	// 慎用,因为效率不高 -> O(N)
	// 实践中需求也不高
	string s2("hello world");
	s2.insert(0, "xxxx");
	cout << s2 << endl;

	s2.insert(0, 1,'y');
	cout << s2 << endl;

	s2.insert(s2.begin(), 'y');
	cout << s2 << endl;

	s2.insert(s2.begin(), s1.begin(), s1.end());
	cout << s2 << endl;
}

void test_string()
{
	string s1("hello world");
	cout << s1 << endl;

	// erase效率不高,慎用,和insert类似,要挪动数据
	s1.erase(0, 1);
	cout << s1 << endl;

	//s1.erase(5);//不传
	s1.erase(5, 100);//传个很大的
	cout << s1 << endl;
}

下面看一下replace:

void test_string()
{
// replace效率不高,慎用,和insert类似,要挪动数据
string s2("hello world");
s2.replace(5, 1, "%20");
cout << s2 << endl;

//功能实现:把所有空格都替换成 "%20"
//方法1
string s3("hello world hello C++");
for (size_t i = 0; i < s3.size();)
{
	if (s3[i] == ' ')
	{
		s3.replace(i, 1, "%20");
		i += 3;
	}
	else
	{
		i++;
	}
}
cout << s3 << endl;

//方法二
string s4("hello world hello C++");
string s5;
for (auto ch : s4)
{
	if (ch != ' ')
	{
		s5 += ch;
	}
	else
	{
		s5 += "%20";
	}
}

}

int main()
{
	string url("https://legacy.cplusplus.com/reference/string/string/substr/");

	size_t pos1 = url.find(':');
	string url1 = url.substr(0, pos1 - 1);
	cout << url1 << endl;

	size_t pos2 = url.find('/', pos1 + 3);
	string url2 = url.substr(pos1 + 3, pos2 - (pos1 + 3));
	cout << url2 << endl;

	string url3 = url.substr(pos2 + 1);
	cout << url3 << endl;
	return 0;
}

string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> 输入运算符重载
operator<< 输出运算符重载
getline 获取一行字符串


 

int main()
{
	string s1 = "hello";
	string s2 = "world";

	string ret = s1 + s2;
	cout << ret << endl;

	string ret2 = s1 + "xxxxx";
	cout << ret2 << endl;
    
    //第三种用法就是为什么要将operator+ 设置成非成员函数的原因
	string ret3 = "xxxxx" + s2;
	cout << ret3<< endl;

	return 0;
}

最后我们来看一下getline 

这个函数我们要搭配一道题来看:

字符串最后一个单词的长度_牛客题霸_牛客网

这道题,我们可能会这么写:

int main() 
{
    string str;
    cin>>str;
    size_t pos = str.rfind(' ');
    cout << str.size() - (pos+1) << endl;

    return 0;
}

但是,这样写的结果是:

为什么?因为它遇到空格就结束了,cin或者scanf默认规定空格或者换行是多个值的分割

那么,如何才能完整的提取呢 ?

接下来我们看一下getline

它是默认遇到换行才结束,当然,这个结束符也可以由我们来 自定义

知道了getline,我们就可以将上面的代码进行修改

int main() 
{
    string str;
    getline(cin, str); 
    size_t pos = str.rfind(' ');
    cout << str.size() - (pos+1) << endl;

    return 0;
}

总结

对于string类的常用接口使用我们就先说到这里,另外,值得在这里强调对于一些接口的使用我们可以去查文档进行理解使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃肉的Humble

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值