string类的学习

前言

1. 万能头文件bits/stdc++.h

 `#include<bits/stdc++.h>`了目前c++所包含的所有头文件,只要用了这个头文件就不再写其他头文件了

2. 关于C++中ios::sync_with_stdio(false);

ios::sync_with_stdio(false)-关闭同步输出流,用来加速cin速率
这个函数是一个“是否兼容stdio”的开关,C++为了兼容C,保证程序在使用了std::printf和std::cout的时候不发生混乱,将输出流绑到了一起。
cin,cout之所以效率低,是因为先把要输出的东西存入缓冲区,再输出,导致效率降低,而这段语句可以来打消iostream的输入 输出缓存,可以节省许多时间,使效率与scanf与printf相差无几,还有应注意的是scanf与printf使用的头文件应是stdio.h而不是 iostream。
使用场合:
string是C++标准库的一个重要的部分,主要用于字符串处理。可以使用输入输出流方式直接进行操作,也可以通过文件等手段进行操作。同时C++的算法库对string也有着很好的支持,而且string还和c语言的字符串之间有着良好的接口。虽然也有一些弊端,但是瑕不掩瑜。
其中使用的代码多数都是来自cpp官网,因为例子非常全。

1. 声明和初始化方法:

想使用string首先要在头文件当中加入< string >
声明方式也很简单

1.1声明:

string s;//声明一个string 对象
string ss[10];//声明一个string对象的数组

1.2初始化:

使用等号的初始化叫做拷贝初始化,不使用等号的初始化叫做直接初始化。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    string s;//默认初始化,一个空字符串
    string s1("ssss");//s1是字面值“ssss”的副本
    string s2(s1);//s2是s1的副本
    string s3=s2;//s3是s2的副本
    string s4(10,'c');//把s4初始化
    string s5="hiya";//拷贝初始化
    string s6=string(10,'c');//拷贝初始化,生成一个初始化好的对象,拷贝给s6

    //string s(cp,n)
    char cs[]="12345";
    string s7(cs,3);//复制字符串cs的前3个字符到s当中

    //string s(s2,pos2)
    string s8="asac";
    string s9(s8,2);//从s2的第二个字符开始拷贝,不能超过s2的size

    //string s(s2,pos2,len2)
    string s10="qweqweqweq";
    string s11(s10,3,4);//s4是s3从下标3开始4个字符的拷贝,超过s3.size出现未定义
    return 0;
}

1.3 getline 读取整行文本

getline函数取输入流对象和一个string对象作参数,将istream参数作返回值

int main()
{
	string line;
    while (getline(cin,line))   //getline不读取换行符
        cout<<line<<endl;
    return 0;
}

getline 指定分隔符

string line;
while (getline(cin,line,','))   //getline以逗号作为分隔符。在退出while时,ctrl+z才会输出最后一个字符串(因为没有以逗号结尾)。
    cout<<line<<endl;

3.vector< string >

3.1 vector< string > 在不经过for遍历的前提下转为一个字符串

3.1.1 accumulate( )

#include <vector>
#include <string>
#include <numeric>
#include <iostream>
int main()
{
    std::string lastdata;
    std::vector<std::string> veckrcid;
    veckrcid.push_back("hello");
    veckrcid.push_back("world");
    lastdata = accumulate(veckrcid.begin(), veckrcid.end(), lastdata);
    std::cout<<lastdata.c_str()<<std::endl;//
}

输出:

helloworld

accumulate定义在#include< numeric>
例:将sum设置为vec的元素之和再加上42。

int sum = accumulate(vec.begin() , vec.end() , 42);

  accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。
  accumulate算法返回累加的结果,其返回类型就是其第三个实参的类型。

3.1.2 join( )

通过boost中的join函数:

#include <boost/algorithm/string/join.hpp>
int main()
{
    std::vector<std::string> StrVec{"Hello,", " liu ", "World!"};
    std::string result = boost::algorithm::join(StrVec, "");

    std::cout<<result<<std::endl;//
}

2. 字符串处理:

2.1 substr操作:

注意substr没有迭代器作为参数的操作

string substr (size_t pos = 0, size_t len = npos) const;

产生子串
返回一个新建的初始化为string对象的子串的拷贝string对象。

子串是,在字符位置pos开始,跨越len个字符直到字符串的结尾,以先到者为准)对象的部分。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string s="abcdefg";

    //s.substr(pos1,n)返回字符串位置为pos1后面的n个字符组成的串
    string s2=s.substr(1,5);//bcdef

    //s.substr(pos)//得到一个pos到结尾的串
    string s3=s.substr(4);//efg

    return 0;
}

如果输入的位置(pos)超过字符的长度,会抛出一个out_of_range的异常

2.2 insert操作:

代码来自cpp官网,经过自己的整理
注意用迭代器当参数和无符号数当参数的区别
总结:

1. 在某个位置后面插入str.intsert(pos,str1,pos1,len)//pos1和len可以分情况省略
2. 在某个位置前面进行插入 要用迭代器表示某个具体位置str.intsert(iter,n,char)//n若缺省,则默认n=1;
   或者用s.insert(it,str.ita,str.itb)在it所指向的位置的前面插入[ita,itb)的字符串
#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    string str="to be question";
    string str2="the ";
    string str3="or not to be";
    string::iterator it;

    //s.insert(pos,str)//在s的pos位置插入str
    str.insert(6,str2);                 // to be the question

    //s.insert(pos,str,a,n)在s的pos位置插入str中插入位置a到后面的n个字符
    str.insert(6,str3,3,4);             // to be not the question

    //s.insert(pos,cstr,n)//在pos位置插入cstr字符串从开始到后面的n个字符
    str.insert(10,"that is cool",8);    // to be not that is the question

    //s.insert(pos,cstr)在s的pos位置插入cstr
    str.insert(10,"to be ");            // to be not to be that is the question

    //s.insert(pos,n,ch)在s.pos位置上面插入n个ch
    str.insert(15,1,':');               // to be not to be: that is the question

    //s.insert(s.it,ch)在s的it指向位置前面插入一个字符ch,返回新插入的位置的迭代器
    it = str.insert(str.begin()+5,','); // to be, not to be: that is the question

    //s.insert(s.it,n,ch)//在s的it所指向位置的前面插入n个ch
    str.insert (str.end(),3,'.');       // to be, not to be: that is the question...

    //s.insert(it,str.ita,str.itb)在it所指向的位置的前面插入[ita,itb)的字符串
    str.insert (it+2,str3.begin(),str3.begin()+3); // to be, or not to be: that is the question...

    return 0;
}

2.3 erase操作:

用来执行删除操作

1.  str.erase (pos,len) //删除str中pos位置开始的len个长度的字符串的值
2.  str.erase (str.ita,str.itb)//表示删除【str.ita,str.itb)区间的字符串,str.itb可缺省

删除操作有三种

指定pos和len,其中pos为为起始位置,pos以及后面len-1个字符串都删除
迭代器,删除迭代器指向的字符
迭代器范围,删除这一范围的字符串,范围左闭右开
代码来自cpp官网

#include <iostream>
#include <string>

int main ()
{
  std::string str ("This is an example sentence.");
  std::cout << str << '\n';
                          // "This is an example sentence."
  str.erase (10,8);       //            ^^^^^^^^
  //直接指定删除的字符串位置第十个后面的8个字符
  std::cout << str << '\n';
                            // "This is an sentence."
  str.erase (str.begin()+9);//           ^
  //删除迭代器指向的字符
  std::cout << str << '\n';
                            // "This is a sentence."
                            //       ^^^^^
  str.erase (str.begin()+5, str.end()-9);
  //删除迭代器范围的字符
  std::cout << str << '\n';
                            // "This sentence."
  return 0;
}

2.4 append和replace操作:

2.4.1 append()

append函数可以用来在字符串的末尾追加字符和字符串。由于string重载了运算符,也可以用+=操作实现
repalce顾名思义,就是替换的意思,先删除,后增加。
代码来自cpp官网,附上自己的解释

#include <iostream>
#include <string>

int main ()
{
    std::string str;
    std::string str2="Writing ";
    std::string str3="print 10 and then 5 more";

    //直接追加一个str2的字符串
    str.append(str2);                       // "Writing "
    //后面追加str3第6个字符开始的3个字符串
    str.append(str3,6,3);                   // "10 "
    //追加字符串形参的前5个字符
    str.append("dots are cool",5);          // "dots "
    //直接添加
    str.append("here: ");                   // "here: "
    //添加10个'.'
    str.append(10u,'.');                    // ".........."
    //添加str3迭代器范围的字符串
    str.append(str3.begin()+8,str3.end());  // " and then 5 more"
    //最后这个比较特殊,意思是添加5个'A',实际上参数里面的65对应的asc码就是65
    str.append<int>(5,65);                // "....."
    //字符串追加也可以用重载运算符实现
    str+="lalala";
    std::cout << str << '\n';
    return 0;
}

2.4.2 replace()

replace的使用方法,replace支持使用无符号整数寻找位置,也支持用迭代器寻找位置

#include <iostream>
#include <string>

int main ()
{
    std::string base="this is a test string.";
    std::string str2="n example";
    std::string str3="sample phrase";
    std::string str4="useful.";

    // replace signatures used in the same order as described above:

    // Using positions:                 0123456789*123456789*12345
    std::string str=base;           // "this is a test string."
    //第9个字符以及后面的4个字符被str2代替
    str.replace(9,5,str2);          // "this is an example string." (1)
    //第19个字符串以及后面的5个字符用str的第7个字符以及后面的5个字符代替
    str.replace(19,6,str3,7,6);     // "this is an example phrase." (2)
    //第8个字符以及后面的9个字符用字符串参数代替
    str.replace(8,10,"just a");     // "this is just a phrase."     (3)
    //第8个字符以及后面的5个字符用字符串参数的前7个字符替换
    str.replace(8,6,"a shorty",7);  // "this is a short phrase."    (4)
    //第22以及后面的0个字符用3个叹号替换
    str.replace(22,1,3,'!');        // "this is a short phrase!!!"  (5)
    //迭代器的原理同上
    // Using iterators:                                               0123456789*123456789*
    str.replace(str.begin(),str.end()-3,str3);                    // "sample phrase!!!"      (1)
    str.replace(str.begin(),str.begin()+6,"replace");             // "replace phrase!!!"     (3)
    str.replace(str.begin()+8,str.begin()+14,"is coolness",7);    // "replace is cool!!!"    (4)
    str.replace(str.begin()+12,str.end()-4,4,'o');                // "replace is cooool!!!"  (5)
    str.replace(str.begin()+11,str.end(),str4.begin(),str4.end());// "replace is useful."    (6)
    std::cout << str << '\n';   
    return 0;
}

以上的replace操作可以用insert和erase的操作组合替换,但是replace操作更加方便。

2.5 assign操作:

assign(分配,赋值)操作在一起列容器当中都存在,比如vector等等。是一个很基本的操作函数,string使用assign可以灵活的对其进行赋值。
代码来自cpp官网

#include <iostream>
#include <string>

int main ()
{
    std::string str;
    std::string base="The quick brown fox jumps over a lazy dog.";

    // used in the same order as described above:
    //直接把base赋值给str
    str.assign(base);
    std::cout << str << '\n';
    //把base第10个字符以及后面的8个字符赋给str
    str.assign(base,10,9);
    std::cout << str << '\n';         // "brown fox"
    //把参数中的0到6个字符串赋给str
    str.assign("pangrams are cool",7);
    std::cout << str << '\n';         // "pangram"
    //直接使用参数赋值
    str.assign("c-string");
    std::cout << str << '\n';         // "c-string"
    //给str赋值10个'*'字符
    str.assign(10,'*');
    std::cout << str << '\n';         // "**********"
    //赋值是10个'-'
    str.assign<int>(10,0x2D);
    std::cout << str << '\n';         // "----------"
    //指定base迭代器范围的字符串
    str.assign(base.begin()+16,base.end()-12);
    std::cout << str << '\n';         // "fox jumps over"

    return 0;
}

2.6 string的搜索操作:find和rfind函数:

string类中提供了很多性能优秀,使用方便的成员方法。而且在泛型算法当中也有很多实用的技巧。

find和rfind函数:

2.6.1 find()

find函数主要是查找一个字符串是否在调用的字符串中出现过,大小写敏感。
注意:find函数返回的是无符号整型。所以其返回的结果必定大于0,其返回值pos必须定义为string::size_type/(std::size_t),判断是否找到的方法是:if(pos != string::npos),其中,static const size_type npos = -1;于是 -1 被转换为无符号整数型别,npos 也就成了该型别的最大无符号值。
代码来自cpp官网

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    std::string str ("There are two needles in this haystack with needles.");
    std::string str2 ("needle");

    // different member versions of find in the same order as above:
    //在str当中查找第一个出现的needle,找到则返回出现的位置,否则返回结尾
    std::size_t found = str.find(str2);
    if (found!=std::string::npos)
    std::cout << "first 'needle' found at: " << found << '\n';
    //在str当中,从第found+1的位置开始查找参数字符串的前6个字符
    found=str.find("needles are small",found+1,6);
    if (found!=std::string::npos)
    std::cout << "second 'needle' found at: " << found << '\n';
    //在str当中查找参数中的字符串
    found=str.find("haystack");
    if (found!=std::string::npos)
    std::cout << "'haystack' also found at: " << found << '\n';
    //查找一个字符
    found=str.find('.');
    if (found!=std::string::npos)
    std::cout << "Period found at: " << found << '\n';
    //组合使用,把str2用参数表中的字符串代替
    // let's replace the first needle:
    str.replace(str.find(str2),str2.length(),"preposition");
    std::cout << str << '\n';
    return 0;
}

2.6.2 rfind

rfind函数就是找最后一个出现的匹配字符串,返回的位置仍然是从前往后数的。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    std::string str ("The sixth sick sheik's sixth sheep's sick.");
    std::string key ("sixth");//                    ^
    //rfind是找最后一个出现的匹配字符串
    std::size_t found = str.rfind(key);
    if (found!=std::string::npos)
    {
        cout<<found<<endl;//输出23
        str.replace (found,key.length(),"seventh");//找到的sixth替换成seventh
    }

    std::cout << str << '\n';
    return 0;
}

查找的效率非常高,我没看过stl源码剖析,但是感觉是用kmp实现的。呵呵,可以自己写一个。

2.6.3 find_….of函数:

find_first_of(args) 查找args中任何一个字符第一次出现的位置
find_last_of(args) 最后一个出现的位置
find_fist_not_of(args) 查找第一个不在args中的字符
find_last_not_of 查找最后一个不在args中出现的字符

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    std::string str1 ("Please, replace the vowels in this sentence by asterisks.");
    std::size_t found1 = str1.find_first_of("aeiou");
    //把所有元音找出来用*代替
    while (found1!=std::string::npos)
    {
        str1[found1]='*';
        found1=str1.find_first_of("aeiou",found1+1);
    }
    std::cout << str1 << '\n';

    //在str2中找到第一个不是英文字母和空格的字符
    std::string str2 ("look for non-alphabetic characters...");
    std::size_t found2 = str2.find_first_not_of("abcdefghijklmnopqrstuvwxyz ");
    if (found2!=std::string::npos)
    {
        std::cout << "The first non-alphabetic character is " << str2[found2];
        std::cout << " at position " << found2 << '\n';
    }
    return 0;
}

find_last_of和find_last_not_of与first基本相同,就不写例子代码了。

2.7 比较与转换:

类似c语言的字符串比较函数strcmp函数一样,支持字符串比较操作,同时也类似python、C#语言中的函数一样,支持把数字和字符串转换。有些特性是C++11当中才有。
注意编译器bug:
在MinGW编译器当中如果版本低于3.8,虽然支持c++11但是里面有一个bug,就是不支持字符串和数组的转换!要更新MinGW的版本才可以,或者直接使用g++。

2.7.1 比较

2.7.1.1 strcmp,stricmp函数:

这两个函数都是针对char类型的字符的,所以在使用这两个函数的时候,需要将其转换为字符类型。对于string s;使用s.c_str();
strcmp:

extern int strcmp(const char *s1,const char * s2);

不区分大小写比较:
stricmp:

extern int stricmp(const char *s1,const char * s2);

在编译过程中发现此函数针对vs2012版本及以前的编译器有效,之后版本的编译器需要使用_stricmp()

2.7.1.2 compare函数:

和strcmp函数一样,如果两个字符串相等,那么返回0,调用对象大于参数返回1,小于返回-1。
在compare当中还支持部分比较,里面有6个参数可以设置。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    string s1="123",s2="123";
    cout<<s1.compare(s2)<<endl;//0

    s1="123",s2="1234";
    cout<<s1.compare(s2)<<endl;//-1

    s1="1234",s2="123";
    cout<<s1.compare(s2)<<endl;//1

    std::string str1 ("green apple");
    std::string str2 ("red apple");

    if (str1.compare(str2) != 0)
    std::cout << str1 << " is not " << str2 << '\n';
    //str1的第6个字符以及后面的4个字符和参数比较
    if (str1.compare(6,5,"apple") == 0)
    std::cout << "still, " << str1 << " is an apple\n";

    if (str2.compare(str2.size()-5,5,"apple") == 0)
    std::cout << "and " << str2 << " is also an apple\n";
    //str1的第6个字符以及后面的4个字符和str2的第4个字符以及后面的4个字符比较
    if (str1.compare(6,5,str2,4,5) == 0)
    std::cout << "therefore, both are apples\n";
    return 0;
}

由于string重载了运算符,可以直接用>,<,==来进行比较,也很方便。

2.7.2 转换

2.7.2.1 字符串大小写转换

字符串全部转大写:
transform(s2.begin(), s2.end(), s2.begin(), ::toupper);
字符串全部转小写:
transform(s3.begin(), s3.end(), s3.begin(), ::tolower);

2.7.2.2 数值转换:

在io的部分有过数值和字符串相互转换的例子,使用的是stringstream函数,在c++11当中有定义好的现成的函数取调用,非常方便。

函数用途
to_string(val)把val转换成string
stoi(s,p,b)把字符串s从p开始转换成b进制的int
stol(s,p,b)long
stoul(s,p,b)unsigned long
stoll(s,p,b)long long
stoull(s,p,b)unsigned long long
stof(s,p)float
stod(s,p)double
stold(s,p)long double

//注意,下段代码在MinGw中会报错!即使使用c++11编译也一样,无法识别to_string!

#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    string s1;
    s1=to_string(100);
    cout<<s1<<endl;
    int a=stoi(s1,0,10)+1;
    cout<<a<<endl;

    return 0;
}
2.7.2.2.1 atoi()与.c_str()函数

atoi()是C语言中的字符串转换成整型数的一个函数,其函数原型为:

int atoi(const char *nptr);

.c_str()函数的原型是:

const char*c_str() const;

atoi()是C语言提供的函数,而C语言中没有string类,字符串使用char指针来实现的。C与C++本身就是一家,为了让它们在一定程度上可以通用,就有了.c_str()函数。

#include <iostream>
#include <string>

using namespace std;

int main()
{  
    string str ="123";
    int num = atoi(str.c_str());
    cout<<num<<endl;
    getchar();
    return 0;
}

2.8 size()与length()

c++中,在获取字符串长度时,size()函数与length()函数作用相同。返回的都是size_type除此之外,size()函数还可以获取vector类型的长度。

2.9 empty()

s.empty() 返回bool值

2.10 sort()

与vector相同

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值