• 締切済み

C言語 エラーチェックについて

初めまして。分からないところがあったので質問させていただきます。 以下のプログラムは引数から値を取得し、その値で生データの切り出しを 行うプログラムです。 read関数のところなのですが、argv[1]に格納されたファイル(パス名)が0byteでもエラーが出力されずに、コンパイルされてしまいます。 どうすればよいのでしょうか? さらに、上司にreadとwriteにエラーチェックのメッセージをつけろ。と言われたのですが、どうやれば良いのかよく分かりませんでした。if()~とすれば良いのでしょうか?初心者なので分かりにくい質問かと思いますが、どうぞよろしくお願いします。 #pragma warning ( disable : 4996 ) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <io.h> #include <sys/stat.h> #define ONESEGSIZE 2048 void main ( argc, argv ) int argc; char *argv[]; { int fd, fd2; // ファイルハンドル int segment; // 列数 int raw_n; // 切り出す生データの数 int tviews; // 総ビュー数 int start_view; // 切り出し開始ビュー int size_view; // 切り出しサイズ int pitch_view; // 切り出しピッチ char *Rawdivit; // コマンド char *raw_file; // 生データファイル名 char *outraw_file; // 生データ出力ファイル名 char *mem; // メモリ変数 /* パラメータの個数チェック */ if ( argc != 9 ) { printf( "usage : Rawdivit raw_file outraw_file segment raw_n" " tviews start_view size_view pitch_view \n" ); exit ( 1 ); } /* 引数の取得char型 */ Rawdivit = argv[0]; raw_file = argv[1]; outraw_file = argv[2]; /* 引数の取得int型 */ segment = atoi ( argv[3] ); raw_n = atoi ( argv[4] ); tviews = atoi ( argv[5] ); start_view = atoi ( argv[6] ); size_view = atoi ( argv[7] ); pitch_view = atoi ( argv[8] ); /* 生データファイルオープン */ fd = open ( raw_file, O_RDONLY | O_BINARY ); if ( fd == -1 ) { printf ( "Fileopen error : read\n" ); exit ( -1 ); } /* 生データ読み込み用メモリ確保 */ mem = ( char * ) malloc ( ONESEGSIZE * segment * size_view ); // 単位 = byte if ( mem == NULL ) { printf ( "Memorysecure error\n" ); exit ( -1 ); } /* 切り出し開始位置までファイルポインタをシーク */ lseek ( fd, ONESEGSIZE * segment * start_view, SEEK_SET ); /* 切り出しサイズ分読み込み */ read ( fd, mem, ONESEGSIZE * segment * size_view ); /* 出力ファイルオープン */ fd2 = open ( outraw_file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE ); if ( fd2 == -1 ) { printf ( "Fileopen error : write\n" ); exit ( -1 ); } /* 読み込んだデータを出力ファイルに書き込み */ write ( fd2, mem, ONESEGSIZE * segment * size_view ); /* メモリの開放 */ free ( mem ); /* ファイルクローズ */ close ( fd ); close ( fd2 ); exit ( 0 ); }

みんなの回答

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★回答者 No.3 です。 ・数値が違う理由は、他のエラー場所で『exit( -1 );』にしているので分けただけ。  同じ値を返してもエラー判定できないため、-2 という数値で分けたのです。  回答者 No.4 さんのアドバイスも参考にして下さい。 ・なお、-1 の場合は OS 側には 255 の値が返され、-2 では 254 という数になります。  分かりやすく記号定数で定義することをお勧めします。  下にそのサンプルを載せます。 サンプル: /* エラー定数の定義 */ #define ERR_SUCCESS (0) // 正常 #define ERR_OPEN (-1) // オープンエラー #define ERR_READ (-2) // 読み込みエラー #define ERR_MEMORY (-3) // メモリ不足エラー int main( int argc, char *argv[] ) ←この1行に定義を変更しましょう。外に書くのは古い形式です。注意! {   :  宣言部   :  /* 生データファイルオープン */  if ( (fd = open(raw_file,O_RDONLY|O_BINARY)) == ERR_OPEN ){   printf( "Fileopen error : read\n" );   exit( ERR_OPEN ); ←(1)  }  /* 生データ読み込み用メモリ確保 */  mem = (char *)malloc( ONESEGSIZE * segment * size_view ); // 単位 = byte  if ( mem == NULL ){   printf( "Memorysecure error\n" );   exit( ERR_MEMORY ); ←(2)  }  /* 切り出し開始位置までファイルポインタをシーク */  lseek( fd, (ONESEGSIZE * segment * start_view), SEEK_SET );    /* 切り出しサイズ分読み込み */  if ( read(fd,mem,(ONESEGSIZE * segment * size_view)) < 0 ){   printf( "切り出しサイズでエラーが発生しました。" );   exit( ERR_READ ); ←(3)  }   :  出力ファイルも同じ要領で記述   :  return( ERR_SUCCESS ); ←(4) } 解説: ・ヘッダ部の『#define』でエラー定数を定義しています。  ここの数値は、私が勝手に付けていますので teru3128 さんが自由に決めて変更しても構いません。 ・teru3128 さんのソースでエラーが起こると exit( -1 ); していますが、全部同じ数値ですよね。  これだと OS には全部同じ数値(255)がエラーコードとして返されます。するとエラーが起きたか、  正常に動作したかの判定は出来ますが、エラーの種類は判定できなくなります。このため、エラーの  数値を -1、-2、-3 …と分ければエラーコードでエラーの種類を特定できて便利になります。  上の(1)、(2)、(3)、(4)は記号定数でエラーコードの種類を分けて返しています。 ・このようにエラー数値を分ければ、エラーが起きたときに printf() 関数で表示しないオプションを  つけてもエラーコードで取得して判定できます。→特に他のプログラムから呼び出したときにも  エラーコードを参照できるため便利になりますよ。 ・また、エラーコードは Windows の OS では、if errorlevel 数値 命令という感じでバッチファイルなど  から参照できます。つまり、今作っている プログラム名が read.exe の場合は、  -------------------------------  @echo off   read.exe   if errorlevel 255 goto error1   if errorlevel 254 goto error2   if errorlevel 253 goto error3   echo 正常!   goto end  :error1   echo オープンエラー   goto end  :error2   echo 読み込みエラー   goto end  :error3   echo メモリ不足エラー  :end  -------------------------------  というバッチファイルを作って実行させると、実行後にエラーレベルの数値で正常か、エラーかの判定が  行えることになります。このため、エラーコードを OS に返すのならば、エラーの数値は分けたほうが  便利なことになります。特に DOS コマンドを作成する場合はそのような仕組みを取り入れるべきですね。 ・以上。わかりますか?→バッチファイルとか。エラーレベルとか。

teru3128
質問者

お礼

バッチファイルは存じあげていたのですが、 エラーレベルについては調べて理解することが出来ました。 この仕事は未経験で出来るかかなり不安だったのですが、やりがいもあると 思うので頑張っていこうと思います。 丁寧な回答本当にありがとうございました。 また機会がありましたらよろしくお願いします。

  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.4

>ちなみになぜ戻り値が-2なのでしょうか? >エラーの場合は-1では無いのでしょう? エラー発生時に必ず-1が戻り値になってても、 呼び出したプログラムは何にも判定出来ませんね。 汎用的に作るなら戻り値にも意味を持たせます。 マイナスでエラーと定義すれば、コード番号毎にエラー原因を 分けるのが普通ベストです。

teru3128
質問者

お礼

>>マイナスでエラーと定義すれば、コード番号毎にエラー原因を分ける それは分かりませんでした。何事ももっと深く理解しなくてはいけませんね。 ありがとうございました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★『read』関数の引数は必要ですよ。 ・下のようにします。 /* 切り出しサイズ分読み込み */ if ( read(fd,mem,ONESEGSIZE * segment * size_view) < 0 ){  printf( "切り出しサイズでエラーが発生しました。" );  exit( -2 ); }

teru3128
質問者

お礼

レスありがとうございます。 ちなみになぜ戻り値が-2なのでしょうか? エラーの場合は-1では無いのでしょう? 質問ばかりで申し訳ありません。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> >>エラーを検出したときにメッセージを出すということでよいのでしょうか? > はいそうです。今一記述の仕方がよく分からないです。 何をもってエラーとするかにもよりますが、単に入出力のエラーを返すだけであれば、 if (read(...) < 0) {  fprintf(stderr, ...);  /* ここでreturn, exitまたはabortしてもよい */ } のようにするだけだと思うのですが...

teru3128
質問者

お礼

レスありがとうございます。 if(read(...)<0) のカッコの中には何も入れなくていいんですよね?

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

> read関数のところなのですが、argv[1]に格納されたファイル(パス名)が0byteでもエラーが出力されずに、コンパイルされてしまいます。 ファイルのサイズは、実行時にファイルを調べるまでわからないので、コンパイル時に検出することは原理的に不可能です。 > どうすればよいのでしょうか? どうすることもできません。 実行時にサイズを調べるしかないのでは? > さらに、上司にreadとwriteにエラーチェックのメッセージをつけろ。と言われたのですが、どうやれば良いのかよく分かりませんでした。if()~とすれば良いのでしょうか?初心者なので分かりにくい質問かと思いますが、どうぞよろしくお願いします。 エラーチェックならわかりますが、「エラーチェックのメッセージ」というのが何を期待されているのかよくわかりません。エラーを検出したときにメッセージを出すということでよいのでしょうか?

teru3128
質問者

お礼

レスありがとうございました。 >>エラーを検出したときにメッセージを出すということでよいのでしょうか? はいそうです。今一記述の仕方がよく分からないです。