線形リスト

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ruohack
記事: 4
登録日時: 2年前

線形リスト

#1

投稿記事 by ruohack » 2年前

コード:

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

struct dt{
	int student;
	char course[20];
	int score;
	struct dt *next;
};

struct dt *head;
void load_file()
{
	FILE *file= fopen("data.txt","r");
	int s;
	char c[20];
	int sc;
	
	head=NULL;
	
	while(fscanf(file,"%d %s %d", &s,c,&sc)!=EOF){
		struct dt *n;
		printf("%d %s %d\n",s,c,sc);
		n=(struct dt *)malloc(sizeof(struct dt));
		n->student=s;
		strcpy(n->course,c);
		n->score=sc;
		
		n->next=head;
		head=n;
	}
}

void remove_one(struct dt *d){
	struct dt *p,*prev;
	if(head==d){
		head=d->next;
	}
	
	prev=head;
	for(p=head->next;p!=NULL;prev=p,p=p->next){
		if(p==d){
			prev->next=d->next;
			return;
		}
	}
}

void sort_list(){
	struct dt *p,*t;
	struct dt *min=head;
	
	if(head==NULL 
	){
		return;
	}
	
	for(p=head->next;p!=NULL;p=p->next){
		if(min->student > p->student){
			min=p;
		}
	}
	remove_one(min);
	sort_list();
	min->next=head;
	head=min;
	printf("%d\n",p->student);
	return;
	
}

void print_average(){
	int count=0,total=0;
	struct dt *p;
	
	for(p=head;p!=NULL;p=p->next){
		if(p->student == p->next->student){
			count++;
			total+=p->score;
		}else{
			count++;
			total+=p->score;
			printf("%d %d %d\n",p->student,count,total/count);
			count=total=0;
		}
	}
}

void print(){
	struct dt *p;
	
	for(p=head;p!=NULL;p=p->next){
		printf("%d %s %d\n",p->student,p->course,p->score);
		
	}
}
int main(void){
	int i;
	struct dt *p;
	
	int s;
	while(1){
		printf("select 1:load 2:remove 3:print 0ther:finish\n");
		scanf("%d",&s);
		
		switch(s){
			case 1:load_file();break;
			case 2:for(i=0,p=head;i<3;p=p->next,i++){
						p=p->next;
					}
					remove_one(p);		
					break;
			case 3:print();break;
			case 4:sort_list();print();break;
			default:exit(1);
		}
	}
	
	return 0;
}
線形リストの問題なのですが。sort_list()がうまく動作しません。おそらく
min->next=head;
head=min;
がうまく動作していないのですが。この二つを変更させてうまく動作させる場合どのような解決策があるか教えてください。お願いします。

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

Re: 線形リスト

#2

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

NULLをデリファレンスしてはいけません。
・remove_one関数において、headがNULLであってもfor文の初期化 p=head->next を実行してしまう
・sort_list関数において、pがNULLであっても printf("%d\n",p->student); を実行してしまう
という問題があるので、これらを実行しないようにheadやpがNULLかどうかのチェックを追加するといいかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ruohack
記事: 4
登録日時: 2年前

Re: 線形リスト

#3

投稿記事 by ruohack » 2年前

ご回答ありがとうございます。
プログラム歴浅くてデリファレンスの意味が分からないのですが、参照先を除くという意味であっていますでしょうか?
そしてご指摘いただいた通りheadがNULL出ないか監視するためにremove_oneに

コード:

void remove_one(struct dt *d){
	struct dt *p,*prev;
	if(head==d){
		head=d->next;
	}
	if(head==NULL){
		return;
	}
	prev=head;
	for(p=head->next;p!=NULL;prev=p,p=p->next){
		if(p==d){
			prev->next=d->next;
			return;
		}
	}
}
条件分岐をつけ、sort_list()のprintf表示を削除したら無事行くことができました。これはremove_oneにおけるheadがNULLの時も実行されていることなんでしょうか。自分が考えたときはsort_listの再帰の脱出条件としてhead==NULLの時に脱出すると制約をつけているため、headがNULLの状態の時remove_one関数が実行されないものだと思っていたのですがこれはいつ呼ばれているのかわかりますでしょうか?

ruohack
記事: 4
登録日時: 2年前

Re: 線形リスト

#4

投稿記事 by ruohack » 2年前

訂正
除く→覗く

ruohack
記事: 4
登録日時: 2年前

Re: 線形リスト

#5

投稿記事 by ruohack » 2年前

解決しました。
ありがとうございました。

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

Re: 線形リスト

#6

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

ruohack さんが書きました:
2年前
自分が考えたときはsort_listの再帰の脱出条件としてhead==NULLの時に脱出すると制約をつけているため、headがNULLの状態の時remove_one関数が実行されないものだと思っていたのですがこれはいつ呼ばれているのかわかりますでしょうか?
remove_one関数内で head=d->next; としているので、ここでheadがNULLになる可能性がありそうですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

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