質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

1727閲覧

200人のスコアの評価を求める

kun_monimoni

総合スコア26

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2020/07/23 11:00

編集2020/07/23 15:54

200人分の評価(-1〜100点)が記載されたファイルがs.txtであるとします。そのときに、s.txtを読み込んで、集計結果を表示させたいです。
点が-1点の人は評価対象から外すとする場合に、その他0〜100点の人の人数をカウントcountし、その中で最大値max、最小値min、平均点averageを求めます。さらに、その平均点から20点以上下回っている評価対象の人数をfailureとしてカウントして求めたいです。

以下ソースコードを書いたのですが、平均点から20点以上下回っている評価対象の人数が0人になってしまいます。わかる方教えていただきたいです。(このとき、評価対象の平均点は50点で、s.txtの中には20点のスコアの人がいるので、0にはならないはずなのですが、0になってしまいます。)

#include <stdlib.h> int main(void) { FILE *fp; fp = fopen("s.txt","r"); if(fp == NULL) { printf("Open error\n"); exit(1); } int i, score_data, score_sum = 0, count = 0, max = 0, min = 100, failure = 0; for(i = 0; i < 200; i++) { fscanf(fp, "%d\n", &score_data); if (score_data >= 0) { count++; score_sum += score_data; if (max < score_data) { max = score_data; } if (min > score_data) { min = score_data; } } } double average = (double)score_sum / count for(i = 0; i < 300; i++) { fscanf(fp, "%d\n", &score_data); if (score_data >= 0) { if(score_data <= (average - 20.0) { failure++; } } } fclose(fp); printf("Count: %d\n", count); printf("Average: %f\n", average); printf("Max: %d\n", max); printf("Min: %d\n", min); printf("Failure: %d\n", failure); return 0; } コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/07/23 11:13

このままではコードが読みづらいので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
guest

回答4

0

ファイルから読込み処理の結果として,点数の度数分布を作ればよいのではないでしょうか.

最大値max、最小値min、平均点averageを求めます。さらに、その平均点から20点以上下回っている評価対象の人数

これらはそこから求めればよいでしょう.

投稿2020/07/24 02:52

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

Cを勉強したいのはともかく、データプロセスが目的だとしたら、他のツールの方が楽だと思います。Pythonとか、Excelとか。Python のコードを置いておきます。

python

1def average(l): 2 return sum(l) / len(l) 3 4with open("s.txt") as fp: 5 scores = [int(line) for line in fp if not line.isspace() and int(line) != -1] 6 print(f"Count: {len(scores)}") 7 print(f"Average: {average(scores)}") 8 print(f"Max: {max(scores)}") 9 print(f"Min: {min(scores)}") 10 print(f"Failure: {len([x for x in scores if x <= (average(scores) - 20)])}") 11

Cの勉強を応援したいから、ファイルを配列に読み込むコードも置いておきます。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int main() { 5 FILE *fp = fopen("s.txt", "r"); 6 if (fp == NULL) { printf("Open error\n"); return 1; } 7 8 int score_arr[200]; 9 int count = 0; 10 for (int i = 0; i < 200; i++) { 11 int score = 0; 12 fscanf(fp, "%d\n", &score); 13 if (score >= 0) { score_arr[count] = score; count++; } 14 } 15 16 for (int i = 0; i < count; i++) { 17 // データ処理 18 printf("%d\n", score_arr[i]); 19 } 20}

投稿2020/07/23 12:41

編集2020/07/23 12:58
YufanLou

総合スコア464

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SHOMI

2020/07/23 12:48 編集

>ファイルを配列に読み込むコード -1を読み捨てたうえで不定値にしていますが…
YufanLou

2020/07/23 12:56

ご指摘ありがとうございます。そうですね、本当の長さを変数でキープしなければいけません。編集し直しました。まぁ、ですからCがこんなデータ処理の問題に似合わないと思います。みんなにRustを薦めたい。
SHOMI

2020/07/23 12:57

>score_arr[i] = score; countで管理するなら score_arr[count] = score; では
SHOMI

2020/07/23 12:58

fseekを習っていないとコメントされているのでC言語の課題でしょうかね?
YufanLou

2020/07/23 13:04

ご訂正ありがとうございます! Pythonを書いてからコメント読んで課題かもと気づいたから、Cコードを追加に書きました。もしかしたら配列もまだ習っていないと思って。
guest

0

ひとつ目のループでfscanfを使って200人分のデータを読み終わった後、
ふたつ目のループで再度fscanfを使って読もうとしていますが、既にファイルを読み終わっているので読み取れません。
一度目のループでは配列に読み取っておきそれを使用するか、fseekで読み取り位置をファイル先頭に戻してください。

また、ふたつ目のループは300回になっています。

投稿2020/07/23 11:18

SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kun_monimoni

2020/07/23 11:22 編集

返信いただき、ありがとうございます。fseekというものを習っていないのですが、以下のようなソースコードではうまくいったのですが、おかしいところはありますでしょうか。また、簡単化できますでしょうか。見ていただきたいです。 #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fp; fp = fopen("s.txt","r"); if(fp == NULL) { printf("Open error\n"); exit(1); } int i, score_data, score_sum = 0, count = 0, max = 0, min = 100, failure = 0; for(i = 0; i < 200; i++) { fscanf(fp, "%d\n", &score_data); if (score_data >= 0) { count++; score_sum += score_data; if (max < score_data) { max = score_data; } if (min > score_data) { min = score_data; } } } fclose(fp); double average = (double)((int)(10 * ((double)score_sum / count))) / 10; fp = fopen("s.txt","r"); if(fp == NULL) { printf("Open error\n"); exit(1); } for(i = 0; i < 200; i++) { fscanf(fp, "%d\n", &score_data); if ((score_data >= 0) && (score_data <= (average - 20.0))) { failure++; } } fclose(fp); printf("Count: %d\n", count); printf("Average: %f\n", average); printf("Max: %d\n", max); printf("Min: %d\n", min); printf("Failure: %d\n", failure); return 0; }
SHOMI

2020/07/23 12:48

>簡単化 回答にも書いていますが、読み取ったものを配列に格納しておき使用しましょう
guest

0

気がついたのですが、一度ファイルを開いて読み込んだら、その後closeさせて、再度ファイルを開き読み込みをしなければいけないのでしょうか?

投稿2020/07/23 11:14

kun_monimoni

総合スコア26

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2020/07/23 11:18

わざわざ訊くまでもない、そう思うならやってみれば?
kun_monimoni

2020/07/23 11:27

上記のようにやってみて成功したのですが、他にいい方法はないのかと思ったため、聞いてしまいました。申し訳ないです。
episteme

2020/07/23 12:47 編集

二度読まずに済ませるため配列に読み込んでおけばいい。 二度目のファイル読み込みの代わりに、配列の各要素を使ってfailureを探す。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問