C程序设计语言 练习1-24

① 练习描述

写一个检查圆括号()、方括号[]、花括号{}不匹配的初级错误的程序,不要忘记单双引号、转义序列、注释。(要想完全通用,程序将变得困难)

② 思路

1.首先要想办法标记一下导入的文本,用int c, s, line, para来标记在字符''、字符串""、行注释//、段注释/* */中,1为在其中,0为在其外。借助练习1-23的思路即可,即通过识别开头和结尾的字符来标记状态。我们无需讨论这些状态中的括号,!c && !s && !line && !para表示不在这些状态中,即正常文本内。

2.可将问题分为检查错误和显示错误两部分。

用row和col记录当前的位置,用二维数组errorinfo来记录错误出现的行列位置和错误类型,0、1、2分别为圆括号()、方括号[]、花括号{}不匹配。

3.检查错误:

以圆括号()为例子,用state作依据检查,初值为0。遇到'(',state++,遇到')',state--。正常情况下,state只可能有0或1两个值。

当遇到单独的')',state = -1,记录此时坐标(row, col)及错误类型到errorinfo里,然后state = 0归零;

当state = 2,即碰到( ( 连着来怎么办呢?我采取的办法是,用last记录上一次state = 1时的位置,即第一个( ,当state增加到2时,说明第一个( 不匹配,那么记录last到errorinfo里,然后state = 1重置为1,这样连着三个( ( ( 也能处理。

当读取结束EOF后,如果state = 1,说明仍有一个未匹配的括号,把last记录到errorinfo即可。

把state定义为state[3]就能同时存三种错误的state了,last也是last[3]。

4.显示错误:

由于errorinfo中记录的位置一般不是从小到大顺序排列的,所以先按行列排个序,然后显示出来。

5.不足:

如果有int main(){

                  }

          }

会把最后一行}当作错误。

#include<stdio.h>
#include<stdlib.h>
 
#define PARENTHESE_UNBALANCED   0   // error of unbalanced parentheses code: 0
#define BRACKET_UNBALANCED      1   // error of unbalanced brackets code: 1
#define BRACE_UNBALANCED        2   // error of unbalanced braces code: 2
#define MAXERROR                100 // max number of errors       

void sort(int s[MAXERROR][3], int len);
void errorprint(int row, int col, int errortype);

int main(void){
    char ch;                    // current character
    int i, j;
    int errorinfo[MAXERROR][3]; // save the info of errors, [][0] & [][1] mean position, [][2] means type of error
    int count;                  // count the errors
    int c, s, line, para;       // mark the state when in '', "", // and /* */
    int escape, slash, star;    // mark the \, / and *
    int row, col;               // current position
    int state[3], last[3][2];   // last[0/ 1/ 2][] means the last position of ( / [ / {
    
    count = 0;
    c = s = line = para = 0;    
    escape = slash = star = 0;  
    row = 1;
    col = 0;
    state[0] = state[1] = state[2] = 0;
    for(i = 0; i < MAXERROR; ++i){
        errorinfo[i][0] = errorinfo[i][1] = errorinfo[i][2] = 0;
    }

    // now read the code
    for(i = 0; (ch = getchar()) != EOF; ++i){
        // current position
        ++col;
        // change of state
        if(!c && !s && !line && !para){     // be not in quotes or comments
            switch(ch){
                case '(':   ++state[0]; break;
                case ')':   --state[0]; break;
                case '[':   ++state[1]; break;
                case ']':   --state[1]; break;
                case '{':   ++state[2]; break;
                case '}':   --state[2]; break;
                default:    break;
            }
        }
        // use state to judge errors and record their positions
        for(j = 0; j < 3; ++j){
            if(state[j] == -1){
                state[j] = 0;
                errorinfo[count][0] = row;
                errorinfo[count][1] = col;
                errorinfo[count][2] = j;
                ++count;
            }
            if(state[j] == 2){
                state[j] = 1;
                errorinfo[count][0] = last[j][0];
                errorinfo[count][1] = last[j][1];
                errorinfo[count][2] = j;
                ++count;
            }
        }
        // record the last position of ( / [ / {
        if(state[0] == 1 && ch == '('){
            last[0][0] = row;
            last[0][1] = col;
        }
        if(state[1] == 1 && ch == '['){
            last[1][0] = row;
            last[1][1] = col;
        }
        if(state[2] == 1 && ch == '{'){
            last[2][0] = row;
            last[2][1] = col;
        }
        /* below are current states of code */
        // in ''?        
        if(ch == '\'' && c && escape == 0){
            c = 0;
        }
        else if(ch == '\'' && !c && !s && !line && !para){
            c = 1;
        } 
        // in ""?
        if(ch == '"' && s && escape == 0){
            s = 0;
        }
        else if(ch == '"' && !c && !s && !line && !para){
            s = 1;
        }
        // in line comment //?
        if(line && ch == '\n'){
            line = 0;
        }
        else if(!c && !s && !line && !para && ch == '/' && slash == 1){
            line = 1;
        }        
        // in paragraph comment /* */?
        if(para && ch == '/' && star == 1){
            para = 0;
        }
        else if(!c && !s && !line && !para && ch == '*' && slash == 1){
            para = 1;
        }
               
        // mark escape sequence
        if(ch == '\\'){
            if(escape == 1){
                escape = 0;
            }
            else escape = 1;
        }
        else escape = 0;
        // mark the * in paragraph comment
        if(para && ch == '*' && slash == 0){
            star = 1;
        }
        else star = 0; 
        // mark the first /
        if(!c && !s && !line && !para && ch == '/'){
            slash = 1;
        }
        else slash = 0;  
        // newline if read the '\n'
        if(ch == '\n' && !c && !s && !line){
            ++row;
            col = 0;
        }   
    }
    // in the end, state should be 0, which means balanced
    for(j = 0; j < 3; ++j){
        if(state[j] == 1){
            errorinfo[count][0] = last[j][0];
            errorinfo[count][1] = last[j][1];
            errorinfo[count][2] = j;
            ++count;
        }
    }
    // now sort all the errors recorded by rows and cols
    sort(errorinfo, count);
    // now print all the errors recorded
    printf("Here are your errors:\n");
    for(i = 0; i < count; ++i){
        errorprint(errorinfo[i][0], errorinfo[i][1], errorinfo[i][2]);
    }

    system("pause");
    return 0;
}

void sort(int s[MAXERROR][3], int len){
    int i, j, min;
    int temp[3];
  
    for(i = 0; i < len; ++i){
        min = i;
        for(j = i + 1; j < len; ++j){
            if(s[j][0] < s[min][0]){
                min = j;
            }
            else if(s[j][0] == s[min][0]){
                if(s[j][1] < s[min][1]){
                    min = j;
                }               
            }
        }
        if(min != i){
            temp[0] = s[min][0];
            temp[1] = s[min][1];
            temp[2] = s[min][2];
            s[min][0] = s[i][0];
            s[min][1] = s[i][1];
            s[min][2] = s[i][2];
            s[i][0] = temp[0];
            s[i][1] = temp[1];
            s[i][2] = temp[2];
        }
    }
}

void errorprint(int row, int col, int errortype){
    printf("ERROR(行 %3d 列 %2d):", row, col);
    switch (errortype){
        case PARENTHESE_UNBALANCED:
            printf("圆括号不匹配。\n");
            break;
        case BRACKET_UNBALANCED:
            printf("方括号不匹配。\n");
            break;
        case BRACE_UNBALANCED:
            printf("花括号不匹配。\n");
            break;
        default:
            break;
    }
}

 运行示例:

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

int main((void)){
    (char c] = '*';
    int i;

    }i = 10;
    if(10 == '\n' && i){     // 说明在运算时,'\n'被当作10
        [printf("%c%d,hello,world\n\"\n", c, !i);
    }
    system("pause");
    return 0;
}
^Z
Here are your errors:
ERROR(行   4 列  9):圆括号不匹配。
ERROR(行   4 列 16):圆括号不匹配。
ERROR(行   5 列  5):圆括号不匹配。
ERROR(行   5 列 12):方括号不匹配。
ERROR(行  10 列  9):方括号不匹配。
ERROR(行  14 列  1):花括号不匹配。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值