当前位置:网站首页>虫子 STL string 下 练习题

虫子 STL string 下 练习题

2022-06-26 13:06:00 华为云

4.string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

注意:

  1. 在string尾部追加字符时,s.push_back / s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

image-20220129011010870

int main(){	string s;	s.push_back('h');	s.push_back('e');	s.push_back('l');	s.push_back('l');	s.push_back('o');	cout << s << endl;	s.append(" world");	cout << s << endl;	string s2 = "!!!!!!";	s.append(s2);	cout << s << endl;	//但是不巧的是实际中最喜欢用的是+=	string s3;	s3 += 'X';	s3 += "你好";	s3 += s2;	cout << s3 << endl;	//尽量少用insert,因为底层实现是数组,头部或者中间需要挪动数据	s3.insert(0, "x");	s3.insert(0,"hhhh");	cout << s3 << endl;	//删除	string s4 = s3;	string s5 = s3;	string s6 = s3;	s4.erase(3, 100);//从第三个开始删除	s5.erase(3);//从第三个开始删除,一直删完	s6.erase(); //直接删光	cout << s4 << endl;	cout << s5 << endl;	cout << s6 << endl;	return 0;}

image-20220129185118237

int main(){	string s("Hello world");	cout << s << endl;        //这边调的是operator<<(cout,s);	cout << s.c_str() << endl;//这边调用的是内置类型operator<<(cout,const char*);	s.resize(20);	s += "!!!";	cout << s << endl;	cout << s.c_str() << endl;	return 0;}

image-20220129202118400

int main(){	//假设我们需要取文件名的后缀	string filename = "text.txt.zip";	size_t pos = filename.rfind('.');	if (pos != string::npos)	{		string suff(filename, pos);		cout << suff << endl;	}	return 0;}

image-20220130103936419

//取域名string GetDomain(const string& url){	size_t pos = url.find("://");	if (pos != string::npos)	{		//找到域名的最开始位置		size_t start = pos + 3;		//从域名开始的位置向后面找 ’/‘ 		size_t end = url.find('/', start);		if (end != string::npos)		{			return url.substr(start, end - start);		}	}	//假如没有就返回一个匿名对象	return string();}//取协议string GetProtocol(const string& url){	size_t pos = url.find("://");	if (pos != string::npos)	{		return url.substr(0, pos);	}	//假如没有就返回一个匿名对象	return string();}int main(){	//分别取出域名和协议名	string url1 = "http://www.cplusplus.com/reference/string/string/find/";	string url2 = "https://juejin.cn/creator/home";	cout << GetDomain(url1) << endl;	cout << GetProtocol(url1) << endl;	cout << GetDomain(url2) << endl;	cout << GetProtocol(url2) << endl;	return 0;}

5.string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)输入运算符重载
operator<< (重点)输出运算符重载
getline (重点)获取一行字符串
relational operators (重点)大小比较

几题小菜

找字符串中第一个只出现一次的字符

用这题来练手3种遍历

image-20220127165401047

下标+[]

image-20220127170528297

class Solution {public:int firstUniqChar(string s) {  //26个字母计数数组  int count[26] = {0};  int i= 0;  //遍历计数  for(i = 0;i<s.size();i++)  {      count[s[i]-97]++;  }  //找第一个是1的  for(i = 0;i<s.size();i++)  {      if(1 == count[s[i]-97])      return i;  }  return -1;}};
迭代器

image-20220127185059304

class Solution {public:int firstUniqChar(string s) {  //26个字母计数数组  int count[26] = {0};  //迭代器  string::iterator it = s.begin();  while(it != s.end())  {      count[*it-97]++;      it++;  }  //找第一个是1的  for(int i = 0;i<s.size();i++)  {      if(1 == count[s[i]-97])      return i;  }  return -1;}};
范围for

image-20220127190748999

class Solution {public:int firstUniqChar(string s) {  //26个字母计数数组  int count[26] = {0};  //范围for for(auto& e:s) {      count[e-97]++; }  //找第一个是1的  for(int i = 0;i<s.size();i++)  {      if(1 == count[s[i]-97])      return i;  }  return -1;}};

仅仅反转字母

image-20220128105728308

image-20220128105637326

class Solution {public: //判断是否是字母 bool isletter(const char ch) {     if((ch >= 'a' && ch<='z') ||(ch >= 'A' && ch <='Z'))     return true;     return false; } string reverseOnlyLetters(string s) {     if(!s.size())      return s;    //头尾下标    int begin = 0,end = s.size()-1;    while(begin < end)    {        while(begin < end && !isletter(s[begin]))             begin++;        while(begin < end && !isletter(s[end]))             end--;         swap(s[begin],s[end]);         begin++;         end--;    }    return s;    }};

字符串最后一个单词的长度

image-20220127211552511

image-20220130112625865

image-20220130113017517

#include <iostream>using namespace std;int main(){ string str; getline(cin,str); size_t pos = str.rfind(' '); if(pos != string::npos) {     cout<< str.size()-pos-1<<endl; } else {     cout<< str.size()<<endl; } return 0;}

验证回文串

image-20220127212716778

image-20220130130005327

class Solution {public: bool isPalindrome(string s) {     //创建两个空字符串     string str1,str2,str3;             //反向迭代器     string::reverse_iterator rit = s.rbegin();     while(rit != s.rend())     {         if(*rit >= 'A' && *rit <='Z')             str1 += *rit+32;         else if(*rit >= 'a' && *rit<='z')             str1 += *rit;         else if(*rit >= '0' && *rit<='9')             str1 += *rit;         rit++;     }     str2 = str1;     //再来一次反向迭代器     string::reverse_iterator rt = str2.rbegin();     while(rt != str2.rend())        str3 += *rt++;     if(str3 == str2)         return true;     else         return false; }};

image-20220130132239335

class Solution {public: //判断字母数字 bool islettername(const char& ch){     if(ch >= 'a' && ch <= 'z'     || (ch >= '0' && ch <='9'))     return true;     return false; } bool isPalindrome(string s) {     //先把s里面大写全部改成小写的     for(auto& e:s)     {         if(e>='A' && e<='Z')         e+=32;     }     int begin = 0;     int end = s.size()-1;     while(begin < end)     {         while(begin < end && !islettername(s[begin]))         begin++;         while(begin < end && !islettername(s[end]))         end--;         if(s[begin] == s[end])         {              begin++; end--;         }         else         return false;     }     return true; }};

字符串相加

image-20220130133032959

image-20220130141528575

class Solution {public: string addStrings(string num1, string num2) {     //两个下标     int end1 = num1.size()-1,end2 = num2.size()-1;     //计算后的对象     string ansStr;     //进位     int carry = 0;     while(end1>=0 || end2>=0)     {         int n1 = 0;         if(end1 >= 0){             n1 = num1[end1] - '0';             end1--;         }         int n2 = 0;         if(end2 >= 0){             n2 = num2[end2] - '0';             end2--;         }         //两个位置开始相加         int ret = n1+n2+carry;         if(ret > 9){             ret -= 10;             carry = 1;         }         else             carry = 0;         //这是就准备插字符         ansStr.insert(0,1,ret+'0');     }     //插最后一个进位的     if(carry)     ansStr.insert(0,1,carry+'0');     return ansStr; }};

==实际上我们可以看到提交时间看到我们时间复杂度不行,那是因为我们头插了insert了,字符串越长,挪动的就越恶心,也就效率越低,所以我就直接尾插,到最后再来个逆置reverse就行了,这时候就看我们选用的接口了,基本一题都有好几种解法==

image-20220130143407011

class Solution {public: string addStrings(string num1, string num2) {     //两个下标     int end1 = num1.size()-1,end2 = num2.size()-1;     //计算后的对象     string ansStr;     //进位     int carry = 0;     while(end1>=0 || end2>=0)     {         int n1 = 0;         if(end1 >= 0){             n1 = num1[end1] - '0';             end1--;         }         int n2 = 0;         if(end2 >= 0){             n2 = num2[end2] - '0';             end2--;         }         //两个位置开始相加         int ret = n1+n2+carry;         if(ret > 9){             ret -= 10;             carry = 1;         }         else             carry = 0;         //这是就准备插字符 我们这就直接尾插         ansStr += (ret +'0');     }     //插最后一个进位的     if(carry)     ansStr += (carry +'0');     //然后逆置就行     reverse(ansStr.begin(),ansStr.end());     return ansStr; }};
原网站

版权声明
本文为[华为云]所创,转载请带上原文链接,感谢
https://bbs.huaweicloud.com/blogs/361765