一道华为编程大赛的试题

请大家帮我看看,程序有问题没有?

  • 问题描述:
    • 检查字符串表达式中的括号是否匹配;
    • 左括号数目同有括号数目不相等即为不匹配;
    • 去除多余的左括号或者右括号,优先保留先出现的括号;
    • 匹配后去除无效的括号:如:((表达式)) 应为(表达式);
    • 只考虑小括号,不考虑先出现右括号的情况;
  • 要求实现函数: (字符串最长长度为60;表达式正确性不需要考虑)

void Bracket(char* src, char* dst);

如果匹配则通过dst输出原串;

如果不匹配则根据要求去处多于括号后通过dst输出匹配后的串

  • 示例

输入:12+(345*25-34)   输出:12+(345*25-34)

     输入:12+(345*(25-34)   输出: 12+(345*25-34)

     输入:(12+345)*25)-34   输出: (12+345)*25-34

     输入:(543+(256-43)*203))+24   输出:(543+(256-43)*203)+24

     输入:((1+2)*((34-2))+((2*8-1) 输出:((1+2)*(34-2)+2*8-1)

我的分析思路:

    该题目有点像检测代码语法错误,输入一个符合格式的字符数组,程序检查给格式的正确性。并给与改正。

    算法步骤:

    1 判断括号匹配(这个是栈的一个很好的运用):

        扫描字符数组(程序中规定的是字符串,可以通过memcpy将他们拷贝到一个数组里面,这样好修改),如果是‘(’就入栈,当如果是‘)’,这时就要小心了:我发现有三种情况:

        (1)如果栈为空,很明显,这个字符没有匹配的,判断为错误字符,用‘@’字符替代(原因后面再说)。  

        (2)如果栈不为空且大于1,但是这个字符串中最后一个‘)’符号。这就说明,前面出现了((????)这种局面,按照第三个条件,优先保留最前面的,所以这个和应该和栈低的那个‘(’比配。

        (3)如果栈不为空且,这个字符也不是最后一个字符,说明这个和栈顶的元素匹配。

    2 判断出相邻多余的括号

      经过上面的筛选,我们就得到一个存匹配括号的vector,然后就可以检查他们是不是多余的括号了;经过观察,如果是多余的括号,那么他们的左右括号位置相差为1。如(左括号位置,右括号位置)(2 ,5)(3,4)。当然这种思路不会筛选出(2,4)(3,5),但是这里就这个题而言,一部的筛选已经把这种情况排出了。

下面是我的代码(为了实现简单,用了一些stl库):

void M_Bracket(char* src, char* dst)
{
int len=strlen(src);
if(len>MaxNum)//src >MaxNum
{
dst=NULL;
return;
}
bool flg=true;
vector<Pair> Pairs; //存储匹配结果
stack<Pair> bracket;
///计算出右括号的个数
int right_Bracket=0;
int recordOFDele=0;//记录删除数据的个数
int Ince=0; //
while (src[Ince]!='\0')
{
if (src[Ince]==')')
{
right_Bracket++;//
Ince++;
}else 
Ince++;
}
for (int i=0;i<len;i++)
{
Pair tmp_Pair;
switch (src[i])
{
case '(':
tmp_Pair.c_char='(';
tmp_Pair.left=i;
tmp_Pair.right=0;
bracket.push(tmp_Pair);
break;
case ')':
if (right_Bracket>1&&bracket.size()>0)
{
tmp_Pair=bracket.top();
tmp_Pair.right=i;
Pairs.push_back(tmp_Pair); //存储结果
bracket.pop();          //
}
else if(right_Bracket==1&&bracket.size()>0)
{
int s_size=bracket.size();
for(int i=0;i<s_size-1;i++)//删除前面的(( 除第一个
{
tmp_Pair=bracket.top();
src[tmp_Pair.left]='@';//标记将被删除的数据
recordOFDele++;
bracket.pop();
}
tmp_Pair=bracket.top();
tmp_Pair.right=i;
Pairs.push_back(tmp_Pair);
}
else if(bracket.size()==0)//没有匹配
{
flg=false;
//删除该符号
recordOFDele++;
src[i]='@';
}
right_Bracket--;
break;
default:
break;
}
}
for (int i=0;i<Pairs.size()-1;i++)
{
if(abs(Pairs[i].right-Pairs[i+1].right)==1&&abs(Pairs[i].left-Pairs[i+1].left)==1)///这组括号中间相隔为0 及为多余的括号
  {
  src[Pairs[i].left]='@';
  src[Pairs[i].right]='@';
  recordOFDele=recordOFDele+2;
  }
}
///将src复制到dst中
int j=0;
for (int i=0;src[i]!='\0';i++)
{
if (src[i]!='@')
{
dst[j]=src[i];
j++;
}
}
dst[j]='\0';
}
int _tmain(int argc, _TCHAR* argv[])
{
char src[]="((1+2)*((34-2))+((2*8-1)";
char dst[MaxNum];
M_Bracket(src,dst);
puts(dst);
return 0;
}

大家如果觉得有问题,留言哦。我还是个菜鸟 d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值