CodingFirst

C言語、Perl、JavaScript、最近はPythonも。出来上がったものより、プログラムを書くことが好き。あと、スイーツ。

スポンサーサイト

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コメントアウトにありがちな笑えない話

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2

C言語のコメントアウトのありがちな話だけど、
「可能」とか「表」の笑えない話を書いておく。

i に 1 を代入するコードを書いたとする。

#include <stdio.h>
int main(int argc,char*argv){
  int i=0;
  //i=1:使用可能
  i=1;
  printf("i=%d¥n",i);
  return 0;
}

これを gcc で実行すると、

$ gcc a.c && ./a.out
i=0

なぜか i=1 でなく、 i=0 と出力されてしまった。

知ってればありがちな罠なんだけど、
a.c が Shift_JIS だった場合に、「能」が 0x94,0x5C で、
0x5c は asciicode で \ なので、継続行とみなされ、次行の i = 1 がコメント扱いになってしまった。

なので、文字コードを変えれば、ちゃんと動く。

$ nkf -w a.c | gcc -x c - && ./a.out
i=1

この罠、いまだに笑っていられない話で、
たとえば、windows の gcc では動いたけど、 linux の gcc では動かなくて、
その原因が svn / git のチェックアウト時に文字コードを自動変換させてたがため
この問題に引っかかったとか起こりそうな話だったりする。

スポンサーサイト

C言語でmd5

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2

C言語でmd5を計算する。

MD5は、ファイルの指紋(フィンガープリント)としてよく使われてる。
用語的にはMD5チェックサムの方が一般的かも。

MD5 - Wikipedia

あやまって一致する事はまず無いので、
ダウンロードしたデータの正当性とか、Jenkinsのようにビルドの追跡とか、
要するに、テストの期待値を圧縮する手段としてよく利用される。

MD5は linux だと簡単に下のように計算できる。

$ openssl dgst -md5 fox.jpg 
MD5(fox.jpg)= c7880ecd95d8dcf0efe82f465aa41e3f

$ md5sum fox.jpg 
c7880ecd95d8dcf0efe82f465aa41e3f  fox.jpg

C言語でも使いたい事がある。
簡単に使いたいので openssl を利用する。まず、環境入手。

$ sudo apt-get install libssl-dev

MD5を計算する Cコードは以下。

$ tcc "-lssl" -run md5sum-1.c fox.jpg 
c7880ecd95d8dcf0efe82f465aa41e3f	fox.jpg
$ tcc "-lssl" -run md5sum-2.c fox.jpg 
c7880ecd95d8dcf0efe82f465aa41e3f	fox.jpg

2番目の方、後で文字列を追加する(ループする)には、
どうすればいいかよくわからんかった。まぁマジックナンバーが必要だし、 1番目のケースしか使わなけりゃいいか。

参考)
チェックサム - Wikipedia
巡回冗長検査 - Wikipedia(CRC)
MD5 - Wikipedia

Cソースを見ながら学ぶなら、やっぱアルゴリズム辞典。


C言語による最新アルゴリズム事典 (ソフトウェアテクノロジー)C言語による最新アルゴリズム事典 (ソフトウェアテクノロジー)
(1991/03)
奥村 晴彦

商品詳細を見る

[C]クイックソートをする

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2

C言語でクイックソート。
標準でqsortがあるけど、筋トレ的に書いてみよう。

その前に、アルゴリズムを復習しよう。
クイックソート - Wikipedia
C言語による最新アルゴリズム事典 (ソフトウェアテクノロジー)

一言で言うと、配列を中間値で大小に分割して再起するソートか。
実装方法に悩むけど、思いつきで書いてみた。
gist に書いたコードを以下に。

中間値は一番左の要素にして、左のバケツを決めていく方法にした。
これはこれでいいけど、奥村先生本の手法をみたら愕然。こんなコードになる頭が欲しい!

では、
コンペアとスワップを基準に前に書いたソートも含めて性能比較。

$ git clone git://gist.github.com/1476722.git sort-eg
Cloning into sort-eg...
remote: Counting objects: 26, done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 26 (delta 15), reused 5 (delta 3)
Receiving objects: 100% (26/26), done.
Resolving deltas: 100% (15/15), done.
$ cd sort-eg
$ for i in *.c ; do tcc -run $i ; done
         bblsort: cmp=4950.0, swp=2472.6, xor=197DFD2F
        bblsort2: cmp=4768.0, swp=2472.6, xor=197DFD2F
           qsort: cmp= 541.8, swp=??????, xor=197DFD2F
          qsort2: cmp= 890.6, swp= 158.9, xor=197DFD2F
          qsort3: cmp= 944.1, swp= 155.1, xor=197DFD2F
         selsort: cmp=4950.0, swp=  94.8, xor=197DFD2F

安定的では無いとはいうけど、バブルソートや選択ソートに比べりゃ、やっぱり早いな。
cのqsortはかなり早そうだけど、実装がイントロソートとかなのだろう。

クイックソートは、アルゴリズムが単純で早いけど、再起を使うのが難点かな。
C言語だとスタックまで気を使う事も多いし。
もちろん、実装次第の話でもあって、例えば奥村先生本に再起を使わないコードがある。
ご利用は計画的にってとこか。

いい勉強になった。


C言語による最新アルゴリズム事典 (ソフトウェアテクノロジー)C言語による最新アルゴリズム事典 (ソフトウェアテクノロジー)
(1991/03)
奥村 晴彦

商品詳細を見る

C言語で正規表現 - PCRE編

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2

C言語で正規表現、第2弾。PCREを使ってみた。

PCREは perl5コンパチな正規表現ライブラリ。
前エントリのコメントで教えていただいたんで早速。

PCRE - Perl Compatible Regular Expressions

libpcre.a はすでに入ってたので、apt-getで libpcre3-dev だけ入れた。
以下、gistに貼ったpcreを使ったサンプルコード。

動作例。svn infoの Revision: の番号を取得するサンプルです。

$LANG=c svn info http://svn.apache.org/repos/asf/subversion/trunk > info.txt
$ cat info.txt |./pcre-eg.c 
1243564$

あっけないほど簡単で、使いやすい。便利だ。
これなら LL系に弱い人にも使いこなせる気がする。

例えば、svnのリビジョン番号のファイルを作成したいとき、

touch r`LANG=c svn info|grep '^Revision:'|cut -d ' ' -f 2`.log
とか、
touch r`LANG=c svn info|perl -ne 'print $1 if(/^Revision: (\d+)/)'`.log

とかワンライナーで書くけど、
grepってなんすか?な人は意外に多いし、
perlは読めないんで!と断られたりもするけど、
みんな大好きc言語だよ!なら受け入れられそう。

touch r`LANG=c svn info|../pcre.c`.log

と、こんな感じかな。


詳説 正規表現 第3版詳説 正規表現 第3版
(2008/04/26)
Jeffrey E.F. Friedl

商品詳細を見る

C言語で正規表現

  • このエントリーをはてなブックマークに追加
  • web拍手 by FC2

C言語で正規表現を使ってみた。
といっても、ライブラリたたいただけだけど。

まず、コード。

使用例

$ LANG=c svn info http://svn.apache.org/repos/asf/subversion/trunk|tcc -run ./regex.c 'Revision: (.*)' 2
Revision: 1243192,1243192

$ echo 'one-two-tree-daa' |tcc -run ./regex.c '([a-z]+)-([a-z]+)' 3
one-two,one,two

$ LANG=c svn info http://svn.apache.org/repos/asf/subversion/trunk|tcc -run ./regex.c '([[:alpha:][:blank:]]+): (.*)' 3
Path: trunk,Path,trunk
URL: http://svn.apache.org/repos/asf/subversion/trunk,URL,http://svn.apache.org/repos/asf/subversion/trunk
Repository Root: http://svn.apache.org/repos/asf,Repository Root,http://svn.apache.org/repos/asf
Repository UUID: 13f79535-47bb-0310-9956-ffa450edef68,Repository UUID,13f79535-47bb-0310-9956-ffa450edef68
Revision: 1243192,Revision,1243192
Node Kind: directory,Node Kind,directory
Last Changed Author: hwright,Last Changed Author,hwright
Last Changed Rev: 1242958,Last Changed Rev,1242958
Last Changed Date: 2012-02-11 07:10:34 +0900 (Sat, 11 Feb 2012),Last Changed Date,2012-02-11 07:10:34 +0900 (Sat, 11 Feb 2012)

POSIX準拠なregex.hを使った。
とりあえずgccで使えたんだけど、VCでも鬼車を使えばできるらしい。

使い方の詳細はググるなり、man 7 regex をみるとして、
[a-z]とか{1,2}とか(hoge|fuga)とか(.*)とか(.+)が使える。
あと、isalphaなどのisな関数を[:alpha:]と使えるとかかな。

にしても、使い勝手がよくない。
本格的に組み込むならwrapper関数を作る必要があるだろうし、
鬼車のようなライブラリを組み込むのが楽か、
C言語なら1から自作するほうがそれらしいかな。

Beautiful Code読んだ人は自作かな。


ビューティフルコードビューティフルコード
(2008/04/23)
Brian Kernighan、Jon Bentley 他

商品詳細を見る

 | HOME |  »

Search

Recent Entries

Foot Print



Categories

Monthly

Recent Comments

Recent Trackbacks

Profile

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。