String类
在C语言中,我们对于对于字符数组的认识,仅仅局限于字符串,我们对于该数组进行一些操作的时候,往往要配合str系列的库函数来使用,但是这些库函数比较繁琐,底层空间需要用户来维护,有可能会在操作中越界访问。
C++中提供了string类,来完善对于字符串的使用和处理
总结:
- string类型是表示字符串的字符串类
- 该类的接口与常规的容器的接口基本相同,再向其中添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
- 不能操作多字节或者变长字符的序列。
String的用法
我们对于String的使用从string的构造开始
string类对象的构造方法
四种构造方法:
1. string( ) 空参构造,得到一个空的字符串类型
2.string(const char* s) 使用C-string来构造string类对象,即传参一个字符串"xxx"
3.string(size_t n ,char c) 表示得到一个n个c字符的字符串
4.string(const string& s) 表示通过拷贝构造函数来得到新的string对象
下面是代码演示:
int main()
{
string s1; //得到空字符串
string s2("hello world!!!"); //字符串内容为hello world!!!\0
string s3(s2); //拷贝构造函数,数值一样,地址不同
string s4(10,'c');//十个字符为c的连起来的字符串
return 0;
}
string类的容量操作
函数名称 | 功能说明 |
---|---|
size | 返回字符串有效字符长度 |
length | 返回字符串有效字符长度 |
capacity | 返回空间总大小 |
empty | 检测字符串是否为空串,如果为空,返回true,反之返回false |
clear | 清空字符串 |
reserve | 扩容,为字符串预留足够的空间 |
resize | 设置有效字符的个数,多出来的空间用‘\0’来代替 |
代码演示
size和length的区别
size()和length()方法底层实现的原理是一样的,只是为了与其他STL容器接口保持一致,才又加入了size(),以后一般情况下,直接使用size()即可
#include<iostream>
#include<string>
using namespace std; //需要导入这些头文件以及展开std命名空间,下文不再一一写入代码段
void test11()
{
string s("hello world");
cout << s.size() << endl; //11
cout << s.length() << endl;//11
}
int main()
{
test11();
return 0;
}
capacity的使用
capacity在不同的环境下的初始化的数值是不同的,在VS下我们根据下面代码可知,初始值为15,后序大概为1.5倍扩容,在Linux下初始值从0开始,。后序大概为2倍扩容。
void test12()
{
//测试capacity
String::string s;
int num = s.capacity();
cout << num << endl;
for (int i = 0; i < 100; i++)
{
s += i;
if (num != s.capacity())
{
cout << "capacity改为:" << s.capacity() << endl;
}
num = s.capacity();
}
}
int main()
{
test12();
return 0;
}
empty和clear的使用
empty是用来判断当前字符串是否为空值(空串),真返回1,假返回0
clear用来清理字符串内容的,实际上是通过'\0'来实现的,会改变size的数值为0,capacity不会改变
void test13()
{
string s("hello world");
//检验empty的使用
cout << s.empty() << endl;
s.clear(); //当清空clear字符串s之后,再通过empty判空
cout << s.empty() << endl;
//empty返回为0表示假,返回为1表示真
//判断clear之后是否size以及capacity发生改变
string s1("hello world");
cout << "当前capacity为:"<<s1.capacity() << endl;
cout << "当前size为:" <<s1.size() << endl;
//清理clear
s1.clear();
cout << "当前capacity为:" << s1.capacity() << endl;
cout << "当前size为:" << s1.size() << endl;
}
int main()
{
test13();
return 0;
}
reserve和resize的使用
reserve是用来扩容更改capacity的,reserve在VS中只能向上扩容,不能缩容(减小),且不会改变size的大小
resize是用来改变字符串长度大小的,不管如何要满足size<=capacity,所以resize底层会在更改size大小前调用reserve来判断此时是否需要扩容,所以可能会影响capacity的大小
//capacity的大小只能是在15 31 ...这样的取值,保证大概1.5倍扩容,向上扩容
void test14()
{
string s("hello world");
cout << "原始数值" << endl;
cout << "当前capacity为:" << s.capacity() << endl;
cout << "当前size为:" << s.size() << endl;
//验证reserve和resize
s.reserve(20);
cout << "使用reserve扩容后:" << endl;
cout << "当前capacity为:" << s.capacity() << endl;
cout << "当前size为:" << s.size() << endl;
s.resize(20);
cout << "使用resize更改size后:" << endl;
cout << "当前capacity为:" << s.capacity() << endl;
cout << "当前size为:" << s.size() << endl;
cout << endl;
//如果此时我们通过reserve缩容(减小当前容量)
s.reserve(10000);
cout << "缩容为10:结果如下" << endl;
cout << "当前capacity为:" << s.capacity() << endl;
cout << "当前size为:" << s.size() << endl;
//那么我们继续缩小size
s.resize(100);
cout << "缩小size为5:结果如下" << endl;
cout << "当前capacity为:" << s.capacity() << endl;
cout << "当前size为:" << s.size() << endl;
}
int main()
{
test14();
return 0;
}
shrink_to_fit()
一般capacity扩容之后,不会再缩容,但是通过shrink_to_fit将容器的内部存储空间缩小到恰好容纳当前元素数量,以节省不必要的内存空间
shrink_to_fit使得capacity==size
总结
- size()与length()底层实现是一样的,是因为为了与STL其他容器兼容,所以增加了size()的使用,以后一般使用size()
- clear()只是将string中有效字符清空,不会改变底层空间的大小
- resize(size_t n) 和resize(size_t n , char c) 都是可以改变size,只是对于多余的空间,前者默认用‘\0’来填充,后者用指定字符c来填充,其他是一致的。
- resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。也就是size<=capacity
- reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
string类对象的访问
我们有四种方法来对于string对象进行访问
函数名称 | 功能说明 |
---|---|
operator[ ] | 返回指定位置的字符,const string类对象调用 |
begin + end | begin( )获取string对象的首元素的迭代器+end( )获得最后一个字符的下一个位置的迭代器 |
rbegin+rend | rbegin得到最后一个字符的迭代器+rend得到string对象第一个字符的上一个位置的迭代器 |
范围for(增强for) | 是C++11支持的for循环遍历方式,本质是调用迭代器 |
void test15()
{
string s("hello world");
//1.operator[] 访问,可以赋值 和数组一样
cout << s[0] << endl;
//2.begin 和 end 的使用 迭代器类似于指针的使用
string::iterator it = s.begin();
//auto it =s.begin(); 可以用auto智能指针接收
while(it!=s.end())
{
cout << *it << "";
++it;
}
cout << endl;
//3.rbegin和end的使用,就是反向遍历
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit << "";
++rit; //反向遍历也是要++rit迭代器
}
cout << endl;
//4.范围for
for (auto ch : s)
{
cout << ch << ""; //范围for只能正向遍历
}
cout << endl;
}
int main()
{
test15();
return 0;
}
注意:反向迭代器和正向迭代器的rit/it都是++
string类对象的修改操作
函数名称 | 功能说明 |
---|---|
push_back | 在字符串后尾插字符c |
append | 在字符串后追加一个字符串str |
operator+= | 在字符串后追加字符串str |
c_str | 返回C格式的字符串,也就是const char* (char指针) |
find+npos | 从字符串pos位置开始向后找字符c,返回该字符在字符串中的位置 |
rfind | 从字符串pos位置开始向前找字符c,返回该字符在字符串中的位置 |
substr | 在str中从pos位置开始,截取n个字符,然后将其返回 |
insert | 在pos指定位置插入字符串str,很多insert用法,常用的如下。 |
earse | 在pos位置开始,删除n个字符 |
函数的使用
push_back和append以及operator+=
都是在string类对象尾部,添加字符或者字符串,push_back添加字符C,append以及operator+=添加字符串
void test16()
{
string s;//空串
//push_back的使用
s.push_back('1');
s.push_back('2');
s.push_back('3');
s.push_back('4');
s.push_back('5');
for (auto ch : s)
{
cout << ch << " ";
}
cout << endl;
//append
s.append("hello world");
for (auto ch : s)
{
cout << ch << " ";
}
cout << endl;
//3.operator+=
s += "abcdefg";
for (auto ch : s)
{
cout << ch << " ";
}
}
int main()
{
test16();
return 0;
}
c_str的使用
c_str实际上就是将c++的string类型与C语言中的char* 兼容,因为在C语言中char* 字符数组表示的就是字符串。所以c_str返回的就是C语言中的const char* 类型
void test17()
{
//const char* c_str() const;
string s("hello world");
cout << s.c_str() << endl;//c_str主要就是兼容C语言 返回的是const char*字符指针类型
}
int main()
{
test17();
return 0;
}
find和rfind的使用
find正向查找,rfind逆向查找,都可以指定pos位置作为起点,向后,向前查找指定字符C或者字符串,找到便返回下标位置,找不到返回的是npos也就是-1
void test18()
{
string s("hello world");
int pos = s.find('h'); //如果找不到返回的是npos 也就是-1
cout << pos << endl;
pos = s.find('l', 0);
cout << pos << endl;
pos = s.find('l', 6);
cout << pos << endl;
pos = s.find("hello");
cout << pos << endl;
//rfind的使用,就是从后向前开始查找
string s1("123456 123456");
pos = s1.rfind("123456"); //7
cout << pos << endl;
pos = s1.rfind('1'); //7
cout << pos << endl;
pos = s1.rfind('1',5); //0
cout << pos << endl;
}
int main()
{
test18();
return 0;
}
substr的使用
两个参数,表示起始位置和截止位置,前闭后开 [) 截止位置为缺省参数赋值npos
1. s.substr(5) 表示从下标为5的位置开始截取到字符串s的末尾
2. s.substr(0,5) 表示截取[0,5)的s字符串
void test19()
{
//string substr (size_t pos = 0, size_t len = npos) const;
string s("hello world");
cout << s << endl;
s.substr(5); //在1str中从pos位置开始,截取n个字符,然后将其返回
cout << s.substr(5) << endl;
cout << s.substr(0, 5) << endl;
}
int main()
{
test19();
return 0;
}
insert的用法
insert有很多种方法,但是常用的就那些,比如在pos位置上插入字符串str,在pos位置上插入字符串str并指定该插入该字符串的元素个数,在pos位置上插入字符串str并指定从该字符串的subpos位置开始插入sublen字符,或者是
常用四种用法
string& insert (size_t pos, const char* s); 在pos位置上插入字符串str
string& insert (size_t pos, const char* s, size_t n); 在pos位置上插入字符串str并指定该插入该字符串的字符个数
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
在pos位置上插入字符串str并指定从该字符串的subpos位置开始插入sublen字符
string& insert (size_t pos, size_t n, char c); 在pos位置上插入n个字符c
void test21()
{
string s("hello world");
//string& insert (size_t pos, const char* s);
//表示在pos位置上插入字符数组s
s.insert(1, "123");
cout << s << endl;
//string& insert (size_t pos, const char* s, size_t n);
//表示在pos位置上插入s字符数组的前n个字符
s.insert(1, "123456",10); //如果n超过原有数组的长度,将多出来的字符位置填充'\0',相当于将这个"123456"字符串扩容为"123456\0\0\0\0" 然后插入到s对象pos位置
cout << s.size() << endl;
// string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
s.clear();
cout << s << endl;
s.insert(0, "123456"); //如果插入数值pos的位置越界,那么就会报错
cout << s.size() << endl;
cout << s << endl;
//string& insert (size_t pos, size_t n, char c);
//表示在pos位置上,插入n个字符c
s.insert(0, 10, 'c');
cout << s << endl;
}
int main()
{
test21();
return 0;
}
earse的使用
string& erase (size_t pos = 0, size_t len = npos); 从pos位置删除len个字符,len默认npos,即删除pos位置之后所有元素
iterator erase(iterator p); 删除指定迭代器位置的字符
iterator erase (iterator first, iterator last); 删除在[first,last) 之间的字符
void test22()
{
//1. string& erase (size_t pos = 0, size_t len = npos);
string s("hello world");
cout << s << endl;
s.erase(0, 6);
cout << s << endl;
//2. iterator erase(iterator p);
s.erase(s.begin() + 3); //删除该迭代器位置的元素
cout << s << endl;
//3. iterator erase (iterator first, iterator last);
s.erase(s.begin() + 1, s.end());
cout << s << endl;
}
int main()
{
test22();
return 0;
}
pop_back
作用为删除字符串的最后一个字符
replace的用法
replace就是对于指定区间的字符进行替换,替换为另一个字符串的内容,参数多样,顺序一般为pos,len,str,subpos,sublen,分别表示replace的字符串的指定下标,长度,要替换为的字符串str,str开始的位置,截取str的长度
主要理解就是,replace替换,需要指定空间,然后替换为str字符串形式,至于替换str字符串的那一部分,由subpos和sublen决定,从左到右,最少三个参数 pos len str。
可以由迭代器来表示范围(pos和len)如:string& replace (iterator i1, iterator i2, const char* s, size_t n);最后参数n表示替换s字符数组的个数
void test23()
{
string s("hello world");
//string& replace (size_t pos, size_t len, const string& str);
cout << s << endl;//hello world
s.replace(0, 2, "123456");//将pos位置向后的len个字符,替换成str字符串 //123456llo world
cout << s << endl;
//string& replace (iterator i1, iterator i2, const string& str);
//可以使用迭代器,也能实现
string s1("hello world");
cout << s1 << endl;
s1.replace(s1.begin(), s1.begin() + 2, "123456"); //123456llo world
cout << s1 << endl;
//string& replace (size_t pos, size_t len, const string& str,size_t subpos, size_t sublen);
//就是将pos位置向后的len个字符,替换成从subpos位置上长度为sublen的str字符串的字符内容
//相当于substr之后的字符串替换pos的len个字符
string s2("hello world");
cout << s2 << endl;//hello world
s2.replace(0,2,"123456",0,2); //12llo world
cout << s2 << endl;
//string& replace (size_t pos, size_t len, const char* s, size_t n);
//在pos位置长度为len个字符,替换为s字符数组的前n个字符
string s3("hello world");
cout << s3 << endl;//hello world
s3.replace(0, 2, "123456",2); //12llo world
cout << s3 << endl;
}
int main()
{
test23();
return 0;
}
string类对象非成员函数
operator+、operator>>、operator<<、getline、relational operators的使用
operator+ 少用,因为传值返回,导致深拷贝效率低
operator>>、operator<< 分别表示输入运算符重载和输出运算符重载
getline 获取一行字符串,用法为:getline(cin,s) 输入的字符串放在s内
relational operators 即比较大小,字符串可以比较大小,是根据每一字符的Ascil码值
文章来源:https://www.toymoban.com/news/detail-603549.html
int main()
{
string s;
cin>>s; //这样读取字符串,读取到' '的时候就会截止
getline(cin,s); //这样除非遇到'\n' 反之不会停止读取,遇到' '也会继续读取,所以可以读取一行
cout<<s<<endl;
return 0;
}
总结文章来源地址https://www.toymoban.com/news/detail-603549.html
- string类是对应C语言中的char* 字符数组,C++中为了操作方便,提供的字符串类
- string的各种函数的用法,只需要去记住常用的一些即可。比如:append、push_back、+=、find、substr、reserve、resize、empty 、clear、c_str、insert、erase等
- 只要是涉及到范围的函数,都是前闭后开,熟练掌握string的使用即可,其扩容机制与版本环境有关。
到了这里,关于C++中string类用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!