C程序括号匹配检查

【问题描述】

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

注意:

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

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

3. 字符和字符串常量中不包含特殊的转义字符(\',\")

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

不匹配判断规则:

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

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

【输入形式】

打开当前目录下文件example.c,查体其括号是否匹配。

【输出形式】

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

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】

(){()}


【样例说明】

样例1:在注释部分和字符串中的括号不考虑,在将程序处理之后得到的括号序列是(){()),遇到右括号时与最近的左括号匹配,发现最后一个小括号和大括号不匹配。

样例2:处理之后的括号序列是(){(),在最后缺少了右大括号,那么应该输出与之相对应的左括号不匹配。

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

void ERROR(char b, int l, int *e)
{
	(*e)++;
	printf("without maching '%c' at line %d\n",b,l);
}

int main()
{
	FILE *fin;
	int tmp;
	int linenum[1000];
	char bracket_stack[500], bracket_w_stack[1000];
	int  iter_bstack = -1, iter_w_bstack = -1, error = 0, line = 1;
	fin = fopen("example.c", "r");
	if (fin == NULL) exit(1);
	for (;;)
	{
		tmp = fgetc(fin);
		if (tmp == EOF) break;
		else if (tmp == '\n') line++;
		else if (tmp == '"')
		{
			for (;;)
			{
				tmp = fgetc(fin);
				if(tmp=='\\') tmp = fgetc(fin);
				else if (tmp == '"') break;
			}
		}
		else if (tmp == '\'')
		{
			for (;;)
			{
				tmp = fgetc(fin);
				if (tmp == '\\') tmp = fgetc(fin);
				else if (tmp == '\'') break;
			}
		}
		else if (tmp == '/')
		{
			tmp = fgetc(fin);
			if (tmp == '/') 
			{// single-line comment 
				while ((tmp = fgetc(fin)) != '\n'); 
				line++;
			} 
			else if (tmp == '*')
			{// multi-line comment
				int flag = 0;
				tmp = fgetc(fin);
				if (tmp == '\n') line++;
				for (;;)
				{
					if (flag) break;
					while (tmp != '*') 
					{ 
						tmp = fgetc(fin); 
						if (tmp == '\n') line++;
					}
					tmp = fgetc(fin);
					if (tmp == '\n') line++;
					if (tmp == '/') flag = 1;
				}
			}
			else if (tmp == '(')
			{
				bracket_stack[++iter_bstack] = tmp;
				bracket_w_stack[++iter_w_bstack] = tmp;
				linenum[iter_bstack] = line;
			}
		}
		else if (tmp == '(' || tmp == '{')
		{
			bracket_stack[++iter_bstack] = tmp;
			bracket_w_stack[++iter_w_bstack] = tmp;
			linenum[iter_bstack] = line;
		}
		else if (tmp == ')')
		{
			bracket_w_stack[++iter_w_bstack] = tmp;
			linenum[iter_bstack] = line;
			int leap = 0;
			while (leap <= iter_bstack && bracket_stack[iter_bstack - leap] != '(') leap++;
			if (iter_bstack<0 || leap) ERROR(tmp, line, &error);
			if (leap <= iter_bstack)
			{
				int i;
				for (i = iter_bstack - leap; i < iter_bstack; i++)
				{
					bracket_stack[i] = bracket_stack[i + 1];
					linenum[i] = linenum[i + 1];
				}
				iter_bstack--;
			}
		}
		else if (tmp == '}')
		{
			bracket_w_stack[++iter_w_bstack] = tmp;
			linenum[iter_bstack] = line;
			int leap = 0;
			while (leap <= iter_bstack && bracket_stack[iter_bstack - leap] != '{') leap++;
			if (iter_bstack<0 || leap) ERROR(tmp, line, &error);
			if (leap <= iter_bstack)
			{
				int i;
				for (i = iter_bstack - leap; i < iter_bstack; i++)
				{
					bracket_stack[i] = bracket_stack[i + 1];
					linenum[i] = linenum[i + 1];
				}
				iter_bstack--;
			}
		}
		else continue;
	}
	bracket_w_stack[++iter_w_bstack] = '\0';
	while (!error && iter_bstack >= 0)
	{
		ERROR(bracket_stack[iter_bstack], linenum[iter_bstack], &error);
		iter_bstack--;
	}
	if(!error) printf("%s", bracket_w_stack);
	fclose(fin);
	return 0;
}

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值