#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define max_stack_size 1000
typedef struct stack
{
char data[max_stack_size];
int top;
}stack;
void initstack(stack* s)
{
s->top = -1;
}
int isempty(stack* s)
{
return s->top == -1;
}
int isfull(stack* s)
{
return s->top == max_stack_size - 1;
}
void push(stack* s, char c)
{
if (isfull(s))
{
printf("栈溢出\n");
exit(EXIT_FAILURE);
}
s->data[++s->top] = c;
}
char pop(stack* s)
{
if (isempty(s))
{
printf("栈下溢");
exit(EXIT_FAILURE);
}
return s->data[s->top--];
}
char peek(stack* s)
{
if (isempty(s))
{
return '\0';
}
return s->data[s->top];
}
int ismatchingpair(char open, char close)
{
return (open == '(' && close == ')') ||
(open == '[' && close == ']') ||
(open == '{' && close == '}');
}
int checkbrackets(FILE* fp)
{
stack stack;
initstack(&stack);//初始化
int ch;
int prev = '\0';
int line = 1;//当前的行号
int state = 0;
while ((ch = fgetc(fp)) != EOF)
{
int prve = '\0';
switch (state)
{
case 0://正常代码
if (ch == '"')
{
state = 1;//开始字符串
}
else if (ch == '\'')//开始字符如:'a'
{
state = 2;
}
else if (ch == '/')
{
int next = fgetc(fp);//可能是注释的开始
if (next == '*')
{
state = 3;//多行注释如:/*hahha*/
}
else if (next == '/')
{
state = 4;//单行注释
}
else
{
ungetc(next, fp);
}
}
else if (ch == '(' || ch == '[' || ch == '{')
{
push(&stack, ch);
}
else if (ch == ')' || ch == ']' || ch == '}')
{
if (isempty(&stack))
{
printf("错误:多余的右括号‘%c’出现在第%d行\n", ch, line);
return 0;
}
char top = pop(&stack);
if (!ismatchingpair(top, ch)) {
printf("错误:括号不匹配 '%c' 和 '%c' 在第 %d 行\n", top, ch, line);
return 0;
}
}
break;
case 1:
//在字符串中
if (ch == '"'&& prev !='\\')
{
state = 0;//字符串结束
}
else if (ch == '\\')
{//转义字符
fgetc(fp);
}
break;
case 2://在字符常量中
if (ch == '\'')
{
state = 0;
}
else if (ch == '\\')
{//转义字符
fgetc(fp);
}
break;
case 3:
if (ch == '*' && (fgetc(fp) == '/'))
{//多行注释
state = 0;
}
else if (ch == '\n')
{
line++;//处理换行
}
break;
case 4://单行注释中
if (ch == '\n')
{
state = 0;
line++;
}
break;
}
prev = ch;
if (ch == '\n')
{
line++;//更新当前行数
}
}
if (!isempty(&stack))
{
printf("错误:缺少右括号‘%c,未闭合的括号出现在前面代码中\n", peek(&stack));
return 0;
}
return 1;//所有的括号匹配成功
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("用法:%s<源代码文件.c>\n", argv[0]);
return 1;
}
FILE* fp;
if (fopen_s(&fp, argv[1], "r") != 0 || fp == NULL) {
perror("无法打开文件");
return 1;
}
printf("正在检查文件:%s\n", argv[1]);
if (checkbrackets(fp))
{
printf("所有的括号匹配成功,语法正确\n");
}
else
{
printf("括号存在不匹配问题\n");
}
fclose(fp);
return 0;
}