« 2013年8月 | トップページ | 2014年5月 »

2014年4月

2014年4月18日 (金)

ココログでソースコードを見やすくする

SyntaxHighlighter を入れたりました。


プログラムのソースコードを見やすくするやつです。
ココログは使いにくいなー書いてもパッとしないし、と思ってたけどこういうのやるだけでモチベぐっとあがりますね。
一時的にですけど。


ここ http://trivia.cocolog-nifty.com/blog/2013/04/post-0fcc.html に従って。


簡単に書くと、SyntaxHighlighter を落としてきて http://alexgorbatchev.com/SyntaxHighlighter/ 解凍します。ココログの「コントロールパネル」の「ファイル」で、適当にフォルダ作って、そこにJavaScriptとCSSを全部アップロードします。で「ブログ」の「設定」で、「ブログのサブタイトル」に使うJavaScriptとCSSを書いておく。

ブログのサブタイトル
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shCore.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushAS3.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushCpp.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushCss.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushCSharp.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushJScript.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushPlain.js" type="text/javascript"></script>
<script src="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shBrushXml.js" type="text/javascript"></script>
<link href="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shCore.css" rel="stylesheet" type="text/css" />
<link href="http://自分のサイトのアドレス-nifty.com/作ったフォルダ/shThemeDefault.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
SyntaxHighlighter.config.stripBrs = true;
SyntaxHighlighter.all();
</script>

なお、上記だと今時点で配布されているすべてが載っているわけではないので注意を。具体的に言うと上記別サイトのをコピって入れて、僕はC#が多いのでパッと書いてみたらエラーダイアログばっか出やがりまして。
上記のは減らし済みです、PerlやPythonは僕はきっと使わない。自分が使うものだけ書いておけばいいのではないかと思います。


書くときはpreタグの class に、こんな感じに指定する。

<pre class="brush: c#;">
C#のソースコード
</pre>

たとえばC#の場合、c#、csharp、c-sharp の3つの書き方ができるようなので、ちらっとでもジャバスクリプトのソース見ておくといいですよ。

2014年4月17日 (木)

ある文字列のうち、nバイト以内に収まるのは何文字か

英字かな交じりの文字列が100字くらいあるんだけど、30バイト以内ずつに分けたい、とかいう場合。文字数で切るのではなく。データベースに書き込むような時とかさ、カラムサイズに合わせて分割しないといけないときあるじゃん。


「abcあいうdefえおか」
って文字列があって5バイトずつだ、とか。


文字コードによっても変わるし。
シフトJISの場合は "abcあ"、"いうd"、"efえ"、"おか" になりますよね。
UTF-8なら約日本語3バイトだと思ってるんで "abc"、"あ"、"い"、"うde"、"fえ"、"お"、"か" ですかね。


「abあいcdうえefおか」を5バイトずつだと
Shift-JISは "abあ"、"いcd"、"うえe"、"fおか" 、
UTF8だと "abあ"、"いcd"、"う"、"えef"、"お"、"か" 。


つーことで、「nバイトに収まるのはm文字だ」というのを求めたい。
.NET Framework 3.5、C#。
ちなみに今の問題では UTF-8 な Oracle DBに入れたいので、その辺をターゲットに。


「この文字列はnバイトだ」というのは Encoding クラスの GetByteCount() が使えますよね。
UTF-8 とかなら static なメンバがあるそうなので

Encoding utf8Enc = Encoding.UTF8;
int byteCount = utf8Enc.GetByteCount("文字列");

いろんな文字コードに対応できるように作りたいなら、

Encoding.GetEncoding("UTF8");

を使って "UTF8" の部分書き換えてって感じですかね。


さて、もちろんいろいろと可変なので、文字列の長さを変えながら、nバイト以上にならないかどうかとかで調べていきます。
でも単純に、頭から順番に一文字ずつ増やして、納まるかオーバーするか見ていくと、各種短いものだったらいいんですが、例えば10万文字を8万バイトでとかいう場合にかなり時間を食うと思われる。


ので、二分探索をします。バイナリサーチ or バイナリーサーチ。
今回やるのは二分探索って名前じゃないかもしれないけど、なんかそれっぽい感じの動きの。二分法?一緒か。 http://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%B3%95
しかしきちっとした二分探索も面倒くさいなーと思ったんで、てきとーにやります。
でもそれだけだとやっぱまずいので、目星をつけた後で補正します。

/// <summary>
/// 指定バイト以下になる文字数を返す
/// </summary>
/// <param name="strOrg">調査対象文字列</param>
/// <param name="start">何文字目から開始か(0始まり)</param>
/// <param name="getbyte">制限したいバイト数</param>
/// <returns>getbyteより少なくなる文字数</returns>
protected int GetByteCount(string strOrg, int start, int getbyte)
{
    //--収まるなら全文字数でOKと返す
    Encoding utf8Enc = Encoding.UTF8;
    int orgByte = utf8Enc.GetByteCount(strOrg.Substring(start));
    if (getbyte >= orgByte)
    {
        return strOrg.Substring(start).Length;
    }
 
    #region 適当な二分探索
    int y = (strOrg.Length - start) / 2;    //--着目点
    int delta = y / 2;    //--着目点の変化量
 
    while (delta > 0)    //--1以上の間ループ
    {
        if (getbyte > utf8Enc.GetByteCount(strOrg.Substring(start, y)))
        {
            y += delta;
        }
        else if (getbyte < utf8Enc.GetByteCount(strOrg.Substring(start, y)))
        {
            y -= delta;
        }
        //--getbyteと一致したら
        else
        {
            //--終わる
            break;
        }
 
        delta /= 2;    //--半分にする
    }
    #endregion
 
    #region 適当さを補正
    //--目標より少なければ
    if (getbyte >= utf8Enc.GetByteCount(strOrg.Substring(start, y)))
    {
        //--1文字足しても大丈夫かどうか
        while (getbyte >= utf8Enc.GetByteCount(strOrg.Substring(start, y + 1)))
        {
            y++;
        }
    }
    //--多ければ
    else
    {
        do
        {
            y--;    //--1つ減らして
        } while (getbyte < utf8Enc.GetByteCount(strOrg.Substring(start, y)));    //--まだ多いかどうか
    }
    #endregion
 
    return y;
}

呼び出すときに strOrg と start を指定するのは、同じ文字列を使って500バイト分1回目は1~300文字まで、500バイト2回目は301~725文字まで、とかいう使い方を想定しているからです。

こんな。

string message = "元のmessageフガフガ";
int limitByte = 5;
int next;
for (int i = 0; i < message.Length; i += next)
{
    next = GetByteCount(message, i, limitByte);
    //--message.Substring(i, next); を使ってどこかに出力
}

そりゃあ引数に Substring(i) を使って726文字目から終わりまでを渡す、でもいいかとは思いますけど。
オーバーロードでそっちを呼び出すべきか。


きちんと二分探索をやって、後の補正なんか汚いからやめたいって人は、こういうところがすごいしっかりしてるんで参考にするといいですよ。
その他ググれ。


404 Blog Not Found 「アルゴリズム百選 - 二分探索(binary search)」 http://blog.livedoor.jp/dankogai/archives/50961989.html


「二分探索の古典的実装にオーバーフローのバグがある」という話も発見しましたが、上のものだと足し算してるところはほとんどないから大丈夫かしら。足してても 1/2 単位だから Length へ向けての左極限だし。intをバリバリ使ってるから全然ダメという視点はあるでしょうがそこだけならlongかInt64なんか適切なのに置き換えてやってください。stringクラスの文字数制限ってあるのかしら、もし無かったら上記はダメね。制限あるならstringクラスに準じるって言えるから楽です。


ホットコーナーの舞台裏 「古典的バイナリサーチアルゴリズムにバグ」 http://iiyu.asablo.jp/blog/2006/06/05/393464

404 Blog Not Found 「(a+a)/2 == -a /* 半世紀もののバグ */ 」 http://blog.livedoor.jp/dankogai/archives/50522708.html


あとstring型の内部構造と文字コードに起因するこういう話もありますので、当然ですけど自己責任で検証/お使いください。


「C#プログラムでサロゲート・ペアの動作を検証する」 http://itpro.nikkeibp.co.jp/article/COLUMN/20080109/290600/?k2


魚へんに花のホッケの字をばしばし入れて確かめた結果なんとなく大丈夫じゃねーかなーと、か、思いつつ、半文字ズレ、が、怖く、なって、きた、ので、1バイトずつ増やしながら試してたらズレキター
どうすっかなこれ。最後の1文字が「そういうの」じゃないかどうか確認する?サロゲートペアだけでええんか?組み合わせ文字・結合文字?
͛꒰ू ऀ•̥́ꈊ͒ੁ•ૅू॰˳ऀ꒱ ͟͟͞ ̊ ̥ ̥” とかo͡͡͡͡͡͡͡͡͡͡͡͡͡͡╮( ꒪⌓꒪)╭o͡͡͡͡͡͡͡͡͡͡͡͡͡͡とか入れてきたらどこで切るのが正しいんだろ。おぉ難題だ。ややこしい時代になってきた気がする。


DOBON.NET プログラミング道 「サロゲートペアや結合文字が含まれているか調べる」 http://dobon.net/vb/dotnet/string/issurrogatepair.html


車輪の再発明ならぜひ教えてください!

« 2013年8月 | トップページ | 2014年5月 »

AmazonSearch


最近のトラックバック

無料ブログはココログ