2011年3月31日木曜日

バイナリファイル対応の head コマンド

バイナリファイルにも対応した head コマンドの例題です。

head コマンドは、ファイルの先頭行を表示するものですが、バイナリファイルの場合、改行が含まれないためにファイルの先頭から最後まで表示されてしまったりするため、非常に困ったことになる場合があります。

そこで、折り返すバイト数を指定したり、表示できない文字が含まれる場合には '*' や 16進数で表示したりすることができるようにしています。

表示には、通常の printf 関数ではなく、write 関数を用いています。
描画速度的には printf よりも write の方が速く、printf を行った後に write を行うと、write で行った表示の方が先に表示されます。
printf の表示を優先したい場合には、fflush(stdout); を行う必要があったりします。

実行結果

バイナリファイルの読み取り

バイナリファイルの読み取り例です。

fread 関数により指定したバイト単位毎にファイルを読み込み、表示を行っています。

実行結果

ファイルの行数読取り

ファイルの行数を取得する例題です。

実行結果

また、メモリマップドファイルを利用した例は、以下になります。

2011年3月26日土曜日

構造体データの並べ替え

構造体により定義されたデータを並べ替える例です。

本例題では、データの挿入時に日付毎 (char hday) に並べ替えて挿入されるようになっていますが、データ挿入後に再度、別の条件で並べ替えを行っています。

並び替えの部分 (sort_list 関数) では、関数ポインタ (int (* const comp[2])()) により並び替えの手法を変更しています。
また、sort_list 関数に指定する引数により、昇順/降順の指定を行うことができます.
例:
売り上げ金額毎に昇順に並べる:
sort_list(SORT_ASC,&start,uk_compare);
日付毎に降順に並べる:
sort_list(SORT_DESC,&start,date_compare);
→ それぞれの条件を計算するための比較関数を用意し、ASC(昇順)、DESC(降順) を指定しています。


sample.txt
004 東京 20050524 00001 東京商店 25000
003 横浜 20050321 00002 横浜商店 20000
002 千葉 20050103 00001 東京商店 30000
004 東京 20050603 00003 関東商事 15000
004 東京 20050603 00003 関東商事 18000
004 東京 20050603 00003 関東商事 17000
004 東京 20050603 00003 関東商事 16000
004 東京 20050603 00003 関東商事 11000
004 東京 20050603 00003 関東商事 12000
実行結果

共用体による1ビット毎のデータアクセス

共用体を用いて1バイトデータの各ビット毎にアクセスする例題です。

実行結果

構造体による木構造のノードデータの格納

構造体により木構造体のノードデータを格納する例題です。

例題では、ノードデータの入力、検索、削除を行っています。


実行結果

メモリの再割り当て

メモリを再割り当てして利用する例題です。

実行結果

2011年3月24日木曜日

可変引数リストを用いたデバッグ出力

可変引数リストを用いたデバッグ出力の例題です。

printf 関数のように、関数に複数の引数を自由に与え処理を行います。
引数に与えられた変数は、キャストすることにより自由に型を変えることは可能ですが、型チェックのようなことを c/c++ では行えませんので、お勧めできません。
(Java では instanceof 演算子によりチェック可能です。)

実行結果

CSV ファイルのデータ内容に合わせて2次元配列の動的確保(int 型)

CSV ファイルのデータ内容に合わせて2次元配列を動的に確保し、表示する例題です。

その他、CSVデータを動的に配列として読み取る例や、クラス化して扱う例などは こちら

csvdata.csv
実行結果

2011年3月22日火曜日

CRC の計算

ランダムに生成された数値データに対し、誤りチェックのためのCRCを計算する例題です。

CRCでは、
(1)送信すべきビット列を2進数とみなし、
(2)検査用の2進数ビット列で割り算し、
(3)最後はあまりを出す。
という手順を取ります。

相手側には、送信すべきビット列と余りを送ります。
受信側でも同じ割り算を行い、余りが一致すれば正しく受信できたことになります。
(割り算と言っても「桁借り」の無い特殊な割り算です)

多項式:2進ビット列のビットは上に行くほど桁の重みが大きい。
    そこで、重みを考慮した多項式表示(足し算の形)で表現します。
(例)1011100111001011 (16bit)
   最上位は2^15、最下位は2^0=1です。
   
   すると上のビット列は
   x^15 + x^13 + x^12 + x^11 + x^8 + x^7 + x^6 + x^3 + x + 1 (x=2)
   で表せます。
これが(送信すべきビット列の)多項式です。

生成多項式:検査用のビット列(割る数)も同じように多項式の形で表します。
      (余りを生成するもとの式という意味で)生成多項式と呼びます。

例題では、多項式を用い直接計算する方式と(calculateCRC16)と、余剰テーブルを用いて高速化を図った方式(calculateCRC16t/calculateCRC32t)の2種類の計算を行っていますが、それぞれの結果は同じです。
配列のサイズが大きくなると計算量も大きくなるため、このような工夫が取られています。
また、検査用ビット数を16/32ビットとした計算の2種類用意しています。

生成された配列にCRCを付与した配列に対し、再度CRCを計算(CRCデータも含め)するとCRCが0になることを確認することにより、CRCの計算結果が正しいことが確認できます。

CRCを配列に格納する場合のバイトオーダーは、ビッグエンディアンで格納する必要があります。
ネットワークでやり取りされるデータは、通常ビッグエンディアンになりますので、ホスト内のバイトオーダーとは異なる点に注意が必要です。
例題では、htons/htonl 関数により、16/32 ビットのデータをビッグエンディアンに変更し格納しています。

ソース等をまとめたもの:DL

crc.h

crc.cpp

crcTest.cpp

実行結果

2011年3月21日月曜日

XOR和によるチェックサムの計算

データを送受信する際の誤り検出方法の一つであるチェックサムを計算し、配列に格納する例題です。

誤り検出の方法としては、他にもCRCMD5等があります(SHA-1)。

今回のチェックサムではXOR和を用いており、単純な加算・減算方式、パリティ方式、CRC方式等々、様々な方法があります。
送信側、受信側のアルゴリズムが一致しないと、正しいデータ転送を行えませんので、どの方式が利用されているか確認の上、ご利用下さい。


例題では、ランダムに発生した数値データに対し、チェックサムを計算し、その値を格納後、通信の終りを示す EOT(0x04)/0 を配列に格納しています。
(このような形はあくまで例題であり、私が使っていた通信機器のデータ格納方式がそうだったというだけです。汎用な形式ではありません。)


実行結果

半角・全角カナ文字の変換

SJIS ファイル中に含まれる半角カナ文字を全角に変換する例題です。
小文字の英単語も大文字に変換を行っています。
例題に用いられたテキストは SJIS で保存を行ってください。


hankaku.txt
英数字を含む文字列:

When he smiled with NIYARI, he lifted the glasses of a black spot and
floated a haughty expression. Where [ of such a fellow ] will be said
"Really trust"? A command of a superior official still cannot oppose
absolutely and poor. It is being [ such YATSU- of I CHI O U - /
asuperior official ] DA mosquito RA-. The moment such thinking emerged
on the head, it has appeared in expression. It seems that he also has
full knowledge of my thinking enough by years of association, and the
present thinking is also already read. When considering soon, my life
began to turn around a corner of a street greatly from this
moment. Although it is the thing of the future, it will be known
personally that just the slack of this momentary mind was fatal.

日本語文章(半角カナ含む):

彼はニヤリと微笑むと、黒斑の眼鏡を持ち上げ不遜な表情を浮かべた。一体、こんな
奴のどこを信用しろと言うのであろうか?それでも、上司の命令は絶対であり下
手に逆らうことはできない。こんなヤ・ツ・でも、イ・チ・オ・ウ・は、上司なのダ・カ・ラ・。と、
そんな思考が頭に浮かび上がった瞬間、それが表情に出てしまった。長年の付き
合いで彼は私の思考も十分熟知しており、現在の思考もすでに読まれているよ
うだ。今に思えばこの瞬間から、私の人生は大きく曲がり角を回り始めたのであ
る。後々のことであるが、この一瞬の気の緩みこそが命取りであった、というこ
とを身をもって知ることになる。

実行結果
% ./list_xxx
英数字を含む文字列:

WHEN HE SMILED WITH NIYARI, HE LIFTED THE GLASSES OF A BLACK SPOT AND
FLOATED A HAUGHTY EXPRESSION. WHERE [ OF SUCH A FELLOW ] WILL BE SAID
"REALLY TRUST"? A COMMAND OF A SUPERIOR OFFICIAL STILL CANNOT OPPOSE
ABSOLUTELY AND POOR. IT IS BEING [ SUCH YATSU- OF I CHI O U - /
ASUPERIOR OFFICIAL ] DA MOSQUITO RA-. THE MOMENT SUCH THINKING EMERGED
ON THE HEAD, IT HAS APPEARED IN EXPRESSION. IT SEEMS THAT HE ALSO HAS
FULL KNOWLEDGE OF MY THINKING ENOUGH BY YEARS OF ASSOCIATION, AND THE
PRESENT THINKING IS ALSO ALREADY READ. WHEN CONSIDERING SOON, MY LIFE
BEGAN TO TURN AROUND A CORNER OF A STREET GREATLY FROM THIS
MOMENT. ALTHOUGH IT IS THE THING OF THE FUTURE, IT WILL BE KNOWN
PERSONALLY THAT JUST THE SLACK OF THIS MOMENTARY MIND WAS FATAL.

日本語文章(半角カナ含む):

彼はニヤリと微笑むと、黒斑の眼鏡を持ち上げ不遜な表情を浮かべた。一体、こんな
奴のどこを信用しろと言うのであろうか?それでも、上司の命令は絶対であり下
手に逆らうことはできない。こんなヤ・ツ・でも、イ・チ・オ・ウ・は、上司なのダ・カ・ラ・。と、
そんな思考が頭に浮かび上がった瞬間、それが表情に出てしまった。長年の付き
合いで彼は私の思考も十分熟知しており、現在の思考もすでに読まれているよ
うだ。今に思えばこの瞬間から、私の人生は大きく曲がり角を回り始めたのであ
る。後々のことであるが、この一瞬の気の緩みこそが命取りであった、というこ
とを身をもって知ることになる。

%

ハッシュ表の作成

ハッシュ表を作成し、検索する例題です。

実行結果

2011年3月20日日曜日

パス指定によるファイル検索, 引数解析

検索を行うパス、ファイル名を指定し、ファイル検索を行う例題です。

実行ファイルに渡す引数を解析し、検索を行うパス、ファイル名を指定しています。


実行結果

拡張子によるファイル検索

拡張子を指定し、フォルダ内にあるファイル名を表示する例題です。


実行結果

10進・2進文字列の変換

10進・2進文字列の変換を行う例題です。

相互変換した結果を表示しています。


実行結果

2011年3月19日土曜日

CSV ファイルの行と列を入れ替え

CSVファイルを読み込み、行と列を入換えて出力する例題です。

その他、CSVデータを動的に配列として読み取る例(char, int/double 型など)や、クラス化して扱う例などは こちら

実行結果

ファイル情報読み込み、構造体への格納

適当なフォーマットのファイルから構造体にデータを格納し、表示する例題です。

フォーマットは以下のようなコンフィグファイルの形となっています。
[id1]
connect cause = "ip address1"
connect point = "path1"

[id2]
connect cause = "ip address2"
connect point = "path2"

バイナリファイルを構造体に格納する例は こちら

実行結果

カレンダーの表示


実行結果

タイムアウト機能付のコンソール入力

タイムアウト機能付のコンソール入力例です。

シグナルハンドラとインターバルタイマによる sleep 関数の例を利用し、時間内に入力が得られなければタイムアウトします。

実行結果

kbhit 関数の再現(Enterなしの1文字入力)

DOS プログラム等でよく利用される kbhit() 関数を cygwin/gcc(OSX/gcc)上で実現する関数です。


実行結果

トークン毎のデータ抜き出し、日本語処理

トークン毎にデータを抜き出し、表示する例題です。

セパレータ文字(" ",",","/",";",":" etc)等で区切ることができない場合にも対応することができるよう、英語と日本語の入力の境目で区切る処理も加えています。
今回の例題では、iskanji 関数により SJIS の漢字か英語かどうかを判定しています。

word1.txt
in front of,・・・の前で
in vain,無駄に
in spite of,・・・にもかかわらず
word2.txt
in front of ・・・の前で
in vain 無駄に
in spite of ・・・にもかかわらず
実行結果

文字列から余計なスペースの除去

文字列の前後に余計な記号等が含まれる場合、その文字列を除去する例題です。

" Hello World! " → "Hello World!"


実行結果

文字列の間にスペースの代入

文字列の間にスペースを代入する例題です。


実行結果

文字列の検索、プログラムパスの分割

プログラムパスを分割し2次元配列へとコピーする例題です。

配列は動的に確保されます。
パスの分割の際、UNIX パスと DOS パスではそれぞれ書式が異なりますので、それぞれ関数を用意しています。
検索する文字列、区切り文字はそれぞれ異なっています。

実行結果

2011年3月18日金曜日

大文字・小文字の変換

小文字を大文字へ、大文字は小文字へ変換する例題です。

tolower, toupper 等の関数がありますが、それらを自分で実装する際には、下記のソースの一部を変更して頂ければ実装可能です。

実行結果

2次元配列の動的確保

'\n' 文字毎に区切られた文字列を格納するための配列を、動的に確保する例題です。
それぞれの配列は2次元配列として確保されます。

その他例題は こちら
実行結果

トークン毎のデータ抜き出し

エクセルファイル等では良くCSVと言うカンマ(,)区切りのデータフォーマットが用いられますが、区切り文字で分けられたデータをトークンと呼びます。
区切り文字を適当に指定すればCSV形式のファイルをスペース区切りのフォーマットに変換したり、その逆も可能です。

実行結果

2011年3月16日水曜日

10進・16進[文字列]の変換(バイナリデータからアスキーテキストへの変換)

10進数字から16進文字列への変換(1234 → "04 D2")、
16進文字列から10進数字への変換("04 02" → 1234)、
を行う例題です。

16進数のデータはchar型データの文字列として扱います。
バイナリエディタなどでは、char 型で扱われる 0〜255 までの文字を1バイトずつ printf にて %x 形式で出力すれば良い話です。
一方古い通信機器等では、通信を行う際の形式がアスキー形式かつ1バイト(char)を変換した "AA" ではなく、2バイト(short)、4バイト(int)等の場合があり、一文字のデータを送る場合にも "000000AA" のように "00" 文字を埋めた形のアスキーテキストを送る必要があります。
また、そのアスキーデータを受信した後にバイナリデータとして変換する必要があります。

例題では、バイナリダンプで行うような1バイトずつの16進文字列への変換と、変換するバイト数(1バイト・8バイト)を指定した変換を行っています。
バイナリダンプを行うような場合は、hexdump/dump2char 関数のみを参考にしてください。

バイト数を指定する例ではバイトオーダーを考慮し、リトルエンディアン[最下位のバイト順](Intel) の並びで変換が行われた結果が表示されています(Intel OSX)。
バイトオーダーの違いによるバイト列の並びは以下のようなものです。
例:2バイト(16ビット)の数値(1)
ビッグエンディアン  00000000 00000001  (Byte4:Byte3:Byte2:Byte1)
リトルエンディアン  00000001 00000000  (Byte1:Byte2:Byte3:Byte4)

実行結果

2011年3月13日日曜日

バイトオーダーのチェック(ネットワークバイトオーダーへの変換)

バイトオーダーをチェックする際には以下のようなコードを利用することができます。
32ビット整数に数字の 1 を代入し、先頭8ビットのみを調べて数字の 1 と同じ値になるのがリトルエンディアン、0 になるのがビッグエンディアンになります。
例:2バイト(16ビット)の数値(1)
ビッグエンディアン  00000000 00000001  (Byte4:Byte3:Byte2:Byte1)
リトルエンディアン  00000001 00000000  (Byte1:Byte2:Byte3:Byte4)

下記の例題では、バイトオーダーをチェックし、その並び順に沿ったバイト列を表示しています。
また、htons/htonl 関数によりネットワーク間のデータ送受信に用いられるネットワークバイトオーダー(ビッグエンディアン)に変換し、バイト列を表示しています。

実行結果

構造体による社員名簿管理

構造体を利用した社内スタッフの整理例です。

ID、氏名、身分、部門、給料
の情報を構造体内に格納し、管理します。

例題では、部署ごとの情報を表示し、平均給料を計算・表示を行っています。
また、IDにより情報を並べ替え、元の管理ファイルへの書き出しを行っています。


992766A3.txt
#ID 氏名 身分 部門 給料
2169 michael CEO outside 10000
2374 arthor president company 8000
1922 mike secretary company 4000
343 ken staff room1 3000
1080 john staff room2 4000
1080 carl staff room3 2500
1278 david staff room1 3000
2231 dianne staff room2 4000
1175 alan staff room3 2500
1584 andreas staff room1 3000
1430 ben staff room2 4000
実行結果