らずらいと姫の挑戦日記(第37回)~構造体~
2017-02-15
先週は、配列で文字列を扱うところを勉強しました。
今回は、さまざまな型を一つのカタマリで扱うことが出来る『構造体』について勉強します。
構造体とは
例えば、従業員名簿を作成したい場合、①名前(文字)、②従業員番号(数字)、③住所(長い文字)のデータを扱いますが、それぞれ型が違ってしまいます。でも、名前・従業員番号・住所の3セット揃って1つのデータとして扱えたほうがとても便利です。
このような時に、型の違うデータを1つのデータとして扱えるのが『構造体』です。
使い方
書式の設定
このとき、name, id, addrなど構造体内の変数をメンバー変数といいます。
さて、この構造体はここに含む変数を定義しただけで、データの中身というか実態は何もありません。
- struct → 構造体(personal_info という名前です。)
- char型 → 64バイト分の文字データが扱えます。
- unisighed short型 → 従業員番号
- char型 → 128バイト分の文字データが扱えます。
構造体の使用方法
実際に実験用のプログラムを作ったので、それを使用してテストしてみたいと思います。
①構造体の書式の設定
②プログラムを起動したときにセットされているように、himeの構造体の中身を初期化しています。初期化する時は、データを順番に書いてくだけなんですね!!
③1号2号3号のデータです(中身は何もありません)。
④の関数は2号のデータのポインタを受け取り、関数の中でデータを変更しています。
⑤の関数は3号のデータをデータ渡しで受け取って、関数内でデータを書き換えています。
⑥himeのデータを表示させます。
⑦1号のデータを表示させます。
⑧1号のデータを書き込んで、表示させます。
⑨2号のデータをポインタで渡して、表示させます。
⑩3号のデータをデータで渡して表示させます。
結果
⑥himeのデータが表示されました。プログラムを実行した時に初期化のデータがそのまま表示されています。
⑦1号のデータが表示されました。内容はありません。
⑧プログラム実行後に書き込んだ1号のデータが表示されました。
④のup-date関数に戻り、2号のデータをポインタで渡して表示されました。→※1
⑨2号のデータをポインタで渡して表示されました。
⑤のup-date関数に戻り、3号のデータをデータで渡して表示されました。→※1
⑩3号のデータをデータで渡して表示されましたが、データ渡しなので、⑤の{}外の関数ではデータはもらえず中身は何もありません。
※1 プログラムは上から順番に実行されていくわけではないそうです。
この場合だと、⑨(⑩)が実行される前にup-date関数に戻り、④(⑤)を実行しています。
ポインタ渡しとデータ渡し
以前に勉強したポインタが久々登場です!
ポインタ渡しは原本のありかを教えており、データ渡しはデータをコピーして渡しているという説明でした。
2号・3号のデータは最初は何もありません。白紙の紙です。→③
2号はその白紙のありかを関数に渡して、関数内で直接白紙に値を書き込んでいます。このやり方は、④⑨の関数を実行する時に&をつけて結果を返しています。なので、2号の結果は④と⑨の両方とも中身が表示されています。
3号はポインタではなくデータ渡しを使用してしまっています。データ渡しはデータのコピーを渡しているイメージなので、⑤の関数の{ }内では設定したデータを見れていますが、関数の外 すなわち⑩の関数のほうでは中身が更新されていません。
ポインタ渡しは「原本をデータの保存場所を教えていている」
データ渡しは、「データのコピーを渡している」
ということの確認も行うことが出来ました!!
ポインタ渡しで使われる記号
●& → 構造体のポインタを関数に渡すとき
●-> → 構造体のポインタから、そのメンバー変数にアクセスする時
● . → 構造体のデータから、そのメンバー変数にアクセスする時
今回の実験で使用したソースコードはこちらです。
[c]
#include "struct_test_ide.h" // Additional Header
struct personal_info {
char name[64];
unsigned short id;
char addr[128];
};
struct personal_info hime ={
"Lazurite Hime",
0x1001,
"Yokohama-shi"
};
struct personal_info ichigou;
struct personal_info nigou;
struct personal_info sangou;
void update_nigou(struct personal_info *data)
{
strncpy(data->name,"nigou",sizeof(data->name));
data->id = 0x1003;
strncpy(data->addr,"Tokyo",sizeof(data->addr));
Serial.println("");
Serial.println("");
Serial.println("Print in update_nigou()::");
Serial.println("sangou info::");
Serial.print("name :: ");
Serial.println(data->name);
Serial.print("id :: ");
Serial.println_long(data->id,HEX);
Serial.print("addr :: ");
Serial.println(data->addr);
}
void update_sangou(struct personal_info data)
{
strncpy(data.name,"sangou",sizeof(data.name));
data.id = 0x1004;
strncpy(data.addr,"Kanagawa",sizeof(data.addr));
Serial.println("");
Serial.println("");
Serial.println("Print in update_sangou()::");
Serial.println("sangou info::");
Serial.print("name :: ");
Serial.println(data.name);
Serial.print("id :: ");
Serial.println_long(data.id,HEX);
Serial.print("addr :: ");
Serial.println(data.addr);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("hime info::");
Serial.print("name :: ");
Serial.println(hime.name);
Serial.print("id :: ");
Serial.println_long(hime.id,HEX);
Serial.print("addr :: ");
Serial.println(hime.addr);
Serial.println("");
Serial.println("");
Serial.println("ichigou info::");
Serial.print("name :: ");
Serial.println(ichigou.name);
Serial.print("id :: ");
Serial.println_long(ichigou.id,HEX);
Serial.print("addr :: ");
Serial.println(ichigou.addr);
Serial.println("");
Serial.println("");
strncpy(ichigou.name,"ichigou",sizeof(ichigou.name));
ichigou.id = 0x1002;
strncpy(ichigou.addr,"Hachioji-shi",sizeof(ichigou.addr));
Serial.println("ichigou info::");
Serial.print("name :: ");
Serial.println(ichigou.name);
Serial.print("id :: ");
Serial.println_long(ichigou.id,HEX);
Serial.print("addr :: ");
Serial.println(ichigou.addr);
Serial.println("");
Serial.println("");
update_nigou(&nigou);
Serial.println("nigou info::");
Serial.print("name :: ");
Serial.println(nigou.name);
Serial.print("id :: ");
Serial.println_long(nigou.id,HEX);
Serial.print("addr :: ");
Serial.println(nigou.addr);
update_sangou(sangou);
Serial.println("");
Serial.println("");
Serial.println("sangou print in setup::");
Serial.print("name :: ");
Serial.println(sangou.name);
Serial.print("id :: ");
Serial.println_long(sangou.id,HEX);
Serial.print("addr :: ");
Serial.println(sangou.addr);
}
void loop() {
// put your main code here, to run repeatedly:
}
[/c]