3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++11でBrainf*ck【Better C】

Last updated at Posted at 2018-09-08

#Brainf*ckとは

以下の命令によって動く言語です。

  1. > ポインタをインクリメントする。ポインタをptrとすると、C言語の「ptr++;」に相当する。
  2. < ポインタをデクリメントする。C言語の「ptr--;」に相当。
  3. + ポインタが指す値をインクリメントする。C言語の「(*ptr)++;」に相当。
  4. - ポインタが指す値をデクリメントする。C言語の「(*ptr)--;」に相当。
  5. . ポインタが指す値を出力に書き出す。C言語の「putchar(*ptr);」に相当。
  6. , 入力から1バイト読み込んで、ポインタが指す先に代入する。C言語の「*ptr=getchar();」に相当。
  7. [ ポインタが指す値が0なら、対応する ] の直後にジャンプする。C言語の「while(*ptr){」に相当。
  8. ] ポインタが指す値が0でないなら、対応する [ (の直後[1])にジャンプする。C言語の「}」に相当[2]。
    (引用: Wikipedia Brainfuck)

使用する命令が8個しかないのが非常に特徴的ですね。
では、実装していきましょう。

#ソースコード(Visual C++)

Source.cpp
#include <cstdio>
#include <cstdint>
#include <string>

int main(int argc, char *argv[])
{
	//ファイルが指定されていない時のエラー処理
	if (argc != 2) {
		std::printf("開くファイルを指定してください。\n");
		return -1;
	}
	//ファイルが開けない時のエラー処理
	std::FILE *fp = nullptr;
	if (fopen_s(&fp, argv[1], "r")) {
		std::printf("ファイルを開くことが出来ません。\n");
		return -1;
	}

	//コードを読み取って格納
	char read_char;
	std::string code{};
	while ((read_char = std::fgetc(fp)) != EOF) {
		code.push_back(read_char);
	}
	std::fclose(fp);

	//コードを処理
	constexpr std::size_t buffer_size = 30000;
	char buffer[buffer_size]{};
	std::size_t buffer_ptr = 0;
	std::int_fast32_t loop = 0;

	const std::size_t code_len = code.size();
	for (std::size_t code_ptr = 0; code_ptr < code_len; ++code_ptr) {

		switch (code[code_ptr]) {
		case '>':++buffer_ptr; break;
		case '<':--buffer_ptr; break;
		case '+':++buffer[buffer_ptr]; break;
		case '-':--buffer[buffer_ptr]; break;
		case '.':std::putchar(buffer[buffer_ptr]); break;
		case ',':buffer[buffer_ptr] = std::getchar(); break;
		case '[':
			if (buffer[buffer_ptr] != 0) break;
			for (++code_ptr; loop > 0 || code[code_ptr] != ']'; ++code_ptr) {
				if (code[code_ptr] == '[') ++loop;
				if (code[code_ptr] == ']') --loop;
			}
			break;
		case ']':
			if (buffer[buffer_ptr] == 0) break;
			for (--code_ptr; loop > 0 || code[code_ptr] != '['; --code_ptr) {
				if (code[code_ptr] == ']') ++loop;
				if (code[code_ptr] == '[') --loop;
			}
			--code_ptr;
			break;
		}
	}
	return 0;
}

#ソースコード(その他 C++)

Source.cpp
#include <cstdio>
#include <cstdint>
#include <string>

int main(int argc, char *argv[])
{
	//ファイルが指定されていない時のエラー処理
	if (argc != 2) {
		std::printf("開くファイルを指定してください。\n");
		return -1;
	}
	//ファイルが開けない時のエラー処理
	std::FILE *fp = nullptr;
	if ((fp = std::fopen(argv[1], "r")) == nullptr) {
		std::printf("ファイルを開くことが出来ません。\n");
		return -1;
	}

	//コードを読み取って格納
	char read_char;
	std::string code{};
	while ((read_char = std::fgetc(fp)) != EOF) {
		code.push_back(read_char);
	}
	std::fclose(fp);

	//コードを処理
	constexpr std::size_t buffer_size = 30000;
	char buffer[buffer_size]{};
	std::size_t buffer_ptr = 0;
	std::int_fast32_t loop = 0;

	const std::size_t code_len = code.size();
	for (std::size_t code_ptr = 0; code_ptr < code_len; ++code_ptr) {

		switch (code[code_ptr]) {
		case '>':++buffer_ptr; break;
		case '<':--buffer_ptr; break;
		case '+':++buffer[buffer_ptr]; break;
		case '-':--buffer[buffer_ptr]; break;
		case '.':std::putchar(buffer[buffer_ptr]); break;
		case ',':buffer[buffer_ptr] = std::getchar(); break;
		case '[':
			if (buffer[buffer_ptr] != 0) break;
			for (++code_ptr; loop > 0 || code[code_ptr] != ']'; ++code_ptr) {
				if (code[code_ptr] == '[') ++loop;
				if (code[code_ptr] == ']') --loop;
			}
			break;
		case ']':
			if (buffer[buffer_ptr] == 0) break;
			for (--code_ptr; loop > 0 || code[code_ptr] != '['; --code_ptr) {
				if (code[code_ptr] == ']') ++loop;
				if (code[code_ptr] == '[') --loop;
			}
			--code_ptr;
			break;
		}
	}
	return 0;
}

#出力

h.bf
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
------------.<++++++++.--------.+++.------.--------.>+.
出力
$ brainc.exe h.bf
Hello, World!

#他言語での実装

コンパイラ・インタプリタ、ともに載せています。
Rust >> brainf*ck
Javascript >> シラミ騒動で Brainf**k
D言語 >> D言語でBrainf
C# >> Brainf*ck .NET
Ruby >> Brainfck | RubyでBrainfckのコードを生成する
Ruby >> brainf*ckを書いてみた
JavaScript >> Node.jsでPEG.jsでBrainf*ck
C >> c言語でBrainf*ckインタプリタ
D >> D言語でBrainf*ckコンパイル時コンパイラを作ろう
JavaScript >> JavaScriptでBrainF*ckインタプリタを実装する
解説 >> 今すぐBrainf*ckを始めるべき10の理由

##ソースコードのライセンス

These codes are licensed under CC0.
CC0

ソースコードは自由に使用してください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?