前言
上一节我们讲解了string类中的一部分函数,本节我们继续讲解string类的另外一部分函数,那么废话不多说,我们正式进入今天的学习。
1. string类对象对字符串的操作
**************************************************************************************************************
函数名称 | 函数功能 |
push_back | 在字符串后尾插字符c |
append | 在字符串后尾插一个字符串 |
operator+= | 在字符串后追加字符串str |
assign | 拷贝并覆盖原字符串 |
insert | 在字符串中插入字符串 |
erase | 删除字符串中指定位置的数据 |
replace | 对字符串进行替换 |
swap | 交换两个字符串中的内容 |
pop_back | 尾删字符串中的最后一个字符 |
函数名称 | 函数功能 |
c_str | c_str用于返回指向字符串的指针 |
data | 用于返回指向数组的指针 |
get_allocator | 空间配置器 |
copy | 将字符串里面的内容拷贝出来 |
find | 找到一个字符串中的某个字符或者字符串的位置 |
rfind | 反向查找一个字符串中的某个字符或者字符串的位置 |
find_first_of | 在字符串中搜索与其参数指定的任何字符匹配的第一个字符 |
find_last_of | 在字符串中搜索与其参数指定任何字符匹配的最后一个字符 |
find_first_not_of | |
find_last_not_of | |
**************************************************************************************************************
1.push_back函数
该函数的功能是在字符串后尾插字符c
void test_push_back()
{
string s1("hello worl");
s1.push_back('d');
cout << s1 << endl;
}
2.append函数
append函数用于在字符串后追加一个字符串
void test_append()
{
string s1("123 ");
string s2("234 ");
string s3;
string s4("456 ");
string s5("567 ");
s1.append(s2);
cout << "string& append (const string& str): ";
cout << s1 << endl;
s2.append(s1, 1, 2);
cout << "string& append (const string& str, size_t subpos, size_t sublen):";
cout << s2 << endl;
s3.append("hello world");
cout << "string& append (const char* s):";
cout << s3 << endl;
s4.append("hello world", 5);
cout << "string& append (const char* s, size_t n):";
cout << s4 << endl;
s5.append(1, '6');
cout << "string& append (size_t n, char c):";
cout << s5 << endl;
}
append函数的常用的五种用法展示在上面的代码和运行图片中了,可以自行了解
第六种是迭代区间,在string类中的使用很少,我们到vector部分再进行讲解
3. operator+=
operator+=用于在字符串后追加字符串str
void test_operator()
{
string s1("123 ");
string s2("234 ");
string s3("345 ");
s1 += s2;
cout << "string& operator+= (const string& str):";
cout << s1 << endl;
s2 += "hello world";
cout << "string& operator+= (const char* s):";
cout << s2 << endl;
s3 += '6';
cout << "string& operator+= (char c):";
cout << s3 << endl;
}
4. assign
assign的用法和operator+=类似,但是它赋值并拷贝完以后会把原来的值覆盖
void test_assign()
{
string s1("123 ");
string s2("234 ");
string s3("345 ");
string s4("456 ");
string s5("567 ");
string s6("678 ");
s1.assign(s2);
cout << "string& assign (const string& str):";
cout << s1 << endl;
s2.assign(s2, 0, 1);
cout << "string& assign (const string& str, size_t subpos, size_t sublen):";
cout << s2 << endl;
s3.assign("3");
cout << "string& assign (const char* s)";
cout << s3 << endl;
s4.assign("hello world", 5);
cout << "string& assign (const char* s, size_t n):";
cout << s4 << endl;
s5.assign(1, '5');
cout << "string& assign (size_t n, char c):";
cout << s5 << endl;
}
5. insert
insert是用来在字符串中插入数据的
void test_insert()
{
string s1("123 ");
string s2("234 ");
string s3("345 ");
string s4("456 ");
string s5("567 ");
string s6("678 ");
s1.insert(4, s2);
cout << "string& insert (size_t pos, const string& str):" << s1 << endl;
s2.insert(4, s2, 0, 2);
cout << "string& insert (size_t pos, const string& str, size_t subpos, size_t sublen):" << s2 << endl;
s3.insert(4, "hello world");
cout << "string& insert (size_t pos, const char* s):" << s3 << endl;
s4.insert(4, "hello world", 5);
cout << "string& insert (size_t pos, const char* s, size_t n):" << s4 << endl;
s5.insert(4, 2, '6');
cout << "string& insert (size_t pos, size_t n, char c):" << s5 << endl;
}
因为string类中没有头插的函数,所以我们要想头插数据,就得使用insert
我们需要谨慎使用,因为使用insert在指定位置插入数据需要把指定位置后面的数据往后挪动,挪动数据可能会提升时间复杂度,可能会拖垮代码的效率
6.erase
erase用于对字符串的删除
void test_erase()
{
string s1("hello world");
string s2("hello world");
string s3("hello world");
s1.erase(6, 5);
cout << "string& erase (size_t pos = 0, size_t len = npos):" << s1 << endl;
s2.erase(0, 6);
cout << "string& erase (size_t pos = 0, size_t len = npos):" << s2 << endl;
//头删(间接实现)
s3.erase(s3.begin());
cout << "iterator erase (iterator p):" << s3 << endl;
//尾删(间接实现)
s3.erase(--s3.end());
cout << s3 << endl;
s3.erase(s3.size() - 1, 1);
cout << s3 << endl;
}
当传入的len大于字符串的长度时,它会删到字符串删完就停止删除了,不会越界删除(npos)
7.replace
replace用于对字符串的替换
void test_replace()
{
string s1("123 ");
string s2("234 ");
string s3("345 ");
string s4("456 ");
string s5("567 ");
string s("xyz");
s1.replace(0, 2, s);
cout << "string& replace (size_t pos, size_t len, const string& str):" << s1 << endl;
s2.replace(0, 2, s, 1, 2);
cout << "string& replace (size_t pos, size_t len, const string& str,size_t subpos, size_t sublen):";
cout << s2 << endl;
s3.replace(2, 2, "xyz");
cout << "string& replace (size_t pos, size_t len, const char* s):" << s3 << endl;
s4.replace(0, 4, "xyz", 2);
cout << "string& replace (size_t pos, size_t len, const char* s, size_t n):" << s4 << endl;
s5.replace(0, 4, 6, '6');
cout << "string& replace (size_t pos, size_t len, size_t n, char c):" << s5 << endl;
}
8.swap
swap函数是用来交换字符串的。
swap在底层实现的原理是将两个对象的_str、_capacity、_size全部交换,不涉及拷贝和赋值,更加高效
void test_swap()
{
string s1("hello");
string s2("world");
s1.swap(s2);
cout << "void swap (string& str): s1 = " << s1 << " s2 = " << s2 << endl;
}
9.pop_back
该函数的功能是尾删最后一个字符
void test_pop_back()
{
string s1("hello world*");
s1.pop_back();
cout << "void pop_back(): " << s1 << endl;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.c_str
暂时只需了解即可
c_str用于返回指向字符串的指针
该函数存在的意义是为了兼容C语言,因为C语言中没有string类,而C++有时候不可避免的需要使用C语言的语法
void test_c_str()
{
string file;
cin >> file;
FILE* fout = fopen(file.c_str(), "r");
char ch = fgetc(fout);
while (ch != EOF)
{
cout << ch;
ch = fgetc(fout);
}
fclose(fout);
}
2.data
data的存在和c_str类似,也是为了兼容C语言,它会返回一个指向数组的指针
3.get_allocator
是STL六大组件中的空间配置器,也就是内存池,我们平常几乎不会使用,所以可以忽略
4.copy
copy将字符串里面的内容拷贝出来,使用情况也很少
void test_copy()
{
string s1("hello");
char s2[10];
s1.copy(s2, 4, 0);
for (int i = 0; i < 4; i++)
{
cout << s2[i] << " ";
}
cout << endl;
}
5.find
find函数用于找到一个字符串中的某个字符或者字符串的位置
void test_find()
{
string s1("hello world");
string s2("o");
size_t ret1 = s1.find(s2);
cout << "size_t find (const string& str, size_t pos = 0) const: " << ret1 << endl;
size_t ret2 = s1.find(s2, 5);
cout << "size_t find (const string& str, size_t pos = 5) const: " << ret2 << endl;
cout << "********************************************************" << endl;
size_t ret3 = s1.find("ll");
cout << "size_t find (const char* s, size_t pos = 0) const: " << ret3 << endl;
size_t ret4 = s1.find("ll", 5);
cout << "size_t find (const char* s, size_t pos = 5) const: " << ret4 << endl;
cout << "********************************************************" << endl;
size_t ret5 = s1.find("hellof", 0, 6);
cout << "size_t find (const char* s, size_t pos = 0, size_t n = 6) const: " << ret5 << endl;
size_t ret6 = s1.find("hellof", 0, 5);
cout << "size_t find (const char* s, size_t pos = 0, size_t n = 5) const: " << ret6 << endl;
cout << "********************************************************" << endl;
size_t ret7 = s1.find(' ');
cout << "size_t find (char c, size_t pos = 0) const: " << ret7 << endl;
size_t ret8 = s1.find(' ', 6);
cout << "size_t find (char c, size_t pos = 6) const: " << ret8 << endl;
}
当我们寻找的字符串或者字符在原字符串中出现多次的时候,此时默认返回的是字符串第一次出现的位置;
如果找不到字符或者字符串的话,就会返回npos,也就是整型的最大值;
当我们指定pos,此时寻找就会默认从pos位置之后开始,不会在找pos之前的字符或者字符串了;
注意第三点中的n是要寻找的字符的长度,而不是原字符串寻找的区间;
**************************************************************************************************************
巩固练习:把 "hello world hello world" 字符串中的 ' ' 全部替换为 '**'
void test01()
{
string s("hello world hello world");
size_t pos = s.find(' ');
while (pos != string::npos)
{
s.replace(pos, 1, "**");
pos = s.find(' ');
}
cout << s << endl;
}
如果对效率的要求不高的话,可以写这个代码,因为涉及到扩容。每次插入**的时候都要扩容。(如果是一个换一个或者两个换两个这种等量代换则没有影响,但是这种情况用operator[]会更加方便)
如果对效率要求高的话,我们可以采取以空间换时间的方式:
void test02()
{
string s("hello world hello world");
string tmp;
tmp.reserve(s.size());
//避免多次扩容,拖垮效率
for (auto ch : s)
{
if (ch == ' ')
tmp += "**";
else
tmp += ch;
}
cout << tmp << endl;
}
注意:erase、insert、replace使用都有可能会很大程度的拖垮程序效率,需要谨慎使用
**************************************************************************************************************
6.rfind
rfind和find都起到了查找的功能。但是find是正向查找,rfind是反向查找,故不作详细讲解了
void test_rfind()
{
string s1("hello world hello world");
string s2("hello");
string s3("hello world");
size_t ret1 = s1.rfind(s2, string::npos);
cout << "size_t rfind (const string& str, size_t pos = npos) const: " << ret1 << endl;
size_t ret2 = s1.rfind("hello", string::npos);
cout << "size_t rfind (const char* s, size_t pos = npos) const: " << ret2 << endl;
size_t ret3 = s1.rfind("hello1", 10, 5);
cout << "size_t rfind (const char* s, size_t pos, size_t n) const: " << ret3 << endl;
size_t ret4 = s1.rfind('h', string::npos);
cout << "size_t rfind (char c, size_t pos = npos) const: " << ret4 << endl;
}
7.find_first_of
该函数用于在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。注意,序列中的一个字符匹配就足够了,不要求所有字符匹配
void test_find_first_of()
{
string s1("hello world");
string s2("hed");
size_t ret1 = s1.find_first_of(s2);
cout << "size_t find_first_of (const string& str, size_t pos = 0) const: " << ret1 << endl;
size_t ret2 = s1.find_first_of("low");
cout << "size_t find_first_of (const char* s, size_t pos = 0) const: " << ret2 << endl;
size_t ret3 = s1.find_first_of("abcd", 0, 3);
cout << "size_t find_first_of (const char* s, size_t pos, size_t n) const: " << ret3 << endl;
size_t ret4 = s1.find_first_of('l');
cout << "size_t find_first_of (char c, size_t pos = 0) const: " << ret4 << endl;
}
8.find_last_of
该函数用于在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。注意,序列中的一个字符匹配就足够了,不要求所有字符匹配
void test_find_last_of()
{
string s1("hello world");
string s2("hed");
size_t ret1 = s1.find_last_of(s2);
cout << "size_t find_last_of (const string& str, size_t pos = npos) const: " << ret1 << endl;
size_t ret2 = s1.find_last_of("low");
cout << "size_t find_last_of (const char* s, size_t pos = 0) const: " << ret2 << endl;
size_t ret3 = s1.find_last_of("abcd", s1.npos, 3);
cout << "size_t find_last_of (const char* s, size_t pos, size_t n) const: " << ret3 << endl;
size_t ret4 = s1.find_last_of('l');
cout << "size_t find_last_of (char c, size_t pos = 0) const: " << ret4 << endl;
}
9.find_first_not_of
搜索与其参数中指定的任何字符都不匹配的字符串的第一个字符,如果搜索不到则返回npos
void test_find_first_not_of()
{
string s1("hello world");
string s2("hello*world");
size_t ret1 = s1.find_first_not_of(s2);
cout << "size_t find_first_not_of (const string& str, size_t pos = 0) const: " << ret1 << endl;
size_t ret2 = s1.find_first_not_of("nello*world");
cout << "size_t find_first_not_of (const char* s, size_t pos = 0) const: " << ret2 << endl;
size_t ret3 = s1.find_first_not_of("hellp*", 0, 6);
cout << "size_t find_first_not_of (const char* s, size_t pos, size_t n) const: " << ret3 << endl;
size_t ret4 = s1.find_first_not_of('d');
cout << "size_t find_first_not_of (char c, size_t pos = 0) const: " << ret4 << endl;
}
10.find_last_not_of
void test_find_last_not_of()
{
string s1("hello world");
string s2("wrld");
size_t ret1 = s1.find_last_not_of(s2);
cout << "size_t find_last_not_of (const string& str, size_t pos = 0) const: " << ret1 << endl;
size_t ret2 = s1.find_last_not_of("nello*worlo");
cout << "size_t find_last_not_of (const char* s, size_t pos = 0) const: " << ret2 << endl;
size_t ret3 = s1.find_last_not_of("dolwr", s1.npos, 5);
cout << "size_t find_last_not_of (const char* s, size_t pos, size_t n) const: " << ret3 << endl;
size_t ret4 = s1.find_last_not_of('hd');
cout << "size_t find_last_not_of (char c, size_t pos = 0) const: " << ret4 << endl;
}
11.substr
拷贝字符串中的子串并返回一个新构造的对象
void test_substr()
{
string s1("hello world");
string s = s1.substr(6);
cout << "string substr (size_t pos = 0, size_t len = npos) const: " << s << endl;
}
**************************************************************************************************************
练习:
假设我们要查找一个文件的后缀名(例如Test.cpp的后缀名就是cpp),我们可能会想到先用find找到" . ",然后用copy将后缀名复制出来。但其实我们很少会使用copy,因为copy需要自己创建一个字符数组,万一我们自己开辟的数组的空间不够的话就会造成数据的丢失。所以我们在获取某字符串的一个子串的时候通常会采用substr
void test_02()
{
string s("test.cpp");
size_t pos = s.find('.');
string suffix = s.substr(pos+1);
cout << suffix << endl;
}
但是假设文件名为Test.cpp.zip呢?我们此时又该如何取后缀呢?
我们此时就只需要把find改成rfind即可:
void test_02()
{
string s("test.cpp");
size_t pos = s.rfind('.');
string suffix = s.substr(pos+1);
cout << suffix << endl;
}
**************************************************************************************************************
12.compare
该函数使用非常少,而且string类专门重载了大于小于符号,compare函数几乎不会使用,仅作了解即可
void test_compare()
{
std::string str1("green apple");
std::string str2("red apple");
if (str1.compare(str2) != 0)
std::cout << str1 << " is not " << str2 << '\n';
if (str1.compare(6, 5, "apple") == 0)
std::cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size() - 5, 5, "apple") == 0)
std::cout << "and " << str2 << " is also an apple\n";
if (str1.compare(6, 5, str2, 4, 5) == 0)
std::cout << "therefore, both are apples\n";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
结尾
本节我们把string类大部分的函数都学习完了,下一节我们将会进行string类的习题练习,希望可以给您带来帮助,谢谢您的浏览!!!