string是C++标准库中表示字符串的字符串类。在之前的笔记中也涉及到过string的应用,我们大概知道string与c风格字符串的区别在于前者不用操心字符串长度的问题,其内部会动态分配需要的内存。其实string 类是 STL(标准模板库)中 basic_string 模板实例化得到的模板类。其定义如下:
typedef basic_string <char> string;
basic_string 此处可以不必深究。string 类的成员函数有很多,同一个名字的函数也常会有五六个重载的版本。篇幅所限,不能将这些原型一一列出并加以解释。这里仅对常用成员函数按功能进行分类,并直接给出应用的例子,通过例子,读者可以基本掌握这些成员函数的用法。
注意,使用string类的时候,必须包含头文件string(不是cstring或string.h)以及using namespace std。
一、构造函数
string类的构造函数如下:
string():构造空的string类对象,既空字符串
string(const char* s):使用C语言的字符串构造string类对象
string(size_t n,char c):构造后的string类对象包括n个字符c
string(const string& s):用string类对象s拷贝构造另一个对象
string(const string& s, size_t pos, size_t n):使用对象s中从pos开始的第n个字符开始构造新的string类对象
string s1; // 构造空的string类对象s1,si = "" string s2("hello,world"); //使用C字符串构造,s2 = " hello,world " string s3(10, 'a'); // 10个a构造对象,s3 = "aaaaaaaaaa" string s4(s2); //拷贝构造,s4=”hello,world” string s5(s2, 6, 5);//从s2对象下标为的位置开始,将个字符复制到s5中,s5=”world” |
二、容量操作
size_t size() const:返回字符串有效字符长度,size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
size_t length() const:返回字符串有效的长度(同size)。
size_t capacity() const:返回空间总大小,既容量。通常,开辟的容量会比实际的大小大,且为2的整倍数。
bool empty() const:判断字符串是否为空串,是返回true,不是返回false
void clear():清空有效的字符,不改变底层空间大小。
void resize(size_t n,char c):将有效字符的个数改成n个,多出来的空间用c填充,resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
void reserve(size_t res_arg = 0):修改string类的容量,为字符串预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserve不会改变容量大小。
string s("hello,world"); cout << s.length() << endl; // 11 cout << s.size() << endl; // 11 cout << s.capacity() << endl;// 15 ,capacity是但是实际上开辟了个char的空间,最后还有`\0` cout << s << endl;//string类对象支持直接用cin和cout进行输入输出
//将对象s中的字符串清空,只改变有效数据的大小,不改变容量的大小 s.clear(); cout << s.size() << endl; // 0 cout << s.capacity() << endl; // 15
// 将s中有效字符个数增加到个,多出位置用'j'进行填充 s.resize(10, 'j'); cout << s.size() << endl; // 10 cout << s.capacity() << endl; // 15 cout << s << endl; // jjjjjjjjjj
//将s中有效字符个数增加到个,多出位置用缺省值'\0'进行填充 s.resize(15); cout << s.size() << endl; // 15 cout << s.capacity() << endl; // 15 cout << s << endl; // jjjjjjjjjj\0\0\0\0\0
//将s中有效字符个数缩小到个 s.resize(5); cout << s.size() << endl; // 5 cout << s.capacity() << endl; // 15 cout << s << endl; // jjjjj cout << "--------------" << endl;
//测试reserve string s2("hehe");//reserve不会改变string中有效元素个数 cout << s2.size() << endl;//4 cout << s2.capacity() << endl;//15 s2.reserve(100); cout << s2.size() << endl;//4 cout << s2.capacity() << endl;//111 //当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小 s2.reserve(50); cout << s2.size() << endl; // 4 cout << s2.capacity() << endl; // 111 |
三、访问操作
1. string类重载了[]符号获取指定元素:
char& operator[] (size_t pos):返回pos位置的字符,也可以修改
const char& operator[] (size_t pos):返回pos位置字符,只能访问不能修改
2.const char* c_str() const返回C格式的字符串,既char*
string filename; cin >> filename; ofstream fout; fout.open(filename.c_str()); |
3.substr 成员函数可以用于求子串 (n, m),原型如下:
tring substr(int n = 0, int m = string::npos) const;
调用时,如果省略 m 或 m 超过了字符串的长度,则求出来的子串就是从下标 n 开始一直到字符串结束的部分。例如:
string s1 = "this is ok"; string s2 = s1.substr(2, 4); // s2 = "is i" s2 = s1.substr(2); // s2 = "is is ok" |
四、字符串连接
常见的字符串修改主要有以下接口函数:
void push_back(char c):在字符串尾插入字符c
string& append(const char* s):在字符串后边追加一个C语言字符串
string& operator+=(const string& str):在字符串后边追加string类字符串
string& operator+=(const char* s):在字符串后边追加C语言字符串
string& operator+=(char c):在字符串后追加字符c
注意:在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
除了可以使用append和+=运算符对string对象执行字符串的连接操作外,string 类还重载了+运算符,可以用来向字符串后面添加内容。
对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好,这样可以减少调用扩容函数增加的额外开销。
string str("hello"); str.push_back('C');//在str后边追加字符C cout << str << endl; str.append(" world");//在str后边追加字符串 cout << str << endl; str += 'X'; //str后边追加字符X cout << str << endl; str += "xxx";//str后边追加字符串xxx cout << str << endl; cout << str.c_str() << endl;//以C语言形式打印字符串 |
五、字符串比较
String类重载了<、<=、==、!=、>=、> 运算符比较 string 对象,同时,string 类还有 compare 成员函数,可用于比较字符串。compare 成员函数有以下返回值:
-
小于 0 表示当前的字符串小;
-
等于 0 表示两个字符串相等;
-
大于 0 表示另一个字符串小。
string s1("hello"), s2("hello, world"); int n = s1.compare(s2); n = s1.compare(1, 2, s2, 0, 3); //比较s1的子串(1,2) 和s2的子串(0,3) n = s1.compare(0, 2, s2); // 比较s1的子串(0,2) 和s2 n = s1.compare("Hello"); n = s1.compare(1, 2, "Hello"); //比较s1 的子串(1,2)和"Hello” n = s1.compare(1, 2, "Hello", 1, 2); //比较s1 的子串(1,2)和"Hello" 的子串(1,2) |
六、交换字符串
swap 成员函数可以交换两个 string 对象的内容。例如:
string s1("West"),s2("East"); s1.swap(s2); // s1 = "East",s2 = "West" |
七、查找字符或子串
string 类有一些查找子串和字符的成员函数,它们的返回值都是子串或字符在 string 对象字符串中的位置(即下标)。如果查不到,则返回 string::npos。string: :npos 是在 string 类中定义的一个静态常量。这些函数如下:
find:从前往后查找子串或字符出现的位置。
rfind:从后往前查找子串或字符出现的位置。
find_first_of:从前往后查找何处出现另一个字符串中包含的字符。例如:s1.find_first_of("abc"); //查找s1中第一次出现"abc"中任一字符的位置
find_last_of:从后往前查找何处出现另一个字符串中包含的字符。
find_first_not_of:从前往后查找何处出现另一个字符串中没有包含的字符。
find_last_not_of:从后往前查找何处出现另一个字符串中没有包含的字符。
string s1("Source Code"); int n; if ((n = s1.find('u')) != string::npos) //查找u 出现的位置 cout << "1) " << n << "," << s1.substr(n) << endl; //输出l)2,urce Code if ((n = s1.find("Source", 3)) == string::npos) //从下标开始查找"Source",找不到 cout << "2) " << "Not Found" << endl; //输出2) Not Found if ((n = s1.find("Co")) != string::npos) //查找子串"Co"。能找到,返回"Co"的位置 cout << "3) " << n << ", " << s1.substr(n) << endl; //输出3) 7, Code if ((n = s1.find_first_of("ceo")) != string::npos) //查找第一次出现或'c'、'e'或'o'的位置 cout << "4) " << n << ", " << s1.substr(n) << endl; //输出4) l, ource Code if ((n = s1.find_last_of('e')) != string::npos) //查找最后一个'e' 的位置 cout << "5) " << n << ", " << s1.substr(n) << endl; //输出5) 10, e if ((n = s1.find_first_not_of("eou", 1)) != string::npos) //从下标开始查找第一次出现非'e'、'o' 或'u' 字符的位置 cout << "6) " << n << ", " << s1.substr(n) << endl; //输出6) 3, rce Code |
八、替换字符
replace 成员函数可以对 string 对象中的子串进行替换,返回值为对象自身的引用。例如:
string s1("Real Steel"); s1.replace(1, 3, "123456", 2, 4); //用"123456" 的子串(2,4) 替换s1 的子串(1,3) cout << s1 << endl; //输出R3456 Steel string s2("Harry Potter"); s2.replace(2, 3, 5, '0'); //用5 个'0' 替换子串(2,3) cout << s2 << endl; //输出HaOOOOO Potter int n = s2.find("OOOOO"); //查找子串"00000" 的位置,n=2 s2.replace(n, 5, "XXX"); //将子串(n,5)替换为"XXX" cout << s2 < < endl; //输出HaXXX Potter |
十、删除子串
erase 成员函数可以删除 string 对象中的子串,返回值为对象自身的引用。例如:
string s1("Real Steel"); s1.erase(1, 3); //删除子串(1, 3),此后s1 = "R Steel" s1.erase(5); //删除下标及其后面的所有字符,此后s1 = "R Ste" |
十一、插入字符串
insert 成员函数可以在 string 对象中插入另一个字符串,返回值为对象自身的引用。例如:
string s1("Limitless"), s2("00"); s1.insert(2, "123"); //在下标2 处插入字符串"123",s1 = "Li123mitless" s1.insert(3, s2); //在下标2 处插入s2 , s1 = "Li10023mitless" s1.insert(3, 5, 'X'); //在下标3 处插入5 个'X',s1 = "Li1XXXXX0023mitless" |