#include <stdio.h> int main(void){ double a; double b; char o; //演算子 int x; //繰り返すかどうか do{ printf("電卓です。\n数字を入力してください。\n"); scanf_s("%d", &a); printf("演算子を入力してください。\n"); scanf_s("%c",&o); printf("数字を入力してください\n"); scanf_s("%d", &b); switch (o) { case +: printf("%d+%dの値は%dです", a, b, a + b); break; case -: printf("%d-%dの値は%dです", a, b, a - b); break; case *: printf("%d×%dの値は%dです", a, b, a*b); break; case /: printf("%d÷%dの値は%dです", a, b, a / b); break; case %: printf("%dと%dを割ったときの余りは%dです", a, b, a%b); break; default: printf("演算子は+か-か*か/か%のみ対応しています。"); break; } printf("\n続けますか?Yesなら偶数、Noなら奇数を入力してください。\n"); scanf_s("%d", &y); } while (y % 2 == 0); return 0; }
プログラミング自体初心者です。
電卓を作ってみました。コードをのせるので、ここをこうすると良い、この文よりこの文のほうがいい、など意見やダメ出しをお願いします。
皆さまのくださった意見や、他サイトでの指摘を元に変更してみました。
ただ、0での除算時の対応や、fgets、sscanfなど、まだ理解のできてないものもあります。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
ベストアンサー
そもそも、コンパイルして実行してみましたか?
- まず、コードブロックで投稿してください。入力エリアの上に </> というのがあると思うので、それで。
「ここに言語を入力」のところは、「C」と書いて、「コード」のところにコードを書いてください。 scanf_s
の戻り値を確認していない。while (a % 2 != 1, 0)
が意味不明。2で割った余りが1でないかを調べて、その結果を捨てて、0
って意図は?- 演算子種類を入力した後、
do ~while
でループなので、必ず"1から5の間の整数で入力してください。\n"が表示される。 scanf_s
よりもfgets
とsscanf_s
を組み合わせた方が、わかりやすい動作をします。while(1) { ~~~; if(~) { break; } ~~; }
というループをうまく使うと良いです。
追記:
思い直して、書き直し例のプログラムを載せてみます。
C
1#include <stdio.h> 2 3int getint(char *errmsg){ 4// 整数を入力して返す 5// 整数が入力されなかったらエラーメッセージを出して入力し直し 6 char line[200]; 7 int x; 8 9 while(1) { 10 fgets(line,sizeof(line),stdin); 11 if(sscanf_s(line,"%d",&x)>0){ 12 return x; 13 } 14 printf(errmsg); 15 }; 16} 17 18int main(void){ 19 int a; //整数1 20 int b; //整数2 21 int x; //演算子 22 int y; //続けるかどうか 23 24 do{ 25 a = getint("整数のみを入力してください。\n"); 26 27 printf("演算子を入力してください。\n"); 28 printf("足し算なら1。\n引き算なら2。\n掛け算なら3。\n割り算なら4。\n余りを求めるなら5。\n"); 29 30 while(1) { 31 x = getint("1から5の間の整数で入力してください。\n"); 32 if(x>=1 && x<=5){ 33 break; 34 } 35 printf("1から5の間の整数で入力してください。\n"); 36 } 37 printf("二番目の数字を入力してください\n"); 38 39 b = getint("整数のみを入力してください。\n"); 40 41 switch (x) { 42 case 1: 43 printf("%d+%dの値は%dです", a, b, a + b); 44 break; 45 case 2: 46 printf("%d-%dの値は%dです", a, b, a - b); 47 break; 48 case 3: 49 printf("%d×%dの値は%dです", a, b, a*b); 50 break; 51 case 4: 52 if(b==0){ 53 printf("ゼロでは割れません\n"); 54 break; 55 } 56 printf("%d÷%dの値は%dです", a, b, a / b); 57 break; 58 case 5: 59 if(b==0){ 60 printf("ゼロでは割れません\n"); 61 break; 62 } 63 printf("%dと%dを割ったときの余りは%dです", a, b, a%b); 64 break; 65 } 66 printf("\n続けますか?Yesなら偶数、Noなら奇数を入力してください。\n"); 67 y = getint("Yesなら偶数、Noなら奇数を入力してください。\n"); 68 } while (y % 2 == 0); 69 return 0; 70}
細かいことを言うと、fgetsがEOFを返した場合の考慮も必要ですが、省略。
投稿2015/11/05 11:31
編集2015/11/06 23:44総合スコア84380
0
{}の位置を一定にした方がいいと思いますよ
たとえば
if(){
}
と
if()
{
}
など混じらない方がほかの人が見るときに見やすいです
投稿2015/11/08 14:50
総合スコア30
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
・ゼロ除算のガードが必要
・変数名をもっとわかりやすい名前にすべき
投稿2015/11/05 14:08
総合スコア18155
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2015/11/06 08:58
2015/11/06 11:29
退会済みユーザー
2015/11/06 13:16
0
scanf_s
の戻り値の確認を行わないと、数字以外が入力された場合に予期しない動作が発生します。
私の場合は、**続けますか?Yesなら偶数、Noなら奇数を入力してください。**の後にyes
と入力すると無限ループが発生しました。
文字列が入力された場合は、scanf_s("%s")
が出現するまでscanf_s()
が無視されるのが原因みたいです。
投稿2015/11/06 00:57
総合スコア131
0
- main() にすべての処理を書かずに、適宜 関数に処理を分ける。
- switch による処理分岐を避ける。
この2つの方針を考慮するとよいとおもいます。
質問文のコードとは大きく異なってしまいますが、↓にその方針で書いたコードを示します。
c
1// See http://www.kishiro.com/programming/c/function_pointer.html 2 3#include <stdio.h> 4 5typedef void (*FUNCPTR)(int a, int b); 6 7void op_nil(int a, int b) { 8} 9void op_add(int a, int b) { 10 printf("%d+%dの値は%dです", a, b, a + b); 11} 12void op_sub(int a, int b) { 13 printf("%d-%dの値は%dです", a, b, a - b); 14} 15void op_mul(int a, int b) { 16 printf("%d×%dの値は%dです", a, b,a* b); 17} 18void op_div(int a, int b) { 19 if (b == 0) { 20 printf("0で割ることはできません"); 21 } else { 22 printf("%d÷%dの値は%dです", a, b, a / b); 23 } 24} 25void op_mod(int a, int b) { 26 printf("%dと%dを割ったときの余りは%dです", a, b, a % b); 27} 28 29FUNCPTR operations[] = { &op_nil, &op_add, &op_sub, &op_mul, &op_div, &op_mod }; 30 31int read_quit() { 32 int q; 33 while(1) { 34 int ret; 35 printf("\n続けますか?Yesなら偶数、Noなら奇数を入力してください。\n"); 36 ret = scanf("%d", &q); 37 if (ret == 1) { 38 return (q % 2 == 0); 39 } 40 scanf("%*s"); 41 printf("整数のみを入力してください。\n"); 42 } 43 return 0; 44} 45 46void read_problem(int * a, int * b, int * kind) { 47 printf("電卓です。\n数字を入力してください。\n"); 48 while(1) { 49 int ret = scanf("%d", a); 50 if (ret == 1) { 51 break; 52 } 53 scanf("%*s"); 54 printf("整数のみを入力してください。\n"); 55 } 56 57 printf("演算子を入力してください。\n"); 58 printf("足し算なら1。\n引き算なら2。\n掛け算なら3。\n割り算なら4。\n余りを求めるなら5。\n"); 59 while(1) { 60 int ret = scanf("%d", kind); 61 if (ret == 1) { 62 if ((1 <= *kind) && (*kind <= 5)) { 63 break; 64 } 65 } else { 66 scanf("%*s"); 67 } 68 printf("1から5の間の整数で入力してください。\n"); 69 } 70 71 printf("数字を入力してください\n"); 72 while(1) { 73 int ret = scanf("%d", b); 74 if (ret == 1) { 75 break; 76 } 77 scanf("%*s"); 78 printf("整数のみを入力してください。\n"); 79 } 80} 81 82int main() { 83 int a; // 数値 84 int b; // 数値 85 int kind; // 演算の種類 86 while(1) { 87 read_problem(&a, &b, &kind); 88 operations[kind](a, b); 89 if (read_quit() == 0) { 90 break; 91 } 92 } 93}
投稿2015/11/05 22:20
総合スコア22322
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/11/06 02:39
退会済みユーザー
2015/11/06 08:19
2015/11/06 08:55
0
質問文が編集されて、記載されていたソースコードの挙動が変化したので、
それに合わせて再度、回答コードを投稿します。
電卓を発展させていくことを考えた場合、演算種類が増えていくことが予想されます。
その場合、swich 文、 if-esle では保守がしにくくなります。
そこで、あえてデータ駆動方式で書いてみています。
c
1#include <stdio.h> 2 3typedef void (*FUNCPTR)(int a, int b); 4 5void op_add(int a, int b) { 6 printf("%d+%dの値は%dです", a, b, a + b); 7} 8void op_sub(int a, int b) { 9 printf("%d-%dの値は%dです", a, b, a - b); 10} 11void op_mul(int a, int b) { 12 printf("%d×%dの値は%dです", a, b, a * b); 13} 14void op_div(int a, int b) { 15 if (b == 0) { 16 printf("0で割ることはできません"); 17 } else { 18 printf("%d÷%dの値は%dです", a, b, a / b); 19 } 20} 21void op_mod(int a, int b) { 22 printf("%dと%dを割ったときの余りは%dです", a, b, a % b); 23} 24 25struct { 26 const char op; 27 const FUNCPTR func; 28} const FUNCS[] = { 29 {'+', &op_add}, 30 {'-', &op_sub}, 31 {'*', &op_mul}, 32 {'/', &op_div}, 33 {'%', &op_mod}, 34 {'\0', NULL} // End of Data 35}; 36 37void calc(int a, int b, char op) { 38 for (int i = 0; FUNCS[i].op; i++) { 39 if (FUNCS[i].op == op) { 40 FUNCS[i].func(a, b); 41 return; 42 } 43 } 44 printf("演算子は+か-か*か/か%のみ対応しています。[%c]は不正な指定です。", op); 45} 46 47int read_quit() { 48 int q; 49 while(1) { 50 int ret; 51 printf("\n続けますか?Yesなら偶数、Noなら奇数を入力してください。\n"); 52 ret = scanf("%d", &q); 53 if (ret == 1) { 54 return (q % 2 == 0); 55 } 56 scanf("%*s"); 57 printf("整数のみを入力してください。\n"); 58 } 59 return 0; 60} 61 62void read_problem(int * a, int * b, char * kind) { 63 printf("電卓です。\n数字を入力してください。\n"); 64 while(1) { 65 int ret = scanf("%d", a); 66 if (ret == 1) { 67 break; 68 } 69 scanf("%*s"); 70 printf("整数のみを入力してください。\n"); 71 } 72 73 printf("演算子を入力してください。\n"); 74 while(1) { 75 int ret = scanf(" %c", kind); 76 if (ret == 1) { 77 break; 78 } 79 scanf("%*s"); 80 printf("演算子を入力してください。\n"); 81 } 82 83 printf("数字を入力してください\n"); 84 while(1) { 85 int ret = scanf("%d", b); 86 if (ret == 1) { 87 break; 88 } 89 scanf("%*s"); 90 printf("整数のみを入力してください。\n"); 91 } 92} 93 94int main() { 95 int a; // 数値 96 int b; // 数値 97 char op; // 演算子 98 while(1) { 99 read_problem(&a, &b, &op); 100 calc(a, b, op); 101 if (read_quit() == 0) { 102 break; 103 } 104 } 105}
投稿2015/11/06 14:02
総合スコア22322
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2015/11/05 11:59 編集
2015/11/05 12:49
退会済みユーザー
2015/11/06 08:56
2015/11/06 10:26
2015/11/06 23:46
退会済みユーザー
2015/11/07 23:29