Last active
October 3, 2016 13:59
-
-
Save TonyMooori/6d161e7325f10cd3c34640fbf81e35d0 to your computer and use it in GitHub Desktop.
Brainfuckを実行するプログラム.コマンドライン引数でソースコードの入ったファイルを指定する.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <stack> | |
| #include <cstdio> | |
| #include <cstdlib> | |
| // メモリー(配列)の数 | |
| #define N_BYTE 8192 | |
| using namespace std; | |
| // 指定したファイルからコードを読み込む関数 | |
| string read_code(char *filename); | |
| // コードを評価する関数 | |
| void eval(string code); | |
| int main(int argc,char *argv[]){ | |
| // ファイルはコマンドライン引数で指定する | |
| if( argc <= 1 ){ | |
| cout << "Error:" << "\t" << "No inputs files" << endl; | |
| cout << "example:>> main.exe bf_code.txt" << endl; | |
| exit(0); | |
| } | |
| // コードを読み取る | |
| string code = read_code(argv[1]); | |
| // 評価する | |
| eval(code); | |
| return 0; | |
| } | |
| // 指定したファイルからコードを読み込む関数 | |
| string read_code(char *filename){ | |
| string ret = ""; | |
| char c; | |
| FILE *fp; | |
| // とりあえず開き,開けなかったらエラーを表示して終了 | |
| fp = fopen( filename , "r" ); | |
| if( fp == NULL ){ | |
| cout << "Error:" << "\t" << filename << ":\t" << "No such file." << endl; | |
| exit(0); | |
| } | |
| // 1文字ずつ読み取る | |
| while( true ){ | |
| c = getc(fp); | |
| if( c == EOF )break; | |
| ret += c; | |
| } | |
| fclose(fp); | |
| return ret; | |
| } | |
| // コードを評価する関数 | |
| void eval(string code){ | |
| int index = 0; // 現在指し示す場所 | |
| uint8_t memory[ N_BYTE ] = {0}; // メモリー(配列) | |
| stack< int > pos_loop_start; // ループスタートの位置を保存 | |
| for(int i = 0 ; i < code.size() ; i++ ){ | |
| switch(code[i]){ | |
| case '>': | |
| index = (index+1+N_BYTE)%N_BYTE; // 一周して回ってくるようにする | |
| break; | |
| case '<': | |
| index = (index-1+N_BYTE)%N_BYTE; // 一周して回ってくるようにする | |
| break; | |
| case '+': | |
| memory[index]++; | |
| break; | |
| case '-': | |
| memory[index]--; | |
| break; | |
| case '.': | |
| putchar(memory[index]); | |
| break; | |
| case ',': | |
| memory[index] = getchar(); | |
| break; | |
| case '[': | |
| if( memory[index] == 0 ){ | |
| // 0ならば ] まで進む(コードが続く限り) | |
| int counter = 0; | |
| do{ | |
| if( code[i] == '[' ){ | |
| counter++; | |
| }else if( code[i] == ']' ){ | |
| if( counter == 0 ){ | |
| // ] が多い場合はエラー | |
| cout << "Error:" << "\t" << "Too much loop end command. ( \']\' )" << endl; | |
| exit(0); | |
| }else{ | |
| counter--; | |
| } | |
| } | |
| i++; | |
| }while( i < code.size() && counter != 0 ); | |
| i--; | |
| }else{ | |
| // 0で無ければその位置を保存 | |
| pos_loop_start.push(i); | |
| } | |
| break; | |
| case ']': | |
| if( pos_loop_start.empty() ){ | |
| // ] が多く,もとに戻る場所がない場合はエラーを表示して終了 | |
| cout << "Error:" << "\t" << "No loop start command. ( \'[\' )" << endl; | |
| exit(0); | |
| }else{ | |
| // [ の場所に戻る | |
| i = pos_loop_start.top() - 1; | |
| pos_loop_start.pop(); | |
| } | |
| break; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment