まず、ポインタとは何か。。。
説明する前に、PCの構造を理解しないといけません。
C言語では関数を宣言するとPCのメモリ上に
関数が存在する場所を確保します。
同じように、変数を関数の中で宣言すると、
変数が存在する場所をメモリ上に確保します。
それぞれがメモリ上にある場所を確保すると、今度はその場所の中に
文字列やら、数字やらを入れていくわけですが、、、
関数間で大きなデータをやり取りすると、どうしても
関数の中でそれぞれの変数を宣言することになり、
メモリを大きく消費してしまいます。
そこで、大きな変数をやり取りする際には、
それぞれの変数がどこにあるかを把握し、
その場所を関数間でやり取りをしてあげると、
使うメモリの量は極端に少なくなります。
。。。前置きはこのくらいにして、
今回もソースを見て行きましょう。。。
と、そのまえに、次のようなtxtファイルを、
ソースのあるディレクトリ(フォルダ)に[test2.txt]って名前をつけて用意しておいてください。
inoue,30,さいたま市
。。。一行でいいです。
お好みに応じて追加してもいいですけど。
それでは、ここからソースになります。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int hyouzi(char* buff);
typedef struct{
int age;
char name[20];
char adr [20];
} add;
int main()
{
FILE *fp;
char a[20];
char buff[20];
memset(buff,'\0',sizeof(buff));
memset(a,'\0',sizeof(a));
fp=fopen("test2.txt","r");
if(fp==NULL)
{
printf("ファイルが開けませんでした。\n");
return 1;
}
fgets(a,sizeof(a),fp);
strncpy(buff,a,strlen(a)-1);
hyouzi(buff);
close(fp);
return 0;
}
int hyouzi(char* buff)
{
add add1;
char a[20];
char agen[20];
char pt[20];
char pt2[20];
char *pa;
memset(&add1,'\0',sizeof(add1));
memset(agen,'\0',sizeof(agen));
memset(pt,'\0',sizeof(pt));
memset(pt2,'\0',sizeof(pt2));
pa = strchr(buff,',');
strcpy(pt,pa);
strncpy(add1.name,buff,strlen(buff)-strlen(pt));
printf("name=%s\n",add1.name);
memset(pt,'\0',sizeof(pt));
strcpy(pt,pa+1);
pa=strchr(pt,',');
strcpy(pt2,pa);
strncpy(agen,pt,strlen(pt)-strlen(pt2));
add1.age=atoi(agen); /* 使ってみたかっただけ */
printf("age=%d\n",add1.age);
strcpy(add1.adr,pt2+1);
printf("adr=%s\n",add1.adr);
return 0;
}
まずは全体の説明を。。
main関数ではファイルを読み込み、
読み込んだ情報を hyouzi関数に渡しています。
hyouzi関数では、わたされた情報から、必要な部分を切り出して
わかりやすいように表示をしています。
表示が終わるとmain関数に処理成功を通知して、
main関数がファイルを閉じます。
次は細かく各箇所を見ていきましょう。
まずは、
int hyouzi(char* buff);
関数宣言時にchar型のアドレス(ポインタ)を引数として宣言します。
これで、現物ではなくて、ポインタで関数間の変数のやり取りが出来ます。
hyouzi関数ではbuffの中身をいじります。。。ということですね。
次は、
FILE *fp;
今回のようにファイルの入出力時には、
必ずファイルのポインタを宣言してあげなければなりません。
そこにファイルの中身をはりつけて使えるようにするのです。
そして、
char buff[20];
これを今回は関数間で渡して、中身をhyouzi関数でいじります。
。。。あれ???って思った人。。。鋭いです。
char buff[20];
は実体で、
char* buff
はポインタになります。
ポインタは大きさを宣言しません。
なぜなら、ポインタはその変数が
メモリ上のどこにあるかを示すだけの変数であり、
大きさはまったく見ていないからです。
ためしに、このソースのどこかに
printf("sizeof(buff)=%d\n",sizeof(buff));
と、一文加えてポインタのサイズを表示してみてください。
もっと時間のある人は、hyouzi関数内で
printf("sizeof(add->age)=%d\n",sizeof(add->age));
と加えて、int型のポインタとchar型のポインタは大きさに何も変化がないことを
確認してください。
では、int型のポインタと、char型のポインタは何が違うのでしょう。
答えは、「動き」です。
ためしに、hyouzi関数に以下の部分と追加してみてください。
printf("char* buff=[%d]\n",buff);
printf("char* buff +1=[%d]\n",buff+1);
printf("add1->age=[%d]\n",&add1.age);
printf("add1->age+1=[%d]\n",&add1.age+1);
すると、char型のポインタとint型のポインタでは、
明らかに数字の増え方が違うと思います。
実は
「ポインタに 1 加える」ということは
「ポインタに格納されているアドレス + 1番地」ではなく
「ポインタに格納されているアドレス + 型のサイズ」
ということになります。
つまり、同じ「++p」でも
char型なら サイズ 1バイトなので 1番地
int型なら サイズ 2バイトなので 2番地
long型なら サイズ 4バイトなので 4番地
float型なら サイズ 4バイトなので 4番地
double型なら サイズ 8バイトなので 8番地
構造体ならその構造体分だけ
アドレスが増えることになります。
。。。ここまで説明すると、
後は
ヘッダ&標準関数表を見ながら
このソースが解読できると思います。
どうでしょうか。。。ここまでくれば後は慣れです。
がんがんソースを書くしかないと思います。
わからないことは
bbsに書き込んでください。
誰かが答えてくれます。
。。。でもね、調べることが出来るっていうことも
大事なスキルなんですよ。
最後に、malloc/reallocをつかって、
簡単なエディタを作ってみましょう。
[仕様]
1)ファイルに書き込むのはユーザーが
書き込み終わって、リターンキーを三回押したら
(改行三回連打で自動書き込み。。。強制)
2)ファイルの頭には書き込んだ日付と
最初の一行の先頭5文字が自動的に入ること
3)絶対にメモリリークはさせないこと。
。。。以上
お疲れ様でした。
最終更新:2007年02月02日 15:56