今回は、前章のプログラムを利用してカウンタを表示する仕組みを考えてみます。
左の図のような感じのカウンターを作ります。SSIは使いません。IMGタグのところに
CGIプログラム名を書いて呼び出しています。
前準備として0から9までの数字を表示したGIF画像を用意しておきます。GIF画像の 名前はそれぞれ0.gif, 1.gif,...9.gifのようにします。背景は透明にしても、好みの 色にしてもよいでしょう。なるべく表示を軽くするために減色しておきます。これらのファイルは imgというフォルダを作って、そこに入れておきます。
また、logというフォルダを作っておきcount.txtというファイルを作っておきます。このファイルにはカウンタの初期値を6桁で書き込んでおきます。(1から表示したいなら000001のように書き込んでおきます。)
呼び出し側のHTMLは次のような感じになります。
<HTML> <HEAD> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <TITLE>カウンタ表示</TITLE> </HEAD> <BODY BGCOLOR="yellow"> <CENTER> <H1>カウンタ表示</H1> <IMG SRC="img02.cgi?1"> <IMG SRC="img02.cgi?2"> <IMG SRC="img02.cgi?3"> <IMG SRC="img02.cgi?4"> <IMG SRC="img02.cgi?5"> <IMG SRC="img02.cgi?6"> </CENTER> </BODY> </HTML>これを見てわかるように、IMGタグのところでCGIプログラム(img02.cgi)を呼び出しています。 また、プログラム名の後に「?」マークを入れて、プログラムに渡すデータを記載しています。 この場合、カウンタの先頭から順番に1,2,...6としてあります。(6桁表示)
通常はHTMLファイルを置く場所とCGIプログラムを置く場所は全然違うところになるので CGIプログラム名の前にディレクトリがつくのが普通です。
今回の方式ですとSSIが使用不可の環境でも実現できます。
では、プログラムはどうなっているのでしょうか。
// img02.c
#define FCOUNT "log/count.txt"
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
int loadpic(int, int);
int main()
{
char *lpno;
int keta;
FILE *fp;
int cnt;
lpno = getenv("QUERY_STRING");
keta = atoi(lpno);
//カウンタの読み込み
fp = fopen(FCOUNT, "r");
if (fp == NULL)
return -1;
fscanf(fp, "%d", &cnt);
fclose(fp);
//画像出力関数を呼び出す
loadpic(keta, cnt);
//1桁目を出力したらカウンタの数値を増やして書き込み
if (keta == 6) {
cnt++;
fp = fopen(FCOUNT, "w");
if (fp == NULL)
return -1;
fprintf(fp, "%06d", cnt);
fclose(fp);
}
return 0;
}
main関数です。lpno = getenv("QUERY_STRING");
これで、HTMLからCGIプログラムを呼び出すとき「?」以降に記載した文字列を 取得できます。ここでは、int型の数値に変換して変数ketaに格納しています。
次にcount.txtファイルから書き込まれている文字列を数値として読み込みcntに格納します。
そして、loadpic関数を呼び出します。
ketaが6まで来たらcntを1増やしてcount.txtファイルに上書きします。
int loadpic(int keta, int cnt)
{
int j;
unsigned char buf[4];
FILE *fp;
char szFname[16], szTemp[16];
//カウントを6桁の文字列に
sprintf(szTemp, "%06d", cnt);
//呼び出す画像ファイル名を作る
sprintf(szFname, "img/%c.gif", szTemp[keta-1]);
//画面に出力
printf("Content-type:image/gif\n\n");
fp = fopen(szFname, "rb");
if (fp == NULL)
return -1;
_setmode(_fileno(stdout), _O_BINARY);
while (1) {
j = (int)fread(buf, 1, 1, fp);
fwrite(buf, 1, j, stdout);
if (feof(fp))
break;
}
fclose(fp);
return 0;
}
これは、ほとんど前章のプログラムと同じですね。違うところは、引数のketaとcntから読み込んで表示するgif画像のファイル名を作っている点です。
今回も簡単でした。実際には、インターネットでは多くの人がアクセスするので、ファイル入出力 のところで、排他制御しないとファイルが破損するおそれがあります。
Update May/19/2003 By Y.Kumei