• ベストアンサー

C言語 テキストファイルから比較

日付:2004/02/02 17時30分 体重:91.0 体脂肪率:21.0 除脂肪体重:71.9 日付:2004/02/04 20時47分 体重:88.6 体脂肪率:24.0 除脂肪体重:67.3 日付:2004/02/05 18時43分 体重:88.2 体脂肪率:22.5 除脂肪体重:68.4 日付:2004/02/06 18時35分 体重:88.4 体脂肪率:21.5 除脂肪体重:69.4 テキストファイルに以上のように入力されている場合に 除脂肪体重が多いもの3つだけを抜き出す(除脂肪体重だけを変数に入力する)には どの用にすればよいのでしょうか? アドバイスでも構いません。教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • earth
  • ベストアンサー率33% (1/3)
回答No.4

テストしてないので間違ってるかもしれませんが こんなのはどうでしょう? //lineにはfgetsなどで解析する文字列を代入してください char *line = "日付:2004/02/02 17時30分 体重:91.0 体脂肪率:21.0 除脂肪体重:71.9"; int n,i; char str[5]; n = strlen(line); //文字列を最後から見て行って':'を探します while(line[n] != ':'){   n--; } n++; i = 0; //文字列を数値に変換するatoi()は「.」があると正しく処理されないので取り除く必要があります while(line[n] != '\0'){   if(line[n] == '.'){     n++;   }   str[i] = line[n];   n++;   i++; } これで71.9の10倍である719の文字列がstrに入るのでそれをatoi()で数値に変換すればいいと思います。 ただしこれだと小数点第1位のみしか対応していません。 小数点がない場合や第2位まである場合にはさらに追加の処理が必要です。

ebinamori
質問者

お礼

回答ありがとうございます。 実際にプログラムまで作ってもらって非常にありがたいです。 ひとつ気になったのはatoiではなくatofを使えばもっと簡単に処理できるのではないですか? 早速作ってみようと思います。

ebinamori
質問者

補足

作ってみました。(めちゃくちゃ複雑…) void rank(void){ FILE *fp; int n,i,j,k[3]; double a,b[3]; char p[100][80],str[80]; for(i=0;i<3;b[i]=0,k[i++]=0); i=j=0; if((fp=fopen("tj.txt","r"))==NULL){ printf("ファイルを読み込めません。\n"); exit(1); } do{ fgets(p[j],79,fp); if(!feof(fp)){ n=strlen(p[j]); while(p[j][n-1]!=':')n--; while(p[j][n]!='k')str[i++]=p[j][n++]; } str[i]='\0'; i=0; a=atof(str); if(b[0]<a){ b[2]=b[1];b[1]=b[0];b[0]=a; k[2]=k[1];k[1]=k[0];k[0]=j; } else if(b[1]<a){ b[2]=b[1];b[1]=a; k[2]=k[1];k[1]=j; } else if(b[2]<a){ b[2]=a; k[2]=j; } j++; }while(!feof(fp)); printf("第1位 %s",p[k[0]]); printf("第2位 %s",p[k[1]]); printf("第3位 %s",p[k[2]]); fclose(fp); }

その他の回答 (7)

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.8

#7です。 ちょっと訂正です。 「日付」のところだけコロンが全角なんですね。 ですから、質問の1行目は以下のように分割されます(strtok()の戻り値は以下のようになります)。 ---------- 日付:2004/02/02 17時30分 体重 ←strtok()1回目 91.0 体脂肪率          ←2回目 21.0 除脂肪体重         ←3回目 71.9              ←4回目 ---------- >#define N 4 /* 除体脂肪体重は4番目だから */ 「日付」の後のコロンも半角だったら #define N 5 になります。

ebinamori
質問者

補足

なんかそこだけ全角にしてしまったすみません。 ありがとうございます。

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.7

#3,5です。 自分で紹介しておきながら申し訳ないんですけど、 ご質問の場合だと strtok()には向いていないかも しれませんね。 コロンで分けるとこんなふうに↓ 分かれてしまいますから。 ---------- 日付 2004/02/02 17時30分 体重 91.0 体脂肪率 21.0 除脂肪体重 71.9 ---------- > やってみたんですが漢字が入っていると難しいようです。 私の環境(winXP cygwin gcc3.3.1)で 以下のようにやってみたらうまくいきました。 とりあえず参考まで。 #define BUFFSIZE 256 #define N 4 /* 除体脂肪体重は4番目だから */ char buff[BUFF_SIZE]; FILE *fp = fopen(filename, "r"); /* 1行読み込んで */ while (fgets(buff, BUFF_SIZE, fp) != NULL) { char *temp; double weight; int i; /* コロンでトークン分割して */ strtok(buff, ":"); for (i = 0; i < N - 1; ++i) temp = strtok(NULL, ":"); /* 数値に変換 */ weight = strtod(temp, NULL); printf("weight (except fat): %.2f\n", weight); } fclose(fp);

ebinamori
質問者

お礼

再度回答ありがとうございます。 漢字ではなくコロンで移動していくようにしているのですね。 これでもうまくいきました。 いろいろな角度からアプローチできて とてもいい経験になりました。 ありがとうございます。

  • jagd-doga
  • ベストアンサー率31% (14/45)
回答No.6

fgets()でファイルを1行ずつ読み出して、 strstr()でポインタを「除脂肪体重」まで移動させて、 sscanf()で数値を読み出せばOKだと思います。 ●strstr()を使えば「strlen()を使って4文字分戻る」よりもシンプルなソースを書けます。 参考までにこんな感じです。   char buf[0x80]; /* 読み出し領域  */   char *ptr;    /* ワークポインタ */   float weight;   /* 除脂肪体重値  */   /* ファイルを1行ずつファイルの最後まで読み出す */   while( fgets(buf,sizeof(buf),fp) != NULL)   {     /* fgets()で読み出した文字列から"除脂肪体重"を検索 */     ptr = strstr(buf, "除脂肪体重");     /* "除脂肪体重"を検出した場合 */     if( ptr != NULL )     {       /* 数値を読み出す */       sscanf(ptr, "除脂肪体重:%e", &weight);     }   } ●すみません。sscanfって小数を読み出せるのか、小数を使う習慣が無いので自信ありません。 自分なら整数部分と小数点以下を別々の変数(int型)で扱うかも・・・

ebinamori
質問者

お礼

アドバイスありがとうございます。 この質問をしてみておそらく基本的なものであろう 関数をほとんど知らないのだと気づかされました。 試してみたところうまく行きました。 ありがとうございます。

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.5

文字列を実数に直す関数に strtof() と strtod() があったと思います。 使い方はこんなかんじ↓。 #include <stdlib.h> char *str = "69.4"; float f = strtof(str, NULL); /* floatにする場合 */ double d = strtod(str, NULL); /* doubleにする場合 */

ebinamori
質問者

お礼

アドバイスありがとうございます。 新たな知識を得ることができてうれしいです。

  • HOGERA3
  • ベストアンサー率35% (50/139)
回答No.3

各項目がコロンで区切られてるようですから、 strtokを使うという方法もありますね。 ファイルからfgetsで読み込んで それをstrtokで分解。そして数値に変換。

ebinamori
質問者

お礼

回答ありがとうございます。 strtokという関数をはじめて知りました。 これなら楽に作れそうです。

ebinamori
質問者

補足

やってみたんですが漢字が入っていると難しいようです。

  • asuca
  • ベストアンサー率47% (11786/24626)
回答No.2

strlenでも文字列の長さをはかってそこからマイナス4文字分をポインタを使ってほかの変数に代入して数値変換すればいいかと思うんですが。

ebinamori
質問者

お礼

回答ありがとうございます。 これで解決できそうです。

  • mi-si
  • ベストアンサー率35% (200/567)
回答No.1

1行ごとに文字列を解析して、構造体に放り込みます。 除脂肪体重だけ必要な場合は変数1個で良いです。 上から3つ取り出す場合、 1.ソートしてから上から3つを抜き出す。 2.最初から多い3つだけを残す。 2の場合は、 weightdata,nowは除脂肪体重を格納する配列と変数 File *fp; double now,weightdata[3]; weightdata[0] = 0.0; //1st weightdata[1] = 0.0; //2nd weightdata[2] = 0.0; //3rd ... do { now = parsedata(fp); /* EOFの場合はマイナスを返す */ if (now > weightdata[0]) { weightdata[2] = weightdata[1]; weightdata[1] = weightdata[0]; weightdata[0] = now; } else if (now > weightdata[1]) { weightdata[2] = weightdata[1]; weightdata[1] = now; } else if now > weightdata[2]) { weightdata[2] = now; } } while (now >= 0.0);

ebinamori
質問者

お礼

アドバイスありがとうございます。 質問の仕方だが悪かったのですが 数値を取り出せれば上位3つを選び出すことは 自分でもわかるのですが文字列の解析の仕方がわかりません。 できればもう一度アドバイスよろしくお願いします。

関連するQ&A