• Cpp知识点系列-字符串


    前言

    记录一些对字符串的理解。

    接下来我所说的都是依赖于头文件的。

    理论

    什么是字符串

    字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。

    string与cstring有什么区别

    是C++标准库头文件,包含了拟容器class std::string的声明(不过class string事实上只是basic_stringtypedef),用于字符串操作

    是C标准库头文件的C++标准库版本,包含了C风格字符串(NULL即'\0'结尾字符串)相关的一些类型和函数的声明,例如strcmp、strchr、strstr等。

    两者最大区别在于:

    • string是新标准,定义了namespace std;cstring定义中包含的是string.h

    • string中可以进行+ = += >等运算,而cstring中不能进行相关运算。

    什么是string类型的迭代器

    声明一个string类中特有的类型size_type变量,名称为position

    string::size_type position;
    

    迭代器是一个变量,相当于容器和操纵容器的算法之间的中介 , 实在理解困难认为是个特别的int下标也可以。

    迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。

    1. //从类名获取该对象
    2. string::npos;
    3. //从对象获取该对象
    4. string tempstr;
    5. tempstr.npos;

    这个npos是个特别的迭代器对象,可以理解成为string类型中特别的NULL,如果查找失败或者遍历完毕之后迭代器的值就是这个.

    操作

    首先引入头文件,并且在命名空间中使用。

    1. #include
    2. using namespace std;

    Strings常用方法

    方法名作用
    Operators操作符,可以用 ==, >, <, >=, <=, and !=比较字符串. 可以用 + 或者 += 操作符连接两个字符串, 并且可以用[]获取特定的字符
    append()在字符串的末尾添加文本(就是+=)
    compare()比较两个字符串
    empty()如果字符串为空,返回真
    erase()删除字符
    insert()插入字符
    length()返回字符串的长度
    replace()替换字符
    size()返回字符串中字符的数量(结果等价于length)
    substr()返回某个子字符串
    swap()交换两个字符串的内容

    如果可以使用自带的方法去实现的话自然是比较好的,但是如果只能够针对部分字符进行复杂变化的话,就需要转化成为char*类型的数组

    构造法

    平常更多是用等号直接赋值,如果要求字符串中间有结尾符可以这样声明。

    1. void stringTestConstruct() {
    2.     string str =string("12345 \0 54321"13);//不等价于str="12345 \0 54321";
    3.     cout << str<<endl;
    4.     string str1 = "12345 \0 54321";
    5.     cout << str1;
    6. }

    image-20221108134445583

    image-20221108132722476

    append

    1. void stringTestAppend() {
    2.     string str = "Hello";
    3.     str.append(3'!');//等价于str+="!!!" ;
    4.     cout << str;
    5. }

    image-20201126161713323

    初学时,没考虑太多,后来才发现在添加'\0'字符时有奇效。

    1. void stringTestAppend2() {
    2.     string str="abc";
    3.     str.append("\0 def",5);//等价于 str =string("abc\0 def"8);
    4.     cout << str;
    5. }

    image-20221108135309114

    compare

    compare()比较时逐字符比较的,一旦能比较出结果,就不再比较了。

    虽然有多个重载,但是只需要理解,在this字符串与传入的比较字符串str一部分(至于是哪一部分用起点和长度来评定)之间进行的比较即可。

    1.  int compare( const basic_string &str );
    2.  int compare( const char *str );
    3.  int compare( size_type index, size_type length, const basic_string &str );
    4.  int compare( size_type index, size_type length, const basic_string &str, size_type index2size_type length2 );
    5.  int compare( size_type index, size_type length, const char *str, size_type length2 );

    在str之前的参数是修饰this,在str之后的参数是修饰str的

    返回值情况
    小于零this < str(自己弱小就认''负'')
    this == str
    大于零this > str(自己强大就嚣''正'')
    1. void stringTestCompare() {
    2.     string s1 = "abandon";
    3.     string s2 = "about";
    4.     int b = s1.compare(s2);//直接比较,s1小于s2,故返回-1
    5.     int c = s1.compare(24, s2);//s1下标为2的字符a开始的4个字符ando和s2进行比较。ando大于s2故返回1
    6.     cout << c << endl;
    7.     int d = s1.compare(24, s213);
    8.     cout << d << endl;//s1下标为2的字符a开始的4个字符ando和s2下标为1的字符b开始的3个字符bou比较。前者小,故返回-1
    9.     string s3 = "abc";
    10.     string s4 = "abc";
    11.     int e = s3.compare(s4);//相等返回0
    12.     cout << e << endl;
    13. }

    erase

    也有参数为迭代器的函数,在下面介绍。

    basic_string &erase( size_type index = 0, size_type num = npos );
    
    • 删除从index索引开始的num个字符, 返回删减后的字符串。其中index默认从0开始,num默认是最大值。

    1. void stringTestErase() {
    2.     string s("1234567890123456789012345");//总共25个字符
    3.     cout << s << endl;
    4.     cout << s.erase(106<< endl;//从下标第10的字符开始删除,一共删除6个。
    5.     cout << s.erase(10<< endl;//删除下标为10的字符及之后的 ==保留下标小于10的字符
    6.     cout << s.erase();//清空字符串
    7. }

    image-20201126200020627

    insert

    1. basic_string &insert( size_type index, const basic_string &str );
    2. basic_string &insert( size_type index, const char *str );
    3. basic_string &insert( size_type index1, const basic_string &str, size_type index2, size_type num);
    4. basic_string &insert( size_type index, const char *str, size_type num );
    5. basic_string &insert( size_type index, size_type num, char ch );
    • 在字符串的位置index插入字符串str;

    • 在字符串的位置index插入字符串str的子串(从index2开始,长num个字符);

    • 在字符串的位置index插入字符串str的num个字符;

    • 在字符串的位置index插入num个字符ch的拷贝字符串。

    其实理解起来就是,在本字符串的index位置,插入参数中的字符串的一部分(至于是哪一部分

    用起点和长度来评定)。

    1. void stringTestInsert() {
    2.     string str = "abc";
    3.     str.insert(1"123");
    4.     /*在下标为1的位置,插入字符串123全部*/
    5.     cout << str << endl;
    6.     str = "abc";
    7.     str.insert(1"123"11);
    8.     /*在下标为1的位置,插入字符串123的一部分,并且从下标1开始,长度为1的一段*/
    9.     cout << str << endl;
    10.     str = "abc";
    11.     str.insert(1"123"2);
    12.     /*在下标为1的位置,插入字符串123的一部分,并且从下标0开始,长度为2的一段*/
    13.     cout << str << endl;
    14.     str = "abc";
    15.     str.insert(12'z');
    16.     /*在下标为1的位置,插入2个字符z*/
    17.     cout << str;
    18. }

    image-20221108141757159

    length

    其实不用纠结在获取长度的时候是用size还是length,至少在GCC6的情况下,返回的都是同一个字段_M_string_length

    1. void stringTestLength() {
    2.     //其实后面都是返回的同一个字段_M_string_length
    3.     string s("1234567890123456789012345");//总共25个字符
    4.     cout << s.size()  << endl;//输出25
    5.     cout << s.length()  << endl;//输出25
    6. }

    replace

    1. basic_string &replacesize_type index, size_type num, const basic_string &str );
    2. basic_string &replacesize_type index1, size_type num1, const basic_string &str, size_type index2size_type num2 );
    3. basic_string &replacesize_type index, size_type num, const char *str );
    4. basic_string &replacesize_type index, size_type num1, const char *str, size_type num2);
    5. basic_string &replacesize_type index, size_type num1, size_type num2, char ch );

    其实理解起来就是,在将本字符串的index位置长度为num的字符串,替换成参数中的字符串的一部分(至于是哪一部分用起点和长度来评定)。

    一般用起来的时候,更多是和find函数一起,实现查找替换的作用。然而find函数是涉及到了迭代器,所以这里只是简单示例一下。有兴趣可以直接下翻。

    1. void stringTestReplace() {
    2.     string str="1234567890";
    3.     str.replace(0,9,"ABC");
    4.     /*把下标从0开始、长度为2的一段字符串,替换为ABC*/
    5.     cout << str<<endl;
    6.     str="1234567890";
    7.     str.replace(str.find('8'),3,"ABC");
    8.     /*把从字符8开始、长度为2的一段字符串,替换为ABC*/
    9.     cout << str;
    10. }

    substr

      basic_string substr( size_type index, size_type num = npos ); 
    

    截取本字符串从index开始之后的num个字符,没错就是跟上面的删除差不多!

    特别的,用程序形象的看一眼效果:

    1. void stringTestSubstr() {
    2.     string s("123456789012345678901234567890");
    3.     cout << s << endl;
    4.     printf("%30s\n", s.substr(21).c_str());
    5.     cout << s.erase(21<< endl;
    6. }

    image-20201126222643653

    swap

     void swap( basic_string &str );
    

    这个函数的作用主要就是将两个字符串的全部元素进行交换。

    1. void stringTestSwap() {
    2.     string first"This comes first" );
    3.     string second( "And this is second" );
    4.     first.swap( second );
    5.     cout << first << endl;
    6.     cout << second << endl;
    7. }

    image-20201126222955616

    如果只是针对部分元素,可以用insertreplace进行操作。

    转char*

    方法名作用
    c_str()将字符串以C字符数组的形式返回
    copy(*str, num, index )将内容复制为一个字符数组
    data()返回内容的字符数组形式

    c_str( )

     const char *c_str();
    

    返回一个const临时指针,指向以\0结尾的字符数组,应该使用strcpy()函数等来操作。

    1. void stringTestC_str() {
    2.     //数组
    3.     char c[20];
    4.     string s="1234";
    5.     strcpy(c,s.c_str());//注意strcpy函数是在cstring头文件中的
    6.     cout<<c;
    7.     //指针
    8.     string str = "hello";
    9.     const char* p1 = str.c_str();//加const
    10.     char * p2=(char*)str.c_str();//或者是强制转换
    11. }

    data( )

    const char *data();
    

    照常来说是字符串内容外,**不附加结束字符'\0'**。

    有资料显示,两者是应该有区别的c_str()有结束符,而data()没有结束符。

    image-20201126172130028

    因为我这个编译环境的问题,在dev的环境中两个方法,其实都是返回的_M_data()方法而已的。

    copy(*str,num,index )

    拷贝自己的num个字符到str中(从索引index开始)。返回值是拷贝的字符个数

    size_type copy( char *str, size_type num, size_type index );
    

    由于还需要手动加结束符

    1. void stringTestCopy() {
    2.     string str = "hmmm";
    3.     char p[10];
    4.     str.copy(p, 30);
    5.     /*把从0开始、长度为3的字符串,复制到字符数组p之中*/
    6.     p[3= '\0';//注意手动加结束符!!!
    7.     cout << p;
    8. }

    迭代器

    方法名作用
    begin()返回一个迭代器,指向第一个字符
    end()返回一个迭代器,指向字符串的末尾。(最后一个字符的下一个位置)
    erase()删除字符
    find()在字符串中查找字符
    find_first_of()查找第一个与value中的某值相等的字符
    find_first_not_of()查找第一个与value中的所有值都不相等的字符
    find_last_of()查找最后一个与value中的某值相等的字符
    find_last_not_of()查找最后一个与value中的所有值都不相等的字符
    get_allocator()返回配置器
    insert()插入字符
    rbegin()返回一个逆向迭代器,指向最后一个字符
    rend()返回一个逆向迭代器,指向第一个元素的前一个位置
    replace()替换字符
    rfind()查找最后一个与value相等的字符(逆向查找)

    find

    把str的全部字符当作整体进行查找.

    1.  size_type find( const basic_string &str, size_type index );
    2.  size_type find( const char *str, size_type index );
    3.  size_type find( const char *str, size_type index, size_type length );
    4.  size_type find( char ch, size_type index );
    • 返回str在字符串中第一次出现的位置(从index开始查找)如果没找到则返回string::npos

    • 返回str在字符串中第一次出现的位置(从index开始查找,长度为length)。如果没找到就返回string::npos

    • 返回字符ch在字符串中第一次出现的位置(从index开始查找)。如果没找到就返回string::npos

    代码:

    1. void stringIteratorTestFind() {
    2.     string s("qwe123qwee123qweqwe1");
    3.     string flag = "123";
    4.     string::size_type position = 0;
    5.     int i = 1;
    6.     while ((position = s.find(flag, position)) != string::npos) {
    7.         cout << "position  " << i << " : " << position << endl;
    8.         position++;
    9.         i++;
    10.     }
    11. }

    image-20201126230709115

    find_first_of

    1.  size_type find_first_of( const basic_string &str, size_type index = 0 );
    2.  size_type find_first_of( const char *str, size_type index = 0 );
    3.  size_type find_first_of( const char *str, size_type index, size_type num );
    4.  size_type find_first_of( char ch, size_type index = 0 );

    跟上面的参数相似,重点理解find的即可。

    特别注意

    find_first_of 函数和find函数最大的区别就是,如果在str1中查找str2时,如果str1中含有str2中的任何字符,就会查找成功,而find则只有全部相同才会查找成功.

    比如:

    1. void stringIteratorTestFind_first_of () {
    2.     string s("qwe123qwee123qweqwe1");
    3.     string flag="123";
    4.     string::size_type position=0;
    5.     int i=1;
    6.     while((position=s.find_first_of(flag,position))!=string::npos) {
    7.         cout<<"第"<<i<<"次匹配 : "<<position<<endl;
    8.         position++;
    9.         i++;
    10.     }
    11. }

    与上面的例子区别只是更换了一个函数而已,但是结果完全不同。

    image-20221108150441682

    至于其他的not,last的变名函数则是顾名思义即可。

    rfind

    反向查找子字符串

    1.  size_type rfind( const basic_string &str, size_type index );
    2.  size_type rfind( const char *str, size_type index );
    3.  size_type rfind( const char *str, size_type index, size_type num );
    4.  size_type rfind( char ch, size_type index );

    当正向查找与反向查找得到的位置不相同说明子串不唯一。

    erase

    1.  iterator eraseiterator pos );
    2.  iterator eraseiterator start, iterator end );
    • 删除pos指向的字符, 返回指向下一个字符的迭代器,

    • 删除从start到end的所有字符, 返回一个迭代器,指向被删除的最后一个字符的下一个位置

    insert

    1.  iterator insert( iterator i, const char &ch );
    2.  void insert( iterator i, size_type num, const char &ch );
    3.  void insert( iterator i, iterator start, iterator end );
    • 在迭代器i表示的位置前面插入一个字符ch,

    • 在迭代器i表示的位置前面插入num个字符ch的拷贝,

    • 在迭代器i表示的位置前面插入一段字符,从start开始,以end结束.

    replace

    1.  basic_string &replace( iterator start, iterator end, const basic_string &str );
    2.  basic_string &replace( iterator start, iterator end, const char *str );
    3.  basic_string &replace( iterator start, iterator end, const char *str, size_type num );
    4.  basic_string &replace( iterator start, iterator end, size_type num, char ch );
    • 用str中的字符替换本字符串中的字符,迭代器start和end指示范围

    • 用str中的num个字符替换本字符串中的内容,迭代器start和end指示范围,

    • 用num个ch字符替换本字符串中的内容,迭代器start和end指示范围.

    Strings全部方法

    方法名作用
    Constructors构造函数,用于字符串初始化
    Operators操作符,用于字符串比较和赋值
    append()在字符串的末尾添加文本
    assign()为字符串赋新值
    at()按给定索引值返回字符
    begin()返回一个迭代器,指向第一个字符
    c_str()将字符串以C字符数组的形式返回
    capacity()返回重新分配空间前的字符容量
    compare()比较两个字符串
    copy()将内容复制为一个字符数组
    data()返回内容的字符数组形式
    empty()如果字符串为空,返回真
    end()返回一个迭代器,指向字符串的末尾。(最后一个字符的下一个位置)
    erase()删除字符
    find()在字符串中查找字符
    find_first_of()查找第一个与value中的某值相等的字符
    find_first_not_of()查找第一个与value中的所有值都不相等的字符
    find_last_of()查找最后一个与value中的某值相等的字符
    find_last_not_of()查找最后一个与value中的所有值都不相等的字符
    get_allocator()返回配置器
    insert()插入字符
    length()返回字符串的长度
    max_size()返回字符的最大可能个数
    rbegin()返回一个逆向迭代器,指向最后一个字符
    rend()返回一个逆向迭代器,指向第一个元素的前一个位置
    replace()替换字符
    reserve()保留一定容量以容纳字符串(设置capacity值)
    resize()重新设置字符串的大小
    rfind()查找最后一个与value相等的字符(逆向查找)
    size()返回字符串中字符的数量
    substr()返回某个子字符串
    swap()交换两个字符串的内容

    感谢

    参考书籍《C++语言程序设计(第4版)》(郑莉,董渊)

    C++string的compare()比较函数

    感谢现在的好奇,为了能成为更好的自己。

  • 相关阅读:
    java 使用GeoTools工具 geojson 与shp 相互转换
    弱监督点云分割(论文解读:CVPR2020)
    【NOI模拟赛】给国与时光鸡(构造)
    【译】自制前端玩具框架
    JVM调优记录
    SElinux avc dennied权限问题解决方法
    新手学编程前端好还是后端?
    系统架构设计师(第二版)学习笔记----多媒体技术
    (附源码)ssm人力资源管理系统 毕业设计 271621
    14个SpringBoot优化小妙招,看完后同事说写代码像写诗!
  • 原文地址:https://blog.csdn.net/qq_41461536/article/details/128112344