• 締切済み

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

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の値を交換するときにどうすればいけるでしょうか?ご教授ください。

みんなの回答

noname#42542
noname#42542
回答No.6

No.2で回答したものです。 構造体の値の交換の部分をいちいちメンバ変数を指定してますが、これはNo.3の方が書いたように a = b; で、構造体変数に直接代入できます。 (私がC言語を覚えた20年以上前には構造体変数の代入が出来ないコンパイラが結構あったのです。いつの間にかそのスタイルで書いてしまいました)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★また、寝ぼけていた。本当にごめんなさい。 ・(1)code で昇順ソートするならば  間違い⇒if ( strcmp( rec[i].code, rec[j].code ) ){  正しい⇒if ( strcmp( rec[i].code, rec[j].code ) < 0 ){  としてください。 ・(2)name で昇順ソートするならば  間違い⇒if ( strcmp( rec[i].name, rec[j].name ) ){  正しい⇒if ( strcmp( rec[i].name, rec[j].name ) < 0 ){  としてください。 ・寝起きでボケてしまった(恥)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★あっ、寝ぼけていた。→比較部分を追加修正します。 ・交換部分の  tmp = rec[ i ];  rec[ i ] = rec[ j ];  rec[ j ] = tmp;  を  if ( 条件式 ){   tmp = rec[ i ];   rec[ i ] = rec[ j ];   rec[ j ] = tmp;  }  に修正して下さい。 ・また『条件式』はソートする項目により3タイプあります。  回答者 No.1 さんのアドバイスにあるようにどのデータで『昇順』ソートしますか?  (1)code で昇順ソート…strcmp( rec[i].code, rec[j].code )  (2)name で昇順ソート…strcmp( rec[i].name, rec[j].name )  (3)score で昇順ソート…rec[i].score <rec[j].score  どの項目で昇順ソートするか分からないため、上記に3つ条件式を用意しました。  下のようになります。 ・(1)code で昇順ソートするならば、  if ( strcmp( rec[i].code, rec[j].code ) ){   tmp = rec[ i ];   rec[ i ] = rec[ j ];   rec[ j ] = tmp;  } ・(2)name で昇順ソートするならば、  if ( strcmp( rec[i].name, rec[j].name ) ){   tmp = rec[ i ];   rec[ i ] = rec[ j ];   rec[ j ] = tmp;  } ・(3)score で昇順ソートするならば、  if ( rec[i].score <rec[j].score ){   tmp = rec[ i ];   rec[ i ] = rec[ j ];   rec[ j ] = tmp;  } ・以上。おわり。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★交換の部分だけアドバイス ・一般にデータの交換は、一時変数(配列、構造体)などを1つ用意して代入を3回  行うことで交換できます。 ・つまり、  (1)一時変数←交換値1  (2)交換値1←交換値2  (3)交換値2←一時変数  この3ステップです。 ・一時変数は入れ替えるデータと同じ型を1つ宣言すればよい。  つまり、my_sort() 関数の最初に『REC tmp;』を1つ宣言します。  そして、  tmp = rec[ i ];  rec[ i ] = rec[ j ];  rec[ j ] = tmp;  の3ステップで rec[i] と rec[j] の2つのデータが交換できます。 ・下に my_sort() 関数を提示します。 サンプル: void my_sort( REC *rec, int n ) {  REC tmp; ←これを宣言。    for ( i = 0 ; i < n - 1 ; i++ ){   for( j = n - 1 ; j > i ; j-- ){    /*この中身が問題----1*/    tmp = rec[ i ];    rec[ i ] = rec[ j ];    rec[ j ] = tmp;    ↑ここに3ステップを記述。   }  } } その他: ・バブルソートのアルゴリズムは理解しているようですね。  データの交換は一時変数 tmp を1つ用意して代入ステップを3回行うことで出来ます。 ・私は配列の交換を行うときに一時変数 tmp を tmp[ 1 ] として宣言します。  これは交換部分を  tmp[ 0 ] = rec[ i ];  rec[ i ] = rec[ j ];  rec[ j ] = tmp[ 0 ];  と桁をそろえて、見やすくする意味で行っています。→私流です。まねるかどうかは自由です。 ・以上。おわり。

noname#42542
noname#42542
回答No.2

まず、rec[j - 1]とrec[j]の大小を比較しますよね。 scoreでソートする場合、 if (rec[j - 1].score > rec[j].score) {   入れ替え処理 } codeやnameでソートする場合、 if (strcmp(rec[j - 1].code, rec[j].code) > 0) {   交換処理 } そして、値を交換するとき、   rec[j - 1].score = rec[j].score; だとj - 1のほうの内容が消えてしまいますので、一時的にj - 1の内容を退避する変数を用意します。my_sort()に   REC temp; を宣言し、   /* 退避する */   temp.score = rec[j - 1].score;   strcpy(temp.code, rec[j - 1].code);   strcpy(temp.name, rec[j - 1].name);   /* j - 1にjをコピーする */   rec[j - 1].score = rec[j].score;   strcpy(rec[j - 1].code, rec[j].code);   strcpy(rec[j - 1].name, rec[j].name);   /* jに退避したデータ(j - 1)をコピーする */   rec[j].score = temp.score;   strcpy(rec[j].code, temp.code);   strcpy(rec[j].name, temp.name); とします。 1. j - 1を退避 2. j - 1にjをコピー 3. jに退避データをコピー のセットで値の交換ができます。 バブルソートは、ソートする際にデータが泡のように移動していくことからそう呼ばれます。 外側のループが1回実行されるたびに内側のループでの最小値が確定します。 i = 0のときに内側ループが n - 1回実行され、rec[0]が確定(rec[0]~rec[n - 1]を比較) i = 1のときに内側ループが n - 2回実行され、rec[1]が確定(rec[1]~rec[n - 1]を比較) i = 2のときに内側ループが n - 3回実行され、rec[2]が確定(rec[2]~rec[n - 1]を比較) : : i = n - 2のときに内側ループが1回実行され、rec[n - 1]が確定(rec[n - 2]~rec[n - 1]を比較)

参考URL:
http://www1.cts.ne.jp/~clab/hsample/Sort/Sort1.html
  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

> データを昇順にソートして結果を出力したい データには ・コード ・名前 ・点数 の3種類があります。 どれの昇順ですか?