線形リスト

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

線形リスト

#1

投稿記事 by ruohack » 3週間前

コード:

#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
記事: 6436
登録日時: 10年前
住所: 千葉県
連絡を取る:

Re: 線形リスト

#2

投稿記事 by みけCAT » 3週間前

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

ruohack
記事: 4
登録日時: 3週間前

Re: 線形リスト

#3

投稿記事 by ruohack » 3週間前

ご回答ありがとうございます。
プログラム歴浅くてデリファレンスの意味が分からないのですが、参照先を除くという意味であっていますでしょうか?
そしてご指摘いただいた通り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
登録日時: 3週間前

Re: 線形リスト

#4

投稿記事 by ruohack » 3週間前

訂正
除く→覗く

ruohack
記事: 4
登録日時: 3週間前

Re: 線形リスト

#5

投稿記事 by ruohack » 3週間前

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

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

Re: 線形リスト

#6

投稿記事 by みけCAT » 3週間前

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

返信

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