広告
↓発売日:2018年09月22日↓
新品価格 |
しばらく離れておりましたが、再びポインタのお時間です。
ため息が聞こえてきそうですが、避けては通れない道なのでがんばりましょう!
まずは構造体の変数をポインタにしてみます。
/*十二日目 プログラム1*/ #include <stdio.h> struct DENWABOOK{ const char* name; const char* tel; }; int main(){ struct DENWABOOK no1; struct DENWABOOK* no1_p; no1.name = "鈴木一郎"; no1.tel = "09011111111"; no1_p = &no1; printf("お名前:%s 電話番号:%s\n",no1_p -> name,no1_p -> tel); return 0; }
構造体でポインタを使う場合もキホンは変わりません!
ポインタの事は覚えておりますでしょうか?
「*」アスタリスクをつければポインタ変数になるんでしたね!
int* p;
これを構造体に変えるだけです!
struct DENWABOOK* p;
これだけで大丈夫です!
そして同じようにアドレスを保存します!
アドレスは先頭に「&」アンパサンドでしたね!
no1_p = &no1;
これで「no1_p」にアドレスが保存されます。
それではここから内容を確認するべく間接参照するやり方ですが見た事のない記号がありますね。
「->」
こちらです。前回までの「no1.name」の「.」コンマの部分が「->」になりました。
これもまあ・・・。そのまま覚えてください!
構造体ポインタからそれぞれのメンバを確認したい時は
no1_p -> name; no1_p -> tel;
のようにします。
これを「矢」のようなカタチをしている所から「アロー演算子(えんざんし)」といいます!
/*十二日目 プログラム2*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> struct DENWABOOK{ char name[128]; char tel[128]; }; void func(struct DENWABOOK* ); int main(){ struct DENWABOOK no1 = { "鈴木一郎", "09011111111" }; printf("変更前\n"); printf("お名前:%s 電話番号:%s\n\n",no1.name,no1.tel); func(&no1); printf("変更後\n"); printf("お名前:%s 電話番号:%s\n",no1.name,no1.tel); return 0; } void func(struct DENWABOOK* no1_p){ strcpy(no1_p -> name,"佐藤三郎"); strcpy(no1_p -> tel,"09012345678"); }
他の関数に渡す場合もキホンは変わりません。
まずはプロトタイプ宣言です。
普通の変数でポインタを関数に渡す時は
void func(int* );
でしたね。構造体の場合も同じように
void func(struct DENWABOOK* )
「*」アスタリスクをつけます。
そして「int main()」内で関数「func」に構造体のアドレスを渡します!
func(&no1);
アドレスを渡す時は先頭に「&」アンパサンドですね。
あとは関数「func」の内容ですね!
void func(struct DENWABOOK *no1_p){ strcpy(no1_p -> name,"佐藤三郎"); strcpy(no1_p -> tel,"09012345678"); }
受け取る変数名を「*no1_p」に決めました。
そして内容を確認、変更する時は「->」アロー演算子を使えばオッケーですね!
ポインタで受け取って変更しているので元の変数の内容も変更されているのが確認できますね。
広告
/*十二日目 プログラム3*/ #include <stdio.h> struct STUDENT{ char name[128]; int age; }; void func(struct STUDENT* ); int main(){ struct STUDENT student[5] = { {"鈴木一郎",15}, {"田中二郎",14}, {"佐藤三郎",15}, {"斎藤四朗",13}, {"渡辺五郎",14} }; func(student); return 0; } void func(struct STUDENT* student){ int i; for(i=0;i<5;i++){ printf("生徒名:%s 年齢%d才\n",(student + i)->name,(student + i)->age); } }
構造体配列を他の関数に渡す場合も見てみましょう。
配列の場合は配列名だけ渡すのでしたね。
struct STUDENT student[5];
この構造体配列だとすると配列名は「student」になるので
func(student);
こうなりますね!
そして配列名だけの場合はそのまま先頭アドレスを表す事になるので渡された関数本体の方で内容を確認、変更する時は
student->name; student->age;
そのまま「->」アロー演算子をつければ確認できます。
ただ配列の他の要素を確認する時だけは少しややこしい書き方になるので注意です。
(student + 2)->name;
先に()カッコでくくって目的のデータまでポインタ演算してから確認するという感じなります。
最後に構造体の中に構造体を持つ方法を見ていきましょう。
構造体も変数の一つなので、構造体の中に他の変数と同じように構造体を入れる事もできます!
ちょっとややこしいので一つ一つやっていきましょう!
まず内容ですが、ロールプレイングゲームのキャラクターのステータスを構造体で作って、
その装備としてもう一つ構造体を作ろうと思います。
まずはキャラクターのステータスですね!
名前「太郎」年齢「20」構造体の名前「PARTY」
これを構造体にします。
struct PARTY{ const char* name; int age; };
名前「const char* name」年齢「int age」としました。
次にその装備を構造体として作ります。
武器「鉄の剣」防具「鉄の鎧」構造体の名前「SOUBI」
こんな内容で作ってみます!
struct SOUBI{ const char* buki; const char* bougu; };
これも別々に考えれば簡単ですね!
武器「const char* buki」防具「const char* bougu」としました!
ではこれをさっきの構造体「PARTY」に入れるには、どうしましょう?というお話ですね。
普通の変数は「int age」というようにできます。
構造体の場合も変わりません。
という事は
struct SOUBI tarou_soubi;
こんな感じのを中に入れれば良さそうです。
他の変数と同じくここで「tarou_soubi」と変数の名前を決めている所に注意です。
まとめると
struct PARTY{ const char* name; int age; struct SOUBI tarou_soubi; };
こうなりますね!
それではこの構造体を使ってプログラムを組んでみましょう!
/*十二日目 プログラム4*/ #include <stdio.h> struct SOUBI{ const char* buki; const char* bougu; }; struct PARTY{ const char* name; int age; struct SOUBI tarou_soubi; }; int main(){ struct PARTY tarou; tarou.name = "太郎"; tarou.age = 20; tarou.tarou_soubi.buki = "鉄の剣"; tarou.tarou_soubi.bougu = "鉄の鎧"; printf("名前:%s 年齢:%d\n", tarou.name,tarou.age); printf("武器:%s 防具:%s\n", tarou.tarou_soubi.buki,tarou.tarou_soubi.bougu); return 0; }
2つの構造体を書く順番に注意です!
「struct PARTY」の中で「struct SOUBI tarou_soubi」と変数名まで決めているので、その前に「struct SOUBI」の内容を書かないとエラーになります。
あとはさきほど説明したとおりですね!
それでは、その構造体の中の構造体の内容を確認してみたいと思います。
tarou.tarou_soubi.buki;
「構造体の中の構造体の中の内容」って感じですね!
このように「.」ドットで区切りを入れてさらに次の構造体変数名を指定すれば目的のデータを確認する事ができます。
こんな感じでさらには構造体「SOUBI」の中に武器の性能として構造体を入れたりなんかすると
tarou.tarou_soubi.buki.buki_seinou;
みたいにえんえんと奥に奥に続けられるワケです。
これを使えば複雑なデータも構造体を分ける事によって階層化できますね!
ちなみにこのメンバの一つがポインタだったりすると当たり前ですが
taoru->tarou_soubi.buki;
途中が「->」アロー演算子になったりします。
ここまでで構造体の説明はひとまず終わりにしたいと思います。
先にも言いましたが構造体は現在主流のオブジェクト指向プログラミングで使われるクラスの元になるようなとても大事な技術です。
ポインタなどが絡んでくると少し難しいですが、これを身につければプログラミングの幅も広がると思いますので何度もポインタらへんから繰り返し復習して覚えてしまいましょう!
次回は関数ポインタについて見ていきたいと思います。
広告
↓発売日:2016年02月29日↓
12歳からはじめる ゼロからのC言語 ゲームプログラミング教室 新品価格 |
↓発売日:2018年06月22日↓
新品価格 |
↓発売日:2018年03月09日↓
新品価格 |
↓発売日:2017年06月14日↓
新品価格 |
↓発売日:2018年05月21日↓
新品価格 |
↓発売日:2017年12月07日↓
新品価格 |
↓発売日:2017年02月08日↓
新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ) 新品価格 |
↓発売日:2017年09月26日↓
新品価格 |