string类(1)

一、string类的作用

我们知道在C语言中, 字符串是一个以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离的, 不太符合面向对象编程的思想,并且底层空间需要用户自己进行管理, 稍不留神可能还会造成越界访问等问题,比较不方便。

而string类出现后我们能够向定义内置类型一样直接定义出一个字符串,不需要在使用C语言风格的char*类型的字符串了,并且string类里面包含了很多对字符串进行操作的成员函数,符合面向对象编程的思想,使得我们对字符串的控制更加简单,方便。

二、 标准库中的string类

2.1 string类

string类的标准文档

string类的基本介绍:

1. 字符串是表示字符序列的类。

2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符串的设计特性。

3. string类是使用char作为它的字符类型。

4. string类是basic_string模版类的一个实例, 它使用char来实例化basic_string模版类,并用char_traits和allocator作为basic_string的默认参数(更多的模版信息参考basic_string)。

5. 注意:这个类独立于所使用的编码来处理字节: 如果用来处理多字节或者变长字符(如UTF-8)的序列,这个类的所有成员以及迭代器,仍然按照字节来操作而不是按照实际编码的字符来操作。

总结:

1.string类是表示字符串的字符串类

2.该类的接口与常规容器的接口基本相同,在此基础上又增加了专门用来操作string的常规操作。

3.string在底层实现时是:basic_string模版类的别名, typedef basic_string<char , char_traits,  allocator> string;

4.不能操作多字节或者变长字符的序列。

使用string类的时候必须包含头文件<iostream> 和 using namespace std;

2.2 string类的常用接口介绍

2.2.1 string类对象的常见构造

函数名称 函数功能
string() (重点) 构造空的string类对象,即空字符串
string(const char* s) (重点) 用c风格的字符串来构造string类的对象
string(size_t n, char c) 构造string类对象中包含n个字符c
string(const string& s) (重点) 拷贝构造函数

 下面我们来看一下代码实例:

void test()
{
	string s1; //构造空的string类对象s1
	string s2("hello");//使用c风格的字符串构造string类对象s2
	string s3(s2); //使用拷贝构造函数用s2拷贝构造出s3

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
}

2.2.2 string类对象的容量操作

函数名称 函数功能
size() (重点) 返回字符串的有效字符长度
length()  返回字符串的有效字符长度与size()的功能相同
capacity()  返回字符串的容量
empty() (重点) 检测字符串是否为空串,为空则返回true,不为空返回false
clear() (重点) 清空字符串中的有效字符
reserve(size_t n)  (重点) 为字符串预留空间,可以进行扩容
resize(size_t n, char c) (重点) 将有效字符的个数改为n,多出来的空间用字符c来填充

 下面来看下这些函数的使用实例:

void test1()
{
	string s1;//空串
	string s2("hello string");
	string s3(s2);
	cout << s1.size() << " " << s1.length() << endl;
	cout << s2.size() << " " << s2.length() << endl;
	cout << s3.size() << " " << s3.length() << endl;
	cout << endl;
	
	cout << s1.capacity() << endl;
	cout << s2.capacity() << endl;
	cout << s3.capacity() << endl;
	cout << endl;

	cout << s1.empty() << endl;
	cout << s2.empty() << endl;
	cout << s3.empty() << endl;
	cout << endl;

	s3.clear();
	cout << s3.size() << " " << s3.capacity() << " " << s3.empty() << endl;
	s3.reserve(8);
	cout << s3.capacity() << endl;
	cout << endl;

	s2.resize(5, 'x');
	cout << s2 << endl;
	cout << s2.size() << " "  << s2.capacity() << endl;
	cout << endl;

}

注意:

1.size() 与 lenth()方法的底层实现原理是完全相同的, 引入size()的原因是为了与其他容器的接口保持一致,一般情况下都是使用size()。

2.clear()只是将string中的有效字符全部清空,但是不改变底层空间的大小,影响size()但不影响capacity()。

3.resize(size_t n) 与 resize(size_t n, char c)都是将字符串中的有效字符个数改变成n个,但是当字符个数增多时:resize(n)是用0来填充多出的元素空间,resize(size_t n, char c)是用字符c来填充多出的元素空间。

注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

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

函数名称 函数功能
operator[] (重点) 返回pos为之的字符,相当于将string类的对象当作数组使用
beign() 和 end() begin获取一个字符的迭代器,end获取最后一个字符的下一个位置的迭代器,++迭代器是向后遍历
rbeign()和rend()

反向迭代器,和begin与end相反

rbegin指向最后一个数据,rend指向第一个数据的前一个位置,++迭代器相当于向前遍历,相对于begin和end是相反的

范围for

C++11开始支持的更简洁的一种for循环的新遍历方式,可以使用迭代器遍历

注意:所有容器都支持范围for,for(auto e : s1);就是自动取s1中的对象赋值给e,自动++,自动判断结束,底层角度就是迭代器,在范围for里面如果需要修改数据的话auto后面要加上&。

begin() :任何容器返回第一个数据位置的iterator

end() : 任意容器返回最后一个数据的下一个位置的iterator

正向迭代器是iterator, 反向迭代器是reverse_iterator

iterator 可读可写的迭代器

const_iterator 只读 迭代器指向的数据不可写

const iterator 迭代器本身不能修改

下面看一下string类对象的访问和遍历的演示实例:

void test2()
{
	string s1("hello string");
	string s2(s1);
	//operator[]
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1[i];
	}
	cout << endl;
	//迭代器遍历
	string::iterator it1 = s2.begin();
	string::iterator it2 = s2.end();
	while (it1 != it2)
	{
		cout << *it1;
		it1++;
	}
	cout << endl;
	//反向迭代器
	string::reverse_iterator it3 = s2.rbegin();
	string::reverse_iterator it4 = s2.rend();
	while (it3 != it4)
	{
		cout << *it3;
		it3++;
	}
	cout << endl;


}

2.2.4 string类对象的修改工作

函数名称 函数功能
push_back 在字符串后尾插字符c
append

在字符串后面追加一个字符串

operator+= (重点) 在字符串后追加字符窜str
c_str(重点) 返回c风格的字符串
find和npos 从pos位置开始找字符c,返回该字符在字符串中的位置,npos代表末尾,值是size_t类型的-1,是整型最大值
rfind 从字符串pos位置开始向前找字符c,返回该字符在字符串中的位置
substr 在str中从pos位置开始,截取n个字符,然后将其返回

下面我们来看下string类对象的修改操作的使用演示实例:

void test3()
{
	string s1("hello string");
	string s2(s1);
	s1.push_back('x');
	s1.push_back('y');
	cout << s1 << endl;

	s2.append("abcde");
	cout << s2 << endl;
	s2.append(s1);
	cout << s2 << endl;

	s2.clear();
	s2 += s1;
	cout << s2 << endl;
	cout << s2.c_str() << endl;

	size_t pos = s2.find('x');
	cout << pos << endl;
	size_t rpos = s2.rfind('x');
	cout << rpos << endl;
	string str = s1.substr(0, 5);
	cout << str << endl;
}

注意:

1. 在string尾部追加字符时, s.push_back(c) / s.append(1, c) / s += 'c' 这三种的实现方式差不多,一般情况下string类的 += 操作用的比较多, += 操作不仅可以连接单个字符而且可以连接字符串。

2. 对string操作时,如果能够大概预估到放多少个字符,可以事先通过reserve把空间给预留好。

2.2.5 string类非成员函数

函数名称 函数功能
operator+ 尽量少用,因为是传值返回,导致深拷贝效率低
operator>> (重点) 流提取运算符重载(输入运算符重载)
operator<< (重点) 流插入运算符重载(输出运算符重载)
getline (重点) 获取一行字符串
relational operators (重点) 大小比较

下面是这些非成员函数的使用演示:

void test4()
{
	string s1("hello string");
	string s2("abcdefghijkmn");
	string s3;
	s3 = s1 + s2;
	cout << s3 << endl;
	s3.clear();
	getline(cin, s3);
	cout << s3 << endl;
}

 2.3补充

C++中的迭代区间都是左闭右开的,例如[first, last);

对于C++对象的修改工作中还有一个按pos位置进行插入的函数:insert函数

insert函数效率不够,时间复杂度是o(N),慎用,实践中的需求也不高。

还有一个按pos位删除的函数:erase函数

时间复杂度同样为o(N),效率也不高慎用。

需要注意的是以上两种函数都是string类中的成员函数,下面我们来看下这两个函数的使用实例:

void test5()
{
	string s1("abced");
	string s2("yyyy");
	s1.insert(s1.begin(), 'x');//在开头插入字符x
	cout << s1 << endl;
	s1.insert(0, s2);
	cout << s1 << endl;
	s1.erase(0, 4);//从0位置处删除4个字符
	cout << s1 << endl;
}

这篇博客到这里就结束了,后面的内容将在下一篇博客继续讲解。

相关推荐

  1. string(1)

    2024-05-16 07:00:16       38 阅读
  2. <span style='color:red;'>string</span><span style='color:red;'>类</span>

    string

    2024-05-16 07:00:16      46 阅读
  3. <span style='color:red;'>string</span><span style='color:red;'>类</span>

    string

    2024-05-16 07:00:16      31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-16 07:00:16       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-16 07:00:16       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-16 07:00:16       82 阅读
  4. Python语言-面向对象

    2024-05-16 07:00:16       91 阅读

热门阅读

  1. Git服务器(中心仓库(裸仓库))搭建

    2024-05-16 07:00:16       32 阅读
  2. VC++6.0自定义实现日志记录到文件及界面显示

    2024-05-16 07:00:16       33 阅读
  3. 分布式websocket实时通讯的session共享问题

    2024-05-16 07:00:16       32 阅读
  4. 安卓手机APP开发__支持64位的架构

    2024-05-16 07:00:16       30 阅读
  5. 16 | 缓存策略:如何使用缓存来减少磁盘IO?

    2024-05-16 07:00:16       34 阅读
  6. 如何玩转github

    2024-05-16 07:00:16       31 阅读
  7. Pinia:Vue 的强大存储库

    2024-05-16 07:00:16       36 阅读
  8. NIUKE Python:Python入门(上)

    2024-05-16 07:00:16       30 阅读
  9. python脚本编辑oss文件

    2024-05-16 07:00:16       29 阅读