C++ sting类(一)各类操作

1、 C语言中的字符串

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,

但是这些库函数与字符串是分离开的,不太符合程序设计的思想,而且底层空间需要用户自己管理,稍不留神可

能还会越界访问

2. 标准库中的string类

注意:本文是在VS2019下操作学习,不同环境下一些结论可能不成立

2.1 string类

几个注意点:

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

2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作

3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>

string;

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

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

注意没有 .h 为 include<string>

2.2 string类的常用接口说明

1. string类对象的常见构造

(constructor)函数名称

功能

string() (重点)

构造空的string类对象,即空字符串

string(const char* s) (重点)

用C-string来构造string类对象

string(size_t n, char c)

string类对象中包含n个字符c

string(const string&s) (重点)

拷贝构造函数

#include<iostream>
using namespace std;
#include<string>

int main()
{
    string s1;

    string s2("hello");

    string s3(s2);//拷贝构造

    string s4(10, 'A');
        //十个A

    cout << s2 << endl;
    cout << s2 << endl;
    cout << s4 << endl;

    return 0;
}

2. string类对象的容量操作

函数名称

功能说明

size(重点)

返回字符串有效字符长度

length

返回字符串有效字符长度

capacity

返回空间总大小

empty (重点)

检测字符串释放为空串,是返回true,否则返回false

clear (重点)

清空有效字符

reserve (重点)

为字符串预留空间**

resize (重点)

将有效字符的个数该成n个,多出的空间用字符c填充

代码举例:

size\length\capacity\empty

void TestString2()
{
    string s("hello");
    cout << s.size() << endl;
    cout << s.length() << endl;
    cout << s.capacity() << endl;

    if (!s.empty())
    {
        cout << "s is not empty():"<<s << endl;
    }
    else
    {
        cout << "s is empty()"<<endl;
    }
    
    //将s中有效字符清空
    s.clear();
    cout << s.size() << endl;
}
int main()
{
    TestString2();

    return 0;
}

reserve

void TestString3()
{
    string s("hello");
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.reserve(20);
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.reserve(100);
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.reserve(80);
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.reserve(15);
    cout << s.size() << endl;
    cout << s.capacity() << endl;
}

通过reserve将string底层空间扩大,假设string底层旧空间大小为oldcapacity

如果newcapacity大于oldcapacity,空间确实会变大。

string类内部会按照一定机制跟进用户所传递的容量去计算新的容量

扩容机制:开辟新空间,拷贝元素,释放旧空间

但是:如果new<old && new>=16时,reserve会忽略本次操作,不会扩容缩小

new<16:reserve会将底层空间大小缩为15

问题:为什么new<16时,reserve才会真正将空间缩小?

因为在string对象内部包含了一个固定大小数组--》char buff[16]

原因:绝大多数情况下的字符串中的有效字符个数都是小于16 如人名等

直接使用固定大小的数组,不从堆上开辟空间可以让string类效率更高,

当有效元素超过16时,string类才真正从堆上开辟空间,从堆上开辟空间是有时间消耗,所以string类从堆上申请成功之后一般不会将空间缩小

resize

resize(size_t newsize, char ch='\0'):将有效元素个数修改到newsize,如果newsize大于string对象中原有的字符个数多出的字符就用ch填充

void TestString3()
{
    string s("hello");
    s.resize(10, 'A');
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.resize(20, 'B');
    s.resize(40, 'C');
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.resize(20);
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.resize(17);
    s.resize(16);
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    s.resize(15);
    s.resize(5);
    cout << s.size() << endl;
    cout << s.capacity() << endl;
}

当newsize小于string对象中有效元素个数时,将有效元素个数缩小到newsize个,缩小时不会改变容量

其他注意:

1. size()与length()方法底层实现原理完全相同,引入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不会改变容量大小

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

operator[]

越界检测操作

at也是访问任意位置元素的,处理越界方式不一样

begin+ end

begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器

4. string类对象的修改操作

push_back (char ch):往string尾部插入ch

append 和operator+= :在string中拼接单个字符,C格式的字符串,string对象

void TestString3()
{
    string s("hello");
    s.push_back(' ');//等价于s.append(1,' ');

    //拼接C格式字符串
    s += "world";//等价于 s.append("world");

    //拼接string对象
    string ss("zx");
    s += ss;//等价于 s.append(ss);

    s += 'A';
    cout << s << endl;
}

注意:

1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般

情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

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

insert

void TestString3()
{
    string s("hello");

    //在0号位置插入3个A
    s.insert(0, 3, 'A');
    cout << s << endl;

    s.insert(1, "bite");
    cout << s << endl;
}

erase删除

void TestString3()
{
    string s("hello world");
    //0号位置删6个
    s.erase(0, 6);
    cout << s << endl;

    //begin此时在w位置,+2在r位置,删掉
    s.erase(s.begin() + 2);
    cout << s << endl;

    s.erase(s.begin(), s.end());//等价于全部删除了
    cout << s << endl;
}

此处所能用的各种功能函数还有很多,不再一一举例,使用时搜索即可。

一些操作

void TestString3()
{
    string s("12435234");
    cout << s << endl;

    //逆置s
    reverse(s.begin(), s.end());
    cout << s << endl;

    //排序
    sort(s.begin(), s.end());
    cout << s << endl;
}

猜你喜欢

转载自blog.csdn.net/weixin_59215611/article/details/129205308