Created
August 16, 2010 20:15
-
-
Save 7shi/527649 to your computer and use it in GitHub Desktop.
This file contains 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 <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