- 締切済み
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; }
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- yama5140
- ベストアンサー率54% (136/250)
>またソートは以下のアルゴリズムで行うものです >与えられたリストをリスト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)
ソースコードをすべて見たわけではありませんが、 気になる点があります。 listsort関数の下記コードで >head=malloc(sizeof(Physical)); >head=NULL; mallocでせっかく確保した領域が、直後の文でムダになるとともに、 メモリリークを起こしています。 これはまずいです。 この2つの文を連続して書いた理由は、どういったものですか? また、mallocの呼び出し全般についていえることは、 mallocによる領域確保は必ず成功する「とは限りません」。 戻り値をチェックすることは必須です。
- Tacosan
- ベストアンサー率23% (3656/15482)
「ソート部分がどうしてもできません。」というのはどのような状態を指しているのでしょうか? あと, ひょっとして #include <stdio.h> void foo(int x) { x = 4; } int main() { int x = 3; foo(x); printf("%d\n", x); return 0; } というプログラムで「4」が出力されると思ってはいないですよね?