Powered by SmartDoc

ソフトウェア概論B (2010/12/10)
Ver. 1.0

2010年12月10日
栗野 俊一
kurino@math.cst.nihon-u.ac.jp
http://edu-gw2.math.cst.nihon-u.ac.jp/~kurino/2010/soft/soft.html
ソフトウェア概論 B2010年12月10日 の資料

目次

講義資料

当日の OHP 資料

当日のOHP資料です。

本日の概要

12.構造体

講義で利用するサンプルプログラム

sample-000

Download : sample-000.c ( SJIS 版 )

sample-000.c
/*
 * [参考] list 12-1 (text p.268)
 */

/*
 * 5 人の学生の <<身長>> を昇順にソート
 */

#include <stdio.h>

#define NUMBER	5	/* 学生の人数 */

/* x および y が指す整数の値を交換 */

void swap ( int *x, int *y ) {
  int temp = *x;

  *x = *y;
  *y = temp;

}

/* 配列 data の先頭 n 個の要素を昇順にソート */

void sort ( int data[], int size ) {	/* 素直な実装 */
  int sort_end;				/* ソートが済でない場所の最終位置 */
  int looking;				/* 比較する場所 */

  /* n 個のデータの隣合った二つの組み合わせは nC2 = n(n-1)/2 */

  for ( sort_end = size - 1; sort_end > 0; sort_end-- ) {

    /*
     - 最初は、全然ソートが済んでいないので、sort_end の場所は、配列の最後 (size-1)
     - sort_end が 0 になるということは、ソートの対象が 1 個になったという事なので、
      それ以上の作業は不要 ( 一個のデータはそれだけで、ソートされている )
     - ソートが済んでいない場所を一通りチェックすると、一番大きいデータが、最後まで「沈んで」
      来るので、sort_end は一つ減らしてよい
    */

    for ( looking = 0; looking < sort_end; looking++ ) { 
      /*
	- ソート済みでない場所 ( 0 〜 sort_end ) を先頭 (0) から眺めて (looking) ゆく
	- 眺めている場所(looking)が、ソート済みの最後 ( sort_end ) になったら、
	  一通り眺めた事になる ( その隣は調べる必要がない )
	- 眺める場所は、頭から順に一つずつ
       */

      if ( data[ looking ] > data[ looking + 1 ] ) {
	/* 眺めている場所 (looking) とその隣 ( looking + 1 ) が不整合ならば */

	swap( &data[looking], &data[looking + 1] );
	/* データを交換して、整合化する */

      }
    }
  }
}

int main ( void ) {
  int i;
  int height[] = { 178, 175, 173, 165, 179 };

  sort ( height, NUMBER );

  for ( i = 0; i < NUMBER; i++ ) {
    printf ( "%2d : %4d\n", i + 1, height[i] );
  }

  return 0;
}
sample-000.c の実行結果
C:\usr\c\> sample-000
 1 :  165
 2 :  173
 3 :  175
 4 :  178
 5 :  179
C:\usr\c\> 

sample-001

Download : sample-001.c ( SJIS 版 )

sample-001.c
/*
 * [参考] list 12-1 (text p.268)
 */

/*
 * 5 人の学生の <<身長>> を昇順にソート
 */

#include <stdio.h>

#define NUMBER	5	/* 学生の人数 */

/* x および y が指す整数の値を交換 */

void swap ( int *x, int *y ) {
  int temp = *x;

  *x = *y;
  *y = temp;

}

/* 配列 data の先頭 n 個の要素を昇順にソート */

void sort ( int data[], int n ) {
  int k = n - 1;

  while ( k >= 0 ) {
    int i, j;

    for ( i = 1, j = -1; i <= k; i++ ) {
      if ( data[ i - 1 ] > data[ i ] ) {
	j = i - 1;
	swap( &data[i], &data[j] );
      }
    }

    k = j;
  }
}

int main ( void ) {
  int i;
  int height[] = { 178, 175, 173, 165, 179 };

  sort ( height, NUMBER );

  for ( i = 0; i < NUMBER; i++ ) {
    printf ( "%2d : %4d\n", i + 1, height[i] );
  }

  return 0;
}
sample-001.c の実行結果
C:\usr\c\> sample-001
 1 :  165
 2 :  173
 3 :  175
 4 :  178
 5 :  179
C:\usr\c\> 

sample-002

Download : sample-002.c ( SJIS 版 )

sample-002.c
/*
 * [参考] list 12-2 (text p.271)
 */

/*
 * 5 人の学生の <<名前と身長>> を、身長の昇順にソート
 */

#include <stdio.h>
#include <string.h>

#define NUMBER		5	/* 学生の人数 */
#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* x および y が指す整数の値を交換 */

void swap ( int *x, int *y ) {
  int temp = *x;

  *x = *y;
  *y = temp;

}

/* sx および sy が指す文字列を交換 */

void swaps ( char sx[NAME_SIZE], char sy[NAME_SIZE] ) {
  char temp[NAME_SIZE];

  strcpy ( temp, sx );
  strcpy ( sx, sy );
  strcpy ( sy, temp );

}

/* 配列 data と name の先頭 n 個の要素を昇順にソート */

void sort ( int data[], char name[][NAME_SIZE], int n ) {
  int k = n - 1;

  while ( k >= 0 ) {
    int i, j;

    for ( i = 1, j = -1; i <= k; i++ ) {
      if ( data[ i - 1 ] > data[ i ] ) {
	j = i - 1;
	swap( &data[i], &data[j] );
	swaps( name[i], name[j] );
      }
    }

    k = j;
  }
}

int main ( void ) {
  int i;
  int height[] = { 178, 175, 173, 165, 179 };
  char name[][NAME_SIZE] = { "Sato", "Sanake", "Takao", "Mike", "Masaki" };

  sort ( height, name, NUMBER );

  for ( i = 0; i < NUMBER; i++ ) {
    printf ( "%2d : %-8s%4d\n", i + 1, name[i], height[i] );
  }

  return 0;
}
sample-002.c の実行結果
C:\usr\c\> sample-002
 1 : Mike     165
 2 : Takao    173
 3 : Sanake   175
 4 : Sato     178
 5 : Masaki   179
C:\usr\c\> 

sample-003

Download : sample-003.c ( SJIS 版 )

sample-003.c
/*
 * [参考] list 12-3 (text p.274)
 */

/*
 * 学生を表す構造体で表した佐中君
 */

#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

int main ( void ) {
  struct gstudent sanaka;

  strcpy ( sanaka.name, "Sanaka" );	/* 名前 */
  sanaka.height = 175;			/* 身長 */
  sanaka.weight = 60.5;			/* 体重 */
  sanaka.schols = 70000;		/* 奨学金 */

  printf ( "名  前 = %s\n", sanaka.name );
  printf ( "身  長 = %d\n", sanaka.height );
  printf ( "体  重 = %f\n", sanaka.weight );
  printf ( "奨学金 = %ld\n", sanaka.schols );

  return 0;
}
sample-003.c の実行結果
C:\usr\c\> sample-003
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 70000
C:\usr\c\> 

sample-004

Download : sample-004.c ( SJIS 版 )

sample-004.c
/*
 * [参考] list 12-3 (text p.274)
 */

/*
 * 学生を表す構造体で表した佐中君の初期化
 */


#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

int main ( void ) {
  struct gstudent sanaka = { "Sanaka", 175, 60.5 };

  printf ( "名  前 = %s\n", sanaka.name );
  printf ( "身  長 = %d\n", sanaka.height );
  printf ( "体  重 = %f\n", sanaka.weight );
  printf ( "奨学金 = %ld\n", sanaka.schols );

  return 0;
}
sample-004.c の実行結果
C:\usr\c\> sample-004
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 0
C:\usr\c\> 

sample-005

Download : sample-005.c ( SJIS 版 )

sample-005.c
/*
 * 構造体型変数の代入 : 佐中君の双子の兄弟
 */

#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

/* 佐中君と双子の兄弟 */

int main ( void ) {
  struct gstudent sanaka = { "Sanaka", 175, 60.5 };	/* 佐中君 */
  struct gstudent twin;					/* 双子 */

  twin = sanaka;					/* 佐中君と同じ */
  twin.schols = 50000;					/* 奨学金は別 */

  printf ( "[佐中君の情報]\n" );
  printf ( "名  前 = %s\n", sanaka.name );
  printf ( "身  長 = %d\n", sanaka.height );
  printf ( "体  重 = %f\n", sanaka.weight );
  printf ( "奨学金 = %ld\n", sanaka.schols );

  printf ( "[双子の兄弟の情報]\n" );
  printf ( "名  前 = %s\n", twin.name );
  printf ( "身  長 = %d\n", twin.height );
  printf ( "体  重 = %f\n", twin.weight );
  printf ( "奨学金 = %ld\n", twin.schols );

  return 0;
}
sample-005.c の実行結果
C:\usr\c\> sample-005
[佐中君の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 0
[双子の兄弟の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 50000
C:\usr\c\> 

sample-006

Download : sample-006.c ( SJIS 版 )

sample-006.c
/*
 * 関数への構造体型の値の受渡し (No.2)
 */

#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

/* 構造体で表現された学生情報の表示 */

void print_student ( struct gstudent student ) {

  printf ( "名  前 = %s\n", student.name );
  printf ( "身  長 = %d\n", student.height );
  printf ( "体  重 = %f\n", student.weight );
  printf ( "奨学金 = %ld\n", student.schols );
}

/* 佐中君と双子の兄弟 */

int main ( void ) {
  struct gstudent sanaka = { "Sanaka", 175, 60.5 };	/* 佐中君 */
  struct gstudent twin;					/* 双子 */

  twin = sanaka;					/* 佐中君と同じ */


  twin.schols = 50000;					/* 奨学金は別 */

  printf ( "[佐中君の情報]\n" );
  print_student ( sanaka );

  printf ( "[双子の兄弟の情報]\n" );
  print_student ( twin );

  return 0;
}
sample-006.c の実行結果
C:\usr\c\> sample-006
[佐中君の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 0
[双子の兄弟の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 50000
C:\usr\c\> 

sample-007

Download : sample-007.c ( SJIS 版 )

sample-007.c
/*
 * 関数への構造体型の値の受渡し (No.2)
 */

#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

/* 構造体で表現された学生情報の表示 */

void print_student ( struct gstudent student ) {

  printf ( "名  前 = %s\n", student.name );
  printf ( "身  長 = %d\n", student.height );
  printf ( "体  重 = %f\n", student.weight );
  printf ( "奨学金 = %ld\n", student.schols );
}

/* 構造体で表現された学生情報の情報の変更 (失敗例) */

void set_schols ( struct gstudent student, long new_schols ) {

  printf ( "以前の奨学金 = %ld\n", student.schols );

  student.schols = new_schols;

  printf ( "新規の奨学金 = %ld\n", student.schols );

}

/* 佐中君と双子の兄弟 */

int main ( void ) {
  struct gstudent sanaka = { "Sanaka", 175, 60.5 };	/* 佐中君 */
  struct gstudent twin;					/* 双子 */

  twin = sanaka;					/* 佐中君と同じ */

  set_schols ( twin, 50000 );				/* 奨学金を与える事に */

  printf ( "[佐中君の情報]\n" );
  print_student ( sanaka );

  printf ( "[双子の兄弟の情報]\n" );
  print_student ( twin );

  return 0;
}
sample-007.c の実行結果
C:\usr\c\> sample-007
以前の奨学金 = 0
新規の奨学金 = 50000
[佐中君の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 0
[双子の兄弟の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 0
C:\usr\c\> 

sample-008

Download : sample-008.c ( SJIS 版 )

sample-008.c
/*
 * 関数への構造体型の値の受渡し (No.3)
 */

#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

/* 構造体で表現された学生情報の表示 */

void print_student ( struct gstudent student ) {

  printf ( "名  前 = %s\n", student.name );
  printf ( "身  長 = %d\n", student.height );
  printf ( "体  重 = %f\n", student.weight );
  printf ( "奨学金 = %ld\n", student.schols );
}

/* 構造体で表現された学生情報の情報の変更 (成功例:ポインターを利用) */

void set_schols ( struct gstudent *ptr_student, long new_schols ) {

  printf ( "以前の奨学金 = %ld\n", (*ptr_student).schols );

  (*ptr_student).schols = new_schols;

  printf ( "新規の奨学金 = %ld\n", (*ptr_student).schols );

}

/* 佐中君と双子の兄弟 */

int main ( void ) {
  struct gstudent sanaka = { "Sanaka", 175, 60.5 };	/* 佐中君 */
  struct gstudent twin;					/* 双子 */

  twin = sanaka;					/* 佐中君と同じ */

  set_schols ( &twin, 50000 );				/* 奨学金を与える事に */

  printf ( "[佐中君の情報]\n" );
  print_student ( sanaka );

  printf ( "[双子の兄弟の情報]\n" );
  print_student ( twin );

  return 0;
}
sample-008.c の実行結果
C:\usr\c\> sample-008
以前の奨学金 = 0
新規の奨学金 = 50000
[佐中君の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 0
[双子の兄弟の情報]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 50000
C:\usr\c\> 

sample-009

Download : sample-009.c ( SJIS 版 )

sample-009.c
/*
 * [参考] list 12-5 (text p.277)
 */

/*
 * 超能力をもったひろ子さん
 */

#include <stdio.h>
#include <string.h>

#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* 学生を表す構造体 */
struct gstudent {
  char  name[NAME_SIZE];	/* 名前 */
  int   height;			/* 身長 */
  float weight;			/* 体重 */
  long	schols;			/* 奨学金 */
};

/* 構造体で表現された学生情報の表示 */

void print_student ( struct gstudent student ) {

  printf ( "名  前 = %s\n", student.name );
  printf ( "身  長 = %d\n", student.height );
  printf ( "体  重 = %f\n", student.weight );
  printf ( "奨学金 = %ld\n", student.schols );
}

/* 身長を伸ばし、体重を減らしてくれるひろ子さん */

void hiroko ( struct gstudent *ptr_student ) {

  if ( (*ptr_student).height < 180 ) {		/* 身長が低いと... */
    (*ptr_student).height = 180;		/* 背を伸ばしてくれる */
  }

  if ( (*ptr_student).weight >  80.0 ) {	/* 体重が重いと... */
    (*ptr_student).weight = 80.0;		/* 痩せさせてくれる */
  }

}

/* ひろ子さんの超能力で、ダイエット */

int main ( void ) {
  struct gstudent sanaka = { "Sanaka", 175, 60.5, 70000 };

  printf ( "[ダイエット前]\n" );
  print_student ( sanaka );

  hiroko ( &sanaka );				/* ひろ子さん.. */

  printf ( "[ダイエット後]\n" );
  print_student ( sanaka );

  return 0;
}
sample-009.c の実行結果
C:\usr\c\> sample-009
[ダイエット前]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 70000
[ダイエット後]
名  前 = Sanaka
身  長 = 180
体  重 = 60.500000
奨学金 = 70000
C:\usr\c\> 

sample-010

Download : sample-010.c ( SJIS 版 )

sample-010.c
/*
 * [参考] list 12-6 (text p.278)
 */

/*
 * 超能力をもったひろ子さん (その 2)
 */

#include <stdio.h>
#include <string.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 );
}

/* 身長を伸ばし、体重を減らしてくれるひろ子さん */

void hiroko ( Student *ptr_student ) {

  if ( ptr_student -> height < 180 ) {		/* 身長が低いと... */
    ptr_student -> height = 180;		/* 背を伸ばしてくれる */
  }

  if ( ptr_student -> weight >  80.0 ) {	/* 体重が重いと... */
    ptr_student -> weight = 80.0;		/* 痩せさせてくれる */
  }

}

/* ひろ子さんの超能力で、ダイエット */

int main ( void ) {
  Student sanaka = { "Sanaka", 175, 60.5, 70000 };

  printf ( "[ダイエット前]\n" );
  print_student ( sanaka );

  hiroko ( &sanaka );				/* ひろ子さん.. */

  printf ( "[ダイエット後]\n" );
  print_student ( sanaka );

  return 0;
}
sample-010.c の実行結果
C:\usr\c\> sample-010
[ダイエット前]
名  前 = Sanaka
身  長 = 175
体  重 = 60.500000
奨学金 = 70000
[ダイエット後]
名  前 = Sanaka
身  長 = 180
体  重 = 60.500000
奨学金 = 70000
C:\usr\c\> 

本日の課題

構造体を利用したプログラムを作成する

課題20101217-01
sample-002.c (List 12-2)を参考に「5人の学生の<<名前と体重>>を昇順にソート」する、次のプログラムを完成させなさい。
課題20101217-01の穴埋め
課題
/*
 * [課題] 20091211-1
 */

/*
 * 5 人の学生の <<名前と体重>> を、体重の昇順にソート
 */

#include <stdio.h>
#include <string.h>

#define NUMBER		5	/* 学生の人数 */
#define	NAME_SIZE	20	/* <<名前>> の最大の長さ -1 */

/* fx および fy が指す浮動小数点数の値を交換 */

void swapf ( float *fx, float *fy ) {

	/*
	**	 この部分を完成させなさい
	*/

}

/* sx および sy が指す文字列を交換 */

void swaps ( char sx[NAME_SIZE], char sy[NAME_SIZE] ) {
  char temp[NAME_SIZE];

  strcpy ( temp, sx );
  strcpy ( sx, sy );
  strcpy ( sy, temp );

}

/* 配列 data と name の先頭 n 個の要素を昇順にソート */

void sort ( float data[], char name[][NAME_SIZE], int n ) {

	/*
	**	 この部分を完成させなさい
	*/

}

int main ( void ) {
  int i;
  float weight[] = { 72.0, 60.5, 62.5, 85.0, 70.5 };
  char name[][NAME_SIZE] = { "Sato", "Sanake", "Takao", "Mike", "Masaki" };

  sort ( weight, name, NUMBER );

  for ( i = 0; i < NUMBER; i++ ) {
    printf ( "%2d : %-8s%4f\n", i + 1, name[i], weight[i] );
  }

  return 0;
}
出力例
出力例
C:\usr\c\> 20101217-1
 1 : Sanake  60.500000
 2 : Takao   62.500000
 3 : Masaki  70.500000
 4 : Sato    72.000000
 5 : Mike    85.000000
C:\usr\c\> 
課題20101217-02
sample-008.cを参考に「キーボードから学生情報を入力し、構造体に収める関数input_student」を利用する、次のプログラムを完成させなさい。
課題20101217-02の穴埋め
課題
/*
 * [課題] 20091211-2
 */

/*
 * キーボードから学生情報を入力し、構造体に収める関数
 */

#include <stdio.h>
#include <string.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 );
}

/* 構造体で表現された学生情報の情報の入力 (ポインターを利用) */

void scan_student ( Student *ptr_student ) {

  printf ( "名  前 を入力してください\n" );

	/*
	**	 この部分を完成させなさい
	*/

  printf ( "身  長 を入力してください\n" );

	/*
	**	 この部分を完成させなさい
	*/

  printf ( "体  重 を入力してください\n" );

	/*
	**	 この部分を完成させなさい
	*/

  printf ( "奨学金 を入力してください\n" );

	/*
	**	 この部分を完成させなさい
	*/


}

/* データの入力 */

int main ( void ) {
  Student sanaka;

  /* scan_student を呼び出し、佐中君のデータをキーボードから入力する */

	/*
	**	 この部分を完成させなさい
	*/


  /* 佐中君のデータを出力する */
  print_student ( sanaka );

  return 0;
}
入力例
入力例
Sanaka
180
60.5
70000
出力例
出例
C:\usr\c\> 20101217-2
名  前 を入力してください
身  長 を入力してください
体  重 を入力してください
奨学金 を入力してください
名  前 = Sanaka
身  長 = 180
体  重 = 60.500000
奨学金 = 70000
C:\usr\c\> 

参考 Link