dポイントプレゼントキャンペーン実施中!

各ファイルの名前はinput_0.txtからinput_4.txtまであるとします。これらのファイルには(1)ナンバー(2)身長(3)体重がスペースをはさんで入力されています。
例:input_0.txt
1 172.3 65.3
2 164.3 54.6
3 176.4 55.4
4 170.2 70.4
5 167.4 63.8

この例では3番目の176.4が最大値として認識し2番目の164.3を最小値として出力させたいのですが、うまくいきません。プログラムを以下のように作りました。どこがいけないでしょうか?ご教授の方よろしくお願いします。

FILE *fpr,*fpw;
int no[N],i,j,max_j,min_j;
char fname[30];
float height[N],weight[N],max=0,min=0;

for(i=0;i<4;i++)//file題名用ループ
{
sprintf(fname,"input_%d.txt",i);

if((fpr=fopen(fname,"r"))==NULL)
{puts("file open error!!");return 0;}

for(j=0;j<5;j++){//ファイル内容用ループ
while((fscanf(fpr,"%d%f%f",&no[j],&height[j],&weight[j]))!=EOF)


if(height[j]>max){
max=height[j];max_j=j;
printf("number=%d__height=%.2f__weight=%.2f\n",no[max_j],max,weight[max_j]);
}
if(height[j]<min){
min=height[j];min_j=j;}
printf("number=%d__height=%.2f__weight=%.2f\n",no[min_j],min,weight[min_j]);

fclose(fpr);

A 回答 (4件)

うまくいかないとは、具体的にどういう結果になってしまうのかを


書いてくだされば原因を特定しやすいのですが……。

ざっと見て思ったのは以下のとおり。これで直ればよいのですが……。
○2つめのファイルを読み込むとき、たとえば一つ目のファイルの
 最大値が max に代入されたままです。
 ループの最初でmaxやその他の変数に初期値を代入しましょう。
○if(height[j]>max) と if(height[j]<min) の閉じ括弧の位置が違う。
○最大値や最小値を発見するたびに表示してしまっているので
 ファイル内容用ループのあとにprintfを移動する。
○fscanf(fpr,"%d %f %f",&no[j],&height[j],&weight[j])
 と、第二引数に半角スペースを空ける。

この回答への補足

ご指摘ありがとうございます。
一点目、ループの始めでmaxの値が初期化されていない。max=0、min=0、max_j=0、min_j=0;をファイル内容ループ前に付け加えました。

二点目の閉じ括弧の位置が違う意味がわかりません。
もう少し詳しく教えてもらえないでしょうか?

三点目、printfはファイル内容ループが終了してから入力しました。

四点目、fscanf()はスペースをデータの区切りと解釈するそうです。読み取りはこのままでOKでした。

これで実行したところ、input_0.txtでは(最大値)3番目の176.4 55.4と出力してほしいのですが、4番目の176.4 70.4と出力されてしまいます。身長の最大値は認識されていますが、身長に対するno[max_j],weight[max_j]が一致しません。(一つ下の数字を認識)max_jの考え方を教えてもらえないでしょうか?

補足日時:2006/09/05 22:10
    • good
    • 1

色々と突っ込みどころがあるような気がするが……


とりあえず、下のは動くので、自分のものと何が違うのか比べてみて欲しい。
多少方法を変えてはいるが、ね。
尚、インデントを全角スペースでつけているので、コピペの際は気をつけて。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct _Data_t {
 int  nNo;
 float fHeight;
 float fWeight;
} Data_t;

int main(void)
{
 FILE *fp;   // ファイルポインタ
 int  i,j;   // ループ用変数
 Data_t tMax;   // 最大値
 Data_t tMin;   // 最小値
 Data_t tTmp;   //
 char szFname[256]; // ファイル名
 char szBuf[256];  // 作業用バッファ
 char *p;    // 作業用ポインタ
 char *pToken;  // トークン用ポインタ


 for(i = 0; i < 5; i++) {
  sprintf(szFname, "input_%d.txt", i);
  
  if((fp = fopen(szFname, "r")) == NULL) {
   fprintf(stderr, "ファイル %s が開けません\n", szFname);
   return 0;
  }

  // 初期化
  tMax.fHeight = -1;
  tMin.fHeight = 9999;

  while(fgets(szBuf, 256, fp) != NULL) {
   // 改行コード対策
   p = strchr( szBuf, '\n' );
   if( p != NULL ){
    *p = '\0';
   }

   // 番号
   pToken = strtok(szBuf, " ");
   if(pToken == NULL) {
    continue;
   }
   tTmp.nNo = atoi(pToken);

   // 身長
   pToken = strtok(NULL, " ");
   if(pToken == NULL) {
    continue;
   }
   sscanf(pToken, "%f", &tTmp.fHeight);

   // 体重
   pToken = strtok(NULL, " ");
   if(pToken == NULL) {
    continue;
   }
   sscanf(pToken, "%f", &tTmp.fWeight);

   // 比較
   if(tTmp.fHeight > tMax.fHeight) {
    tMax = tTmp;
   }
   if(tTmp.fHeight < tMin.fHeight) {
    tMin = tTmp;
   }
  }

  // 表示
  printf("ファイル %s\n", szFname);
  printf("最大:Number=%d Height=%.2f Weight=%.2f\n", tMax.nNo, tMax.fHeight, tMax.fWeight);
  printf("最小:Number=%d Height=%.2f Weight=%.2f\n", tMin.nNo, tMin.fHeight, tMin.fWeight);

  fclose(fp);
 }

 return 0;
}
    • good
    • 1

while文のループ範囲が、最大値判定のif文のみ繰り返されますね。


しかもj==0のまま、その後の動作は、j==1の時は、EOF読み取り後
さらに読み出しに行くので、システムによってはそこで、暴走しますね。
number=1__height=172.30__weight=65.30
number=3__height=176.40__weight=55.40
セグメンテーション違反です
maxの方は、#1さん指摘のように、今より大きいのが見つかるたびに表示
するようになっていますね。
minは上記の理由で、到達しないかもしくは、値が[0]にしか入って
いませんが、
minは、0の身長より低い人を探すことになりますが、該当者がいないようですね。
    • good
    • 1

そもそも,heightとweigjhtを配列に入れる必要がないですね.


「これまで調べた中での最大値」,と「いま読み取った値」などを単純変数で持てばそれで良いのでは.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!