Skip to content

Instantly share code, notes, and snippets.

@TonyMooori
Last active October 3, 2016 13:59
Show Gist options
  • Select an option

  • Save TonyMooori/6d161e7325f10cd3c34640fbf81e35d0 to your computer and use it in GitHub Desktop.

Select an option

Save TonyMooori/6d161e7325f10cd3c34640fbf81e35d0 to your computer and use it in GitHub Desktop.
Brainfuckを実行するプログラム.コマンドライン引数でソースコードの入ったファイルを指定する.
#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