Skip to content

Instantly share code, notes, and snippets.

@7shi
Created August 16, 2010 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 7shi/527649 to your computer and use it in GitHub Desktop.
Save 7shi/527649 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
int main(int argc, char* argv[]) {
char heap[65536]; //メモリ
char* order = NULL; //実行する命令を保存する配列
unsigned short ptr = 0; //メモリのポインタ
int order_ptr = 0; //実行する命令を指すポインタ
int order_end = 0; //実行する命令の数を保存する
char *filename; //ファイル名を保存する
std::stack<int> loops; //ループ([)の先頭位置を保存するスタック
FILE* fp;
//配列の初期化
memset(heap, 0, sizeof(heap));
//コマンドライン引数が正しく設定されているのか、チェックする処理
if (argc != 2) {
printf("コマンドライン引数の数が不正です。1つのファイルを指定して下さい\n");
return 0;
}
//argvの第1引数から、ファイル名を取り出す
filename = argv[1];
//ファイルを開く
if (!(fp = fopen(filename, "rb"))) {
printf("ファイルを開けません\n");
exit(1);
}
//ファイルの内容を配列にコピー
//実行する命令の数をorder_endに代入する
if (fseek(fp, 0, SEEK_END) == 0) {
int size = ftell(fp);
if (fseek(fp, 0, SEEK_SET) == 0) {
order = new char[size];
order_end = fread(order, 1, size, fp);
}
}
fclose(fp);
//命令ポインタが指す値が、order_endに達しない限りループする
while(order_ptr < order_end) {
//配列の要素に従って、命令の分岐を行う
switch(order[order_ptr]) {
//Brainfuckの各命令の処理
case '>':
ptr++;
break;
case '<':
ptr--;
break;
case '+':
(heap[ptr])++;
break;
case '-':
(heap[ptr])--;
break;
case '.':
putchar(heap[ptr]);
break;
case ',':
heap[ptr]=getchar();
break;
//ループの先頭。命令ポインタの指す値が0である場合、ループの末尾にジャンプ
case '[':
loops.push(order_ptr);
//メモリのポインタが指す値が0なら、対応する]の直後までジャンプする。
//角括弧(])が見つかるまで、命令ポインタをインクリメントする。
if(heap[ptr] == 0) {
int depth = 1;
while (depth > 0) {
order_ptr++;
if (order_ptr >= order_end) {
printf("対応する ] がありません。\n");
return 1;
}
switch (order[order_ptr]) {
case '[': depth++; break;
case ']': depth--; break;
}
}
loops.pop();
}
break;
//ループの末尾。ループの先頭にジャンプ
case ']':
if (loops.size() == 0) {
printf("対応する [ がありません。\n");
return 1;
}
order_ptr = loops.top() - 1;
loops.pop();
break;
//空白類を検出した場合、スキップする
case '\r':
case '\n':
case '\t':
case '\v':
case '\f':
break;
//Brainfuckの言語仕様に含まれていない文字を検出した場合
default:
printf("\nファイルにBrainfuckの言語仕様で定められていない文字列が含まれています。\n");
printf("ファイルの内容を修正し、プログラムを実行し直してください。\n");
return 0;
}
//命令ポインタをインクリメントし、次の命令を実行できるようにする
order_ptr++;
}
//終了前の後処理。メモリの解放など。
if (order) delete [] order;
printf("\nbrainfuckの処理が終了しました\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment