M - 翻译布尔表达式(C语言版详细注释)

Description

大家都学过了布尔表达式的翻译,其中有一个拉链-回填技术,这次我们就练习这个技术。

Input

输入为一行字符串,例如: a < b or c < d and e < f

每个符号都用空格间隔。

其中逻辑运算符包含 and 和 or , 关系运算符包含 < 、> 、<= 、 >= 、== 、 != 。

Output

 假链跳到0,真链跳到1,表达式序号从100开始排。

Sample

Input 

a < b or c < d and e < f

Output 

100(j<,a,b,1)
101(j,_,_,102)
102(j<,c,d,104)
103(j,_,_,0)
104(j<,e,f,100)
105(j,_,_,103)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

/********************************
M - 翻译布尔表达式
时间:2021 - 5 - 5
注意事项:首先要注意 and  和 or 之间是存在优先级关系的
如果 or 和and 一起出现的话,那么 这个bool 表达式的假出口 一定是
在最后一个or后面(即全为假的时候),而这个bool表达式的真出口 4一定在
第一or的前面,因为or的话有一个为真其余全为真,接下来的关键就是找到这个位置,
即假出口和真出口的位置,所以无论真出口还是假出口都是遇到or 开始操作的 或者是
走到最后才进行的操作,为了能处理最后一个or后面的操作,所以需要一个结束的标志
这里我选择#,及遇到#号然后进行操作
********************************/

// 一个结构体队列用来存储 表达式
typedef struct{
    char left ; // 表达式左边的字符
    char right;  // 表达式右边的字符
    char op[4]  ; // 由于 op可以最大可以为 2个 , 为了 让其形成字符串,后面还要加一个 \0 故至少需要三个

}Queue;

int  top = 0 ; // 记录队列的起始位置
int cur = 0 ; // 记录队列的当前位置
int count = 100; // 记录 序列号
int TRUE  = 1  ; //记录真出口,真出口 一定是1 有上面的分析很容易得出
int FALSE  = 100  ;// 记录假出口 , 由于假出口一开始无法确定位置,所以先把假出口放到第一个位置,然后遍历找到真正的假出口

char str[100000] ; // 用来接收输入的字符串
char temp[5] ; // 记录临时数据
int tcount = 0;  // 临时数据表的指针


int main(){

    gets(str) ; // 从键盘上获得数据
    // 为 数据添加# 代表结束

    int len = strlen(str) ;
    str[len] = '#' ;
    str[len+1] = '\0' ;
    len = strlen(str) ;
    Queue s[100000] ;

    int  i = 0;
    // 遍历新补充好了的str 来获得 的数据
    for(;i<len ; i++){
            // 如果是空格就跳过
            if(str[i] == ' '){
                continue ;
            }
            else {
                temp[tcount++] = str[i] ; // 先将数据存入temp 中,然后在给s
                if(str[i] == '#'){
                    // 也就是最后 ,那么假出口一定在最后
                    FALSE = 0 ; // 其余情况不变化
                      for(;top<cur-1 ; top++){
                                // 由于最后一个and 连接的 表达式可以决定 真出口 ,这时就要分开进行讨论
                                printf("%d(j%s,%c,%c,%d)\n",count,s[top].op,s[top].left,s[top].right,count+2) ;
                                count++  ; //跳到下一条表达式上
                                //假出口
                                printf("%d(j,_,_,%d)\n",count,FALSE) ;

                                // 记录当前的假出口,方便回填
                                FALSE = count ;
                                count++ ;
                            }

                            // or前面的部分确定真出口
                            printf("%d(j%s,%c,%c,%d)\n",count,s[top].op,s[top].left,s[top].right,TRUE) ;
                             // 记录真出口方便回填
                            TRUE = count ;
                            count++  ; //跳到下一条表达式上

                            //假出口
                            printf("%d(j,_,_,%d)\n",count,FALSE) ;
                            count++ ;
                            // 将当前队列进行清空
                            top = cur ;
                                // 初始化temp
                            tcount = 0;
                            temp[tcount] = '\0' ;


                }
                if(tcount == 2){
                    temp[tcount] = '\0' ;
                    // 判断是否为or
                    if(strcmp(temp,"or") ==0){
                            // 由于假出口一定在or 后面
                            FALSE += 2  ;
                            // 遍历当前队列中的数据,即or 前面的数据,都是由and组成的
                            for(;top<cur-1 ; top++){
                                // 由于最后一个and 连接的 表达式可以决定 真出口 ,这时就要分开进行讨论
                                printf("%d(j%s,%c,%c,%d)\n",count,s[top].op,s[top].left,s[top].right,count+2) ;
                                count++  ; //跳到下一条表达式上
                                //假出口
                                printf("%d(j,_,_,%d)\n",count,FALSE) ;

                                // 记录当前的假出口,方便回填
                                FALSE = count ;
                                count++ ;
                            }

                            // or前面的部分确定真出口
                            printf("%d(j%s,%c,%c,%d)\n",count,s[top].op,s[top].left,s[top].right,TRUE) ;
                            // 记录真出口方便回填
                            TRUE = count ;
                            count++  ; //跳到下一条表达式上

                            //假出口
                            printf("%d(j,_,_,%d)\n",count,FALSE) ;
                            // 可能大家会在这儿疑惑 ,为什么上面回填 FALSE ,这儿就不回填FLASE
                            // 原因是 其实这里的FALSE 实际上是的前的and表达式构成的假出口
                            count++ ;
                            // 将当前队列进行清空
                            top = cur ;

                            // 初始化temp
                            tcount = 0;
                            temp[tcount] = '\0' ;

                    }
                    else {
                        continue  ;
                    }
                }
                else if(tcount == 3){
                    //判断是否为and ,或者三个字符长度的表达式
                    temp[tcount] = '\0' ;
                    if(strcmp(temp,"and") == 0){
                        FALSE +=2;  // 遇到一个and 假出口就加2
                        // 初始化 temp
                        tcount = 0;
                        temp[tcount] = '\0' ;
                    }
                    else if(str[i] != '=') {
                            //  如果不是 = 的话,说明当前的表达式 是一个长度为3 的表达式,然后将其放入队列中
                            s[cur].left = temp[0] ;
                            s[cur].right = temp[2] ;
                            temp[0] = temp[1] ;
                            temp[1] = '\0' ;
                            strcpy(s[cur].op,temp) ;
                            cur++ ;
                            // 初始化temp
                            tcount = 0;
                            temp[tcount] = '\0' ;
                    }
                    else {
                        continue;
                    }
                }
                else if(tcount == 4){
                        //这种情况必是表达式
                        s[cur].left = temp[0] ;
                        s[cur].right = temp[3] ;
                        temp[0] = temp[1] ;
                        temp[1] = temp[2] ;
                        temp[2] = '\0' ;
                        strcpy(s[cur].op,temp) ;
                        cur++ ;
                        // 初始化temp
                        tcount = 0;
                        temp[tcount] = '\0' ;

                }
            }

    }



    return 0 ;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值