C++中的string类使用,看我这一篇就够了!

C++中的string类使用,看我这一篇就够了!

由于cpp中的string类的函数数量很多,用法繁杂,我替大家进行了总结

1. 标准库中的string类

1.1 string类介绍

https://cplusplus.com/reference/string/string/?kw=string

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

1.2 对上述string类的总结

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

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

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

  4. 不能操作多字节或者变长字符的序列。
    在使用string类时,必须包含#include头文件以及using namespace std;

2.string类常用函数用法

2.1 string类对象的常用构造

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

void test1()
{
  


    //0.构造空string对象,即空字符串
    string str;

    //1.生成"123456789"(方法一) 使用同一个类的对象来初始化另一个同类型的对象
    string str1 = "123456789";

    //2.生成"123456789"(方法二) string (const string& str);  str1是"123456789"的复制品
    string str2("123456789"); 

    //3.string (const string& str, size_t pos, size_t len = npos); 将字符串str中从下标pos开始、长度为len的部分作为字符串初值
    string str3("12345", 0, 3);

    //4.string (cstr, size_t n); 以C_string类型cstr的前n个字符串作为字符串s的初值
    string str4("012345",5);     

    //5.string (size_t n, char c);  生成n个c字符的字符串
    string str5(5, '1');     

    //6.string s(str, x):将字符串str中从下标x开始到字符串结束的位置作为字符串初值
    string str6(str2, 2);  

    cout << str1 << endl;//结果为123456789
    cout << str2 << endl;//结果为123456789
    cout << str3 << endl;//结果为123
    cout << str4 << endl;//结果为01234
    cout << str5 << endl;//结果为11111
    cout << str6 << endl;//结果为3456789

}

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

注意:4与6的区别为4是c风格的字符串(即以空字符\0结尾的字符数组)

运行结果如图
在这里插入图片描述

2.2 string类对象的容器操作

void test2()
{
    string s("123456");
    cout << "size=" << s.size() << endl;//返回字符串有效字符长度
    cout << "length=" << s.length() << endl;//返回字符串有效字符长度
    
    cout << "capacity=" << s.capacity() << endl;//返回总空间大小
    cout << "empty=" << s.empty() << endl;//检查字符串是否是空串,是返回true,否则返回false

    cout << "---------------------------------------" << endl;

    s.resize(10);
    cout << "size=" << s.size() << endl;//返回字符串有效字符长度
    cout << "capacity=" << s.capacity() << endl;//返回总空间大小


	s.resize(10,'a');
    cout << "size=" << s.size() << endl;//返回字符串有效字符长度
    cout << "capacity=" << s.capacity() << endl;//返回总空间大小
    cout << s << endl;

    
    s.resize(3);
    cout << s << endl;
    cout << "size=" << s.size() << endl;//返回字符串有效字符长度
    cout << "capacity=" << s.capacity() << endl;//返回总空间大小


    cout << "---------------------------------------" << endl;
    string t("123456");
    cout << t << endl;
    cout << "size=" << t.size() << endl;//返回字符串有效字符长度
    cout << "capacity=" << t.capacity() << endl;//返回总空间大小
    t.reserve(20);
    cout << "size=" << t.size() << endl;//返回字符串有效字符长度
    cout << "capacity=" << t.capacity() << endl;//返回总空间大小
    t.reserve(3);
    cout << "size=" << t.size() << endl;//返回字符串有效字符长度
    cout << "capacity=" << t.capacity() << endl;//返回总空间大小
    cout << "--------------------------------------" << endl;
    s.clear();
    cout << "clear=" << s << endl;//清空有效字符串
}

你看懂了吗? 结果如图
在这里插入图片描述

string容量相关方法使用注意:

  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来填充多出的元素空间。

  4. 注意:resize()函数会影响string对象的size(),当容量不够需要扩容时则同时会影响到capacity()
    a.如果新的大小比原来的大小大,那么多出来的元素会用默认值或者指定值进行初始化(刚刚提到)。
    b.如果新的大小比原来的大小小,那么多余的元素会被删除。

  5. reserve(size_t res_arg=0):为string预留空间:
    reserve()函数不会影响string对象的size(),但会影响它的capacity()。
    a.如果新的容量比原来的容量大,那么string对象会分配更多的内存空间,以避免后续插入元素时发生内存重新分配。
    b.如果新的容量比原来的容量小,那么reserve()函数不会做任何事情。

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

void test3()
{
    string s1("abcdef"); 

    // 方法一: 下标法

    for (int i = 0; i < s1.size(); i++)
    {
        cout << s1[i];
    }
    cout << endl;

    // 方法二:正向迭代器

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

    //方法二的简化版用auto进行自动类型推导
    for (auto it = s1.begin(); it != s1.end(); it++)
    {
        cout << *it;
    }
    cout << endl;
    // 方法三:反向迭代器
    string::reverse_iterator rit ;
    for (rit = s1.rbegin(); rit < s1.rend(); rit++)
    {
        cout << *rit;
    }
    cout << endl;

    //方法三的简化版用auto进行自动类型推导
    for (auto rit = s1.rbegin(); rit != s1.rend(); rit++)
    {
        cout << *rit;
    }
    cout << endl;
    //方法四: 范围for
    for (auto e : s1)
    {
        cout << e;
    }
    cout << endl;
}

结果如图
在这里插入图片描述
注意:
1.利用迭代器遍历string是可以使用auto自动类型推导,详细讲解见我的博客https://blog.csdn.net/2302_80295520/article/details/141598383?spm=1001.2014.3001.5501
2.范围for的底层其实也是和迭代器相同,只是使用起来更加方便

2.4 string类对象的修改操作-push_back()&insert()&append()&operator+=

void  test4()
{
    string s1;

    // 在字符串后尾插一个字符
    s1.push_back('a');
    s1.push_back('b');
    s1.push_back('c');
    cout << "s1:" << s1 << endl; // s1:abc

    // insert(pos,char):在制定的位置pos前插入字符char
    s1.insert(s1.begin(), '1');
    cout << "s1:" << s1 << endl; // s1:1abc




    cout << "----------------------------------" << endl;


    
    //在字符串后追加一个字符串
    //方法1:使用append操作:
    string s2("abc");
    cout << s2 << endl;
    s2.append("111");
    cout << s2 << endl;
    //方法2:+ 操作符
    string s3("abc");
    cout << s3 << endl;
    string t("111");
    cout << s3 + t << endl;



    cout << "----------------------------------" << endl;



    


    
}

在这里插入图片描述
注意:

  1. 在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般
    情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

2.5 string类对象的查找操作-find()&rfind() …

void test5()
{
    //find
    string s("dog bird chicken bird cat");

    //字符串查找-----找到后返回首字母在字符串中的下标

    // 1. 查找一个字符串,返回该字符串首字符的下标
    cout << s.find("chicken") << endl;        // 结果是:9

    // 2. 从下标为6开始找字符'i',返回找到的第一个i的下标
    cout << s.find('i', 6) << endl;            // 结果是:11

    // 3. 从字符串的末尾开始查找字符串,返回的还是首字母在字符串中的下标
    cout << s.rfind("chicken") << endl;       // 结果是:9

    // 4. 从字符串的末尾开始查找字符
    cout << s.rfind('i') << endl;             // 结果是:18-------因为是从末尾开始查找,所以返回第一次找到的字符

    // 5. 在该字符串中查找第一个属于字符串s的字符
    cout << s.find_first_of("13br98") << endl;  // 结果是:4---b

    // 6. 在该字符串中查找第一个不属于字符串s的字符------先匹配dog,然后bird匹配不到,所以打印4
    cout << s.find_first_not_of("hello dog 2006") << endl; // 结果是:4
    cout << s.find_first_not_of("dog bird 2006") << endl;  // 结果是:9

    // 7. 在该字符串最后中查找第一个属于字符串s的字符
    cout << s.find_last_of("13r98") << endl;               // 结果是:19

    // 8. 在该字符串最后中查找第一个不属于字符串s的字符------先匹配t--a---c,然后空格匹配不到,所以打印21
    cout << s.find_last_not_of("teac") << endl;            // 结果是:21


    cout << "----------------------------------" << endl;
}

结果如图
在这里插入图片描述
上述string类的查找函数用法

  1. size_t find (constchar* s, size_t pos = 0) const;在当前字符串的pos索引位置开始,查找子串s,返回找到的位置索引,-1表示查找不到子串

  2. size_t find (charc, size_t pos = 0) const;在当前字符串的pos索引位置开始,查找字符c,返回找到的位置索引,-1表示查找不到字符

  3. size_t rfind (constchar* s, size_t pos = npos) const;在当前字符串的pos索引位置开始,反向查找子串s,返回找到的位置索引,-1表示查找不到子串

  4. size_t rfind (charc, size_t pos = npos) const;在当前字符串的pos索引位置开始,反向查找字符c,返回找到的位置索引,-1表示查找不到字符

  5. size_tfind_first_of (const char* s, size_t pos = 0) const;在当前字符串的pos索引位置开始,查找子串s的字符,返回找到的位置索引,-1表示查找不到字符

  6. size_tfind_first_not_of (const char* s, size_t pos = 0) const;在当前字符串的pos索引位置开始,查找第一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到字符

  7. size_t find_last_of(const char* s, size_t pos = npos) const;在当前字符串的pos索引位置开始,查找最后一个位于子串s的字符,返回找到的位置索引,-1表示查找不到字符

  8. size_tfind_last_not_of (const char* s, size_t pos = npos) const;在当前字符串的pos索引位置开始,查找最后一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到子串

2.6 string类的截取与分割_strtok&substr

void test6()
{
    //字符分割函数strtok
    //char *strtok(char *str, const char *delim)
    //str—要被分解的字符串 ; delim—用作分隔符的字符(可以是一个,也可以是集合)
    //该函数返回被分解的第一个子字符串,若无可检索的字符串,则返回空指针
    char str[] = "I,am,a,student; hello world!";

    const char* split = ",; !";
    char* p2 = strtok(str, split);
    while (p2 != NULL)
    {
        cout << p2 << endl;
        p2 = strtok(NULL, split);
    }
    //首次调用 token = strtok(str, s); 时,strtok 会在 str 中查找第一个不包含在 s 中的字符序列,并返回指向该序列的指针(即 token)。然后,它会在找到的序列后面插入一个字符串结束符 '\0' 来结束当前子字符串,并继续搜索下一个子字符串。
    //在 while 循环中,使用 token = strtok(NULL, s); 继续从上次停止的地方开始搜索下一个子字符串。strtok 的第一个参数是 NULL 表示继续从上一次分割的位置开始搜索。
    //当 strtok 无法找到更多的子字符串时,它会返回 NULL,循环终止。

}
void test7()
{
    //substr函数:在str中从pos位置开始,截取n个字符,然后将其返回
    string s1("0123456789");
    string s2 = s1.substr(2, 5); // 结果:23456-----参数5表示:截取的字符串的长度
    cout << s2 << endl;
}

test6()的运行结果
在这里插入图片描述
test7()的运行结果
在这里插入图片描述

2.7 string的删除:erase()

使用方法:

  1. iterator erase(iterator p);删除字符串中p所指的字符

  2. iterator erase(iterator first, iterator last);删除字符串中迭代器区间[first,last)上所有字符

  3. string& erase(size_t pos = 0, size_t len = npos);删除字符串中从索引位置pos开始的len个字符

  4. void clear();删除字符串中所有字符

void test8()
{
    string s1 = "123456789";


    // s1.erase(s1.begin()+1);              // 结果:13456789
    // s1.erase(s1.begin()+1,s1.end()-2);   // 结果:189
    s1.erase(1,6);                       // 结果:189
    string::iterator iter = s1.begin();
    while( iter != s1.end() )
    {
        cout<<*iter;
        *iter++;
    }
    cout<<endl;

}

在这里插入图片描述

2.8 string的读取操作-getline

void test9()
{
    string name;

    cout << "Please, enter your full name: ";
    getline(cin, name);//获取一行的字符串
    cout << "Hello, " << name << "!\n";
}

结果如图
在这里插入图片描述

2.9 string的替换-replace

replace的使用方法:

  1. string& replace(size_t pos, size_t n, const char *s);将当前字符串从pos索引开始的n个字符,替换成字符串s

  2. string& replace(size_t pos, size_t n, size_t n1, char c); 将当前字符串从pos索引开始的n个字符,替换成n1个字符c

  3. string& replace(iterator i1, iterator i2, const char* s);将当前字符串[i1,i2)区间中的字符串替换为字符串s

void test10()
{
    string s1("hello,world!");

    cout << s1.size() << endl;                     // 结果:12
    s1.replace(s1.size() - 1, 1, 1, '.');           // 结果:hello,world.

    // 这里的6表示下标  5表示长度
    s1.replace(6, 5, "girl");                    // 结果:hello,girl.
    // s1.begin(),s1.begin()+5 是左闭右开区间
    s1.replace(s1.begin(), s1.begin() + 5, "boy"); // 结果:boy,girl.
    cout << s1 << endl;
}

结果如图:
在这里插入图片描述

2.10 string 的比较操作-compare

用法:
对于std::string类,它有一个compare成员函数,用于比较两个字符串。这个函数可以比较两个std::string对象、C风格字符串(const char*)或其他字符串类型的对象。compare函数返回一个整数,表示两个字符串在字典序上的比较结果:

如果返回值 < 0,则表示调用对象小于参数对象。
如果返回值 == 0,则表示两者相等。
如果返回值 > 0,则表示调用对象大于参数对象。

void test11()
{
    // (A的ASCII码是65,a的ASCII码是97)
    // 前面减去后面的ASCII码,>0返回1,<0返回-1,相同返回0
    string A("aBcd");
    string B("Abcd");
    string C("123456");
    string D("123dfg");

    // "aBcd" 和 "Abcd"比较------ a > A
    cout << "A.compare(B):" << A.compare(B) << endl;                          // 结果:1

    // "cd" 和 "Abcd"比较------- c > A
    cout << "A.compare(2, 3, B): " << A.compare(2, 3, B) << endl;                // 结果:1

    // "cd" 和 "cd"比较 
    cout << "A.compare(2, 3, B, 2, 3): " << A.compare(2, 3, B, 2, 3) << endl;  // 结果:0

    // 由结果看出来:0表示下标,3表示长度
    // "123" 和 "123"比较 
    cout << "C.compare(0, 3, D, 0, 3): " << C.compare(0, 3, D, 0, 3) << endl;    // 结果:0

}

结果如图
在这里插入图片描述

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值