![]() |
zunbe |
![]() |
|
2005年8月 | ![]() |
| [<<先頭] [<前へ] [ 1 2 3 4 ] [次へ>] [最後>>] | ||
2005/07/16
|
久しぶりに Oracle をインストールした。
ひとつ前のバージョン 9i だ。
Oracle をインストールを度に思う。
なんで、Oracle のインストーラは X が必須なんだろうか。
公開WEBサーバに X なんか入れたくないし、入れる必要性も感じないのだが、Oracle が必須といっているのだから、仕方がない。
インストール自体も、事前にユーザ oracle を作っておかなければならない、インストール中に root でコンソールにログインしてコマンドを実行しないといけない。
あんまり簡単じゃないなぁ。
Windows版などと同じインターフェースでインストールできるという配慮もあるのだろうが、他のソフトウェアに様に、「make install」だけでさくっとインストールできるようにならんものなのだろうか。
このエピソードはいかがでしたか? ![]() ![]() | ![]() |
投稿者 zunbe : 2005/07/16 08:50:48 | コメント (2)
|
ずんべは、プログラムを書くとき goto をよく使う。
goto は諸悪の根源の様に言われるが、ずんべは goto を積極的に使っている。
たとえば、こんなコードである。
-----
int function(char * fname1, char* fname2)
{
FILE* fp1;
FILE* fp2;
int ret;
// コンストラクト
ret = FALSE;
fp1 = NULL;
fp2 = NULL;
// 本処理
fp1 = fopen(fname1, "r");
if (fp1 == NULL)
goto DO_ERROR;
fp2 = fopen(fname2, "r");
if (fp2 == NULL)
goto DO_ERROR;
// その他処理
ret = TRUE;
DO_ERROR:
// デストラクト
if (fp2 != NULL)
fclose(fp2);
if (fp1 != NULL)
fclose(fp1);
return ret;
}
-----
goto は、諸悪の根源だとよく言われる。
java では廃止されてしまったし、perlでも、昔から新バージョンでは実装されない可能性が囁かれている。
しかし、正しく使えば、構造化プログラミングどころか、オブジェクト指向に近いプログラミングが可能となる。
上記のコードがそうである。
このコードは、関数レベルでオブジェクト指向に近いコードを実現している。
■「コンストラクト」のブロック
関数内にあるオブジェクトを初期化している。
■「本処理」のブロック
実際の動作を行い、何か問題が発生すれば、処理を中断して「デストラクト」に飛ぶ。
■「デストラクト」のブロック
必要な終了処理をすべて行い、関数を抜ける。
gotoを使う事によって、関数レベルで「コンストラクト」「本処理」「デストラクト」という、オブジェクト指向の基本的な考え方が実現できている。
また、原則として、処理の流れは一直線に下に延びるので、コードの可読性が非常に高い。
更に、このコードは、メンテナンス性も高い。
たとえば、第3のファイル「fname3」が必要になったと仮定しよう。
プログラムの修正はこんな手順になる。
・引数および変数「fp3」を追加。
・「コンストラクト」ブロックに変数「fp3」の初期化を記述。
・「本処理」ブロックに変数「fp3」の処理を追加。
・「デストラクト」ブロックに変数「fp3」の終了処理を追加。
ネストをいじる必要もなければ、終了処理をいろいろなところで追記する必要もない。
もちろん、上記のコードがあらゆるパターンの開発に当てはまるとは思わないが、gotoも使い方によっては非常に有用である事を、言語仕様を策定する識者の方に知っていただきたいと思う。
このエピソードはいかがでしたか? ![]() ![]() | ![]() |
投稿者 zunbe : 2005/07/16 04:59:26 | コメント (0)
2005/07/15
|
C言語には「配列名」というものがある。
これが、いわゆる「変数名」と違うという事を知っているプログラムは意外に少ない。
「配列名」は変数ではない。実行時にローカルに定まる定数である。
変数ではないのだから、値を代入する事はできない。
たとえば、以下の様な事はできない。
-----
char a[2];
a = NULL;
-----
実際、配列名 a には、メモリは割り当てられていない。
スタックの積まれ方を見ればわかる。
コードの記述の通り、メモリは2バイトしか確保されない。
配列名 a そのものに対する記憶領域は存在しないのである。
残念な事に、最近のCコンパイラでは、以下の様なコードを書いても、警告もエラーも出ない。
-----
char a[256];
sprintf("%s", &a);
-----
しかしながら、このコードは明らかに間違いである。
配列名 a には記憶領域がないのであるから、そのアドレスを求める事はできないはずだ。
正しくは、以下の様にコードを記述するべきである。
-----
char a[256];
sprintf("%s", &a[0]);
sprintf("%s", a);
-----
「&a」というコードについては、まぁ、意味はわかるので、そう目くじらを立てる事でもないとは思うが、問題は、本来の仕組みを知らずにプログラマを組んでいるプログラマが多いことである。
最近は、Visual Basicなどの便利な言語があるので、こういった細かい話はどうでもよくなりつつあるが、若いプログラマは、アセンブラやC言語をきちんと勉強して、こういった基本的な動作を知ってほしいと思う。
このエピソードはいかがでしたか? ![]() ![]() | ![]() |
投稿者 zunbe : 2005/07/15 16:33:46 | コメント (0)
|
演算には優先順位がある。
たとえば、「2-3*4」という式で、「3*4」の演算が先に行われ、次に「2-12」が計算される。
これが演算の優先順位である。
ところが、長年プログラミングをやっている人でも、評価順序があることを知らない人は多い。
評価順序とは、「3*4」という演算で、「3」が先に評価されるか、「4」が先に評価されるかという事である。
一般的に、評価は左から右に行われるので、問題になる事はまずない。
しかし、ほとんどの言語において、評価順序は処理系依存となっており、必ずしも左から右に評価されるとは限らない。
以下のコードは、よく見かけるコードだが、潜在的にバグを含んでいる。
-----
if ((p != NULL) && (p->func() == true))
{
// 処理
}
-----
このコードは、左から右に評価される事を前提に記述されているが、先の通り、評価順序は左から右とは限らない。
つまり、「p->func() == true」が先に評価される可能性があり、変数 p が NULL の時、アプリケーションエラーを引き起こす。
「式は左から右に評価される」と明示的に仕様として確定されてもよさそうな気がするのだが。
■2006/0915追記
ななしさんより、「C/C++では、&&、|| などの演算での評価順序は、左から右と規格で決まっている」というご指摘を頂きました。
調査したところ、C/C++ではご指摘の通りであり、C/C++で記述した上記のサンプルは不適切でした。
しかしながら、他の演算子や、他の言語では、やはり、評価順序は不定であるため、プログラムの作成に際して注意を要する事は変わりありません。
このエピソードはいかがでしたか? ![]() ![]() | ![]() |
投稿者 zunbe : 2005/07/15 16:18:33 | コメント (0)
|
今日、こんな事があった。
簡単なバックアップのプログラムを社員に書かせたんだな。
仕様はこうだ。
(1).ファイル名は「YYYYMMDDHHNNSS.*」
(2).ローカルにあるファイル群を、他のサーバにFTPでアップロードする。
(3).指定期間以上経過したフバックアップァイルは、ローカル、サーバとも削除する。
(4).アップロード先のサーバに、既に存在しているファイルはアップロードしない。
(5).ファイルの日付は、ファイルのタイムスタンプではなく、ファイル名を用いる。
さて、社員がプログラムを作っているとき、こんな指示を出した。
・削除対象のファイルや、アップロード対象のファイルは、ファイル名にある日付で決めるのだから、以下の様に組みなさい。
「ファイルの一覧を取得した後、取得した一覧をファイル名でソートし、ソートした一覧の先頭から順に処理していき、日付が指定期間外になったところでループを終了しなさい。」
当然こうなりますな。
予めファイルの一覧を日付でソートしておいて、順に処理していけば、指定期間外になったところで、ループを終了すればいい。
それ以降に、指定期間内とマッチする事はありえないからだ。
ところが、うちの社員は仕様(4)でこれをやりおった。
サーバ上のファイルを走査して一覧を取得してファイル名でソート、その上で順位走査を行い、ローカルにあるファイルと突合せし、存在しているファイルを一覧から削除するというコードを書いた。
ところが、なぜか、「ファイルが存在していない」事を検出した時点で、その後の走査を打ち切り、それ以降は、全部アップロード対象とするコードになっていた。
こらこら、ファイルの存在の有無を検査するのに、なんで、日付が関係あるねん。
ファイルの日付に関係なく、「存在していないものをアップロード」しなければならないのに、何で「日付でソート」→「順にループ」→「ファイルが存在していないで終了」になるねん。
すべてのファイルを走査して、有無を検査しなきゃいかんだろうが。
まったく。
このエピソードはいかがでしたか? ![]() ![]() | ![]() |
投稿者 zunbe : 2005/07/15 01:10:16 | コメント (5)
| [<<先頭] [<前へ] [ 1 2 3 4 ] [次へ>] [最後>>] | ||