导读
用字符数组存放字符串容易发生数组越界的错误,而且往往难以察觉。因此,C++标准模板库设计了 string 数据类型,专门用于字符串处理。string 并不是 C++ 的基本数据类型,它是 C++ 标准模板库中的一个“类”。
目录
一、string类
string 类 是一个模板类 ,它的定义如下:
typedef basic_string<char> string;
使用string类要包含头文件 <string>
string对象的初始化:
string s1 = "hello"; //初始化字符串
string s2 ("world"); //另一种初始化
string s3; //初始化字符串,空字符串
string s4(5, 'a'); //s4由连续5个a组成,即s4="aaaaa";
string s5(s1,2,3); //从s1的下标为2的字符开始,连续3个字符赋值给s5,即s5="llo";
string s6(s1, 1); //从s1的下标为1的字符开始,将后续的所有字符赋值给s6,即s6="ello";
char name [] = "Lady Gaga";
s1 = name; //赋值后s1中的内容和name相同,修改s1不会影响name
char *p=“hello”; //字符指针也可赋值给string对象
s1=p;
类中不提供以字符和整数为参数的构造函数
错误的初始化方法:
string error1 = ‘c’; // 错
string error2(‘u’); // 错
string error3 = 22; // 错
string error4(8); // 错
可以将字符赋值给string对象
string s;
s = ‘n’;
程序样例
#include <string>
#include <iostream>
using namespace std;
int main(){
string s1("Hello"); cout << s1 << endl;
string s2(8,'x'); cout << s2 << endl;
string month = "March"; cout << month << endl;
string s;
s='n';
cout << s << endl;
return 0;
输出
Hello
xxxxxxxx
March
n
构造的string太长而无法表达时会抛出length_error异常
string对象的内容不一定用‘\0’结束;
string 对象的长度用成员函数 length()读取;
string s("hello");
cout << s.length() << endl;
string 支持流读取运算符
string s;
cin>>s;
string 支持getline函数
string s;
getline(cin,s);
二、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的字符开始复制3个字符给s3
s3=“atp”
单个字符复制
s2[5] = s1[3] = ‘a’;
逐个访问string对象中的字符
string s1("Hello");
for(int i=0;i<s1.length();i++)
cout << s1.at(i) << endl;//cout<<s1[i]<<endl;
成员函数at会做范围检查,如果超出范围,会 抛出out_of_range异常,而下标运算符不做范围 检查。
可以自己写个验证程序,观察两者的区别。
用 + 运算符连接字符串
string s1 = "hello";
string s2 = " world";
s1 += s2;//正确,s1的值为" hello world "
s1 +="world";// 正确,s1的值为"hello world "
s1 +='c'; //正确,s1的值"helloc“
注意:加号两边至少要有一个string类型的对象
s1 = “hello" + “world"; //错误
用成员函数 append 连接字符串
string s1("good "), s2("morning! "); s1.append(s2);
cout << s1<<endl;
s2.append(s1, 3, s1.size());//s1.size(),s1字符数 cout << s2<<endl;
// 下标为3开始,s1.size()个字符,如果字符串内没有足 够字符,则复制到字符串最后一个字符
good morning!
morning! d morning!
三、比较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 << f2 << endl << f3 << endl;
cout << f4 << endl << f5 << endl;
0 // hello == hello
1 // hello > hell
-1 // hell < hello
-1 // el < hell
1 // hello > hell
四、子串
成员函数 substr
string s1("hello world"), s2;
s2 = s1.substr(4,5); // 下标4开始5个字符
cout << s2 << endl;
o wor
五、交换string
成员函数 swap
string s1("hello world"), s2("really");
s1.swap(s2);
cout << s1 << endl;
cout << s2 << endl;
really
hello world
六、string的特性
成员函数 capacity() 返回无需增加内存即可存放的字符数;
成员函数maximum_size()返回string对象可存放的最大字符数;
成员函数length()和size()相同,返回字符串的大小/长度;
成员函数empty() 返回string对象是否为空;
成员函数resize()改变string对象的长度。
string s1("hello world");
cout << s1.capacity() << endl; cout << s1.max_size() << endl; cout << s1.size() << endl;
cout << s1.length() << endl;
cout << s1.empty() << endl; cout << s1 << "aaa" << endl; s1.resize(s1.length()+10);
cout << s1.capacity() << endl;
cout << s1.max_size() << endl; cout << s1.size() << endl;
cout << s1.length() << endl;
cout << s1 << "aaa" << endl; s1.resize(0);
cout << s1.empty() << endl;
31// capacity
4294967293// maximum_size
11// length
11// size
0// empty
hello worldaaa
31
4294967293
21
21
hello world aaa
1
七、在string中寻找、替换和插入字符
寻找string中的字符
成员函数 find()
string s1("hello world");
int pos=s1.find("lo"); //pos=3
在s1中从前向后查找 “lo” 第一次出现的地方,如果 找到,返回 “lo”开始的位置,即' l '所在的位置下标。 如果找不到,返回 string::npos (string中定义的静态常量)
成员函数rfind()
string s1("hello world");
int pos=s1.rfind("lo"); //pos=3
在s1中从后向前查找 “lo” 第一次出现的地方,如果 找到,返回 “lo”开始的位置,即 'l '所在的位置下标。 如果找不到,返回 string::npos 。
成员函数 find_first_of()
string s1("hello world");
int pos=s1.find_first_of(“abcd"); //pos=10
在s1中从前向后查找 “abcd” 中任何一个字符第一次出现的地方,如果找到,返回找到字母的位置,如 果找不到,返回 string::npos。
成员函数 find_last_of()
string s1("hello world");
int pos=s1.find_last_of(“abcd"); //pos=10
在s1中从后向前查找 “abcd” 中任何一个字符最后一次出现的地方,如果找到,返回找到字母的位置,如果找不 到,返回 string::npos。
成员函数 find_first_not_of()
string s1("hello world");
int pos=s1.find_first_not_of(“abcd"); //pos=0
在s1中从前向后查找不在 “abcd” 中的字母第一次出现的地方,如果找到,返回找到字母的位置,如果找不到,返回 string::npos。
成员函数 find_last_not_of()
string s1("hello world");
int pos=s1.find_last_not_of(“abcd"); //pos=9
在s1中从后向前查找不在 “abcd” 中的字母第一次出现的地方,如果找到,返回找到字母的位置,如果找不到,返回 string::npos。
string s1("hello worlld");
cout << s1.find("ll") << endl;
cout << s1.find("abc") << endl;
cout << s1.rfind("ll") << endl; cout << s1.rfind("abc") << endl;
cout << s1.find_first_of("abcde") << endl; cout << s1.find_first_of("abc") << endl; cout << s1.find_last_of("abcde") << endl; cout << s1.find_last_of("abc") << endl;
cout << s1.find_first_not_of("abcde") << endl;
cout << s1.find_first_not_of("hello world") << endl; cout << s1.find_last_not_of("abcde") << endl;
cout << s1.find_last_not_of("hello world") << endl;
2
4294967295
9
4294967295
1
4294967295
11
4294967295
0
4294967295
10
4294967295
查找不成功,尽量用string::npos来判断。例如:
int n=s1.find("abc");
if(n==string::npos) cout<<"not found"<<endl;
else cout<<"found"<<endl;
成员函数find()
string s1("hello worlld");
cout << s1.find("ll",1) << endl;
cout << s1.find("ll",3) << endl;
cout << s1.find("lol",3) << endl;
// 分别从下标1,3,3开始查找
2
9
4294967295
删除string中的字符
成员函数erase()
string s1("hello world");
s1.erase(5); // 去掉下标 5 及之后的字符
cout << s1<<endl;
cout << s1.length()<<endl;
cout << s1.size()<<endl;
string s2("hello world");
s2.erase(5,2); // 去掉从下标 5 开始的连续2个字符
cout << s2<<endl;
cout << s2.length()<<endl;
cout << s2.size()<<endl;
hello
5
5
helloorld
9
9
替换string中的字符
成员函数 replace()
string s1("hello world");
s1.replace(2,3, “haha");
cout << s1;
//将s1中下标2 开始的3个字符换成“haha”输出:
hehaha world
string s1("hello world");
s1.replace(2,3, "haha", 1,2); cout << s1;
// 将s1中下标2 开始的3个字符换成“haha”中下标1 开始的2个字符
heah world
在string中插入字符
成员函数insert()
string s1("hello world");
string s2(“show insert");
s1.insert(5,s2); // 将s2插入s1下标5的位置
cout << s1 << endl;
s1.insert(2,s2,5,3);
//将s2中下标5开始的3个字符插入s1下标2的位置
cout << s1 << endl;
helloshow insert world
heinslloshow insert world
八、转换成c语言式char *字符串
注意:string中的字符串没有null做结束符
成员函数 c_str()
string s1("hello world");
const char *p=s1.c_str();
cout<<p<<endl;
// s1.c_str() 返回传统的char * 类型字符串,并在末尾增加了一个null结束符。
直接接收string的值,只允许使用常指针,不能修改字符串的值。const char *p=s1.c_str();
如果希望可以随意改变字符串的值,要如下使用:
string s1("hello world");
char *p=new char[s1.length()+1];
strcpy(p,s1.c_str());
cout<<p<<endl;
hello world
成员函数data()
string s1("hello world");
const char * p1=s1.data();
for(int i=0;i<s1.length();i++)
cout<<*(p1+i);
// s1.data() 返回一个char * 类型的字符串,对s1 的修改可能会使p1出错。
hello world
同理可得:
string s1("hello world");
char * p1=new char[s1.length()+1];
strcpy(p1,s1.data());
cout<<p1<<endl;
成员函数copy()
string s1("hello world"); int len = s1.length();
char * p2 = new char[len+1]; s1.copy(p2,5,0);
p2[5]=0;
cout << p2 << endl;
// s1.copy(p2,5,0) 从s1的第一个字符开始制作一个最长5 个字符长度的字符串副本并将其赋值给p2。返回值表明 实际复制字符串的长度。
数值和字符串的相互转化
数值转化成字符串str()
( #include <bits/stdc++.h> //定义了stringstream )
int a=123;
stringstream sstr;
string s;
sstr << a;
sstr>>s;
//或者s=sstr.str();
字符串转化成数值
(#include <bits/stdc++.h> //定义了stringstream )
string a=”123.45”;
double r;
stringstream ss;
ss<<a;
ss>>r;
九、迭代器
迭代器的概念:是一种可以遍历容器元素的数据类型。
字符串上的迭代器相当于一个指针,某一时刻 该指针指向字符串上的一个字符,该指针可以 通过 + - 操作移动位置,从而指向字符串不同的 字符。
可以把string::const_iterator看作一种数据类型,用它可以定义字符串上的迭代器变量,用来在 字符串中的字符间游走。
例如:
string s1("testing iterators"); string::const_iterator i1 = s1.begin();
while(i1 != s1.end()){
cout << *i1; i1++;
}
cout << endl;
// s1.begin() 和 s1.end() 返回值类型为const_iterator
// 分别为字符串的第一个和最后一个,i1++实现迭代器 的移动。
十、字符串流处理
除了标准流和文件流输入输出外,还可以从string进行输入输出;
#include <sstream.h>
例:字符串输入流
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";
输出:
Input test 123
4.7
A
empty
例:字符串输出流
string input("Output test 123 4.7 A");
istringstream inputString(input);
string string1, string2;
int i; double d;
char c;
inputString >> string1 >> string2 >> i >> d >> c;
ostringstream outputString;
outputString << string1 << endl << string2 << endl; outputString << i << endl << d << endl << c <<endl; cout << outputString.str();
输出: Output test
123
4.7
A