読者です 読者をやめる 読者になる 読者になる

C言語 構造体

Program C言語

C言語改訂版1 はじめてのプログラミング (CD-ROM付) (プログラミング学習シリーズ)

C言語改訂版1 はじめてのプログラミング (CD-ROM付) (プログラミング学習シリーズ)

構造体とは、

   様々な型の複数のデータをまとめて、1つの型のように扱うもの

という理解。個体に紐づけて様々な情報を管理したいときに使う「型を柔軟にした変数」という理解。

簡単に書いてみた。構造体については、本よりもこっちの方がわかりやすかった。

(本は、display関数についての解説が不可解)

まず、ヘッダーファイルで構造体を定義(さまざまなファイルからのアクセスが想定される構造体はヘッダーファイルに残す)。構造体の定義時は

    struct タグ名 {構造体の中身};

とするらしい。タグ名という名称が初めて出てきた。

//Person.h
	struct Person {			//個人情報を格納する構造体Personを定義(※架空)。struct タグ名 という形で書く(今回ならPersonがタグ名)
		int ID;			//ID
		int birthday;		//誕生年,月,日
		char pref[30];		//居住都道府県
		char postalcode[30];	//郵便番号
		char sex[30];		//性別
		char name[30];		//名前
		int income;		//年収
	};

…で、本編で構造体の要素を入力する。下記、構造体を表す変数を、

   struct タグ名 構造体変数名[要素数] = { { }, { }, { }, …}

という形で定義している。

//strc.c
#include <stdio.h> #include "Person.h" //ヘッダーファイルから構造体の定義を読込 main () { int i = 0; printf("ID\tBrithday\tPref\tPostalcode\tSex\tName\t\tIncome\n"); //表示時の項目名。タブ(\t)を使うと表示が綺麗に struct Person A[3] = { //構造体の初期化。3は入力する構造体の要素数。 1 {1, 19801203, "Tokyo", "160-0012", "Male", "Tanaka Taro", 600}, {2, 19830228, "Kyoto", "606-8243", "Female", "Sato Hanako", 1000}, {3, 19480831, "Chiba", "277-0291", "Male", "Takahashi Jiro", 800}, }; //順にID,誕生年月日,居住都道府県,郵便番号,性別,名前,年収 for(i = 0; i < 3; i++) { //入力した構造体を表示 printf("%d\t%d\t%s\t%s\t%s\t%s\t%d\n", A[i].ID, A[i].birthday, A[i].pref, A[i].postalcode, A[i].sex,A[i].name, A[i].income); } return 0; //終了宣言 }

gcc strc.c でコンパイル後、./a.exeを実行。出力はこんな感じになった。

ID      Brithday        Pref    Postalcode      Sex     Name            Income

1       19801203        Tokyo   160-0012        Male    Tanaka Taro     600

2       19830228        Kyoto   606-8243        Female  Sato Hanako     1000

3       19480831        Chiba   277-0291        Male    Takahashi Jiro  800

---------------------------------------------------------------------------------------------------------------

変数と同様、構造体はポインタとセットで使えるとなお良い。確かポインタ変数は、メモリの住所の受け皿(住所を与えることで住所の先にある変数に対して処理を行うための変数)という理解をしていた。

ポインタ変数使うときは、

   ポインタ変数 = 変数の住所 (&変数名 で表す) もしくは

   ポインタ変数で定義した関数の引数に変数の住所を書き込む

形でポインタ変数に住所を与えていた。

同様にして、構造体ポインタ変数についても、

   構造体ポインタ変数 = 構造体変数の住所 (&構造体変数名 で表す) もしくは

   構造体ポインタ変数で定義した関数の引数に構造体変数の住所を書き込む

という形で使えば良い、ということか。ところで、変数を配列で定義している場合は、&で住所を指定する必要はないのだった。配列の先頭が住所に対応することになる。だから、次のように書けばよい。

 #include <stdio.h>
#include "Person.h"

main  () {
	int i = 0;
	printf("ID\tBrithday\tPref\tPostalcode\tSex\tName\t\tIncome\n"); 

	struct Person A[3] = {
		{1, 19801203, "Tokyo", "160-0012", "Male", "Tanaka Taro", 600},
		{2, 19830228, "Kyoto", "606-8243", "Female", "Sato Hanako", 1000},
		{3, 19480831, "Chiba", "277-0291", "Male", "Takahashi Jiro", 800},
	};

	struct Person *p;	//構造体ポインタ変数pの定義
	p = A;			//構造体ポインタ変数にAの住所を与える(&A[0]の省略形)

	for(i = 0; i < 3; i++) {
		printf("%d\t%d\t%s\t%s\t%s\t%s\t%d\n",
			(p+i)->ID, (p+i)->birthday, (p+i)->pref, (p+i)->postalcode,
			(p+i)->sex,(p+i)->name, (p+i)->income);
	}
	return 0;
}

 ただし、構造体ポインタ変数を用いて構造体の要素(住所とか)にアクセスするときは、

     (ポインタ構造体変数) -> 要素名

とするらしい。この理解でよいのだろうか。とりあえず先に進む。

【追記】

本に載っていた演習問題の解説で発見があったのでメモ。