ググるとSystem.Drawing.Graphics.MeasureString()を用いた方法がHITしますが、これでは誤差が出るので悩んでいる人を掲示板のログ等で見かけます。
僕も同じことをやろうとして調べてみたのですが、
System.Windows.Forms.TextRenderer.MeasureText()メソッドを用いると誤差なく描画サイズの取得が出来ました。
ググるとSystem.Drawing.Graphics.MeasureString()を用いた方法がHITしますが、これでは誤差が出るので悩んでいる人を掲示板のログ等で見かけます。
僕も同じことをやろうとして調べてみたのですが、
System.Windows.Forms.TextRenderer.MeasureText()メソッドを用いると誤差なく描画サイズの取得が出来ました。
これは使いやすいと思います。常駐しないで、壁紙に付箋を埋め込んで終了するのでメモリにやさしいです。また、使用方法の単純さは同種のソフトの中でもダントツだと思います。
自分で気に入ってしまった…。
唐突ですが、ちょっとやってみたくなったんです。
まずはインタプリタ
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
class Program {
static void Main(string[] args) {
if(args.Length == 0) {
Console.WriteLine("ソースファイルを指定して下さい。");
return;
}
int memorySize = 256; /**************************************************
*BrainFuckコードの実行に割り当てるメモリーサイズ。*
*実行するコードに対して充分な大きさが必要。 *
**************************************************/
//ヘルプの表示
if(args[0].ToLower().Contains("help") || args[0].ToLower().Contains("?")) {
Console.WriteLine(
@"bfi [ドライブ:][パス]ファイル名[メモリサイズ]
メモリサイズ プログラム実行の為に確保するメモリのサイズです。充分なサイズを指定して下さい。
大き過ぎても落ちるかも…。規定値は256。");
Console.ReadLine();
return;
}
//ソースファイルの読み込み*/
string src;
string srcFile = Environment.CurrentDirectory + "\\" + args[0];
if(File.Exists(args[0])) {
srcFile = args[0];
} else if(!File.Exists(srcFile)) {
Console.WriteLine("ソースファイルがありません。");
return;
}
using(System.IO.StreamReader sr = new System.IO.StreamReader(srcFile, Encoding.GetEncoding("Shift-Jis"))) {
src = sr.ReadToEnd();
sr.Close();
}
//コマンドラインオプションパーサ
if(args.Length > 1) {
if(!int.TryParse(args[1], out memorySize)) {
Console.WriteLine("メモリサイズの指定が正しくありません。");
return;
}
}
brainFuck(src, memorySize);
#if DEBUG
while(true) {
Console.ReadLine();
}
#endif
}
unsafe static void brainFuck(string src, int memorySize) {
/*メモリーの確保と初期化*/
byte* point = stackalloc byte[memorySize];
byte* tmp = point;
for(int i = 0; i < memorySize; i++) {
*(tmp + i) = 0;
}
//実行
for(int i = 0; i < src.Length; i++) {
switch(src[i]) {
case '>':
point++;
break;
case '<':
point--;
break;
case '+':
(*point)++;
break;
case '-':
(*point)--;
break;
case '.':
Console.Write*1;
break;
case ',':
*point = (byte)(Console.Read());
break;
case '[':
if(*point == 0) {
i = kakko(src, i);
}
break;
case ']':
if(*point != 0) {
i = kakko(src, i);
}
break;
}
}
}
static int kakko(string src, int index) {
int nest = 0;
bool flag = src[index] == '[';
for(int i = index; flag ? i < src.Length : i >= 0; i = i + (flag ? 1 : -1)) {
if(src[i] == '[') nest++;
else if(src[i] == ']') nest--;
if(nest == 0) return i;
}
return -1;
}
}
unsafeでポインタ使ってみました。C#だとわかるんですよね、何故か。なのにCでポインタ使って書くと動かないのは何故なんでしょう…。
素直に配列使ってもそんなに速度変わらなかったりして、試して無いけど。List<byte>とか使えばメモリの指定が要らなくなってより安心して使えるかも知れないですね。
次にコンパイラ
using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Text;
using Microsoft.CSharp;
namespace Brainfuckコンパイラ {
class Program {
static void Main(string[] args) {
if(args.Length == 0) {
Console.WriteLine("ソースファイルを指定して下さい。");
return;
}
int memorySize = 256; /**************************************************
*BrainFuckコードの実行に割り当てるメモリーサイズ。*
*実行するコードに対して充分な大きさが必要。 *
**************************************************/
//ヘルプの表示
if(args[0].ToLower().Contains("help") || args[0].ToLower().Contains("?")) {
Console.WriteLine(
@"bfi [ドライブ:][パス]ファイル名 [メモリサイズ]
メモリサイズ プログラム実行の為に確保するメモリのサイズです。充分なサイズを指定して下さい。
大き過ぎても落ちるかも…。規定値は256。");
Console.ReadLine();
return;
}
//ソースファイルの読み込み*/
string src;
string srcFile = Environment.CurrentDirectory + "\\" + args[0];
if(File.Exists(args[0])) {
srcFile = args[0];
} else if(!File.Exists(srcFile)) {
Console.WriteLine("ソースファイルがありません。");
return;
}
using(System.IO.StreamReader sr = new System.IO.StreamReader(srcFile, Encoding.GetEncoding("Shift-Jis"))) {
src = sr.ReadToEnd();
sr.Close();
}
//コマンドラインオプションパーサ
if(args.Length > 1) {
if(!int.TryParse(args[1], out memorySize)) {
Console.WriteLine("メモリサイズの指定が正しくありません。");
return;
}
}
brainFuck(src, memorySize,srcFile);
#if DEBUG
while(true) {
Console.ReadLine();
}
#endif
}
static void brainFuck(string src, int memorySize,string srcFile) {
StringBuilder sb = new StringBuilder();
sb.AppendLine("using System;");
sb.AppendLine("class C{");
sb.AppendLine( "unsafe static void Main(){");
sb.AppendLine( "int memorySize = " + memorySize.ToString() + ";");
sb.AppendLine( "byte* point = stackalloc byte[memorySize];");
sb.AppendLine( "byte* tmp = point;");
sb.AppendLine( "for(int i = 0; i < memorySize; i++)*(tmp + i) = 0;");
for(int i = 0; i < src.Length; i++) {
switch(src[i]) {
case '>':
sb.Append("point++;");
break;
case '<':
sb.Append("point--;");
break;
case '+':
sb.Append("(*point)++;");
break;
case '-':
sb.Append("(*point)--;");
break;
case '.':
sb.Append("Console.Write*2;");
break;
case ',':
sb.Append("*point = (byte)(Console.Read());");
break;
case '[':
sb.Append("while(*point != 0){");
break;
case ']':
sb.Append("}");
break;
}
}
sb.Append("}}");
CompilerParameters param = new CompilerParameters();
param.OutputAssembly = Path.GetFileNameWithoutExtension(srcFile) + ".exe";
param.GenerateExecutable = true;
param.CompilerOptions += " /unsafe";
CompilerResults rs = new CSharpCodeProvider().CompileAssemblyFromSource(param, sb.ToString());
foreach(string str in rs.Output) {
Console.WriteLine(str);
}
}
}
}
コンパイラだなんて言ってカッコつけてますけど、中身はBrainf*ck→C#のトランスレータです。これをC#としてコンパイルさせてるだけです。
やっぱインタプリタとは速度が段違いです。
次はWhitespaceの処理系に挑戦してみようかと思っているのですが、僕にもわかるような言語仕様の説明が見付かりません。本家サイトは英語だし…。英語読めたらなぁ。努力はしませんけどね。
うわぁ、読みにくいですね。
ソースコードをHTMLに整形するツールを使ってみたのですが、ブログのスタイルシートが干渉して行間が…。
やっぱ今まで通りソースファイルをそのままアップした方がよさそうですね。
最近、全くネタが無く更新をサボっていたあにすです。自転車になんて全く乗ってません。
そんな久々の更新のネタはこれです。
ニコ動で晒されてます。
動画の一番最後、29分辺りからなのですが、僕がどう書く?orgに書いたコードを紹介して頂いてます。これ失敗作です。
まぁ、素直に嬉しいです。
とりあえず動くってレベルで6時間かかりましたよ。
それでも思ったよりは楽でした、さすが.NET。
C#でこんなことしてるサンプルってネット上探しても見付からないので、晒してみます。
実行ファイル
ソースコード
心配してた通信部分は.NETのライブラリのおかげで苦労はありませんでした。それよりも、板一覧のHTMLから板の情報を抽出する文字列処理が大変でした。しかも結構危ういんですよね。
あとは.datの解析も仕様通りに処理すれば問題なく動きました。
まぁ、僕のコメント一切無しのサンプル読むよりここ
http://www.monazilla.org/index.php?c=6-20
見た方が良いですよってことです。
久し振りの更新は久し振りのどう書く?投稿です。
http://ja.doukaku.org/comment/6862/
最初はランダムウォークインターフェイスを定義して、次元数別に別のランダムウォーククラスを書きました。
すると、次元数が変わっても共通の処理が多いことに気が付いたので、1次元のランダムウォーククラスを継承して、いくつかのメソッドをオーバーライドするだけで別の次元数のランダムウォークを書けるようにしました。
実際に書いてみるとオーバーライドしたメソッドが一つだけだったので、引数で処理分けるだけでいいんじゃない?という結論に至りhttp://ja.doukaku.org/comment/6862/のコードになりました。
なんとも無駄の多いコーディングでした。
http://ja.doukaku.org/comment/6397/
最近また盛り上がってきてますね。
yield可愛いよyield。
IEnumerator<T>きもいよIEnumerator<T>。
久し振りに面白そうなトピックが出てきたので書いてみました。
http://ja.doukaku.org/comment/6359/
http://ja.doukaku.org/comment/6361/
書いてから気付いたのですが、ネットで記事を読んだりして知ってはいたけど、実際にマルチスレッドでプログラミングするのは初めてでした。
結構楽しいですね。
メーカー純正のキーボードのFキーとJキーが磨り減ってきたので、キーボードを新調しました。
タッチ音がとても静かです。友人を付き合わせて電気屋を数件回り、やっと見付けたお気に入りです。
タッチ、キー配置、値段の最大公約数です。2000円位で買いました。展示している限りのキーボードを触りました。感触の良いキーボードは例外なく高いです。
色々と弄っていると、どうやらメカニカルタイプのキーボードのタッチが好みのようです。しかし、高いです。
手当たりしだいに弄っていると、どう見ても2000円しないだろうという地味な見た目のキーボードのタッチが最高なので、即決と思ったら、うわさのリアルフォースで、値段を聞いたら1万7千円くらいとのことでぶっ飛んだりしました。
そんなこんなで、なんとか妥協出来るものを見付けて、そのキーボードでこの記事を書いています。
悪くないです。普通のキーボードです。強いて特徴を挙げれば、タッチ音が静かなことです。パチンという高い音ではなく、カチョッっというような響かない音です。
まぁ大事に使おうと思います。
今年ロード初乗りです。支笏湖まで行ってきました。千歳~支笏湖温泉辺りまで行って、のりさんととりさんと落ち合い、一緒に千歳まで引き返しました。
やっぱ楽しいです。でも、翌日に筋肉痛が…。朝に走って、夕方に筋肉痛になって、夜には治ってた頃が懐かしいです。
詳細は面倒なので書きません。
サイコンデータ
走行距離 64.76km
平均速度 23.5km/h
最高速度 51.3km/h
走行時間 2h45m07s