STL-string详解

server/2024/9/20 6:00:59/ 标签: c++, 开发语言

string详解,文章内容值得认真研读;文章值得收藏回头复习;专栏值得订阅;


C++中string是标准库中一种容器,相当于保存元素类型为char的vector容器(自己理解),这个类提供了相当丰富的函数来完成对字符串操作,以及与C风格字符串之间转换,下面是对string一些总结


C语言的字符串及C++string类

在C语言里,对字符串的处理一项都是一件比较痛苦的事情,因为通常在实现字符串的操作的时候都会用到最不容易驾驭的类型——指针。

比如下面这个例子:

//example 1:

char str[12] = "Hello";

char *p = str;

*p = 'h';  //改变第一个字母

//example 2:

char *ptr = "Hello";

*ptr = 'h';  //错误

第一个字符串时用数组开辟的,它是可以改变的变量。而第二个字符串则是一个常量,也就是字面值。ptr只是指向它的指针而已,而不能改变指向的内容。

要想通过指针来改变常量是错误,正确的写法应该是用const指针。

const char *ptr = "Hello";

C++string类

正是因为C风格字符串(以空字符结尾的字符数组)太过复杂难于掌握,不适合大程序的开发,所以C++标准库定义了一种string类,定义在头文件<string>。注意<string.h>和<cstring>都是错误的,这两个头文件主要定义C风格字符串操作的一些方法,譬如strlen(), strcpy()等。第一个是C的头文件格式,而第二个是C++风格的头文件,但是和<string.h>是一样的,它的目的是为了和C兼容。

我们可以来了解C++标准库定义的一系列丰富的字符串操作,当然都是基于string类型。从某一种程度上来说,string就是一种字符容器。

标准库为string定义了很多方法,包括构造、插入(insert)、替换(assign和replace)、比较(compare)、查找(find)、删除(erase)、连接(append)以及对子串的操作(substr)。而每一种操作都有很多种重载。

string是一种非常灵活的字符串类型,标准库让我们可以忽略内存管理和具体实现方式,我们只需要关注其接口就好。并且初学者在使用字符串的时候也应尽量使用这种类型,而不是C风格的字符串。


String详解

首先,为了在我们的程序中使用string类型,我们必须包含头文件 。如下:
   #include //注意这里不是string.h string.h是C字符串头文件

1.声明一个C++字符串


声明一个字符串变量很简单:
   string Str;
这样我们就声明了一个字符串变量,但既然是一个类,就有构造函数和析构函数。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把Str初始化为一个空字符串。String类的构造函数和析构函数如下:
a)    string s;  //生成一个空字符串s
b)    string s(str) //拷贝构造函数 生成str的复制品
c)    string s(str,stridx) //将字符串str内“从stridx开始”的部分当作字符串的初值
d)    string s(str,stridx,strlen) //将字符串str内“从stridx开始且长度为strlen”的部分作为字符串的初值
e)    string s(cstr) //将字符串cstr作为s的初值
f)     string s(chars,chars_len) //将字符串前chars_len个字符作为字符串s的初值。
g)    string s(num,c) //生成一个字符串,包含num个字符c
h)    string s(beg,end) //以区间beg;end(不包含end)内的字符作为字符串s的初值
i)      s.~string() //销毁所有字符,释放内存

2.字符串操作函数


   这里是C++字符串的重点,我先把各种操作函数罗列出来:详细看下方详解
a) =,assign()   //赋以新值
b) swap()   //交换两个字符串的内容
c) +=,append(),push_back() //在尾部添加字符
d) insert() //插入字符
e) erase() //删除字符
f) clear() //删除全部字符
g) replace() //替换字符
h) + //串联字符串
i) ==,!=,<,<=,>,>=,compare()  //比较字符串
j) size(),length()  //返回字符数量
k) max_size() //返回字符的可能最大个数
l) empty()  //判断字符串是否为空
m) capacity() //返回字符容量
n) reserve() //保留一定量内存以容纳一定数量的字符
o) [ ], at() //存取单一字符
p) >>,getline() //从stream读取某值
q) <<  //将谋值写入stream
r) copy() //复制字符
s) c_str() //将内容以C_string返回
t) data() //将内容以字符数组形式返回
u) substr() //返回某个子字符串
v)查找函数
w)begin() end() //提供类似STL的迭代器支持
x) rbegin() rend() //逆向迭代器
y) get_allocator() //返回配置器

2.1 C++字符串和C字符串的转换


   C++提供的由C++字符串得到对应的C_string的方法是使用data()、c_str()和copy(),其中,data()以字符数组的形式返回字符串内容,但并不添加’\0’。c_str()返回一个以‘\0’结尾的字符数组,而copy()则把字符串的内容复制或写入既有的c_string或字符数组内。C++字符串并不以’\0’结尾。我的建议是在程序中能使用C++字符串就使用,除非万不得已不选用c_string。

2.2 大小和容量函数

一个C++字符串存在三种大小:a)现有的字符数,函数是size()和length(),他们等效。Empty()用来检查字符串是否为空。b)max_size() 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。我们一般情况下不用关心他,应该大小足够我们用的。但是不够用的话,会抛出length_error异常c)capacity()重新分配内存之前 string所能包含的最大字符数。这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

2.3元素存取

我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。但是应该注意的是操作符[]并不检查索引是否有效(有效索引0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用at()的时候索引无效,会抛出out_of_range异常。

const string Cstr(“const string”);
string Str(“string”);

Str[3];    //ok
Str.at(3);  //ok

Str[100]; //未定义的行为
Str.at(100);  //throw out_of_range

Str[Str.length()]  //未定义行为
Cstr[Cstr.length()] //返回 ‘\0’
Str.at(Str.length());//throw out_of_range
Cstr.at(Cstr.length()) throw out_of_range

不赞成类似于下面的引用或指针赋值:
char& r=s[2];
char* p= &s[3];
因为一旦发生重新分配,r,p立即失效。避免的方法就是不使用。

2.4比较函数


   C++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<”hello”)。在使用>,>=,<,<=这些操作符的时候是根据“当前字符特性”将字符按字典顺序进行逐一得比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。同时,string(“aaaa”)    另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等 〉0-大于 <0-小于。举例如下:
   string s(“abcd”);
   
   s.compare(“abcd”); //返回0
   s.compare(“dcba”); //返回一个小于0的值
   s.compare(“ab”); //返回大于0的值
   
s.compare(s); //相等
   s.compare(0,2,s,2,2); //用”ab”和”cd”进行比较 小于零
   s.compare(1,2,”bcx”,2); //用”bc”和”bc”比较。

2.5 更改内容

这在字符串的操作中占了很大一部分。
首先讲赋值,第一个赋值方法当然是使用操作符=,新值可以是string(如:s=ns) 、c_string(如:s=”gaint”)甚至单一字符(如:s=’j’)。还可以使用成员函数assign(),这个成员函数可以使你更灵活的对字符串赋值。还是举例说明吧:

这在字符串的操作中占了很大一部分。
首先讲赋值,第一个赋值方法当然是使用操作符=,新值可以是string(如:s=ns) 、c_string(如:s=”gaint”)甚至单一字符(如:s=’j’)。还可以使用成员函数assign(),这个成员函数可以使你更灵活的对字符串赋值。还是举例说明吧:
s.assign(str); //不说
s.assign(str,1,3);//如果str是”iamangel” 就是把”ama”赋给字符串
s.assign(str,2,string::npos);//把字符串str从索引值2开始到结尾赋给s
s.assign(“gaint”); //不说
s.assign(“nico”,5);//把’n’ ‘I’ ‘c’ ‘o’ ‘\0’赋给字符串
s.assign(5,’x’);//把五个x赋给字符串
把字符串清空的方法有三个:s=””;s.clear();s.erase();(我越来越觉得举例比说话让别人容易懂!)。
string提供了很多函数用于插入(insert)、删除(erase)、替换(replace)、增加字符。
先说增加字符(这里说的增加是在尾巴上),函数有 +=、append()、push_back()。举例如下:
s+=str;//加个字符串
s+=”my name is jiayp”;//加个C字符串
s+=’a’;//加个字符

s.append(str);
s.append(str,1,3);//不解释了 同前面的函数参数assign的解释
s.append(str,2,string::npos)//不解释了

s.append(“my name is jiayp”);
s.append(“nico”,5);
s.append(5,’x’);

详细代码可转gitee:STL-string · 文河/CSDN博客专栏 - 码云 - 开源中国 (gitee.com)

string类的构造函数:

string(const chr *s); //用字符串s初始化

string(int n,char c); //用n个字符c初始化

此外,string类还支持默认构造函数河复制构造函数,如string s1;string s2 = "hello";都是正确1的写法,当构造的string太长而无法表达时会抛出length_error异常

string类的字符操作:

const char &operator[](int n) const;

const char &at(int n)const;

char &operator[](int n);

char &at(int n);

operator[]和at()均返回当前字符串中第n个字符的位置,但at()提供范围检查,当越界

时会抛出out_of_range异常,下标运算符[]不提供检查访问

const char *data()const;//返回一个非null终止的c字符数组

const char *c_str()const;//返回一个以null终止的c字符串

int copy(char* s,int n,int pos = 0)const;//把当前串中以pos开始的n个字符拷贝到以s为起始位置的字符串数组中,返回实际拷贝的数目

string的特性描述:

int capacity()const;//返回当前容量(即string中不必增加内存即可存放的元素个数)

int max_size()const;//返回string对象中可存放的最大字符串的长度

int size()const;//返回当前字符串的大小

int length()const;//返回当前字符串的长度

bool empty()const;//返回当前字符串是否为空

void resize(int len,char c);//把字符串当前大小置为len,并用字符串填充不足的部分string类的输入输出操作:

string类重载运算符operator>> //用于输入,同样重载运算符operator<<用于输出操作。

函数getline(istream &in,string &s);//用于从输入流In中读取字符串到s中,以换行符‘\n’分开

string的赋值:

string &operator=(const string &s);//把字符串s赋给当前字符串

string &assign(const char *s);//用c类型字符串s赋值

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中从statr开始的n个字符赋值给当前字符串

string &assign(const_iterator first,const_iterator last);//把first和last迭代器之间的部分赋值给字符串

string的连接:

string &operator+=(const string &s);//把字符串s连接到当前字符串的结尾

string &append(const char *s);//把c类型的字符串s连接到当前字符串的结尾

string &append(const char *s,int n);//把c类型的字符串s前n个字符连接到当前字符串结尾

string &append(const string &s); //同operator+=

string &append(const string &s,int pos,int n);//把字符串s中从pos位开始的n个字符连接到当前字符串的结尾

string &append(int n,char c);//在当前字符串结尾田间n个字符c

string &append(const_iterator first,const_iterator last);//把迭代器first到last之间的部分连接到当前字符串的结尾

strng的比较:

bool perator==(const string &s1,const string &s2)const;//比较s1,s2是否相等,

运算符">","<",">=","<=","!="均被重载用于字符串的比较;

int compare(const string &s)const;//比较当前字符串和s大小

int compare(int pos,int n,const string &s,int pos2,int n2)const;//比较当前字符串从pos开始的n个字符组成的字符串与s中pos2开始的n2个字符组成的字符串大小

int compare(const char *s)const;

int compare(int pos,int n,const char *s)const;

int compare(int pos,int n,const char *S,int pos2)const;

compare函数在>时返回1,<时返回-1,==时返回0

string的子串:

string substr(int pos = 0,int n = npos)const;//返回pos开始的n个字符组成的字符串string:

void swap(string &s2);//交换当前字符串与s2的值

string类的查找函数:

int find(char c,int pos = 0)const;//从pos位开始查找字符c在当前字符串的位置

int find(const char* s,int pos = 0);//从pos开始查找字符串s在当前串中的位置

int find(const char* s,int pos ,int n)const;//从pos开始查找字符串s中前n个字符串在当前字符串中的位置

int find(const string &s,int pos = 0)const;//从pos开始查找字符串s在当前串中的位置

//查找成功返回所在位置,失败返回string::npos的值

int rfind(char c,int pos = npos);//从pos开始从后向前查找字符c在当前串中的位置

int rfind(const char* s,int pos = npos);

int rfind(const char* s,int pos,int n = npos;

int rfind(const string &s,int pos = npos)const;

//从pos位从后往前找,找到返回位置,找不到返回string::npos

int find_first_not_of(char,int pos = 0)const;

int find_first_of(const char* s,int pos = 0)const;

int find_first_of(const char* s,int pos,int n)const;

int find_first_of(const string& s,int pos = 0)const;

//从pos开始查找当前串中第一个在s的前n个字符组成的数组里的字符的位置查找失败返回string::npos

int find_first_not_of(char c,int pos = 0)const;

int find_first_not_of(const char* s,int pos = 0)const;

int find_first_not_of(const char* s,int pos,int n)const;

int find_first_not_of(const string& s,int pos = 0)const;

//从当前串中查找第一个不在串s中的字符出现的位置,失败返回string::npos

int find_last_of(char c,int pos = npos)const;

int find_last_of(const char* s,int pos = npos)const;

...

//find_last_of和find_last_not_of与find_first_of和find_first_not_of相似,只不过是倒着查找,这里不再过多赘述

string类的替换函数:

string &replace(int p0,int n0,const char* s);//删除从p0开始的n0个字符,然后再p0处插入出串s

string &replace(int p0,int n0,const char* s,int n);//删除从p0开始的n0个字符,然后再p0处替换成字符串s的前n个字符

string &replace(int p0,int n0,const string &s);//删除从p0开始到n0个字符然后再p0处插入串s

string &replace(int p0,int n0,const string& s,int pos,int n);//删除从p0开始到n0个字符,然后在p0插入串s从pos位到n个字符

string& replace(int p0,int n0,int n,char c);//删除p0开始的n0个字符,在p0处插入n个字符c

string &replace(iterator first0,iterator last0,cosnt char* s);//把[first0,edn0)之间的部分替换为字符串s

string& replace(iterator first0,iterator last0,const char* s,int n);//把[first0,last0)之间的部分替换为字符串s前n个字符

string& replace(iterator first0,iterator last0,const string& s);//把[first0,end0)之间的部分替换为串s

string& replace(iterator first0,iterator last0,int n,char c);//把[first0,end0)之间的部分替换为c的前n个字符

string& replace(iterator first0,iterator last0,const_iterator first,const_iterator end);//把[first0,last0)之间的部分替换成[first,last)之间的字符串

string类的插入函数:

string& insert(int p0,const char* s);

string& insert(int p0,const char*,int n);

string& insert(int p0,const string& s);

string& insert(int p0,const string& s,int pos,int n);

//在p0位置插入字符串s中pos开始的前n个字符

string& insert(int p0,int n,char c);//在p0处插入n个字符c

iterator insert(iterator it,char c);//在it处插入字符c,返回插入后迭代器的位置

void insert(iterator it, const_iterator first, const_iterator last);//在it处插入[first,last)之间的字符

void insert(iterator it, int n, char c);//在it处插入n个字符c

string类的删除函数

iterator erase(iterator first, iterator last);//删除[first,last)之间的所有字符,返回删除后迭代器的位置

iterator erase(iterator it);//删除it指向的字符,返回删除后迭代器的位置

string &erase(int pos = 0, int n = npos);//删除pos开始的n个字符,返回修改后的字符串


内容转载:C++ string学习 - gaojun - 博客园 (cnblogs.com)


http://www.ppmy.cn/server/41903.html

相关文章

2024年营销技术远景图发布:14,106种营销技术产品(同比增长27.8%)

每年五月的第一个星期二&#xff08;美国东部时间&#xff09;&#xff0c;Scott Brinker设定为Martech Day&#xff0c;以此来庆祝营销技术行业和所有有才华的营销技术专家和营销运营专业人士的工作&#xff0c;「为你们在开拓这片荒野所做的一切而欢呼&#xff01;」 同时&a…

D-Bus(TODO)

写不写看心情了。。。

git常用命令及其ignore文件

1.git本地操作命令 # 查看git的版本 git --version # 生成空的本地仓库 git init # 将文件添加到暂存区 git add 文件 # 将暂存区里的文件提交到本地仓库 git commit -m "描述"2.git远程仓库命令 # 添加远程仓库 git remote add origin http://192.168.1.130:9000/…

Docker快速搭建NAS服务——NextCloud

Docker快速搭建NAS服务——NextCloud 文章目录 前言NextCloud的搭建docker-compose文件编写运行及访问 总结 前言 本文主要讲解如何使用docker在本地快速搭建NAS服务&#xff0c;这里主要写如下两种&#xff1a; FileBrowser1&#xff1a;是一个开源的Web文件管理器&#xff…

JAVA毕业设计138—基于Java+Springboot+Vue的医院预约挂号小程序(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的医院预约挂号小程序(源代码数据库)138 一、系统介绍 本系统前后端分离带小程序和后台 小程序&#xff08;用户端&#xff09;&#xff0c;后台管理系统&a…

十二.吊打面试官系列-JVM优化-深入JVM内存模型

JVM内存模型 1.JVM的组成 整个JVM组成由 &#xff1a;运行时数据区 &#xff0c; 类加载子系统 &#xff0c; 执行引擎 &#xff0c; 本地方法库 几部分组成 上面是Java7的内存模型&#xff0c;Java8以后做了一些调整&#xff0c;把方法区变成了元空间&#xff0c;元空间不在…

领导者十二问答【关心部属、钦佩之意、不败、抱着当老二心情来当老大、用他人的长处、先赞成,后反对】

目录 领导出差不在如何管理&#xff1f; 当合作者做决策时候&#xff0c;没有跟你商量&#xff0c;如何处理&#xff1f; 处理人际关系&#xff0c;比较极端&#xff0c;如何调整&#xff1f; 未来管理的发展方向&#xff1f; 关于信心&#xff1f; 如何制定目标&#xff…

数据结构(二)关于空间的使用

数据结构&#xff08;二&#xff09;关于空间的使用 要点&#xff1a;解决问题的效率跟空间的利用效率有关 思考&#xff1a;如何空间的利用效率 01 如何空间的利用效率 参考&#xff1a;递归导致的栈溢出 Exception in thread "main" java.lang.StackOverflowE…

16:00面试,16:06就出来了,问的问题过于变态了。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

Linux备份---异地

参考文档&#xff1a;Linux环境实现mysql所在服务器定时同步数据文件到备份服务器&#xff08;异地容灾备份场景&#xff09;_mysql异地备份-CSDN博客 通过SSH进行连接&#xff1a; 应用服务器&#xff1a; 通过ssh-keygen -t rsay建立ssh通信的密钥 密钥建立后&#xff0c;…

阿里云 服务之前设置的密钥登陆,关闭了密码登录,现在打开密码登录

通过网页远程链接 切换用户 sudo -i 输入vim /etc/ssh/sshd_config 进入配置文件 找到 将这一项设置为yes 重启系统 systemctl restart sshd.service

某能源集团电力公司搭建数据报表中心,实现采集填报分析一体化

​在当今这个信息爆炸的时代&#xff0c;数据已成为企业最宝贵的财富&#xff0c;越来越多的企业开始重视数据的积累和归集。在企业日常生产和工作过程中&#xff0c;会产生绵延不断的数据&#xff0c;但这些数据往往没有统一的记录、归纳和整理&#xff0c;或者录入了系统却分…

将excel表中的数据导入到navicat中

1.将excel中的表头改成英文 2.在navicat中右键表&#xff0c;选择【导入向导】 3.在弹出的导入向导中选择Excel文件&#xff0c;然后点击【下一步】 4.选择需要导入的excel&#xff0c;选中后&#xff0c;在下方会罗列出excel中的sheet&#xff0c;勾选需要导入的sheet&#xf…

通义千问 1.5 -7B fine-tune验证

尝试对对中文数据进行finetune验证&#xff0c;测试模型的可优化方向。下面是代码的详细情况 代码实现 from datasets import load_dataset from transformers import (AutoModelForCausalLM,AutoTokenizer,BitsAndBytesConfig,HfArgumentParser,AutoTokenizer,TrainingArgum…

以下是服务器的一些主要作用:

2. 数据存储&#xff1a;服务器可以用来存储大量数据&#xff0c;如文件、图片、视频和音频等。此外&#xff0c;服务器还可以存储应用程序和数据库&#xff0c;以支持各种业务需求。

单例模式如何实现?

单例模式是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个唯一实例。在 C 中&#xff0c;可以通过将构造函数设为私有&#xff0c;并提供一个静态方法来获取或创建类的实例来实现单例模式。 下面是一个简单的 C 单例模式的…

东莞酷得电子方案 遥控水弹坦克车

首先遥控小车是一种能够通过无线遥控器进行远程操控的小型机器人。遥控小车应用了哪些软硬件技术呢&#xff1f;本文将从以下几个方面进行详细介绍。 遥控小车应用了多种软硬件技术&#xff0c;涉及底盘结构、动力系统、传感器、控制器等多个方面。 底盘结构&#xff1a;遥控…

深入理解K8S【安全认证机制kubectlconfig】

深入理解K8S【安全认证机制】 1 核心概念 1.1 安全体系 对于大型系统来说&#xff0c;对业务的权限、网络的安全认证是必不可少的。 对于linux系统来说&#xff0c;用户和组、文件权限、SELinux、防火墙、pam、sudo等&#xff0c;究其核心的目的都是为了保证系统是安全的。 …

如何使用Python进行网页爬取

Python爬虫案例可以有很多种&#xff0c;但我会为你提供一个简单的案例&#xff0c;该案例使用Python的requests库来爬取一个网页的内容&#xff0c;并使用BeautifulSoup库来解析HTML并提取特定的信息。 假设我们要从某个新闻网站&#xff08;例如&#xff1a;示例网站&#x…

做抖店的门槛高吗?一个月的时间能入门吗?基础问题解答如下

我是王路飞。 抖店&#xff0c;依旧是普通人做抖音最好的渠道&#xff0c;没有之一&#xff0c;依旧值得我们all in。 这是我对2024年抖音小店的看法和态度&#xff0c; 那么做抖店的门槛高吗&#xff1f;新手用一个月的时间能做到入门吗&#xff1f;投入和回报的数据是多少…