C++STL标准库学习笔记(八)string

目录

前言:

正文

1.1 string的建立

1.2 string的赋值和连接

1.3 比较string

1.4 子串

1.5 删除string中的字符

1.6 替换string中的字符

1.7 在string中插入字符

1.8 转换成C语言式char*字符串

1.9 字符串流处理

后记:


前言:

        在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来。

        另外,由于笔者主要是在word上编辑的这篇文章,除了代码部分的部分””双引号不是编辑器可以理解的双引号,所以如果要复制的话记得修改双引号,造成不便深表歉意。

        在这一篇文章中,我们主要介绍string的用法和应用

正文

1.1 string建立

        string类是模板类:

        typedef basic_string<char>string;

        使用string类要包含头文件<string>

        string对象的初始化:

        string s1(“hello);

        string month = “March;

        string s2(8,’x);(这里面s2就有8个x)

        错误的初始化方法:

        string error1 = ‘c’; //错

        string error2(‘u’); //错

        string error3 = 22; //错

        string error4(8); //错

        (归纳起来就是不能直接赋字符和其他类型的变量)

        但是我们可以将字符赋给string对象

        string s;

        s = ‘n’;

        这样是对的

        一个包含以上的内容的简单样例:

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

int main(int argc, char const *argv[])
{
    string s1("hello");
    cout<<s1<<endl;//输出:hello
    string s2(8,'x');
    cout<<s2<<endl;//输出:xxxxxxxx
    string month = "March";
    cout<<month<<endl;//输出:March
    string s;
    s = 'n';
    cout<<s<<endl;//输出:n
    return 0;
}

        string对象的长度用成员函数length()读取

        string s(“hello”);

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

        string支持流读取运算符(如果没学过类中的输入输出流的话,只用了解它支持cin就行了)

        string stringObject;

        cin>>stringObject;

        string支持getline函数

        string s;

        getline(cin,s);(getline相当于读取一整行的cin,不会因为空格而停顿,在输入人名时会有用,比如用cin输入Awake Fantasy就会在接收完Awake时就结束了,而getline就能接收整个名字)

1.2 string的赋值和连接

        用 = 赋值

        string s1(“cat”),s2;

        s2 = s1;

        用assign成员函数复制

        string s1(“cat”),s3;

        s3.assign(s1);

        用assign成员函数部分复制

        string s1(“catpig”),s3;

        s3.assign(s1,1,3);//从s1中下标为1的字符开始复制三个字符

        (测试一下发现这里s3是atp,看来string是从下标为1开始存的,我还以为老师会复制cat呢)

        单个字符复制

        s2[5] = s1[3] =’a’;

        逐个访问string对象中的字符

        string s1(“hello”);

        for(int i = 0;i<s1.length();i++)

                cout<<s1.at(i)<<endl;

        成员函数at会做范围检查,如果超出范围,会抛出out_of_range异常,而下标运算符[]不做范围检查。(不做范围检查的效率比做的快,所以要是打比赛要用什么懂得都懂)

        用 + 运算符连接字符串

        string s1(“good ”),s2(“morning!”);

        s1 += s2;

        cout<< s1;

        用成员函数append连接字符串

        string s1(“good ”),s2(“morning!”);

        s1.append(s2);

        cout<<s1;

        s2.append(s1,3,s1.size());//s1.size()为s1的字符数

        cout<<s2;

        下标为3开始,s1.size()个字符,如果字符串内没有足够字符,则复制到字符串最后一个字符

1.3 比较string

        用关系运算符比较string的大小

        ==, >, >=, <, <=, !=

        返回值都是bool类型,成立返回true,否则返回false

        例如:

    string s1("hello"),s2("hello"),s3("hell");
    bool b = (s1 == s2);
    cout<<b<<endl;
    b = (s1 == s3);
    cout<<b<<endl;
    b = (s1 > s3);
    cout<<b<<endl;

        输出:1 0 1

        用成员函数compare比较string的大小

    string s1("hello"),s2("hello"),s3("hell");
    int f1 = s1.compare(s2);
    int f2 = s1.compare(s3);
    int f3 = s3.compare(s1);
    int f4 = s1.compare(1,2,s3,0,3);//s1 1-2; s3 0-3
    int f5 = s1.compare(0,s1.size(),s3);//s1 0-end
    cout<<f1<<endl;//0  hello == hello
    cout<<f2<<endl;//1  hello > hell
    cout<<f3<<endl;//-1 hell < hello
    cout<<f4<<endl;//-1 el < hell
    cout<<f5<<endl;//1  hello > hell

        (int f4 = s1.compare(1,2,s3,0,3);//s1 1-2; s3 0-3

        这里的1,2是表示从1开始的2个字符,不是下标1到下标2,有兴趣可以去尝试一下)

1.4 子串

        成员函数 substr

    string s1("hello world"),s2;
    s2 = s1.substr(4,5);
    cout<<s2<<endl;//结果:o wor

        这里substr(4,5)是指下标4开始5个字符

        成员函数swap

    string s1("hello world"),s2("really");
    s1.swap(s2);
    cout<<s1<<endl;//结果:really
    cout<<s2<<endl;//结果:hello world

        寻找string中的字符

        成员函数find()

        string s1(“hello world”);

        s1.find(“lo”);

        在s1中从前向后查找”lo”第一次出现的地方,如果找到,返回”lo”开始的位置,即l所在位置的下标。如果找不到,返回string::npos(string中定义的静态常量)(npos应该就是 no position吧)

        成员函数rfind()

        string s1(“hello world”);

        s1.rfind(“lo”);

        在s1中从后向前查找”lo”第一次出现的地方,如果找到,返回”lo”开始的位置,即l所在位置的下标。如果找不到,返回string::npos(string中定义的静态常量)(这个rfind的“r”应该就是reverse)

        find还可以指定开始查找的位置:

    string s1("hello worlld");
    cout<<s1.find("ll",1)<<endl;//结果:2
    cout<<s1.find("ll",2)<<endl;//结果:2
    cout<<s1.find("ll",3)<<endl;//结果:9
    //分别从下标1,2,3开始查找“ll”

        (注意一下哈,从第三个开始找时,这里s1是“worlld”,有两个‘l’,所以找到了,如果是“world”,输出的是垃圾数字(18446744073709551615),如果自己测试一下的话,会发现find函数找不到的返回值是前面的提到的string::npos)

        成员函数find_first_of()

        string s1("hello world");

        s1.find_first_of("abcd");

        在s1中从前向后查找"abcd"中任何一个字符第一次出现的地方,如果找到,返回找到字母的位置,如果找不到,返回string::npos。

        成员函数find_last_of()

        string s1("hello world");

        s1.find_last_of("abcd");

        在s1中查找"abcd"中任何一个字符最后一次出现的地方,如果找到,返回找到字母的位置,如果找不到,返回string::npos。

        成员函数find_first_not_of()

        string s1("hello world");

        s1.find_first_not_of("abcd");

        在s1中从前向后查找不在"abcd"中的字母第一次出现的地方,如果找到,返回找到字母的位置,如果找不到,返回string::npos。

        成员函数find_last_not_of()

        string s1("hello world");

        s1.find_last_not_of("abcd");

        在s1中从后向前查找不在"abcd"中的字母第一次出现的地方,如果找到,返回找到字母的位置,如果找不到,返回string::npos。

        上述4个函数的例子:

    string s1("hello world");
    cout<<s1.find("ll")<<endl;//结果:2
    cout<<s1.find("abc")<<endl;//结果:18446744073709551615
    cout<<s1.rfind("ll")<<endl;//结果:2
    cout<<s1.rfind("abc")<<endl;//结果:18446744073709551615
    cout<<s1.find("ll")<<endl;//结果:2
    cout<<s1.find_first_of("abcde")<<endl;//结果:1
    cout<<s1.find_first_of("abc")<<endl;//结果:18446744073709551615
    cout<<s1.find_last_of("abcde")<<endl;//结果:10
    cout<<s1.find_last_of("abc")<<endl;//结果:18446744073709551615
    cout<<s1.find_first_not_of("abcde")<<endl;//结果:0
    cout<<s1.find_first_not_of("abc")<<endl;//结果:0
    cout<<s1.find_last_not_of("abcde")<<endl;//结果:9
    cout<<s1.find_last_not_of("abc")<<endl;//结果:10

        (那串乱七八糟的数字就是npos对应的)

1.5 删除string中的字符

        成员函数erase()

        string s1("hello world");

        s1.erase(5);

        cout<<s1;

        cout<<s1.length();

        cout<<s1.size();

        去掉下标5及以后的字符

        输出:hello55

        (刚查了一下,size()和length()完全等同,只是length的可读性比较好而已)

1.6 替换string中的字符

        成员函数replace()

        用法1:

        string s1("hello world");

        s1.replace(2,3,"haha");

        cout<<s1;

        将s1中下标2开始的3个字符换成"haha"

        (这里就是把"llo"换成了"haha")

        输出:hehaha world

        用法2:

        string s1("hello world");

        s1.replace(2,3,"haha",1,2);

        cout<<s1;

        将s1中下标2开始的3个字符换成"haha"中下标1开始的2个字符

        (这里就是把"llo"换成了"ha")

        输出:heah world

        (老师这例子真别扭,heha world也行啊,heah是啥玩意啊)

        (我还以为是我英语不好,上网一查:)

        (好吧其实好像有这个单词,但是好像不太正式)

        (啊啊啊不扯了,继续学习)

1.7 在string中插入字符

        成员函数insert()

    string s1("hello world");
    string s2("show insert");
    s1.insert(5,s2);//将s2插入s1下标5的位置
    cout<<s1<<endl;//输出:helloshow insert world
    s1.insert(2,s2,5,3);
    //将s2中下标5开始的3个字符插入s1下标2的位置
    cout<<s1<<endl;//输出:heinslloshow insert world

        (从这个例子中能发现插入的位置是选定下标的后面)

1.8 转换成C语言式char*字符串

        成员函数c_str()

        string s1("hello world");

        printf("%s\n",s1.c_str());

        s1.c_str()返回传统的const char* 类型字符串,且该字符串以'\0'结尾,

        输出:hello world

        成员函数data()

        string s1("hello world");

        const char * p1 = s1.data();

        for(int i=0;i < s1.length();i++)

                printf("%c",&(p1+i))

        s1.data()返回一个char* (区别)类型的字符串,对s1的修改可能会使p1出错。

        输出:hello world

1.9 字符串流处理

        除了标准流和文件流输入输出外,还可以从string进行输入输出;

        类似istream和ostream进行标准流输入输出,我们用istringstream和ostringstream进行字符串上的输入输出,也称为内存输入输出。

        #include<string>

        #include<iostream>

        #include<sstream>

        样例:

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

int main(int argc, char const *argv[])
{
    string input("Input test 123 4.7 A");
    istringstream inputString(input);
    string string1, string2;
    int i;
    double d;
    char c;
    inputString >> string1 >> string2 >> i >> d >>c;
    cout<<string1<<endl<<string2<<endl;
    cout<<i<<endl<<d<<endl<<c<<endl;
    long L;
    if (inputString >> L)
    {
        cout<<"long\n";
    }
    else
    {
        cout<<"empty\n";
    }
    ostringstream outputString;
    int a = 10;
    outputString <<"This "<< a << "ok" << endl;
    cout<<outputString.str();
    /*
    输出:
    Input
    test
    123
    4.7
    A
    empty
    This 10ok
    */  
    return 0;
}

        最后inputString >> L 时,因为整个流已经读完了,所以返回false

后记:

        开始做这篇笔记是一天前,本来一看视频只有20分钟,想着做完就跑路,然后那天跑路了还没做四分之一,无奈,第二天下午继续,下午2点开始,一动不动做了3个小时才把剩下的做完。

        如果你问我累不累,我可以直接告诉你累,但是我是快乐的,我想说的是如果学习编程没有一个一颗爱好的心,是很难坚持下去的。

        不知为什么,在我思考如何敲程序的时候,我的内心充满的是一种追求答案的渴望,在我敲出程序的时候,我的内心充满的是成就感,在我学习这些知识的时候,我感叹设计STL标准库的那帮人的精巧。

        标准库中太多东西是相似的,不会在这里的函数在另一个地方不兼容,不会存在两个差不多的容器操作方式却截然不同的现象,还有类和对象的设计,提高了巨大的兼容性,或许这就是艺术吧。

        找到自己的爱好和擅长的事物太重要了,如果一个人热爱着一个事物,其他人若在对那件事无感的情况下,热爱者做好那件事的概率相对来说要大得多。而且热爱者还能获得极大的正向反馈。

        所以如果还没有找到自己的方向的话,努力去寻找吧!找到了方向的话,努力去前进吧!

        突发奇想写了这么多,逻辑也是乱七八糟,大家看看就好,如果对大家有所帮助那自然最好,没所帮助的话大家就当我啥也没说吧哈哈哈~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值