括号匹配(C语言问题,不要C++)

applepath 2006-06-28 03:55:52
【问题描述】
假设一个输入字符串中包含圆括号、方括号和花括号三种类型的括号,以及其它一些任意字符。编写程序,判别串中的括号是否正确匹配,即:
1. 各种左、右括号的个数要一致;
2. 要符合正确的嵌套规则。

【输入形式】
从当前目录下correct.in文件中读入一行字符串。字符串最大长度80,不含空格。

【输出形式】
输出到当前目录下correct.out文件中。输出只有一个单词,如果括号匹配则输出“True”到文件中,否则输出“False”。在输出末尾要有一个回车符。

【输入样例】
设输入文件内容如下:

rhe+[35(fjej)w-wr3f[efe{feofds}]

【输出样例】
输出文件内容为:

False

【样例说明】
输入字符串为rhe+[35(fjej)w-wr3f[efe{feofds}],在式中“[”与“]”的个数不一致,不符合嵌套规则,故输出为“False”。



#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define LEN 80


typedef struct list
{
char node;
struct list* next;
}list,*plist;

void iniList(plist);
int isEmpty(plist);
int listAppend(plist,char);
int delBracketsFormList(plist);

int main(int argc,char* argv[])
{
FILE *in,*out;
char test[LEN];
int i;
list a;
plist p;
p=&a;
iniList(p);


in=fopen("correct.in","r");
out=fopen("correct.out","w");


fscanf(in,"%s",test);

for (i=0;i<LEN;i++)
{
switch(test[i])
{
case '[':
case ']':
case '{':
case '}':
case '(':
case ')':
listAppend(p,test[i]);
break;
default:continue;
}
}
delBracketsFormList(p);
if (isEmpty(p))
{
fprintf(out,"True\n");
}
else
fprintf(out,"False\n");



fclose(in);
fclose(out);
return 0;
}



void iniList(plist aplist)
{
aplist->next=NULL;
aplist->node='\0';
}



int isEmpty(plist aplist)
{
return aplist->next==NULL?1:0;
}



int listAppend(plist aplist,char a)
{
plist bplist=aplist,anode;

while (bplist->next)
{
bplist=bplist->next;
}

anode=(plist)malloc(sizeof(list));

if (!anode)
exit(-1);
anode->node=a;
anode->next=NULL;
bplist->next=anode;
return 0;
}



int delBracketsFormList(plist aplist)
{
plist temp;
int has=1;
if (isEmpty(aplist))
return 0;

while(has)
{
has=0;
temp=aplist;
while (temp->next)
{
if(temp->next->next)
{
if((temp->next->next->node-temp->next->node==1)||(temp->next->next->node-temp->next->node==2))
{
temp->next = temp->next->next->next;
has=1;

}
else
temp = temp->next;
}
else
temp =temp->next;
if(!has)
break;
}

}
return 0;
}





老师说delBracketsFormList(plist)的算法有问题,不能正确处理(((2+3)*5)-6)的情况。
请朋友帮我看看要怎么改啊
...全文
5331 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
duanqiaoguhun 2010-06-08
  • 打赏
  • 举报
回复
一定要用堆栈吗?感觉这样好像有点复杂啊
TianChong 2006-06-29
  • 打赏
  • 举报
回复
作业题,鉴定完毕!
低调的小青蛙 2006-06-29
  • 打赏
  • 举报
回复
是酱紫的。如果用 C ,就应该使用一个 char 数组来作为 "栈"

char stack[200]; /* 栈空间 */
int size = 0; /* 入栈个数 */

char txt = "(((2+3)*5)-6)";

for(i=0; i<strlen(txt); i++)
{
char c = txt[i];

/* 遇到左括号 */
if( c == '(' || c == '[' || c == '{' )
{
stack[size] = c; /* stack push */
size ++;
}
/* 遇到右括号 */
else if( c == ')' )
{
/* 检查 stack 最后一个是否是 '(' */
if( size <= 0 || stack[size-1] != '(' )
return 失败;
else
size --; /* stack pop */
}
else if( c == ']' )
{
/* 检查 stack 最后一个是否是 '[' */
if( size <= 0 || stack[size-1] != '[' )
return 失败;
else
size --; /* stack pop */
}
else if( c == '}' )
{
/* 检查 stack 最后一个是否是 '{' */
if( size <= 0 || stack[size-1] != '{' )
return 失败;
else
size --; /* stack pop */
}
}

if(size == 0)
return 成功;
else
return 失败;
crazy_lazy_pig 2006-06-29
  • 打赏
  • 举报
回复
上面又打错了 这两天总是晕晕的.

左括号 右括号刚好说反, 把他们的位置换一下就对了.
crazy_lazy_pig 2006-06-29
  • 打赏
  • 举报
回复
呵呵, 开始以为左右括号数相等就可以了呢, 看来还是要那种欠套结构的, 那也很简单啊, 不过要比原来稍微复杂点:
那要用数组或者链表也可以, 其实应该说是堆栈, 在扫描表达式的时候, 见右括号, 则该右括号入栈, 见左括号, 则栈顶元素出栈, 比较类型, 一致则继续扫描, 不一致则退出报告说不匹配, 扫描结束若栈不空, 则不匹配, 否则匹配.

红龙宝典(dragon book)是国外比较经典的编译原理教材, 因封面画有一条龙而得名.
applepath 2006-06-29
  • 打赏
  • 举报
回复
是C语言的作业,还没学数据结构呢!下学期才开数据结构!
SilenceLeaf 2006-06-29
  • 打赏
  • 举报
回复
想必crazy_lazy_pig(疯狂懒猪)说的“红龙宝典”就是最牛的一本编译原理书吧,不知道是不是

我觉得用递归进行括号匹配是不是效率不高呢?就像用递归进行非波那次数列计算一样,很多的递归计算被浪费掉了

还是用栈最好,数据结构里面就是这么说的
zhaojiang 2006-06-29
  • 打赏
  • 举报
回复
看了"crazy_lazy_pig(疯狂懒猪)"的算法,非常赞同, 我的想法跟他一样, 只不过是求括号配对问题, 楼主是不是把问题复杂化了.
imdg 2006-06-29
  • 打赏
  • 举报
回复
这个是你们数据结构的作业是吧?栈这一节的?
伪码描述一下
while(!strEnd(str))
{
ch = getChar(str);
if(ch为左括号) //包括(,[,{
{
push(stack, ch);
}
else if(ch为右括号) //包括),],}
{
ch2 = peek(stack);
if(ch与ch2配对) //即ch==')' && ch2=='(' 或 ch==']' && ch2=='[' 等等
{
pop(stack);
if(上一步不成功)
{
不配对!!!
}
}
else
{
不配对!!!
}
}
}
if(stack不为空)
{
不配对!!!
}
低调的小青蛙 2006-06-29
  • 打赏
  • 举报
回复
搂主的思路是对的,不过

if(ch[i]==')') F=(t[--k]!=1);
if(ch[i]==']') F=(t[--k]!=10);
if(ch[i]=='}') F=(t[--k]!=100);

如果先遇到 "右括号" 的时候,就会有问题,因为 k=0 的时候, --k 等于 -1,会出现越界。

另外,搂主没有必要用 1,10,100 来代替 '(', '[', '{' ,直接用 char 作为栈就可以了。
applepath 2006-06-29
  • 打赏
  • 举报
回复
TianChong(VC.NET++) 不用鉴定,就是作业!嘿嘿!
applepath 2006-06-29
  • 打赏
  • 举报
回复
mLee79() 请问您这个是什么语言,我见过的语言少,不认识啊!那么多%
applepath 2006-06-29
  • 打赏
  • 举报
回复
请问各位大师如何结贴啊?怎么给分啊?是可以给好多人,还是只能给一个人啊????
crazy_lazy_pig 2006-06-29
  • 打赏
  • 举报
回复
to swimmer2000(人):
呵呵, 我其实确实是忘了业内人士都怎么称呼这本书了, 不过按我的理解, 翻译成红龙宝典更舒服一点, 原因有三:
1. 汉语里比较喜欢四字结构, 这样感觉气派 文雅
2. 翻译时最好兼顾音, 意两个方面, 你听: dragon book 和 "红龙宝点" 不是读起来很相似吗?
3. 那书的封面上本来就是条红龙嘛, 这又兼顾了"形".
swimmer2000 2006-06-29
  • 打赏
  • 举报
回复
to crazy_lazy_pig(疯狂懒猪)
红龙宝典叫龙书不是更好?
llmsn 2006-06-29
  • 打赏
  • 举报
回复
mark!
mLee79 2006-06-29
  • 打赏
  • 举报
回复
酱紫也可以:
#include <stdio.h>

int foobar( char* s )
{
char st[1024]; int cc = 0;
for( ; *s; ++s )
{
switch( *s )
{
case '{':st[cc++] = '}';break;
case '[':st[cc++] = ']';break;
case '(':st[cc++] = ')';break;
case ')':case '}':case ']': if( !cc || st[--cc] != *s ) return 0;break;
}
}
return cc == 0;
}

int main()
{
FILE *ifs = NULL , *ofs = NULL;
char line[1024+1] = "";
ifs = fopen( "correct.in" , "r" );
ofs = fopen( "correct.out" , "w" );
if( ifs && ofs )
{
while(!feof(ifs))
{
if( fgets( line , sizeof(line)-1 , ifs ) )
fputs( foobar(line)?"True\n":"False\n" , ofs );
}
}
if(ifs)fclose( ifs );
if(ofs)fclose( ofs );
return 0;
}
mLee79 2006-06-29
  • 打赏
  • 举报
回复
这样子行不行 .......

$ cat correct.in;echo ----------------------; cat foo.y; yacc -ofoo.y.c foo.y; gcc -o foo foo.y.c ; ./foo;echo ---------------; cat correct.out
rhe+[35(fjej)w-wr3f[efe{feofds}]
rhe+[35(fjej)w-wr3f[efe{feofds}]]
1+1(x{-)}

----------------------
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* _curr_ptr = NULL;
void yyerror( const char* msg ) {}
int yylex()
{
if( strchr( "(){}[]" , *_curr_ptr ) )
return *_curr_ptr++;
return _curr_ptr++ , '*';
}
%}
%start foobar
%%
foobar : foo|foobar foo;
foo :'*'|'(' foobar ')'|'[' foobar ']'|'{' foobar '}';
%%
int main()
{
FILE *ifs = NULL , *ofs = NULL;
char line[ 1024 + 1 ] = "";
ifs = fopen( "correct.in" , "r" );
ofs = fopen( "correct.out" , "w" );
if( !ifs || !ofs ) exit(1);
while( !feof( ifs ) )
{
fgets( line , sizeof( line ) - 1 , ifs );
_curr_ptr = line;
fputs( yyparse() ? "False\n" : "True\n" , ofs );
}
return 0;
}
---------------
False
True
False
True
低调的小青蛙 2006-06-29
  • 打赏
  • 举报
回复
To cuibo1123(月满C楼) 兄,当然不是。比如:

( [ ) ]

能够符合 "是0",但嵌套不正确。
bo.cui 2006-06-29
  • 打赏
  • 举报
回复
???

不就是判断括号是不是成队吗??

一个字符一个字符的读入.
用个 int a[3];
switch(ch)
{
case '(': {a[0]++; break;}
case ')': {a[0]--; break;}
....
default :;
}
在看看a[n]里面是不是0

不是这样吗???
加载更多回复(14)

64,639

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧