• ベストアンサー

プログラムの関数化

皆様に助けていただき、なんとかコーディング出来たのですが、関数化したいと思います。アドバイスお願いします。 int overflow_check1(); int overflow_check2(); int overflow_check3(); int overflow_check4(); int lop; // 左のオペランドに入力する値 int rop; // 右のオペランドに入力する値 int result; // 計算結果 int mod; // 除算の余り int max = INT_MAX; // 表現可能な最大値 int min = INT_MIN; // 表現可能な最小値 char *check; // 変換不能な文字を格納 char op; // 入力する演算子 int main ( int argc, char *argv[] ) { /* 引数の個数チェック */ if ( argc != 4 ) { printf ( "usage : %s lop op rop\n", argv[0] ); exit ( 0 ); } /* 引数を取得して整数型に変換 */ lop = atoi ( argv[1] ); rop = atoi ( argv[3] ); /* 引数の取得 */ op = ( argv[2][0] ); /* startが整数であるか文字であるかのチェック */ lop = strtol ( argv[1], &check, 10 ); if ( errno != ERANGE ) { if ( *check != '\0' ) { printf ( "error : 整数を入力して下さい。\n" ); exit ( -1 ); } /* startに範囲を超えた値を入力した場合 */ } else { printf( "error : 整数型の範囲を超えました。\n" ); exit( -1 ); } /* endが整数であるか文字であるかのチェック */ rop = strtol ( argv[3], &check, 10 ); if ( errno != ERANGE ) { if ( *check != '\0' ) { printf ( "error : 整数を入力して下さい。\n" ); exit ( -1 ); } /* endに範囲を超えた値を入力した場合 */ } else { printf( "error : 整数型の範囲を超えました。\n" ); exit( -1 ); } /* argv[2]が2文字以上の場合 */ if ( strlen ( argv[2] ) >= 2 ) { printf ( "error : 演算子を正しく入力して下さい。\n" ); exit ( -1 ); } /* argv[2]に入力された演算子が'+'の場合 */ switch ( op ) { case '+': overflow_check1(); result = lop + rop; break; /* argv[2]に入力された演算子が'-'の場合 */ case '-' : overflow_check2(); result = lop - rop; break; /* argv[2]に入力された演算子が'*'の場合 */ case '*': overflow_check3(); result = lop * rop; break; /* argv[2]に入力された演算子が'/'の場合 */ case '/' : /* 0による除算 */ if ( rop == 0 ) { printf ( "error : 0による除算は禁止です。\n" ); exit ( -1 ); } overflow_check4(); result = lop % rop; // 剰余を求める break; default: printf ( "error : '+' '-' '*' '/'のいずれかの演算子を入力して下さい。\n" ); exit ( -1 ); } /* 割り算の結果として余りが出なかった場合 */ if ( result == 0 ) { result = lop / rop; printf ( "%d %c %d = %d", lop, op, rop, result ); exit ( 0 ); /* 割り算の結果として余りが出た場合 */ } else { result = lop / rop; mod = lop % rop; printf ( "%d %c %d = %d余り%d", lop, op, rop, result, mod ); exit ( 0 ); } /* 数値1 演算子 数値2 = 演算結果の形式で出力する */ printf ( "%d %c %d = %d", lop, op, rop, result ); exit ( 0 ); } int overflow_check1 () { /* オーバーフローのチェック */ if ( lop > 0 && rop > 0 ) { if ( lop > max - rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } /* オーバーフローのチェック */ if ( lop < 0 && rop < 0 ) { if ( lop < min - rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } return 0; } int overflow_check2 () { /* オーバーフローのチェック */ if ( lop > 0 && rop < 0 ) { if ( lop > max + rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } /* オーバーフローのチェック */ if ( lop < 0 && rop > 0 ) { if ( lop < min + rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } } return 0; } int overflow_check3 () { /* オーバーフローのチェック */ if ( lop > max / rop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( -1 ); } /* オーバーフローのチェック */ if ( rop < max / lop ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } return 0; } int overflow_check4 () { /* オーバーフローのチェック */ if ( ( lop == min ) && ( rop == -1 ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( -1 ); } return 0; }

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

  • ベストアンサー
回答No.2

お返事ありがとうございました。 先ほどは、プログラムをよく検証せずに方法のみで返事をさせていただいたのですが、 よくよく見ると、このプログラムは正常に動くのでしょうか? 実際に引数を入力して動かしてみると、 #a.out 3 - 1 3 - 1 = 3 0 となりました。正しい結果じゃないですね^^; 上手く動作しないということ以外でなければ、プログラムを提示するときは、動作を一応確認しておいてください。 今回の質問者さんの目的は関数化ですし。 それとこの質問から見始めた方もいると思うので、プログラムの仕様なども記載しておくべきと思います。 >ちなみに少しだけ関数化させてみたのですが、あまり意味のない関数化だと思い、全く自信がありません。 経験がなければ、自信が無いのは普通です。経験と共にきれいなプログラムが書けるようになってきますし、 最初はメイン関数のみになるというのも普通のことです。 今回、関数化されているところは私は適切だと思いますし、 まずはできるだけ自信を持って、自分なりにやってみてください。

teru3128
質問者

お礼

一応オーバーフローも考慮して、ちゃんと動くようになりましたよ。 開発環境はvc2005です。ファイル名 オペランド 演算子 オペランド と入力して実行すればちゃんと動きますよ! <<今回、関数化されている部分は適切 ありごとうございます。少しずつ関数になれていきたいと思います。

teru3128
質問者

補足

失礼しました。確認したところ確かにバグがありました。 case '/' : /* 0による除算 */ if ( rop == 0 ) { printf ( "error : 0による除算は禁止です。\n" ); exit ( -1 ); } overflow_check4(); result = lop % rop; // 剰余を求める /* 割り算の結果として余りが出なかった場合 */ if ( result == 0 ) { result = lop / rop; printf ( "%d %c %d = %d", lop, op, rop, result ); exit ( 0 ); /* 割り算の結果として余りが出た場合 */ } else { result = lop / rop; mod = lop % rop; printf ( "%d %c %d = %d余り%d", lop, op, rop, result, mod ); exit ( 0 ); } break; default: printf ( "error : '+' '-' '*' '/'のいずれかの演算子を入力して下さい。\n" ); exit ( 0 ); } /* 数値1 演算子 数値2 = 演算結果の形式で出力する */ printf ( "%d %c %d = %d", lop, op, rop, result ); exit ( 0 ); } ちなみに掛け算のオーバーフローのコードが間違っている気が するのですが、これで正しいのでしょうか?

その他の回答 (6)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.7

> ありがとうございました。一応こんな感じでやってみたのですが > 除算の部分で、result = ごとに条件が違うため、どうすればよいのか > 困っています。 条件の違いとは?単純に「余り」の有無なのでは? であれば、私の元コードでも条件で出力は変わってます。 (構造体のようなものはあえて使わずポインタ引数で処理してますが) ちなみに、私のコードでは「余り」は「mod」に格納されresultには「余り」が入りません。 mod = lop % rop; result = lop / rop; になるようにコードが書かれており、同じresultを使いまわしたりしてません。 (変数の使いまわしは理解しにくいコードになりがちですので) そして、「余り」を表示するか否かは「余りがあるかないか」で決まるのであり、 結果として「余りがなければ表示しない」のであれば、 加減乗賛の際にはmodを0(加減乗には余りがない)にしておけば、 割り算とか掛け算とかを区別する必要はなくなります。 (私のコードではこういう処理を行っています)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.6

/** 四則演算 */ static int calc(int lop, char op, int rop, int* mod) {  int result =0;  assert(mod != NULL);  *mod = 0; /* 除算以外は0を保証(print_resultで"余り"をはじく) */  switch(op)  {  case '+': result = add(lop, rop);  break;  case '-': result = sub(lop, rop);  break;  case '*': result = mul(lop, rop);  break;  case '/': result = div(lop, rop, mod); break;  default : check_ok_or_exit(ALWAYS_ERROR, -1, UNKNOWN_OP_MSG); return -1; /* no return */  }  return result; // ←抜けてました。 }

teru3128
質問者

お礼

ありがとうございました。一応こんな感じでやってみたのですが 除算の部分で、result = ごとに条件が違うため、どうすればよいのか 困っています。 /* 加算 */ int add ( int lop, int rop ) { if ( ( lop > 0 && rop > 0 ) && ( lop > max - rop ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } else if ( ( lop < 0 && rop < 0 ) && ( lop < min - rop ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } return lop + rop; } /* 減算 */ int sub ( int lop, int rop ) { if ( ( lop > 0 && rop < 0 ) && ( lop > max + rop ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } else if ( ( lop < 0 && rop > 0 ) && ( lop < min + rop ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } return lop - rop; } /* 乗算 */ int mul ( int lop, int rop ) { if ( ( lop > 0 && rop > 0 ) && ( lop > max / rop ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } if ( ( ( lop == min ) && ( rop == -1 ) ) || ( ( lop == -1 ) && ( rop == min ) ) ) { printf ( "error : オーバーフローが起こります。\n" ); exit ( 0 ); } return lop * rop; }

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.5

Cの場合、エラーで一度戻すのが一般的なので、 関数内部で直接終了、というのが違和感がありますけど、 check_ok_or_exitは、Cでいえばassertに近い。 (ここでは条件が逆ですが合わせてもいいですし) # C++とかだと例外処理ってのがあるので、まだ理解しやすいでしょうけど。 関数分割ってのは突き詰めると、「一行コメントで内容が表せる」ところまでいくのですが、 この例で言えば、オーバフローを個別に分けるよりは、 計算処理とセットにしておいた方がまだ分かりやすいように思います。 # ザックリ直すとこんな感じ?少なくともoverflow_check1~4とかいう"名前"はよくないです。(そして粒度も細かすぎると思います) /* エラーが起きるとexitで抜けてしまう設計 */ #include <stdarg.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <limits.h> /* $$$ プロトタイプ宣言省略 $$$ */ #define ALWAYS_ERROR 1 /* 常に失敗 */ /* エラーメッセージ */ static const char OVERFLOW_MSG[]   = "error : オーバーフローが起こります。\n"; static const char ZERO_DIV_MSG[]   = "error : 0による除算は禁止です。\n"; static const char OUT_OF_RANGE_MSG[] = "error : 整数型の範囲を超えました。\n"; static const char NON_NUMBER_MSG[]  = "error : 整数を入力して下さい。\n"; static const char BAD_CHAR_MSG[]   = "error : 演算子を正しく入力して下さい。\n"; static const char UNKNOWN_OP_MSG[]  = "error : '+' '-' '*' '/'のいずれかの演算子を入力して下さい。\n"; static const char USAGE[]       = "usage : %s lop op rop\n"; /** 四則演算を行う */ int main(int argc, char *argv[]) {  int   lop = 0, rop = 0, result = 0, mod = 0;  char op = 0;  check_ok_or_exit(argc != 4, 0, USAGE, argv[0]);  lop  = get_number_from(argv[1]);  rop  = get_number_from(argv[3]);  op   = get_char_from(argv[2]);  result = calc(lop, op, rop, &mod);  print_result(lop, op, rop, result, mod);  return 0; } /** 四則演算 */ static int calc(int lop, char op, int rop, int* mod) {  int result =0;  assert(mod != NULL);  *mod = 0; /* 除算以外は0を保証(print_resultで"余り"をはじく) */  switch(op)  {  case '+': result = add(lop, rop);  break;  case '-': result = sub(lop, rop);  break;  case '*': result = mul(lop, rop);  break;  case '/': result = div(lop, rop, mod); break;  default : check_ok_or_exit(ALWAYS_ERROR, -1, UNKNOWN_OP_MSG); return -1; /* no return */  } } /** 数式表示 */ static void print_result(int lop, char op, int rop, int result, int mod) {  printf("%d %c %d = %d", lop, op, rop, result);  if(mod) printf("余り%d\n", mod); } /** 十進表示数字(文字列)⇒int */ static int get_number_from(const char* const msg) {  char* check = NULL;  int  value = strtol(msg, &check, 10);  check_ok_or_exit(errno == ERANGE, -1, OUT_OF_RANGE_MSG);  check_ok_or_exit(*check != '\0', -1, NON_NUMBER_MSG);  return value; } /** 文字列⇒単一文字 */ static char get_char_from(const char* const msg) {  assert(msg != NULL);  check_ok_or_exit(strlen(msg) >= 2, -1, BAD_CHAR_MSG);  return msg[0]; } /** 加算 */ static void add(calc(int lop, int rop) {  check_ok_or_exit((lop > 0 && rop > 0) && (lop > INT_MAX - rop), 0, OVERFLOW_MSG);  check_ok_or_exit((lop < 0 && rop < 0) && (lop < INT_MIN - rop), 0, OVERFLOW_MSG);  return lop + rop; } /** 減算 */ static void sub(int lop, int rop) {  check_ok_or_exit((lop > 0 && rop < 0) && (lop > INT_MAX + rop), 0, OVERFLOW_MSG);  check_ok_or_exit((lop < 0 && rop > 0) && (lop < INT_MIN + rop), 0, OVERFLOW_MSG);  return lop - rop; } /** 乗算 */ static void mul(int lop, int rop) {  // "0の掛け算"をすると以下のゼロ除算で落ちるとかね  check_ok_or_exit(lop > INT_MAX / rop, -1, OVERFLOW_MSG);  check_ok_or_exit(rop < INT_MAX / lop, 0, OVERFLOW_MSG);  return lop * rop; } /** 除算 */ static void div(int lop, int rop, int* mod) {  assert(mod != NULL);  check_ok_or_exit(rop == 0, -1, ZERO_DIV_MSG);  check_ok_or_exit((lop == INT_MIN) && (rop == -1), -1, OVERFLOW_MSG);  *mod = lop % rop;  return lop / rop; } /** * エラーチェック * <p> *  条件に合致する場合、エラーとしてプログラムを終了する<br> *   合致しない場合、何もしない * </p> * @param expr 条件式 * @arg  0(偽)  何もしない * @arg  !0(真)  プログラム終了(終了コードはerr) * @param err q エラー終了時の終了コード * @param msg  エラー終了時の標準出力メッセージ(可変個引き数文字列) */ static void check_ok_or_exit(int expr, int err, const char* const msg, ...) {   va_list va;  va_start(va, msg);  if(expr)  {   vprintf(msg, va);   va_end(va);   exit(err);   return;  }  va_end(va); }

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.4

失礼。 > check_ok_or_exit(strlen(msg) > 2, -1, BAD_CHAR_MSG); check_ok_or_exit(strlen(msg) >)= 2, -1, BAD_CHAR_MSG);ですね。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.3

一番単純な関数化の方針は「重複部分を削っていく(同じことは二度書かない)」 後は、「冗長なだけで意味のないコメントは書かない」 例:argv[2]に入力された演算子が'-'の場合 「意味のある名をつける」 で、ちょっとだけ弄ってみた一例 (一部のバグも直ってるし元コードとは仕様も多少違うけど…) (これを推奨とは言わない…ゼロから書くならこうは書かないし…) /* エラーが起きるとexitで抜けてしまう設計 */ #include <stdarg.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <limits.h> /* $$$ プロトタイプ宣言省略 $$$ */ #define ALWAYS_ERROR 1 /* 常に失敗 */ /* エラーメッセージ */ static const char OVERFLOW_MSG[]   = "error : オーバーフローが起こります。\n"; static const char ZERO_DIV_MSG[]   = "error : 0による除算は禁止です。\n"; static const char OUT_OF_RANGE_MSG[] = "error : 整数型の範囲を超えました。\n"; static const char NON_NUMBER_MSG[]  = "error : 整数を入力して下さい。\n"; static const char BAD_CHAR_MSG[]   = "error : 演算子を正しく入力して下さい。\n"; static const char UNKNOWN_OP_MSG[]  = "error : '+' '-' '*' '/'のいずれかの演算子を入力して下さい。\n"; static const char USAGE[]       = "usage : %s lop op rop\n"; int main(int argc, char *argv[]) {  int   lop = 0, rop = 0, result = 0, mod = 0;  char op = 0;  check_ok_or_exit(argc != 4, 0, USAGE, argv[0]);  lop  = get_number_from(argv[1]);  rop  = get_number_from(argv[3]);  op   = get_char_from(argv[2]);  result = calc(lop, op, rop, &mod);  print_result(lop, op, rop, result, mod);  return 0; } static int calc(int lop, char op, int rop, int* mod) {  assert(mod != NULL);  *mod = 0; /* 除算以外は0を保証(print_resultで"余り"をはじく) */  switch( op )  {  case '+': overflow_add(lop, rop); return lop + rop;  case '-': overflow_sub(lop, rop); return lop - rop;  case '*': overflow_mul(lop, rop); return lop * rop;  case '/': overflow_div(lop, rop); *mod = lop % rop; return lop / rop;  default : check_ok_or_exit(ALWAYS_ERROR, -1, UNKNOWN_OP_MSG); return -1; /* no return */  } } static void print_result(int lop, char op, int rop, int result, int mod) {  printf("%d %c %d = %d", lop, op, rop, result);  if(mod) printf("余り%d\n", mod); } static int get_number_from(const char* const msg) {  char* check = NULL;  int  value = strtol(msg, &check, 10);  check_ok_or_exit(errno == ERANGE, -1, OUT_OF_RANGE_MSG);  check_ok_or_exit(*check != '\0', -1, NON_NUMBER_MSG);  return value; } static char get_char_from(const char* const msg) {  assert(msg != NULL);  check_ok_or_exit(strlen(msg) > 2, -1, BAD_CHAR_MSG);  return msg[0]; } static void overflow_add(int lop, int rop) {  check_ok_or_exit((lop > 0 && rop > 0) && (lop > INT_MAX - rop), 0, OVERFLOW_MSG);  check_ok_or_exit((lop < 0 && rop < 0) && (lop < INT_MIN - rop), 0, OVERFLOW_MSG); } static void overflow_sub(int lop, int rop) {  check_ok_or_exit((lop > 0 && rop < 0) && (lop > INT_MAX + rop), 0, OVERFLOW_MSG);  check_ok_or_exit((lop < 0 && rop > 0) && (lop < INT_MIN + rop), 0, OVERFLOW_MSG); } static void overflow_mul(int lop, int rop) {  check_ok_or_exit(lop > INT_MAX / rop, -1, OVERFLOW_MSG);  check_ok_or_exit(rop < INT_MAX / lop, 0, OVERFLOW_MSG); } static void overflow_div(int lop, int rop) {  check_ok_or_exit(rop == 0, -1, ZERO_DIV_MSG);  check_ok_or_exit((lop == INT_MIN) && (rop == -1), -1, OVERFLOW_MSG); } static void check_ok_or_exit(int expr, int err, const char* const msg, ...) {   va_list va;  va_start(va, msg);  if(expr)  {   vprintf(msg, va);   va_end(va);   exit(err);   return;  }  va_end(va); }

teru3128
質問者

お礼

<<「冗長なだけで意味のないコメントは書かない」 そうですね。関数以前に無駄なものは省かないと駄目ですね。 main関数はスッキリしますが、やはり理解するのが難しいですね。 なぜかまた掛け算が上手くいかなくなってしまいました(泣)

回答No.1

前回の質問も読ませていただいておりました。 大変苦労なさっているようですね。 今回、関数化されたいようですが、何をお困りでしょうか? 個人によって好みや考えが違い、関数や記述の仕方が変わってきます。 現段階の時点で、関数を使われているので書き方が分からないということではないでしょうが。 どう関数化すればプログラムがすっきりするかということですかね? 長くなったプログラムを関数やモジュールとして分割したいのであれば、基本的に各機能や処理ごと。 一旦、処理の流れをフローチャートなどにして全体を見てみると、 全体の処理を把握することができ、どのように分割したらきれいになるかがわかるかもしれません。 色々大変でしょうが、がんばってくださいね。

teru3128
質問者

お礼

<<どう関数化すればプログラムがすっきりするかということですかね? はい。その通りです。とにかくmain関数をスッキリさせたいです。特に エラーチェックが多いので、まとめられたらと思います。 ちなみに少しだけ関数化させてみたのですが、あまり意味のない関数化 だと思い、全く自信がありません。おかしい部分を指適して下さると ありがたいです。あと、こうした方がいいというアドバイスがあれば よろしくお願いします。

関連するQ&A

  • 加減剰余のオーバーフローについて

    今C言語で加減剰余のプログラムを作っていて、 オーバーフローのチェックだけが上手くいきません。 limits.hをインクルードして、オーバーフローのチェック を行いたいのですがどうすればよいのでしょうか? 扱いたい範囲はint型の-2147483648~2147483647です。 ちなみに開発環境はvc++2005です。 一応ソースを載せておきますので、よろしくお願いします。 #pragma warning ( disable : 4996 ) #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <limits.h> int main ( int argc, char *argv[] ) { int start; // 最初に入力する値(引数1) int end; // 最後に入力する値(引数3) int kekka; // 計算結果を格納 int amari; // 除算の余りを格納 int max = INT_MAX; // 表すことが出来る最大値 int min = INT_MIN; // 表すことが出来る最小値 char enzansi; // 入力する演算子 (引数2) char str1[512]; // 格納用の配列を宣言(start用) char str2[512]; // 格納用の配列を宣言(end用) /* 引数の個数チェック */ if ( argc != 4 ) { printf ( "usage : %s start enzansi end\n", argv[0] ); exit ( 0 ); } /* 引数を取得して整数型に変換 */ start = atoi ( argv[1] ); end = atoi ( argv[3] ); /* 引数の取得 */ enzansi = ( argv[2][0] ); sprintf ( str1, "%d", start ); // str1に値を格納 sprintf ( str2, "%d", end ); // str2に値を格納 /* str1とargv[1]による文字列の比較 */ if ( strcmp ( str1, argv[1] ) ) { printf ( "error : 整数を入力して下さい。\n" ); exit ( 0 ); /* str2とargv[3]による文字列の比較 */ } else if ( strcmp ( str2, argv[3] ) ) { printf ( "error : 整数を入力して下さい。\n" ); exit ( 0 ); /* argv[2]が2文字以上の場合 */ } else if ( strlen ( argv[2] ) >= 2 ) { printf ( "error : 演算子を正しく入力して下さい。\n" ); exit ( 0 ); } /* 入力された演算子の条件ごとに計算 */ if ( enzansi == '+' ) { kekka = start + end; } else if ( enzansi == '-' ) { kekka = start - end; } else if ( enzansi == '*' ) { kekka = start * end; } else if ( enzansi == '/' ) { /* startの値を0で除算する場合 */ if ( end == 0 ) { printf ( "error : 0による除算は禁止です。\n" ); exit ( 0 ); } kekka = start % end; // 剰余を求める /* 割り算の結果として余りが出なかった場合 */ if ( kekka == 0 ) { kekka = start / end; printf ( "%d %c %d = %d", start, enzansi, end, kekka ); exit ( 0 ); /* 割り算の結果として余りが出た場合 */ } else if ( kekka != 0 ) { kekka = start / end; amari = start % end; printf ( "%d %c %d = %d余り%d", start, enzansi, end, kekka, amari ); exit ( 0 ); } /* 入力された演算子が異なる場合 */ } else { printf ( "error : '+' '-' '*' '/'のいずれかの演算子を入力して下さい。\n" ); exit ( 0 ); } /* 数値1 演算子 数値2 = 演算結果の形式で出力する */ printf ( "%d %c %d = %d", start, enzansi, end, kekka ); exit ( 0 ); } もし変な部分がありましたら指摘お願いします。 一応四則演算は問題なくできます。

  • ソースプログラムのエラー

    自分で四則演算のプログラムを組んだのですが エラーが出てお手上げ状態です。 どこが間違っているのかどなたか教えていただけませんか?? ちなみに足し算の場合はいくつ足しても計算できるという プログラムです☆ #include<stdio.h> int main(int argc, char *argv[]){ int i,a=0,b=0,x=0; int m=0; if(argv[1]!="+"||argv[1]!="-"||argv[1]!="*"||argv[1]!="/"||){ printf("指定された文字ではありませんよ\n"); return -1; } a = atoi(argv[2]); b = atoi(argv[3]); if(argv[1]=="-"){ m=a-b; } if(argv[1]=="*"){ m=a*b; } if(argv[1]=="/"){ m=a/b; } if(argv[1]=="+"){ for(i=2;i<argc;i++){ x=atoi(argv[i]); m+=x; } printf("%d\n",m); return 0; }

  • プログラムがバグっている箇所を教えて下さい(1)

    C++初心者です。 以下のソースコードでバグっていると思われる箇所を教えていただけるとありがたいです。 /* 02_LIFO.cpp * * int型整数を格納するスタックを、配列を用いて実現する(格納上限1000個) * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "02_LIFO.h" /* スタック格納要素最大数実装 */ const int LIFO::m_maxSize = 1000 * sizeof(int); /* コンストラクタ */ LIFO::LIFO() { memset(m_stack, 0, m_maxSize); } /* デストラクタ */ LIFO::~LIFO() { /* nop */ } /* プッシュ */ int LIFO::LIFO_push_array(const int push_value) { if (m_stored > m_maxSize) { return EXIT_FAILURE; } else { m_stack[m_stored++] = push_value; return EXIT_SUCCESS; } } /* ポップ */ int LIFO::LIFO_pop_array(int *pop_value) { if (m_stored == 0) { return EXIT_FAILURE; } else { *pop_value = m_stack[m_stored--]; return EXIT_SUCCESS; } } /* 以下テスト用 */ static void Check(bool result, int line) { if (result == false) { /* 結果がおかしい処理の行をログ出力 */ printf("ERROR Line:%d\n", line); } } /* 正常系テスト */ static void TestNormal(void) { int result; LIFO stack; result = stack.LIFO_push_array(10); Check((result == EXIT_SUCCESS), __LINE__); result = stack.LIFO_push_array(20); Check((result == EXIT_SUCCESS), __LINE__); int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 20), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 10), __LINE__); } /* 境界値テスト */ static void TestLimit(void) { int result; LIFO stack; /* 空の状態でPOP */ int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_FAILURE), __LINE__); /* MAX値までPUSH */ for (int i = 0; i < 1000; i++) { result = stack.LIFO_push_array(10); Check((result == EXIT_SUCCESS), __LINE__); } /* MAX値を超えてPUSH */ result = stack.LIFO_push_array(10); Check((result == EXIT_FAILURE), __LINE__); } /* メイン関数 */ int main() { /* テスト */ printf("TestStart\n"); TestNormal(); TestLimit(); printf("TestEnd\n"); return 0; }

  • scanf関数のプログラムをgetchar関数で

    scanf関数を使って四則演算、論理輪、論理積をint、float、double型で表示するプログラムを作ったのですが これをscanf関数ではなく、getchar関数で組みなおし、関数化する課題が出ました。 そのままscanf関数のところだけを変えても型が違うというエラーが出てうまくいきません。 どうすればいいでしょうか? 一応scanf関数で組んだプログラムの一部を載せておきます。 #include <stdio.h> #include <math.h> main() { float a , b; float x[5]; printf("正の数字を2つ入力して下さい(小数点を含めて4ケタまで):\n"); for(;;) { printf("\na="); scanf("%f" , &a); if(a>=0 && a<=9999 && a) { break; } else { printf("****aに入力エラー****\n"); printf("数字は4ケタ以内の正数を入力:\n"); continue; } } for(;;) { printf("b="); scanf("%f" , &b); if(b>=0 && b<=9999 && b) { break; } else { printf("****bに入力エラー****\n"); printf("数字は4ケタ以内の正数を入力:\n"); continue; } } x[0] = a+b; x[1] = a-b; x[2] = a*b; x[3] = a/b; x[4] = a||b; x[5] = a&&b; printf("\n"); printf("int型 結果:\n足し算=%d\n" , (int)x[0]); printf("引き算=%d\n" , (int)x[1]); printf("掛け算=%d\n" , (int)x[2]); printf("割り算=%d\n" , (int)x[3]); printf("論理和=%d\n" , (int)x[4]); printf("論理積=%d\n" , (int)x[5]); printf("\n"); printf("float型 結果:\n足し算=%f\n" , x[0]); printf("引き算=%f\n" , x[1]); printf("掛け算=%f\n" , x[2]); printf("割り算=%f\n" , x[3]); printf("論理和=%f\n" , x[4]); printf("論理積=%f\n" , x[5]); ・ ・ ・ getchar(); }

  • プログラムがバグっている箇所を教えて下さい(2)

    C++初心者です。 以下のソースコードでバグっていると思われる箇所を教えていただけるとありがたいです。 /* LIFO_04.cpp * * int型整数を格納するスタックを、配列を用いて実現する * メモリ確保処理回数を少なくするために、512*N個の格納時にメモリを確保する * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LIFO_04.h" #define DEBUG #ifdef DEBUG static int newCount = 0; /* mallocのコール回数 */ static int resizeCount = 0; /* reallocのコール回数 */ static int deleteCount = 0; /* freeのコール回数 */ #endif LIFO_04::LIFO_04() : m_pStack(0), m_stored(0) { #ifdef DEBUG newCount = 0; resizeCount = 0; deleteCount = 0; #endif } LIFO_04::~LIFO_04() { /* nop */ } int LIFO_04::LIFO_push_array(const int push_value) { int result = PreProcess(); if (result == EXIT_SUCCESS) { m_pStack[m_stored++] = push_value; } return result; } int LIFO_04::LIFO_pop_array(int *pop_value) { int result; if (m_stored <= 0) { /* スタック空 */ result = EXIT_FAILURE; } else { *pop_value = m_pStack[--m_stored]; result = PostProcess(); } return result; } /* 指定バイト境界に値を切り上げる */ int LIFO_04::RoundUp(int val, int align) { if (val > 0) { return (((val - 1) / align) + 1) * align; } else { return val / align * align; } } /* 事前処理 */ int LIFO_04::PreProcess(void) { int result; if (m_stored == 0) { /* スタック新規作成 */ m_pStack = new int[m_blockLen]; #ifdef DEBUG newCount++; #endif } else if (m_stored % m_blockLen == 0) { /* スタック領域拡大 */ int resize = RoundUp(m_stored, m_blockLen * sizeof(int)); int* pBuf = ResizeBlock(m_pStack, resize); if (pBuf != 0) { m_pStack = pBuf; } } else { /* nop */ } return (m_pStack != 0) ? EXIT_SUCCESS : EXIT_FAILURE; } /* 事後処理 */ int LIFO_04::PostProcess(void) { int result; if (m_stored <= 0) { /* スタックが空になった */ delete m_pStack; #ifdef DEBUG deleteCount++; #endif m_pStack = 0; result = EXIT_SUCCESS; } else if (m_stored % m_blockLen == 0) { /* 領域縮小 */ int* pBuf = ResizeBlock(m_pStack, m_stored); if (pBuf != 0) { m_pStack = pBuf; result = EXIT_SUCCESS; } } else { result = EXIT_SUCCESS; } return result; } /* ブロックサイズを変更する */ int* LIFO_04::ResizeBlock(int* pBlock, int resize) { int* pBuf = new int[resize]; /*int* pBuf = (int*)(realloc(m_pStack, sizeof(int) * resize));*/ #ifdef DEBUG resizeCount++; #endif if (pBuf != 0) { /* 新たに確保したメモリへコピーして、元の領域を開放 */ memcpy(pBuf, pBlock, resize); delete pBlock; } return pBuf; } /* 以下評価用 */ #ifdef DEBUG static void Check(bool result, int line) { if (result == false) { printf("ERROR Line:%d\n", line); } } static void TestNormal(void) { int result; LIFO_04 stack; result = stack.LIFO_push_array(10); Check((result == EXIT_SUCCESS), __LINE__); Check((newCount == 1), __LINE__); result = stack.LIFO_push_array(20); Check((result == EXIT_SUCCESS), __LINE__); int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 20), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 10), __LINE__); Check((deleteCount == 1), __LINE__); Check((resizeCount == 0), __LINE__); } static void TestLimit(void) { int result; LIFO_04 stack; /* 空の状態でPOP */ int val = 0; result = stack.LIFO_pop_array(&val); Check((result == EXIT_FAILURE), __LINE__); /* m_blockLen値までPUSH */ for (int i = 0; i < 512; i++) { result = stack.LIFO_push_array(10 + i); Check((result == EXIT_SUCCESS), __LINE__); } Check((deleteCount == 0), __LINE__); Check((resizeCount == 0), __LINE__); /* m_blockLen値を超えてPUSH */ result = stack.LIFO_push_array(20); Check((result == EXIT_SUCCESS), __LINE__); Check((resizeCount == 1), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 20), __LINE__); result = stack.LIFO_pop_array(&val); Check((result == EXIT_SUCCESS), __LINE__); Check((val == 10 + 511), __LINE__); } #endif int main() { #ifdef DEBUG printf("TestStart\n"); TestNormal(); TestLimit(); printf("TestEnd\n"); #endif return 0; }

  • 並べ替えのプログラム

    整数を20個入力し、まずそのまま表示してその後大きい順に並べ替えて表示するプログラムを作っているのですが、最大値しか表示されません。多分for文の3重ループの中がおかしいと思うのですがよくわかりません。 #include <stdio.h> int main(int argc, char* argv[]) { int c,i,x,max; int sav = 0; int before[20]; int after[20]; int check[20] = {0}; printf("整数を20個入力してください: "); for(i = 0; i < 20; i++) { scanf("%d",&before[i]); } printf("\n"); printf("BEFORE\n"); for(i = 0; i < 20; i++) { printf("%d\n",before[i]); } printf("\n"); max = 0; for(c = 0; c < 20; c++) { for(x = 0; x < 20; x++) { for(i = 0; i < 20; i++) { if(before[i] > max && check[i] == 0) max = before[i]; sav = i; } if(check[sav] == 0) check[sav] = 1; after[19 - x] = max; } } printf("AFTER\n"); for(x = 0; x < 20; x++) { printf("%d\n",after[x]); } return 0; } よろしくお願いします。

  • プログラムのフローチャートがかけません。

    次のプログラムのフローチャート(流れ図)を書いてください。お願いします。 フローチャートの書き方は以下のwebから見れます。 http://sasuke.main.jp/furo.html #include<stdio.h> #include<math.h> #include<stdlib.h> #define MAX_DATA_NUMBER 400 int check_value(int x, char* error_message); int main(int argc ,char*argv[]){ int M=0 ,i=0,N,U double x[2][MAX_DATA_NUMBER],y_bunshi FILE *in_file; in_file = fopen(argv[1],"r"); M = 0; if(argc != 3){ printf("使い方: ./smooth 入力データファイル名 平滑化数N"); exit(1); } N = check_value(atof(argv[2]),"平滑化数は正の値を入力してください。\n使い方: ./smooth 入力データファイル名 平滑化数N"); if(argc == 3){ if( in_file == NULL){ printf("使い方: ./smooth 入力データファイル名 平滑化数"); exit(1); } } while( EOF != fscanf(in_file, "%lf", &x[0][M]) && M<MAX_DATA_NUMBER){ M++; } fclose(in_file); for(i=0;i<=N-1;i++){ y_bunshi = 0; for(U=0;U<=i+N;U++){ y_bunshi += x[0][U]; } x[1][i] = y_bunshi/(i+N+1); } for(i=N;i<M-N;i++){ y_bunshi = 0; for(U=1;U<=N;U++){ y_bunshi += x[0][i+U]; y_bunshi += x[0][i-U]; } y_bunshi += x[0][1]; x[1][i] = y_bunshi/(2*N+1); } for(i=M-N;i<=M-1;i++){ y_bunshi = 0; for(U=i-N;U<=M-1;U++){ y_bunshi += x[0][U]; } x[1][i] = y_bunshi/(M+N-i); } for(i=0;i<M;i++){ printf("%3d,%8.2f,%8.3f\n",i,x[0][i],x[1][i]); } return 0; int check_value(int x,char* error_message){ if( x <= 0.0){ printf(error_message); exit(1); return x; }

  • プログラム問題(3)

    以下の問題のプログラムをやったのですが、コマンドプロンプトで実行してみるとエラーになってしまうのですが、どなたか問題点を指摘していただけないでしょうか? 【問題】 3桁の整数の値を入力していき、-9999が入力されたところで、それまでに入力された数の個数と合計を整数で、平均を浮動小数点数で出力するプログラム。 【プログラム】 #include <stdio.h> #include <stdlib.h> #include <string.h> #define streq(a, b) !strcmp((a), (b)) int main(int argc, char *argv[]) { int i, num, sum = 0; double avg; char buf[256]; char *endptr; for (i = 0;; i++) { printf("INPUT>"); if (fgets(buf, sizeof buf, stdin) == NULL) { perror("fgets"); exit(1); } if (streq(buf, "-9999") || streq(buf, "-9999\n")) { break; } if (streq(buf, "") || streq(buf, "\n")) { fprintf(stderr, "数値を入力してください。\n"); exit(1); } num = (int) strtol(buf, &endptr, 0); if (! (*endptr == '\n' || *endptr == '\0')) { fprintf(stderr, "数値を入力してください。\n"); exit(1); } sum += num; } printf("入力数:%d 合計:%d 平均:%g\n", i, sum, (double) sum / i); return 0; }

  • 任意のファイルを別のファイルにコピーするプログラム。

    コマンドラインからコピー元、コピー先ファイル名を指定してファイルをコピーするプログラムなんですが… #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { FILE *fp; if ((fp = fopen(argv[0],"r") == NULL){ printf("ファイル%sが存在しません。\n",argv[0]);exit(-1); } if ((fp = fopen(argv[1],"w") == NULL){ printf("ファイル%sがコピーできません。\n",argv[1]);exit(-1); } fclose(fp); } どこか間違っているところがあるでしょうか? ありましたら詳しく教えてもらえると幸いです。 少し自信がないのでわかる方はよろしくおねがいします。

  • プログラムエラー

    プログラムを実行したところ、こんなエラーが出てしまいました。 msgrcv failure: Argument list too long 実行したいプログラムは3つのプロセスがもつ数字を順番に並べる作業です。 1番目のプロセスはうまくいくのですが、2番目が上記のようなエラーがでてきてしまいます。 なぜでしょうか?? エラーで出てくるところは int main( int argc, char** argv ) { int qid; Qmsg message; long int myNo; int myProp; int data[NUM_DATA]; int isSwap = 0; int needMinSort = 0; int needMaxSort = 0; int got_data; int totalSwapNum = 0; int i,flag,m,n,l,s; if( argc != 2){ fprintf(stderr, "Usage: %s <own order(1-10)>\n", argv[0]); exit(1); } myNo = atol(argv[1]); if( myNo <= 0 || NUM_PROCESS < myNo ){ fprintf(stderr, "Illegal own order (%ld)\n", myNo); exit(1); } switch( myNo ){ case 1: myProp = LEFT_SIDE; printf("[%ld] is LEFT SIDE\n", myNo); break; case NUM_PROCESS: myProp = RIGHT_SIDE; printf("[%ld] is RIGHT SIDE\n", myNo); break; default: myProp = MIDDLE; printf("[%ld] is MIDDLE\n", myNo); } errno = 0; if( (qid = msgget((key_t)KEY_NO, 0666 | IPC_CREAT)) == -1 ){ perror("msgget failure"); exit(1); } message.msgData.status = MSG_AWAKE; switch( myProp ){ case LEFT_SIDE: sendMsgRhs( qid, myNo, message ); break; case MIDDLE: recvMsgLhs( qid, myNo, &message );         //ここでエラー if( message.msgData.status != MSG_AWAKE ){ exit(1); } sendMsgRhs( qid, myNo, message ); break; case RIGHT_SIDE: recvMsgLhs( qid, myNo, &message ); if( message.msgData.status != MSG_AWAKE ){ exit(1); } break; } } int recvMsgLhs( int qid, long int myNo, Qmsg* message ) { long int read_from = myNo; errno = 0; if(msgrcv(qid, message, sizeof(message->msgData), read_from, 0) == -1){ perror("msgrcv failure"); exit(1); } #ifdef SHOW_XFER_MESSAGE printf("Lhs[%2ld] ---> Recv ---> [myNo:%2ld] (%s)", message->type - 1, myNo, msgStr[message->msgData.status]); switch( message->msgData.status ){ case MSG_SWAP: case MSG_NEED: case MSG_SWAP_CNT: printf(" {data:%d}\n", message->msgData.data); break; default: printf("\n"); } #endif return errno; }

専門家に質問してみよう