とっておきの手土産を教えて

ソート部分がどうしてもできません。
またソートは以下のアルゴリズムで行うものです
与えられたリストをリストA、ソート済みのリストをリストBとする。処理の開始段階では、リストBは空である。
1.リストAの要素の中で、最大値をもつ要素Cを探す。
2.要素CをリストAから削除する。
3.要素CをリストBの先頭に挿入する。
4.リストAが空であれば終了。空でなければ 1. にもどる。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct physical Physical;
struct physical {
char name[41];
int age;
float height;
float weight;
Physical *next;
};

void read_data(char *file,Physical *p,Physical *tail);
int comp1(const Physical *, const Physical *);
int comp2(const Physical *, const Physical *);
int comp3(const Physical *, const Physical *);
int comp4(const Physical *, const Physical *);
void sort(char *arg,Physical *p,Physical *q);
Physical *listsort(Physical *p, int (*compar)(const void *, const void *));

int main(void) {
char s[20],t,u[20];

Physical *p,*tail,*q;
p=malloc(sizeof(Physical));
q=malloc(sizeof(Physical));
tail=malloc(sizeof(Physical));

while(1)
{ printf("CMD>");
fflush(stdout);
fgets(s,20,stdin);
sscanf(s,"%c %s",&t,u);
switch(t){

case 'q':exit(0);

case 'r':read_data(u,p,tail);
break;
case 's':sort(u,p,q);
break;
case 'd':

while(q!=NULL)
{ printf("%s %d %.1f %.1f ",q->name,q->age,q->height,q->weight );
q=q->next;}
break;

}
}
free(p);
return 0;
}

void read_data(char *file,Physical *p,Physical *tail){
FILE *fp;

char string[100];
Physical header;
tail=&header;
header.next = NULL;
p->next = NULL;
tail->next = p;
tail = p;

if ((fp = fopen(file, "r")) == NULL)
{ exit(1); }

while(fgets(string,sizeof(string),fp)!= NULL)
{ sscanf(string,"%s %d %f %f",p->name,&p->age,&p->height,&p->weight);
Physical *tail2;
tail2=malloc(sizeof(Physical));
tail2->next=NULL;
p->next=tail2;
p=tail2;

}
fclose(fp);
}

void sort(char *arg,Physical *p,Physical *q){

if(strcmp(arg,"name") == 0)
q=listsort(p,(int(*)(const void*, const void*))comp1);
if(strcmp(arg,"age") == 0)
q=listsort(p,(int(*)(const void*, const void*))comp2);
if(strcmp(arg,"height") == 0)
q=listsort(p,(int(*)(const void*, const void*))comp3);
if(strcmp(arg,"weight") == 0)
q=listsort(p,(int(*)(const void*, const void*))comp4);

}
Physical *listsort(Physical *p,int (*compar)(const void *, const void *)){

Physical *q, *max,*s,*head;
s=malloc(sizeof(Physical));
head=malloc(sizeof(Physical));
head=NULL;

while(p->next){max = p, q = p->next;
while( q->next ) {
if( compar(q->next,max->next) )
max = q;
q = q->next;}
s=max->next;
max->next=max->next->next;
if(head==NULL)
{head=s;}
s->next=s;
}



return head;
}
int comp1(const Physical *a, const Physical *b){
return (strncmp(a->name,b->name,sizeof(Physical)));
}

int comp2(const Physical *a, const Physical *b){


if(a->age > b->age) return 1;
else return 0;

}

int comp3(const Physical *a, const Physical *b){

if(a->height > b->height) return 1;
else return 0;
}
int comp4(const Physical *a, const Physical *b){

if(a->weight > b->weight) return 1;
else return 0;
}

A 回答 (3件)

>またソートは以下のアルゴリズムで行うものです


>与えられたリストをリストA、ソート済みのリストをリストBとする。処理の開始段階では、リストBは空である。
>1.リストAの要素の中で、最大値をもつ要素Cを探す。
>2.要素CをリストAから削除する。
>3.要素CをリストBの先頭に挿入する。
>4.リストAが空であれば終了。空でなければ 1. にもどる。

 リストA、リストBとありますが、リストAだけの方が簡単だと思います。
 「やはりリストBも用いて、手順どおりに」でしたら、以降無視して下さい。
++++++++++++++++++++++++++++++++
☆リストAだけのもので、ソート機能を確認することを主目的に、簡便化したものを投稿します。

 ・この手の処理では、構造体(頭)はグローバルが易しいかと。
 ・リスト「入れ換え」の注意点として、アドレスは入れ換えない(◆)ことです(入れ物はそのままで、中身のみ入り換え)。

  なお、comp1() は、思うように機能しませんでした・・残念。

用いたデータ( test.txt )

abc 18 170.2 68.3
xxx 19 173.4 65.1
nnn 55 170.1 80.4
yyy 30 172.3 66.2
++++++++++++++++++++++++++++++++
#1 さんへ
ひょっとして

#include <stdio.h>
void foo(int *x)
{
*x = 4;
}

int main()
{
int x = 3;
foo(&x);
printf("%d\n", x);
return 0;
}
というプログラムで、「4」が出力されると質問者様は、確信しているのでは?

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

typedef struct _cell{
 char name[ 32 ]; // 奇数キライ
 int age;
 float height;
 float weight;
 struct _cell *next;
}PHYSICAL;

PHYSICAL sgHead;

int comp1( const PHYSICAL *a, const PHYSICAL *b ){
return ( strncmp( a->name, b->name, sizeof(PHYSICAL) ) );
}
int comp2( const PHYSICAL *a, const PHYSICAL *b ){
if( a->age > b->age ) return 1;
return 0;
}
int comp3( const PHYSICAL *a, const PHYSICAL *b ){
if( a->height > b->height ) return 1;
return 0;
}
int comp4( const PHYSICAL *a, const PHYSICAL *b ){
if( a->weight > b->weight ) return 1;
return 0;
}
void read_data( char *file )
{
 FILE *fp;
 char string[ 64 ];
 PHYSICAL *p, *q, *new_p;

 if( ( fp = fopen( file, "r" ) ) == NULL ) exit( 1 );

 while( fgets( string, sizeof( string ), fp ) != NULL ){

  p = sgHead.next;
  q = &sgHead;

  while( NULL != p ){

   q = p;
   p = p->next;
  }
  new_p = (PHYSICAL *)malloc( sizeof(PHYSICAL) ); // 1人分のメモリ確保

  sscanf( string, "%s %d %f %f", new_p->name, &new_p->age, &new_p->height, &new_p->weight );

  new_p->next = NULL;

  q->next = new_p;
 }
 fclose( fp );
}
void listsort( int (*compar)( const PHYSICAL *, const PHYSICAL * ) )
{
 PHYSICAL *q, *s, tmp;
 long lTmp;

 for( q = sgHead.next; NULL != q; q = q->next ){

  for( s = q->next; NULL != s; s = s->next ){

   if( compar( q, s ) ){

    tmp = *q;
    *q = *s;
    *s = tmp;

    lTmp = (long)q->next; // ◆アドレスを戻す
    q->next = s->next;
    s->next = (PHYSICAL *)lTmp;
   }
  }
 }
}
void sort( char *arg )
{
 if( strcmp( arg, "name" ) == 0 ) listsort( ( int(*)( const PHYSICAL *, const PHYSICAL * ) )comp1 );
 if( strcmp( arg, "age" ) == 0 )  listsort( ( int(*)( const PHYSICAL *, const PHYSICAL * ) )comp2 );
 if( strcmp( arg, "height" ) == 0 ) listsort( ( int(*)( const PHYSICAL *, const PHYSICAL * ) )comp3 );
 if( strcmp( arg, "weight" ) == 0 ) listsort( ( int(*)( const PHYSICAL *, const PHYSICAL * ) )comp4 );
}
void Output( void )
{
 PHYSICAL *q;

 q = sgHead.next;

 while( q != NULL ){

  printf( "%-16s %d %.1f %.1f\n", q->name, q->age, q->height, q->weight );

  q = q->next;
 }
 printf( "\n" );
}
void AllDeleteList( void )
{
 PHYSICAL *p;

 while( NULL != sgHead.next ){

  p = sgHead.next;

  sgHead.next = p->next;

  free( p );
 }
}
void main( void )
{
 sgHead.next = NULL;

 read_data( "test.txt" );

 Output(); // 出力

 sort( "height" ); // 身長でソート

 Output(); // 出力

 AllDeleteList(); // メモリ解放
}
注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。
    • good
    • 0

ソースコードをすべて見たわけではありませんが、


気になる点があります。
listsort関数の下記コードで

>head=malloc(sizeof(Physical));
>head=NULL;

mallocでせっかく確保した領域が、直後の文でムダになるとともに、
メモリリークを起こしています。
これはまずいです。
この2つの文を連続して書いた理由は、どういったものですか?

また、mallocの呼び出し全般についていえることは、
mallocによる領域確保は必ず成功する「とは限りません」。
戻り値をチェックすることは必須です。
    • good
    • 0

「ソート部分がどうしてもできません。

」というのはどのような状態を指しているのでしょうか?
あと, ひょっとして
#include <stdio.h>
void foo(int x)
{
x = 4;
}

int main()
{
int x = 3;
foo(x);
printf("%d\n", x);
return 0;
}
というプログラムで「4」が出力されると思ってはいないですよね?
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報