アットウィキロゴ
まず、ポインタとは何か。。。
説明する前に、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