エラー処理について – プログラミング – Home

通知
すべてクリア

エラー処理について


桂華
 桂華
(@桂華)
ゲスト
結合: 23年前
投稿: 10
Topic starter  

こんばんは。いつもお世話になっています。

ファイルの読み書きエラーをヘルプを見ながら追加したのですが、
エラーが出ていないのにエラーが出力されてしまったりするのです。
未熟者で、コードのどこがおかしいのか分かりません...。
もしよろしければご教授ください。お願いします。

//ファイル読み込み
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);
}
}


引用解決済
トピックタグ
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

if文の評価で読み書きが行われちゃいますけど、意図どおりですか?

int ret;
for( ; ; ){

ret = fputc(mChgData[iCount],fpchgptn);

if( ret == EOF ){
// エラー
}
}

では?


返信引用
桂華
 桂華
(@桂華)
ゲスト
結合: 23年前
投稿: 10
Topic starter  

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);
}


返信引用
Bun
 Bun
(@Bun)
ゲスト
結合: 24年前
投稿: 761
 

>はい、if評価の読み書きで意図とおりです。
>ですが、PAI様のアドバイスであるコードと、元のコードの違いは
>何でしょうか???

ヨコからスンズレイすますま。

PAIさんは

>//ファイルに書き込み
>for(iCount=0; iCount<ilen; iCount++){
> fputc(mChgData[iCount],fpchgptn); // ここでも書き込んでいて
> //書き込みエラー
> if((fputc(mChgData[iCount],fpchgptn))==EOF){ // 更にここでも書き込んでしま
いますよ!いいのですか?

といいたいのでしょう。
これが意図したとおりですか?(^^;


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

ちょっと確認の言葉がまずかったですね、ごめんなさい。

で、エラー処理に関してですが、
12行であることを判別することが難しいのでしょうか?
ファイルを閉じる等の処理が煩雑になるのが難しいのでしょうか?

前者であればこの場合。

int i;
for( i=0 ; i<12 ; i++){

if( fgets(/*・・・*/) == EOF )
break;// エラー、ループから抜ける

// 正常、データのコピー等
// ・・・・・
}

if( i != 12 ){
// エラー、12行でない。
}

とするのがスマートですかね?まあいろんな考え方があるんで、
これが一番だ、とは思いませんけど、

あれ?ぴったりファイルの終端まで読んだときって、
もしかしてEOF返ってきましたっけ?


返信引用
クラフトマン
 クラフトマン
(@クラフトマン)
ゲスト
結合: 24年前
投稿: 72
 

>あれ?ぴったりファイルの終端まで読んだときって、
>もしかして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以外の値が返る。


返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

>fgets関数の戻り値は、読み込んだ文字列へのポインタです。

ほんとだ、何と勘違いしたんだろ。恥ずかしい。
フォローどうもです。


返信引用
桂華
 桂華
(@桂華)
ゲスト
結合: 23年前
投稿: 10
Topic starter  

おはようございます。
レスが大変遅くなって申し訳ありません。

たくさんのアドバイスありがとうございました。
根本的にエラー処理が間違っていたのですね....。

そして、皆様のアドバイスを参考にして以下のコードで
エラー処理を行う事にしました。
もし、ご指摘がありましたらどんどんつっこんでください。

ところで、未だにファイル読み込みの場合のエラー処理の
書き方がよく分かりません。
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);
}


返信引用
クラフトマン
 クラフトマン
(@クラフトマン)
ゲスト
結合: 24年前
投稿: 72
 

実際にファイルに存在する行分を読むのではなく、必ず固定で、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さんが実力者であることは推測していますし、誰でも
勘違いはありますからね。そういった場合は、気付いたものが指摘すれば
いいというのが私の考えです。
後になって言葉足らずの部分があって、気分を害されちゃうかなと心配しま
したが、好意的に受け取ってくれてありがとう。


返信引用
桂華
 桂華
(@桂華)
ゲスト
結合: 23年前
投稿: 10
Topic starter  

クラフトマン様、ご指摘ありがとうございました。
詳しい解説も添えていただき、大変勉強になりました。
また、他にも至らない点が多くあったようで。
きちんとエラー処理も書けない未熟者でお恥ずかしいです...。

ところで、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);
}



返信引用
PAI
 PAI
(@PAI)
ゲスト
結合: 23年前
投稿: 359
 

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
がはいってくれますね。


返信引用
桂華
 桂華
(@桂華)
ゲスト
結合: 23年前
投稿: 10
Topic starter  

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);
}


返信引用
YuO
 YuO
(@YuO)
ゲスト
結合: 24年前
投稿: 252
 

> 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によるクローズに任せればよいです。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました