C言語関係掲示板

過去ログ

No.1121 ファイルにデータが欠如していた場合ずれることなく読み取る方法 

[戻る] [ホームページ]
No.1990

ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/06/11 16:36:28)


いつもお世話になっております。

ファイルにデータが欠如していた場合ずれることなく指定した場所に
数値を読み取る方法を教えていただけないでしょうか。

ファイルには
データ取得時間 データ1 データ2 (*)
という形式で書かれてあります。
(*)が.logファイルに数千行かかれてあります。
データ1、データ2には実数値が入ってあります。
ここで、作成したプログラムを抜粋しますと

FILE *fp1;
while(EOF != fscanf(fp1,"%d %lf %lf\n",&log[i].time ,&log[i].data1,&log[i].data2))
i++;

log[i]:構造体を用いています。
となります。

fp1でファイルを指定し、
log[i].time にデータ取得時間を、
log[i].data1にデータ1を、
log[i].data2にデータ2を格納できるようにして、
ファイルの最後まで数値を読み取るようにしてあります。

ここまでは問題なかったのですが、
実はこのデータファイル(正式にはログファイル)には
データ1、データ2がときどき欠如されてあることが分かりました。
データ取得時間 データ1 データ2 のはずが
データ取得時間            となり、
空白になってあります。
【問題点】
while(EOF != fscanf(fp1,"%d %lf %lf\n",&log[i].time ,&log[i].data1,&log[i].data2))
だと空白をとばして次の数値を読み取るため、log[i].data1、log[i].data2に別の値が入ってしまいます。

対策として考えたことですが、空白は0.0にするということにして、
 while(EOF != fscanf(fp1,"%d ",&log[i].time))
 {
   fscanf(fp1,"%lf %lf\n",&log[i].data1,&log[i].data2))
   {
    if ( (char)log[i].data1 == NULL ) 
    {
     log[i].data1 = 0.0;
    }
    if ( (char) log[i].data2== NULL )
    {
     log[i].data2 = 0.0;
    }
   }
i++;
 }
としたのですが、症状が変わりませんでした。
空白は0.0にして数値を適切に読むことを
ファイルの最後まで行なうためにはどこを工夫すればよろしいでしょうか。
ご教授のほどよろしくお願い致します。

【環境】
OS:Windows2000
VC++6.0を利用していますがC言語を勉強中。

余談ですが・・・
値が全て入ってあるという前提でプログラムを作成していましたが
その保障があるわけではなく、汎用性をもたさないといけない
と改めて思いました。
ファイルを扱う際は
if( ( fp1 = fopen("in.log","r") ) == NULL)
{
  printf("in.log is not here. \n");
  return 0;
}
とファイルが無い場合も考えないといけないことは
知っていますが、いろいろなケースの洗い出しが不足しておりました。

>qsortの理解とお返事も急ぎ進捗します。すみません。


No.1991

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---tetrapod(2004/06/11 16:44:19)


1行のデータを読み取り、それを分析するほうがいいでしょう。
fscanf を直接使わず fgets+sscanf に修正。

実際問題として、データ 0.0 が入っていて大丈夫ですか?
むしろデータ不在に(その行は無視)するほうがよいと思う。



No.1992

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/06/11 17:18:02)


tetrapod殿
早速のご返答ありがとうございます。

>実際問題として、データ 0.0 が入っていて大丈夫ですか?
>むしろデータ不在に(その行は無視)するほうがよいと思う。
言葉足らずで申し訳ありません。
このデータ1、2は後で計算で使うので数値が必要です。
場合分けも後で行なうので0.0が入っても大丈夫です。

>1行のデータを読み取り、それを分析するほうがいいでしょう。
>fscanf を直接使わず fgets+sscanf に修正。
ありがとうございます。
お恥ずかしい話ですがfgetsを使ったことがありません。

今調べたところ、
char *fgets(char *line , int maxline, FILE *fp)
ファイルからの入力行が文字配列lineへ読み込まれ、
このとき読み込まれる文字はmaxline−1個ということがわかりました。
(参照:プログラミング言語C 第2版 p200)

一旦lineに取得データ時間、データ1、データ2をひとくくりに収め
sscanfで分けるということでよろしいでしょうか??

こんな感じで試してみます。
while(EOF != *fgets(char *line[i], 50,*fp1)
i++;

while(EOF != sscanf(line, "%d %lf %lf",&log[i].time ,&log[i].data1,&log[i].data2)))
/* ここにデータが空白だったら0.0を入れる文を記載 */
i++;



No.1993

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---おでん(2004/06/11 18:36:46)


>>
>こんな感じで試してみます。
>while(EOF != *fgets(char *line[i], 50,*fp1)
>i++;
>

char *line[i]・・・書き方が変です。
fgets(),line[i]やfp1に'*'が付いているのはなぜでしょう?

>while(EOF != sscanf(line, "%d %lf %lf",&log[i].time ,&log[i].data1,&log[i].data2)))
>/* ここにデータが空白だったら0.0を入れる文を記載 */
>i++;

int i ;
char line[50] ;

for( i= 0 ; fgets( line, sizeof line, fp1 ) != EOF ; i++ ){
    if( sscanf(line, "%d %lf %lf",&log[i].time, &log[i].data1, &log[i].data2 ) == 3 ){
        /* データ正常時の処理    */
    }else{
        /* データ欠落時の処理    */
    }
}



こんな感じでしょうか。


No.1995

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---おでん(2004/06/11 19:23:14)


ふと思ったのですが、
>(*)が.logファイルに数千行かかれてあります。

全てのデータをメモリ展開する必要があるのでしょうか?
・・・なんだかの集計をするだけなら、配列に読み込む必要は無いのでは?

※ 外していたらごめんなさい。


No.1996

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/06/11 21:02:14)


おでん殿
アドバイスありがとうございます。

>全てのデータをメモリ展開する必要があるのでしょうか?
>・・・なんだかの集計をするだけなら、配列に読み込む必要は無いので
>は?
メモリ展開する理由は(次のステップの話になりますが)
データを加工してグラフ化するために用いるからです。
時間範囲を指定しグラフ表示させるために配列に入れています。

>char *line[i]・・・書き方が変です。
>fgets(),line[i]やfp1に'*'が付いているのはなぜでしょう?
ご指摘ありがとうございます。
使い方が間違っておりました。参考書に使い方が載ってありました。
(参考書:今さら聞けないCの基礎 p213,214)

プログラムを作成してみましたが、エラーがでます。
char line[256];
  while( fgets(line, 256, fp1) != EOF)
  {
    if( sscanf(line, "%d %lf %lf",&log[i].time, &log[i].data1, &log[i].data2 ) == 3 )
    {
    }
    else
    {
     log[i].data1 = 0.0;
     log[i].data2 = 0.0;
    }
   i++; 
  }
すると、コンパイル時にエラーが2つ出ました。貼り付けます。

error C2446: '!=' : 'const int' 型から 'char *' 型への変換ができません。整数型からポインタ型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。
error C2040: '!=' : 'char *' は 'const int' と間接操作のレベルが異なります。cl.exe の実行エラー

おでん殿に作っていただいたソースを貼り付けてみたものの同じ
エラーがでました。

!=EOF 
が原因かと思います。==NULL だとコンパイルできたためです。
この使い方はできないのでしょうか??もう少し調べてみます。


No.1997

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---おでん(2004/06/11 21:50:08)


>
>おでん殿に作っていただいたソースを貼り付けてみたものの同じ
>エラーがでました。
>
>!=EOF 
>が原因かと思います。==NULL だとコンパイルできたためです。
>この使い方はできないのでしょうか??もう少し調べてみます。

ごめんなさい m(_"_)m

fgets()は、戻り値がchar *でした。
NULLで正解です。

!=EOFを!=NULLとしてください。


No.1998

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/06/11 22:30:46)


おでん殿
ご指導ありがとうございます。

>fgets()は、戻り値がchar *でした。
>NULLで正解です。
>
>!=EOFを!=NULLとしてください。
はい。おかげさまでうまくいきました。
EOFってconst int型だったんですね。勉強になりました。
ありがとうございます。


No.2005

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---NykR(2004/06/13 15:00:29)


>EOFってconst int型だったんですね。勉強になりました。
>ありがとうございます。

EOFは負の値をもつ整数定数式に展開されるマクロです。定数式が修飾型をもつことはないので、EOFはconst int型ではなくint型です。

# constというのは変更できない“オブジェクト”のことであって定数のことではない


No.2161

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/06/25 02:27:25)


NykR殿
ご指摘ありがとうございます。誤解したまま理解するところでした。

>EOFは負の値をもつ整数定数式に展開されるマクロです。定数式が修飾型をもつことはないので、EOFはconst int型ではなくint型です。
>
># constというのは変更できない“オブジェクト”のことであって定数のことではない

調べてみました。
・stdio.hの中をみました。
#define EOF (-1)
と書かれてありました。
・私の参考書にも載ってありました。
(参照:プログラミング言語C 第2版 p185)
ここまでは理解できました。

ここで、確認したいことと教えていただきたいことがあります。
自分で使ったことがない単語ということもあり、
”整数定数式に展開されるマクロ”の”マクロ”と
“オブジェクト”の意味が分かりません。

調べてみたところ、
マクロ…プログラムのコンパイル以前に決められた仕組みに従って別の文字に変換する機能(参照:今さら聞けないCの基礎 p143)
ということでしたが、よろしいでしょうか。

また、“オブジェクト”とは名前付きのメモリ領域と
(参照:プログラミング言語C 第2版 p240)
書かれてありましたが私の理解力では文面と直結しません。
この意味であっておりますでしょうか?

ご協力なにとぞよろしくお願い致します。


No.2162

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ニタチ(2004/06/25 09:04:17)


>マクロ…プログラムのコンパイル以前に決められた仕組みに従って別の文字に変換する機能(参照:今さら聞けないCの基礎 p143)
>ということでしたが、よろしいでしょうか。

 はい、それでいいと思います。


>また、“オブジェクト”とは名前付きのメモリ領域と
>(参照:プログラミング言語C 第2版 p240)
>書かれてありましたが私の理解力では文面と直結しません。

 名前付きメモリ領域、変数のことですね。


No.2178

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/06/28 00:07:50)


ニタチ殿
ご返答ありがとうございます。

>名前付きメモリ領域、変数のことですね。
やっと意味が理解できました。


No.2179

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---YuO(2004/06/28 00:58:45)


混ぜっ返すようですが……。


>>また、“オブジェクト”とは名前付きのメモリ領域と
>>(参照:プログラミング言語C 第2版 p240)
>>書かれてありましたが私の理解力では文面と直結しません。
> 名前付きメモリ領域、変数のことですね。

オブジェクトが変数であるとは限りませんよ。

mallocで割り付けられたオブジェクトには当然名前は付いていませんし,
配列の一部であるオブジェクトにも名前は付いていません。
なので,「名前付きメモリ領域」という表現がそもそも間違っている,ということになります。


ちなみに,JISの定義は下の通り。
>その内容によって,値を表現することができる実行環境中の記憶域の部分。

非常に簡単に言うと,何らかの形でアクセスできる,
それ自身が値をもつもの,と言えばよいのでしょうか。
#整定数などはアクセスできないからオブジェクトではない。
#関数自身は値を持たないので関数はオブジェクトではない。


No.2375

Re:ファイルにデータが欠如していた場合ずれることなく読み取る方法を教えていただけませんでしょうか。
投稿者---ピヨピヨ(2004/07/23 16:41:41)


YuO殿
ご意見ありがとうございます。

>非常に簡単に言うと,何らかの形でアクセスできる,
>それ自身が値をもつもの,と言えばよいのでしょうか。
例を出していただいたのでわかりやすいです。
名前がついているものもあればついていないものもあるということですね。

>混ぜっ返すようですが……。
どうかご遠慮なくご意見していただければと思います。
よろしくお願い致します。