2 部データ構造とアルゴリズムI レポート課題

本講義では 2 通のレポートで評価します。 レポートは A4 縦の様式で PDF 形式で作成して下さい。 またプログラムは C 言語で作成しなさい。

変更履歴

2026/5/21 18:10:00
課題1初出
2026/6/18 18:10:00
課題2初出
2026/6/18 19:00:00
課題2追記
2026/6/25 18:10:00
課題2 問題2-1訂正
2026/6/25 19:30:00
課題2 問題2-3訂正、 ダウンロードファイルを algo2026kadai22.zipに差し替え

課題2

レポート締切日: 2026年7月1日(水)23:59
提出先: BOX にファイル名を 学籍番号_2.pdfとして、 アップロードすること

解答法は課題1と同等である。 但し、課題1で作成したプログラムを使用、結合して良く、またその際には、 課題1のプログラムの詳細の説明は省いてよい。

問題の最後に、本課題で必要なヘッダファイル kadai2.h と Makefile を示す。 課題で作成する関数は「関数名.c」というファイルに入れられる前提としている。

本課題で使用するヘッダファイル kadai2.h (後述)には次の構造体が定義されてい る。


typedef struct ulist {
  URIAGE uriage;
  struct ulist *next;
} ULIST;

これを使用した線形リストを処理するプログラムを作成する

問題2-1

ULIST を用いて作成した線形リストについて、 順に売上を表示して改行するのを繰り返し、税込みの売上の合計を返す double printuriagelist(ULIST* p) をprinturiagelist.cというファイルに作成せよ。 なお、空のリストを受け取った場合は、何も表示しない。 なお作成にあたって、課題1で作成した printuriage などの関数を使用して良い。

これと、下記のテストプログラムと kadai1.c getzeiritsu.c printuriage.c などを結合し て実行し、出力結果を示せ。

kadai21.c


#include <stdio.h>
#include <stdlib.h>
#include "kadai2.h"
int main(void){
  int i;
  ULIST ul[5]={{{0}},{{12,3}},{{1,4}},{{2,5}},{{11,6}}};
  ul[0].next=NULL;
  ul[1].next=&ul[3];
  ul[2].next=&ul[1];
  ul[3].next=&ul[0];
  ul[4].next=&ul[2];
  for(i=0;i<sizeof(ul)/sizeof(ul[0]); i++){
    printf("%.2f円\n-----------\n", printuriagelist(&ul[i]));
  }
  return 0;
}
出力例2-1
0.00円
-----------
サンドイッチ              	x3	  648円 (税率8%)
ノート                       	x5	 1100円 (税率10%)
1748.00円
-----------
水性ボールペン           	x4	  440円 (税率10%)
サンドイッチ              	x3	  648円 (税率8%)
ノート                       	x5	 1100円 (税率10%)
2188.00円
-----------
ノート                       	x5	 1100円 (税率10%)
1100.00円
-----------
おにぎり                    	x6	  648円 (税率8%)
水性ボールペン           	x4	  440円 (税率10%)
サンドイッチ              	x3	  648円 (税率8%)
ノート                       	x5	 1100円 (税率10%)
2836.00円
-----------

問題2-2

商品番号から該当する商品番号を持つSHOHIN のポインターを返す SHOHIN* getshohin(int no) をgetshohin.cというファイルに作成せよ。 なお、商品番号に該当する商品がない場合はNULLを返すこと。

これと、下記のテストプログラムと kadai1.c などを結合し て実行し、出力結果を示せ。

kadai22.c


#include <stdio.h>
#include "kadai2.h"
int main(void){
  int i;
  SHOHIN* p;
  SHOHIN* q;
  for(p=master; p->no!=0; p++){
    printf("no:%d, ", p->no);
    q=getshohin(p->no);
    printf("種別:%d, 単価:%d, 品名:%s\n",q->shubetsu, q->tanka, q->name);
  }
  return 0;
}
出力例2-2
no:1, 種別:0, 単価:100, 品名:水性ボールペン
no:2, 種別:0, 単価:200, 品名:ノート
no:11, 種別:1, 単価:100, 品名:おにぎり
no:12, 種別:1, 単価:200, 品名:サンドイッチ

問題2-3

ULIST を用いて作成した線形リストについて、 商品種別を指定して、 順に種別に該当する売上を表示して改行するのを繰り返し、税込みの売上の合計を返す double printuriagelistbyshubetsu(ULIST *p,int shubetsu) をprinturiagelistbyshubetsu.cというファイルに作成せよ。 なお、空のリストを受け取った場合は、何も表示しない。 なお作成にあたって、課題1で作成した printuriage や getshohin などの関数を使用して良い。

これと、下記のテストプログラムと kadai1.c getzeiritsu.c printuriage.c getshohin.c などを結合し て実行し、出力結果を示せ。

kadai23.c


#include <stdio.h>
#include <stdlib.h>
#include "kadai2.h"

int main(void){
  int i;
  int j;
  ULIST ul[5]={{{0}},{{12,3}},{{1,4}},{{2,5}},{{11,6}}};
  ul[0].next=NULL;
  ul[1].next=&ul[3];
  ul[2].next=&ul[1];
  ul[3].next=&ul[0];
  ul[4].next=&ul[2];
  for(j=0;j<2;j++){
    printf("種別: %d\n",j);
    for(i=0;i<sizeof(ul)/sizeof(ul[0]); i++){
      printf("%.2f円\n-----------\n", printuriagelistbyshubetsu(&ul[i],j));
    }
  }
  return 0;
}
出力例2-3
種別: 0
0.00円
-----------
ノート                       	x5	 1100円 (税率10%)
1100.00円
-----------
水性ボールペン           	x4	  440円 (税率10%)
ノート                       	x5	 1100円 (税率10%)
1540.00円
-----------
ノート                       	x5	 1100円 (税率10%)
1100.00円
-----------
水性ボールペン           	x4	  440円 (税率10%)
ノート                       	x5	 1100円 (税率10%)
1540.00円
-----------
種別: 1
0.00円
-----------
サンドイッチ              	x3	  648円 (税率8%)
648.00円
-----------
サンドイッチ              	x3	  648円 (税率8%)
648.00円
-----------
0.00円
-----------
おにぎり                    	x6	  648円 (税率8%)
サンドイッチ              	x3	  648円 (税率8%)
1296.00円
-----------

問題2-4

ULIST を用いた線形リストの先頭に URIAGE を追加し、 追加したデータを含む ULIST のポインタを返す ULIST* add(ULIST* p, URIAGE u) をadd.cというファイルに作成せよ。 なお、 malloc でメモリを確保できなかった場合は NULL を返すこと。

これと、下記のテストプログラムと kadai1.c getzeiritsu.c getshohin.c printuriage.c printuriagelist.c printuriagelistbyshubetsu.c などを結合し て実行し、出力結果を示せ。 なお、問題2-1,2-2,2-3で作成した printuriagelist.c getshohin.c printuriagelistbyshubetsu.c などの内容は問題2-1, 2-2, 2-3で示したプログラムを この問題にだけ変更することは絶対にしてはならない。 変更した場合は科目不合格とする。

kadai24.c


#include <stdio.h>
#include <stdlib.h>
#include "kadai2.h"

void dellist(ULIST* p){
  if(p!=NULL){
    dellist(p->next);
    free(p);
  }
}
int main(void){
  int i;
  int j;
  URIAGE u[]={{12,3},{1,4},{2,5},{11,6},{0}};
  ULIST* p=malloc(sizeof(ULIST));
  ULIST* q;
  if(p==NULL){
    exit(1);
  }
  p->next = NULL;
  for(i=0; u[i].no!=0; i++){
    q=add(p, u[i]);
    if(q==NULL){
      dellist(p);
      exit(1);
    }
    printf("売上:");
    printuriage(q->uriage);
    printf("%.2f円\n-----------\n", printuriagelist(p));
  }
  zeiritsu[1]=0;
  for(j=0;j<2;j++){
    printf("種別: %d\n",j);
    printf("%.2f円\n-----------\n", printuriagelistbyshubetsu(p,j));
  }
  return 0;
}
出力例2-4
売上:サンドイッチ              	x3	  648円 (税率8%)
サンドイッチ              	x3	  648円 (税率8%)
648.00円
-----------
売上:水性ボールペン           	x4	  440円 (税率10%)
水性ボールペン           	x4	  440円 (税率10%)
サンドイッチ              	x3	  648円 (税率8%)
1088.00円
-----------
売上:ノート                       	x5	 1100円 (税率10%)
ノート                       	x5	 1100円 (税率10%)
水性ボールペン           	x4	  440円 (税率10%)
サンドイッチ              	x3	  648円 (税率8%)
2188.00円
-----------
売上:おにぎり                    	x6	  648円 (税率8%)
おにぎり                    	x6	  648円 (税率8%)
ノート                       	x5	 1100円 (税率10%)
水性ボールペン           	x4	  440円 (税率10%)
サンドイッチ              	x3	  648円 (税率8%)
2836.00円
-----------
種別: 0
ノート                       	x5	 1100円 (税率10%)
水性ボールペン           	x4	  440円 (税率10%)
1540.00円
-----------
種別: 1
おにぎり                    	x6	  600円 (税率0%)
サンドイッチ              	x3	  600円 (税率0%)
1200.00円
-----------

ヘッダファイル、Makefile

kadai2.h


#include "kadai1.h"
typedef struct ulist {
  URIAGE uriage;
  struct ulist *next;
} ULIST;
double printuriagelist(ULIST* p);
SHOHIN* getshohin(int no);
double printuriagelistbyshubetsu(ULIST *p,int shubetsu);  
ULIST* add(ULIST* p, URIAGE u);

Makefile

$(CC) -o $@ $^の $(CC) の前には TAB 記号が一つ だけ入っていることに注意する。これが空白記号に置き換わっていると動作しない。


kadai24.exe: kadai24.o kadai1.o getshohin.o printuriage.o printuriagelist.o getzeiritsu.o add.o printuriagelistbyshubetsu.o 
	$(CC) -o $@ $^
kadai23.exe: kadai23.o kadai1.o getshohin.o printuriage.o printuriagelistbyshubetsu.o getzeiritsu.o
	$(CC) -o $@ $^
kadai22.exe: kadai22.o kadai1.o getshohin.o
	$(CC) -o $@ $^
kadai21.exe: kadai21.o kadai1.o getzeiritsu.o printuriage.o printuriagelist.o
	$(CC) -o $@ $^
kadai13.exe: kadai13.o kadai1.o getzeiritsu.o printuriage.o printreceipt.o
	$(CC) -o $@ $^
kadai12.exe: kadai12.o kadai1.o getzeiritsu.o printuriage.o
	$(CC) -o $@ $^
kadai11.exe: kadai11.o kadai1.o getzeiritsu.o
	$(CC) -o $@ $^
kadai21.o: kadai1.h kadai2.h
kadai22.o: kadai1.h kadai2.h
kadai23.o: kadai1.h kadai2.h
kadai24.o: kadai1.h kadai2.h
printuriagelist.o:  kadai1.h kadai2.h
getshohin.o:  kadai1.h kadai2.h
printuriagelistbyshubetsu.o: kadai1.h kadai2.h
add.o: kadai1.h kadai2.h
kadai11.o: kadai1.h
kadai12.o: kadai1.h
kadai13.o: kadai1.h
kadai1.o: kadai1.h
getzeiritsu.o: kadai1.h
printuriage.o: kadai1.h
printreceipt.o: kadai1.h

Visual Studio での開発法

なお、課題1でVisual Studio で開発した場合、次のような手順でプロジェ クトを追加し、課題2も開発できます。

  1. 追加ファイル algo2026kadai2.zip algo2026kadai22.zip をダウンロード して、解凍する。
  2. ダウンロードしたzipファイルをすべて解凍
  3. 解凍したalgo2026フォルダを、課題1の開発で使っている algo2026フォルダ に重ねて内容を移す。 algo2026.slnは置き換える。
  4. algo2026.sln をダブルクリックして起動すると開発できる。

課題1

レポート締切日: 2026年6月3日(水)23:59
提出先: BOX にファイル名を 学籍番号_1.pdfとして、 アップロードすること

解答法として、分割コンパイルによる別ファイルにプログラムを書く方 法と、下記のテストプログラムに関数を追記する方法の二通りがあるが、 どちらでも良い。 プログラムの解説は、自分で作成した関数について行うこと。 こちらで提供したテストプログラムの説明は基本的には不要である。 但し、自分で作成した関数を説明するのに必要な内容には言及すること。 また前問で作成した関数については自由に使用して良い。

問題とテストプログラムの改変は不合格である。 なお、こちらの提供したファイルやMakefile は使用してもしなくても良い。 また、プログラムを結合するためなどのやむを得ない必要な変更(include の代わりにプログラムを埋め込むなど)は許される。

問題の最後に、本課題で必要なヘッダファイル kadai1.h と Makefile を示す。また、 Visual Studio のソリューションを含む圧縮ファイルを置く。 課題で作成する関数は「関数名.c」というファイルに入れられる前提としている。

なお、課題1だけはレポートは締め切り後も提出できます。 同じファイル名で複数のバージョンが存在できます。 締め切り内に採点可能なレポートがある場合は、最も締切に近いものだけを採 点します。 締め切り内に有効なレポートがない場合、最も新しいレポートを遅れレポー トとして減点の上採点します。


kadai1.h には本課題に必要な宣言が含まれている。 まず、 構造体 SHOHIN は次のように定義されている。


typedef struct {
  int no;
  int shubetsu;
  int tanka;
  char* name;
} SHOHIN;

no は商品番号、 shubetsu は商品種別コード、 tanka は単価、name は商 品名を意味する。

また、構造体 URIAGE は次のように定義されている。


typedef struct {
  int no;
  int kosuu;
} URIAGE;

no は商品番号、 kosuu は個数を意味する。

またグローバル変数として、 商品種別コード別の税率が入っている配列 zeiritsu と 商品の配列 master (番兵として最後に no=0 となっている要素が含まれる) が次のように extern されている。


extern double zeiritsu[];
extern SHOHIN master[];

この他、課題で必要な、関数のプロトタイプ宣言が含まれている。 また、kadai1.c には zeiritsu, master の定義が含まれているため、 各問題で作成したプログラムを実行するには kadai1.c を結合する必要があ る。

問題1-1

構造体 SHOHIN の値を受け取り、 その商品種別コードから税率を得る double getzeiritsu(SHOHIN s) を getzeiritsu.cというファイルに作成せよ。

これと、下記のテストプログラム, kadai1.h, kadai1.c を結合して実行し、出 力結果を示せ。

kadai11.c


#include <stdio.h>
#include "kadai1.h"
int main(void){
  SHOHIN* p;
  for(p=master;p->no !=0; p++){
    printf("%2d:\t%-32s\t%4d円\t%2d%%\n",p->no, p->name, p->tanka,
	   (int)(getzeiritsu(*p)*100));
  }
  return 0;
}
出力例1-1
 1:	水性ボールペン           	 100円	10%
 2:	ノート                       	 200円	10%
11:	おにぎり                    	 100円	 8%
12:	サンドイッチ              	 200円	 8%

問題1-2

構造体URIAGEの の値を受け取り、その商品コードを master から検索して 、商品名、個数、税込価格、税率を表示し、税込み購入価格を返す double printuriage(URIAGE u) 関数を作成せよ。 この関数のファイル名を printuriage.c とする。

これと、下記のテストプログラム, kadai1.h, kadai1.c, getzeiritsu.cを 結合して実行し、出力結果を示せ。

kadai12.c


#include <stdio.h>
#include "kadai1.h"
int main(void){
  URIAGE list[] = {{1,1},{2,2},{11,3},{12,4},{0}};
  double keisan;
  double kakaku[]={110,440,324,864};
  double epsilon=0.01;
  int i;
  for(i=0;list[i].no !=0; i++){
    keisan= printuriage(list[i])-kakaku[i];
    if(keisan>-epsilon && keisan<epsilon){
      printf("Ok\n");
    }else{
      printf("NG\n");
    }
  }
  return 0;
}
出力例1-2
水性ボールペン           	x1	  110円 (税率10%)
Ok
ノート                       	x2	  440円 (税率10%)
Ok
おにぎり                    	x3	  324円 (税率8%)
Ok
サンドイッチ              	x4	  864円 (税率8%)
Ok

問題1-3

URIAGE の配列(ただし、最後に商品コード 0の番兵を含む)を受け取り、 それぞれの売上を表示し、最後に合計金額を表示し、合計金額を返す double printreceipt(URIAGE* u) 関数を作成せよ。

これと、下記のテストプログラム, kadai1.h, kadai1.c, getzeiritsu.c, printuriage.c を 結合して実行し、出力結果を示せ。

kadai13.c


#include <stdio.h>
#include "kadai1.h"
int main(void){
  URIAGE list[] = {{1,1},{2,2},{11,3},{12,4},{0}};
  double epsilon=0.01;
  double keisan;
  keisan = printreceipt(list)- 1738;
  if(keisan> -epsilon && keisan<epsilon){
    printf("Ok\n");
  }else{
    printf("NG\n");
  }
  zeiritsu[1]=0;
  keisan = printreceipt(list)- 1650;
  if(keisan>-epsilon && keisan<epsilon){
    printf("Ok\n");
  }else{
    printf("NG\n");
  }
  return 0;
}
出力例1-3
水性ボールペン           	x1	  110円 (税率10%)
ノート                       	x2	  440円 (税率10%)
おにぎり                    	x3	  324円 (税率8%)
サンドイッチ              	x4	  864円 (税率8%)
合計 1738.00円
Ok
水性ボールペン           	x1	  110円 (税率10%)
ノート                       	x2	  440円 (税率10%)
おにぎり                    	x3	  300円 (税率0%)
サンドイッチ              	x4	  800円 (税率0%)
合計 1650.00円
Ok

kadai1.h


typedef struct {
  int no;
  int shubetsu;
  int tanka;
  char* name;
} SHOHIN;
typedef struct {
  int no;
  int kosuu;
} URIAGE;
extern double zeiritsu[];
extern SHOHIN master[];
double getzeiritsu(SHOHIN s);
double printuriage(URIAGE u);
double printreceipt(URIAGE* u);

kadai1.c


#include "kadai1.h"
double zeiritsu[]={0.1,0.08};
SHOHIN master[] = {{1,0,100,"水性ボールペン"},
		   {2,0,200,"ノート"},
		   {11,1,100,"おにぎり"},
		   {12,1,200,"サンドイッチ"},
		   {0}};

Makefile

$(CC) -o $@ $^の $(CC) の前には TAB 記号が一つ だけ入っていることに注意する。これが空白記号に置き換わっていると動作しない。


kadai13.exe: kadai13.o kadai1.o getzeiritsu.o printuriage.o printreceipt.o
	$(CC) -o $@ $^
kadai12.exe: kadai12.o kadai1.o getzeiritsu.o printuriage.o
	$(CC) -o $@ $^
kadai11.exe: kadai11.o kadai1.o getzeiritsu.o
	$(CC) -o $@ $^
kadai11.o: kadai1.h
kadai12.o: kadai1.h
kadai13.o: kadai1.h
kadai1.o: kadai1.h
getzeiritsu.o: kadai1.h
printuriage.o: kadai1.h
printreceipt.o: kadai1.h

Visual Studio での開発法

下記の操作をしたものをalgo2026.zipとし てダウンロードできます。 ダウンロードしたzipファイルをすべて解凍して、中の sln ファイルをダブ ルクリックすると使用できます。

  1. プロジェクトを作成する時に、プロジェクト名を kadai11 とし、ソリュー ション名は別に与える(例えばalgo2026など)
  2. 日本語の設定として
    1. ツール→オプション
    2. 環境の中のドキュメントタブ
    3. 「特定のエンコードでファイルを保存する」をチェックし
    4. 「Unicode(UTF-8 署名付き)コードページ 65001」を選択する
  3. 以下をソリューションエクスプローラで実施する
  4. プロジェクト kadai11 には、ソースファイルとして、新しい項目に kadai11.c を入れる。
  5. プロジェクト kadai12, kadai13 をソリューションに追加す る。
  6. それぞれのプロジェクトに kadai12.c, kadai13.c をソー スファイルに入れる。
  7. ソリューションを右クリックして 「エクスプローラーでフォルダーを開く」
  8. kadai フォルダを新規に作成する
  9. kadai フォルダに kadai1.h, kadai1.cを入れる。 また、getzeiritsu.c, printuriage.c, printreceipt.c という名前の 空のファイルを、「新規作成→テキストドキュメントで作成して、名前の変更」 で作成する。これが終わったらエクスプローラーの画面を消して良い。
  10. 3つのプロジェクトそれぞれを右クリックして、プロパティを選ぶ。
    1. C/C++ の項目の最上段の「追加のインクルードディレクトリ」で <編集…>を選択し
    2. 入力欄に「$(SolutionDir)kadai」を入力し、Okを押す
    3. プロパティの Okを押す
  11. 3つのプロジェクトそれぞれで、 「ヘッダファイルを右 クリック→追加→既存のファイル」で kadai フォルダから kadai1.h を選び、 さらに、各プロジェクトで必要なファイルを「ソースファイルを右 クリック→追加→既存のファイル」 で追加する。
  12. 実行するプロジェクトを切り替えるには、実行したいプロジェクトを右クリックして「スタートアッププロジェクトに設定」を選ぶ

レポート作成上の注意

  1. レポートはグラフの表現など特殊な事情がない限り、必ず白黒で作成する こと。
  2. プログラミングのレポートでは必ずプログラムの説明をすること。その時 に、一行一行を日本語に直訳するのではなく、プログラムを機能毎に区分し、 機能の実現方法を説明すること。 プログラムに一行ずつコメントを入れてもプログラムの説明とは見なしません。
  3. 「問題を解きなさい」という問に対して「解きました。合ってました」は 正解ではありません。 「プログラムを作りなさい」という問題については、作成の手順の説明をする こと。 「テストしなさい」という問題についてはテストの手法、合否判定の基準、結 果の検討などを説明しなさい。
  4. プログラムが短くて説明がしづらい場合は、ポインタなどの関係を図示す るなどして工夫してください。
  5. 出力例は個々に異なりますので、手計算であらかじめ正しい値の求め方を 示し、値を提示してテストの合否を判定しなさい。
  6. レポートは手書きでも良いですが、プログラムの実行結果だけは必ずコン ピュータの出力の印刷(スクリーンショット)にして下さい。
  7. 考察は必ず書いて下さい。ネタがない人は以下を参考にして下さい。

なお、写したと思われるほど酷似したレポートが複数提出された場合、原著が どれかの調査を行わず、抽選で一通のレポートのみを評価 の対象とし、他は提出済みの不合格レポートとして再提出は課しません。 自分で意図せずに他人にコピーされてしまった場合も同様ですので、レポート の取り扱いについては十分に注意して下さい。


坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科