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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

Q&A

解決済

2回答

1041閲覧

while文を用いて指定された文字数が入力されるまで読み込みを続ける

kouchan_dd

総合スコア11

C

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

0グッド

0クリップ

投稿2023/04/29 13:02

編集2023/04/30 00:41

実現したいこと

while文を用いて指定された文字数(12文字)が入力されるまで読み込みを続けること。

前提

C言語で以下のような課題のプログラムを作っています。

バイナリファイルには,先頭から,生徒0のデータ→生徒」のデータ → 生徒2のデータ→・・・のように複数の生徒(30人以内)のデータが格納されており,各生徒のデータは次のような構成になっている。
姓(char型12個分)
科目1の点数(int型1個分)
科目2の点数(int型1個分)科目3の点数(int型1個分)

文字型2次元配列name(要素数30x12),整数型2次元配列sub(要素数30
x3),double型配列 ave(要素数3)を宣言する、そして,このファイルから,i番目の生徒の姓,科目1の点数,科目2の点数,科目3の点数をname[i],sub[i][0], sub[i][1], sub[i][2]に格納する。その後,生徒の絵数,科目1,科目2,科目3の平均点を求めて ave[0], ave[1], ave[2]に格納し,画面出力(表示)するプログラムを作成せよ。
※データ個数が与えられていないのでfor文ではなくwhile文を用いる..
※ fopen ではファイル名は“./../bin-score.dat"と設定する。

そして、自分なりにプログラムを作りました。

while文のところでおそらく間違っているのですが、「nameに対して文字が12個分読めている間繰り返す」という指示と、「ファイルの内容の読み出しデータの個数の情報は与えられていないので、ファイルの末尾まで読み出しを繰り返す」という指示があります。

発生している問題・エラーメッセージ

Kawai 84 62 74 Abe 62 58 68 Kubota 88 95 54 Yamada 77 39 100 Suzuki 82 55 66 Ogawa 48 100 61 Asai 88 92 96 Yoshida 94 92 96 Number of students : 8 Average : 77.875000 74.125000 76.875000 C:\Lecture\Prog2\Prog2_3_hw5\x64\Debug\Prog2_3_hw5.exe (プロセス 2364) は、コード 0 で終了しました。 このウィンドウを閉じるには、任意のキーを押してください... という風に正しいように表示されるのですが、正答例を見てみると"Kawai"の上に"Kimura"というデータがあるそうなんです。

該当のソースコード

C

1#include <stdio.h> 2 3int main(void) 4{ 5 FILE* fp; 6 char name[30][12]; 7 int sub[30][3]; 8 double ave[3] = { 0.0,0.0,0.0 }; 9 int i; 10 fp = fopen("../../bin-score.dat", "rb"); 11 if (fp == NULL) 12 { 13 printf("File open error.\n"); 14 return 1; 15 } 16 i = 0; 17 while (fread(&name[i], sizeof(char), 12, fp) == 12) 18 { 19 fread(&sub[i], sizeof(int), 3, fp); 20 fread(name[i], sizeof(char), 12, fp); 21 fread(&sub[i], sizeof(int), 3, fp); 22 ave[0] += sub[i][0]; 23 ave[1] += sub[i][1]; 24 ave[2] += sub[i][2]; 25 printf("%s %d %d %d\n", name[i], sub[i][0], sub[i][1], sub[i][2]); 26 i++; 27 } 28 ave[0] /= (float)i; 29 ave[1] /= (float)i; 30 ave[2] /= (float)i; 31 printf("Number of students : %d\n", i); 32 printf("Average : %lf %lf %lf\n", ave[0], ave[1], ave[2]); 33 fclose(fp); 34 return 0; 35}

試したこと

while文の中にfgetsを入れてみたりsizeof(Int)にしたりしましたが、ファイルがうまく出力されませんでした。
また、teratailでの皆様の回答を参考にさせていただき、whileの{}中のfreadの文を増やしてname→subのデータでループできるようにしたところ8個の正確なデータと平均点もデータが出たのですが、正答例を見ると"Kawai"のデータの上に"Kimura"というデータがあるらしく、やはりwhile文の中が間違えていると思うのです。

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

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

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

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

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

y_waiwai

2023/04/29 13:17

質問は編集できます 無駄に質問建てないで追記修正しましょう
episteme

2023/04/29 18:31 編集

> データ個数が与えられていないのでfor文ではなくwhile文を用いる.. これには異議アリ。 いくらたくさんのデータがファイル内にあっても30個で頭打ちなんだから for文(による30回の固定loop) でOK。
jimbe

2023/04/29 17:07

タグの Visual studio は関係ありますか? Visual studio で無いと発生しないのでしょうか。 バイナリも、バイナリファイルとは違う意味と思いますが。
guest

回答2

0

ベストアンサー

c

1 while (fread(&name[i], sizeof(char), 12, fp) == 12) 2 { 3 fread(name[i], sizeof(char), 12, fp); 4 fread(&sub[i], sizeof(int), 3, fp); 5 fread(&ave, sizeof(double), 3, fp);

少なくとも、 while の () 中に書いた fread によって name は読み取られてしまいますので、後の {} 内の fread の段階では読み取り位置がずれていて、想定通りの読み込みになっていません。
また、バイナリファイル内に ave のデータがあるとは書かれていないのに何を読もうというのでしょうか。

投稿2023/04/29 17:10

編集2023/04/29 17:14
jimbe

総合スコア12775

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

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

0

バイナリファイルを読みだすとこだけ:

C

1 FILE* fp; 2 char name[30][12]; 3 int sub[30][3]; 4 double ave[3] = { 0.0,0.0,0.0 }; 5 int count = 0; 6 7 const char* path = "bin-score.dat"; 8 9 fp = fopen(path, "rb"); 10 if ( !fp ) return -1; 11 12 for ( int i = 0; i < 30; ++i ) { 13 if ( fread(&name[i][0], sizeof(char), 12, fp) != 12 ) break; 14 if ( fread(&sub[i][0], sizeof(int), 3, fp) != 3 ) break; 15 printf("%s %d %d %d\n", name[i], sub[i][0], sub[i][1], sub[i][2]); 16 ++count; 17 } 18 fclose(fp);

投稿2023/04/29 14:50

episteme

総合スコア16614

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.45%

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

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

質問する

関連した質問