题目要求
编写一个程序,它从标准输入(终端)读取C源代码,并验证所有的花括号都正确的成对出现。
注意:你不必担心注释内部、字符串常量内部和字符常量形式的花括号。
算法分析
我们先判断左花括号的数量是否相等。
如果左右花括号数量不等,肯定不成对!
如果左右花括号数量相等,一定就成对吗???
好像也不一定。
我们来举例分析一下,左右花括号相等时可能会出现的情况:
1.{{{{{}}}}}(匹配)
2.{}{}{}{}{}(匹配)
...
3.}}}}}{{{{{(不匹配)
4.{{{{}}}}}{(不匹配)
......
第1种情况和第2种情况,属于左右花括号数目相等且匹配的情况,所以我们不用分析。
第3种情况和第4种情况,属于左右花括号数目相等但不匹配的情况,因此我们需要找出它们的共同点.
稍加分析我们就可以得出以下结论:
当右花括号出现时,如果左花括号的数目小于右花括号数目时,左右花括号必然不匹配.
可能有人对以上结论不理解,在此我再来详细解释一下:
(如果你表示已理解结论,请直接跳转算法总结部分)
我们先来分析情况3:
当我们看到第一个右花括号时,发现它前面并没有左花括号.
因此情况3必然属于左右花括号不匹配的情况.
我们再来分析情况4:
我们看第1个右花括号,发现它前面有4个左花括号;
第2个右花括号,前面有4个左花括号
......
直到第5个右花括号,前面只有4个左花括号.
因此情况3也属于左右花括号不匹配的情况.
算法总结
根据上面的分析,我们得出如下结论:
判断左右花括号是否成对出现需要两个条件:
1.左右花括号数目必须相等.
2.当右花括号出现时,左花括号数目必须大于右花括号.
算法转程序
根据题目要求,首先我们需要从标准输入获得数据。
(不清楚这些函数功能的童鞋请直接点击函数名称)
scanf()函数和gets()函数都需要指定一个字符数组来做存储。
如果用这两个函数的话,那就必须得定义一个字符数组。
定义字符数组的话又会面临数组溢出或者浪费空间等问题。
(数组定义小了,可能会溢出;定义大了,又会浪费空间.)
而getchar()函数每次只能从控制台接受一个字符,因此我们需要用循环来操作。
所以,我们用getchar()函数通过循环操作,从标准输入获得数据。
于是便可以完成这样的代码:
//定义一个整型变量用来接收控制台数据
int ch = 0;
//提示信息
printf("请输入一段字符以ctrl+z结束:\n");
//从控制台读入字符并判断是否满足循环条件。
while((ch=getchar())!=EOF){
...//判断左右花括号是否匹配的代码
}
接下来我们开始写分析左右花括号是否匹配的代码。
根据,算法总结,我们可以设置两个int型变量left和right,分别用来记录左花括号的数量和右花括号的数量。
如果遇到左花括号,则left++;
如果如果遇到右花括号,我们首先得判断左花括号的数目是否大于右花括号,right++;否则直接退出。
//定义一个整型变量用来接收控制台数据
int ch = 0;
//定义一个整型变量用来计算左花括号数目
int left = 0;
//定义一个整型变量用来计算右花括号数目
int right = 0;
//提示信息
printf("请输入一段字符以ctrl+z结束:\n");
//从控制台读入字符并判断是否满足循环条件。
while((ch=getchar())!=EOF){
//遇到左花括号,left+1
if(ch==’{’){
left++;
}
//遇到右花括号
if(ch==’}’){
//左花括号数目大于右花括号数目right+1
if(left>right){
right++;
}else{
//否则就是这种情况
//{{{{}}}}}{
//}}}}}{{{{{
//.....
//直接退出程序
printf("不匹配!\n");
return 0;
}
}
}
//如果程序能走到这里
//就已经排除}}}}{{{{这种特殊情况
//如果左花括号数目等于右花括号数目
if(right==left){
printf("匹配!\n");
}else{
printf("不匹配!\n");
}
最终的完整的代码如下:
#include
int main(){
//定义一个整型变量用来接收控制台数据
int ch = 0;
//定义一个整型变量用来计算左花括号数目
int left = 0;
//定义一个整型变量用来计算右花括号数目
int right = 0;
//提示信息
printf("请输入一段字符以ctrl+z结束:\n");
//从控制台读入字符并判断是否满足循环条件。
while((ch=getchar())!=EOF){
//遇到左花括号,left+1
if(ch==’{’){
left++;
}
//遇到右花括号
if(ch==’}’){
//左花括号数目大于右花括号数目right+1
if(left>right){
right++;
}else{
//否则就是这种情况
//{{{{}}}}}{
//}}}}}{{{{{
//.....
//直接退出程序
printf("不匹配!\n");
return 0;
}
}
}
//如果程序能走到这里
//就已经排除}}}}{{{{这种特殊情况
//如果左花括号数目等于右花括号数目
if(right==left){
printf("匹配!\n");
}else{
printf("不匹配!\n");
}
return 0;
}
程序优化
写到这里,好像就已经结束了?
其实....并没有!
在上述程序中,我们用了两个变量left和right来记录左右花括号数目。
其实,我们并不需要知道left和right具体的值.
因此,我们可以用一个变量来记录左右花括号的状态.
我们定义一个整型变量count.
如果遇到左花括号,count++;
如果遇到右花括号,判断count是否大于0,如果是count--,否则直接退出.
最终代码如下:
#include
int main(){
//定义一个整型变量用来接收控制台数据
int ch = 0;
//定义一个整型变量用来记录左右花括号的状态
int count = 0;
//提示信息
printf("请输入一段字符以ctrl+z结束:\n");
//从控制台读入字符并判断是否满足循环条件。
while((ch=getchar())!=EOF){
//遇到左花括号,count++
if(ch==’{’){
count++;
}
//遇到右花括号
if(ch==’}’){
//左花括号数目大于右花括号数目right+1
if(count>0){
count--;
}else{
//否则就是这种情况
//{{{{}}}}}{
//}}}}}{{{{{
//.....
//直接退出程序
printf("不匹配!\n");
return 0;
}
}
}
//如果程序能走到这里
//就已经排除}}}}{{{{这种特殊情况
//如果左花括号数目等于右花括号数目
if(count==0){
printf("匹配!\n");
}else{
printf("不匹配!\n");
}
return 0;
}
看了本篇文章,如果你还不会如何用C语言来验证花括号是否成对.....
请关注微信公众号gxdydd,在微信公众号下留言,有空我一定会回复的哦!
本文来自于高小调博客,如需转载,请注明出处!