C++string使用

Posted Suk-god

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++string使用相关的知识,希望对你有一定的参考价值。

文章目录

1、 为什么要学习string类

1、C语言中,字符串是以’\\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问

2、在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数

2、标准库中的string类

2.1了解string类

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型)
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

总结:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  4. 不能操作多字节或者变长字符的序列。

在使用string类时,必须包含#include<string>头文件以及using namespace std

2.2string类常用的接口

申明:以下的所有Windows平台测试均在VS2013环境下进行,期间也会有部分功能在Linux平台下测试

2.2.1 构造和析构相关

  1. (constructor)—构造

(1)string()
默认构造函数,得到的是一个长度为0的空串

(2)string(const string& str)
这是一个 拷贝构造函数,用已经存在的字符串str拷贝构造新的字符串
具体使用方式如下:

(3)sting(const string& str,size_t pos,size_t len = npos)
功能:使用字符串str的从pos下标开始,长度为len这一部分字符串来构造新的字符串(len是一个缺省参数,默认值为npos,如果不给定,默认到字符串str的末尾
功能演示

(4)string(const char* s)
使用C语言中的字符串来构造新的对string对象

(5)string(const char* s,size_t n);
使用C语言中的字符串s中的前n个字符来构造string对象

(6)string(size_t n,char c)
使用n个字符c来构造string对象

(7)template<class InputIterator>
string(InputIterator first,InputIterator last)

  1. (destructor)—析构
 ~string();

每个对象在生命周期结束时会自动调用该析构函数

  1. operator=—赋值
    (1)string& operator= (const string& str);
    (2)string& operator= (const char* s);
    (3)string& operator= (char c);

2.2.2 迭代器

暂时理解—是一个类似于指针的玩意儿
2. begin() && end()
iterator begin() | const_iterator begin() const;
iterator end() | const_iterator end() const;
3. rbegin() && rend()
reverse_iterator rbegin() | const_reverse_iterator rbegin() const;
reverse_iterator rend() | const_reverse_iterator rend() const;
画图解释:

2.2.3 容量相关

  1. size_t size() const;
  2. size_t length() const ;
    size() 和length()功能完全一致,都是获取字符串的有效长度
    展示:

疑问:为什么string要提供两个功能完全一致的方法size()和length()呢?

原因: length是因为沿用C语言的习惯而保留下来的,string类最初只有length,引入STL之后,为了兼容又加入了size,它是作为STL容器的属性存在的,便于符合STL的接口规则,以便用于STL的算法

  1. size_t capacity() const;
    获取string对象在底层维护的顺序表的容量

  2. void resize(size_t newsize); | void resize(size_t newsize,char c);
    resize—将string对象现有的有效元素个数更新为newsize个
    注意:newsize的值可以大于原来有效元素的个数,也可以小于。因此,我们在使用resize的时候要注意区分。具体情况见下图:

    下面我们通过代码验证上述的每个情况:
    ①验证newsize<= oldsize

    ②验证newsize > oldsize && newsize <= capacity

    ③验证newsize > olssize && newsize > capacity

  3. void reverse(size_t newcapacity = 0);
    作用:扩容,只改变容量,不会修改有效元素的个数
    假设string中原来的容量为oldcapacity,现在的参数为newcapacity

    验证:
    (1)newcapacity <= oldcapacity
    ①newcapacity <= oldcapacity && oldcapacity <= 15

    ②newcapacity <= oldcapacity && oldcapacity > 15 && newcapacity >15

    ③newcapacity <= oldcapacity && oldcapacity > 15 && newcapacity <=15

    为什么在newcapacity<=15 && oldcapacity > 15的情况下,缩小容量会变成15?
    原因分析:在string类的内部除了维护顺序表必须的三个成员以外,还有一个char array[BUF_SIZE],该数组的大小为16。具体如下图

    (2)newcapacity > oldcapacity
    会进行扩容,主要执行以下步骤:
    开辟新空间—>拷贝元素---->释放旧空间—>返回新空间

    验证string内部扩容的方式~
    Ⅰ在Windows平台下使用VS2013验证


    Ⅱ在Linux平台下验证

  4. void clear();
    清空有效元素,不改变空间大小

2.2.4 元素访问 && 元素遍历

元素访问

使用[]和at两类方法访问元素时,效果一样,只是针对于异常情况的处理方式不一样。具体区别如下:
(1)operator[]
char& operator[](size_t pos) | const char& operator[](size_t pos)const
在访问越界的时候,会触发assert断言,直接终止程序

(2)at
char& at(size_t pos) | const char& at(size_t pos) const
在访问越界的时候,会抛出异常,用户可以对其进行捕获

总结operator[] 与at:

(3)front----C++11
char& front(); | const char front()const
C++11中引入的新方法,获取string的第一个字符
(4)back----C++11
char& back(); | const char back()const
C++11中引入的新方法,获取string的最后一个字符

疑问:为什么这些元素访问类的函数,都会提供const和非const两份代码呢?

这个想要搞清楚,首先要明白const修饰成员函数后有哪些特性!(深入了解点这里)由于const对象不能调用非const的成员函数,所以必须提供两份代码。不然被const修饰对象就无法调用该方法,那也就意味着无法访问string的pos处的元素,这显然是不合理的!因此,对于这种元素访问类型的方法,需要提供两份代码!

元素遍历

(1)for循环+[]访问
(2)迭代器
(3)范围for
这个比较简单,直接看代码

int main()

	string str("hello");
	//for+[]
	for (int i = 0; i < str.size(); i++)
	
		cout << str[i];
	
	cout << endl;
	//迭代器
	string::iterator it = str.begin();
	while (it != str.end())
	
		cout << *it;
		it++;
	
	cout << endl;
	//范围for
	for (auto e : str)
	
		cout << e;
	
	cout << endl;
	return 0;


2.2.5 修改相关

  1. operator+=
    string& operator+=(const string& str);—末尾追加string
    string& operator+=(const char* s);----末尾追加C中的字符串
    string& operator+=(const char c);—末尾追加字符
  2. append
    string& append(const string& str);
    功能:末尾追加一个str

    string& append(const string& str,size_t subpos,size_t sublen);
    功能:将str从subpos开始,长度为sublen的子串追加到调用者的末尾

    string& append(const char* s);
    功能:在末尾追加一个C中的字符串

    string& append(const char* s,size_t n);
    功能:在末尾追加字符串s从0号位置开始,长度为n的子串

    string& append(size_t n,char c);
    功能:在末尾追加n个char类型的元素c

    template<calss IputIterator>
    string& append(InputIterator first,InputIterator last);
    功能:将迭代器first–last区间内的内容追加到字符串的末尾
  3. push_back
    void push_back(char c);
    功能:末尾追加一个字符c
  4. insert
    string& insert(size_t pos,const string& str);
    功能:在pos处,插入字符串str

    string& insert(size_t pos,const string& str,size_t subpos,size_t sublen);
    功能:在pos处插入str从subpos开始,长度为sublen的子串

    string& insert(size_t pos,const char* s);
    功能:在pos处插入C中的字符串s

    string& insert(size_t pos,const char* s,size_t n);
    功能:在pos处插入字符串s的前n个字符

    string& insert(size_t pos,size_t n,char c);
    void insert(iterator p,size_t n,char c);
    功能:在pos或者p处插入n个字符c
  5. erase
    string& erase(size_t pos = 0,size_t len = npos);
    功能:删除从pos开始,长度为len的子串。
    注意:pos和len均为缺省参数,默认删除整个字符串

    iterator erase(iterator p);
    功能:删除p位置的元素,返回下一个元素的位置

    注意:在删除字符串的最后一个位置时,返回值是非法的,无法再次被使用

    iterator erase(iterator first,iterator last);
    删除区间first–last之间的元素
  6. swap
    void swap(string& str);
    功能:交换两个string类型的对象,string::swap效率比全局的swap要高,在交换字符串的时候强烈建议使用string::swap

2.2.6 其他

  1. c_str
    const char* c_str() const;
    以C语言的方式返回字符串string
  2. find
    size_t find(const string& str,size_t pos = 0)const;
    功能:在目标字符串中查找str字符串出现的位置,默认从头开始查找。找到返回str首个字符在目标字符串中的位置,找不到返回npos

    size_t find(const char* s,size_t pos = 0)const;
    功能与上一个一致,唯一区别是这个查询的是C中的字符串
    size_t find(const char* s,size_t pos,size_t n)const;
    功能:查询C中字符串的前n个字符
    size_t find(char c,size_t pos=0)const;
    功能:查询字符c的位置,,哦人从0下标开始查询
  3. rfind
    功能与find类似,只不过是从字符串的末尾向起始位置查找
  4. find_first_of
    与find类似,只不过是查找第一次出现的某一个字符或字符串
    接口如下:

size_t find_first_of(const string& str,size_t pos=0)const;

找第1次出现string str的位置,默认从头开始查找

size_t find_first_of(const char*s,size_t pos=0)const;

找第1次出现C语言字符串s的位置,默认从头开始查找

size_tfind_first_of(const char* s,size_t pos,size_t n)const;

找第1次出现C语言字符串s从pos开始,长度为n的子串的位置,

size_t find_first_of(char c,size_tpos=0)const;

找第1次出现字符c的位置,默认从起始位置开始查找

  1. find_last_of
    与rfind类似,只不过是查找第一次出现的某一个字符或字符串
    接口如下:

size_t find_last_of(const string& str,size_t pos=npos)const;

找第1次出现string str的位置,默认从末尾开始查找

size_t find_last_of(const char*s,size_t pos=npos)const;

找第1次出现C语言字符串s的位置,默认从末尾开始查找 ③`size_t

find_last_of(const char* s,size_t pos,size_t n)const;`

找第1次出现C语言字符串s从pos开始,长度为n的子串的位置,

size_t find_last_of(char c,size_tpos=npos)const;

找第1次出现字符c的位置,默认从末尾开始查找

  1. substr
    string& substr(size_t pos,size_t len = mpos)const;
    功能:截取子串,pos为截取的起始位置,len表示截取的长度

ok~以上就是string容器的基本接口介绍及其使用,当然,这些也不是全部的接口,只是一些比较常用的接口!更下详细的可以参考http://www.cplusplus.com/
各位看官要是觉得有所收获,留下你们的足迹!

以上是关于C++string使用的主要内容,如果未能解决你的问题,请参考以下文章

C字符串末尾的'/0'问题

Gtk TextView - 将光标放置或移动到文本末尾?

c++中字符串为啥有两种形式? c-style 和 string 有啥区别?

如何使用c ++从字符串的末尾删除撇号

C语言中string指令是啥?

Java String.format用法