加減剰除のプログラム
加減剰除のプログラム
こんにちは。@とんぷぅ~です。
質問間隔が短くてすみません(笑)
今回は上記タイトルのプログラムを作成していて、過去ログも
参考にコーディングしてみたのですが、疑問点があるので
質問させていただくことにしました。
記述したコードはこんな感じです。
/****************************************
* *
* NAME 【jyoujyo.c】 *
* SYNOPSIS【jyoujyo start enzansi end】 *
* *
*****************************************/
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[/url] )
{
int start; // 最初に入力する値(引数1)
int end; // 最後に入力する値(引数3)
int kekka; // 計算結果を格納
char enzansi; // 入力する演算子(引数2)
char str [512]; // 格納用の配列を宣言(start用)
char str1[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 ( str, "%d", start ); // strに値を格納
/* strとargv[1]による文字列の比較 */
if ( strcmp ( str, argv[1] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
sprintf ( str1, "%d", end ); // str1に値を格納
/* str1とargv[3]による文字列の比較 */
if ( strcmp ( str1, argv[3] ) ) {
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 == '/' ) {
/* 0による除算を行おうとした場合 */
if ( start == 0 || end == 0 ) {
printf ( "error : 0による除算は禁止です。\n" );
exit ( 0 );
}
/* 割り算でstartとendを逆に入力した場合 */
if ( start < end ) {
printf ( "error : startにendより大きい値を入力して下さい。\n" );
exit ( 0 );
}
kekka = start / end; // '/'が入力された場合の計算式
/* 入力された演算子が異なる場合 */
} else {
printf ( "error : 正しい演算子を入力して下さい。\n" );
exit ( 0 );
}
/* 数値1 演算子 数値2 = 演算結果の形式で出力する */
printf ( "%d %c %d = %d", start, enzansi, end, kekka);
exit ( 0 );
}
ifばかりで大変汚いコードですが、お許し下さい。
上記コードのenzansi = ( argv[2][0] );という部分で、引数の2番目に
演算子を格納するのですが、なぜ( argv[2] )では駄目なのでしょうか?
それと、除算の結果を余りを含めて表示することは可能なんでしょうか?
例えば5/2 = 2余り1といった具合に表示することです。
よろしくお願いします。
質問間隔が短くてすみません(笑)
今回は上記タイトルのプログラムを作成していて、過去ログも
参考にコーディングしてみたのですが、疑問点があるので
質問させていただくことにしました。
記述したコードはこんな感じです。
/****************************************
* *
* NAME 【jyoujyo.c】 *
* SYNOPSIS【jyoujyo start enzansi end】 *
* *
*****************************************/
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[/url] )
{
int start; // 最初に入力する値(引数1)
int end; // 最後に入力する値(引数3)
int kekka; // 計算結果を格納
char enzansi; // 入力する演算子(引数2)
char str [512]; // 格納用の配列を宣言(start用)
char str1[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 ( str, "%d", start ); // strに値を格納
/* strとargv[1]による文字列の比較 */
if ( strcmp ( str, argv[1] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
sprintf ( str1, "%d", end ); // str1に値を格納
/* str1とargv[3]による文字列の比較 */
if ( strcmp ( str1, argv[3] ) ) {
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 == '/' ) {
/* 0による除算を行おうとした場合 */
if ( start == 0 || end == 0 ) {
printf ( "error : 0による除算は禁止です。\n" );
exit ( 0 );
}
/* 割り算でstartとendを逆に入力した場合 */
if ( start < end ) {
printf ( "error : startにendより大きい値を入力して下さい。\n" );
exit ( 0 );
}
kekka = start / end; // '/'が入力された場合の計算式
/* 入力された演算子が異なる場合 */
} else {
printf ( "error : 正しい演算子を入力して下さい。\n" );
exit ( 0 );
}
/* 数値1 演算子 数値2 = 演算結果の形式で出力する */
printf ( "%d %c %d = %d", start, enzansi, end, kekka);
exit ( 0 );
}
ifばかりで大変汚いコードですが、お許し下さい。
上記コードのenzansi = ( argv[2][0] );という部分で、引数の2番目に
演算子を格納するのですが、なぜ( argv[2] )では駄目なのでしょうか?
それと、除算の結果を余りを含めて表示することは可能なんでしょうか?
例えば5/2 = 2余り1といった具合に表示することです。
よろしくお願いします。
Re:加減剰除のプログラム
> 上記コードのenzansi = ( argv[2][0] );という部分で、引数の2番目に
> 演算子を格納するのですが、なぜ( argv[2] )では駄目なのでしょうか?
argv[2]は、演算子の内容を格納している文字列へのポインタです。
argv[2]には、"+", "-", "*", "/" というまっとうな内容以外に
"+$%&#" とか ";012vu*&" なんかも与えることができます。
今回は、argv[2]の先頭文字を四則演算子として採用したいらしいので、
argv[2]が指している文字列の先頭文字であるargv[2][0]を参照しています。
> それと、除算の結果を余りを含めて表示することは可能なんでしょうか?
> 例えば5/2 = 2余り1といった具合に表示することです。
もちろんできます。
割り算の際、%演算子で余りを求めて、それがゼロかどうかによって
出力のやり方を変えればよいのです。
> 演算子を格納するのですが、なぜ( argv[2] )では駄目なのでしょうか?
argv[2]は、演算子の内容を格納している文字列へのポインタです。
argv[2]には、"+", "-", "*", "/" というまっとうな内容以外に
"+$%&#" とか ";012vu*&" なんかも与えることができます。
今回は、argv[2]の先頭文字を四則演算子として採用したいらしいので、
argv[2]が指している文字列の先頭文字であるargv[2][0]を参照しています。
> それと、除算の結果を余りを含めて表示することは可能なんでしょうか?
> 例えば5/2 = 2余り1といった具合に表示することです。
もちろんできます。
割り算の際、%演算子で余りを求めて、それがゼロかどうかによって
出力のやり方を変えればよいのです。
Re:加減剰除のプログラム
>上記コードのenzansi = ( argv[2][0] );という部分で、引数の2番目に
>演算子を格納するのですが、なぜ( argv[2] )では駄目なのでしょうか?
enzansi は char型で宣言されています。(char* 型でないことに注意)
char型は'一文字'を格納するスペースしか持ち合わせていません。
argv[2][0] とすると argv[2]配列中の先頭文字([0])のみを取得し、
argv[2] とすると argv[2]配列の先頭アドレスを指定することになります。
>それと、除算の結果を余りを含めて表示することは可能なんでしょうか?
剰余を行いたい場合は %演算子 を用います。
例) 12 % 5 = 2
12 % 6 = 0
つまり、剰余を行った結果、0以外が返ってきた場合に"余り・・・"と出力することで可能です。
>演算子を格納するのですが、なぜ( argv[2] )では駄目なのでしょうか?
enzansi は char型で宣言されています。(char* 型でないことに注意)
char型は'一文字'を格納するスペースしか持ち合わせていません。
argv[2][0] とすると argv[2]配列中の先頭文字([0])のみを取得し、
argv[2] とすると argv[2]配列の先頭アドレスを指定することになります。
>それと、除算の結果を余りを含めて表示することは可能なんでしょうか?
剰余を行いたい場合は %演算子 を用います。
例) 12 % 5 = 2
12 % 6 = 0
つまり、剰余を行った結果、0以外が返ってきた場合に"余り・・・"と出力することで可能です。
Re:加減剰除のプログラム
boxさん。お世話になっております。
大変分かり易い回答ありがとうございました。
keichanさん初めまして。
ありがとうございました。やはり配列とポインタに
ついてもっと勉強しなければならないですね。
まだまだ未熟ですがよろしくお願いします。
お二人とも本当にありがとうございました。
大変分かり易い回答ありがとうございました。
keichanさん初めまして。
ありがとうございました。やはり配列とポインタに
ついてもっと勉強しなければならないですね。
まだまだ未熟ですがよろしくお願いします。
お二人とも本当にありがとうございました。
Re:加減剰除のプログラム
割り算に関して細かいことを申しますと、
ある数をゼロで割ることはできませんが、ゼロをゼロ以外で割ることはできます。
今の仕様ですと
C:\> hoge 0 / 3 <Enter>
のように実行したとき、「error : 0による除算は禁止です。」と
出力するようですが、実際には計算できて、答はもちろんゼロです。
ある数をゼロで割ることはできませんが、ゼロをゼロ以外で割ることはできます。
今の仕様ですと
C:\> hoge 0 / 3 <Enter>
のように実行したとき、「error : 0による除算は禁止です。」と
出力するようですが、実際には計算できて、答はもちろんゼロです。
Re:加減剰除のプログラム
boxさんありがとうございました。
/* startの値を0で除算する場合 */
if ( end == 0 ) {
printf ( "error : 0による除算は禁止です。\n" );
exit ( 0 );
}
/* 割り算でstartとendを逆に入力した場合 */
if ( start < end && start != 0 ) {
printf ( "error : startにendより大きい値を入力して下さい。\n" );
exit ( 0 );
}
こんな感じで大丈夫でしょうか?
/* startの値を0で除算する場合 */
if ( end == 0 ) {
printf ( "error : 0による除算は禁止です。\n" );
exit ( 0 );
}
/* 割り算でstartとendを逆に入力した場合 */
if ( start < end && start != 0 ) {
printf ( "error : startにendより大きい値を入力して下さい。\n" );
exit ( 0 );
}
こんな感じで大丈夫でしょうか?
Re:加減剰除のプログラム
皆さんの意見を参考に一通りコーディングしてみました。
ただあまりに読みにくくなってしまったので、ココを
こうした方がいいなどのご指摘をよろしくお願いしますm(_ _)m
以下コードになります。
/****************************************
* *
* NAME 【jyoujyo.c】 *
* SYNOPSIS【jyoujyo start enzansi end】 *
* *
*****************************************/
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[/url] )
{
int start; // 最初に入力する値(引数1)
int end; // 最後に入力する値(引数3)
int kekka; // 計算結果を格納
int amari; // 除算の余りを格納
char enzansi; // 入力する演算子(引数2)
char str [512]; // 格納用の配列を宣言(start用)
char str1[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 ( str, "%d", start ); // strに値を格納
/* strとargv[1]による文字列の比較 */
if ( strcmp ( str, argv[1] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
sprintf ( str1, "%d", end ); // str1に値を格納
/* str1とargv[3]による文字列の比較 */
if ( strcmp ( str1, argv[3] ) ) {
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 );
}
/* 割り算でstartとendを逆に入力した場合 */
if ( start < end && start != 0 ) {
printf ( "error : startにendより大きい値を入力して下さい。\n" );
exit ( 0 );
}
kekka = start % end;
/* 割り算の結果として余りが出なかった場合 */
if ( kekka == 0 ) {
kekka = start / end;
printf ( "%d %c %d = %d", start, enzansi, end, kekka);
exit ( 0 );
}
/* 割り算の結果として余りが出た場合 */
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 );
}
ただあまりに読みにくくなってしまったので、ココを
こうした方がいいなどのご指摘をよろしくお願いしますm(_ _)m
以下コードになります。
/****************************************
* *
* NAME 【jyoujyo.c】 *
* SYNOPSIS【jyoujyo start enzansi end】 *
* *
*****************************************/
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[/url] )
{
int start; // 最初に入力する値(引数1)
int end; // 最後に入力する値(引数3)
int kekka; // 計算結果を格納
int amari; // 除算の余りを格納
char enzansi; // 入力する演算子(引数2)
char str [512]; // 格納用の配列を宣言(start用)
char str1[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 ( str, "%d", start ); // strに値を格納
/* strとargv[1]による文字列の比較 */
if ( strcmp ( str, argv[1] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
sprintf ( str1, "%d", end ); // str1に値を格納
/* str1とargv[3]による文字列の比較 */
if ( strcmp ( str1, argv[3] ) ) {
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 );
}
/* 割り算でstartとendを逆に入力した場合 */
if ( start < end && start != 0 ) {
printf ( "error : startにendより大きい値を入力して下さい。\n" );
exit ( 0 );
}
kekka = start % end;
/* 割り算の結果として余りが出なかった場合 */
if ( kekka == 0 ) {
kekka = start / end;
printf ( "%d %c %d = %d", start, enzansi, end, kekka);
exit ( 0 );
}
/* 割り算の結果として余りが出た場合 */
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 );
}
Re:加減剰除のプログラム
お世話になります。@とんぷぅ~です。問題点を
解消したくて質問させていただきました。
1.( )を含む計算
1 + -5 = -4は出来るのですが、1 + (-5) = 等の計算ができません。
2.演算子に続けて演算子を入力した場合
1 ++ 5 = 6、1 *///// 6 = 6という風にも計算出来てしまいます。
3.限界値について
前もってint型の最小値、最大値を決めておき
それを超える値になる場合計算出来ないようにしたいです。
意味不明な部分があるかもしれませんがよろしくお願いします。
以下がソースです。
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[/url] )
{
int start; // 最初に入力する値(引数1)
int end; // 最後に入力する値(引数3)
int kekka = 0; // 計算結果を格納
int amari; // 除算の余りを格納
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]による文字列の比較 */
if ( strcmp ( str2, argv[3] ) ) {
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 );
}
/* 割り算の結果として余りが出た場合 */
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 );
}
解消したくて質問させていただきました。
1.( )を含む計算
1 + -5 = -4は出来るのですが、1 + (-5) = 等の計算ができません。
2.演算子に続けて演算子を入力した場合
1 ++ 5 = 6、1 *///// 6 = 6という風にも計算出来てしまいます。
3.限界値について
前もってint型の最小値、最大値を決めておき
それを超える値になる場合計算出来ないようにしたいです。
意味不明な部分があるかもしれませんがよろしくお願いします。
以下がソースです。
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[/url] )
{
int start; // 最初に入力する値(引数1)
int end; // 最後に入力する値(引数3)
int kekka = 0; // 計算結果を格納
int amari; // 除算の余りを格納
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]による文字列の比較 */
if ( strcmp ( str2, argv[3] ) ) {
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 );
}
/* 割り算の結果として余りが出た場合 */
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 );
}
Re:加減剰除のプログラム
> 1.( )を含む計算
> 1 + -5 = -4は出来るのですが、1 + (-5) = 等の計算ができません。
どんな風に計算できませんか?
何かエラーメッセージが出ますか?
また、カッコの中には、どの程度複雑な式を入れたいですか?それによっては、
データ構造やアルゴリズムを一から見直す必要があります。
カッコ付きの式をちゃんと扱おうとすると、けっこう奥が深いですよ。
例えば、2 * (1 + 3) を計算するという、人間にとっては何ということもない式でも、
今のプログラムでは全く歯が立たないことがおわかりになると思います。
> 2.演算子に続けて演算子を入力した場合
> 1 ++ 5 = 6、1 *///// 6 = 6という風にも計算出来てしまいます。
argv[2] の長さが2以上のとき、しかるべきメッセージを出力して
計算させないようにすればよいと思います。
> 3.限界値について
> 前もってint型の最小値、最大値を決めておき
> それを超える値になる場合計算出来ないようにしたいです。
限界値の具体的な値は、いくらですか?
> 1 + -5 = -4は出来るのですが、1 + (-5) = 等の計算ができません。
どんな風に計算できませんか?
何かエラーメッセージが出ますか?
また、カッコの中には、どの程度複雑な式を入れたいですか?それによっては、
データ構造やアルゴリズムを一から見直す必要があります。
カッコ付きの式をちゃんと扱おうとすると、けっこう奥が深いですよ。
例えば、2 * (1 + 3) を計算するという、人間にとっては何ということもない式でも、
今のプログラムでは全く歯が立たないことがおわかりになると思います。
> 2.演算子に続けて演算子を入力した場合
> 1 ++ 5 = 6、1 *///// 6 = 6という風にも計算出来てしまいます。
argv[2] の長さが2以上のとき、しかるべきメッセージを出力して
計算させないようにすればよいと思います。
> 3.限界値について
> 前もってint型の最小値、最大値を決めておき
> それを超える値になる場合計算出来ないようにしたいです。
限界値の具体的な値は、いくらですか?
Re:加減剰除のプログラム
>1.についてはデバッグした際に以下の部分で終了します。
/* str1とargv[1]による文字列の比較 */
if ( strcmp ( str1, argv[1] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
/* str2とargv[3]による文字列の比較 */
if ( strcmp ( str2, argv[3] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
最終的に(-5) - (-5) = 0などの計算まで出来るようにしたいです。
つまり1、3番目の引数にカッコを含んでいても整数であるなら計算
出来るようにしたいということです。ちなみにカッコとは別ですが、
-5 - -5 = 0は通りますが、+5 + +5 = は計算できません。
>2.についてはなんとか出来そうです。
>3.は-2147483648~2147483647を扱いたいです。
その値を超えるような計算は出来ないようにしたいです。
文章が分かりにくいかもしれませんがよろしくお願いします。
/* str1とargv[1]による文字列の比較 */
if ( strcmp ( str1, argv[1] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
/* str2とargv[3]による文字列の比較 */
if ( strcmp ( str2, argv[3] ) ) {
printf ( "error : 整数を入力して下さい。\n" );
exit ( 0 );
}
最終的に(-5) - (-5) = 0などの計算まで出来るようにしたいです。
つまり1、3番目の引数にカッコを含んでいても整数であるなら計算
出来るようにしたいということです。ちなみにカッコとは別ですが、
-5 - -5 = 0は通りますが、+5 + +5 = は計算できません。
>2.についてはなんとか出来そうです。
>3.は-2147483648~2147483647を扱いたいです。
その値を超えるような計算は出来ないようにしたいです。
文章が分かりにくいかもしれませんがよろしくお願いします。
Re:加減剰除のプログラム
> 最終的に(-5) - (-5) = 0などの計算まで出来るようにしたいです。
> つまり1、3番目の引数にカッコを含んでいても整数であるなら計算
> 出来るようにしたいということです。
argv[1]とargv[3]の内容を1文字ずつ解析して、
正負の符号と数字だけから成る、
正しく数値と認識できる要素を取り出す必要があります。
厳密な仕様を求めるなら、
・開きカッコと閉じカッコの対応が合っているかどうかを判定する
・正負の符号が2つ以上あったらエラーにする
・整数に限定するなら、小数点があったらエラーにする
というようなロジックを組み込む必要があります。
> >3.は-2147483648~2147483647を扱いたいです。
> その値を超えるような計算は出来ないようにしたいです。
計算した結果がlong型の範囲に収まらず、変な値を出力してしまったので、
「あ~、やっぱりダメだったか」と後からわかる、ということはあるのですが、
計算する前にわかる方法があるかどうか、よくわからないです。
> つまり1、3番目の引数にカッコを含んでいても整数であるなら計算
> 出来るようにしたいということです。
argv[1]とargv[3]の内容を1文字ずつ解析して、
正負の符号と数字だけから成る、
正しく数値と認識できる要素を取り出す必要があります。
厳密な仕様を求めるなら、
・開きカッコと閉じカッコの対応が合っているかどうかを判定する
・正負の符号が2つ以上あったらエラーにする
・整数に限定するなら、小数点があったらエラーにする
というようなロジックを組み込む必要があります。
> >3.は-2147483648~2147483647を扱いたいです。
> その値を超えるような計算は出来ないようにしたいです。
計算した結果がlong型の範囲に収まらず、変な値を出力してしまったので、
「あ~、やっぱりダメだったか」と後からわかる、ということはあるのですが、
計算する前にわかる方法があるかどうか、よくわからないです。
Re:加減剰除のプログラム
<argv[1]とargv[3]の内容を1文字ずつ解析して、
正負の符号と数字だけから成る、
正しく数値と認識できる要素を取り出す必要があります。
難しそうですね~。調べてみます。
<2.についてはboxさんに教えていただき、上手くいきました。
<3.についてはカッコの問題が終わり次第考えていきたいと思います。
いつもご回答ありがとうございます。
正負の符号と数字だけから成る、
正しく数値と認識できる要素を取り出す必要があります。
難しそうですね~。調べてみます。
<2.についてはboxさんに教えていただき、上手くいきました。
<3.についてはカッコの問題が終わり次第考えていきたいと思います。
いつもご回答ありがとうございます。
Re:加減剰除のプログラム
お世話になっております。
今、問題点で()の部分を考えているのですが、1文字ずつ
解析するといったことがよくわかりません。
よろしくお願いします。
今、問題点で()の部分を考えているのですが、1文字ずつ
解析するといったことがよくわかりません。
よろしくお願いします。
Re:加減剰除のプログラム
いくつかの状態を定義して、ある状態が成立するには
他のどの状態(複数の場合あり)が成立している必要があるか、について
考えてみるとよいかもしれません。
初期状態は「状態なし」(下記の状態すべてがOFF)
'('を読み取ったら「開きカッコ状態」をON
')'を読み取ったら「閉じカッコ状態」をON
'+'を読み取ったら「+符号状態」をON
'-'を読み取ったら「-符号状態」をON
'0'~'9'を読み取ったら「数字状態」をON
解析の例
・"()"のように、開きカッコの後ろに+-の符号も数字もなくて
いきなり閉じカッコが来るとエラー
・"(-5()"のように、開きカッコと閉じカッコの数が一致しなければエラー
・"-96+"のように、+-の符号が混在するとエラー
他にも、エラーとするパターンはたくさんあります。
なお、もっと簡単に解析できる方法があるかもしれません。
他のどの状態(複数の場合あり)が成立している必要があるか、について
考えてみるとよいかもしれません。
初期状態は「状態なし」(下記の状態すべてがOFF)
'('を読み取ったら「開きカッコ状態」をON
')'を読み取ったら「閉じカッコ状態」をON
'+'を読み取ったら「+符号状態」をON
'-'を読み取ったら「-符号状態」をON
'0'~'9'を読み取ったら「数字状態」をON
解析の例
・"()"のように、開きカッコの後ろに+-の符号も数字もなくて
いきなり閉じカッコが来るとエラー
・"(-5()"のように、開きカッコと閉じカッコの数が一致しなければエラー
・"-96+"のように、+-の符号が混在するとエラー
他にも、エラーとするパターンはたくさんあります。
なお、もっと簡単に解析できる方法があるかもしれません。
Re:加減剰除のプログラム
boxさん。レスが遅れて申し訳ありません。
1字解析とはトークンを取得するということなんでしょうか?
このプログラムを作成するにあたり、足りない知識は何なのでしょうか?
こんなことが出来れば良い。といったアドバイス等があればよろしくお願いします。
1字解析とはトークンを取得するということなんでしょうか?
このプログラムを作成するにあたり、足りない知識は何なのでしょうか?
こんなことが出来れば良い。といったアドバイス等があればよろしくお願いします。
Re:加減剰除のプログラム
先日の回答で挙げた各状態について、2次元の表を作って、
・Aの状態からはBの状態へ移れる
・Cの状態からDの状態へは移れない(エラー)
・Eの状態からFの状態へ移ることはない
という内容を管理してみてはいかがでしょうか。
()や正負の符号を含む可能性があるargv[1]とargv[3]について、
内容を1文字ずつ読む際に「今、どの状態にあるからこの文字が来ていいのか、
それともダメなのか」を逐次みていくと、
数値を正しく取得できるのではないかと思います。
・Aの状態からはBの状態へ移れる
・Cの状態からDの状態へは移れない(エラー)
・Eの状態からFの状態へ移ることはない
という内容を管理してみてはいかがでしょうか。
()や正負の符号を含む可能性があるargv[1]とargv[3]について、
内容を1文字ずつ読む際に「今、どの状態にあるからこの文字が来ていいのか、
それともダメなのか」を逐次みていくと、
数値を正しく取得できるのではないかと思います。
Re:加減剰除のプログラム
私が今作りたいものの中でインタープリンタもどきが必要でなので、丁度今調べて
いるところです。参考になればと書いておきます。
解析する順番としては、字句解析して構文解析を行います。私が今不足している知識は
構文解析で使う(使わない方法もあるのでしょうが)オートマンです。box さんが言う
「2次元の表」とはオートマンの状態遷移表なのでしょう。
これらのことを行うCコードを生成するプログラム(lex + yacc)も存在してます。
でも結構手強いのとGNUなので、自力でやるか頼っちゃおうか迷ってます。
キーワードとして 字句解析, 構文解析, lex, flex, yacc, byacc, bison で調べると
いろいろ出てきます。
いるところです。参考になればと書いておきます。
解析する順番としては、字句解析して構文解析を行います。私が今不足している知識は
構文解析で使う(使わない方法もあるのでしょうが)オートマンです。box さんが言う
「2次元の表」とはオートマンの状態遷移表なのでしょう。
これらのことを行うCコードを生成するプログラム(lex + yacc)も存在してます。
でも結構手強いのとGNUなので、自力でやるか頼っちゃおうか迷ってます。
キーワードとして 字句解析, 構文解析, lex, flex, yacc, byacc, bison で調べると
いろいろ出てきます。
Re:加減剰除のプログラム
boxさん、しっぽさんありがとうございました。
取り合えず、現段階では難しそうなので
次にしたいと思います。本当にありがとうございました。
もう一点問題があるのですが、扱える数字の限界値を超えて
計算出来ないようにしたいのです。ちなみに扱える範囲は
-2147483648~2147483647です。
limitsなどのライブラリを使い、上記の数を指定すれば
よいのでしょうか?よろしくお願いします。
取り合えず、現段階では難しそうなので
次にしたいと思います。本当にありがとうございました。
もう一点問題があるのですが、扱える数字の限界値を超えて
計算出来ないようにしたいのです。ちなみに扱える範囲は
-2147483648~2147483647です。
limitsなどのライブラリを使い、上記の数を指定すれば
よいのでしょうか?よろしくお願いします。
Re:加減剰除のプログラム
上記問題をなんとかクリアして、今度は関数化にチャレンジしているのですが、
いかんせん関数を作るということに抵抗がありまして、なかなか上手くいきません。
一応自分で少しだけ関数化してみたのですが、あまり意味がない関数化のような気もします。
エラーチェックなどをまとめる関数等を作成してmain関数をスッキリさせたいと思っています。
関数の使い方も正しいのかはっきり分かりません。ソースコードを記載しますので
ここが駄目といった部分やこうした方がいい等の助言よろしくお願いします。
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
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[/url] )
{
/* 引数の個数チェック */
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;
}
いかんせん関数を作るということに抵抗がありまして、なかなか上手くいきません。
一応自分で少しだけ関数化してみたのですが、あまり意味がない関数化のような気もします。
エラーチェックなどをまとめる関数等を作成してmain関数をスッキリさせたいと思っています。
関数の使い方も正しいのかはっきり分かりません。ソースコードを記載しますので
ここが駄目といった部分やこうした方がいい等の助言よろしくお願いします。
#pragma warning ( disable : 4996 )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
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[/url] )
{
/* 引数の個数チェック */
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;
}