当日のOHP資料です。
構造体の続き( Text p.280-289 )
Download : sample-001.c ( SJIS 版 )
/* * [参考] list 12-7 (text p.281) * [比較] 2009/12/11 の sample-003 */ /* * 構造体を返す関数 */ #include <stdio.h> #define NAME_SIZE 20 /* <<名前>> の最大の長さ -1 */ /* 学生を表す構造体 */ typedef struct gstudent { char name[NAME_SIZE]; /* 名前 */ int height; /* 身長 */ float weight; /* 体重 */ long schols; /* 奨学金 */ } Student; /* 構造体で表現された学生情報の表示 */ void print_student ( Student student ) { printf ( "名 前 = %s\n", student.name ); printf ( "身 長 = %d\n", student.height ); printf ( "体 重 = %f\n", student.weight ); printf ( "奨学金 = %ld\n", student.schols ); } /* 学生情報の構造体 Student を返す関数 */ Student new_student ( char *name, int height, double weight, long schols ) { Student aStudent; strcpy ( aStudent.name, name ); /* 名前 */ aStudent.height = height; /* 身長 */ aStudent.weight = weight; /* 体重 */ aStudent.schols = schols; /* 奨学金 */ return aStudent; /* 構造体の内容を値として返す */ } /* 構造値 Student を返す関数の利用 */ int main ( void ) { Student who; who = new_student ( "Sanaka", 175, 60.5, 70000 ); print_student ( who ); return 0; }
C:\usr\c\> sample-001 名 前 = Sanaka 身 長 = 175 体 重 = 60.500000 奨学金 = 70000 C:\usr\c\>
Download : sample-002.c ( SJIS 版 )
/* * [参考] list 12-8 (text p.283) * [比較] 2009/12/11 sample-002.c */ /* * 5 人の学生を、身長の昇順にソート */ #include <stdio.h> #include <string.h> #define NAME_SIZE 20 /* <<名前>> の最大の長さ -1 */ #define NUMBER_OF_STUDENT 5 /* 学生の人数 */ /* * 構造体を返す関数 */ #include <stdio.h> /* 学生を表す構造体 */ typedef struct gstudent { char name[NAME_SIZE]; /* 名前 */ int height; /* 身長 */ float weight; /* 体重 */ long schols; /* 奨学金 */ } Student; /* 構造体で表現された学生情報の表示 */ void print_student ( Student student ) { printf ( "%-8s %6d %6.1f %7ld\n", student.name, student.height, student.weight, student.schols ); } /* dst_ptr および src_ptr が指す学生の情報を交換 */ void swap_student ( Student *dst_ptr, Student *src_ptr ) { Student temp = *src_ptr; *src_ptr = *dst_ptr; *dst_ptr = temp; } /* dst_ptr および src_ptr が指す学生の情報を身長で比較 */ /* * dst_ptr で指された学生を src_ptr 指された学生の身長と、比較し * 大きい場合は > 0 の値を、 * 小さい場合は < 0 の値を、 * そして、小さい場合は 0 を整数値として返す。 */ int compare_student_by_height ( Student *dst_ptr, Student *src_ptr ) { return ( dst_ptr -> height ) - ( src_ptr -> height ); } /* 配列 data と name の先頭 n 個の要素を身長の昇順にソート */ void sort_student_by_height ( Student data[], int n ) { int k = n - 1; while ( k >= 0 ) { int i, j; for ( i = 1, j = -1; i <= k; i++ ) { if ( compare_student_by_height ( &data[ i - 1 ], &data[ i ] ) > 0 ) { j = i - 1; swap_student ( &data[i], &data[j] ); } } k = j; } } int main ( void ) { int i; Student meibo[] = { { "Sato", 178, 61.0, 80000 }, /* 佐藤宏史 */ { "Sanaka", 175, 60.5, 70000 }, /* 佐中俊哉 */ { "Takao", 173, 80.0, 0 }, /* 高尾健司 */ { "Mike", 165, 72.0, 70000 }, /* 平木Mike */ { "Masaki", 179, 77.5, 70000 } /* 真崎宏孝 */ }; sort_student_by_height ( meibo, NUMBER_OF_STUDENT ); printf ( "----------------------------\n" ); for ( i = 0; i < NUMBER_OF_STUDENT; i++ ) { print_student ( meibo [ i ] ); } printf ( "----------------------------\n" ); return 0; }
C:\usr\c\> sample-002 ---------------------------- Mike 165 72.0 70000 Takao 173 80.0 0 Sanaka 175 60.5 70000 Sato 178 61.0 80000 Masaki 179 77.5 70000 ---------------------------- C:\usr\c\>
Download : sample-003.c ( SJIS 版 )
/* * [参考] list 12-9 (text p.285) */ /* * 今日の「年月日」を表示する */ #include <time.h> #include <stdio.h> /* * print_date * * ptr_time で指されている時刻データの「年月日」だけを出力する */ void print_date ( struct tm *ptr_time ) { char *week_day_name[] = { "日", "月", "火", "水", "木", "金", "土" }; printf ( "%4d年%02d月%0d日(%s)", ptr_time -> tm_year + 1900, /* 年 */ ptr_time -> tm_mon + 1, /* 月 */ ptr_time -> tm_mday, /* 日 */ week_day_name [ ptr_time -> tm_wday ] /* 曜日 */ ); } /* * print_today * * 関数が呼出された時刻の「年月日」だけを出力する */ void print_today ( void ) { time_t current_time; /* 現在の時刻をデータ */ struct tm *ptr_local_time; /* 地方時へのポインタ */ time ( ¤t_time ); /* 現在の時刻を取得 */ ptr_local_time = localtime ( ¤t_time ); /* 地方時に変換 */ print_date ( ptr_local_time ); /* 「年月日」を出力 */ } /* * 本日の「年月日」を出力する */ int main ( void ) { printf ( "本日は" ); print_today(); printf ( "です。\n" ); return 0; }
C:\usr\c\> sample-003 本日は2009年12月18日(金)です。 C:\usr\c\>
Download : sample-004.c ( SJIS 版 )
/* * [参考] list 12-10 (text p.286) */ /* * 2 点間の距離を求める */ #include <math.h> #include <stdio.h> #define squre(N) ((N)*(N)) /* 二乗を計算するマクロ関数 */ /* * 平面座標を表現する構造体型 Point の宣言 */ typedef struct { int x; /* X 座標 */ int y; /* Y 座標 */ } Point; /* 「点」型 */ /* * 「点」の座標の出力 */ void print_point ( Point point ) { printf ( "(%d, %d)", point.x, point.y ); } /* * 「点」の座標の入力 */ void scan_point ( Point *ptr_point ) { printf ( "X 座標\n" ); scanf ( "%d", & ( ptr_point -> x ) ); printf ( "Y 座標\n" ); scanf ( "%d", & ( ptr_point -> y ) ); } /* * 二点間の距離を計算する */ double distance_of ( Point dst, Point src ) { return sqrt ( squre( dst.x - src.x ) + squre( dst.y - src.y ) ); } /* * 二点の座標を入力し、その間の距離を計算した結果を出力する */ int main ( void ) { Point point1; Point point2; /* 一点目の座標の入力 */ printf ( "一点目\n" ); scan_point ( &point1 ); /* ニ点目の座標の入力 */ printf ( "二点目\n" ); scan_point ( &point2 ); /* 距離の計算とその結果の出力 */ printf ( "点" ); print_point ( point1 ); printf ( "と、" ); printf ( "点" ); print_point ( point2 ); printf ( "の距離は %.2f です。\n", distance_of ( point1, point2 ) ); return 0; }
10 20 15 35
C:\usr\c\> sample-004 一点目 X 座標 Y 座標 二点目 X 座標 Y 座標 点(10, 20)と、点(15, 35)の距離は 15.81 です。 C:\usr\c\>
Download : sample-005.c ( SJIS 版 )
/* * [参考] list 12-11 (text p.287) */ /* * 車の移動と燃料の消費 */ #include <math.h> #include <stdio.h> /* */ #define squre(N) ((N)*(N)) /* 二乗を計算するマクロ関数 */ #define FALSE (0) /* 偽 */ #define TRUE (!FALSE) /* 真 */ #define forever for(;;) /* 無限 Loop */ /* * 平面座標を表現する構造体型 Point の宣言 */ typedef struct { int x; /* X 座標 */ int y; /* Y 座標 */ } Point; /* 「点」型 */ /* * 「点」の座標の出力 */ void print_point ( Point point ) { printf ( "(%d, %d)", point.x, point.y ); } /* * 「点」の座標の入力 */ void scan_point ( Point *ptr_point ) { printf ( "X 座標\n" ); scanf ( "%d", & ( ptr_point -> x ) ); printf ( "Y 座標\n" ); scanf ( "%d", & ( ptr_point -> y ) ); } /* * 二点間の距離を計算する */ double distance_of ( Point dst, Point src ) { return sqrt ( squre( dst.x - src.x ) + squre( dst.y - src.y ) ); } /* * 移動先の座標の計算 */ Point moved_position ( Point current_point, int delta_x, int delta_y ) { current_point.x += delta_x; current_point.y += delta_y; return current_point; } /* 「車」を表現する構造体 Car の宣言 */ typedef struct { Point position; /* 現在位置 */ double fuel; /* 現在の燃料 */ } Car; /* * print_car * * 「車」の現在位置と燃料の残りを表示する */ void print_car ( Car car_data ) { /* 現在位置の表示 */ printf ( "現在位置:" ); print_point ( car_data.position ); printf ( "\n" ); /* 残り燃料の表示 */ printf ( "残り燃料:" ); printf ( "%.2f リットル\n", car_data.fuel ); } /* * change_car_position * * 「車」を新しい位置に変化させる * 移動に十分な燃料も指定する */ void change_car_position ( Car *ptr_car, Point new_position, double use_fuel ) { ptr_car -> position = new_position; ptr_car -> fuel -= use_fuel; } /* * move_car * * 「車」を新しい位置に移動する * 移動の際に、移動に十分な燃料があるかどうかを判定する */ int move_car ( Car *ptr_car, Point new_position ) { double distance = distance_of ( new_position, ptr_car -> position ); double use_fuel = distance * 1.0; int movable = use_fuel < ptr_car -> fuel; if ( movable ) { change_car_position ( ptr_car, new_position, use_fuel ); } return movable; } /* * 車を操作する */ #define COMMAND_END (0) /* 終了命令 */ #define COMMAND_MOVE (1) /* 移動命令 */ int main ( void ) { Car mycar = { {0,0}, 90.0 }; forever { /* 無限 Loop */ int command; /* 命令 */ int delta_x; /* X の移動量 */ int delta_y; /* Y の移動量 */ Point next_point; /* 新しい移動先 */ print_car ( mycar ); /* 現状を報告 */ /* 移動するかどうかを選択する */ printf ( "移動しますか [ Yes ... %d / No ... %d ]\n", COMMAND_MOVE, COMMAND_END ); scanf ( "%d", &command ); if ( command == COMMAND_END ) { /* 移動しないならば */ break; /* 繰り返しを終了する */ } /* 移動量の入力 */ printf ( "X 方向の移動距離\n" ); scanf ( "%d", &delta_x ); printf ( "Y 方向の移動距離\n" ); scanf ( "%d", &delta_y ); /* 移動先の位置の計算 */ next_point = moved_position ( mycar.position, delta_x, delta_y ); if ( !move_car ( &mycar, next_point ) ) { printf ( "\a燃料不足で移動できません。\n" ); } } return 0; }
1 10 10 1 60 40 1 55 30 0
C:\usr\c\> sample-005 現在位置:(0, 0) 残り燃料:90.00 リットル 移動しますか [ Yes ... 1 / No ... 0 ] X 方向の移動距離 Y 方向の移動距離 現在位置:(10, 10) 残り燃料:75.86 リットル 移動しますか [ Yes ... 1 / No ... 0 ] X 方向の移動距離 Y 方向の移動距離 現在位置:(70, 50) 残り燃料:3.75 リットル 移動しますか [ Yes ... 1 / No ... 0 ] X 方向の移動距離 Y 方向の移動距離 燃料不足で移動できません。 現在位置:(70, 50) 残り燃料:3.75 リットル 移動しますか [ Yes ... 1 / No ... 0 ] C:\usr\c\>
構造体を利用したプログラムを作成する
/* * [参考] list 12-8 (text p.283) * [比較] 2009/12/11 sample-002.c */ /* * 5 人の学生を、身長の昇順にソート */ #include <stdio.h> #include <string.h> #define NUMBER_OF_STUDENT 5 /* 学生の人数 */ #define NAME_SIZE 20 /* <<名前>> の最大の長さ -1 */ /* * 構造体を返す関数 */ #include <stdio.h> /* 学生を表す構造体 */ typedef struct gstudent { char name[NAME_SIZE]; /* 名前 */ int height; /* 身長 */ float weight; /* 体重 */ long schols; /* 奨学金 */ } Student; /* 構造体で表現された学生情報の表示 */ void print_student ( Student student ) { printf ( "%-8s %6d %6.1f %7ld\n", student.name, student.height, student.weight, student.schols ); } /* dst_ptr および src_ptr が指す学生の情報を交換 */ void swap_student ( Student *dst_ptr, Student *src_ptr ) { Student temp = *src_ptr; *src_ptr = *dst_ptr; *dst_ptr = temp; } /* dst_ptr および src_ptr が指す学生の情報を体重で比較 */ /* * dst_ptr で指された学生を src_ptr で指された学生の体重と比較し * 大きい場合は > 0 の値を、 * 小さい場合は < 0 の値を、 * そして、小さい場合は 0 を整数値として返す。 */ int compare_student_by_weight ( Student *dst_ptr, Student *src_ptr ) { /* ** この部分を完成させなさい */ } /* 配列 data の先頭 n 個の要素を体重の昇順にソート */ void sort_student_by_weight ( Student data[], int n ) { /* ** この部分を完成させなさい */ } int main ( void ) { int i; Student meibo[] = { { "Sato", 178, 61.0, 80000 }, /* 佐藤宏史 */ { "Sanaka", 175, 60.5, 70000 }, /* 佐中俊哉 */ { "Takao", 173, 80.0, 0 }, /* 高尾健司 */ { "Mike", 165, 72.0, 70000 }, /* 平木Mike */ { "Masaki", 179, 77.5, 70000 } /* 真崎宏孝 */ }; sort_student_by_weight ( meibo, NUMBER_OF_STUDENT ); printf ( "----------------------------\n" ); for ( i = 0; i < NUMBER_OF_STUDENT; i++ ) { print_student ( meibo [ i ] ); } printf ( "----------------------------\n" ); return 0; }
C:\usr\c\> 20091218-1 ---------------------------- Sanaka 175 60.5 70000 Sato 178 61.0 80000 Mike 165 72.0 70000 Masaki 179 77.5 70000 Takao 173 80.0 0 ---------------------------- C:\usr\c\>
/* * [参考] 演習 12-1 (text p.285) */ /* * 現在の「時分秒」を表示する */ #include <time.h> #include <stdio.h> /* * print_time * * ptr_time で指されている時刻データの「時分秒」だけを出力する */ void print_time ( struct tm *ptr_time ) { /* ** この部分を完成させなさい */ } /* * print_now * * 関数が呼出された時刻の「時分秒」だけを出力する */ void print_now ( void ) { /* ** この部分を完成させなさい */ } /* * 現在の「時分秒」を出力する */ int main ( void ) { printf ( "現在は" ); print_now(); printf ( "です。\n" ); return 0; }
C:\usr\c\> 20091218-2 現在は06時16分31秒です。 C:\usr\c\>
/* * [参考] sample-005 */ /* * トラックの移動と燃料の消費 */ #include <math.h> #include <stdio.h> /* */ #define squre(N) ((N)*(N)) /* 二乗を計算するマクロ関数 */ #define FALSE (0) /* 偽 */ #define TRUE (!FALSE) /* 真 */ #define forever for(;;) /* 無限 Loop */ /* * 平面座標を表現する構造体型 Point の宣言 */ typedef struct { int x; /* X 座標 */ int y; /* Y 座標 */ } Point; /* 「点」型 */ /* * 「点」の座標の出力 */ void print_point ( Point point ) { printf ( "(%d, %d)", point.x, point.y ); } /* * 「点」の座標の入力 */ void scan_point ( Point *ptr_point ) { printf ( "X 座標\n" ); scanf ( "%d", & ( ptr_point -> x ) ); printf ( "Y 座標\n" ); scanf ( "%d", & ( ptr_point -> y ) ); } /* * 二点間の距離を計算する */ double distance_of ( Point dst, Point src ) { return sqrt ( squre( dst.x - src.x ) + squre( dst.y - src.y ) ); } /* * 移動先の座標の計算 */ Point moved_position ( Point current_point, int delta_x, int delta_y ) { current_point.x += delta_x; current_point.y += delta_y; return current_point; } /* 「車」を表現する構造体 Car の宣言 */ typedef struct { Point position; /* 現在位置 */ double fuel; /* 現在の燃料 */ } Car; /* * print_car * * 「車」の現在位置と燃料の残りを表示する */ void print_car ( Car car_data ) { /* 現在位置の表示 */ printf ( "現在位置:" ); print_point ( car_data.position ); printf ( "\n" ); /* 残り燃料の表示 */ printf ( "残り燃料:" ); printf ( "%.2f リットル\n", car_data.fuel ); } /* * move_car * * 「車」を新しい位置に移動する * 移動の際に、移動に十分な燃料があるかどうかを判定する */ int move_car ( Car *ptr_car, Point new_position ) { double distance = distance_of ( new_position, ptr_car -> position ); int movable = distance < ptr_car -> fuel; if ( movable ) { ptr_car -> position = new_position; ptr_car -> fuel -= distance; } return movable; } /* 「トラック」を表現する構造体 Autotruck の宣言 */ typedef struct { Car car; /* 「トラック」は「車」の一種 */ double carry; /* 現在の積載量 */ } Autotruck; #define MAX_CARRY_WEIGHT (5.0) /* 最大積載量 */ /* * print_autotruck * * 「トラック」の現在位置と燃料の残りを表示する */ void print_autotruck ( Autotruck autotruck_data ) { /* 車としての情報 */ print_car ( autotruck_data.car ); /* 積載量の表示 */ printf ( "積載量:" ); printf ( "%.2f トン\n", autotruck_data.carry ); } /* * change_car_position * * 「車」を新しい位置に変化させる * 移動に十分な燃料も指定する */ void change_car_position ( Car *ptr_car, Point new_position, double use_fuel ) { ptr_car -> position = new_position; ptr_car -> fuel -= use_fuel; } /* * move_autotruck * * 「トラック」を新しい位置に移動する * 移動の際に、移動に十分な燃料があるかどうかを判定する */ int move_autotruck ( Autotruck *ptr_autotruck, Point new_position ) { /* ** この部分を完成させなさい */ } /* * carry_on_autotrack * * 「トラック」に * 移動の際に、移動に十分な燃料があるかどうかを判定する */ int carry_on_autotrack ( Autotruck *ptr_autotruck, double new_carry ) { int carriable = new_carry <= MAX_CARRY_WEIGHT; if ( carriable ) { ptr_autotruck -> carry = new_carry; } return carriable; } /* * トラックを操作する */ #define COMMAND_END (0) /* 終了命令 */ #define COMMAND_MOVE (1) /* 移動命令 */ #define COMMAND_CARRY (2) /* 塔載命令 */ #define COMMAND_STAND (3) /* 給油命令 */ int main ( void ) { Autotruck myautotruck = { {{0,0}, 90.0}, 0.0 }; forever { /* 無限 Loop */ int command; /* 命令 */ int delta_x; /* X の移動量 */ int delta_y; /* Y の移動量 */ Point next_point; /* 新しい移動先 */ double new_carry; /* 新しい塔載量 */ print_autotruck ( myautotruck ); /* 現状を報告 */ /* 命令を選択する */ printf ( "命令をどうぞ [ Move ... %d / Carry ... %d / Stand ... %d / End .. %d ]\n", COMMAND_MOVE, COMMAND_CARRY, COMMAND_STAND, COMMAND_END ); scanf ( "%d", &command ); if ( command == COMMAND_END ) { /* 「終了」ならば */ break; /* 繰り返しを終了する */ } switch ( command ) { case COMMAND_MOVE: /* 移動量の入力 */ printf ( "X 方向の移動距離\n" ); scanf ( "%d", &delta_x ); printf ( "Y 方向の移動距離\n" ); scanf ( "%d", &delta_y ); /* 移動先の位置の計算 */ next_point = moved_position ( myautotruck.car.position, delta_x, delta_y ); if ( !move_autotruck ( &myautotruck, next_point ) ) { printf ( "\a燃料不足で移動できません。\n" ); } break; case COMMAND_CARRY: printf ( "新しい積荷の重さ\n" ); scanf ( "%lf", &new_carry ); if ( !carry_on_autotrack ( &myautotruck, new_carry ) ) { printf ( "\a重過ぎます。\n" ); } break; case COMMAND_STAND: myautotruck.car.fuel = 100.0; /* 無条件に給油 */ break; } } return 0; }
1 10 10 1 60 40 1 55 30 3 2 1 1 10 10 1 60 40 2 10 0
C:\usr\c\> 20091218-3 現在位置:(0, 0) 残り燃料:90.00 リットル 積載量:0.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] X 方向の移動距離 Y 方向の移動距離 現在位置:(10, 10) 残り燃料:75.86 リットル 積載量:0.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] X 方向の移動距離 Y 方向の移動距離 現在位置:(70, 50) 残り燃料:3.75 リットル 積載量:0.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] X 方向の移動距離 Y 方向の移動距離 燃料不足で移動できません。 現在位置:(70, 50) 残り燃料:3.75 リットル 積載量:0.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] 現在位置:(70, 50) 残り燃料:100.00 リットル 積載量:0.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] 新しい積荷の重さ 現在位置:(70, 50) 残り燃料:100.00 リットル 積載量:1.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] X 方向の移動距離 Y 方向の移動距離 現在位置:(80, 60) 残り燃料:71.72 リットル 積載量:1.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] X 方向の移動距離 Y 方向の移動距離 燃料不足で移動できません。 現在位置:(80, 60) 残り燃料:71.72 リットル 積載量:1.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] 新しい積荷の重さ 重過ぎます。 現在位置:(80, 60) 残り燃料:71.72 リットル 積載量:1.00 トン 命令をどうぞ [ Move ... 1 / Carry ... 2 / Stand ... 3 / End .. 0 ] C:\usr\c\>