2007年9月12日水曜日

プログラミング言語の歴史

プログラミング言語というものは
コンピュータに何らかの処理を行わせるために、
あらかじめ書かれた命令の集まりである。
世の中には多くのプログラミング言語が存在するが
ここでは歴史と背景から、各々のコンピュータ言語について考えたいと思います。

初期のコンピュータ(コンピュータというよりも電子計算機といった方が適切かな)には、
プログラムを記憶するための主記憶装置がなかったので、
配線やスイッチ類によって計算順序や入力データ等を指定するしかありませんでした。


その後、プログラム内臓方式の計算機が開発され、機械語により命令を与えることができるようになりました。
機械語(マシン語)は、
CPUが解釈できる0と1の2値を、2進や16進で表現できるようにしただけの最も低いレベルのプログラム言語です。
この時代、プログラムを組むと言うことは、この機械語を直接入力することでした。


機械語は、数字並びを指定するので、それを少しだけわかりやすくしたアセンブリ言語が登場します。
アセンブリ言語は、それぞれの命令に意味のある短い単語を割り当てて、
読みやすく書き表せるようにしました。

2007年8月10日金曜日

Program received signal SIGSEGV, Segmentation fault.

C言語で書いたプログラムが、SIGSGVのシグナルを受けて終了、セグメンテーションフォルトになる場合のデバッグ方法

isii> ./a.out 1301051.htm

Segmentation fault


メモリ操作の誤りによって、不正な位置に書き込んだりすると、
セグメンテーションフォールトとなり、プログラムは殺されます。

ソース中の問題箇所を探す場合はデバッガを使います。
ここでは、GNUのgdbを紹介します。

(1)デバッグ情報を埋め込む
まず、コンパイル時に-gオプションを指定して、デバッグ情報を埋め込みます。

> gcc -g getword.c

(2)デバッガーを起動する
gdbを起動して、問題の実行ファイルをロードします。

> gdb a.out
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (sparc-sun-solaris2.5.1),
Copyright 1996 Free Software Foundation, Inc...
(gdb)

(3) プログラムを実行する。
gdbのrunコマンドで実行します。パラメータがある場合は、指定します。

(gdb) run 1301051.htm

Program received signal SIGSEGV, Segmentation fault.
0xef7291fc in strcpy ()
(gdb)

(4) 問題の場所を特定します

(gdb) where
#0 0xef7291fc in strcpy ()
#1 0x10ab4 in GetWord (fp=0xef79ab40, wd=0xefffed08 ">",
demilit=0x10e50 ";#<>()[]!\n", line=0xeffff10c) at getword.c:169
#2 0x10d4c in main (argc=2, argv=0xeffff18c) at getword.c:242
(gdb)

2007年7月31日火曜日

C言語の典型的バグに注意

典型的なC言語のメモリの扱いに関するバグ・・・初歩的で常識的なこと
しかし、実際にバグは発生している。
開発に携わっている人の中には、基本を理解していない人も多いようだ

【マイコントラブル5】機器操作中に突如リセット,C言語の典型的バグに注意

アドレスを表示する

printfで書式として%pを指定すれば、変数のアドレスを表示することができる。

char *p = "Hello, World";

printf( "%p\n", p);



まだプログラム初心者の子から質問を投げかけられた。
こういったサンプルコードが書かれている書籍を読んで勉強中だ。
そこに書かれているコードとともに実行結果が書いてあるのだが、
コードを打ち込んで、実行したら結果が同じにならないというわけだ。

プログラムは、ファイルとしてハードディスク上に存在する。
プログラムを実行するということは、
シェル上からコマンドを打ち込んで、エンターキーを押したとき、
その実行ファイルがメモリ上にロードされる。
"Hello, World"という文字列リテラルは、メモリ上のどこかに配置される。
そのとき、配置する場所は環境によって変わる。
したがって、環境が異なれば、違って当然である。

2007年7月24日火曜日

データふぁいるを読み込んで、リストを作成する

* ファイルをオープンして、1行づつ処理します。
* 1行から1組のデータを取り出します sscanfで、id, name, ymdに分解しています。
* 更にymdの文字列から、年、月、日の整数にしています。
* スラッシュを空白に変えたあとで、sscanfで年(y),月(m),日(d)を取得しています。
* 実は、sscanf(ymd,"%d/%d/%d", &y, &m, &d);だけでも動作します。
* addPersonal関数に渡します。


int readDataToMemoryList(char *filename)
{
FILE *fp;
int id;
char name[256];
char ymd[256];
char buf[BUFSIZ];
int y, m, d;

fp = fopen(filename, "r");
if ((FILE *)NULL == fp ) {
fprintf( stderr, "ERROR : Can not open %\n", filename);
return 1;
}

while ((char *)NULL != fgets( buf, sizeof buf, fp)) {

if ( DATA_COLUMN == sscanf(buf, "%d %s %s\n", &id, name, ymd)) {

char *p;
while ((char *)NULL != ( p = strchr(ymd, '/'))) {
*p = ' ';
}
sscanf(ymd,"%d %d %d", &y, &m, &d);

if ( addPersonal(id, name, y, m, d )) {
return 3;
}
}
}
fclose(fp);
return 0;
}

1組のデータを読み込みメモリ上に展開する

* 引数で、メンバにセットする、ID, 名前、生年月日(年、月、日)を渡す。
* crPersonal関数を使ってPersonal構造体の領域を確保し、メンバを初期化する。
* メンバでポインタ変数の場合は、メモリ確保。Personal構造体は、メンバnameがポインタであるため、名前を保存するために必要な領域を確保し、その領域の場所をセットする。
* 1つ目のデータの場合には、リストの先頭topにセットする。
* 1つ目のデータでない場合は、最後に追加する。

int addPersonal(int id, char *name, int y, int m, int d)
{
Personal *ip = crPersonal();
if ((Personal *)NULL == ip) {
return 1;
}

ip->id = id;
ip->name = (char *)malloc(strlen(name)+1);
strcpy(ip->name, name);
ip->birthday_y = y;
ip->birthday_m = m;
ip->birthday_d = d;

ip->next = (Personal *)NULL;

if ( top == (Personal *)NULL ) {
top = ip;
} else {
Personal *cp;
for ( cp = top; cp != (Personal *)NULL; cp = cp->next ) {
if ( cp->next == (Personal *)NULL ) {
cp->next = ip;
break;
}
}
}

return 0;
}

※あくまでも学習用なので冗長な処理を書いています。毎回、先頭から最後の要素を検索しているのは無駄なので、本来であれば、最後に登録した要素のアドレスをグローバルに保存しておくことで、一発で追加することができます。


1つ目のデータを読み込んだイメージ


2つ目のデータを読み込んだイメージ

ひとつの要素のメモリ領域を確保して初期化する

Personal構造体の領域を確保し、メンバ変数を初期化します。そして、領域の先頭アドレスを返します。


Personal* crPersonal(void)
{
Personal *pp;

pp = (Personal *)malloc(sizeof(Personal));
if ((Personal *)NULL == pp ) {
return NULL;
}
pp->id = 0;
pp->name = (char *)NULL;
pp->birthday_y = 0;
pp->birthday_m = 0;
pp->birthday_d = 0;
pp->next = (struct personal *)NULL;

return pp;
}





メモリ確保はmalloc関数で行います。
malloc関数には引数で指定したバイト数の領域を確保し、その領域の先頭アドレスを返します。
sizeof演算子は、この型のサイズを返します。このように実際のサイズは処理系によって変わってくるので、このような計算はコンパイラにお任せします。

自己参照型構造体とリスト

前回、Personal構造体を宣言した。
この構造体は、メンバの中にその構造体自身のポインタを持っている。
このような構造体を自己参照型の構造体と呼ぶ。

nextというメンバ名にしているのには意味があります。

このポインタ変数を使って、1つ1つ要素を辿れるようにするためです。

そのためには、先頭の要素の場所を保存し、そこから
1つづつ要素を辿れるようにメモリ上にデータを配置していく必要があります。

ソースでは、ヘッダpersonal.hをインクルードします。
Personal構造体のリストの先頭要素を指し示すポインタ変数としてtopを宣言します。


# include
# include
# include "personal.h"

# define DATA_COLUMN (3)

Personal* top = (Personal *)NULL;

2007年7月22日日曜日

デニスリッチーとカーニハン

プログラミング言語C ANSI規格準拠

C言語の開発者のデニスリッチーとカーニハンが書いたバイブルとして
K&Rとよばれる本がある。昔からバイブルとして、Cのプログラマはこれを持っていたものです。
ANSIが制定され、内容の新しくなっていますが、C言語を習得したい人はバイブルとして一冊手元の置いておくことをすすめます。

よく、初心者はこの本を読まないほうがよいとか言う人がいますが、
サンデープログラマーとかの趣味であれば、どこから入ろうが何を読もうがよいですが、
C言語で飯を食うのであれば、最低この本を理解することを目標にすすめるのがよい。
私の考えでは、この本に書かれていることを一通り理解できるまでは、ビジネス上での
プログラムは書くなといいたい。ちと厳しいだろうか?

もっと言えば、ソフトウエアの開発に従事するのであれば、
C言語の言語仕様は、プログラミング言語の基本として理解しておいて欲しいと思います。

なぜかといえば、プログラムを作る上では、
以下のような事について意識的に考える事が必要であり、
このようなことを意識して仕事をすることによって、
考える事のできるエンジニアになれる可能性があるからです。

・データ型の意識
 各データ型のサイズと表現できる値の範囲
・メモリの管理について
 メモリの確保・解放
・効率よいデータ構造とアルゴリズム
 ポインタを利用することによって
 できるだけ小さいリソースでも動作することと
 そして、高速に動作することを意識する
・メモリ上のデータ操作
 文字列型などがないおかげで、一番低レベルな視線で
 処理を考える事ができる

まあ、ポインタでつまずく人が多いのだけれど、
これは言語仕様だけで覚えようとするからつまづくのであって、
コンピュータの仕組みなどの基礎知識とあわせて
C言語の言語仕様を理解して欲しいと思います。

2007年7月19日木曜日

構造体を宣言してみる

まずはヘッダファイル personal.hから。
ここでは、個人情報の構造体を宣言します。


# ifndef __PERSONAL_H__
# define __PERSONAL_H__

typedef struct personal {
int id;
char *name;
int birthday_y;
int birthday_m;
int birthday_d;
struct personal *next;
} Personal;

# endif





いろいろ書いてあるが、噛み砕いて説明していこう。
構造体の宣言自体は、struct <構造体タグ名> { ~ } までのところです。
struct personalというデータ型を定義したことになります。

したがって、これ以降で、


struct personal p;



struct personal *p;

などの変数宣言をすることができます。

構造体は、{から}までの中のメンバ変数の1組のデータ構成を、
1つのデータ型として扱えるようにするためのものです。

構成のイメージ図を見るとわかりやすいと思いますが、
整数、ポインタ、整数、整数、整数の構成で新たなデータ型
struct personal型としてプログラム中で利用できるようになります。

2007年7月14日土曜日

プログラムの構造

プログラムの機能や入出力、ユーザインタフェースなどいろいろな要素が
絡んでくると、どこから手をつけていけばよいのか見失ってしまいます。

本来、プログラムを作る場合には、機能仕様書があり、
その機能を実現するために、プログラムの詳細設計を行います。

その中で、データ構造やアルゴリズムを考えます。

プログラムの構造は、大雑把に以下に分類できます。

・自分が宣言するデータ構造
・自分が記述するプログラムコード
・利用するライブラリ

ここでは、何か例をもとに考えてみましょう。
あるひとつのデータ構造を利用できるようにすることを考えてみます。

ID 名前 生年月日 年齢

が書かれたファイルがあります。
この個人情報ファイルをプログラムから利用できるようにすることを
例に考えていきます。

・ヘッダファイル
・ソースファイル

符号化と符号化方式

コンピュータ上では、いまやテキストだけでなく、
画像や映像、音楽などさまざま種類の情報を扱うことができている。

これは、それらの情報を符号化して取り扱っているわけです。

符号化とは、コンピュータで取り扱える形式のデジタルデータに変換する
作業のことです。

その符号化したものを元のデータに戻すことを復号といいます。

その符号化する方法には、そのデータによって適切ないろいろな方式が
考えられています。

2007年7月13日金曜日

関数

関数型 関数名( 引数並び );


/* ANSI Prototype */
int main(int argc, char **argv)
{

return 0;
}

/* K&R Style */
int main(argc, argv)
int argc;
char argv;
{

return 0;
}


関数を作る際に、決めることは、
その関数は何を入力とし、
どんな処理をして、
何を出力する(返す)のか。

まず、処理がわかるように関数名をつけましょう。

例えば、個人情報を得る場合、getPersonalInfo などのように、

「動詞+名詞」の形式で名前をつけるとわかりやすくなります。


入力は、引数で受け取る。
処理は、関数内の手続きとなる。
出力は、戻り値で返す。


引数が沢山になってきたり、戻り値が複数になるとかの場合は
構造体を宣言し、データ構造を考えよう。

2007年7月12日木曜日

PHPやAjax

smarty

PHP用Ajaxライブラリ
xajax 0.2.5

WEB2.0用JavaScriptフレームワーク
prototype.js

Prototype Window Class prototype.jsを利用したウインドウクラスライブラリ
http://prototype-window.xilinus.com/index.html
↓サンプル
http://prototype-window.xilinus.com/samples.html

Rico

2007年7月11日水曜日

Hello, world

Hello, worldを標準出力に印字する。
K&Rの冒頭で書かれているコードである。
これをもとに、さまざま言語でも、最初のチュートリアルとして
このHello, worldを印字するコードを掲載している場合がおおい。


#include

int main(void) {
printf("Hello, world!");
return 0;
}


この短いコードは、
単に、文字列リテラルを、標準出力に出力しているだけではあるが
プログラミング言語の各要素をシンプルに説明するための良い題材となっている。

プリプロセッサについて
stdio.hの存在
main関数
printf関数を利用する
文字列リレラル
戻り値

プログラミング言語の種類 手続き型とオブジェクト指向

このわけかたも、あまりにも乱暴なのだが
オブジェクト指向と非オブジェクト指向としたほうがよいかもしれない。
クラスあり、クラスなしのほうがすっきるするかもしれない。

昔は、コンピュータに実行させる命令を並べて書いた。
そして、それを、わかりやすく構造化した。

さらに視点を変えて、自律したオブジェクトがメッセージを受け取って
処理を行うようになった。

2007年7月9日月曜日

プログラミング言語の種類 インタプリタ コンパイラ

色々な言語があるがあるが、大きくわけて
インタプリタ型プログラミング言語
コンパイラ型プログラミング言語
の二種類にわけることができる。

スクリプト言語ともよばれる
インタプリタ型プログラミング言語は、
インタプリタとよばれるプログラムが、
記述したソースファイルのプログラムコードを逐次解釈しながら、実行する。

それに対して、コンパイラ型プログラミング言語は、
コンパイラと呼ばれる翻訳プログラムによって、
ソースファイルからCPUが直接解釈可能なネイティブなコードを生成し、
ライブラリファイルなどとリンクされて実行ファイルとなる。
実行形式のファイルフォーマットは、OSによって異なり、
コンパイルする環境に依存することになる。

Javaは、コンパイルをするが、実行ファイルを直接生成するわけではなく、
中間コードを生成する。
この中間コードを各環境用に提供されているバイトマシンが解釈して実行する。
このため、同一のプログラムを様々な環境で動作することが出来る。

2007年7月7日土曜日

トライ アンド エラー

試して、どんどん失敗するべし

失敗が経験になる

理論ばっかりの頭でっかち野郎にはなってはいけない

何事も、自分の経験がものを言う

エラーに怯むな

バグなんて出るのが当然と構えよ

ただし、同じ過ちを繰り返すな

複雑にしているのは人間なり

コンピュータの仕組みや、標準化された仕様などは
基本的にはシンプルであり、合理的かつ現実なものだと
思います。

そもそも、コンピュータやプログラミング言語は、
問題解決を助ける道具として登場してきたわけです。

ですから、それらの仕組みを正しく理解すれば
どんな人でも、プログラムを作ることは可能です。

逆にいえば、そういった仕組みをしらずに
無駄な時間をかけている技術者が多いのも事実。
何が普遍的で重要な要素であるかさえ、見つけられていないまま
時が過ぎていく・・・

つぼといえる部分は、結構小さい部分です。

2007年7月6日金曜日

自分の作りたいものを見つけよう

自分が作りたいものを見つけましょう。

それを生き生きつくりましょう。

自分の要件を、
自分が設計し
自分で製造する。

人に言われたことだけ作っているよりも、
いろいろな経験ができるはずです。

言語仕様

どんな言語を習得するにせよ、言語の仕様書とライブラリのリファレンスは
購入しよう。

最近ではネットのあちこつで参照できたりするけれども
仕事でプログラムを書くのであれば、自己投資すべきだ。

言語の仕様なんてものは、本当はコンパクトなものだ。
一字一句最初から暗記なんてしなくてよい。

まずは言語仕様には、どんな項目が用意されているのか?
を知ろう。

・データ型
・変数や定数
・関数と引数の渡し方
・制御構文
・標準関数

手続き型の言語であれば、こんなものが用意されている。
オブジェクト指向の言語であれば、クラスなども用意されている。

さまざまな言語があるが、記述の仕方が多少違うだけで、やれることは同じだ。

the popularity of programming languages

The TIOBE Programming Community index gives an indication of the popularity of programming languages.

http://www.tiobe.com/index.htm?tiobe_index

1.Java
2.C
3.C++
4.PHP
5.(Visual)Basic
6.Perl
7.Python
8.C#
9.JavaScript
10.Ruby
11.Delphi
12.SAS
13.PL/SQL
14.D
15.ABAP
16.Lisp/Scheme
17.Ada
18.FoxPro/xBase
19.Fortran
20.COBOL

■Good language


わたしのプログラミング言語歴史は
fortran
C
sh/csh/bash
Lisp
perl
C++
Delphi
VB
PL/SQL
JavaScript
Java
PHP
Ruby
Python

UNIX上ならC(これが一番長い)
Windows上ならDelphi(最近はぜんぜん使ってない)
WEB系ならPHP

最近はプログラムはほどんど書かない。
写真を撮るほうが多い。(笑)

入力と出力

システムを中心に考えた場合、入力があり、出力があります。
大きいシステムでも、小さいシステムでも、構成として

入力→システム→出力

を整理して単純化することが大切です。

そして、そのシステム自体は、何をするのか。
これが、わかっていないままコード書くなよ。

2007年7月5日木曜日

The Programming is not The Programing Language

プログラミングという作業は、非常に楽しいものです。
しかし、時には苦みばしった顔でコードと睨めっこしている人もいます。
プログラミングというと、まずはプログラミング言語からはいるのですが、
言語だけではプログラムは作れません。

一歩下がって、もっと視野を広げてみてみましょう。

そんなブログです。