• ベストアンサー

エラーの意味

このプログラムは、三番目のコマンドライン引数に、 watch が入力されると、画面に文字表示されるはずですが、 おそらく if ( argv [3] == 'a' ) putchar ( c ) のところで、エラーが出ます。 文字列定数は 、1 文字か 2 文字でなければならない ( 関数 main ( int,char * * ) ) ' int ' 型は 、' char * ' 型に変換できない ( 関数 main ( int,char * * ) ) このエラーの意味が解らないのですが、何を伝えたいのか解説をお願いします。 int main(int argc,char *argv[]) { FILE *fp ,*fp1; int c; fp=fopen(argv[1],"r"); if(argv[1]==NULL){ printf("no open"); exit(1); } fp1=fopen(argv[2],"w"); if(argv[2]==NULL){ printf("no open"); exit(1); } while ( ( c=fgetc ( fp ) ) !=EOF ) { fputc ( c , fp1 ) ; if ( argv[3] == ' watch ' ) putchar ( c ) ; }

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

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

>文字列定数は 、1 文字か 2 文字でなければならない ( 関数 main ( int,char * * ) ) 「'」で括られた文字は、文字列ではなく、intの整数です。 char c; c='a'; は char c; c=0x61; と同等です。同様に int i; i='あ'; は int i; i=0x82a0; と同等です。 その為「'」で括られた中には、1文字(半角1文字)か2文字(全角1文字)しか書けません。 つまり if ( argv[3] == 'watch' ) は 「文字列定数は 、1 文字か 2 文字でなければならない」に違反するのでエラーになります。 >' int ' 型は 、' char * ' 型に変換できない ( 関数 main ( int,char * * ) ) 「argv[3]」は「char *型」です。一方「'~'」は上記で書いた通り「int型」です。 コンパイラは「char *型」と「int型」を比較するよう指示されたので、int型をchar *型に昇格しようとしました。でも「'int' 型は 、'char *' 型に変換できない」のでエラーになります。 質問者さんがやろうとした比較 >if ( argv[3] == 'watch' ) は if ( "abcdef" == 0x7761 ) と同等です。こう書けば「明らかに間違ってる」のが判りますね? では、比較する定数を以下のように「'」ではなく「"」で括ればと思うでしょうが、これも間違いです。 if ( argv[3] == "watch" ) この比較は「argv[3]が存在するメモリのアドレス」と「文字列定数"watch"が置かれているメモリのアドレス」を比較するので「常に等しくない」と評価されます。例えargv[3]に「watch」が入っていても「等しくない」のです。 なお、蛇足ですが、 if ( "watch" == "watch" ) は「等しくないか、等しいか、判らない」です。右辺の文字列定数"watch"が置かれているメモリのアドレスと、左辺の文字列定数"watch"が置かれているメモリのアドレスは、同じアドレスになるか違うアドレスになるか、厳密には決まっていません。 なぜなら「内容が同一の複数の文字列定数は、実体を1つにまとめてメモリ消費を抑えても良いし、それぞれ別々の実体を持っても良い」と言う事になっているからです。 質問者さんがやろうとした比較を踏襲して修正すると if (( argv[3][0] == 'w' ) && ( argv[3][1] == 'a' ) && ( argv[3][2] == 't' ) && ( argv[3][3] == 'c' ) && ( argv[3][4] == 'h' ) && ( argv[3][5] == '\0' )) となります。 しかし、普通はこんな書き方はせず、 if (strcmp(argv[3],"watch") == 0) と書きます。 質問者さんは「文字定数」と「文字列定数」が区別できてません。 また、argvが「文字列へのポインタが集まった配列である」と言う事も理解できてません。

startover
質問者

お礼

すばやい回答ありがとうございます。 すごく詳しい回答ありがとうございます! よく解りました! 本当にありがとうございました!

その他の回答 (3)

回答No.4

直接ご質問の内容ではないのですが…… fp=fopen(argv[1],"r"); if(argv[1]==NULL){ ファイルオープンの失敗は、if(fp == NULL) で判定すべきです。 fopen() は、ファイルオープンに失敗したときに NULL を返すので。 (argv[1] は、元のコマンドライン引数の内容をポイントしています) また、argv[1] や argv[2] や argv[3] が必ず有効な文字列をポイントしている保証はないので、argc の値をチェックした方が安全ではあります。 ちなみに、argv[0] は、必ず有効な文字列をポイントしていることになっています。

startover
質問者

お礼

すばやい回答ありがとうございます。 ファイル処理の本当に、作法勉強になります。 どうもありがとうございました!

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.2

No.1です。初歩的なミスを犯しました。 if ( strcmp(argv[3],"watch") = 0 ) ではなく if ( strcmp(argv[3],"watch") == 0 ) です。

  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

if ( argv[3] == ' watch ' ) が誤りです。 if ( strcmp(argv[3],"watch") = 0 ) とすればいいと思います。 ・文字列は''でなく""で囲みます。 ・そもそもCには文字列型というのはありません。文字列はcharの配列として扱われます。 ・そのため、文字列の結合や比較などは、上記のような文字列操作関数を使う必要があります。 C++になると、またちょっと変わってきますが。 あとお節介ですが、 ・このあとちゃんとfclose()ややっていますか? ・エラーメッセージはprintf()でなくfprintf(stderr,"…"))で標準エラー出力に出した方がよいでしょう

startover
質問者

お礼

すばやい回答ありがとうありがとうございます。 fclose( )忘れてました~ すごく解りやすい解説をありがとうございました!