8.string字符串操作
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'就截止了:
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. }
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. }
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. }
分为字符串对象和字符串对象比较、字符串对象和字符串比较、字符串和字符串对象比较:
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. };