STL:string类使用解析
程序员文章站
2022-03-23 14:58:45
...
目录
string介绍
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,
但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可
能还会越界访问。而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。
sstring并不是一个单独的容器,只是basic_string 模板类的一个typedef 而已,相对应的还有wstring, string 其实相当于一个保存字符的序列容器,因此除了有字符串的一些常用操作以外,还有包含了所有的序列容器的操作
string特点
- string表示字符串的字符串类
- 该类的接口与常规容器接口基本相同,在添加了一些专门用来操作的string常规操作
- string在底层实际是:basic_string模板类的别名
- 不能操作多字节或者变长字符的序列
- 使用string类时,必须包含头文件以及using namespace std
string类的常用接口说明
函数名称 | 功能说明 |
string() | 构造空的string类对象,即空字符串 |
string(const char* s) | 用C-string来构造string类对象 |
string(size_t n, char c) | string类对象中包含n个字符c |
string(const string&s) | 拷贝构造函数 |
string(const string&s, size_t n) | 用s中的前n个字符构造新的string类对象 |
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1;// 构造空的string类对象s1
string s2("hhhhh");// 用C格式字符串构造string类对象s2
string s3(10,'a');// 用10个字符'a'构造string类对象s3
string s4(s2);// 拷贝构造s4
string s5(s3,5);// 用s3中前5个字符构造string对象s5
return 0;
}
string类对象的容量操作
函数名称 | 功能 |
size_t size() const | 返回字符串有效字符长度 |
size_t length() const | 返回字符串有效字符长度 |
size_t capacity ( ) const | 返回空间总大小 |
bool empty ( ) const | 检测字符串是否为空串,是返回true,否则返回false |
void clear() | 清空有效字符 |
void resize ( size_t n, char c ) | 将有效字符的个数改成n个,多出的空间用字符c填充 |
void resize ( size_t n ) | 将有效字符的个数改成n个,多出的空间用\0填充 |
void reserve ( size_t res_arg=0 ) | 为字符串预留空间 |
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s("hello");
s.clear();//将s中的字符串清零,只是将size清零,不是改变底层空间的大小
cout << s.size() << endl;
cout << s.capacity() << endl;
//将s中有效字符增加到10个,用‘a’填充
s.resize(10,'a');
cout << s.size() << endl;
cout << s.capacity() << endl;
//将s有效字符增加到15个,多出位置用‘\0’填补
s.resize(15);
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
//将有效元素缩减至5个
s.resize(5);
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
//测试reserver是否会改变string中的有效元素个数
//不会
s.reserve(100);
cout << s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
// 测试reserve参数小于string的底层空间大小时,是否会将空间缩小
//不会
s.reserve(2);
cout <<"reserve小于size:"<< s.size() << endl;
cout << s.capacity() << endl;
cout << s << endl;
return 0;
}
- size()和length()方法底层实现原理相同,引入size()是为了与其他容器的接口一致,一般都会使用size()
- clear()只是将有效字符清空不改变底层大小
- resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符增多时
resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize
在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空
间总大小不变 - reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
string的底层空间总大小时,reserver不会改变容量大小
string类对象的访问操作
函数名称 | 功能说明 |
char& operator[] ( size_t pos ) | 返回pos位置的字符,const string类对象调用 |
const char& operator[] ( size_t pos ) const | 返回pos位置的字符,非const string类对象调用 |
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类型对象不能修改
string类对象的修改操作
void push_back(char c) | 在字符串后尾插字符c |
string& append (const char* s); | 在字符串后追加一个字符串 |
string& operator+=(const string& str) | 在字符串后追加字符串str |
string& operator+=(const char* s) | 在字符串后追加C字符串 |
string& operator+=(char c) | 在字符串后追加字符c |
const char* c_str( )const | 返回C格式字符串 |
size_t find (char c, size_t pos = 0)const | 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 |
size_t rfind(char c, size_t pos = npos) | 从字符串pos位置开始往前找字符c,返回该字符在 字符串中的位置 |
string substr(size_t pos = 0, size_t n = npos)const |
在str中从pos位置开始,截取n个字符,然后将其 返回 |
string s;
s.push_back(' ');
s.append("hello");
s += 'h';
s += "hh";
cout << s << endl;
cout << s.c_str() << endl; // 以C语言的方式打印字符串
//获取文件后缀
string file("string.cpp");
size_t pos = file.rfind('.');
string suffix(file.substr(pos,file.size()-pos));
cout << suffix << endl;
//npos是string中的一个静态成员变量
//static const size_t npos = -1;
//取出url中的域名
string url("http://www.cplusplus.com/reference/string/string/find/");
cout << url << endl;
size_t start = url.find("://");
if (start == string::npos)
{
cout << "invalid url" << endl;
return 1;
}
start += 3;
size_t finish = url.find('/',start);
string address = url.substr(start, finish - start);
cout << address << endl;
//删除url的协议前缀
pos = url.find("://");
url.erase(0, pos + 3);
cout << url << endl;
//不断增容
string s;
size_t sz = s.capacity();
cout << "making s grow:\n";
for (int i = 0; i < 100; ++i)
{
s += 'c';
if (sz != s.capacity())
{
sz = s.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
/*making s grow :
capacity changed : 31
capacity changed : 47
capacity changed : 70
capacity changed : 105*/
//// 利用reserve提高插入数据的效率,避免增容带来的开销
string s;
s.reserve(100);
size_t sz = s.capacity();
cout << "making s grow:\n";
for (int i = 0; i < 100; ++i)
{
s += 'c';
if (sz != s.capacity())
{
sz = s.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
- 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般
情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串 - 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。
find | 查找 |
rfind | 反向查找 |
find_first_of | 查找包含子串中的任何字符,返回第一个位置 |
find_first_not_of | 查找不包含子串中的任何字符,返回第一个位置 |
find_last_of | 查找包含子串中的任何字符,返回最后一个位置 |
find_last_not_of | 查找不包含子串中的任何字符,返回最后一个位置 |
substr | 得到字串 |
compare | 比较字符串 |
operator+ | 字符串链接 |
operator== | 判断是否相等 |
operator!= | 判断是否不等于 |
operator< | 判断是否小于 |
operator>> | 从输入流中读入字符串 |
operator<< | 字符串写入输出流 |
getline | 从输入流中读入一行 |
#include <string>
#include <iostream>
using namespace std;
int main() {//在strinfo中找到第一个与strset匹配的H,和最有后一个匹配的d,通过substr截选出来
string strinfo = " //*---Hello Word!......------";
string strset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
int first = strinfo.find_first_of(strset);
if (first == string::npos) {
cout << "not find any characters" << endl;
return -1;
}
int last = strinfo.find_last_of(strset);
if (last == string::npos) {
cout << "not find any characters" << endl;
return -1;
}
cout << strinfo.substr(first, last - first + 1) << endl;
return 0;
}
find_first_of
查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。搜索从index开始,如果没找到就返回string::npos
查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。搜索从index开始,最多搜索num个字符。如果没找到就返回string::npos,
查找在字符串中第一个与ch匹配的字符,返回它的位置。搜索从index开始
经典的string类问题
如果string类没有显示的定义拷贝构造函数与赋值运算符重载,此时编译器会默认合成
即用s1构造s2时,编译器回调用默认的拷贝构造,最终导致问题为s1s2共用一块空间
在释放时同一块空间被释放多次而引起程序崩溃,这种拷贝方式被称为浅拷贝。
浅拷贝也称为位拷贝,不会新建立一份,只会导致多个对象共用一个资源,当一个
对象被销毁时,另外一些对象不知道该资源已经被释放,继续操作时,就会发生违规访问
所以拷贝构造函数,赋值运算符重载以及析构函数必须要显示给出,一般都是按照深拷贝
方式提供
上一篇: STL中的string类
下一篇: STL string类的使用
推荐阅读
-
解析Android中string-array数据源的简单使用
-
C#_Excel数据读取与写入_自定义解析封装类_支持设置标题行位置&使用excel表达式收集数据&单元格映射&标题映射&模板文件的参数数据替换(第二版-增加深度读取和更新功能)
-
Java中String类使用方法总结
-
bootstrap搜索建议插件suggest+使用FastJSON进行JSON和String转换解析
-
C++_STL类模板的使用_单个类模板的使用
-
Java 8新日期类LocalDateTime、LocalDate、LocalTime的解析对日期的格式化使用
-
Redis02 使用Redis数据库(String类型)全面解析
-
Java FutureTask类使用案例解析
-
Ruby中的Proc类及Proc的类方法Proc.new的使用解析
-
【转载】C#中string类使用Replace方法来替换字符串