北航第四次作业——C程序括号匹配检查

【问题描述】

编写一程序检查C源程序文件中{}、()等括号是否匹配,并输出第一个检测到的不匹配的括号及所对应括号所在的行号(程序中同一类括号只有一个不匹配)。

注意:

1.除了括号可能不匹配外,输入的C源程序无其它语法错误。

2.字符常量、字符串常量及注释中括号不应被处理,注释包括单行注释//多行/* */注释

3.字符常量和字符串常量中不包含转义字符\'和\"

4.程序中出现有意义括号的个数不超过200个;

不匹配判断规则:

1.当检测的程序括号为'{'时,若其前序尚未匹配的括号为'('时,输出该'('左括号及所在行号; 

2.当遇到一个不匹配的右括号')'或'}'时,输出该右括号及所在行号;

3.当程序处理完毕时,还存在不匹配的左括号时,输出该左括号及所在行号。

【输入形式】

打开当前目录下文件example.c,查询其括号是否匹配。该文件中每行字符数不超过200

【输出形式】

若存在括号不匹配时,应输出首先能判断出现不匹配的括号及其所在的行号。当出现括号不匹配时,按下面要求输出相关信息:

without maching <x> at line <n>

其中<x>为‘{’, ‘}’, ‘(’, ‘)’等符号,<n>为该符号所在的行号。

若整个程序括号匹配,则按下面所示顺序输出括号匹配情况,中间没有空格。

(){(()){}}

【样例输入1】

若当前目录下输入文件example.c中内容如下:

#include<stdio.h>

int main(){

printf("{ hello world }\n"); // }

)

【样例输出1】

without maching ')' at line 4

【样例输入2】

若当前目录下输入文件example.c中内容如下:

#include<stdio.h>

int main(){

printf("{ hello world }d\n"); /* }*/

【样例输出2】

without maching '{' at line 2

【样例输入3】

若当前目录下输入文件example.c中内容如下:

#include<stdio.h>

int main(){

printf("{ hello world }d\n"); /* }*/

}

【样例输出3】

(){()}

本人语文理解能力比较差,在老师和同学的帮助下才勉勉强强读懂了题(wwww~

#include <stdio.h>
#include <string.h>
#define M 200 
typedef struct node{
	char ch;
	int line;
}Node;
int main()
{
	struct node STACK[M];
	FILE *fp;
	char s[201],c[201];
	int flag=0,len,line=0,i,top=-1,j=0,temp;
	fp=fopen("example.c","r");
	while(fgets(s,200,fp)!=NULL)
	{
		line++;
		len=strlen(s);
		if(flag==1)//多行注释:flag为1,说明在这一行之前的几行里有/*,此处是为了找到多行注释的代码。 
		{
			for(i=0;i<len;i++)
			{
				if(s[i]=='*'&&s[i+1]=='/')
				{
					flag=0;
					i=i+2;
					break;
				}
			}
		}
		else
		{
			i=0;//初始化为0,如果之前有过寻找*/则不用初始化,因为要在*/后面接着找。 
		}
		for(;i<len;i++)
		{
			if(s[i]=='\n')
			{
				break;
			}
			else if(s[i]=='/')
			{//又分两种情况 
				if(s[i+1]=='/')
				{
					break;//即读到//,直接跳出循环 
				}
				else if(s[i+1]=='*')
				{//必须要找到对应的*/ 
					for(i=i+2;i<len;i++)
					{
						if(s[i]=='*'&&s[i+1]=='/')
						{
							flag=0;
							i=i+2;
							break;
						}
					}
					if(i>=len)//这行行没找到对应的*/,跳出循环,继续看下一行 
					{
						break;
					}
				}
			}
			else if(s[i]=='"')
			{//对于引号,即字符常量、字符串常量的处理 
				for(i=i+1;i<len;i++)
				{
					if(s[i]=='"')
					{
						break;
					}
				}
			}
			else if(s[i]=='('||s[i]=='{')
			{//入栈 
				c[j]=s[i];
				j++;
				top++;
				STACK[top].ch=s[i];
				STACK[top].line=line;
			}
			else if(s[i]==')'||s[i]=='}')
			{//判断是否匹配,若匹配则出栈,不匹配则输出。 
				if(s[i]==')')
				{
					if(top==-1)
					{//空栈 
						printf("without maching ')' at line %d\n",line);
						return 0;
					}
					else 
					{
						if(STACK[top].ch=='(')
						{//匹配 
							c[j]=')';
							j++;
							top--;
						}
						else
						{//虽然不匹配,但要进一步判断前面是否匹配
						//例如:{(},应输出( 
							for(temp=top;temp>=0;temp--)
							{
								if(STACK[temp].ch=='(')
								{
									printf("without maching '%c' at line %d\n",STACK[top].ch,STACK[top].line);
									return 0;
								}
							}
							//找到不到对应匹配的括号 
							printf("without maching ')' at line %d\n",line);
							return 0;
						}
					}
				}
				else
				{
					if(top==-1)
					{
						printf("without maching '}' at line %d\n",line);
						return 0;
					}
					else 
					{
						if(STACK[top].ch=='{')
						{
							c[j]='}';
							j++;
							top--;
						}
						else
						{
							for(temp=top;temp>=0;temp--)
							{
								if(STACK[temp].ch=='{')
								{
									printf("without maching '%c' at line %d\n",STACK[top].ch,STACK[top].line);
									return 0;
								}
							}
							printf("without maching '}' at line %d\n",line);
							return 0;
						}
					}
				}
			}
		}
		//重置s 
		memset(s,'0',200);
	}
	//最后再判断栈是否为空,不为空则输出 
	c[j]='\0';
	if(top!=-1)
	{
		do
		{
			printf("without maching '%c' at line %d\n",STACK[top].ch,STACK[top].line);
			return 0; 
		}while(--top!=-1);
	}
	else if(top==-1)
	{//全部匹配,则输出括号序列 
		printf("%s",c);
	}
	return 0;
 } 

要说的都写在代码注释里了。最后,因为教材上提供了本题的核心思路,所以写起来相对容易,较难的地方在于不同层级的逻辑关系比较复杂,嵌套比较多。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值