Skip to main content

ログ取得ツール

Category: プログラミング

TF-IDF法

ちょっとテスト的に使ってみることにした。キーワードを抽出している。…こういうのってもう流行じゃないのかもね。 TF-IDF法自体はいまいち直観的ではないような気もするスコアリング方法ではあるが、メジャーではあるのですね。 このままいくと、いっそbogofilterとかにかけて文章のSPAMレベルを判定させてみるのもいいかもしれない。一応、機能してないけどエントリのスコアリング投票があるので、それを利用して「つまらない」が多いものをSPAMとして学習していくわけ。…何のために?

stack checker

関数毎にスタックの消費量を計算してくれるプログラム(スタックアナライザ??)を作ったら需要はあるだろうか? 需要があるなら、もうあるかもね。まあスタックオーバーフローなんて滅多にないのかもしれないけど。

printf

printfが使いにくいのは引数の扱いだ。

printf("a=%d, b=%d, c=%d\n", a, b, c);

このくらいならばいい。しかし引数が長くなっていくと(例えば数十個とかになると)すぐに破綻するのは周知の通り(たぶん。それともおれだけか??)。これを破綻させないようにしようとすると、複数のprintfに分割ということになってしまう。しかし、本当に分割する必要があるだろうか? 1回の呼び出しでも破綻しないようにprintfを作ることはできるはずだ。 第1引数がフォーマット文字列で、第2引数以降がフォーマットへの引数というのが悪化の原因であると思う。だからいっそのこと、このようにしてみたらどうか?

printf("a=%d, %+", a, "b=%d, %+", b, "c=%d\n", c);

フォーマット文字列で例えば「%+」が出現したら(「%+」は既存のフォーマット文字列でも意味があるので別なものを選ぶ必要はあるけど)、次の引数をフォーマット文字列の続きとして扱う。これで"%d"と引数の位置が近くなり、長いprintfも見易くなると思われる。 …C++を使え、という話もあるけどね。

C++でdivide by zeroを例外としてcatchするにはどうしたらいいだろうか

LinuxでC++を使うとき、gccのg++を使うことが多いだろう。でもいまいち使ってない。なぜか。例外がcatchできないからだろうと思った。というわけで。 C++でdivide by zeroやNULL pointer dereference等はtry〜catchで挟んでも例外としてはcatchできず、普通にシグナルハンドラに落ちる。どうしたらいいのか。 シグナルハンドラを登録してそっから投げりゃいいんじゃねえの?? と思って、そう書いてみた。 #include #include extern “C”{ #include #include }; using namespace std; class sigexception{ int val; public: sigexception(int a){ val=a; } int getvalue(){ return val; } char *getstring(){ return strsignal(val); } }; void sighandle(int a) throw(sigexception) { throw sigexception(a); } int main(int argc, char **argv) { signal(SIGINT, sighandle); signal(SIGFPE, sighandle); signal(SIGSEGV, sighandle); signal(SIGBUS, sighandle); …. } で、try{ sleep(10000); }catch(sigexception e){}みたいにして、killコマンドでシグナルを投げてみると、普通にcatchできた!! と思ったけど、1/0とか計算して本物の例外を出してみるとダメでした。シグナルハンドラ(上のコードで言うsighandle)は起動するんだけど、terminate called after throwing an instance of ‘sigexception’ とか言われ、例外はcatchできずに落ちる。どうしてそうなんだろう…。 コンパイルするときに「-fexceptions」をつけてもダメ。Fedora Core 3のgcc-c++-3.4.3-22.fc3とgcc4-c++-4.0.0-0.41.fc3で試して、どちらも挙動は同じでした。

メモ:Pythonの配列のdeep copy

Pythonの配列は普通に代入していくと参照しか渡されない。

a=[1,2,3]
b=a
print a,b
a[1]=10
print a,b
[1, 2, 3] [1, 2, 3]
[1, 10, 3] [1, 10, 3]

そこで、コピーするには、以下のようにしていた。

a=[1,2,3]
b=a*1
print a,b
a[1]=10
print a,b
[1, 2, 3] [1, 2, 3]
[1, 10, 3] [1, 2, 3]

または、以下のようにする。

a=[1,2,3]
b=a[:]
print a,b
a[1]=10
print a,b
[1, 2, 3] [1, 2, 3]
[1, 10, 3] [1, 2, 3]

しかし実はこれでも多重配列には十分ではないようで、少々ハマった。自力でdeep copyするしかないのかと思ってぐぐってみたら、copyモジュールを使えば普通にdeep copyできるらしい。

import copy
a=[1,2,3]
b=copy.deepcopy(a)
print a,b
a[1]=10
print a,b
[1, 2, 3] [1, 2, 3]
[1, 10, 3] [1, 2, 3]

これはありがたい。試しに3重配列をいじくりながら再帰的に探索するプログラムに使ってみたが、普通に動作してくれた。

C99には複素数が入ってる

知らなかった人はcomplex(5)を見て下さい。 今さら知りました…そんなの入れるくらいなら(略)ですよ。 (追記) 2004-12-28 12:21 昨晩C99の変更点についてまとまっているページ(dll.jp)を見つけたので書いておきます。ひとことで言えば…気持ち悪っ! ということです。 intN_tみたいなのは必要だったとは思うんだけど、変数宣言をC++みたいに書けたりする(以前は「{」のあるところにしか書けなかったので、プログラマが変数を利用する範囲を考えてブロックを作っていた)とか、そういうのもCに入れちゃっている。浮動小数点数を16進数で書けるというのはある種の革命だ(笑)。以前にこんなことを書いたのを思い出すがC99のほうが先だった。 しかし例外処理はさすがに入っていない。文字列の扱いのいいかげんさと、例外処理がないというのが痛いんだよなぁ。

境界

あー、ひさしぶりにElectricFenceが役に立った。こういう手軽に使えるツールは意外と強力で、いつもありがたいものだ。 efenceはlibsafe並みに普段から有効にしておきたいところだが、性能はけっこう落ちる。それに普通に有効にしてるとcppとか、いろいろ動かないプログラムもあるんだよね(笑)。 libsafe有効にして生活してると、Pythonのインタプリタがよく引っ掛かるよね(おいおい)。 (追記) 2004-12-10 09:13 ElectricFence、新しめ(2.4.10とか)のはWindowsに対応した挙句、freeせずにexitしたのも検出してくれるんだな。これは便利だ。efence.hをincludeしておけばmallocした場所(ソースのファイル名と行番号)も特定してくれる。 しかしねえ、普通の人はexitするならいちいちfreeやcloseなんてしないぞ(笑)。リソースをOSが一発で回収してくれることは保証されている。

bisect

メモ。 Pythonのbisect。…ひとつひとつのエントリが構造を持たない場合にしか使えないのが難点かな。まあ、単純ではあるけどいちいち自分で書くのもアレだし、そこそこ便利かもね。 ていうかPythonは配列のfindがindexつーんだよね。まあ文字列操作のindexと同じと思えばいいのだが。

メモ:execinfo.h

書いとかないから忘れるのだ。 なんていうかね、baseとlinkを与えてabsolute-linkにするとか、同じ引き数与えて最も短かいrelative-linkの文字列を作るとか、そういうのも車輪の再発明と言えるけど(結局適当な関数が見つからなくて…書いてしまった)。 最近ではgccとIA32のスタックフレームの構造を調べて自力でスタックを追うなんてことをしようと一瞬思った。…この先死ぬまで何度同じことをしようと思うだろうか。 というわけでプログラム中からのバックトレースの取り方。glibcなら大丈夫。デバッガ使えという説もあるんだけれども。 #include void show_trace(void **ptr) { void **array; int r,i; array = calloc(1, 1024); r=backtrace(array, 1024); for(i=0; i 出てきたアドレスをaddr2lineとかで調べればいい。backtrace_symbolsやbacktrace_symbols_fdよりはaddr2lineのほうが良い結果をくれる。gcc -gでコンパイルしてあればかなり精度は高い。 「addr2line」の名前もメモしとかないとobjdump -dSとかの逆アセンブルの結果からソースの位置を調べるという不毛なことをする羽目になる。

ffs

ffs(find first bit set)ってstirngs.hにあったんだ…知らなかったな。asm/bitops.hとかで、互換性的に良くないものだと思ってた。ffz(find first bit zero)はbitops.hなのだが。 これからはコッソリではなくて堂々と使える。1-originなのがどうもアレだけども。 ffsあるなら、どうせならtest_bitやset_bitも入れてほしい。