本講義では 2 通のレポートで評価します。 レポートは A4 の紙を縦に使い、適宜表紙を付けて提出すること。 またプログラムは C 言語で作成しなさい。
なお、遅れレポートは受け取らない。
レポート作成に当たっては、本課題のために作成したプログラムのみを説明 すれば良い。 課題1で作成したプログラムは、その旨断るだけで自由に使用して良い。
商品の売上の集計を線形リストで管理する。
URIAGE のポインタと次の要素へのポインタを持つ構造体 URIAGELIST を下記のように定義する。
typedef struct uriagelist {
struct uriagelist* next;
URIAGE *uriage;
}URIAGELIST;
これを用いて線形リストを作成する。 先頭のノードを指すポインタを変数で管理し、終端のノードからは空のノー ドに接続し、空のノードの next メンバが NULL であることで、ノードの終 端を検出するとする。 空のノードにはデータを入れないので、 uriage メンバの初期化は義務付け ない。
上記のように定義された線形リストの内容を表示する関数 void printUriageList(URIAGELIST* l) を作成しなさい。
そして、次のテストプログラム、課題1で使用したプログラムと結合し、結 果を示しなさい。
#include <stdio.h>
#include <stdlib.h>
#include "shohin.h"
#include "uriage.h"
#include "uriagelist.h"
int main(void){
URIAGE u1={1,2};
URIAGE u2={2,3};
URIAGE u3={3,4};
URIAGELIST l0={NULL};
URIAGELIST l1={&l0,&u1};
URIAGELIST l2={&l1,&u2};
URIAGELIST l3={&l2,&u3};
printf("-----\n");
printUriageList(&l0);
printf("-----\n");
printUriageList(&l1);
printf("-----\n");
printUriageList(&l2);
printf("-----\n");
printUriageList(&l3);
return 0;
}
----- ----- Orange 単価100円(内税) 2 個 200 円 ----- Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 ----- Book1 単価500円(外税) 4 個 2160 円 Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円
URIAGELIST のノードを動的に確保する関数 URIAGELIST* newlist(void) を作成しなさい。 ただし、領域を確保できなかった場合は NULL を返しなさい。 また、 next メンバは NULL で初期化してください。
そして、次のテストプログラム、課題1で使用したプログラムと結合し、結 果を示しなさい。
#include <stdio.h>
#include <stdlib.h>
#include "shohin.h"
#include "uriage.h"
#include "uriagelist.h"
int main(void){
URIAGE u1={1,2};
URIAGE u2={2,3};
URIAGE u3={3,4};
URIAGELIST *l0;
URIAGELIST *l1;
URIAGELIST *l2;
URIAGELIST *l3;
if((l0=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
return 2;
}
if((l1=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l0);
return 2;
}
if((l2=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l1);
free(l0);
return 2;
}
if((l3=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l2);
free(l1);
free(l0);
return 2;
}
printUriageList(l0);
printf("-----\n");
l1->next=l0;
l1->uriage=&u1;
printUriageList(l1);
printf("-----\n");
l2->next=l1;
l2->uriage=&u2;
printUriageList(l2);
printf("-----\n");
l3->next=l2;
l3->uriage=&u3;
printUriageList(l3);
printf("-----\n");
free(l3);
free(l2);
free(l1);
free(l0);
return 0;
}
----- Orange 単価100円(内税) 2 個 200 円 ----- Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 ----- Book1 単価500円(外税) 4 個 2160 円 Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 -----
線形リストにおいて、動的に確保したすべてのノードをfree関数により解放す る関数 void freeUriageList(URIAGELIST*l,int purge) を作成しなさい。 なお、uriage メンバーは URIAGE 型の領域へのポインタであるが、その領域 に関して、purge が 1 ならその領域も free により、開放する。 また、 purge が 0 ならその領域は free を行わない。
なお、線形リスト終端に接続した空のノードのuriageは使用しないので、こ こは purge が 1 でも free を実施しないこと。
そして、次のテストプログラム、課題1で使用したプログラムと結合し、結 果を示しなさい。
#include <stdio.h>
#include <stdlib.h>
#include "shohin.h"
#include "uriage.h"
#include "uriagelist.h"
int main(void){
URIAGE u1={1,2};
URIAGE u2={2,3};
URIAGE u3={3,4};
URIAGE *up1;
URIAGE *up2;
URIAGE *up3;
URIAGELIST *l0;
URIAGELIST *l1;
URIAGELIST *l2;
URIAGELIST *l3;
if((l0=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
return 2;
}
if((l1=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l0);
return 2;
}
if((l2=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l1);
free(l0);
return 2;
}
if((l3=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l2);
free(l1);
free(l0);
return 2;
}
l1->next=l0;
l1->uriage=&u1;
l2->next=l1;
l2->uriage=&u2;
l3->next=l2;
l3->uriage=&u3;
printUriageList(l3);
printf("-----\n");
freeUriageList(l3,0);
if((l0=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
return 2;
}
if((l1=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l0);
return 2;
}
if((l2=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l1);
free(l0);
return 2;
}
if((l3=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
return 2;
}
if((up1=malloc(sizeof(URIAGE)))==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l2);
free(l1);
free(l0);
return 2;
}
if((up2=malloc(sizeof(URIAGE)))==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l2);
free(l1);
free(l0);
free(up1);
return 2;
}
if((up3=malloc(sizeof(URIAGE)))==NULL){
fprintf(stderr,"領域を確保できませんでした");
free(l2);
free(l1);
free(l0);
free(up2);
free(up1);
return 2;
}
*up1=u1;
*up2=u2;
*up3=u3;
l1->next=l0;
l1->uriage=up1;
l2->next=l1;
l2->uriage=up2;
l3->next=l2;
l3->uriage=up3;
printUriageList(l3);
printf("-----\n");
freeUriageList(l3,1);
return 0;
}
Book1 単価500円(外税) 4 個 2160 円 Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 ----- Book1 単価500円(外税) 4 個 2160 円 Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 -----
URIAGEのポインターを受け取ると、URIAGELIST のノードで作られた線形リス トの先頭に、ノードを追加することで追加する URIAGELIST* add(URIAGELIST* l, URIAGE* u) 関数を作成しなさい。 なお、線形リストは、最初に l は空のノードを指しているものとする。 また、戻り値は新しく追加したURIAGEのポインタを含むノードのポインタを返 すものとし、追加に失敗した場合は NULL を返すものとする。
そして、次のテストプログラム、課題1で使用したプログラムと結合し、結 果を示しなさい。
#include <stdio.h>
#include <stdlib.h>
#include "shohin.h"
#include "uriage.h"
#include "uriagelist.h"
int main(void){
URIAGE u1={1,2};
URIAGE u2={2,3};
URIAGE u3={3,4};
URIAGE* u[]={&u1,&u2,&u3,NULL};
URIAGE **p;
URIAGELIST *l;
URIAGELIST *m;
if((l=newlist())==NULL){
fprintf(stderr,"領域を確保できませんでした");
return 2;
}
for(p=u;*p!=NULL;p++){
if((m=add(l,*p))==NULL){
fprintf(stderr,"領域を確保できませんでした");
freeUriageList(l,0);
return 2;
}
printf("追加%s\n", m->uriage==*p?"Ok":"NG");
printUriageList(l);
printf("-----\n");
}
freeUriageList(l,0);
return 0;
}
追加Ok Orange 単価100円(内税) 2 個 200 円 ----- 追加Ok Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 ----- 追加Ok Book1 単価500円(外税) 4 個 2160 円 Banana 単価200円(内税) 3 個 600 円 Orange 単価100円(内税) 2 個 200 円 -----
以下、ヘッダファイルを示す。
typedef struct uriagelist {
struct uriagelist* next;
URIAGE *uriage;
}URIAGELIST;
void printUriageList(URIAGELIST* l);
URIAGELIST* newlist(void);
void freeUriageList(URIAGELIST*l,int purge);
URIAGELIST* add(URIAGELIST* l, URIAGE* u);
解答法として、分割コンパイルによる別ファイルにプログラムを書く方 法と、下記のテストプログラムに関数を追記する方法の二通りがあるがどちら でも良い。 プログラムの解説は、自分で作成した関数について行うこと。 こちらで提供したテストプログラムの説明は基本的には不要である。 但し、自分で作成した関数を説明するのに必要な内容には言及すること。
なお、遅れレポートは教員に直接提出してください。 遅れた方が有利にならない範囲内で採点します。 遅れレポートの最終期限は7月25日18:10(授業開始時)です。
商品の売上の集計表を出力する。
始めに商品情報のデータ型 SHOHIN を下記のように定める。
#define ZEI (1.08)
typedef struct{
char* name;
int tanka;
int sotozei;
} SHOHIN;
name は商品名を表す文字列、tanka は単価、sotozei は 0 なら単価は消費税を含むが、 1 なら外税表示のため実際の販売単価は tanka*ZEI となることを意味す る。
これを表示する void printshohin(SHOHIN p)
を作成せよ。
但し、この関数で表示するための printf に制御文字列は
"%s\t単価%d円(%s)" とし、例えば次のように表示させるとする(改行しない)。
Apple 単価150円(内税)
shohin.h, shohin.c を下記のように定める。配列shohin は商品リストを表 し、単価が 0 の項目を番兵とする。
#define ZEI (1.08)
typedef struct{
char* name;
int tanka;
int sotozei;
} SHOHIN;
extern SHOHIN shohin[];
void printshohin(SHOHIN s);
#include <stdio.h>
#include "shohin.h"
SHOHIN shohin[]={{"Apple",150},{"Orange",100},{"Banana",200},{"Book1",500,1},{"",0}};
これと、下記のテストプログラムを結合して実行し、出力結果を示せ。
#include <stdio.h>
#include "shohin.h"
int main(void){
int i;
for(i=0;shohin[i].tanka!=0; i++){
printf("商品コード %d 品名 ",i);
printshohin(shohin[i]);
printf("\n");
}
return 0;
}
商品コード 0 品名 Apple 単価150円(内税) 商品コード 1 品名 Orange 単価100円(内税) 商品コード 2 品名 Banana 単価200円(内税) 商品コード 3 品名 Book1 単価500円(外税)
売上を示す構造体を次に示す。
typedef struct {
int code;
int num;
}URIAGE;
code は配列 shohin の添字、num は売上個数を示す。
この時、この構造体のポインターを受け取り、商品名、単価、内税/外税の
区別、個数、税込み購入価格を表示し、税込み購入価格(int型)を返す
int printUriage(URIAGE* q)
関数を作りなさい。
そして、下記のプログラムと結合し、実行結果を報告せよ。
#include <stdio.h>
#include "shohin.h"
#include "uriage.h"
int main(void){
URIAGE u1={0,3};
URIAGE u2={3,4};
int shokei;
shokei = printUriage(&u1);
printf("\t%d\n",shokei);
shokei = printUriage(&u2);
printf("\t%d\n",shokei);
return 0;
}
Apple 単価150円(内税) 3 個 450 円 450 Book1 単価500円(外税) 4 個 2160 円 2160
番兵としてcode=-1を持つURIAGE の配列を渡すと、各売上を表示し、最後に
小計を出力し、さらにその小計を返す
int printUriageArray(URIAGE u[])
を作りなさい。
そして、下記のプログラムと結合し、実行結果を報告せよ。
#include <stdio.h>
#include "shohin.h"
#include "uriage.h"
int main(void){
URIAGE u[]={{0,3},{1,2},{2,1},{3,4},{-1}};
int shokei;
shokei = printUriageArray(u);
printf("\t%d\n",shokei);
return 0;
}
Apple 単価150円(内税) 3 個 450 円 Orange 単価100円(内税) 2 個 200 円 Banana 単価200円(内税) 1 個 200 円 Book1 単価500円(外税) 4 個 2160 円 小計: 3010 円 3010
番兵として NULL を持つ、売上の配列の番地の配列を受け取り、
各売上配列ごとに売上の表示と小計を出力し、--------------------で区切っ
て表示し、
最後に合計金額を表示し、合計金額を返す
int printUriageTrans(URIAGE** u)
を作りなさい。
そして、下記のプログラムと結合し、実行結果を報告せよ。
#include <stdio.h>
#include "shohin.h"
#include "uriage.h"
int main(void){
URIAGE uriage0[]={{2,1},{1,6},{-1}};
URIAGE uriage1[]={{0,3},{1,2},{2,1},{-1}};
URIAGE uriage2[]={{3,1},{-1}};
URIAGE uriage3[]={{1,3},{0,1},{-1}};
URIAGE uriage4[]={{1,3},{0,1},{3,2},{-1}};
URIAGE* uriage[]={uriage0, uriage1, uriage2, uriage3, uriage4, NULL};
int total;
total=printUriageTrans(uriage);
printf("%d\n",total);
return 0;
}
Banana 単価200円(内税) 1 個 200 円 Orange 単価100円(内税) 6 個 600 円 小計: 800 円 ------------------ Apple 単価150円(内税) 3 個 450 円 Orange 単価100円(内税) 2 個 200 円 Banana 単価200円(内税) 1 個 200 円 小計: 850 円 ------------------ Book1 単価500円(外税) 1 個 540 円 小計: 540 円 ------------------ Orange 単価100円(内税) 3 個 300 円 Apple 単価150円(内税) 1 個 150 円 小計: 450 円 ------------------ Orange 単価100円(内税) 3 個 300 円 Apple 単価150円(内税) 1 個 150 円 Book1 単価500円(外税) 2 個 1080 円 小計: 1530 円 ------------------ 合計: 4170 円 4170
以下、ヘッダファイルと補助プログラムを示す。
#define ZEI (1.08)
typedef struct{
char* name;
int tanka;
int sotozei;
} SHOHIN;
extern SHOHIN shohin[];
void printshohin(SHOHIN s);
#include <stdio.h>
#include "shohin.h"
SHOHIN shohin[]={{"Apple",150},{"Orange",100},{"Banana",200},
{"Book1",500,1},{"",0}};
typedef struct {
int code;
int num;
}URIAGE;
int printUriage(URIAGE* q);
int printUriageArray(URIAGE q[]);
int printUriageTrans(URIAGE **p);