当前位置:首页 » 《休闲阅读》 » 正文

C/C++ string详解

15 人参与  2024年05月26日 16:45  分类 : 《休闲阅读》  评论

点击全文阅读


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://zhangshiyu.com/post/113931.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1