こんばんは。いつもお世話になっています。
ファイルの読み書きエラーをヘルプを見ながら追加したのですが、
エラーが出ていないのにエラーが出力されてしまったりするのです。
未熟者で、コードのどこがおかしいのか分かりません...。
もしよろしければご教授ください。お願いします。
//ファイル読み込み
for(iCount=0; iCount<=11; iCount++){
fgets(cData, 64, fpk);
//エラー処理
if((fgets(cData, 64, fpk))==NULL){
#ifdef DEBUG
printf(csvsep:ファイル読み込みエラー\n);
#endif
exit(1);
}
}
//ファイルに書き込み
for(iCount=0; iCount<ilen; iCount++){
fputc(mChgData[iCount],fpchgptn);
//書き込みエラー
if((fputc(mChgData[iCount],fpchgptn))==EOF){
#ifdef DEBUG
printf(csvsep:ファイル書き込みエラー\n);
#endif
exit(1);
}
}
if文の評価で読み書きが行われちゃいますけど、意図どおりですか?
int ret;
for( ; ; ){
ret = fputc(mChgData[iCount],fpchgptn);
if( ret == EOF ){
// エラー
}
}
では?
PAI様、早速のアドバイスありがとうございました。
はい、if評価の読み書きで意図とおりです。
ですが、PAI様のアドバイスであるコードと、元のコードの違いは
何でしょうか???
大変失礼な質問で申し訳ありません...。
また、下記のコードはData配列はData[12][24]と宣言しており、
12行のファイルを読み込んでいるのですが、もしそのファイルが
12行以外の場合にエラーを出したいのですが、書き方が分からず
困っています...。
追加質問になってしまい、大変申し訳ないのですがアドバイスを
お願いできませんでしょうか??
エラー文の書き方が分かっていないようです。
勉強しなおしたいと思います。
//ファイル読み込み
for(iCount=0; iCount<=11; iCount++){
fgets(cData, 64, fp);
//配列に格納
sprintf(tmpData[iCount], %s, cData);
}
//エラー処理
if((feof(fp))==0){
#ifdef DEBUG
printf(csvsep:異常エラー\n);
#endif
exit(1);
//ファイルクローズ
fclose(fp);
}
>はい、if評価の読み書きで意図とおりです。
>ですが、PAI様のアドバイスであるコードと、元のコードの違いは
>何でしょうか???
ヨコからスンズレイすますま。
PAIさんは
>//ファイルに書き込み
>for(iCount=0; iCount<ilen; iCount++){
> fputc(mChgData[iCount],fpchgptn); // ここでも書き込んでいて
> //書き込みエラー
> if((fputc(mChgData[iCount],fpchgptn))==EOF){ // 更にここでも書き込んでしま
いますよ!いいのですか?
といいたいのでしょう。
これが意図したとおりですか?(^^;
ちょっと確認の言葉がまずかったですね、ごめんなさい。
で、エラー処理に関してですが、
12行であることを判別することが難しいのでしょうか?
ファイルを閉じる等の処理が煩雑になるのが難しいのでしょうか?
前者であればこの場合。
int i;
for( i=0 ; i<12 ; i++){
if( fgets(/*・・・*/) == EOF )
break;// エラー、ループから抜ける
// 正常、データのコピー等
// ・・・・・
}
if( i != 12 ){
// エラー、12行でない。
}
とするのがスマートですかね?まあいろんな考え方があるんで、
これが一番だ、とは思いませんけど、
あれ?ぴったりファイルの終端まで読んだときって、
もしかしてEOF返ってきましたっけ?
>あれ?ぴったりファイルの終端まで読んだときって、
>もしかしてEOF返ってきましたっけ?
fgets関数の戻り値は、読み込んだ文字列へのポインタです。
1文字も読めなかった場合に、NULLが返ってきます。(EOFは返ってきません)
1文字も読めなかった場合とは、既に終端(EOF)に達している状態で、fgetsを呼
び出したか、エラーが発生したかです。
ですから、読み込みの終了をfgets関数の戻り値をNULLかどうかで判定するのは、
間違いではありませんが、NULLであった場合にエラーと判断するのは間違いです。
ferror()または、feof()で判定する必要があります。
因みに、fgets()とfeof()の戻り値の関係は、下記のようになります。
1)残り15文字で、最大10文字読もうとした。
fgets() --- 読み込めたので、読み込んだ文字列へのポインタが返る。
feof() ---- 終端に達していないので、0が返る。
2)残り5文字で、最大10文字読もうとした。
fgets() --- 読み込めたので、読み込んだ文字列へのポインタが返る。
feof() ---- 終端に達したので、0以外の値が返る。
3)残り0文字で、最大10文字読もうとした。
fgets() --- 読み込めないので、NULLポインタが返る。
(エラーではないし、この呼び出しは何の問題もない)
feof() ---- 終端に達しているので、0以外の値が返る。
>fgets関数の戻り値は、読み込んだ文字列へのポインタです。
ほんとだ、何と勘違いしたんだろ。恥ずかしい。
フォローどうもです。
おはようございます。
レスが大変遅くなって申し訳ありません。
たくさんのアドバイスありがとうございました。
根本的にエラー処理が間違っていたのですね....。
そして、皆様のアドバイスを参考にして以下のコードで
エラー処理を行う事にしました。
もし、ご指摘がありましたらどんどんつっこんでください。
ところで、未だにファイル読み込みの場合のエラー処理の
書き方がよく分かりません。
12行読み込みの場合と同じにすればよいのでしょうか?
まだコードの理解が完全にできていなくて質問するのも
おこがましいのですが、どうかよろしくお願いします。
書き込みのエラー処理
FILE fp;
int iCount,iput;
//ファイルに書き込み
for(iCount=0; iCount<ilen; iCount++){
iput=fputc(mData[iCount],fp);
//書き込みエラー
if(iput==EOF){
#ifdef DEBUG
printf(ファイル書き込みエラー\n);
#endif
exit(1);
fclose(fp);
}
}
12行読み込みのエラー処理
FILE fp;
int iCount;
//ファイル読み込み
for(iCount=0; iCount<=11; iCount++){
fgets(cData, 64, fp);
//配列に格納
sprintf(tmpData[iCount], %s, cData);
}
//エラー処理
if((feof(fp))!=0){
#ifdef DEBUG
printf(読み込み異常エラー\n);
#endif
exit(1);
//ファイルクローズ
fclose(fp);
}
実際にファイルに存在する行分を読むのではなく、必ず固定で、11行
読み出したいんですね?
であれば、理由にかかわらず、fgets関数がNULLを返してきたらまずい
わけだから、
for(iCount=0; iCount<=11; iCount++){
if (fgets(cData, 64, fp) == NULL) {
if (feof()) {
/* 行数が足りなかった場合のエラー */
}
else {
/* 読み込みエラー */
}
}
//配列に格納
sprintf(tmpData[iCount], %s, cData);
}
とすべきでは?
さらに言えば、
1) 1行の文字数が64文字を超えていた場合、fgets関数は64文字ずつしか
読まないので、2行にわけて読むことになるがよいのか。
2) 実際の行数が11行より多い場合は、正常終了するがよいのか。
3) 11,64などのハードコーディングは避けるべきでは?
また、掲載されたコードでは、書き込み側で、エラー発生時にしかfclose
していませんが、fcloseはきちんとしなければなりません。
それと、書き込みデータは、バッファリングされているはずなので、fclose
した時点(厳密には、fclose内でバッファをフラッシュしようとした時点)で
エラーとなる可能性があります。この点も注意しなければなりません。
>ほんとだ、何と勘違いしたんだろ。恥ずかしい。
>フォローどうもです。
過去の発言から、PAIさんが実力者であることは推測していますし、誰でも
勘違いはありますからね。そういった場合は、気付いたものが指摘すれば
いいというのが私の考えです。
後になって言葉足らずの部分があって、気分を害されちゃうかなと心配しま
したが、好意的に受け取ってくれてありがとう。
クラフトマン様、ご指摘ありがとうございました。
詳しい解説も添えていただき、大変勉強になりました。
また、他にも至らない点が多くあったようで。
きちんとエラー処理も書けない未熟者でお恥ずかしいです...。
ところで、while文の読み込みのエラー処理を書いたのですが
←の部分で「'==' : 間接参照のレベルが 'int ' と 'void *' で異なっています。」
とエラーが出てきます。
根本的に間違っているような気がするのですが...。
つたないデバッグをしてみたのですが、やはり書き方の問題だと思います。
エラー処理は以外と難しいですね...。
本当に何回も質問して申し訳ないのですが、アドバイスをいただけませんでしょうか?
char cget;
//c_systpndataファイル読み込み
while (cget=fgets(cData, 128, fp) != NULL)
{
if(cget==NULL)←ここでエラーが出ます。
{
// 読み込みエラー
#ifdef DEBUG
printf(読み込みエラー\n);
#endif
exit(1);
//ファイルクローズ
fclose(fp);
}
・
・
・
fgetsの戻り値はchar*だから、char*で受けなきゃいけませんよね。
で、そうすると、どうしてコレ
char cget;
while (cget=fgets(cData, 128, fp) != NULL);
でエラーがでないか、という話になりますが、
これはコンパイラには
char cget;
while ( cget=( fgets(cData, 128, fp) != NULL ) );
こう見えてしまうからです。
・・・なんか微妙ですが、一応意図どおりに
NULLだったら 0
NULLじゃなかったら 1
がはいってくれますね。
PAI様ご指摘ありがとうございます。
そうですね、fgetの戻り値はchar*型でした。
うっかりしておりました。
結局、読み込みエラーの処理は以下のようにしました。
PAI様が書かれた通り、なんだか微妙です...。^^;
デバッグしてcgetの値を見てみると「1'・'」となっていたのが
気になる所ですが。
う~ん、もうちょっとスマートなやり方を考えてみます。
もしよろしければまた何かアドバイスをしてやってください。
char cget;
//c_systpndataファイル読み込み
while (cget=fgets(cData, 128, fp) != NULL)
{
if(cget==0)
{
// 読み込みエラー
#ifdef DEBUG
printf(読み込みエラー\n);
#endif
exit(1);
//ファイルクローズ
fclose(fp);
}
> while (cget=fgets(cData, 128, fp) != NULL)
> {
> if(cget==0)
whileループが実行されるのは,cgetが非0の時です。
#今回は常に0か1。ループ実行時,cgetは1のみ。
なので,このif文は常に偽となります。
whileから抜けたところでferrorやfeofを使ってエラーかEOFなのかを判別するとよいかと。
#cget変数は不要になる。
あと,
> exit(1);
> //ファイルクローズ
> fclose(fp);
exitの後の文は実行されませんが……。
fcloseはexitの前に実行するか,exitによるクローズに任せればよいです。