C++中被认为不太好的一个特点就是兼容C,兼容C需要付出很沉重的代价,不过这其中部分原因有当时的局限性。C风格的字符串设计不是一个比较好的方式,特别是结尾的’\0’结束符。所以在此C++ STL中设计了一种string类型来代替C风格的字符串,比起C风格的字符串。C++中的string更安全,也更加好用。
其实string并不是一个单独的容器,是basic_string类的一个typedef,在string头文件中有这样的一个定义。相应地,还有宽字符集的wstring
typedef std::basic_string<char> std::string
typedef std::basic_string<wchar_t> std::string
现在讲一下string的一些基本用法。
string的构造
string s1; //默初始化,s1为一个空串
string s2(s1) //s2是s1的副本
string s3=s1; //same as s2(s1)
string s4("Liang"); //s3位字面值"Liang"的副本
string s5="Liang"; //same as s4("Liang")
string s6(n,'c'); //把s6初始化为n个连续字符c的集合
下面是一个简单示例:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1;
string s2(s1);
string s3=s1;
string s4("Liang");
string s5="Liang";
string s6(10,'c');
cout<<s1<<endl<<s2<<endl<<s3<<endl;
cout<<s4<<endl<<s5<<endl<<s6<<endl;
}
/*Output*/
Liang
Liang
cccccccccc
除了上面之外,string还有另外三种构造函数:
string s(cp,n) //s是从cp指向的数组中前n个字符的拷贝,n至少包含n个字符
string s(s2,pos2) //s是string s2从下标pos2开始的字符的拷贝,如果pos2>s2.size(),则构造函数行为为定义
string s(s2,pos2,len2) //s是string s2从pos2开始len2个字符的拷贝,同样,如果pos2>s2.size()则构//造函数行为未定义,不管len2的大小是多少,构造函数最多拷贝size()-pos2个字符,不会抛出异常.
有点啰嗦是吧,没事,我举个例子。
#include <iostream>
#incldue <string>
using namespace std;
int main(void){
const char *cp="Hello Mark Liang";
char noNull[]={'H','i'};
string s1(cp); //s1=="Hello Mark Liang"
string s2(noNull,2); //copy two character from noNull s2=="Hi"
string s3(noNull); //undefined behavior noNull不是以空字符结尾
string s4(cp+6,5); //copy char from cp[6] so s4=="Mark "
string s5(s1,6,5); //copy char from s1[6] so s5=="Mark "
string s6(s1,6); //copy from s1[6] util the end of s1 so s6=="Mark Liang"
string s7(s1,6,20); //right s7 same as s6 so s7=="Mark Liang"
// string s8(s1,20); //error throw a out_of_range exception
}
运行结果:
Hello Mark Liang
Hi
Hi
Mark
Mark
Mark Liang
Mark Liang
当我们从const char *类型创建string时,要求指针指向的数组必须以空字符结尾, 拷贝操作直到遇到空字符。
string类型的比较操作
有了运算符的重载,string的比较和连接变得很方便。可以对string进行+,+=,==,>=,<=,!=这些操作。
看下面的例子
#include <iostream>
#include <string>
using namespace std;
int main(void){
string name="Mark";
if(name=="SimonS")
cout<<"You are SimonS"<<endl;
else if(name!="SimonS")
cout<<"You are not SimonS"<<endl;
else if(name<"SimonS")
cout<<"Your name should be after of SimonS"<<endl;
else if(name>"SimonS")
cout<<"Your name should be ahead of SimonS"<<endl;
name+=", Do you know SimonS? a ACMer, retired";
string info="Hi, "+name;
for(auto temp=info.begin();temp!=info.end();temp++)
cout<<*temp;
return 0;
}
/**output**/
You are not SimonS
Hi, Mark Do you know SimonS? A ACMer, retired
string可以通过”+”运算符把两个字符串加起来,不过也有一个前提,”+”号两边必须有一个是string类型。例如:
const char * str1="Hello Mark";
const char * str2=" Liang";
string info=str1+str2; //error
上述例子将会编译出错。因为只有左右两边有一个是string类型,编译器就会把其中的C风格字符串转换为string对象。而如果两个都不是string类型,则就无法转换。
除此之外,string中还定义了compare()函数,compar函数有6个版本。根据我们是比较两个string,一个字符串数组与string,参数各有不同。都可以比较整个或一部分字符串。
string类型的查找
1:substr()函数
substr()返回一个string,它是一个原始string的一部分或全部。它支持以下几种操作:
string s="Mark Liang";
string s2=s.substr(0,4); //s2="Mark"
string s3=s.substr(5); //s3="Liang"
string s4=s.substr(5,20); //s4="Liang"
string s5=s.substr(20); //try a out_of_range error
2:find()操作
string类提供了6个不同的搜索函数,其中每个函数都有4个重载版本。如果查找成功,则返回一个string::size_type
值,表示匹配发生位置的下标。如果查找失败,则返回一个string::npos
的static成员,标准库将npos定义为一个const string::size_type类型。6个函数分别如下:
s.find(args) //查找s中args第一次出现的位置
s.rfind(args) //查找s中args最后一次出现的位置
s.find_first_of(args) //在s中查找args中任何一个字符第一次出现的位置
s.find_last_of(args) //在s中查找ars中任何一个字符最后出现的位置
s.find_first_not_of(args)//查找第一个不在args中的字符
s.find_last_not_of(args) //查找最后一个不在args中的字符
下面有一个例子作为示范,把一个string中的某段字符串替换为指定的字符串
#include <iostream>
#include <string>
using namespace std;
void replaceString(string &str,const string &src,const string &dst){
string::size_type pos=0;
while((pos=str.find(src,pos))!=string::npos){
str.replace(pos,src.size(),dst);
pos+=dst.size();
}
}
int main(int argc,char **argv){
string info="Hi,Do you know Mark? A ACMer from HangZhou.Mark is very smart!";
string dst="SimonS";
cout<<"Before replace:"<<info<<endl;
replaceString(info,"Mark",dst);
cout<<"After replace:"<<info<<endl;
return 0;
}
/****Output****/
Before replace:Hi,Do you know Mark? A ACMer from HangZhou.Mark is very smart!
After replace:Hi,Do you know SimonS? A ACMer from HangZhou.SimonS is very smart!
数值转换
C++11标准的引入,让C++变得更加完美。据C++之父,Bjarne Stroustrup也曾说,C++11让他感觉已经不是C++了,是一门新的语言。当然了,string中也增加了类似Java中的toString()方法,stoi(),stod()等从字符串到数值和to_string(),从数值到字符串的转换函数。
#include <iostream>
#include <string>
int main()
{
std::string str1 = "45";
std::string str2 = "3.14159";
std::string str3 = "31337 with words";
std::string str4 = "words and 2";
int myint1 = std::stoi(str1);
int myint2 = std::stoi(str2);
int myint3 = std::stoi(str3);
// error: 'std::invalid_argument'
// int myint4 = std::stoi(str4);
std::cout << "std::stoi(\"" << str1 << "\") is " << myint1 << '\n';
std::cout << "std::stoi(\"" << str2 << "\") is " << myint2 << '\n';
std::cout << "std::stoi(\"" << str3 << "\") is " << myint3 << '\n';
//std::cout << "std::stoi(\"" << str4 << "\") is " << myint4 << '\n';
}
/****OutPut****/
std::stoi("45") is 45
std::stoi("3.14159") is 3
std::stoi("31337 with words") is 31337
对sring的介绍就到这里,大家如果想更详细的了解,请访问:
http://en.cppreference.com/w
参考资料:
https://www.byvoid.com/blog/cpp-string
http://en.cppreference.com/w/cpp/string/basic_string
`