纪念 229头像
C++ 算法模拟(下)封面图

C++ 算法模拟(下)

在这里插入图片描述

༺ 个人主页 · 纪念229 ༻

🏠我的博客主页🏠

༒专栏目录:《数据结构》༒

༒专栏目录:《算法》༒

༒专栏目录:《C++》༒

༒专栏目录:《MySQL数据库》༒

༒专栏目录:《前端开发》༒

༒其它有趣的计算机知识༒

༺世上本没有路,走的人多了自然就有了༻


本篇文章讲述了C++算法中有关模拟的题,希望对你有所帮助

题目链接:
字符串的展开


文章目录


1.字符串的展开

我还是那句话模板题目要用草稿纸把题意的层次关系分好最后在将层次关系实现为代码(其次我们还要积累一些算法函数)

在这里插入图片描述
在这里插入图片描述
需要我们输入p1 p2 p3,在输入这个字符串我们的目的具题意将字符串展开

题目有隐藏的条件需要我们知道 输入的字符串首字符和末为’-‘我们不展开这里我们直接打印这两个下标的字符即可还有就是’-'两边一个是数字字符一个数字母字符无法展开

其它我们设计的代码的时候就根据题意即可


//容器题目不用迭代器用下标不然很麻烦,既然不用迭代器我们一般用while或for得到下标好遍历 

//这种利用容器的题目就不要用迭代器利用下标,这里展开插入的话在原字符插入的话不方便插入如果后续插入的话也会麻烦(下标要记字符'-'要覆盖),我们不妨定义一个新的string对象根据题意将字符或字符串一一插入到新的
//string对象里,最后直接打印对象即可(利用运算符重载)


//题目有两种情况要我们自己推出我们根据这三种情况和题意解题即可
//1.'-'出现在字符串首尾我们不管直接插入新对象不用展开
//2.'-'左右两边类型不同(一个是数字字符一个是字母字符)不用展开直接一个个插入新对象
 

#include<iostream>
#include<string>
#include<cctype>
#include<algorithm>
using namespace std;
int p1, p2, p3;
string s,tmp;//我们利用tmp对象存储展开后的字符串 
int main()
{
   	cin >> p1 >> p2 >> p3 >> s;//不同类型的数据可以连续输入 
    //首先直接插入s[0]不管它是什么直接插入,解决首字符为'-'的问题 
      tmp = s[0]; 
	  for(int i = 1; i < s.size() - 1; i++)//利用for循环遍历s对象因为我们要看'-'左右的字符所以用for循环遍历好控制下标(用while也可以但是最后要加加下标麻烦) 
	  //循环遍历i从1开始到 s.size() - 2就避免了'-'在首末两端遍历左右越界的问题 
	  {
	  //两种情况
	  //展开遇到'-'左右两边都是数字字符或字母字符右边的ascll码值大于左边的且两边都同类型 最后插入字符串 
	  //否则不展开 直接插入字符 
	  //isalnum和isdigiti以及isalpha参数都是int但是实际需求范围在0~225之间传字符时要隐式类型转换为unsigned char 
	  if(s[i] == '-' && (isalnum((unsigned char)s[i -1]) && isalnum((unsigned char)s[i + 1])) && s[i - 1] < s[i + 1] && (isdigit((unsigned char)s[i - 1]) == isdigit((unsigned char)s[i + 1])))//这里isdigit两个是==号确保当已经确定它是数字字符或字母字符时保证'-'两边的数据是同一类型的字符,同时解决字符'-'两边一个是数字字符一个数字母字符的问题 
	  //isalnum返回类型bool判断是否是数字字符或字母字符,isdigit返回bool类型判断是否是数字字符(isalnum和isdigit的头文件是cctype)
	  //先判断是否为数字字符或字母字符并且判断是否都是数字字符不是那一定是字母字符 
	  {
	  	//展开 
		// 我们先判断p1是否为3否则定义char类型的a,b被s[i - 1]和s[i + 1]赋值判断 是否为字母字符 判断p1为1还是2然后利用a,b进行for循环将展开字符一个个插入tmp容器内 
       string fill;//定义一个string类型对象将展开的字符串存储最后插入tmp中 ,fill要放在展开逻辑最前面 
	   if(p1 == 3){
       	//当p1==3时不论是字母子串还是数字字串,都用与要填充的个字母要填多少字母个数相同的星号 * 来填充。这个意思指的是中间字符有几个就就插入几个*在乘以p2个 
//     这个不行  	fill += string(p2, '*');//string(个数,字符(这里要求'*'))返回一个n个目标字符的字符串头文件为string 
	   char a = s[i - 1], b = s[i + 1];
	   for(int i = 0; i < (b - a- 1); i++)
	   for(int j = 0; j < p2; j++) fill += '*';
	   }else{
	   char a = s[i - 1], b = s[i + 1];
	   //判断是否为字母字符这里只用a来判断因为a与b是同一个类型 
	   if(isalpha((unsigned char)a)){
	   	if(p1 == 2) {a = (char)toupper(a); b = (char)toupper(b);}//toupper的作用是将某字符变为大写字符 //有两个;说明有两句所以条件语句要加{}(大括号)  大括号外不需要加;最后一个语句后要加分号; 
	   	else {a = (char)tolower(a); b = (char)tolower(b);}//tolower的作用是将某字符变为小写字符 
	     //toupper和tolower的头文件是cctype返回类型是int所以我们要隐式类型转换为char类型 
	   } 
	   //利用a,b进行for循环以及p2所构建的for循环,利用两个for循环将 字符一个个插入fill对象中
	   for(char i = a + 1; i  < b; i++) 
	   for(int j = 0; j < p2; j++) fill += i;
	   }
	    //如果p3 == 2 就反转展开字符串fill 
		 if(p3 == 2)  reverse(fill.begin(), fill.end()) ;
	   //最后将fill对象中的字符串插入tmp中
	   tmp  += fill; 
	   
	  
	  }else{
	  	//不展开直接插入该字符 
	  	tmp += s[i];
	  } 
	} 
	  //然后要补上s的最后一个字符 解决最后一个字符为'-'的问题 
	  //tmp += s.back(); //DevC++里的tring没有back函数 C++11后string是有back函数的 
	 if(s.size() > 1)   tmp += s[s.size() - 1]; 
	  //最后打印对象tmp
	  cout << tmp; 
	return 0;
} 

题目刚开始就先将第一个字符放入展开字符串然后两种情况第一种展开该位置为’-‘且’-'左右两边都为数字字符或字母字符 并且右边的字符ascll码值大于左边字符的且两边字符是同一类字符(都是数字字符或都是字母字符),我们首先定义一个string对象fill来装展开的字符串首先我们判断 p1 == 3为一类这个意思就是两字符之间有多少字符就每个单独的字符各打p2个然后另一类是我们首先判断左边的字符是不是字母字符(因为到了这一步左右两边的字符都是同一类型的)是的话我们判断 p1 == 2 如果是我们将左右两边的字符转化为大写字符如果不是就将两边字符转化为小写字符 然后我们利用这两个字符用for循环再利用p2做一个内层for循环(因为p2为多少就打印多少两字符之间的每一个字符)里面用fill接收这些字符即可 另一种是不符合该条件的我们直接将该下标指向的字符插入fill即可 离开判断语句我们首先判断p3 == 2 如果成立我们就将fill字符反转
最后我们将fill字符串插入tmp字符串即可 最后离开for循环直接打印tmp对象就是我们要求的展开后的字符串

int p1, p2, p3;
string s,tmp;//我们利用tmp对象存储展开后的字符串 

首先我们定义好p1,p2,p3以及s和tmp s是用来输入字符串的 tmp是用来接收展开后的字符串的

tmp = s[0];我们先将输入字符串的第一个元素放入tmp中解决第一个是’-'的问题

然后利用for循环遍历s字符串里的字符(我们到s.size() - 2就结束因为防止字符串末尾是’-‘)然后我们开始写条件语句这里的isalnum的意思是判断该字符是否为数字字符或字母字符如果不是就false isdigit这里用加上 == 判’-'左右两边的字符是否为同一类型的字符因为之前已经判断这两个字符一定是数字字符或字母字符 (它的意思是该字符是否为数字字符) isalnum和isdigit头文件都是cctyp由于参数类型是int类型但是实际上只接收ascll码0~225之间的字符串所以我们要将字符(char -128到127)隐式类型转换为unsigned char类型

 if(s[i] == '-' && (isalnum((unsigned char)s[i -1]) && isalnum((unsigned char)s[i + 1])) && s[i - 1] < s[i + 1] && (isdigit((unsigned char)s[i - 1]) == isdigit((unsigned char)s[i + 1])))

这里就可以解决’-'两边不能一个是数字字符一个是字母字符

在循环开始我们定义一个fill装展开的字符串

我们将它分为两种一种p1 == 1和另一种(先判断是否为字母字符)然后将’-’
左右两边的字符a - 1 到 b - 1 之间的字符赋值到 字符串 fill中

我们首先看一下p1 == 3的时候 我们定义a 与b接收 '-'左右两边的字符利用这两个字符进行for循环已及利用p2的内循环将 'x’插入fill对象中

 char a = s[i - 1], b = s[i + 1];
	   for(int i = 0; i < (b - a- 1); i++)
	   for(int j = 0; j < p2; j++) fill += '*';

这里第一个循环我们不用i = a -1是因为我们要的’*'个数不是具体的字符而p1不为1我们需要 i为 a - 1到 b -1

然后我们当p1不等于 1的时候我们首先就要判断字符isalpha 头文件是cctype参数是int类型实际上范围在0~255之间我们要隐式类型转换为unsigned char是否为字母字符p1为2的时候将两字符转换为大写字母字符toupper p1 为1 将两字符变为小写字符tolower toupper函数与tolower函数头文件都是cctype返回类型是int类型编译器会隐式类型转换为char类型

 char a = s[i - 1], b = s[i + 1];
	   //判断是否为字母字符这里只用a来判断因为a与b是同一个类型 
	   if(isalpha((unsigned char)a)){
	   	if(p1 == 2) {a = (char)toupper(a); b = (char)toupper(b);}//toupper的作用是将某字符变为大写字符 //有两个;说明有两句所以条件语句要加{}(大括号)  大括号外不需要加;最后一个语句后要加分号; 
	   	else {a = (char)tolower(a); b = (char)tolower(b);}//tolower的作用是将某字符变为小写字符 
	     //toupper和tolower的头文件是cctype返回类型是int所以我们要隐式类型转换为char类型 
	   } 
	   //利用a,b进行for循环以及p2所构建的for循环,利用两个for循环将 字符一个个插入fill对象中
	   for(char i = a + 1; i  < b; i++) 
	   for(int j = 0; j < p2; j++) fill += i;
	   }

遍历一次到了最后我们要判断p3 == 2是的话我们要将fill对象反转最后将fill字符串放入tmp对象中

 //如果p3 == 2 就反转展开字符串fill 
		 if(p3 == 2)  reverse(fill.begin(), fill.end()) ;
	   //最后将fill对象中的字符串插入tmp中
	   tmp  += fill; 

不符合条件就直接将该字符直接插入tmp字符串中

else{
	  	//不展开直接插入该字符 
	  	tmp += s[i];
	  } 

最后我们结束循环还要将s的最后一个字符插入tmp中解决最后一个字符为’-'的问题

if(s.size() > 1) tmp += s[s.size() - 1];
这里条件要输入字符个数大于1是因为为1的话那么首字母和尾字母是同一个字母了就多插了

最后打印tmp对象
cout << tmp;

总之模拟算法题我推荐先把全局写好再一部分一部分实现符合题目规则的代码(当然认识一些基础的有关算法的函数是必要的)


文章到此就告一段落,希望对你有所帮助,感谢观看!

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2503_94479566/article/details/169651451

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--