• 締切済み

c言語の問題です。ファイルからデータを読み込み連結リストに記憶しソートするプログラムです。お願いします

ソート部分がどうしてもできません。 またソートは以下のアルゴリズムで行うものです 与えられたリストをリスト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; }

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.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(); // メモリ解放 } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

ソースコードをすべて見たわけではありませんが、 気になる点があります。 listsort関数の下記コードで >head=malloc(sizeof(Physical)); >head=NULL; mallocでせっかく確保した領域が、直後の文でムダになるとともに、 メモリリークを起こしています。 これはまずいです。 この2つの文を連続して書いた理由は、どういったものですか? また、mallocの呼び出し全般についていえることは、 mallocによる領域確保は必ず成功する「とは限りません」。 戻り値をチェックすることは必須です。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「ソート部分がどうしてもできません。」というのはどのような状態を指しているのでしょうか? あと, ひょっとして #include <stdio.h> void foo(int x) { x = 4; } int main() { int x = 3; foo(x); printf("%d\n", x); return 0; } というプログラムで「4」が出力されると思ってはいないですよね?

関連するQ&A