前言
记录一些对字符串的理解。
接下来我所说的都是依赖于头文件<string>
的。
理论
什么是字符串
字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
string与cstring有什么区别
<string>
是C++标准库头文件,包含了拟容器class std::string
的声明(不过class string
事实上只是basic_string<char>
的typedef
),用于字符串操作。
<cstring>
是C标准库头文件<string.h>
的C++标准库版本,包含了C风格字符串(NULL即'\0'结尾字符串)相关的一些类型和函数的声明,例如strcmp、strchr、strstr等。
两者最大区别在于:
-
string
是新标准,定义了namespace std;
而cstring
定义中包含的是string.h
。 -
string
中可以进行+ = += >
等运算,而cstring
中不能进行相关运算。
什么是string类型的迭代器
声明一个string
类中特有的类型size_type
变量,名称为position
。
string::size_type position;
迭代器是一个变量,相当于容器和操纵容器的算法之间的中介 , 实在理解困难认为是个特别的int下标也可以。
迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。
//从类名获取该对象
string::npos;//从对象获取该对象
string tempstr;
tempstr.npos;
这个npos
是个特别的迭代器对象,可以理解成为string
类型中特别的NULL,如果查找失败或者遍历完毕之后迭代器的值就是这个.
操作
首先引入头文件,并且在命名空间中使用。
#include<string>
using namespace std;
Strings常用方法
方法名 | 作用 |
---|---|
Operators | 操作符,可以用 ==, >, <, >=, <=, and !=比较字符串. 可以用 + 或者 += 操作符连接两个字符串, 并且可以用[]获取特定的字符 |
append() | 在字符串的末尾添加文本(就是+=) |
compare() | 比较两个字符串 |
empty() | 如果字符串为空,返回真 |
erase() | 删除字符 |
insert() | 插入字符 |
length() | 返回字符串的长度 |
replace() | 替换字符 |
size() | 返回字符串中字符的数量(结果等价于length) |
substr() | 返回某个子字符串 |
swap() | 交换两个字符串的内容 |
如果可以使用自带的方法去实现的话自然是比较好的,但是如果只能够针对部分字符进行复杂变化的话,就需要转化成为char*类型的数组
。
构造法
平常更多是用等号直接赋值,如果要求字符串中间有结尾符可以这样声明。
void stringTestConstruct() {string str =string("12345 \0 54321", 13);//不等价于str="12345 \0 54321";cout << str<<endl;string str1 = "12345 \0 54321";cout << str1;
}
image-20221108134445583
image-20221108132722476
append
void stringTestAppend() {string str = "Hello";str.append(3, '!');//等价于str+="!!!" ;cout << str;
}
image-20201126161713323
初学时,没考虑太多,后来才发现在添加'\0'
字符时有奇效。
void stringTestAppend2() {string str="abc";str.append("\0 def",5);//等价于 str =string("abc\0 def", 8);cout << str;
}
image-20221108135309114
compare
compare()比较时逐字符比较的,一旦能比较出结果,就不再比较了。
虽然有多个重载,但是只需要理解,在this字符串与传入的比较字符串str一部分(至于是哪一部分用起点和长度来评定)之间进行的比较即可。
int compare( const basic_string &str );int compare( const char *str );int compare( size_type index, size_type length, const basic_string &str );int compare( size_type index, size_type length, const basic_string &str, size_type index2,size_type length2 );int compare( size_type index, size_type length, const char *str, size_type length2 );
在str之前的参数是修饰this,在str之后的参数是修饰str的
返回值 | 情况 |
---|---|
小于零 | this < str(自己弱小就认''负'') |
零 | this == str |
大于零 | this > str(自己强大就嚣''正'') |
void stringTestCompare() {string s1 = "abandon";string s2 = "about";int b = s1.compare(s2);//直接比较,s1小于s2,故返回-1int c = s1.compare(2, 4, s2);//s1下标为2的字符a开始的4个字符ando和s2进行比较。ando大于s2故返回1cout << c << endl;int d = s1.compare(2, 4, s2, 1, 3);cout << d << endl;//s1下标为2的字符a开始的4个字符ando和s2下标为1的字符b开始的3个字符bou比较。前者小,故返回-1。string s3 = "abc";string s4 = "abc";int e = s3.compare(s4);//相等返回0cout << e << endl;
}
erase
也有参数为迭代器的函数,在下面介绍。
basic_string &erase( size_type index = 0, size_type num = npos );
-
删除从index索引开始的num个字符, 返回删减后的字符串。其中index默认从0开始,num默认是最大值。
void stringTestErase() {string s("1234567890123456789012345");//总共25个字符cout << s << endl;cout << s.erase(10, 6) << endl;//从下标第10的字符开始删除,一共删除6个。cout << s.erase(10) << endl;//删除下标为10的字符及之后的 ==保留下标小于10的字符cout << s.erase();//清空字符串
}
image-20201126200020627
insert
basic_string &insert( size_type index, const basic_string &str );basic_string &insert( size_type index, const char *str );basic_string &insert( size_type index1, const basic_string &str, size_type index2, size_type num);basic_string &insert( size_type index, const char *str, size_type num );basic_string &insert( size_type index, size_type num, char ch );
-
在字符串的位置index插入字符串str;
-
在字符串的位置index插入字符串str的子串(从index2开始,长num个字符);
-
在字符串的位置index插入字符串str的num个字符;
-
在字符串的位置index插入num个字符ch的拷贝字符串。
其实理解起来就是,在本字符串的index位置,插入参数中的字符串的一部分(至于是哪一部分
用起点和长度来评定)。
void stringTestInsert() {string str = "abc";str.insert(1, "123");/*在下标为1的位置,插入字符串123全部*/cout << str << endl;str = "abc";str.insert(1, "123", 1, 1);/*在下标为1的位置,插入字符串123的一部分,并且从下标1开始,长度为1的一段*/cout << str << endl;str = "abc";str.insert(1, "123", 2);/*在下标为1的位置,插入字符串123的一部分,并且从下标0开始,长度为2的一段*/cout << str << endl;str = "abc";str.insert(1, 2, 'z');/*在下标为1的位置,插入2个字符z*/cout << str;
}
image-20221108141757159
length
其实不用纠结在获取长度的时候是用size
还是length
,至少在GCC6的情况下,返回的都是同一个字段_M_string_length
。
void stringTestLength() {//其实后面都是返回的同一个字段_M_string_length。string s("1234567890123456789012345");//总共25个字符cout << s.size() << endl;//输出25cout << s.length() << endl;//输出25
}
replace
basic_string &replace( size_type index, size_type num, const basic_string &str );
basic_string &replace( size_type index1, size_type num1, const basic_string &str, size_type index2,size_type num2 );
basic_string &replace( size_type index, size_type num, const char *str );
basic_string &replace( size_type index, size_type num1, const char *str, size_type num2);
basic_string &replace( size_type index, size_type num1, size_type num2, char ch );
其实理解起来就是,在将本字符串的index位置长度为num的字符串,替换成参数中的字符串的一部分(至于是哪一部分用起点和长度来评定)。
一般用起来的时候,更多是和find函数一起,实现查找替换的作用。然而find函数是涉及到了迭代器,所以这里只是简单示例一下。有兴趣可以直接下翻。
void stringTestReplace() {string str="1234567890";str.replace(0,9,"ABC");/*把下标从0开始、长度为2的一段字符串,替换为ABC*/cout << str<<endl;str="1234567890";str.replace(str.find('8'),3,"ABC");/*把从字符8开始、长度为2的一段字符串,替换为ABC*/cout << str;
}
substr
basic_string substr( size_type index, size_type num = npos );
截取本字符串从index开始之后的num个字符,没错就是跟上面的删除差不多!
特别的,用程序形象的看一眼效果:
void stringTestSubstr() {string s("123456789012345678901234567890");cout << s << endl;printf("%30s\n", s.substr(21).c_str());cout << s.erase(21) << endl;
}
image-20201126222643653
swap
void swap( basic_string &str );
这个函数的作用主要就是将两个字符串的全部元素进行交换。
void stringTestSwap() {string first( "This comes first" );string second( "And this is second" );first.swap( second );cout << first << endl;cout << second << endl;
}
image-20201126222955616
如果只是针对部分元素,可以用insert
和replace
进行操作。
转char*
方法名 | 作用 |
---|---|
c_str() | 将字符串以C字符数组的形式返回 |
copy(*str, num, index ) | 将内容复制为一个字符数组 |
data() | 返回内容的字符数组形式 |
c_str( )
const char *c_str();
返回一个const临时指针,指向以\0
结尾的字符数组,应该使用strcpy()
函数等来操作。
void stringTestC_str() {//数组char c[20];string s="1234";strcpy(c,s.c_str());//注意strcpy函数是在cstring头文件中的cout<<c;//指针string str = "hello";const char* p1 = str.c_str();//加constchar * p2=(char*)str.c_str();//或者是强制转换
}
data( )
const char *data();
照常来说是字符串内容外,**不附加结束字符'\0'
**。
有资料显示,两者是应该有区别的,c_str()
有结束符,而data()
没有结束符。
image-20201126172130028
因为我这个编译环境的问题,在dev的环境中两个方法,其实都是返回的_M_data()
方法而已的。
copy(*str,num,index )
拷贝自己的num个字符到str中(从索引index开始)。返回值是拷贝的字符个数
size_type copy( char *str, size_type num, size_type index );
由于还需要手动加结束符。
void stringTestCopy() {string str = "hmmm";char p[10];str.copy(p, 3, 0);/*把从0开始、长度为3的字符串,复制到字符数组p之中*/p[3] = '\0';//注意手动加结束符!!!cout << p;
}
迭代器
方法名 | 作用 |
---|---|
begin() | 返回一个迭代器,指向第一个字符 |
end() | 返回一个迭代器,指向字符串的末尾。(最后一个字符的下一个位置) |
erase() | 删除字符 |
find() | 在字符串中查找字符 |
find_first_of() | 查找第一个与value中的某值相等的字符 |
find_first_not_of() | 查找第一个与value中的所有值都不相等的字符 |
find_last_of() | 查找最后一个与value中的某值相等的字符 |
find_last_not_of() | 查找最后一个与value中的所有值都不相等的字符 |
get_allocator() | 返回配置器 |
insert() | 插入字符 |
rbegin() | 返回一个逆向迭代器,指向最后一个字符 |
rend() | 返回一个逆向迭代器,指向第一个元素的前一个位置 |
replace() | 替换字符 |
rfind() | 查找最后一个与value相等的字符(逆向查找) |
find
把str的全部字符当作整体进行查找.
size_type find( const basic_string &str, size_type index );size_type find( const char *str, size_type index );size_type find( const char *str, size_type index, size_type length );size_type find( char ch, size_type index );
-
返回str在字符串中第一次出现的位置(从index开始查找)。如果没找到则返回string::npos,
-
返回str在字符串中第一次出现的位置(从index开始查找,长度为length)。如果没找到就返回string::npos,
-
返回字符ch在字符串中第一次出现的位置(从index开始查找)。如果没找到就返回string::npos
代码:
void stringIteratorTestFind() {string s("qwe123qwee123qweqwe1");string flag = "123";string::size_type position = 0;int i = 1;while ((position = s.find(flag, position)) != string::npos) {cout << "position " << i << " : " << position << endl;position++;i++;}
}
image-20201126230709115
find_first_of
size_type find_first_of( const basic_string &str, size_type index = 0 );size_type find_first_of( const char *str, size_type index = 0 );size_type find_first_of( const char *str, size_type index, size_type num );size_type find_first_of( char ch, size_type index = 0 );
跟上面的参数相似,重点理解find的即可。
特别注意:
find_first_of
函数和find函数最大的区别就是,如果在str1
中查找str2
时,如果str1
中含有str2
中的任何字符,就会查找成功,而find
则只有全部相同才会查找成功.
比如:
void stringIteratorTestFind_first_of () {string s("qwe123qwee123qweqwe1");string flag="123";string::size_type position=0;int i=1;while((position=s.find_first_of(flag,position))!=string::npos) {cout<<"第"<<i<<"次匹配 : "<<position<<endl;position++;i++;}
}
与上面的例子区别只是更换了一个函数而已,但是结果完全不同。
image-20221108150441682
至于其他的not,last的变名函数则是顾名思义即可。
rfind
反向查找子字符串
size_type rfind( const basic_string &str, size_type index );size_type rfind( const char *str, size_type index );size_type rfind( const char *str, size_type index, size_type num );size_type rfind( char ch, size_type index );
当正向查找与反向查找得到的位置不相同说明子串不唯一。
erase
iterator erase( iterator pos );iterator erase( iterator start, iterator end );
-
删除pos指向的字符, 返回指向下一个字符的迭代器,
-
删除从start到end的所有字符, 返回一个迭代器,指向被删除的最后一个字符的下一个位置
insert
iterator insert( iterator i, const char &ch );void insert( iterator i, size_type num, const char &ch );void insert( iterator i, iterator start, iterator end );
-
在迭代器i表示的位置前面插入一个字符ch,
-
在迭代器i表示的位置前面插入num个字符ch的拷贝,
-
在迭代器i表示的位置前面插入一段字符,从start开始,以end结束.
replace
basic_string &replace( iterator start, iterator end, const basic_string &str );basic_string &replace( iterator start, iterator end, const char *str );basic_string &replace( iterator start, iterator end, const char *str, size_type num );basic_string &replace( iterator start, iterator end, size_type num, char ch );
-
用str中的字符替换本字符串中的字符,迭代器start和end指示范围
-
用str中的num个字符替换本字符串中的内容,迭代器start和end指示范围,
-
用num个ch字符替换本字符串中的内容,迭代器start和end指示范围.
Strings全部方法
方法名 | 作用 |
---|---|
Constructors | 构造函数,用于字符串初始化 |
Operators | 操作符,用于字符串比较和赋值 |
append() | 在字符串的末尾添加文本 |
assign() | 为字符串赋新值 |
at() | 按给定索引值返回字符 |
begin() | 返回一个迭代器,指向第一个字符 |
c_str() | 将字符串以C字符数组的形式返回 |
capacity() | 返回重新分配空间前的字符容量 |
compare() | 比较两个字符串 |
copy() | 将内容复制为一个字符数组 |
data() | 返回内容的字符数组形式 |
empty() | 如果字符串为空,返回真 |
end() | 返回一个迭代器,指向字符串的末尾。(最后一个字符的下一个位置) |
erase() | 删除字符 |
find() | 在字符串中查找字符 |
find_first_of() | 查找第一个与value中的某值相等的字符 |
find_first_not_of() | 查找第一个与value中的所有值都不相等的字符 |
find_last_of() | 查找最后一个与value中的某值相等的字符 |
find_last_not_of() | 查找最后一个与value中的所有值都不相等的字符 |
get_allocator() | 返回配置器 |
insert() | 插入字符 |
length() | 返回字符串的长度 |
max_size() | 返回字符的最大可能个数 |
rbegin() | 返回一个逆向迭代器,指向最后一个字符 |
rend() | 返回一个逆向迭代器,指向第一个元素的前一个位置 |
replace() | 替换字符 |
reserve() | 保留一定容量以容纳字符串(设置capacity值) |
resize() | 重新设置字符串的大小 |
rfind() | 查找最后一个与value相等的字符(逆向查找) |
size() | 返回字符串中字符的数量 |
substr() | 返回某个子字符串 |
swap() | 交换两个字符串的内容 |
感谢
参考书籍《C++语言程序设计(第4版)》(郑莉,董渊)
C++string的compare()比较函数
感谢现在的好奇,为了能成为更好的自己。