string的操作 初始化、插入和删除等

初始化

string s1(); // s1 = ""(变量 s1 只是定义但没有初始化,编译器会将默认值赋给 s1,默认值是“”,即为空字符串)

 

string s2("Hello"); // s2 = "Hello"(变量 s2 在定义的同时被初始化为“Hello”,与C风格的字符串不同,string 的结尾没有结束标志‘\0’)

想到了美团20240323的一道题:

string s3(4, 'K'); // s3 = "KKKK"(变量 s3 被初始化为由 4个'K'符组成的字符串"KKKK")

这个可以用于字符串截取

string s4("12345", 1, 3); //s4 = "234",即 "12345" 的从下标 1 开始,长度为 3 的子串

代码3d3c4bb20c084658b297bf52c94d3fd5.png

 结果3bbeefb8ec8b4d74921db2069b6d905c.png

 似乎还有点麻烦?😂 后面有方便的erase等操作可以方便的实现!

 

string的assign方法:

string s1("12345"), s2;

 

s3.assign(s1); // s3 = s1,string类对象拷贝

 

s2.assign(s1, 1, 2); // s2 = "23",即 s1 的子串(1, 2),取子串

 

s2.assign("abcde", 2, 3); // s2 = "cde",即 "abcde" 的子串(2, 3)

//这个里面assign的参数意思与string初始化时候一样

尝试一下

这样会报错

0ee8d225599740e097cc75f75a205257.png

 必须先声明,在使用方法700834cbbeae4e518fb4ae77879ee7a5.png

 结果

1e21d67dbb784074ae8a21da4d9da8a8.png

 发现这几种方法都相当于是拷贝了一份,不随a1而改变a3428c53a77e42d488c0f34b5dde7934.png

 904bd40fc95a4ee082c33c5059433c45.png

 在某些必要的时刻,string字符串转换为C风格的字符串

虽然 C++ 提供了 string 类来替代C语言中的字符串,但是在实际编程中,有时候必须要使用C风格的字符串(例如打开文件时的路径),为此,string 类为我们提供了一个转换函数 c_str(),该函数能够将 string 字符串转换为C风格的字符串,并返回该字符串的 const 指针(const char*)。请看下面的代码:

string path = "D:\\demo.txt";

 

FILE *fp = fopen(path.c_str(), "rt"); //为了使用C语言中的 fopen() 函数打开文件,必须将 string 字符串转换为C风格的字符串。

size()/length() 

string字符串求字符串长度时,可以调用 string 类提供的 length() 或size()成员函数。

一些高深的的容器操作

capacity() 返回对象总空间大小

reserve(size_t n) 为字符串对象预留n字节空间

resize(size_t n,char c) 将有效字符串长度改为n,多出的位置用字符c填充(缺省默认使用‘\0’填充)

//例1

#include <iostream>

#include <string>

using namespace std;

 

void stringTest1()

{

    string s("Hello World");

    

    cout<<s.size()<<endl; // 11

    cout<<s.length()<<endl; // 11

    cout<<s.capacity()<<endl; // 15

    cout<<s<<endl; //"Hello World"

    

    s.clear(); //将s中的字符串清空

    cout<<s.size()<<endl; // 0

    cout<<s.capacity()<<endl; // 15

    //所以clear只是改变s的有效字符串长度size,s的容量(底层空间)并没有改变

    

    s.resize(10,'a');

    cout<<s.size()<<endl; // 10

    cout<<s.capacity()<<endl; // 15

    cout<<s<<endl; //"aaaaaaaaaa"

    

    s.resize(20);

    cout<<s.size()<<endl; // 20

    cout<<s.capacity()<<endl; // 30

    cout<<s<<endl; //"aaaaaaaaaa"这里其实后面有10个'\0'作为填充

    

    s.resize(5);

    cout<<s.size()<<endl; // 5

    cout<<s.capacity()<<endl; // 30

    cout<<s<<endl; //"aaaaa"

    //所以resize改变的是有效字符串的个数

    //当n值增大时,可能会改变底容量大小,即底层空间增加

    //而n值减少,则容量不变。

}

 

int main()

{

    

    stringTest1();

    return 0;

}

//例2

#include <iostream>

#include <string>

using namespace std;

 

void stringTest2()

{

    string s; 

    s.reserve(100); 

    cout << s.size() << endl; //0

    cout << s.capacity() << endl; //100

 

    s.reserve(50); 

    cout << s.size() << endl; // 0

    cout << s.capacity() << endl; //100

}

小结:

 

a.clear只是将string中有效字符串清空,不改变底层空间大小。

 

b.resize将字符串有效字符个数改变为n个,个数增多时,多余空间进行填充。

 

另外,resize将元素增多时,可能会改变底层容量的大小,而元素减少时,底层容量不变。

 

c.reserve为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

除了for循环,str[i]遍历以外,还有迭代器

如何取出迭代器的值?答案是用*

void stringTest3()

{

    string s("hello world");

    

    for(string::iterator it=s.begin();it!=s.end();it++)//正向迭代器

    {

        cout<<*it;

    }

    cout<<endl;

    

    for(string::reverse_iterator rit=s.rend();rit>=s.rbegin();rit--)//反向迭代器

    {

        cout<<*rit;

    }

    cout<<endl;

}

 说个笑话,这个报错半天没看出来

"iterator"迭代呀,

3ef8aeb9ab1e4e4ba3325146c4548890.png

begin指向第一个字符

 end指向最后一个字符的后一位80f4992bb29b4cd1994f779ca400380b.png

 de089ad09dae4c49a8517d9201332b4d.png

 c++11才能用的auto,怪不得我用老报错

void stringTest4()

{

    string s("hello world");

    

    for(auto it:s)//通过auto自动推导

    {

        cout<<it<<endl;

    }

}

下面是极其实用的修改string对象部分

插入

1.push_back  在尾部插入

void stringTest4()

{

    string s("hello world");

    s.push_back('!'); //尾部插入字符!

    cout<<s<<endl; //“hello world!”

}

2.直接用加号连接 两个 ~

string 类可以使用 + 或 += 运算符来直接拼接字符串,再也不需要使用C语言中的 strcat()、strcpy()、malloc() 等函数来拼接字符串了,再也不用担心空间不够会溢出了。

用 + 来拼接字符串时,运算符的两边可以都是 string 字符串,也可以是一个 string 字符串和一个C风格的字符串,还可以是一个 string 字符串和一个字符数组,或者是一个 string 字符串和一个单独的字符。

分别对应下面四类:

#include <iostream>

#include <string>

using namespace std;

 

int main(){

    string s1 = "first ";

    string s2 = "second ";

    char *s3 = "third ";

    char s4[] = "fourth ";

    char ch = '@';

 

    string s5 = s1 + s2;

    string s6 = s1 + s3;

    string s7 = s1 + s4;

    string s8 = s1 + ch;

 

    cout<<s5<<endl<<s6<<endl<<s7<<endl<<s8<<endl;

 

    return 0;

 

}

3.append(原来c++也有!我以为只有Python有呢)  在尾部插入

string 类还有 append 成员函数,可以用来向字符串后面添加内容。append 成员函数返回对象自身的引用。

他的参数意义同string

string s1("123"), s2("abc");

s1.append(s2); // s1 = "123abc"

s1.append(s2, 1, 2); // s1 = "123abcbc"

s1.append(3, 'K'); // s1 = "123abcbcKKK"

s1.append("ABCDE", 2, 3); // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)

4.insert 在指定位置插入

作用: string 字符串中指定的位置插入另一个字符串(它可以是 string 字符串,也可以是C风格的字符串),返回值为对象自身的引用

string s1("Limitless"), s2("00");

 

s1.insert(2, "123"); //在下标 2 处插入字符串"123",s1 = "Li123mitless"

 

s1.insert(3, s2); //在下标 2 处插入 s2 , s1 = "Li10023mitless"

 

s1.insert(3, 5, 'X'); //在下标 3 处插入 5 个 'X',s1 = "Li1XXXXX0023mitless"

删除

1.pop_back 在尾部删除

只能删除尾部!要删除别的地方请看下一条

// string::pop_back

#include <iostream>

#include <string>

 

int main ()

{

  std::string str ("hello world!");

  str.pop_back(); //删除尾部字符!

  std::cout << str << std::endl; //"hello world"

  return 0; 

}

 

2.erase 删除指定位置

erase() 函数可以删除 string 中的一个子字符串。

 

 

pos:要删除的子字符串的起始下标

 

len: 要删除子字符串的长度。如果不指明 len 的话,那么直接删除从 pos 到字符串结束处的所有字符(此时 len = str.length() - pos)。

 

   string s1("Real Steel");

 

  s1.erase(1, 3); //删除子串(1, 3),此后 s1 = "R Steel"3是len,不是下标!

 

  s1.erase(5); //删除下标5及其后面的所有字符,此后 s1 = "R Ste"

 

  std::string str ("This is an example sentence.");

  std::cout << str << '\n'; // "This is an example sentence."

                                           

  str.erase (10,8);                     

  std::cout << str << '\n'; // "This is an sentence."

                                          

  str.erase (str.begin()+9); // "This is a sentence."             

                                          

  str.erase (str.begin()+5, str.end()-9); // "This sentence."

  std::cout << str << '\n';

【注意】可能有人认为,在 pos 参数没有越界的情况下, len 参数也可能会导致要删除的子字符串越界。但实际上这种情况不会发生,erase() 函数会从len和str.length() - pos两个值中取出最小的一个作为待删除子字符串的长度。

 

比较字符串

string对象的比较

方法一:比较运算符

用 <、<=、==、!=、>=、> 运算符比较 string 对象

 

方法二: compare() 成员函数

string 类还有 compare 成员函数,可用于比较字符串。

 

compare 成员函数有以下返回值:

 

小于 0 表示当前的字符串小;

等于 0 表示两个字符串相等;

大于 0 表示另一个字符串小。

string s1("hello"), s2("hello, world");

int n = s1.compare(s2);

n = s1.compare(1, 2, s2, 0, 3); //比较s1的子串 (1,2) 和s2的子串 (0,3)参数博大精深参数还是参数

n = s1.compare(0, 2, s2); // 比较s1的子串 (0,2) 和 s2

n = s1.compare("Hello");

n = s1.compare(1, 2, "Hello"); //比较 s1 的子串(1,2)和"Hello”

n = s1.compare(1, 2, "Hello", 1, 2); //比较 s1 的子串(1,2)和 "Hello" 的子串(1,2)

string 对象的子串

 

【substr()成员函数】

substr 成员函数可以用于求pos开始,长度为len的子串。

调用时,如果省略len或len超过了字符串的长度,则子串就是从pos开始直到字符串结束的部分。

 

string s1 = "this is ok";

 

string s2 = s1.substr(2, 4); // s2 = "is i"

 

s2 = s1.substr(2); // s2 = "is is ok"

交换两个string对象的内容【swap()函数】

swap 成员函数可以交换两个 string 对象的内容。例如:

 

string s1("West”), s2("East");

s1.swap(s2); // s1 = "East",s2 = "West"

 

查找和逆向查找,暂时贴个代码,下次再详细讲讲

 

查找子串和字符【find()函数】

string 类有一些查找子串和字符的成员函数,它们的返回值都是子串或字符在 string 对象字符串中的位置(即下标)。如果查不到,则返回 string::npos。string: :npos 是在 string 类中定义的一个静态常量。这些函数如下:

 

find:从前往后查找子串或字符出现的位置。

rfind:从后往前查找子串或字符出现的位置。

find_first_of:从前往后查找何处出现另一个字符串中包含的字符。例如:

s1.find_first_of("abc"); //查找s1中第一次出现"abc"中任一字符的位置

find_last_of:从后往前查找何处出现另一个字符串中包含的字符。

find_first_not_of:从前往后查找何处出现另一个字符串中没有包含的字符。

find_last_not_of:从后往前查找何处出现另一个字符串中没有包含的字符。

#include <iostream>

#include <string>

using namespace std;

 

int main()

{

    string s1("Source Code");

    int n;

    if ((n = s1.find('u')) != string::npos) //查找 u 出现的位置

        cout << "1) " << n << "," << s1.substr(n) << endl;//输出 l)2,urce Code

    

    if ((n = s1.find("Source", 3)) == string::npos)//从下标3开始查找"Source",找不到

        cout << "2) " << "Not Found" << endl; //输出 2) Not Found

    

    if ((n = s1.find("Co")) != string::npos)//查找子串"Co"。能找到,返回"Co"的位置

        cout << "3) " << n << ", " << s1.substr(n) << endl;//输出 3) 7, Code

    

    if ((n = s1.find_first_of("ceo")) != string::npos)//查找第一次出现或 'c'、'e'或'o'的位置

        cout << "4) " << n << ", " << s1.substr(n) << endl;//输出 4) l, ource Code

    

    if ((n = s1.find_last_of('e')) != string::npos)//查找最后一个 'e' 的位置

        cout << "5) " << n << ", " << s1.substr(n) << endl; //输出 5) 10, e

 

    if ((n = s1.find_first_not_of("eou", 1)) != string::npos)

        //从下标1开始查找第一次出现非 'e'、'o' 或 'u' 字符的位置

        cout << "6) " << n << ", " << s1.substr(n) << endl; //输出 6) 3, rce Code

   

    return 0;

}

替换子串【replace()成员函数】

replace 成员函数可以对 string 对象中的子串进行替换,返回值为对象自身的引用。

 

示例如下:

string s1("Real Steel");

 

s1.replace(1, 3, "123456", 2, 4); //用 "123456" 的子串(2,4) 替换 s1 的子串(1,3)

 

cout << s1 << endl; //输出 R3456 Steel

 

string s2("Harry Potter");

 

s2.replace(2, 3, 5, '0'); //用 5 个 '0' 替换子串(2,3)

 

cout << s2 << endl; //输出 HaOOOOO Potter

 

int n = s2.find("OOOOO"); //查找子串 "00000" 的位置,n=2

 

s2.replace(n, 5, "XXX"); //将子串(n,5)替换为"XXX"

 

cout << s2 < < endl; //输出 HaXXX Potter

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值