[1600] 一応できたのでソースをさらします。
投稿者:バッファロー
2010/07/01 09:57:49
助言をいただき、それをむねに一応完成したソースを書き込みます。
変なところがあれば、ぜひ助言をお願いします。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int (*Compare)(int,int) ;
typedef struct DATA DATA;
struct DATA
{
DATA * next;
char * name;
int math;
int language;
int sum;
};
#define MAX 256
int AscendinOrder(int a,int b);
int DescendingOrder(int a,int b);
DATA* merge_sort(DATA* top,Compare);
DATA* merge_list(DATA* x, DATA* y,Compare);
/****************************************
機能:線形リストのデータをすべて解放する。
引数:top 線形リストのトップデータ
comp 使用した比較関数
出力:無し
****************************************/
void AllFree(DATA *top,Compare *comp)
{
DATA *temp,*freeData;
if(*comp == AscendinOrder || *comp == NULL){
temp = top;
while(temp->next){
freeData = temp;
temp =temp->next;
free(freeData->name);
free(freeData);
}
}else if(*comp == DescendingOrder){
temp = top->next;
while(temp){
freeData = temp;
temp =temp->next;
free(freeData->name);
free(freeData);
}
}
}
/****************************************
機能:線形リストのノードを作成。
引数:無し
出力:DATA型の新しいノードのポインタ
****************************************/
DATA* newnode(){
DATA *p;
p=malloc(sizeof(DATA));
p->next=NULL;
return p;
}
/****************************************
機能:合計点を求める
引数:data 合計点を求めるDATA型のポインタ
出力:mathとlanguageの合計点
****************************************/
int SUM(DATA *data)
{
return data->math+data->language;
}
/****************************************
機能:線形リストの末尾にノードを追加。
引数:p リストの先頭
c リストnameにはいる名前
lang リストのlanguageに入る数値
math リストのmathに入る数値
出力:無し
****************************************/
void add(DATA *p,char *c,int lang,int math){
while(p->next != NULL){
p= p->next;
}
p->math = math;
p->language = lang;
p->sum = SUM(p);
p->name=malloc(strlen(c)+1);
strcpy(p->name,c);
p->next=newnode();
}
/****************************************
機能:線形リストの内容を表示。
引数:data リストの先頭
comp 使った比較関数
出力:無し
****************************************/
void ShowData(DATA *data,Compare *comp)
{
DATA *temp;
if(*comp == AscendinOrder || *comp == NULL){
for(temp = data; temp->next;temp= temp->next){
printf("name : %s, language : %d, math : %d, sum :%d \n",temp->name,temp->language,temp->math,temp->sum);
}
}else if(*comp == DescendingOrder){
for(temp = data->next; temp;temp= temp->next){
printf("name : %s, language : %d, math : %d, sum :%d \n",temp->name,temp->language,temp->math,temp->sum);
}
}
}
/****************************************
機能:表示方法の設定。
引数:無し
出力:表示方法の値。
****************************************/
int ShowCase()
{
char c;
printf("昇順で表示 :1 ,降順で表示:2\n");
c = getchar();
switch(c){
case '1':
return 1;
case '2':
return 2;
default:
return 0;
}
}
int main()
{
char data[MAX] = {'\0'};
char ctemp[100] = {'\0'};
int m,l,type;
FILE *fp = fopen("data.txt","r");
char *n;
DATA *top = malloc(sizeof(DATA));
Compare comp = NULL;
type=ShowCase();
if(type == 1){
comp = AscendinOrder;
}else if(type == 2){
comp = DescendingOrder;
}else{
comp = NULL;
}
top->next = NULL;
while(fgets(data,MAX,fp)){
if(n = strchr(data,'\n'))
*n = '\0';
sscanf(data,"%s%d%d",ctemp,&m,&l);
add(top,ctemp,l,m);
}
if(comp != NULL){
top =merge_sort(top,comp);
}
ShowData(top,&comp);
AllFree(top,&comp);
return 0;
}
/****************************************
機能:線形リストのマージソートする。
引数:top リストの先頭
comp 使う比較関数
出力:ソート済みのリストのポインタ
****************************************/
DATA* merge_sort(DATA* top,Compare comp)
{
DATA *a, *b, *y;
/* リストに含まれる要素数が0または1個のときは、ソートの必要がない */
if( top == NULL || top->next == NULL ){
return top;
}
a = top; /* aは先頭の要素を指す */
b = top->next;
if( b != NULL ){
b = b->next;
} /* bは先頭から3番目の要素を指す */
/* 線形リストを中心くらいから半分に分けるため、中心位置がどこにあるのか探る */
while( b != NULL )
{
a = a->next; /* aは常に1つだけ進む */
b = b->next;
if( b != NULL ){
b = b->next;
} /* bは基本的に2つ進む */
}
/* 線形リストを2つに分割する */
y = a->next; /* yは分割後の2つのリストのうちの、後半部分の方の先頭を指す */
a->next = NULL;
/* 分割した2つのリスト */
return merge_list( merge_sort( top ,comp), merge_sort( y ,comp) ,comp);
}
/************************************************************************
機能:2つの線形リストをマージする。
引数:x マージする2つの線形リストのうちの片方の先頭要素へのポインタ
y マージする2つの線形リストのうちの片方の先頭要素へのポインタ
comp 比較関数
出力: マージされた線形リストの先頭要素へのポインタ
*************************************************************************/
DATA* merge_list(DATA* x, DATA* y,Compare comp)
{
DATA z, *p;
p = &z; /* xとyをマージしてzを作り上げる */
/* 分割されている2つのリストのいずれか一方が空になるまで繰り返す */
while( x != NULL && y != NULL )
{
/* 2つのリストの先頭要素同士を比較する */
if( comp(x->sum , y->sum) )
{
/* リストxの方の先頭要素を、マージ後のリストに連結する */
p->next = x;
p = x;
x = x->next;
}
else
{
/* リストyの方の先頭要素を、マージ後のリストに連結する */
p->next = y;
p = y;
y = y->next;
}
}
/* 先に片方のリストが空になるので、残された方のリストの要素を、マージ後リストに連結する */
if( x == NULL )
{
p->next = y;
}
else
{
p->next = x;
}
return z.next;
}
int AscendinOrder(int a,int b)
{
return a>=b? 1:0;
}
int DescendingOrder(int a,int b)
{
return a <= b?1:0;
}
data.txtの中身
jon 90 30
sum 40 50
jack 20 100
tom 35 70