虫子 STL string 下 练习题

举报
虫子VV 发表于 2022/06/26 02:50:11 2022/06/26
【摘要】 4.string类对象的修改操作函数名称功能说明push_back在字符串后尾插字符cappend在字符串后追加一个字符串operator+= (重点)在字符串后追加字符串strc_str(重点)返回C格式字符串find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置substr在s...

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;
 }
};
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。