• 締切済み

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を読み込み横に合計を表示させるのはわかりました。 しかし、縦の合計もだし、その結果から整列して表示させることができずに 困っています。分かるかた教えてください><

  • ksy9z
  • お礼率12% (1/8)

みんなの回答

回答No.4

#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)
回答No.3

> 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

回答No.2

こういう質問をするときは自分が書いたコードを書いたところまでいいので出しましょう。コードがない質問というのは丸投げだとみなされて、ほとんど答えがつかないと思います。また、質問者が書いたコードを基に回答することが多いので、コードがない場合はコードを使った回答はまず期待できないと思ったほうがよいでしょう。 さらに、コードを出すとプログラムの書き方に本質的な誤りや理解不足がある場合に指摘してもらえることが多いです。 自分が質問されているようなプログラムを書く場合、次のデータ構造を用意します。 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も表示できます。 以上、がんばって。

ksy9z
質問者

補足

回答ありがとうございます。 ここまで書いてみました。縦方向の合計を求めるループの中に 横方向の合計を求めるループを入れるのは間違いでしょうか? 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]; }

  • k_kota
  • ベストアンサー率19% (434/2186)
回答No.1

私だったらですが、 2次元配列に格納する。 タテヨコそれぞれで何位が何列目なのか配列に格納 順位を入れた配列をもとに出力させる これ以上は自力でやるべきだと思います。

関連するQ&A

  • C言語のプログラムについて

    リスト処理による挿入法で得点の降順に整列して表示する。また、整列する際に要素どうしを比較した回数も表示する。 このプログラムを作成したいのですが、ファイルを開いてからこの先どのように書けばいいのかわからなくなりました。分かる方教えてください。 実行例 番号 氏名      得点 1021 Machida Msao 100 1017 Nonaka Fujio 98 1011 Suzuki Kaoru 93 1006 kato Ichiro 91 1002 Inoue Yasuo 85 整列のための比較回数=○○回 ファイルを開くのはこのように書きました。 #include<stdio.h> #include<stdlib.h> int main(void) { struct GDATA{ int bango; char sei[11],mei[11]; int tokuten; }; struct GDATA seiseki; FILE *fp; if((fp=fopen("data-a.dat","r"))==NULL) { printf("data-a.dat OPEN ERROR!\n"); exit(1); }

  • C言語のプログラムについて

    このプログラムが作れず困っています。分かる方教えてください。 data.datを入力し構造体型の配列に格納する(データ件数は50件以下,EOFになるまで入力) 次に<CTRL>Dが押されるまで学生番号をキー入力し,その氏名と得点を表示する。 学生番号の探索には二分探索法を使い構造体の配列を調べた回数も表示する。学生番号が存在しない場合は、存在しないことを 示すメッセージを表示する。 [実行例] 学生番号を入力してください ←入力要求のメッセージ(scanfの前に毎回入れる) 1012 1012番Sonoda Mari 得点=42点 探索回数=3回   ←学生番号,氏名,得点,探索回数を表示 学生番号を入力してください 1001 1001番Ando Ichiro 得点=73点  探索回数=1回 学生番号を入力してください 1016 1016番Nakai Kanji 得点=49点 探索回数=2回 学生番号を入力してください 1000 1000番なし 学生番号を入力してください(<CTRL>D=終了) <CTRL>D いちよ私が書いてみたものを載せます。 #include<stdio.h> #include<stdlib.h> int main(void) { struct GDATA { int bango; char sei[11],mei[11]; int tokuten; }; struct GDATA seiseki[50], tmp; int i,lo,hi,flg, kensuu, bango; FILE*fp; if((fp=fopen("data-a.dat","r"))==NULL) { printf("data-a.dat OPEN ERROR!\n"); exit(1); } for(kensuu=0;fscanf(fp,"%d%s%s%d",&tmp.bango, tmp.sei, tmp.mei, &tmp.tokuten)!= EOF;kensuu++) { seiseki[kensuu] = tmp; } printf("学生番号を入力してください\n"); while(scanf("%d", &bango)!= EOF) lo=0; hi=50 flg=0; while(flg==0&&lo<=hi) { i=(lo+hi)/2; if(bango!=seiseki[i].bango) { if(bango<seiseki[i])hi=i-1; elselo=i+1; } else flg=1; } if(flg==1)printf("%d番%s %s 得点=%d点\n",seiseki[i].bango,seiseki[i].sei,seiseki[i].mei,seiseki[i],tokuten); else printf("%d番なし\n",seiseki[i].bango); return 0; }

  • C言語の課題について

    データファイル(txtファイル) に生徒30人分の出席番号、数学 、英語の点数が入っていて、数 学と英語の点数は0点から100点 (整数)です。 このデータを元にして ・構造体型配列に出席番号、数 学、英語の点数を格納する ・国語の得点を70点から100点間 での整数の一様乱数によって格 納する ・各学生の平均点、偏差値を求 める ・偏差値が最もよい学生の出席 番号、数学、英語、国語の得点 、平均点、偏差値と合計点が181 点から210点、211点から240点 、241点から270点、271点から3 00点の学生の人数を数えてその 度数分布をtxtファイルへと出力 する 条件 ・平均点、偏差値を求める箇所 はmain関数から独立させる。 ・国語を入れるときに使用する 乱数は出席番号下4桁により初期 化したものを使うこと。頭の0は 除く(例120012-3→123) ・配列を因数とする関数は使用 可能 ・度数分布を作る際は、if文を使 用しないこと ・合計点が181~300点に含まれ ることは既知である ・txtファイルへの出力は以下の ようにすること。 High score: No. | math: , Eng , Jap | Ave: , D ev 181-200(10): ********** 211-240(17):**************** このような課題が出されたのですが、どのような順序でプログラムを書いていけばいいかが分かりません なのでどのような順序でプログラムを書いていけばいいか教えて下さい

  • C言語プログラムについての質問です。下のプログラムがなぜ降順で出力され

    C言語プログラムについての質問です。下のプログラムがなぜ降順で出力されるのか分かりません。何回も確認したのですが、不等号の向きが昇順になっているのに、どうして降順になるのかが理解できません。 ご教授お願いします。   #include <stdio.h>   #define MAX 10000   int main (int argc, const char * argv[]) { int N,data[MAX],d[MAX],j,k,w,x,a; x=0; a=1; do{printf("学生番号を入力してください\n");    scanf("%d",&N);   if(N!=0){printf("得点を入力してください\n"); scanf("%d",&data[N]);}x++;} while(N!=0);   for(j=0; j<x;j++){ d[j]=data[j];} for(j=0; j<x;j++)      {for(k=0;k<x-j-1;k++){   if(d[k]>d[k+1]){ w=d[k]; d[k]=d[k+1]; d[k+1]=w;}}} printf("昇順での整列結果\n"); for(j=x-1;j>0;j--){ printf("%d位 %d点\n",a,d[j]);a++;} return 0; }

  • C言語プログラムの作成方法がわかりません

    キーボードから5人の点数を入力すると平均点を表示するようにし、平均点以上の学生の点数を表示させるC言語のプログラムの作成方法を教えてください

  • C言語のプログラムなのですが、エラーの原因がわからずに困っています。

    C言語のプログラムなのですが、エラーの原因がわからずに困っています。 ./moji/learn/data/0-00.dat ./moji/learn/data/0-01.dat のようにファイル名が並んでいるテキストファイルをオープンし、 fscanfでファイル名をfileName[256]という配列に代入し、 そのファイル名のテキストファイルをオープンしてデータを読んでいくというものです。 void fv(char *files, int i) { FILE *data; data = fopen(files,"r");     if(data == NULL) { printf("Error\n"); exit(1); } int j, k, l, m, w, h, ww, hh, t; int dw[DN], dh[DN]; fscanf(data, "%d", &w); fscanf(data, "%d", &h); ww = w % DN; hh = h % DN; for(j = 0;j < DN;j++) { dw[j] = w / DN; dh[j] = h / DN; if(ww > 0) { dw[j] += 1; ww--; } if(hh > 0) { dh[j] += 1; hh--; } } for(l = 0;l < DN;l++) { for(m = 0;m < dh[l];m++) { for(j = 0;j < DN;j++) { for(k = 0;k < dw[j];k++) { fscanf(data, "%d", &t); t = 1; feature[i][l][j] += t; } } } } for(l = 0;l < DN;l++) { for(j = 0;j < DN;j++) { feature[i][l][j] = feature[i][l][j] * 10000 / (w * h); } } } 読み込んだファイル名をfvに渡して、 fvを繰り返し実行して計算を行うのですが、 最初の1000回は問題なく実行できるのですが、 1020回実行したところで、 Error が表示されてしまいます。 ファイルは存在しているため、なぜfopenで失敗するのかがわかりません。 原因として考えられることは何があるのでしょうか?

  • C言語のプログラム問題

    【質問】 次の処理を行うプログラムを作成する。 (1)10個の要素を持つ一次配列dat[10]を宣言する (2)dat[0]に0、dat[1]に1をセットする (3)dat[2]以降の要素には、前の2つの要素の和を計算し入力する。 (4)配列の各要素の値を表示する 【プログラム作成例】 dat[ 0] = 0 dat[ 1] = 1 dat[ 2] = 1 dat[ 3] = 2 dat[ 4] = 3 dat[ 5] = 5 dat[ 6] = 8 dat[ 7] = 13 dat[ 8] = 21 dat[ 9] = 34 上記の解答は下記の通りなのですが、下記以外の解答方法を教えてはいただけないでしょうか? C言語に詳しい方よろしくお願いいたします。 #include <stdio.h> main() { int i, dat[10]; dat[0] = 0; dat[1] = 1; for (i=2; i<10; i++) { dat[i] = dat[i-2] + dat[i-1]; } for (i=0; i<10; i++) { printf ("dat[%2d] = %2d\n", i, dat[i]); } return (0); }

  • C言語のプログラムについて質問です。

    C言語のプログラムについて伺いたいことがあるんですが5人くらいの名前、数学、英語、国語の点数を入力して各教科の最高点、最低点、平均点、それぞれの数+英+国の合計点を表示するプログラムを構造体を使って作りたいと思っています。 もしよろしければ事細かに教えていただけないでしょうか。 よろしくお願いします。

  • C言語プログラムについて

    wikipediaのコムソートを参考に、次のように作りました。 動きますでしょうか。動かなければ、どこをどのようにすればよいか教えていただけませんでしょうか。 プログラム「#include<stdio.h> #include<string.h> void combsort(void); void swap(void); int main(void) { combsort(); swap(); printf("データ%dの並べ替え結果は、\n%d\nです。\n"data2,data); return 0; } void combsort(){ int h,swaps,data,len,data2; printf("ソートさせる数を入力。>\n"); scanf("%d",&data); data2 = data; len = strlen(data); h = len * 10 / 13; while(true){ swapa = 0; for(i = 0;i + h <len;i++) { if(data(i) > data(i + h)) { swap(data, i, i + h); swaps +=1; } } if(h==1){ if(swaps==0){ break; } } else{ h = h * 10 / 13; } } } void swap{ int a,i,j; const int t = a[i]; a[i] = a[j]; a[j] = t; } 」 data:scanfによって入力される並べ替えを行う数値(例:0219523056810)を代入。 data2:dataのコピーで、並べ替えを行う前のデータを保管しておくもの。 また、これの反対(これが、昇順なら、降順。降順なら、昇順。)を同じようにしたいと思います。(combsort2にて)どうすればよいでしょうか。 教えていただけませんでしょうか。 お早めのご回答お待ちしております。

  • C言語をお願いします

    何が違うのか教えてください。 segmentation faultになります。 よく分からないので、プログラムを作っていただければ、助かります。 問 整数を入力し、降順並び変えてに表示。 ・入力した整数は配列に入れ、その配列を使って並び変える(入力終りの印は 1000 とする)。 ・入力する整数の個数は #define NUM 100 を使いなさい。 ・使うデータは、下記の例のように、キーボードから入力すること。 #include<stdio.h> #define NUM 100 int main(void){ int d[NUM]; int temp; int i,j,n; printf("Input scores.\n"); for(i=0; i<NUM && d[i]!=1000; i++){ scanf("%d",&d[i]); } n = i; for(i = 0; i < n; i++){ for(j = i + 1; j < n;j++){ if(d[j] > d[i]){ temp = d[i]; d[j] = d[i]; d[i] = temp; } } } printf("After sort."); for(i=0; i < n; i++){ printf("%d\n",d[i]); } return 0; } 実行例 Input scores. 60 30 45 90 100 0 1000 After sort. 100 90 60 45 30 0 よろしければ 問2 並び変えをする部分を mysort 関数にしたプログラムを作ってください。 main 関数から mysort 関数には点数の個数と sort 前の配列を渡し、並び変え結果の表示はmain 関数でお願いします。 (問題の意味が分かりません) 関数はさっぱり分かりません。 では、お願い致します。