線形リストを用いた商品注文プログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
海の藻屑

線形リストを用いた商品注文プログラム

#1

投稿記事 by 海の藻屑 » 7年前

課題を今日中に提出しなければならないのですが、セグメンテーション違反が出て大変困っています。
仕様は次の通りです。

・ユーザーはメニューにある商品の中から商品を選んで注文する。
・ユーザーがENDと入力するまで注文を聞く。
・その際何個注文するかもあわせて入力してもらう
・メニューにない商品の注文はできない
・メニューは予め用意されたものがあるのでそのプログラムを読み込んで使用する
・以前注文したものと同じ物を注文する際は、以前注文した物の個数に今回注文した数を足す
・注文が終わったら注文したものの商品名、個数、合計金額を表示する
・線形リストを用いて実現する


以下のプログラムが予め用意されたメニューのプログラムでファイル名はyakitori.hです。

コード:

typedef struct
{
  char *item;
  int unit_price;
  int number_of_pieces;
} PRICE;

PRICE menu[] = {
  {"Tsukune",480,0},
  {"Kohchin-bonziri",200,0},
  {"Negima",200,0},
  {"Tebasaki",200,0},
  {"Sinzo",180,0},
  {"Sunagimo",180,0},
  {"Liver",230,0},
  {"Hatsumoto",200,0},
  {"Nankotsu",200 ,0},
  {"Tori-kawa",180 ,0},
  {"Seseri",200,0},
  {"Yamaimo-negima",250,0},
  {"Sasami",180,0},
  {"Ume-sasami",230,0},
  {"Sasami-isobemaki",230,0},
  {"Sasami-sabiyaki",230,0},
  {"Lamb-rolled",480,0},
  {"Asparagus-rolled",200 ,0},
  {"Pork-negima",230,0},
  {"Quail-eggs",200 ,0},
  {"Mino",230,0},
  {"Green-papper",180,0},
  {"Mashroom",230,0},
  {"Kumidashi-tofu",250,0},
  {"Hiya-yakko",300,0},
  {"Yu-tofu",580,0},
  {"Toriaezu",780,0},
  {"Special-tomato-salad",780,0},
  {"Japanese-cucumber-pickles",300,0},
  {"Kimchi",380,0},
  {"Chicken-soup",300,0},
  {"Yaki-norimaki",150,0},
  {"Yaki-norimaki-chazuke",400,0},
  {"Seasonal-chazuke",480,0},
  {"Yaki-mochi",150,0},
  {"Homemade-pudding",300,0},
  {"Seasonal-dessart",350,0}
};

以下が自分が作ったプログラムです。

コード:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"yakitori.h"

typedef struct LIST
{
	char *item_name;//商品名
	int one_price;//商品の単価
	int number_item;//何個注文されたか
	int number_prices;//合計金額(商品の単価×何個注文されたか)
	struct LIST *next;
		
}list;

list* new_node(char *name,int number,int number_item)//新規リスト生成
{
	
	list *new=NULL;
	new=(list*)malloc(sizeof(list));
	
	if(new==NULL)
	{
	  printf("割り当て失敗\n");//割り当て失敗
	  return(NULL);
	}
	
	
	  new->item_name=name;
	  new->one_price=menu[number].unit_price;//number=メニューの何番目か
	  new->number_item=number_item;//number_item=何個注文するか
	  new->next=NULL;
	 
	  return(new);//fprintf( stderr, "Check\n" )で確認したところ問題ありそう?
	
		
		
		fprintf( stderr, "Check\n" );
}

int node_add(list *new_list,char *name,int number,int number_item)//最後尾にリスト追加
{
	list *next=NULL;
	list *prev=new_list;
	
	next=new_node(name,number,number_item);
	
	while(prev->next!=NULL)
	{
	    prev=prev->next;
	}
	
	prev->next=next;
	
	return (0);
}

void change_order(list **new_list,int number,int number_item)//注文された個数を変更する
{
	int i;
	
	for(i=0;i<number;i++)
	{
	    new_list=&((*new_list)->next);
	}
	
	(*new_list)->number_item+=number_item;
}

void culclate_amount(list *new_list)
{
    int i;
	
	for(i=0;i<37;i++)
	{
	    (new_list)->number_prices=((new_list)->number_item)*((new_list)->one_price);
	     new_list=((new_list)->next);
	}
	
	
  
}

void list_print(list *new_list)
{
    while(new_list!=NULL)
    {
      printf("%s\n",new_list->item_name);
      printf("%d個\n",new_list->number_item);
      printf("%d円\n",new_list->number_prices);
      putchar('\n');
      new_list=new_list->next;
    }
  
  
}

int main(void)
{
	char *name;//品物
	int i,d;
	int number_item;
	int count_order=0;
	int judge;
	int judge_order[37]={0};
	list *new_list;
	
	while(1)
	{
		int judge;
		do 
		{
		    int count=0;
		    printf("ご注文は?\n");
		    scanf("%s",name);
		
		    d=strcmp(name,"END");
		    if(d==0) 
		      break;
		
		    for(i=0;i<37;i++)
		    {
			if(strcmp(name,menu[i].item)!=0)
			  count++;			
		    }
		    
		    if(count==37)
			printf("申し訳ありませんがその商品はありません。\n");
		    
		    judge=count;
		    
		}while(judge==37);
		
		count_order++;
		if(d==0) 
		  break;
		
		printf("何個ですか?\n");
		scanf("%d",&number_item);
				
		
		for(i=0;i<37;i++)
		{
			if(!strcmp(name,menu[i].item))
			{
			      if(count_order==1)//1回目の注文ならばリスト新規作成
			      {
  
				  new_list=new_node(name,i,number_item);//new_list=一番先頭のノード
  
			      }else{//2回目以降の注文ならばリストを末尾に追加

				      if(judge_order[i]==0)//前に同じ品物の注文がされていない(その品物において初めての注文)ならば
				      {
					judge_order[i]=1;/*次に同じ品物が注文された時に以前注文されたことが分かるようにする
							(1=注文済み,0=まだ注文されたことがない*/
					node_add(new_list,name,i,number_item);
				      }else{//judge_order[i]=1ならば(注文されたことがあるならば)すでにあるリストに個数を追加
					change_order(&new_list,i,number_item);
					
				      }
  
  
				   }
			}
		}
	}
	
	culclate_amount(new_list);//合計金額の計算
	
	list_print(new_list);
	
	free(new_list);
	return 0;
}

実行結果は以下のようになりました。


ご注文は?
apple
申し訳ありませんがその商品はありません。
ご注文は?
orange
申し訳ありませんがその商品はありません。
ご注文は?
Sasami
何個ですか?
2
ご注文は?
Tsukune
何個ですか?
3
ご注文は?
Sasami
何個ですか?
4
ご注文は?
Sasami
何個ですか?
2
Segmentation fault (コアダンプ)


fprintf( stderr, "Check\n" )でプログラムを辿って確認していったのですが、どうやらnew_node関数のretunrn (new)に問題がありそう(ここだけを確認したので他にも問題はありそうです)ということが分かったのですが何がダメなのかは全く分かりません・・。

どなたかご教授よろしくお願いいたします。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 線形リストを用いた商品注文プログラム

#2

投稿記事 by みけCAT » 7年前

海の藻屑 さんが書きました:fprintf( stderr, "Check\n" )でプログラムを辿って確認していったのですが、どうやらnew_node関数のretunrn (new)に問題がありそう(ここだけを確認したので他にも問題はありそうです)ということが分かったのですが何がダメなのかは全く分かりません・・。
return(new);で落ちるということは、範囲外アクセスによる戻り番地の破壊があればありえますが、そうでなければ可能性は低いでしょう。
デバッガが利用可能であればデバッガを使ってどこで落ちているかを調べ、
そうでなけれえばfprintfの直後にfflush(stderr);を追加して出力を指示したものは確実に出力されるようにし、調べ直す方がいいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 線形リストを用いた商品注文プログラム

#3

投稿記事 by みけCAT » 7年前

115行目のscanf("%s",name);で未初期化の自動変数nameの値(不定)が使用されているので、未定義動作を起こします。
事前に十分な領域を確保し、その領域を指すポインタをnameに代入するといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

box
記事: 2002
登録日時: 13年前

Re: 線形リストを用いた商品注文プログラム

#4

投稿記事 by box » 7年前

海の藻屑 さんが書きました:課題を今日中に提出しなければならない
ということであれば、採点者が読みやすいよう、せめてインデントくらいはそろえましょう。
海の藻屑 さんが書きました: 以下が自分が作ったプログラムです。

コード:

	int one_price;//商品の単価
	int number_item;//何個注文されたか
	int number_prices;//合計金額(商品の単価×何個注文されたか)
合計金額は単価と個数から計算できるはずなので、独立したメンバーとして持つ必要があるかどうかは疑問があります。
海の藻屑 さんが書きました:

コード:

	  return(new);//fprintf( stderr, "Check\n" )で確認したところ問題ありそう?
	
		
		
		fprintf( stderr, "Check\n" );
今のコードは本当にこうなっているのですか?だとすると、return文の後ろに何を書いても、そこは実行されません。
海の藻屑 さんが書きました:

コード:

	for(i=0;i<37;i++)
頻出している37という数値(メニューの数ですよね?)は、コンピューターに数えさせましょう。
海の藻屑 さんが書きました:

コード:

	int judge;
		int judge;
どっちのjudgeを使いたいですか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

海の藻屑

Re: 線形リストを用いた商品注文プログラム

#5

投稿記事 by 海の藻屑 » 7年前

お二人方回答大変ありがとうございます。

教えていただいたことを参考に色々と試行錯誤してみました。
時間が無くお二人方からご指摘頂いた部分を十分に改良していませんが、
以下に改良したプログラムを示します。

コード:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"yakitori.h"
#define SUCCESS 1
#define FAILURE 0

typedef struct LIST
{
	char *item_name;//商品名
	int one_price;//商品の単価
	int number_item;//何個注文されたか
	int number_prices;//合計金額(商品の単価×何個注文されたか)
	struct LIST *next;
		
}list;

list *nodeNew(char *name,int number,int number_item,list *nxt)
{
    list *ndPtr;

    ndPtr = malloc(sizeof (list));
    if (ndPtr == NULL) 
    {
        return NULL;      /* 割り当て失敗 */
    } else {
        ndPtr -> item_name = name;
        ndPtr -> one_price = menu[number].unit_price;
	ndPtr -> number_item=number_item;
	ndPtr -> next=nxt;
        return ndPtr;
    }
}

int nodeAppend(list **ndPtrPtr,char *name,int number,int number_item)//最後尾にリスト追加
{
	  list *ndPtr;

	  ndPtr = nodeNew(name,number,number_item, NULL);
	  if (ndPtr == NULL) return FAILURE;
	  while (*ndPtrPtr != NULL) 
	  {
	      ndPtrPtr = &((*ndPtrPtr)->next);
	  }
	  *ndPtrPtr = ndPtr;
	  return SUCCESS;
  
}

void change_order(list *new_list,int number,int number_item)//注文された個数を変更する
{
	int i;
	
	for(i=-1;new_list!=NULL;new_list->next)
	{
	    if(i==number)
	      break;
	}
	
	(new_list->number_item)+=(new_list->number_item);
	printf("%d",new_list->number_item);
  
}

void culclate_amount(list *new_list)
{
    int i;
	
	while(new_list!=NULL){
	    ((new_list)->number_prices)=((new_list)->number_item)*((new_list)->one_price);
	     new_list=((new_list)->next);
	}
	
	
  
}

void list_print(list *new_list)
{
    while(new_list!=NULL)
    {
      printf("%s\n",new_list->item_name);
      printf("%d個\n",new_list->number_item);
      printf("%d円\n",new_list->number_prices);
      putchar('\n');
      new_list=new_list->next;
    }
  
  
}

int main(void)
{
	char name[50]={0};//品物
	int i,d;
	int number_item;

	int judge_order[37]={0};
	list *new_list=NULL;
	
	while(1)
	{
		int judge;
		do 
		{
		    int count=0;
		    printf("ご注文は?\n");
		    scanf("%s",name);
		
		    d=strcmp(name,"END");
		    if(d==0) 
		      break;
		
		    for(i=0;i<37;i++)
		    {
			if(strcmp(name,menu[i].item)!=0)
			  count++;			
		    }
		    
		    if(count==37)
			printf("申し訳ありませんがその商品はありません。\n");
		    
		    judge=count;
		    
		}while(judge==37);
		
		if(d==0) 
		  break;
		
		
		
		printf("何個ですか?\n");
		scanf("%d",&number_item);
				
		
		for(i=0;i<37;i++)
		{
			if(strcmp(name,menu[i].item)==0)
			{
			      
			
  
			      

				      if(judge_order[i]==0)//前に同じ品物の注文がされていない(その品物において初めての注文)ならば
				      {
					judge_order[i]=1;/*次に同じ品物が注文された時に以前注文されたことが分かるようにする
							(1=注文済み,0=まだ注文されたことがない*/
					nodeAppend(&new_list,name,i,number_item);//new_list=一番先頭のノード
				      }else{//judge_order[i]=1ならば(注文されたことがあるならば)すでにあるリストに個数を追加
					change_order(new_list,i,number_item);
					
				      }
  
  
				   
			}
		}
	}
	
	culclate_amount(new_list);//合計金額の計算
	
	list_print(new_list);
	
	free(new_list);
	return 0;
}

実行結果その1は以下のようになりました。

-----------------------------------------------------------------------
ご注文は?
orange
申し訳ありませんがその商品はありません。
ご注文は?
Sasami
何個ですか?
2
ご注文は?
Sasami
何個ですか?
4

----------------------------------------------------------------------
4以下は何の文字を入力しても改行していくだけです。
同じ物を2つ以上入力するとこのように上手く実行できません。

実行結果その2を以下に示します。

---------------------------------------------------------------------
ご注文は?
Sasami
何個ですか?
4
ご注文は?
Tsukune
何個ですか?
3
ご注文は?
END
END
4個
720円

END
3個
1440円

------------------------------------------------------------
同じものを2つ以上入力しなければ一応結果まで出力します。
しかし個数と金額は合っているのですが品物の名前がすべてENDになっていしまいます。


以上、色々と自分でも考えましたがこれ以上どのように改善して良いのかさっぱり分かりません。
何度も質問して大変恐縮ですがどなたかご教授ください。
よろしくお願いします。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 線形リストを用いた商品注文プログラム

#6

投稿記事 by みけCAT » 7年前

海の藻屑 さんが書きました:同じ物を2つ以上入力するとこのように上手く実行できません。
change_order関数内のループで、iもnew_listも更新されないので無限ループになっています。
何らかの処理を加えて有限時間でループを抜けるようにするといいでしょう。
海の藻屑 さんが書きました:個数と金額は合っているのですが品物の名前がすべてENDになっていしまいます。
同じバッファを使いまわして同じアドレスを全部のノードのメンバに代入しているので、当然最後にそのバッファに書き込んだ名前が用いられます。
それぞれの項目用に新しいバッファを割り当てて使うようにするといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 線形リストを用いた商品注文プログラム

#7

投稿記事 by みけCAT » 7年前

このchange_order関数には、他にも
  • 副作用の無い式が不自然な場所にある
  • 使われていないパラメータがある
という不自然な点があります。
まずはコンパイラの警告を有効にするといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 線形リストを用いた商品注文プログラム

#8

投稿記事 by みけCAT » 7年前

オフトピック
最後に1ノードだけfreeしているのは、不自然な気がします。
お行儀よく確保した全部のノードをfreeするか、いっそ全くfreeせずにOSに解放を任せてしまう方がいいのではないでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

海の藻屑

Re: 線形リストを用いた商品注文プログラム

#9

投稿記事 by 海の藻屑 » 7年前

みけCATさん、回答大変ありがとうございます。
とりあえず出来たところまでで提出しました。
ご指導ありがとうございました。

しかしまだセグメンテーション違反が出るところがあり、やはり自分で考えても解決策が思いつかないところがあります。
提出はもうしてしまいましたが今後の勉強に活かしたいのでよろしければ教えていただけないでしょうか。
重ね重ね大変申し訳ありません。考えてもどうしても分かりません・・。

ご指摘頂いたところを大体修正したプログラムを以下に示します。

コード:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"yakitori.h"
#define SUCCESS 1
#define FAILURE 0

typedef struct LIST
{
	char *item_name;//商品名
	int one_price;//商品の単価
	int number_item;//何個注文されたか
	int number_prices;//合計金額(商品の単価×何個注文されたか)
	struct LIST *next;
		
}list;

list *nodeNew(char *name,int number,int number_item,list *nxt)
{
    list *ndPtr;

    ndPtr = malloc(sizeof (list));
    if (ndPtr == NULL) 
    {
        return NULL;      /* 割り当て失敗 */
    } else {
        ndPtr -> item_name = name;
        ndPtr -> one_price = menu[number].unit_price;
	ndPtr -> number_item=number_item;
	ndPtr -> next=nxt;
	
        return ndPtr;
    }
}

int nodeAppend(list **ndPtrPtr,char *name,int number,int number_item)//最後尾にリスト追加
{
	  list *ndPtr;

	  ndPtr = nodeNew(name,number,number_item, NULL);
	  if (ndPtr == NULL) return FAILURE;
	  while (*ndPtrPtr != NULL) 
	  {
	      ndPtrPtr = &((*ndPtrPtr)->next);
	  }
	  *ndPtrPtr = ndPtr;
	  return SUCCESS;
  
}

void change_order(list *new_list,int number,int number_order)//注文された個数を変更する
{
	int i;
	
	for(i=-1;new_list!=NULL;i++,new_list=new_list->next)
	  if(i==number)break;
	
	
	new_list->number_item+=number_order;
	
  
}

void culclate_amount(list *new_list)
{
        int i;
	
	while(new_list!=NULL){
	    ((new_list)->number_prices)=((new_list)->number_item)*((new_list)->one_price);
	     new_list=((new_list)->next);
	}
	
	
  
}

void list_print(list *new_list)
{
    while(new_list!=NULL)
    {
      printf("%s\n",new_list->item_name);
      printf("%d個\n",new_list->number_item);
      printf("%d円\n",new_list->number_prices);
      putchar('\n');
      new_list=new_list->next;
    }
  
  
}

void Release(list *new_list){

	//次のリストのポインタ
	list *next;
	//削除対象のポインタ
	list *del;

	next=new_list->next;

	//NULLになるまでループ
	while(next){
		//削除対象のポインタを保存	
		del=next;
		//次のリストのポインタを取得しとく
		next=next->next;

		free(del);
	}
}



int main(void)
{
	char name[37][50]={0};//品物
	int i,d,cnt;
	cnt=0;
	int number_item=0;

	int judge_order[37]={0};
	list *new_list=NULL;
	while(1)
	{
		int judge;
		do 
		{
		    int count=0;
		    printf("ご注文は?\n");
		    scanf("%s",name[cnt]);
		
		    d=strcmp(name[cnt],"END");
		   
		    if(d==0) 
		      break;
		
		    for(i=0;i<37;i++)
		    {
			if(strcmp(name[cnt],menu[i].item)!=0)
			  count++;			
		    }
		    
		    if(count==37)
			printf("申し訳ありませんがその商品はありません。\n");
		    
		    judge=count;
		    
		}while(judge==37);
		
		if(d==0) 
		  break;
		
		
		
		printf("何個ですか?\n");
		scanf("%d",&number_item);
				
		
		for(i=0;i<37;i++)
		{
			if(strcmp(name[cnt],menu[i].item)==0)
			{
			      
			
  
			      

				      if(judge_order[i]==0)//前に同じ品物の注文がされていない(その品物において初めての注文)ならば
				      {
					judge_order[i]=1;/*次に同じ品物が注文された時に以前注文されたことが分かるようにする
							(1=注文済み,0=まだ注文されたことがない*/
					nodeAppend(&new_list,name[cnt],i,number_item);//new_list=一番先頭のノード
				      }else{//judge_order[i]=1ならば(注文されたことがあるならば)すでにあるリストに個数を追加
					change_order(new_list,i,number_item);
					
				      }
  
  
				   
			}
		}
		cnt++;
	}
	
	culclate_amount(new_list);//合計金額の計算
	
	list_print(new_list);
	
	Release(new_list);
	return 0;
}
実行結果1は以下のとおりです。
----------------------------------------------------------------------------------
ご注文は?
Sasami
何個ですか?
4
ご注文は?
Tsukune
何個ですか?
1
ご注文は?
END
Sasami
4個
720円

Tsukune
1個
480円

----------------------------------------------------------------------------------
同じ物を2つ以上入力しない場合はお陰様で上手く実行できました。
大変有難う御座いました。

問題は2つ以上入力する場合です。
実行結果2を以下に示します。
------------------------------------------------------------------------------------
ご注文は?
Sasami
何個ですか?
2
ご注文は?
Sasami
何個ですか?
2
Segmentation fault
------------------------------------------------------------------------------------
と、セグメンテーション違反になってしまいました。
この部分がどうしても分かりません。

重ね重ね本当に申し訳ありません。
みけCATさん、またはこの問題解決策が分かる方、教えてください。
よろしくお願いします。

海の藻屑

Re: 線形リストを用いた商品注文プログラム

#10

投稿記事 by 海の藻屑 » 7年前

fprintf( stderr, "Check\n" )で確認していったところ59行目が怪しいようです。
しかしやはり解決策が分かりません・・。

どなたかよろしくお願い致します。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 線形リストを用いた商品注文プログラム

#11

投稿記事 by みけCAT » 7年前

海の藻屑 さんが書きました:問題は2つ以上入力する場合です。
実行結果2を以下に示します。
------------------------------------------------------------------------------------
ご注文は?
Sasami
何個ですか?
2
ご注文は?
Sasami
何個ですか?
2
Segmentation fault
------------------------------------------------------------------------------------
と、セグメンテーション違反になってしまいました。
1個しか注文が無いのに13番目の商品を指定しているので、
change_order関数において条件をみたす前にnew_listがNULLになり、そのままそれを59行目でデリファレンスしているので、
未定義動作を起こし、たまたまSegmentation faultになったのでしょう。

単純にノードの数を数えるのではなく、ノードに記録されている番号と比較してノードを探さないといけません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 線形リストを用いた商品注文プログラム

#12

投稿記事 by かずま » 7年前

修正方法はすでに回答されているので、別解を示します。
参考になりますか?

コード:

#include <stdio.h>      // scanf, printf, puts
#include <stdlib.h>     // malloc, free, exit
#include <string.h>     // strcmp
#include "yakitori.h"

typedef struct LIST {
    char *name;
    int price;
    int number;
    struct LIST *next;
} LIST;

void list_add(LIST **p, char *name, int price, int number)
{
    for ( ; *p != NULL && strcmp((*p)->name, name) != 0; p = &(*p)->next) ;
    if (*p != NULL)                 // name が既に存在すれば
        (*p)->number += number;     //   個数 number を修正
    else {                          // name が存在しなければ
        *p = malloc(sizeof(LIST));  //   末尾に新規追加
        if (*p == NULL) puts("out of memory"), exit(1);
        (*p)->name = name;
        (*p)->price = price;
        (*p)->number = number;
        (*p)->next = NULL;
    }
}

int list_print(LIST *p)
{
    int total = 0;
    for (; p != NULL; p = p->next) {
        int price = p->price * p->number;
        total += price;
        printf("%4d個 %5d円  %s\n", p->number, price, p->name);
    }
    return total;
}

void list_release(LIST *p)
{
    while (p != NULL) {
        LIST *next = p->next;
        free(p);
        p = next;
    }
}

int main(void)
{
    LIST *list = NULL;
    char name[50];
    int number, total, i;
    const int N = sizeof(menu) / sizeof(menu[0]);

    while (1) {
        puts("ご注文は?");
        if (scanf("%49s", name) != 1 || strcmp(name, "END") == 0) break;
        for (i = 0; i < N && strcmp(name, menu[i].item); i++) ;
        if (i == N)
            puts("申し訳ありませんがその商品はありません。");
        else {
            puts("何個ですか?");
            if (scanf("%d", &number) != 1) break;
            list_add(&list, menu[i].item, menu[i].unit_price, number);
        }
    }
    total = list_print(list);
    printf(" 合計 %d円\n", total);
    list_release(list);
    return 0;
}
理解できない場合は、どこがわからないのかを質問してください。

かずま

Re: 線形リストを用いた商品注文プログラム

#13

投稿記事 by かずま » 7年前

Segmentation fault しないための最小限の修正

コード:

       if(i==number)break;

コード:

       if (strcmp(new_list->item_name, menu[number].item) == 0) break;
に変える。

閉鎖

“C言語何でも質問掲示板” へ戻る