string 容器基本概念
C风格字符串(以\0
结尾的字符数组)太过复杂,难于掌握,不太适合大程序的开发,所以C++STL中定义了一种string类,在头文件<string>
中。
string 和 C风格字符 串对比
char*
是一个指针,string
是一个类
string
封装了char*
,管理这个字符串,是一个char*
型的容器。
string
封装了很多实用的成员方法
查找find
,拷贝copy
,删除erase
,替换replace
,插入insert
......
不用考虑内存释放和越界
string
管理char*
所分配的内存,每一次string
的复制/赋值,取值都由string
类负责维护,不用担心复制越界和取值越界等。
string
本质上是一个动态的char数组。
string 容器常用操作
string 构造函数
复制 string ();
// 默认构造函数,创建一个空的字符串
string ( const string & str);
// 拷贝构造函数,使用一个string对象初始化另一个string对象
string ( const char* s);
// 含参构造函数,使用C风格字符串初始化
string ( int n , char c);
// p含参构造函数,使用n个字符c初始化
string 基本赋值操作
=
赋值操作符
复制 string & operator =( const char* s);
// C风格字符串赋值给当前的字符串
string & operator =( const string & s);
// 把字符串s赋给当前的字符串
string & operator =( const char c);
//字符赋值给当前的字符串
assign
成员函数
复制 string & assign ( const char* s);
// C风格字符串赋值给当前的字符串
string & assign ( const char* s , int n);
// 把C风格字符串s的前n个字符赋给当前的字符串
string & assign ( const string & s);
// 把字符串s赋给当前字符串
string & assign ( int n , char c);
// 把n个字符c赋给当前的字符串
string & assign ( const string & s , int start , int n);
// 将字符串s中从start开始的n个字符赋值给当前字符串
string 存取字符操作
[]
下标获取操作符
复制 char& operator []( int n);
// 通过[]下标方式获取字符
使用下标操作符获取字符时,如果下标越界,程序将会强制终止。
at
成员函数
复制 char& at ( int n);
// 通过at方法获取字符
使用at方法获取字符时,如果下标越界,at方法内部会抛出异常(exception
),可以使用try-catch
捕获并处理该异常。示例如下:
复制 #include <stdexception>
//标准异常头文件
#incldue < iostream >
using namespace std;
int main ()
{
string s = "hello world" ;
try
{
//s[100]不会抛出异常,程序会直接挂掉
s . at ( 100 );
}
catch (out_of_range & e)
//如果不熟悉异常类型,可以使用多态特性, catch(exception& e)。
{
cout << e . what () << endl;
//打印异常信息
}
return 0 ;
}
string 拼接操作
+=
复合操作符
复制 string & operator +=( const string & str);
// 将字符串str追加到当前字符串末尾
string & operator +=( const char* str);
// 将C风格字符数组追加到当前字符串末尾
string & operator +=( const char c);
// 将字符c追加到当前字符串末尾
/* 上述操作重载了复合操作符+= */
append
成员函数
复制 string & append ( const char* s);
// 把C风格字符数组s连接到当前字符串结尾
string & append ( const char* s , int n);
// 把C风格字符数组s的前n个字符连接到当前字符串结尾
string & append ( const string & s);
// 将字符串s追加到当前字符串末尾
string & append ( const string & s , int pos , int n);
// 把字符串s中从pos开始的n个字符连接到当前字符串结尾
string & append ( int n , char c);
// 在当前字符串结尾添加n个字符c
string 查找和替换
find
成员函数
复制 int find ( const string & str , int pos = 0 ) const ;
// 查找str在当前字符串中第一次出现的位置,从pos开始查找,pos默认为0
int find ( const char* s , int n = 0 ) const ;
// 查找C风格字符串s在当前字符串中第一次出现的位置,从pos开始查找,pos默认为0
int find ( const char* s , int pos , int n) const ;
// 从pos位置查找s的前n个字符在当前字符串中第一次出现的位置
int find ( const char c , int pos = 0 ) const ;
// 查找字符c第一次出现的位置,从pos开始查找,pos默认为0
当查找失败时,find
方法会返回-1
,-1
已经被封装为string的静态成员常量string::npos
。
复制 static const size_t nops = - 1 ;
rfind
成员函数
复制 int rfind ( const string & str , int pos = npos) const ;
// 从pos开始向左查找最后一次出现的位置,pos默认为npos
int rfind ( const char* s , int pos = npos) const ;
// 查找s最后一次出现的位置,从pos开始向左查找,pos默认为npos
int rfind ( const char* s , int pos , int n) const ;
// 从pos开始向左查找s的前n个字符最后一次出现的位置
int rfind ( const char c , int pos = npos) const ;
// 查找字符c最后一次出现的位置
find
方法通常查找字串第一次出现的位置,而rfind
方法通常查找字串最后一次出现的位置。
rfind(str, pos)
的实际的开始位置是pos + str.size()
,即从该位置开始(不包括该位置字符)向前寻找匹配项,如果有则返回字符串位置,如果没有返回string::npos
。
-1
其实是size_t
类的最大值(学过补码的同学应该不难理解),所以string::npos
还可以表示“直到字符串结束”,这样的话rfind中pos的默认参数是不是就不难理解啦?
replace
成员函数
复制 string & replace ( int pos , int n , const string & str);
// 替换从pos开始n个字符为字符串s
string & replace ( int pos , int n , const char* s);
// 替换从pos开始的n个字符为字符串s
string 比较操作
compare
成员函数
复制 int compare ( const string & s) const ; // 与字符串s比较
int compare ( const char* s) const ; // 与C风格字符数组比较
compare
函数依据字典序比较,在当前字符串比给定字符串小时返回-1
,在当前字符串比给定字符串大时返回1
,相等时返回0
。
比较操作符
复制 bool operator <( const string & str) const ;
bool operator <( const char* str) const ;
bool operator <=( const string & str) const ;
bool operator <=( const char* str) const ;
bool operator ==( const string & str) const ;
bool operator ==( const char* str) const ;
bool operator >( const string & str) const ;
bool operator >( const char* str) const ;
bool operator >=( const string & str) const ;
bool operator >=( const char* str) const ;
bool operator !=( const string & str) const ;
bool operator !=( const char* str) const ;
string
类重载了所有的比较操作符,其含义与比较操作符本身的含义相同。
string 子串
substr
成员函数
复制 string substr ( int pos = 0 , int n = npos) const ;
// 返回由pos开始的n个字符组成的字符串
string 插入和删除操作
insert
成员函数
复制 string & insert ( int pos , const char* s); // 在pos位置插入C风格字符数组
string & insert ( int pos , const string & str); // 在pos位置插入字符串str
string & insert ( int pos , int n , char c); // 在pos位置插入n个字符c
返回值是插入后的字符串结果,erase
同理。其实就是指向自身的一个引用。
erase
成员函数
复制 string & erase ( int pos , int n = npos); // 删除从pos位置开始的n个字符
默认一直删除到末尾。
string
和 C-Style
字符串的转换
string
转 const char*
复制 string str = "demo" ;
const char* cstr = str . c_str ();
const char*
转 string
复制 const char* cstr = "demo" ;
string str ( cstr ); // 本质上其实是一个有参构造
在c++中存在一个从const char*
到string
类的隐式类型转换,但却不存在从一个string
对象到const char*
的自动类型转换。对于string
类型的字符串,可以通过c_str()
方法返回string
对象对应的const char*
字符数组。
比如说,当一个函数的参数是string
时,我们可以传入const char*
作为参数,编译器会自动将其转化为string
,但这个过程不可逆。
为了修改string字符串的内容,下标操作符[]
和at
都会返回字符串的引用,但当字符串的内存被重新分配之后,可能发生错误。(结合字符串的本质是动态字符数组的封装便不难理解了)
和 string 相关的全局函数
注:有的可能需要C++11标准。
大小写转换
复制 #include <cctype>
// 在iostream中已经包含了这个头文件,如果没有包含iostream头文件,则需手动包含cctype
int tolower ( int c); // 如果字符c是大写字母,则返回其小写形式,否则返回本身
int toupper ( int c); // 如果字符c是小写字母,则返回其大写形式,否则返回本身
/**
* C语言中字符就是整数,这两个函数是从C库沿袭过来的,保留了C的风格
*/
如果想要对整个字符串进行大小写转化,则需要使用一个for
循环,或者配合和algorithm
库来实现。例如:
复制 #include <string>
#include <cctype>
#include <algorithm>
string str = "Hello, World!" ;
transform ( str . begin () , str . end () , str . begin () , toupper); //字符串转大写
transform ( str . begin () , str . end () , str . begin () , tolower); //字符串转小写
字符串和数字的转换
int
/ double
转 string
c++11标准新增了全局函数std::to_string
,十分强大,可以将很多类型变成string
类型。
复制 #include <string>
using namespace std;
/** 带符号整数转换成字符串 */
string to_string ( int val);
string to_string ( long val);
string to_string ( long long val);
/** 无符号整数转换成字符串 */
string to_string ( unsigned val);
string to_string ( unsigned long val);
string to_string ( unsigned long long val);
/** 实数转换成字符串 */
string to_string ( float val);
string to_string ( double val);
string to_string ( long double val);
string
转 double
/ int
复制 #include <cstdlib>
#include <string>
using namespace std;
/** 字符串转带符号整数 */
int stoi ( const string & str , size_t* idx = 0 , int base = 10 );
long stol ( const string & str , size_t* idx = 0 , int base = 10 );
long long stoll ( const string & str , size_t* idx = 0 , int base = 10 );
/**
* 1. idx返回字符串中第一个非数字的位置,即数值部分的结束位置
* 2. base为进制
* 3. 该组函数会自动保留负号和自动去掉前导0
*/
/** 字符串转无符号整数 */
unsigned long stoul ( const string & str , size_t* idx = 0 , int base = 10 );
unsigned long long stoull ( const string & str , size_t* idx = 0 , int base = 10 );
/** 字符串转实数 */
float stof ( const string & str , size_t* idx = 0 );
double stod ( const string & str , size_t* idx = 0 );
long double stold ( const string & str , size_t* idx = 0 );
与之类似的在同一个库里的还有一组基于字符数组的函数如下。
复制 // 'a' means array, since it is array-based.
int atoi ( const char* str); // 'i' means int
long atol ( const char* str); // 'l' means long
long long atoll ( const char* str); // 'll' means long long
double atof ( const char* str); // 'f' means double
至此,读者应当详细了解了C++STL中string容器的各种用法以及其他一些字符串处理的常用函数。可能量有些大,无法一下子记住,可以暂时留个印象,待到使用时多翻一翻,慢慢就记住了。