プログラミング入門2プログラミング入門2
第11回第11回
構造体・データ型・まとめ構造体・データ型・まとめ
芝浦工業大学情報工学科芝浦工業大学情報工学科 講師講師
青木青木 義満義満
2003/12/22 プログラミング入門2 2
構造体構造体
5人分のサッカー選手データ(前のレポート)
全てのデータを関数に渡して,処理する場合
char name[5][256];int assist[5];int score[5];
void func( char name[ ][256], int assist[ ], int score[ ] )
void func( char name[ ][256], int *assist, int *score)
・氏名・所属チーム・得点・アシスト・年俸・・・・・
選手
データをひとまとめにして効率良くデータを管理・処理したい
構造体の必要性!構造体の必要性!
2003/12/22 プログラミング入門2 3
構造体とは?構造体とは?((p.272p.272))
多人数の学生の身体検査のデータ
char name[5][256]; /* 5人分の学生の名前 */int height[5]; /* 5人分の学生の身長 */double weight[5]; /* 5人分の学生の体重 */
1人目のデータ
name[0][256]
height[0]
weight[0]
2人目のデータ
name[1][256]
height[1]
weight[1]
各配列は独立していて,それぞれの関連性がわかりにくい各配列は独立していて,それぞれの関連性がわかりにくい
個人のデータを“カード”でまとめて表し,そのカードを人数分用意個人のデータを“カード”でまとめて表し,そのカードを人数分用意
2003/12/22 プログラミング入門2 4
構造体とは?構造体とは?
構造体とは,ひとまとまりのデータを集めたデータ構造である
重要
名前 芝浦 義満
身長 168cm
体重 70kg
名前 芝浦 義満
身長 168cm
体重 70kg
名前 芝浦 次郎
身長 165cm
体重 55.5kg
名前 芝浦 次郎
身長 165cm
体重 55.5kg
名前
身長
体重
char 型
int型
double 型
1枚のカード1枚のカード
名前 芝浦 太郎
身長 176cm
体重 64.5kg
名前 芝浦 太郎
身長 176cm
体重 64.5kg
複数の型のデータをひとまとめにして扱う!
2003/12/22 プログラミング入門2 5
構造体の宣言構造体の宣言 ~~自分で新しい自分で新しい““型型””をつくるをつくる
構造体を宣言することは,意味のあるデータをひとまとまりにした,新しい変数の“型“を自分で作ることである
宣言の方法
1枚のカードをどう作るか?
{
}
中括弧でくくってひとまとめに
char name[256];int height;double weight;
typedef struct
type(型)をdefine(定義) 構造体
構造体の名前(型名)※int, double などと同じ役割※セミコロン忘れずに!
student ;
手順①どんなデータをひとまとめにして扱うかを決定②構造体の名前(変数の型)を決定
手順①どんなデータをひとまとめにして扱うかを決定②構造体の名前(変数の型)を決定
構造体のメンバーという
2003/12/22 プログラミング入門2 6
構造体データの使い方構造体データの使い方
変数(オブジェクト)の宣言
構造体内のメンバーへのアクセス
int x; int型のオブジェクト x を宣言
student aoki; student型のオブジェクト aoki を宣言
{
}
char name[256];int height;double weight;
typedef struct
student
student aoki;
構造体オブジェクト aokiは,以下のメンバを持つ
aoki.name[256]aoki.heightaoki.weight
構造体のメンバはドット(.)演算子でアクセス可能構造体のメンバはドット(.)演算子でアクセス可能構造体の定義
2003/12/22 プログラミング入門2 7
構造体を使ったプログラム(構造体のメンバ)構造体を使ったプログラム(構造体のメンバ)
ソースファイル名:list1203.c (p.274, 若干変更)
構造体メンバへの値の代入と表示
#include <stdio.h>#include <string.h> /* 文字列操作関数用 strcpy使用のため*/
typedef struct{char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
student sanaka;
/* 構造体メンバへの値の代入 */strcpy(sanaka.name, "Sanaka"); /* 文字列sanakaをsanaka.nameにコピー */sanaka.height = 175; /* 身長 */sanaka.weight = 60.5; /* 体重 */
/* 構造体メンバの表示 */printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);
return (0);}
#include <stdio.h>#include <string.h> /* 文字列操作関数用 strcpy使用のため*/
typedef struct{char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
student sanaka;
/* 構造体メンバへの値の代入 */strcpy(sanaka.name, "Sanaka"); /* 文字列sanakaをsanaka.nameにコピー */sanaka.height = 175; /* 身長 */sanaka.weight = 60.5; /* 体重 */
/* 構造体メンバの表示 */printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);
return (0);}
2003/12/22 プログラミング入門2 8
解説解説
typedef struct{char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
student sanaka;
/* 構造体メンバへの値の代入 */strcpy(sanaka.name, "Sanaka"); /* 文字列sanakaをsanaka.nameにコピー */sanaka.height = 175; /* 身長 */sanaka.weight = 60.5; /* 体重 */
strcpy(sanaka.name, "Sanaka");文字配列へのポインタ
文字配列(sanaka.name)に“Sanaka”を代入文字配列(sanaka.name)に“Sanaka”を代入
2003/12/22 プログラミング入門2 9
構造体を使ったプログラム(メンバの初期化)構造体を使ったプログラム(メンバの初期化)
ソースファイル名:list1204.c (p.275, 若干変更)構造体メンバの初期化
/* 学生を表す構造体で表した佐中君を初期化 */
#include <stdio.h>
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
student sanaka = {"Sanaka", 175, 60.5};
printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);
return (0);}
/* 学生を表す構造体で表した佐中君を初期化 */
#include <stdio.h>
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
student sanaka = {"Sanaka", 175, 60.5};
printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);
return (0);}
構造体メンバの初期化
2003/12/22 プログラミング入門2 10
構造体同士の値の代入構造体同士の値の代入 ((p.280p.280))
同じ種類の構造体データであれば,互いに値を代入することが可能
student aoki, maeda;
aoki = maeda;
maedaのメンバ(name, height, weight)をそれぞれaokiの対応するメンバに代入maedaのメンバ(name, height, weight)をそれぞれaokiの対応するメンバに代入
配列では不可能!
2003/12/22 プログラミング入門2 11
復習:復習: 配列のコピー配列のコピー 注意点注意点 ((p.93p.93))
va[5], vb[5] と2つの配列は要素数も同じだし,もっと簡単に次のように代入できないの?
vb = va ;
for (i = 0; i < 5; i++)vb[i] = va[i];
面倒でも,1つ1つ代入していく
重要重要
代入演算子によって,配列を代入することはできない代入演算子によって,配列を代入することはできない
2003/12/22 プログラミング入門2 12
関数での構造体データの使用(値変更なし)関数での構造体データの使用(値変更なし)
ソースファイル名:struct1.c関数への構造体データの受け渡し(値は変更しない)
#include <stdio.h>typedef struct {
char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void print_data( student std ){
printf("氏 名= %s¥n", std.name);printf("身 長= %d¥n", std.height);printf("体 重= %f¥n", std.weight);
}int main(void){
student sanaka = {"Sanaka", 175, 60.5};
print_data( sanaka );
return (0);}
#include <stdio.h>typedef struct {
char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void print_data( student std ){
printf("氏 名= %s¥n", std.name);printf("身 長= %d¥n", std.height);printf("体 重= %f¥n", std.weight);
}int main(void){
student sanaka = {"Sanaka", 175, 60.5};
print_data( sanaka );
return (0);}
構造体データを受け取り,値を表示する関数値を変更しない→ポインタでなくてOK
2003/12/22 プログラミング入門2 13
関数での構造体データの使用(値変更あり)関数での構造体データの使用(値変更あり)
ソースファイル名:struct2.c関数への構造体データの受け渡し(値の変更あり)
#include <stdio.h>typedef struct {
char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void change_data( student *std ){
(*std).height = 180;(*std).weight = 80.0;
}
int main(void){
student sanaka = {"Sanaka", 175, 60.5};
change_data( &sanaka );
printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);return (0);
}
#include <stdio.h>typedef struct {
char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void change_data( student *std ){
(*std).height = 180;(*std).weight = 80.0;
}
int main(void){
student sanaka = {"Sanaka", 175, 60.5};
change_data( &sanaka );
printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);return (0);
}
構造体データを受け取り,値を変更する関数値を変更する→ポインタ(アドレス)で受け取り!
2003/12/22 プログラミング入門2 14
解説解説
構造体のポインタ渡し
change_data( &sanaka );
void change_data( student *std ){
(*std).height = 180;(*std).weight = 80.0;
}
sanaka
std
*std
*stdはsanakaのエイリアス
106番地
106番地
student型のオブジェクトのアドレスを入れるための箱(student型オブジェクトへのポインタ)
(*std).height → *std.height()は省略不可*よりも.の方が優先順位が高いため,*(std.height)と解釈されてしまう!
2003/12/22 プログラミング入門2 15
関数での構造体データの使用(値変更あり)関数での構造体データの使用(値変更あり)
ソースファイル名:struct3.c(p.277,変更あり)関数への構造体データの受け渡し(値の変更あり,アロー演算子使用)
#include <stdio.h>typedef struct {
char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void change_data( student *std ){std->height = 180;std->weight = 80.0;}
int main(void){
student sanaka = {"Sanaka", 175, 60.5};
change_data( &sanaka );
printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);return (0);
}
#include <stdio.h>typedef struct {
char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void change_data( student *std ){std->height = 180;std->weight = 80.0;}
int main(void){
student sanaka = {"Sanaka", 175, 60.5};
change_data( &sanaka );
printf("氏 名= %s¥n", sanaka.name);printf("身 長= %d¥n", sanaka.height);printf("体 重= %f¥n", sanaka.weight);return (0);
}
構造体データを受け取り,値を変更する関数値を変更する→ポインタ(アドレス)で受け取り!
2003/12/22 プログラミング入門2 16
アローアロー((-->>))演算子演算子
change_data( &sanaka );
void change_data( student *std ){
(*std).height = 180;(*std).weight = 80.0;
}
void change_data( student *std ){std->height = 180;std->weight = 80.0;
}=
std->height = 180; 構造体へのポインタ名 -> メンバ
重要
ポインタptrが指す構造体のメンバmemである(*ptr).memは,->演算子を用いてptr->memと簡潔に記述せよ
ポインタptrが指す構造体のメンバmemである(*ptr).memは,->演算子を用いてptr->memと簡潔に記述せよ
2003/12/22 プログラミング入門2 17
複数のデータの扱い複数のデータの扱い ((構造体の配列構造体の配列, p.282), p.282)
構造体データを複数扱う際には,構造体の配列を用いる(データカードを人数分用意する)
構造体の配列の宣言
・・・・・・・・・・・・・
std[2].weight
std[2].height
std[2].name
std[1].weight
std[1].height
std[1].name
std[0].weight
std[0].height
std[0].name
std[0]typedef struct {
char name[20]; int height;float weight;
} student;std[1]
student std[5];std[2]
2003/12/22 プログラミング入門2 18
構造体の配列構造体の配列
ソースファイル名:list1208.c (p.283を変更)構造体の配列#include <stdio.h>#define NUMBER 5 /* 学生の人数 */
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
int i;student std[]= {
{ "Sato", 178, 61.0 },{ "Sanaka", 175, 60.5 },{ "Takao", 173, 80.0 },{ "Mike", 165, 72.0 },{ "Masaki", 179, 77.5 },};
puts("-----------------------------");for (i = 0; i < NUMBER; i++)
printf("%-8s %6d%6.1f¥n",std[i].name, std[i].height, std[i].weight);
puts("-----------------------------");
return (0);}
#include <stdio.h>#define NUMBER 5 /* 学生の人数 */
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
int main(void){
int i;student std[]= {
{ "Sato", 178, 61.0 },{ "Sanaka", 175, 60.5 },{ "Takao", 173, 80.0 },{ "Mike", 165, 72.0 },{ "Masaki", 179, 77.5 },};
puts("-----------------------------");for (i = 0; i < NUMBER; i++)
printf("%-8s %6d%6.1f¥n",std[i].name, std[i].height, std[i].weight);
puts("-----------------------------");
return (0);}
2003/12/22 プログラミング入門2 19
構造体の配列を関数へ渡す方法構造体の配列を関数へ渡す方法
ソースファイル名: struct4.c#include <stdio.h>#define NUMBER 5 /* 学生の人数 */
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void print_data( student data[] ){
int i;puts("-----------------------------");for (i = 0; i < NUMBER; i++)
printf("%-8s %6d%6.1f¥n",data[i].name, data[i].height, data[i].weight);puts("-----------------------------");
}
in main(void){
student std[] = {{ "Sato", 178, 61.0 },{ "Sanaka", 175, 60.5 },{ "Takao", 173, 80.0 },{ "Mike", 165, 72.0 },{ "Masaki", 179, 77.5 },
};
print_data( std );
return (0);}
#include <stdio.h>#define NUMBER 5 /* 学生の人数 */
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;
void print_data( student data[] ){
int i;puts("-----------------------------");for (i = 0; i < NUMBER; i++)
printf("%-8s %6d%6.1f¥n",data[i].name, data[i].height, data[i].weight);puts("-----------------------------");
}
in main(void){
student std[] = {{ "Sato", 178, 61.0 },{ "Sanaka", 175, 60.5 },{ "Takao", 173, 80.0 },{ "Mike", 165, 72.0 },{ "Masaki", 179, 77.5 },
};
print_data( std );
return (0);}
配列データを関数に渡す時には,その配列の先頭要素のアドレスを渡すstd(配列名)=&std[0]
配列データを関数に渡す時には,その配列の先頭要素のアドレスを渡すstd(配列名)=&std[0]
void print_data( student data[ ] )=
student *data
どちらも配列の先頭アドレスを受け取る受け取ると,関数内で data[i]として配列要素を扱える
プログラミング入門2プログラミング入門2
第1第122回(最終回)回(最終回)
データ型,補足説明データ型,補足説明総合演習総合演習
芝浦工業大学情報工学科芝浦工業大学情報工学科 講師講師
青木青木 義満義満
2003/12/22 プログラミング入門2 21
データ型データ型
データ型
整数型,文字型,浮動小数点数,倍精度型
データ型 意味
整数型 整数を表現する
文字型 文字を表現する
浮動小数点数 実数を表現する
倍精度型 精度の高い浮動小数点数を表現する
C言語で扱うことのできるデータ型
2003/12/22 プログラミング入門2 22
各データが扱える数値範囲各データが扱える数値範囲
変数を用意する際,目的にあった(扱うデータの値の取りうる範囲,必要とされる精度)データ型を以下から選択して使用
データ型 ビット長 扱える数値の範囲
short 16 -32768 ~ +32767int 32 -2147483648 ~ 2147483648long 32 -2147483648 ~ 2147483648unsigned short 16 0 ~ 65535unsigned int 32 0 ~ 4294967295unsigned long 32 0 ~ 4294967295char 8 (-128 ~ 127)unsigned char 8 (0 ~ 255)float 32 3.4 x 10-38~ 3.4 x 10+38
double 64 1.7 x 10-308 ~1.7 x 10+308
unsigned (符号なし)→ 0と正の数のみ扱える
unsigned (符号なし)→ 0と正の数のみ扱える
※実際のデータサイズは,処理系によって異なる(特にint)
2003/12/22 プログラミング入門2 23
各データ型の変換指定子各データ型の変換指定子
標準入出力のための変換指定子
指定子 意味
%d(%ld) 整数の10進数として出力 (longの場合,%ld)
%u (%lu) 整数の符号なし10進数として出力(unsigned longの場合,%lu)
%f 浮動小数点表示(float, double共通)
%c 1文字を出力
%s 文字列を出力
%p ポインタの値(アドレス)を出力
※scanfの場合,float は%f, double は %lf で読み込み
2003/12/22 プログラミング入門2 24
データ型の値の範囲を出力データ型の値の範囲を出力
ソースファイル名: data.c各データ型の値の取りうる範囲を出力
#include <stdio.h>#include <limits.h>
int main(void){
printf("char : %d to %d¥n", CHAR_MIN, CHAR_MAX);printf("unsigned char : %d to %d¥n", 0, UCHAR_MAX);printf("short : %d to %d¥n", SHRT_MIN, SHRT_MAX);printf("int : %d to %d¥n", INT_MIN, INT_MAX);printf("long : %ld to %ld¥n", LONG_MIN, LONG_MAX);printf("unsigned short : %u to %u¥n", 0, USHRT_MAX);printf("unsigned int : %u to %u¥n", 0, UINT_MAX);printf("unsigned long int: %lu to %lu¥n", 0, ULONG_MAX);
return(0);}
#include <stdio.h>#include <limits.h>
int main(void){
printf("char : %d to %d¥n", CHAR_MIN, CHAR_MAX);printf("unsigned char : %d to %d¥n", 0, UCHAR_MAX);printf("short : %d to %d¥n", SHRT_MIN, SHRT_MAX);printf("int : %d to %d¥n", INT_MIN, INT_MAX);printf("long : %ld to %ld¥n", LONG_MIN, LONG_MAX);printf("unsigned short : %u to %u¥n", 0, USHRT_MAX);printf("unsigned int : %u to %u¥n", 0, UINT_MAX);printf("unsigned long int: %lu to %lu¥n", 0, ULONG_MAX);
return(0);}
各データ型の値の範囲が定義(#define)されている
2003/12/22 プログラミング入門2 25
データ型のサイズ(バイト数)を表示データ型のサイズ(バイト数)を表示
ソースファイル名: datasize.c各データ型の大きさ(サイズ)を表示
#include <stdio.h>
int main(void){
printf("sizeof(char) = %u¥n", sizeof(char) );printf("sizeof(short) = %u¥n", sizeof(short) );printf("sizeof(int) = %u¥n", sizeof(int) );printf("sizeof(long) = %u¥n", sizeof(long) );printf("sizeof(float) = %u¥n", sizeof(float) );printf("sizeof(double) = %u¥n", sizeof(double) );
return(0);}
#include <stdio.h>
int main(void){
printf("sizeof(char) = %u¥n", sizeof(char) );printf("sizeof(short) = %u¥n", sizeof(short) );printf("sizeof(int) = %u¥n", sizeof(int) );printf("sizeof(long) = %u¥n", sizeof(long) );printf("sizeof(float) = %u¥n", sizeof(float) );printf("sizeof(double) = %u¥n", sizeof(double) );
return(0);}
sizeof( データ型 ) → データ型の大きさ(byte数) ※p.180に詳しい解説
2003/12/22 プログラミング入門2 26
総合演習・試験について総合演習・試験について
これまでの授業の総復習
問1~11まで問題は授業ホームページ上(解答は掲載しない。各自考えること)
試験は授業の内容を理解していればできる問題を出題
特に中間テストの結果が悪かった人は挽回しないと落第
レポート未提出の場合,減点:遅れても必ず提出すること!
2003/12/22 プログラミング入門2 27
最後に・・・最後に・・・
今回の授業では,C言語の文法を知識として習得問題解決のための手法(アルゴリズム)については,2年次で詳しく学習プログラミング技術のスキルアップのポイント
資格取得,ゲーム作成など,目標を立てて学習
本などを読むだけでなく,とにかく自分でやってみる
全てを記憶することは不可能,必要とされる知識を辞書などを使って調べる工夫が必要
2003/12/22 プログラミング入門2 28
更にステップアップしたい人へ更にステップアップしたい人へ
お勧め参考図書
秘伝ポインタ問答 ポインタ編,柴田望洋,ソフトバンク出版
プログラム技術情報誌,月刊C Magazine,ソフトバンク出版
C言語辞典
2003/12/22 プログラミング入門2 29
演習課題演習課題 (第(第1111回,構造体)回,構造体)
問1)構造体
キーボードから3点の2次元座標値(x, y)を読み込み,3点から作られる3角形の面積Sを出力するプログラムを作成せよ。
a
p1
p2
p3
b
S( )222
21 babaS •−=
但し,構造体は以下のものを用いること
typedef struct {
double x;double y;
} point;
p.286に参考プログラム
2003/12/22 プログラミング入門2 30
演習課題演習課題 (第(第1111回,構造体)回,構造体)
問2)構造体の配列
student構造体の配列を用い,5名分の学生データを体重の軽い順に並べ替え(ソート),並べ替える前と並べ替えた後の結果を表示するプログラムを作成せよ。
並べ替え(ソート)のアルゴリズムについては,前回のレポート(report8.c)を参考にせよ。
void weight_sort( student *data, int num);
もしくは,student data[ ]
配列の要素数
typedef struct {char name[20]; /* 名前 */int height; /* 身長 */float weight; /* 体重 */
} student;