string类的常用接口
(1)string类对象的常见构造
- string():构造空的string类对象,即空字符串
- string(const char * s):用C-string来构造string类对象
- string(size_t n, char c):string类对象中包含n个字符c
- string(const string& s):拷贝构造函数
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
string s1;
string s2("hello");
string s3(5, 'a');
string s4(s3);
cout<<s1<<endl;
cout<<s2<<endl;
cout<<s3<<endl;
cout<<s4<<endl;
return 0;
}
(2)string类对象的容量操作
- size():返回字符串有效字符长度
- length():返回字符串有效字符长度
- capacity():返回空间总大小
- empty():检测字符串是否为空串
- clear():清空有效字符
- reserve(size_t n):为字符串预留空间
- resize(size_t n, char c):将有效字符个数改成n个,多出的空间用字符c填充
#include<iostream>
#include<cstring>
using namespace std;
//size/length/capacity/clear/resize
void test_string_1()
{
string s("hello");
cout<<s<<endl;//hello
cout<<s.size()<<endl;//5
cout<<s.length()<<endl;//5
cout<<s.capacity()<<endl;//15
s.clear();
cout<<s<<endl;//
cout<<s.size()<<endl;//0
cout<<s.capacity()<<endl;//15
s.resize(10, 'a');
cout<<s<<endl;//aaaaaaaaaa
cout<<s.size()<<endl;//10
cout<<s.capacity()<<endl;//15
s.resize(15);
cout<<s<<endl;//aaaaaaaaaa\0\0\0\0\0
cout<<s.size()<<endl;//15
cout<<s.capacity()<<endl;//15
s.resize(5);
cout<<s<<endl;//aaaaa
cout<<s.size()<<endl;//5
cout<<s.capacity()<<endl;//15
}
//reserve
void test_string_2()
{
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;//50
}
//用reserve提高插入效率,避免增容带来的开销
//有开销
void test_pushBack()
{
string s;
size_t sz = s.capacity();
for(int i = 0; i < 100; ++i)
{
s.push_back('c');
if(sz != s.capacity())
{
sz = s.capacity();
cout<<sz<<endl;
}
}
cout<<s<<endl;
}
//无开销
void test_pushBack_reserve()
{
string s;
s.reserve(100);
size_t sz = s.capacity();
for(int i = 0; i < 100; ++i)
{
s.push_back('c');
if(sz != s.capacity())
{
sz = s.capacity();
cout<<sz<<endl;
}
}
cout<<s<<endl;
}
int main()
{
test_string_1();
cout<<endl;
test_string_2();
cout<<endl;
test_pushBack();
cout<<endl;
test_pushBack_reserve();
return 0;
}
- size()与length()实现原理相同,引入size()是为了与其他容器接口保持一致
- clear()只是将字符串中有效字符清空,不改变底层空间大小
- resize(size_t n)与resize(size_t n, char c)都是将字符串有效字符个数改变到n
- reserve(size_t n)为字符串预留空间,不改变有效元素个数
(3)string类对象的访问及遍历操作
- operator[]:返回pos位置字符,const string类对象调用
- begin()+end():begin获取一个字符的迭代器,end获取最后一个字符下一个位置的迭代器
- rbegin()+rend():begin获取一个字符的迭代器,end获取最后一个字符下一个位置的迭代器
- 范围for:C++11
#include<iostream>
#include<cstring>
using namespace std;
void test_string_1()
{
string s1("hello");
const string s2("HELLO");
cout<<s1<<" "<<s2<<endl;
cout<<s1[0]<<" "<<s2[0]<<endl;
s1[0] = 'H';
cout<<s1<<endl;
//s2[0] = 'h';const不可修改
}
void test_string_2()
{
string s("Hello");
//for+operator[]
for(size_t i = 0; i < s.size(); ++i)
{
cout<<s[i]<<" ";
}
cout<<endl;
//迭代器
string::iterator it = s.begin();
while(it != s.end())
{
cout<<*it<<" ";
++it;
}
cout<<endl;
string::reverse_iterator rit = s.rbegin();
while(rit != s.rend())
{
cout<<*rit<<" ";
++rit;
}
cout<<endl;
//范围for:C++11
for(auto ch : s)
{
cout<<ch<<" ";
}
cout<<endl;
}
int main()
{
test_string_1();
cout<<endl;
test_string_2();
return 0;
}
(4)string类对象的修改操作
- push_back(char c):字符串后尾插字符c
- append(const string s):字符串后追加字符串
- operator+=:在字符串后追加字符串
- c_str():返回C格式字符串
- find()+npos:从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
- rfind():从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
- substr(size_t pos, size_t n):在字符串中从pos位置开始,截取n个字符返回
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string str;
str.append("Hello");
str.push_back(' ');
str += "Linux";
cout<<str<<endl;
cout<<str.c_str()<<endl;
//获取文件后缀
string file("file.cpp");
cout<<file<<endl;
size_t pos = file.find('.');
string suffix(file.substr(pos, file.size()-pos));
cout<<suffix<<endl;
//截取url中的域名
string url("http://github.com/lhn-debug/workspace.git");
cout<<url<<endl;
size_t start = url.find("://");
//static const size_t npos = -1
//npos是string中的一个静态成员变量
if(start == string::npos)
{
cout<<"invalid url"<<endl;
return 0;
}
start += 3;
size_t end = url.find('/', start);
string address = url.substr(start, end - start);
cout<<address<<endl;
//删除url的协议前缀
size_t del = url.find("://");
url.erase(0, pos + 3);
cout<<url<<endl;
return 0;
}
(5)string类非成员函数
- operator+:尽量少用,传值返回,深拷贝效率低
- operator>>:输入运算符重载
- operator<<:输出运算符重载
- getline:获取一行字符串
- relational operators:大小比较
几个例子
(1)翻转字符串
#include<iostream>
using namespace std;
string reverseString(string s)
{
if(s.empty())
{
return s;
}
size_t start = 0;
size_t end = s.size() - 1;
while(start < end)
{
swap(s[start], s[end]);
++start;
--end;
}
return s;
}
int main()
{
string s("hello");
string str = reverseString(s);
cout<<s<<endl;
cout<<str<<endl;
return 0;
}
(2)找字符串中第一个只出现一次的字符
#include<iostream>
using namespace std;
int firstUniqChar(string s)
{
if(s.empty())
{
return -1;
}
int count[256] = {0};
for(int i = 0; i < s.size(); ++i)
{
count[s[i]]++;
}
for(int i = 0; i < s.size(); ++i)
{
if(count[s[i]] == 1)
{
return i;
}
}
return -1;
}
int main()
{
string s = "dskasbfkaffnd";
int pos = firstUniqChar(s);
cout<<pos<<endl;
cout<<s<<endl;
if(pos != -1)
{
cout<<s[pos]<<endl;
}
}
(3)字符串里最后一个字符长度
#include<iostream>
using namespace std;
void lastWordLength()
{
string line;
while(getline(cin, line))
{
size_t pos = line.rfind(' ');
cout<<line.size()-pos-1<<endl;
}
}
int main()
{
lastWordLength();
return 0;
}