string的认识和使用

目录

 一、网站上查看string类

1.网站

2.网站上的string类

二、string类的成员函数

1.默认成员函数

(1)构造函数、拷贝构造函数和析构函数

(2)赋值运算符重载

(3)容量操作

(4)迭代器(iterator)

(5)元素访问

(6)修改操作

(7)其他成员函数

三、string类的非成员函数


 一、网站上查看string类

1.网站

还记得在C语言中我推荐的两个查看库函数的工具吗?其中一个是一个网站叫cplusplus;另一个是一个应用程序叫MSDN。自此我们在学习C++的过程中要经常用到cplusplus这个网站。

网址是:https://cplusplus.com

打开后是这样的,最近这个网站改版了,新版的网站不好用,我们可以点击右上角的[legacy version]切换到旧版本。

切换到旧版本

2.网站上的string类

我们可以在上面搜索string,得到这样的一个类

下面还有各种成员函数,也都给出了各自的使用方法。

二、string类的成员函数

在成员函数的第一部分就是string的默认成员函数:构造函数、拷贝构造函数、析构函数和赋值运算符重载

1.构造函数、拷贝构造函数和析构函数

string的构造与拷贝构造函数有很多,常用的有以下四个:

string();——————不传参的默认构造,构造空string对象,即空字符串

string(const string& str);——————用一个string变量初始化另一个string变量

string(const char* s);——————用一个C语言字符串初始化一个string变量

string(size_t n, char c);——————用一个字符初始化一个string变量让其包含n个字符c

这是官方库中实现的构造函数,在网站上我们可以看到它们的参数和使用,每个接口的使用都有详细的解释。

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test()
{
    string s1;
    cout << s1 << endl;

    string s2("hello world");
    cout << s2 << endl;

    string s3(s2);
    cout << s3 << endl;

    string s4(10, 'x');
    cout << s4 << endl;
}

int main()
{
    test();
    return 0;
}

测试结果:

string类的底层组织形式与顺序表一样,由于析构函数不可重载的特性也只能有一个:~string(),负责释放字符串内容占用的空间。

2.赋值运算符重载

string& operator= (const string& str);——————将str的内容赋值给左侧变量

string& operator= (const char* s);——————将字符串的内容赋值给左侧变量

string& operator= (char c);——————将字符赋值给左侧变量

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world");

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

    string s3;
    s3 = "hello";
    cout << s3 << endl;

    string s4;
    s4 = 'x';
    cout << s4 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

3.容量操作

容量操作包含以下内容,其中C++11标准中新出现的函数后面有标注

size_t size() const;——————返回string有效数据的长度

size_t length() const;——————返回string有效数据的长度

length和size在使用上没有区别,因为我们以后会知道STL的其他类和string是类似的,有些数据结构使用比如顺序表、链表为基础的类使用length表示元素个数更好理解,而对于书和图等数据结构使用size表示元素个数更好理解,所以这两个函数都被保留了下来。

size_t max_size() const;——————返回string可储存的字符串长度上限

就是无符号整形最大值,此接口在使用中没有意义

size_t capacity() const;——————返回开辟空间的大小

void reserve (size_t n = 0);——————如果n值大于当前的空间大小,便扩大空间到n个字符,小于则不做改变。但输入的改变后的空间大小不能小于字符串的长度

void clear();——————清除string的内容为空字符串,但不释放空间

bool empty() const;——————检测当前string是否是空字符串

void resize (size_t n, char c);——————改变空间大小,若新空间大于旧空间插入对应字符,小于则直接截断

void shrink_to_fit();——————将string的容量缩小到有效数据的大小

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");
    cout << "字符串长度:" << s1.size() << endl;
    cout << "空间可容纳元素的个数:" << s1.capacity() << endl;
    cout << "字符串空间最大值:" << s1.max_size() << endl;
    cout << "0为假,1为真:" <<s1.empty() << endl;

    s1.reserve(13);
    cout << "字符串长度:" << s1.size() << endl;
    cout << "空间可容纳元素的个数:" << s1.capacity() << endl;

    s1.reserve(18);
    cout << "字符串长度:" << s1.size() << endl;
    cout << "空间可容纳元素的个数:" << s1.capacity() << endl;

    s1.resize(20, 'x');
    cout << s1 << endl;

    s1.clear();
    cout << s1;
}

int main()
{
    test2();
    return 0;
}

测试结果:

4.迭代器(iterator)

迭代器是一个类似于指针的东西,它的使用与指针非常类似。

我们看一段代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");//s1初始化为hello world
    string::iterator it = s1.begin();
    //it是string类的迭代器变量s1.begin()表示s1字符串内容的首个字符位置
    while (it != s1.end())//s1.end()表示s1内字符串的末尾位置的后一位    
    {
        printf("%c", *it);
        it++;
    }
    cout << endl;
}

int main()
{
    test2();
    return 0;
}

 这个程序可以遍历string字符串的每一个字符,也就相当于遍历数组的每个元素,迭代器可以像指针一样进行加减,也可以通过解引用得到相应内容。但为什么说迭代器是一个类似于指针的东西呢?因为在string类中的迭代器使用与指针相同,但是在STL的链表中也存在list的迭代器,链表在遍历的时候也可以用加一的形式找下一个元素位置,指针加一的遍历方式就不对了,所以说很像但不是。

我们主要学习两个迭代器:正向和反向迭代器

string的正向迭代器

iterator begin();——————string字符串的头,可读可写

const_iterator begin() const;——————string字符串的头,只读

iterator end();——————string字符串的尾,可读可写

const_iterator end() const;——————string字符串的尾,只读

string的反向迭代器

reverse_iterator rbegin();——————string字符串逆向的头,可读可写

const_reverse_iterator rbegin() const;——————string字符串逆向的头,只读

reverse_iterator rend();——————string字符串逆向后的尾,可读可写

const_reverse_iterator rend() const;——————string字符串逆向的尾,只读

所有迭代器的头都是正向或反向的首元素,尾都是尾元素的位置。

  • 创建迭代器对象it1时,必须指明是哪个类的正向或反向迭代器。
  • 使用类成员函数的begin获得数据当前顺序的起始位置。
  • 使用类成员函数的end获得数据当前顺序的结束位置。
  • 将迭代器解引用可访问字符串中的特定元素。

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");
    string::iterator it1 = s1.begin();
    while (it1 != s1.end())
    {
        printf("%c", *it1);
        it1++;
    }
    cout << endl;
    string::reverse_iterator it2 = s1.rbegin();
    while (it2 != s1.rend())
    {
        printf("%c", *it2);
        it2++;
    }
    cout << endl;
    string::iterator it3 = s1.begin();
    while (it3 != s1.end())
    {
        *it3 = 'x';
        it3++;
    }
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

 测试结果:

下面的cbegin、cend、crbegin、crend其实就是将只读的迭代器独立又实现了一遍,我们的使用中很少会用到它们。

5.元素访问

operator[]——————直接重载[]使s[i]就可以直接访问对应下标元素,而且也加上了越界的检查,提高了程序的安全性。

char& operator[] (size_t pos);——————可读可写

const char& operator[] (size_t pos) const;——————只读

at函数——————与[]作用相同

char& at (size_t pos);——————可读可写

const char& at (size_t pos) const;——————只读

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");
    cout << s1[1] << endl;
    cout << s1.at(1) << endl;
    s1[1] = 'a';
    cout << s1 << endl;
    s1.at(1) = 'b';
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

6.修改操作

operator+=—————不同数据的尾插,这个用的最多

string& operator+= (const string& str);——————尾插string变量

string& operator+= (const char* s);——————尾插字符串

string& operator+= (char c);——————尾插字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello");
    cout << s1 << endl;
    s1 += '_';
    cout << s1 << endl;
    string s2("wor");
    s1 += s2;
    cout << s1 << endl;
    s1 += "ld!";
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

string& append(const char* s)——————尾插多个多个字符,内部重载函数很多

assign——————将原本的内容删除然后放入相应数据

string& assign (size_t n, char c);——————将对象赋值为n个c字符

string& assign (size_t n, char c);——————将对象赋值为n个c字符

string& assign (size_t n, char c);——————将对象赋值为n个c字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("xxxxxxxxxxxxx");
    string s2("hello world!");
    s1.assign(s2);
    cout << s1 << endl;

    s1.assign("abcdef");
    cout << s1 << endl;

    s1.assign(5, 'x');
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

void push_back(char c);——————尾插一个字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world");
    cout << s1 << endl;
    s1.push_back('!');
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

insert——————在特定位置插入内容

string& insert (size_t pos, const string& str);——————在pos下标位置插入str变量的内容

string& insert (size_t pos, const char* s);——————在pos下标位置插入字符串

string& insert (size_t pos, size_t n, char c);——————在pos下标位置插入n个c字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("to ");
    cout << s1 << endl;

    string s2("Welcome ");
    s1.insert(0, s2);
    cout << s1 << endl;

    s1.insert(11, "Tianjin,");
    cout << s1 << endl;

    s1.insert(19, 5, 'x');
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

使用insert也能够实现头插,将指定位置的写为0即可,但是顺序表的头插需要移动数据,是一个O(N^2)的程序,效率低,所以能不用则不用。

erase——————清除内容

string& erase(size_t pos = 0; size_t len = npos);——————清除对应下标开始向后数n个字符,这两个参数都是缺省的,我们如果不输入pos,会默认从头开始删;如果我们不输入len,len就会被赋值为npos,也就是无符号整形的最大值。

npos是一个静态成员变量,是无符号整形的最大值

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("Welcome to Shanghai!");
    cout << s1 << endl;

    s1.erase(11, 9);
    cout << s1 << endl;

    s1.erase();
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

replace——————替换内容

string& replace (size_t pos, size_t len, const string& str);——————将长度为n的原字符串内容替换为str变量的内容

string& replace (size_t pos, size_t len, const char* s);——————将长度为n的原字符串内容替换为另一个字符串的内容

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("Welcome to Shanghai!");
    cout << s1 << endl;

    string s2("Tientsin");
    s1.replace(11, 8, s2);
    cout << s1 << endl;

    s1.replace(11, 8, "Tianjin");
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

7.其他成员函数

const char* c_str() const;——————将string变量转换为C字符串返回

find——————在string变量中从头部开始找子串,pos是开始找字串的位置,返回第一次出现子串的头位置

size_t find (const string& str, size_t pos = 0) const;——————以string变量找子串

size_t find (const char* s, size_t pos = 0) const;——————以字符串找子串

rfind——————在string变量中从尾部开始找子串,pos是开始找字串的位置,返回第一次出现子串的头位置

size_t rfind (const string& str, size_t pos = npos) const;——————以string变量找子串

size_t rfind (const char* s, size_t pos = npos) const——————以字符串找子串

string substr (size_t pos = 0, size_t len = npos) const;——————取字符串pos下标开始的len个字符形成string对象,返回该对象。

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world1");
    char arr[20] = "hello world2";
    string s2("o");
    printf("%s\n", s1.c_str());
    printf("%d %d\n", s1.find("o"), s1.find(s2));
    printf("%d %d\n", s1.rfind("o"), s1.rfind(s2));
    cout << s1.substr(6, 5) << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

三、string类的非成员函数

除了流插入和流提取的重载,我还想讲以下getline和流插入重载的区别

流插入和流提取一个是输入一个是输出,流插入类似于C语言中的scanf,scanf读取到空字符就会直接结束;C语言中也提供了一个gets函数,这样就可以继续读取空字符了,同样string中的getline也是一个道理

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1;
    cin >> s1;//我输入hello world
    cout << s1 << endl;//s1只读取到空格之前的部分,输出:hello

    string s2;
    getline(cin, s2);//getline可以读取空字符,将剩余的空格+world读取
    cout << s2 << endl;//输出: world
}

int main()
{
    test2();
    return 0;
}

测试结果:

string类是我们学习STL(标准模板库)的开始,STL是使用C++的利器,它的内部定义了我们之前熟悉的各种数据结构类和接口提供我们使用,这样我们不需要像C语言一样自己去实现各种函数。

string类历史悠久,在STL出现之前string就已经存在了,所以它会有很多在我们看来重复冗余的内容,所以我们也可以在代码的使用过程中感受到C++的发展。

标准模板库_百度百科 (baidu.com)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
string STL(标准模板库)是C++标准库中的一部分,用于处理字符串的类模板。该类提供了一系列接口,用于操作字符串。string类的底层实际上是基于basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> stringstring类可以通过多种方式进行构造,比如构造空字符串、拷贝字符串序列、复制字符等。另外,string类还提供了查找子串的功能,可以截取给定字符串中从指定位置开始的指定长度的字符。总的来说,string STL是C++中处理字符串的一个重要工具。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【C++】-- STL之String详解](https://blog.csdn.net/gx714433461/article/details/124539134)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [STL与string类的认识及简单使用](https://blog.csdn.net/m0_54469145/article/details/130730972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值