C言語の構造体でバブルソートがうまくいかない

このQ&Aのポイント
  • C言語の構造体でバブルソートが上手くいかない問題について質問します。
  • 構造体の身長順にバブルソートを行うソース文での結果表示が不正なため解決方法を探しています。
  • 解決方法を教えていただけると助かります。回答はお願いします。
回答を見る
  • ベストアンサー

C言語の構造体にてバブルソートが上手くいきません‥

C言語の構造体にてバブルソートが上手くいきません‥ 初めて質問致します。 以下は、構造体で、身長順にバブルソートを行うソース文ですが、 結果表示が、最下部に示したように、 5つのレコードのうち1つが消えてしまい、 残った4つのレコードのうちの1つが重複されて表示されてしまいます。 これが、なかなか解決できません‥。 既に結構調べており、また、早く解決できないといけないこともあり、 すみませんが、回答の形式でお願いできますと大変幸いです。 何卒よろしくお願い致します。 #include<stdio.h> #include<string.h> typedef struct kojin { char name[21]; int length; int weight; }KOJIN; int main(void) { int i, c, j; char buf[4]; KOJIN data[10]; KOJIN *d; printf(

  • damae
  • お礼率25% (2/8)

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

>for(i=0;i<10;i++) { >d = &data[i]; 最終的には、 dには &data[9] 、つまり、data[9]へのポインタが入っているわけです。 そして、そのまま >*d= data[i]; >data[i]= data[j]; >data[j]= *d; を実行したら *dはdata[9]になりますから data[9]= data[i]; data[i]= data[j]; data[j]= data[9]; と同じ事、となります。 一応、data[i]とdata[j]との入れ替えにはなりますが、同時にdata[i]がdata[9]へコピーされてしまい、もとあったdata[9]の内容が失われます。 最終的に、最後の入れ替えが発生したときのdata[i]と同じ値がdata[9]に入っているとこになります。 対策は、この KOJIN *d を使わないことです KOJIN temp ; としておいて temp= data[i]; data[i]= data[j]; data[j]= temp; とします。 ところで、これ、バブルソートじゃないですよ。 単純ソートというアルゴリズムになってます。 アルゴリズムの参考書等をもう一度よく確認してください。

damae
質問者

お礼

言われたとおりにして、無事解決することができました。 本当にありがとうございました。 問題となったソース文は、temp等にすることで、上手くいき、 ポインタ(*d)ではダメということでしたね‥。 よい勉強をさせていただきました。 他の皆様も、ご意見をいただきありがとうございました。

その他の回答 (3)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

そういう表示結果を得たとき、何を入力したのでしょうか? >5つのレコードのうち1つが消えてしまい、 >残った4つのレコードのうちの1つが重複されて表示されてしまいます。 という状況が伝わっていません。

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

これで 5個のデータ「だけ」入力できるの? なにがなんでも 10個入力しないとダメな気がするんだけど.... さておき, データの入力が終わったときの d の値を調べてください. あとおまけだけど, 「身長」は length じゃなくて height ではないかな.

  • trajaa
  • ベストアンサー率22% (2662/11921)
回答No.1

お願い致します。 と言われても・・・・・ 尻切れトンボじゃ、わかりません。

damae
質問者

補足

大変申し訳ありません‥ 携帯から投稿したのですが、まさかこんなことになっていたとは‥ 改めて、ソース全文を載せます。 何卒よろしくお願い致します。 #include<stdio.h> #include<string.h> typedef struct kojin { char name[21]; int length; int weight; }KOJIN; int main(void) { int i, c, j; char buf[4]; KOJIN data[10]; KOJIN *d; printf("\n"); for(i=0;i<10;i++) { d = &data[i]; printf("%d人目のデータ入力-------------\n",i+1); printf("名前を入力>"); fgets(d->name,21,stdin); if (strchr(d->name, '\n') != NULL) { strtok(d->name,"\n"); } else { while((c = getchar() != '\n') && (c != EOF)); } printf("身長を入力>"); fgets(buf,sizeof buf,stdin); if (strchr(buf, '\n') != NULL) { strtok(buf,"\n"); } else { while((c = getchar() != '\n') && (c != EOF)); } sscanf(buf,"%d",&d->length); printf("体重を入力>"); fgets(buf,sizeof buf,stdin); if (strchr(buf, '\n') != NULL) { strtok(buf,"\n"); } else { while((c = getchar() != '\n') && (c != EOF)); } sscanf(buf,"%d",&d->weight); } for (i=0 ; i<10 ; i++) { for (j=9 ; j>i ; j--) { if ( data[i].length > data[j].length ) { *d = data[i]; data[i] = data[j]; data[j] = *d; } } } printf("\n"); for(i=0;i<10;i++) { d = &data[i]; printf("レコード=%d %-20s 身長=%dcm 体重=%dkg\n" ,i+1,d->name,d->length,d->weight); } return 0; } ----------------------<表示結果>---------------------- レコード=1 g h 身長=164cm 体重=57kg レコード=2 e e 身長=169cm 体重=66kg レコード=3 s y 身長=172cm 体重=65kg レコード=4 a a 身長=176cm 体重=70kg レコード=5 a a 身長=176cm 体重=70kg ------------------------------------------------------

関連するQ&A

  • C言語の構造体の配列の扱い方

    #include <stdio.h> struct record { char name[10]; float height; float weight; }; /* 各データを、長さ 5 の record 構造体の配列に代入 */ struct record records[5] = { { "yasuo", 170.5, 70.5 }, { "hideaki", 176.5, 65.8 }, { "nobu", 166.5, 58.2 }, { "yuichi", 168.0, 65.4 }, { "nori", 152.7, 68.6 } }; float std_weight(struct record r){ /* 標準体重 = (身長 - 100) * 0.9 */ return (r.height - 100.0) * 0.9; } float std_weight(struct record r); となっている時に、メイン関数にて、5人の身長をもとめる方法と適正標準体重を求める方法を教えてください。構造体の配列を一括で扱うコードがいまいちわかりません。おねがいします。

  • C言語の構造体参照について

    入力ファイルを読み込み、構造体に格納しています。 構造体の中の、char kumiai_kubun[1]が、'0'および'1'になっているかの参照方法を教えてください。 ファイル011100920001000001の部分の最後の数字(1)が組合区分になります。 ・入力ファイル 000000003820050507200504 011100920001000001 エス事業(協)     9999999999999999 ・プログラム #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <errno.h> void print(char* buf, int size); /* 組合情報構造体 */ typedef union kumiaiin_jyouhou { char rawdata[80]; struct hdr { char sikibetu_code[2]; char kensu[8]; char koushin_date[8]; char data_date_year[4]; char data_date_month[2]; char dummy[56]; } header; struct dat { char sikibetu_code[2]; char daicyo_bango[10]; char kumiaiin_bango[5]; char kumiai_kubun[1]; char kaisyamei[46]; char dattai_kaiyaku_ymd[8]; char sakujyo_ymd[8]; } data; } KUMIAIIN_JYOUHOU; int main(int argc, char* argv[]) { KUMIAIIN_JYOUHOU *bufp; FILE *fp; int sts, rtncd; /* 初期化 */ rtncd=0; /* 区切り文字設定 */ strncpy(fs, FS, sizeof(fs)); /* データファイルオープン */ fp = fopen(argv[1], "rb"); /* 組合員情報共用体領域読み込み用メモリの確保 */ bufp = malloc(sizeof(KUMIAIIN_JYOUHOU)); /* ファイル読込 */ while( 1 ) { /* 組合員情報読み込み */ memset(bufp, NULL, sizeof(KUMIAIIN_JYOUHOU)); sts = fread(bufp, sizeof(KUMIAIIN_JYOUHOU), 1, fp); ~組合区分の判定処理~ } fclose(fp); }

  • C言語の構造体についてです。

    構造体employee 型の変数を配列で5つ宣言し、BMI 値、肥満率、理想体重を求めた後、BMI 値の昇順でソートをかけ、表示をするというプログラムを作成したいのですが、うまくいきません。 ・引数は、配列(構造体employee []型 または、構造体employee *型) ・戻り値は、なし。 ・関数名は、sort ・番号はint型 ・名前はchar型 ・身長・体重・BMI値・肥満率・理想体重はdouble型 という指定があります。 #include <stdio.h> #define N 5 struct employee{ int number; char name[20]; double height; double weight; double bmi; double fat; double ideal; }; void bmi_fat(struct employee *); void sort(struct employee []); int main(void) { int i; struct employee std[N]={ {1, "oohata", 173.0, 60.0, 0.0, 0.0, 0.0},{2, "suzuki", 168.8, 60.2, 0.0, 0.0, 0.0}, {3, "satou", 168.2, 80.5, 0.0, 0.0, 0.0},{4, "tanaka", 162.5, 45.2, 0.0, 0.0, 0.0}, {5, "yamada", 155.3, 55.7, 0.0, 0.0, 0.0} }; for(i=0; i<N; i++){ sort(std); bmi_fat(&std [i]); } for(i=0; i<N; i++){ sort(std); printf("社員番号:%d番\n", std[i].number); printf("名前:%s\n", std[i].name); printf("身長:%2.1lfcm\n", std[i].height); printf("体重:%2.1lfkg\n", std[i].weight); printf("BMI:%2.1lf\n", std[i].bmi); printf("肥満率:%2.1lf%\n", std[i].fat); printf("理想体重:%2.1lfkg\n", std[i].ideal); } return 0; } void sort(struct employee a[]) { int i, j; struct employee x; a->bmi=a->weight/((a->height/100.0)*(a->height/100.0)); a->ideal=(a->height-100)*0.9; a->fat=a->weight/a->ideal*100.0; for(i=0; i<N-1; i++){ for(j=0; j<N-i-1; j++){ if(a[j].bmi>a[j+1].bmi){ x=a[j]; a[j]=a[j+1]; a[j+1]=x; } } } } 以上が作成済みのプログラムなのですが、「外部シンボル'_bmi_fat'が未解決」と出てしまいます。 どこを直してよいのかが全く分かりません。 ご教授お願い致します。

  • C++言語で、構造体のコピーは可能(しても良い)のでしょうか?

    C++言語で、構造体のコピーは可能(しても良い)のでしょうか? 問題がある場合は、なぜだめなのか知りたいです。 構造体は可変長ではありません。 typedef struct kumi { char namae[10]; int ten; }Kumi; Kumi a, b; strcpy(a.namae, "AAA"); a.ten = 50; b = a;

  • C++でCの構造体をnewするとまずいのでしょうか?

    以下のようなCで書かれたヘッダがあったとして ---testc.h--- typedef struct __Test { int i; char c[30]; char* x; } Test; これを以下のようにnewして使うのは問題ないでしょうか? ---test.cpp--- extern "C" { #include test.h } int main(void) { Test* test = new Test(); test->i = 30; test->c[3] = 'a'; test->x = "aiueo"; return 0; }

  • C言語 構造体(2)

    ご質問です。 構造体で、あらかじめメンバ数を固定したものではなく、 テキストファイルを読み込んだときにメンバ数を変えて読み込みたいのです。 (カンマできりたい) aaa.txt ------------------------ あああ,いいい ------------------------ となっているときは、 tmp.nm[0]=あああ tmp.nm[1]=いいい となり、 kamoku.nm[0] kamoku.nm[1] をprintf。 aaa.txt --------------------------- あああ,いいい,ううう,えええ --------------------------- の場合は tmp.nm[0]=あああ tmp.nm[1]=いいい tmp.nm[2]=ううう tmp.nm[3]=えええ kamoku.nm[0] kamoku.nm[1] kamoku.nm[2] kamoku.nm[3] をprintf。 下記は動きません。。 よろしくお願いいたします。 #include <stdio.h> struct kamokumei { char nm[10]; }kamoku; int main(void) { int i,P,t; FILE *fp; struct kamokumei kamoku[20]; char buf[1024]; fp = fopen("aaa.txt", "r"); P=3; t=0; while( fgets(buf, sizeof(buf), fp) ){ struct kamokumei tmp; sscanf(buf, "%s", tmp.nm[t]); nm[t++] = tmp; } for(i = 0; i < P; i++) { printf("%s\n", kamoku.nm[i]); } return 0; }

  • 構造体配列の安定なソート

    出席番号と得点の配列を持つ構造体配列で、 出席番号順に並んだ状態でqsortを使って得点をソートする場合、 同じ得点の人でも、出席番号順はばらばらになってしまいますよね。 調べてみて、バブルソートなど安定なソートを使えばいいということが分かったのですが、 qsortは標準ライブラリにあって、 比較関数も見よう見まねで作ってなんとかなったのですが、 他の方法となると具体的にどうすればいいのか、 よくわからない状況です。 http://homepage1.nifty.com/daccho/program/algo/sort3.htm こちらのサイトのソースファイルを見て、 普通のint配列のバブルソートは出来たのですが、 構造体配列を、構造体の中の一つの要素をキーにバブルソートできるようにするには、 ここからどのように変更すればいいのでしょうか? 並び替える内容はint型だけなので、文字列をソートできるようにする必要はなく、 ソート対象も少ないので(上限100程度)、速度的な問題は考慮しなくて大丈夫だと思います。 Cは勉強中で、基本文法がわかるぐらいという状況で、 もしかしたら変なことを言っているのかもしれませんが、 よろしくお願いします。

  • ポインタと構造体の利用について

    samplefile.txtの中身 c03888 工大八郎 90 a03111 工大一郎 100 a03222 工大二郎 30 b03666 工大六郎 70 b03555 工大五郎 60 a03333 工大三郎 80 c03777 工大七郎 40 c03999 工大九郎 20 b03444 工大四郎 50 このデータをfscanfで取り込んで構造体に代入 typedef struct { char code[7]; char name[21]; int score; }REC; そしてこのデータを昇順にソートして結果を出力したいのですが 問題はここから work52.cというファイルとbubble.cというファイルとmy_sort.hというファイルがあり、work52.cからmy_sortという関数(バブルソート)を使いたい。 work52.cの中身 #include <stdio.h> #include "my_sort.h" #define MAX_NUM 500 int main(int argc, char *argv[]){ FILE *fp; REC rec[MAX_NUM]; int i, sum , min, max , n; if (argc != 2) { printf("ファイル名を指定してください\n"); return(-1); } if ((fp = fopen(argv[1], "r")) == NULL) { printf("ファイルを開けませんでした\n"); return(-1); } i = 0; while (fscanf(fp, "%s %s %d", rec[i].code, rec[i].name, &rec[i].score) != EOF){ i++; } fclose(fp); n = i; /* 初期値の設定 */ min = rec[0].score; max = rec[0].score; sum = rec[0].score; for (i = 1; i < n; i++){ sum += rec[i].score; if (rec[i].score < min) { min = rec[i].score; } if (rec[i].score > max) { max = rec[i].score; } } my_sort(rec, n); printf("最高点:%3d\n", max); printf("最低点:%3d\n", min); printf("平均点:%5.1f\n", (double) sum / n); for (i = 0; i < n; i++){ printf("%3d\t%s\t%s\n", rec[i].score, rec[i].code, rec[i].name); } return(0); } my_sort.hの中身 typedef struct { char code[7]; char name[21]; int score; }REC; void my_sort(REC *rec,int n); バブルソートで整列 #include <stdio.h> #include "my_sort.h" #define MAX 50 void my_sort(REC *rec, int n){ for(i = 0;i < n - 1; i++){ for(j = n - 1;j > i;j--){ /*この中身が問題----1*/ } } } 1の部分でchar codeとchar nameとint scoreの値を交換するときにどうすればいけるでしょうか?ご教授ください。

  • C言語 ソートについて

    #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { } bool is_at(char c) { } void justify(char line[], int n) { } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; } 上の雛形を使って文字列lineに含まれる@以外の文字を文字列の前の方に詰めていくプログラミングを作るという問題を解いていたのですが下のプログラミングまでは出来たのですが最後のjustifyの部分がわかりません 良ければ解答をお願いします #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } bool is_at(char c) { if(c == '@') { return true; } else { return false; } } void justify(char line[], int n) { for(int i=0;i<n-1;i++) { } } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; }

  • 構造体の型について

    ある構造体をxxxと名づける以下のプログラムを作成しました。 ーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx aaa; strcpy(aaa.variable,"bbb"); printf("%s\n",aaa.variable); } ーーーーーーーーーーー これは動き、bbbと表示されます。 しかしながら、構造体のポインタを使用した 以下のプログラムではコンパイルはとおりますが実行時にコアダンプして落ち ます。 ーーーーーーーーーーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx* aaa; strcpy(aaa->variable,"bbb"); printf("%s\n",aaa->variable); } ーーーーーーーーーーーーーーーーーーーーーーー 両プログラムの意図はまったく同じなのに何故いけないのでしょうか。

専門家に質問してみよう