【C++】string类

目录

一、C++为什么要引入string类

二、标准库中的string类

三、string类的常用接口

3.1 string类的构造函数:(constructor)

3.2 string类对象的容量操作

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

3.4 string类对象的修改操作

3.5  string类非成员函数


一、C++为什么要引入string类

C++引入string类是为了提供一种更高级、更方便和更安全的字符串处理方式,相比于C语言中使用字符数组和库函数来处理字符串,引入string类有以下几个主要原因:

  1. 方便性:用户在使用字符数组处理字符串时,需要手动处理内存分配、长度计算、字符串拷贝等操作,代码复杂且容易出错。而string类封装了这些底层细节,提供了一系列成员函数来方便地进行字符串的拼接、截取、比较等常用操作,大大简化了字符串处理的过程。
  2. 动态内存管理:字符数组在存储字符串时需要手动分配足够的内存空间,并且固定大小不便扩展。而string类使用动态内存分配,可以根据字符串的需要自动调整内存大小,在字符串长度变化时更加灵活。
  3. 安全性:字符数组没有内置的边界检查机制,容易导致缓冲区溢出和访问越界等安全问题。string类通过封装内部的动态内存管理,提供了范围检查、安全的访问操作,避免了很多常见的安全漏洞。
  4. 高级功能和操作:string类提供了丰富的成员函数和操作符重载,使得字符串的处理更加灵活和高效。例如,可以直接使用"+"进行字符串的拼接,使用"<"和">"进行字符串的比较,还可以使用成员函数find()、replace()等方便地进行字符串的查找和替换。
  5. 面向对象的设计:C语言中字符数组和库函数是分离开的,不太符合C++中面对对象的思想。string类是C++的标准库中的一个类,遵循了面向对象的设计原则,通过封装数据和操作,使得代码更加模块化、可维护性更高。同时,string类还支持运算符重载、迭代器等特性,使得字符串处理可以更加符合C++的编程习惯。

总之,引入string类使得C++中的字符串处理更加便捷、安全和高级,提供了更多的功能和操作,减少了开发者的工作量,同时也提高了代码的可读性和可维护性。因此,使用string类能够在C++中更好地处理字符串。


二、标准库中的string类

先来看一下标准库中对于string类的介绍。

总结:

  1. string是表示字符序列的对象。
  2. string类提供的接口与常规容器的接口基本相同,但是添加了一些专门用来操作string的操作。
  3. string在底层实际是:basic_string模板类的别名,使用char类型和默认的char_traits allocator作为模板参数。
  4. 不支持操作多字节或变长字符的序列。

三、string类的常用接口

3.1 string类的构造函数:(constructor)

  • string();  
    构造空的string类对象,长度为0。
  • string (const string& str);
    拷贝构造str
  • string (const string& str, size_t pos, size_t len = npos);
    从pos位置拷贝str的n个字符(如果pos+len超过字符串末尾或者len为npos,就拷贝至字符串末尾结束)
  • string (const char* s);
    用字符串s(C-string)拷贝一个string类。
  • string (const char* s, size_t n);
    用字符串s(C-string)的前n个字符拷贝一个string类。
  • string (size_t n, char c);
    一个string类填充n个字符c。
void Test1()
{
    string s1;
	string s2("abcd");
	string s3(s2);
	string s4(s3, 1, 5);
	string s5("123456", 3);
	string s6(10, 'a');
}

3.2 string类对象的容量操作

  • size                   返回字符串有效字符长度
    size_t size() const;
  • length               返回字符串有效字符长度
    size_t length() const;
  • capacity           返回空间总大小
    size_t capacity() const;
  • empty               检测字符串释放为空串,是返回true,否则返回false
    bool empty() const;
  • clear                 清空有效字符
    void clear();
  • reserve            为字符串预留空间
    void reserve (size_t n = 0);
  • resize              将有效字符的个数该成n个,多出的空间用字符c填充
    void resize (size_t n);           void resize (size_t n, char c);

注: 

  1. size()与length()的实现原理相同,只是size()与其他接口容器一致,更适合使用习惯。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3.  reserve()为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。
  4. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是:当字符个数n大于有效字符长度时,resize(n)用 '\0' 来填充多出的元素空间,resize( n, c)用字符c来填充多出的元素空间
  5. resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  6. 知道需要空间大小时,reserve可以减少扩容,提高效率.
void Test2()
{
	string s1("1234567");

	s1.reserve(5);

	s1.clear();
	
	s1.resize(20, 'a');
}

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

  • operator[]   返回pos位置的字符的引用
    char& operator[] (size_t pos);   const char& operator[] (size_t pos) const;
  • begin + end 
    begin   获取第一个字符的迭代器,end获取最后一个字符下一个位置的迭代器

    iterator begin(); const_iterator begin() const;
    iterator end();    const_iterator end() const;
  • rbegin + rend
    rbegin  获取最后一个字符逆序的迭代器 ,rend获取第一个字符前一个位置的迭代器

    reverse_iterator rbegin(); const_reverse_iterator rbegin() const;
    reverse_iterator rend();    const_reverse_iterator rend() const;
  • 范围for   C++11支持更简洁的范围for的新遍历方式

注:

  1. operator[] 越界,程序直接终止。string::at() 越界,程序抛异常。
  2. 迭代器使用时要指定类域。
  3. 范围for自动判断结束,自动加加。若要修改,要使用auto& ,否则只是赋值给形参。
  4. 范围for不支持逆序。
void Test3()
{
	string s1("1234567");
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i];
	}
	cout << endl;

	string::iterator it = s1.begin();
	while (it != s1.end())
	{
		cout << *it;
		it++;
	}
	cout << endl;

	string::reverse_iterator it2 = s1.rbegin();
	while (it2 != s1.rend())
	{
		cout << *it2;
		it2++;
	}
	cout << endl;

	for (auto x : s1)
	{
		cout << x;
	}
	cout << endl;
}

3.4 string类对象的修改操作

  • push_back  在字符串后尾插字符c
    void push_back (char c);
  • append       在字符串后追加一个字符串
    string& append (const string& str);
    string& append (const string& str, size_t subpos, size_t sublen);
    string& append (const char* s);
    string& append (const char* s, size_t n);
    string& append (size_t n, char c); 
  • operator+= 在字符串后追加字符串str c_str(重点) 返回C格式字符串
    string& operator+= (const string& str);
    string& operator+= (const char* s);
    string& operator+= (char c); 
  • find           从字符串pos位置开始往后查找字符c/字符串,返回该字符在字符串中的位置
    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 (const char* s, size_t pos, size_t n) const;
    size_t find (char c, size_t pos = 0) const;
  • rfind         从字符串pos位置开始往前找字符c/字符串,返回该字符在字符串中的位置
    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 (const char* s, size_t pos, size_t n) const;
    size_t rfind (char c, size_t pos = npos) const;
  • substr     在str中从pos位置开始,截取n个字符,然后将其返回
    string substr (size_t pos = 0, size_t len = npos) const;

注:

  1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  2. 如果 find() / rfind() 没有匹配到字符,则返回string::npos(size_t类型的-1 )
void Test4()
{
	string s1("123");
	s1.push_back('~');
	s1.append("abc");
	s1 += "456";
	cout << s1 << endl;
	cout << s1.find("~a") << endl;
	cout << s1.find("xx") << endl;
	cout << s1.rfind("c4") << endl;
}

 

3.5  string类非成员函数

  • operator+        返回一个新创建的string对象,值为lhs和rhs相加的结果。
  • operator>>      输入运算符重载
  • operator<<      输出运算符重载
  • getline             获取一行字符串
  • relational operators  大小比较

注:

  1.  operator+ 尽量少用,因为传值返回,导致深拷贝效率低。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值