zoukankan      html  css  js  c++  java
  • [杂记]BrainFuck语言及编译器(c++实现)

    BrainFuck语言

    极简的一种图灵完备的语言,由Urban Müller在1993年创造,由八个指令组成(如下表)。工作机制与图灵机非常相似,有一条足够长的纸带,初始时纸带上的每一格都是0,有一个数据读写头指向纸带的初始位置,读写头的行为由指令指示。

    指令 含义
    > 指针向右移动一位
    < 指针向左移动一位
    + 指针所指位置的值增加1字节
    - 指针所指位置的值减少1字节
    . 将指针所指位置的值按ASCII表输出
    , 接受1字节的输入,存储在当前指针所指位置
    [ 当指针当前处的值为0时,跳转到对应]之后;否则,顺序执行
    ] 跳转回对应[处

    用经典的Hello World!来举例说明BrainFuck语言的画风。

    ++++++++
    [
        >++++
        [
            >++
            >+++
            >+++
            >+
            <<<<-
        ]
        >+
        >+
        >-
        >>+
        [<]
        <-
    ]
    >>.
    >---.
    +++++++..+++.
    >>.
    <-.
    <.
    +++.------.--------.
    >>+.
    >++.

    其中的空格、缩进、换行都不影响程序,只是为了看起来可读性更强而已。事实上,上述程序完全可以写成这样:

    ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

    编译器实现(c++)

    写了两个版本,都差不多。第一个直接开始执行,会在从[跳转到]时向后遍历,时间稍长;第二个先做一次括号匹配,标记对应的括号位置,内存稍大(事实上,如果括号并不多,可以用STL的map来动态管理内存)。

    第一个:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 
      5 using namespace std;
      6 #define MaxCodeLen 1000                                     //代码最大长度
      7 #define MaxTapeLen 3000                                     //纸带最大长度
      8 
      9 char Code[MaxCodeLen];                                      //代码
     10 char Tape[MaxTapeLen];                                      //纸带
     11 int St[MaxCodeLen / 2];                                     //用来匹配括号的栈
     12 int top = 0;                                                //栈顶
     13 
     14 int isLegalInstruction(char ch)
     15 {
     16     int Ret = 0;
     17     switch(ch)
     18     {
     19         case '>' :
     20         case '<' :
     21         case '+' :
     22         case '-' :
     23         case '.' :
     24         case ',' :
     25         case '[' :
     26         case ']' : Ret = 1; break;
     27         case '
    ' :
     28         case ' ' :
     29         case '	' : Ret = 2; break;
     30         default : break;
     31     }
     32     return Ret;
     33 }
     34 
     35 int main()
     36 {
     37     freopen("Pro.txt", "r", stdin);
     38     char ch;
     39     int len = 0;
     40     int cur = 0;
     41     int i, cnt;
     42     char* p = Tape + MaxTapeLen / 2;                        //为了方便左右移动,让纸带从中间开始
     43     while((ch = getchar()) != EOF)
     44     {
     45         //printf("ch = %c
    ", ch);
     46         switch(isLegalInstruction(ch))
     47         {
     48             case 0 :
     49                 printf("illegal instruction
    ");
     50                 return 0;
     51             case 1 :
     52                 Code[len++] = ch;
     53                 break;
     54             default:
     55                 break;
     56         }
     57     }
     58     //Code[len] = '';
     59     //printf("%s
    ", Code);
     60     freopen("CON", "r", stdin);
     61     while(cur < len)
     62     {
     63         switch(Code[cur])
     64         {
     65             case '>' :
     66                 p++;
     67                 break;
     68             case '<' :
     69                 p--;
     70                 break;
     71             case '+' :
     72                 (*p)++;
     73                 break;
     74             case '-' :
     75                 (*p)--;
     76                 break;
     77             case '.' :
     78                 printf("%c", *p);
     79                 break;
     80             case ',' :
     81                 *p = getchar();
     82                 break;
     83             case '[' :
     84                 if(*p)
     85                 {
     86                     St[top++] = cur;
     87                 }
     88                 else
     89                 {
     90                     cnt = 0;
     91                     for(i = cur; i < len; i++)
     92                     {
     93                         if(Code[i] == '[')
     94                             cnt++;
     95                         if(Code[i] == ']')
     96                             cnt--;
     97                         if(!cnt)
     98                             break;
     99                     }
    100                     if(!cnt)
    101                     {
    102                         cur = i;
    103                     }
    104                     else
    105                     {
    106                         printf("parentheses do not match
    ");   //左括号比右括号多
    107                         return 0;
    108                     }
    109                 }
    110                 break;
    111             case ']' :
    112                 cur = St[top - 1] - 1;
    113                 top--;
    114                 break;
    115             default:
    116                 break;
    117         }
    118         cur++;
    119         if(top < 0)
    120         {
    121             printf("parentheses do not match
    ");               //右括号比左括号多
    122             return 0;
    123         }
    124     }
    125     printf("
    ");
    126     return 0;
    127 }
    View Code

    第二个:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 
      5 using namespace std;
      6 #define MaxCodeLen 1000                                     //代码最大长度
      7 #define MaxTapeLen 3000                                     //纸带最大长度
      8 
      9 char Code[MaxCodeLen];                                      //代码
     10 char Tape[MaxTapeLen];                                      //纸带
     11 int St[MaxCodeLen / 2];                                     //用来匹配括号的栈
     12 int top = 0;                                                //栈顶
     13 int Match[MaxCodeLen];                                      //括号匹配
     14 
     15 int isLegalInstruction(char ch)
     16 {
     17     int Ret = 0;
     18     switch(ch)
     19     {
     20         case '>' :
     21         case '<' :
     22         case '+' :
     23         case '-' :
     24         case '.' :
     25         case ',' :
     26         case '[' :
     27         case ']' : Ret = 1; break;
     28         case '
    ' :
     29         case ' ' :
     30         case '	' : Ret = 2; break;
     31         default : break;
     32     }
     33     return Ret;
     34 }
     35 
     36 int main()
     37 {
     38     freopen("Pro.txt", "r", stdin);
     39     char ch;
     40     int len = 0;
     41     int cur, i, cnt;
     42     char* p = Tape + MaxTapeLen / 2;                        //为了方便左右移动,让纸带从中间开始
     43     while((ch = getchar()) != EOF)
     44     {
     45         //printf("ch = %c
    ", ch);
     46         switch(isLegalInstruction(ch))
     47         {
     48             case 0 :
     49                 printf("illegal instruction
    ");
     50                 return 0;
     51             case 1 :
     52                 Code[len++] = ch;
     53                 break;
     54             default:
     55                 break;
     56         }
     57     }
     58     //Code[len] = '';
     59     //printf("%s
    ", Code);
     60     for(i = 0; i < len; i++)
     61     {
     62         if(Code[i] == '[')
     63         {
     64             St[top++] = i;
     65         }
     66         else if(Code[i] == ']')
     67         {
     68             if(top <= 0)
     69             {
     70                 printf("parentheses do not match
    ");           //右括号比左括号多
     71                 return 0;
     72             }
     73             Match[i] = St[top - 1];
     74             Match[St[top - 1]] = i;
     75             top--;
     76         }
     77     }
     78     if(top > 0)
     79     {
     80         printf("parentheses do not match
    ");                   //左括号比右括号多
     81         return 0;
     82     }
     83     freopen("CON", "r", stdin);
     84     cur = 0;
     85     while(cur < len)
     86     {
     87         switch(Code[cur])
     88         {
     89             case '>' :
     90                 p++;
     91                 break;
     92             case '<' :
     93                 p--;
     94                 break;
     95             case '+' :
     96                 (*p)++;
     97                 break;
     98             case '-' :
     99                 (*p)--;
    100                 break;
    101             case '.' :
    102                 printf("%c", *p);
    103                 break;
    104             case ',' :
    105                 *p = getchar();
    106                 break;
    107             case '[' :
    108                 if(!(*p))
    109                 {
    110                     cur = Match[cur];
    111                 }
    112                 break;
    113             case ']' :
    114                 cur = Match[cur] - 1;
    115                 break;
    116             default:
    117                 break;
    118         }
    119         cur++;
    120     }
    121     printf("
    ");
    122     return 0;
    123 }
    View Code

    【也许有空了可以琢磨一下写个界面hhh】

    参考:https://en.m.wikipedia.org/wiki/Brainfuck

  • 相关阅读:
    [LeetCode] Best Time to Buy and Sell Stock
    [LeetCode] Generate Parentheses
    [LeetCode] Best Time to Buy and Sell Stock 2
    [CareerCup][Google Interview] 打印组合
    [微软][笔试] 找出最大序列对
    系统之间的接口测试
    进销存业务的自定义分解
    查找数据库中所有有自增列的用户表
    由创建文件想起的。。。
    反编译想到的代码安全问题
  • 原文地址:https://www.cnblogs.com/CQBZOIer-zyy/p/8979105.html
Copyright © 2011-2022 走看看