- 締切済み
C言語のプログラムについて
ファイル"data\d.dat"にはテストの各問の点数が以下のフォーマットで記録されている。 学生番号 問1の点数 問2の点数 問3の点数 問4の点数 問5の点数 これを入力し、学生ごとの合計点と、間ごと合計点を求めて表示する(整列前)。次に、間の合計点の 降順に左から右に向かって整列し、さらに、学生の合計点で降順に整列して表示する(整列後)。 <実行例> 整列前 番号 問1 問2 問3 問4 問5 合計 1001 20 30 40 41 90 230 1002 50 30 24 0 95 199 1003 20 33 55 35 90 233 1004 93 55 56 61 90 355 1005 20 50 51 44 90 255 合計 203 198 236 181 455 整列後 番号 問5 問3 問1 問2 問4 合計 1004 90 56 93 55 61 355 1005 90 51 20 50 44 255 1003 90 55 20 33 35 233 1001 90 49 20 30 41 230 1002 95 25 50 30 0 199 合計 455 236 203 198 181 このプログラムを作成したいのですが fscanfでdata-d.datを読み込み横に合計を表示させるのはわかりました。 しかし、縦の合計もだし、その結果から整列して表示させることができずに 困っています。分かるかた教えてください><
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- hanabutako
- ベストアンサー率54% (492/895)
#2の補足を見る限り、変数宣言など基本的なところから勉強した方がよいと思います。先生が書いたコードをそのままわけも分からず書いているだけに見えます。 まぁ、他人が書いたコードというのも勉強になると思うので、一応自分がやってみたコードを載せてみます。FreeBSD上でしかコンパイルも実行も確認していません。また、問の数や学生の数は両方共5だとして、プログラムを書いています。 #include <assert.h> #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUM_SCORES 5 #define NUM_STUDENTS 5 #define LINE_SIZE 1024 struct student { int id; int scores[NUM_SCORES]; int sum; }; struct score { int id; int sum; }; int compare_students(const void *i0, const void *i1) { const struct student *s0, *s1; s0 = (const struct student*)i0; s1 = (const struct student*)i1; return s1->sum - s0->sum; } int compare_scores(const void *i0, const void *i1) { const struct score *s0, *s1; s0 = (const struct score*)i0; s1 = (const struct score*)i1; return s1->sum - s0->sum; } #define STUDENT_ID "Id " #define SCORE_ID_PATTERN " Q%d" #define STUDENT_ID_PATTERN "%4d" #define SCORE_PATTERN "%4d" #define SCORE_SUM "Sum " void print_all(struct student *students, struct score *scores) { int i; printf(STUDENT_ID); for (i = 0; i < NUM_SCORES; i++) { printf(SCORE_ID_PATTERN, scores[i].id + 1); } printf("\n"); for (i = 0; i < NUM_STUDENTS; i++) { int j; printf(STUDENT_ID_PATTERN, students[i].id); for (j = 0; j < NUM_SCORES; j++) { printf(SCORE_PATTERN, students[i].scores[scores[j].id]); } printf(SCORE_PATTERN, students[i].sum); printf("\n"); } printf(SCORE_SUM); for (i = 0; i < NUM_SCORES; i++) { printf(SCORE_PATTERN, scores[i].sum); } printf("\n"); } int main(int argc, char* argv[]) { char buf[LINE_SIZE]; struct student students[NUM_STUDENTS]; struct score scores[NUM_SCORES]; int i; FILE *fp; if (argc != 2) { printf("Usage:\n"); printf("%s <filename>\n", getprogname()); exit(EXIT_FAILURE); } fp = fopen(argv[1], "r"); if (fp == NULL) err(errno, "failed to open %s", argv[1]); for (i = 0; i < NUM_SCORES; i++) { scores[i].id = i; scores[i].sum = 0; } for (i = 0; i < NUM_STUDENTS; i++) { char *token, *tmp = buf; int index = 0; students[i].sum = 0; if (fgets(buf, sizeof(buf), fp) == NULL) { errx(-1, "data is too little"); } buf[strlen(buf) - 1] = '\0'; while ((token = strsep(&tmp, " \t")) != NULL) { if (*token == '\0') continue; if (index == 0) { students[i].id = atoi(token); } else { int score = atoi(token); students[i].sum += score; students[i].scores[index - 1] = score; scores[index - 1].sum += score; } ++index; } } fclose(fp); printf("Before:\n"); print_all(students, scores); qsort(students, NUM_STUDENTS, sizeof(struct student), compare_students); qsort(scores, NUM_SCORES, sizeof(struct score), compare_scores); printf("\nAfter:\n"); print_all(students, scores); return 0; } プログラム内で計算するので、d.datの中身には合計を入れていません。 1001 20 30 40 41 90 1002 50 30 24 0 95 1003 20 33 55 35 90 1004 93 55 56 61 90 1005 20 50 51 44 90
- jjon-com
- ベストアンサー率61% (1599/2592)
> fscanfでdata-d.datを読み込み > 横に合計を表示させるのはわかりました。 とのことですが,回答No.2の補足のコードではそれが表示されません。 縦の合計はとりあえず保留するとして, 次のように表示されるプログラムなら提示できるのでしたっけ? 番号 問1 問2 問3 問4 問5 合計 1001 20 30 40 41 90 230 1002 50 30 24 0 95 199 1003 20 33 55 35 90 233 1004 93 55 56 61 90 355 1005 20 50 51 44 90 255
- hanabutako
- ベストアンサー率54% (492/895)
こういう質問をするときは自分が書いたコードを書いたところまでいいので出しましょう。コードがない質問というのは丸投げだとみなされて、ほとんど答えがつかないと思います。また、質問者が書いたコードを基に回答することが多いので、コードがない場合はコードを使った回答はまず期待できないと思ったほうがよいでしょう。 さらに、コードを出すとプログラムの書き方に本質的な誤りや理解不足がある場合に指摘してもらえることが多いです。 自分が質問されているようなプログラムを書く場合、次のデータ構造を用意します。 A. 各学生ごとのテストの点数を入れた構造体。 B. 各問いごとの合計点を入れた構造体。 構造体Aのメンバーには学籍番号、各問の点数 (配列で持たせる)、合計点を格納し、構造体Bのメンバーには問いの番号と合計点を格納します。 これは、学生ごとに縦に並べて点数の表示を行う以上、学生ごとにデータをまとめたほうがよいと思うからです。また、整列を行うというところから、当然、stdlib.hに入っているqsortが使えないかということを検討し、構造体のほうがその取扱をしやすいと判断しました。問いの表示も合計点で並び替えることになるので、当然、構造体Bのように問いごとの構造体があったほうがqsortで扱いやすいと考えました。問いごとの構造体に入れるデータは、ソートに必要な最小限のものということで合計点と問いの番号だけを入れます。 以上のデータ構造を用意した上で、プログラムの流れは次の通り。 1. ファイルからデータを読み込み、構造体Aの配列を埋める (この時に合計点も計算する) 2. 構造体Aの配列を使い、構造体Bの配列を作成 3. 整列前のデータを表示 4. qsortを用い、構造体Aを合計点で並び替え 5. qsortを用い、構造体Bを合計点で並び替え 6. 構造体Bでの問いの順番に従って、構造体Aの点数を表示することで、整列後のデータを表示 1や2ところではそれらの構造体の配列を何らかの方法で確保しないといけませんが、動的に確保するか静的に確保するかは必要に応じて考えてください。 また、読み込み方によっては6の関数と同じ関数で3も表示できます。 以上、がんばって。
- k_kota
- ベストアンサー率19% (434/2186)
私だったらですが、 2次元配列に格納する。 タテヨコそれぞれで何位が何列目なのか配列に格納 順位を入れた配列をもとに出力させる これ以上は自力でやるべきだと思います。
補足
回答ありがとうございます。 ここまで書いてみました。縦方向の合計を求めるループの中に 横方向の合計を求めるループを入れるのは間違いでしょうか? include<stdio.h> #include<stdlib.h> int main(void) { struct GDATA{ int bango; char sei[11],mei[11]; int tokuten; }; struct GDATA t[200]; int i,j,t[N+1],t[M] FILE*fp; if((fp=fopen("data-d.dat","r"))==NULL) { printf("data-d.dat OPEN ERROR\n"); exit(1); } printf("番号問1 問2 問3 問4 問5 合計 \n"); while(fscanf(fp,"%d%s%s%d",&t[0].,t[1],t[2],t[3],t[4])!=EOF) for(i=0;i<N;i++) { for(j=0;j<M;j++)t[N][j]+=t[i][j]; }