【C++】-- STL之String详解(三)

简介: 【C++】-- STL之String详解

8.string字符串操作

(1)获取c形式字符串

const char* c_str() const;//将 const string* 类型 转化为 const char* 类型
1. #include<iostream>
2. #include<string>
3. using namespace std;
4. 
5. int main()
6. {
7.  string s1("cplusplus");
8. 
9.  s1.resize(30);
10.   s1 += "!!!";
11. 
12.   string s2 = s1.c_str();
13. 
14.     cout << s1.size() << endl;
15.   cout << s2.size() << endl;
16. 
17.   return 0;
18. }

监视:s1 resize之后,在末尾插入"!!!",需要重新开空间:

而s1的c形式字符串,遇到第一个'\0'就截止了:

(2)查找

1. size_t find(const string & str, size_t pos = 0) const;//返回在给定字符串中查找字符串str第一次出现的位置  
2. size_t find(const char* s, size_t pos = 0) const;//返回在给定字符串中从下标为pos的位置开始查找字符串s第一次出现的位置
3. size_t find(const char* s, size_t pos, size_t n) const;//返回在给定字符串中从下标为pos的位置开始查找字符串s的前n个字符第一次出现的位置
4. size_t find(char c, size_t pos = 0) const;//返回在给定字符串中从下标为pos的位置开始查找字符c第一次出现的位置
1. #include<iostream>
2. #include<string>
3. using namespace std;
4. 
5. int main()
6. {
7.  string s1("cplusplus.co");
8. 
9.  cout << s1.find("lu") << endl;//返回在s1中查找字符串"lu"第一次出现的位置
10.   cout << s1.find("lu", 3) << endl;//返回在s1中从下标为3的位置开始查找字符串"lu"第一次出现的位置
11.   cout << s1.find('.', 3) << endl;//返回在s1中从下标为3的位置开始查找字符"."第一次出现的位置
12.   cout << s1.find("com", 3, 2) << endl;//返回在s1中从下标为3的位置开始查找字符串"com"的前2个字符第一次出现的位置
13. 
14.     
15.     //取出文件名的后缀
16.   string filename = "main.cpp";
17.   size_t pos = filename.find('.');
18. 
19.   if (pos != string::npos)
20.   {
21.     string buff(filename, pos);
22.     cout << buff << endl;
23.   }
24. 
25.   return 0;
26. }

(3)查找子串

string substr (size_t pos = 0, size_t len = npos) const;//截取给定字符串中从第pos个位置开始的len个长度的字符

成员函数const修饰的是*this,本质是保护成员变量在函数体内不会被改变,相当于this指向的对象成员被保护,不能修改。

1. #include<iostream>
2. #include<string>
3. using namespace std;
4. 
5. //获取域名
6. string getDomain(const string& url)
7. {
8.  size_t pos = url.find("://");
9.  if (pos != string::npos)
10.   {
11.     size_t start = pos + 3;
12.     size_t end = url.find('/', start);
13.     if (end != string::npos)
14.     {
15.       return url.substr(start, end-start);
16.     }
17.     else
18.     {
19.       return string();//返回一个匿名对象
20.     }
21.   }
22.   else
23.   {
24.     return string();
25.   }
26. }
27. 
28. //获取协议名
29. string getProtocal(const string& url)
30. {
31.   size_t pos = url.find("://");
32.   if (pos != string::npos)
33.   {
34.     return url.substr(0, pos);
35.   }
36.   else
37.   {
38.     return string();
39.   }
40. }
41. 
42. int main()
43. {
44. 
45.   //获取URL中的域名和协议名
46.   string url1 = "https://cplusplus.com/reference/string/string/rfind/";
47.   cout << getProtocal(url1) << endl;
48.   cout << getDomain(url1) << endl;
49. 
50.   string url2 = "https://www.baidu.com/";
51.   cout << getProtocal(url2) << endl;
52.   cout << getDomain(url2) << endl;
53. 
54.   return 0;
55. }

(4)反向查找

1. size_t rfind(const string & str, size_t pos = npos) const;//从右向左在给定字符串中查找字符串str第一次出现的位置  
2. size_t rfind(const char* s, size_t pos = npos) const;//从右向左在给定字符串中下标为pos的位置开始查找字符串s第一次出现的位置
3. size_t rfind(const char* s, size_t pos, size_t n) const;//从右向左在给定字符串中从下标为pos的位置开始查找字符串s的前n个字符第一次出现的位置
4. size_t rfind(char c, size_t pos = npos) const;//从右向左在给定字符串中从下标为pos的位置开始查找字符c第一次出现的位置
1. #include<iostream>
2. #include<string>
3. using namespace std;
4. 
5. int main()
6. {
7.     string url1 = "https://cplusplus.com/reference/string/string/rfind/";
8.  cout << url1.rfind(':') << endl;
9. 
10.     return 0;
11. }

9.string字符串比较

分为字符串对象和字符串对象比较、字符串对象和字符串比较、字符串和字符串对象比较:

1. bool operator== (const string& lhs, const string& rhs);
2. bool operator== (const char* lhs, const string& rhs);
3. bool operator== (const string& lhs, const char* rhs);
4. 
5. bool operator!= (const string& lhs, const string& rhs);
6. bool operator!= (const char* lhs, const string& rhs);
7. bool operator!= (const string& lhs, const char* rhs);
8. 
9. bool operator<  (const string& lhs, const string& rhs);
10. bool operator<  (const char* lhs, const string& rhs);
11. bool operator<  (const string& lhs, const char* rhs);
12. 
13. bool operator<= (const string& lhs, const string& rhs);
14. bool operator<= (const char* lhs, const string& rhs);
15. bool operator<= (const string& lhs, const char* rhs);
16. 
17. bool operator>  (const string& lhs, const string& rhs);
18. bool operator>  (const char* lhs, const string& rhs);
19. bool operator>  (const string& lhs, const char* rhs);
20. 
21. bool operator>= (const string& lhs, const string& rhs);
22. bool operator>= (const char* lhs, const string& rhs);
23. bool operator>= (const string& lhs, const char* rhs);
1. #include<iostream>
2. #include<string>
3. using namespace std; 
4. 
5. int main()
6. {
7.     string s1 = "cplusplus";
8.  string s2 = ".com";
9. 
10.   cout << (s1 == s2) << endl;
11.   cout << (s1 == "cplusplus.com") << endl;
12.   cout << ("cplusplus.com" == s2) << endl;
13. 
14.   return 0;
15. }

三、string OJ题

1.仅仅反转字母OJ链接

分析:

(1)发现示例中的字符串,如果是字母就交换,如果不是字母就不做操作,可以用while循环,直到找到都是字母的字符才交换

(2)要判断字符串中,每个字符是不是字母,用函数来判断

1. class Solution {
2. public:
3.     
4.     //判断字符是不是字母
5.     bool IsLetter(char ch)
6.     {
7.         if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
8.         {
9.             return true;
10.         }
11.         else
12.         {
13.             return false;
14.         }
15.     }
16.     
17.     string reverseOnlyLetters(string s) {
18. 
19.         if(s == "")
20.         {
21.             return s;
22.         }
23. 
24.         size_t begin = 0;
25.         size_t end = s.size()-1;
26. 
27.         while(begin < end)
28.         {
29.             //从左边找字母
30.             while((!IsLetter(s[begin])) && (begin < end))
31.             {
32.                 begin++;
33.             }
34.       
35.             //从右边找字母
36.             while((!IsLetter(s[end])) && (begin < end))
37.             {
38.                 end--;
39.             }
40.       
41.             swap(s[begin],s[end]);
42.       
43.             //迭代
44.             begin++;
45.             end--;
46.         }
47. 
48.         return s;
49.     }
50. };

2.字符串里面最后一个单词的长度  OJ链接

分析:

(1)由于cin和scanf一遇到空格就断开了,所以不能接收完整的字符串,getline( )遇到换行才会终止,因此用getline( )来接收

(2)求最后一个单词长度,就要找出从右向左第一个空格的位置,这个位置到字符串末尾的距离就是最后一个单词的长度

1. #include<iostream>
2. #include<string>
3. using namespace std;
4. 
5. int main()
6. {
7.     string s;
8.     
9.     //接收多行输入
10.     while(getline(cin,s))
11.     {
12.         size_t pos = s.rfind(' ');//从右向左找出第一个空格的位置
13.       
14.         if(pos != string::npos)
15.         {
16.             cout << s.size() - 1 - pos <<endl; //字符串末尾到从右向左第一个空格之间的距离
17.         }
18.         else
19.         {
20.             cout << s.size() <<endl;//字符串就是一个完整的单词,最后一个单词长度就是整个字符串长度
21.         }
22.     }
23.     
24.     return 0;
25. }

3.验证回文串  OJ链接

分析:

(1)从示例来看,字母和数字都要进行判断,因此要检查字符是否为字符或数字

(2)忽略大小写,那么可以将大写全部转为小写或小写全部转为大写进行判断

(3)如果对称位置的字符相等,并不能说明一定是回文串,继续迭代;如果不相等,那一定不是回文串

1. class Solution {
2. public:
3.     
4.     //判断字符是不是字母或数字
5.     bool IsLetterOrNumber(char ch)
6.     {
7.         if((ch >= 'a' && ch <= 'z') 
8.         || (ch >= 'A' && ch <= 'Z') 
9.         || (ch >= '0' && ch <= '9'))
10.         {
11.             return true;
12.         }
13.         else
14.         {
15.             return false;
16.         }
17.     }
18. 
19.     bool isPalindrome(string s) {
20.         if(s == "")
21.         {
22.             return true;
23.         }
24.       
25.         //将大写全部转为小写
26.         for(auto& ch:s)
27.         {
28.             if(ch >= 'A' && ch <= 'Z')
29.             {
30.                 ch += 32;
31.             }
32.         }
33.       
34.         //迭代下标定义为int,如果为无符号size_t型,那么当迭代时,end--的如果结果为-1时,-1的无符号数为4294967295,begin一定小于end会再次进入while(begin < end)循环,导致无限循环
35.         int begin = 0;
36.         int end = s.size()-1;
37. 
38.         while(begin < end)
39.         {
40.       
41. 
42.             //从左边找字母
43.             while((!IsLetterOrNumber(s[begin])) && (begin < end))
44.             {
45.                 begin++;
46.             }
47.       
48.             //从右边找字母
49.             while((!IsLetterOrNumber(s[end])) && (begin < end))
50.             {
51.                 end--;
52.             }
53. 
54.             if( s[begin] == s[end] )
55.             {
56.                 //迭代
57.                 begin++;
58.                 end--;
59.             }
60.             else
61.             {
62.                 return false;
63.             }
64.         }
65. 
66.         return true;
67.     }
68. };

4.字符串相加  OJ链接

分析:

(1)相加计算,从低位开始按位相加,迭代就要从字符串末尾向前迭代

(2)相加结果>9就产生进位,下一次相加时,要加上进位

(3)如果将对应位相加结果使用insert依次插入,可以指定插入位置,每次在最前面插入,那么低位相加结果就在低位,高位相加结果就在高位,最后的结果就不需要逆置

        如果将对应位相加结果使用+=拼接起来,那么低位相加结果就在高位,高位相加结果就在低位,最后的结果就需要逆置

1. class Solution {
2. public:
3.     string addStrings(string num1, string num2) {
4.         int end1 = num1.size() - 1;
5.         int end2 = num2.size() - 1;
6. 
7.         string retStr;
8. 
9.         int next = 0;//进位
10.         while(end1 >= 0 || end2 >= 0)
11.         {
12.             int val1 = 0;
13.             if(end1 >= 0)
14.             {
15.                 val1 = num1[end1] - '0';
16.                 end1--;
17.             }
18. 
19.             int val2 = 0;
20.             if(end2 >= 0)
21.             {
22.                 val2 = num2[end2] - '0';
23.                 end2--;
24.             }
25. 
26.             int ret = val1 + val2 + next;
27.       
28.             if(ret > 9)
29.             {
30.                 ret -= 10;
31.                 next = 1;
32.             }
33.             else
34.             {
35.                 next = 0;
36.             }
37. 
38.             retStr.insert(0,1,'0'+ ret);
39.             //retStr += ('0' + ret);//如果不使用insert,而用+=,那么结果就需要逆置
40.         }
41. 
42.         if(next == 1)
43.         {
44.             retStr.insert(0,1,'1');//如果不使用insert,而用+=,那么结果就需要逆置
45.             //retStr += '1';
46.         }
47.       
48.         //reverse(retStr.begin(),retStr.end());//如果不使用insert,而用+=,那么结果就需要逆置
49. 
50.         return retStr;
51.     }
52. };
相关文章
|
1天前
|
存储 算法 程序员
【C++进阶】深入STL之 栈与队列:数据结构探索之旅
【C++进阶】深入STL之 栈与队列:数据结构探索之旅
|
1天前
|
存储 缓存 编译器
【C++进阶】深入STL之list:模拟实现深入理解List与迭代器
【C++进阶】深入STL之list:模拟实现深入理解List与迭代器
|
1天前
|
C++ 容器
【C++进阶】深入STL之list:高效双向链表的使用技巧
【C++进阶】深入STL之list:高效双向链表的使用技巧
|
1天前
|
编译器 C++ 容器
【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题
【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题
|
1天前
|
存储 算法 程序员
【C++进阶】深入STL之vector:构建高效C++程序的基石
【C++进阶】深入STL之vector:构建高效C++程序的基石
|
1天前
|
编译器 C++
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
|
1天前
|
安全 算法 C语言
【C++进阶】深入STL之string:掌握高效字符串处理的关键
【C++进阶】深入STL之string:掌握高效字符串处理的关键
【C++进阶】深入STL之string:掌握高效字符串处理的关键
|
2天前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
1天前
|
编译器 C++
【C++初阶】—— 类和对象 (下)
【C++初阶】—— 类和对象 (下)
|
1天前
|
存储 编译器 C++
【C++初阶】—— 类和对象 (中)
【C++初阶】—— 类和对象 (中)