質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

6回答

7402閲覧

C言語 簡易関数電卓作成 エラーばかり

tokey

総合スコア22

char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2016/10/31 19:25

編集2016/10/31 19:35

プログラミング初心者です。
c言語で電卓を作成してみましたが、うまく動いてくれません。

コンパイルできない。 エラー個所をコメントアウトして実行すると、一文字入力後操作を受け付けなくなる。

どこが間違っているのか、どう改善したらよいのかアドバイスをください。
以下コード

#include <string.h> #include <stdio.h> #include <math.h> #define PI 3.141592 int main(void) { char bye = '0'; char op = '0'; char moji[4] = "\0"; char fun = '\0'; double num = 0; double ans = 0; //演算子読み込み step1_1: { scanf("%[q]", &bye); if (bye == 'q') { return 0; } //文字読み込み(読み込まなければ飛ばす) scanf("%[sincostan", &moji); if (moji != "sin" | "cos" | "tan") { goto step1_1; } else if (moji == "sin") { fun = 's'; } else if (moji == "cos") { fun = 'c'; } else if (moji == "tan") { fun = 't'; } //数字読み込み scanf("%lf", &ans); //関数の計算 if (fun == 's') { ans = sin(ans / 180 * PI); } else if (fun == 'c') { ans = cos(ans / 180 * PI); } else if (fun == 't') { ans = tan(ans / 180 * PI); } //リセット op = '\0'; moji[4] = "\0"; fun = '\0'; } while (1) { //演算子読み込み step1_2: { while (1) { scanf("%[q]", &bye); if (bye == 'q') { return 0; } scanf("%[+-*/]", &op); if (op == '+' | '-' | '*' | '/') { break; } else { printf("ERROOR\n"); } return 0; } } //文字読み込み(読み込まなければ飛ばす) scanf("%[sincostan", &moji); if (moji != "sin" | "cos" | "tan") { goto step1_2; } else if (moji == "sin") { fun = 's'; } else if (moji == "cos") { fun = 'c'; } else if (moji == "tan") { fun = 't'; } //数字読み込み scanf("%lf", &num); //関数の計算 if (fun == 's') { num = sin(num / 180 * PI); } else if (fun == 'c') { num == cos(num / 180 * PI); } else if (fun == 't') { num == tan(num / 180 * PI); } //計算 switch (op) { case'+': ans += num; break; case'-': ans -= num; break; case'*': ans *= num; break; case'/': ans /= num; break; } //表示 printf("%f", ans); //リセット op = '\0'; moji[4] = "\0"; fun = '\0'; num = 0; } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

まずC言語の文法間違いが複数あるため、エラーとなるところが多いのは都度修正していかないといけないと思いますが、
文法間違いはとりあえず横へおいといて、全体的なコーディングでのアドバイスですが、

まずgotoは一般的に極力使用を避けるように言われています。理由は多様するとプログラムがあっちこっちへ飛び可読性が著しく落ちるからです。通常プログラムの流れは基本上から下へ読み進んでいけるのですがそれを完全に覆すつくりになってしまうので読みにくくなります。また今回のソースでは仮に正常に動作してもstep1_1:が一番最初に実行されscanf("%[q]", &bye);の部分が原因で、cos等を入力してもらっても先頭が欠けてosとしかとれなくなります。

次にプログラムの基本は同様の処理は複数書かないように心がけて描く事が大事ですが、ansを計算する部分とnumを計算する部分はほぼ同じなのに処理を分けてかいているのでこれも可読性が落ちるのとバグを誘引する原因になります。

という事でプログラムを実際に書く前に日本語レベルでいいので処理の流れを考えてからコーデイングするようにされるとよいとおもいます。

例えば

char inputBuff[12]; char op; doulbe ans; while(1) { scanfで文字入力をしてinputBuffに入れる inputBuff[0]が'q'ならreturnしてプログラム終了 inputBuff[0]が四則演算+-X/だったらopに入れて、continue; inputBuffがsin,cos,tanなら角度を入力させるscanfを実行 { 入力された角度からsin,cos,tanを求める opが四則演算であれば ansと先ほど求めたsinなどをopに従って計算してansに入れる opが四則演算でないなら ans = 先ほどのsinなどの計算値 }else { 無効な入力値 } }

といった形に仕上げたら一応目的の動作をするとおもうので、これで書く日本語をc言語に直していかれると良いと思います。まずは実際にコーディングする前に骨組みを考える事が大事です。

###文法間違い

最初ソースを読んで、多少の修正でアップしようと思ったのですが、少し修正するべきと思われる箇所が多すぎたため、そこは断念し上記のような流れの説明だけにしましたが、一応、気づいた文法間違いについて

scanf("%[sincostan", &moji);
mojiは配列なので&いりません、またフォーマットも??です。

if (moji != "sin" | "cos" | "tan") {

else if (moji == "sin") {
など
c言語は最近の言語のstring型のような使い方がまだできません、strcmpなどで比較してください

step1_1: {step1_2: {
できればGOTOを使うのはやめましょう、ただし、つかうにしても書方と書いている場所が悪いです

投稿2016/11/01 02:29

編集2016/11/01 02:41
hiim

総合スコア1689

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tokey

2016/11/01 06:30

ありがとうございます! コードの骨組みが洗練されていて、とても参考になりました。 BAに選びました。
guest

0

L 21) moji は charの配列 型なので、scanfにて&は不要です。
L 22) 後ろにsin, cos, tanかどうか、を調べているので、最後にelseで飛ばした方がよいです。
L 25) strcmpを利用してください。28,31も同様です。
L 48) char型にchar*型を代入しようとしています。正しくは moji[4] = '\0'です。

前半でちからつきました。参考に後半も書き換えてみてください。

投稿2016/11/01 00:27

tnd-.-b

総合スコア247

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tokey

2016/11/01 06:24

分かりました!ありがとうございます。
guest

0

内容は良く理解していませんが、ただプログラム的に動くコードに変えました。参考としてください。
値は取れるのでdebug文を入れて行けばよろしいかと思います。
二回の同じ処理が有る様にみられますが、一回目は無くされた方が良いと思います。

c

1#include <string.h> 2#include <stdio.h> 3#include <math.h> 4#define PI 3.141592 5 6int main(void) 7{ 8 char bye = '0'; 9 char op = '0'; 10 char moji[4] = "\0"; 11 char fun = '\0'; 12 double num = 0; 13 double ans = 0; 14 char csin[] = "sin"; 15 char ccos[] = "cos"; 16 char ctan[] = "tan"; 17 //演算子読み込み 18step1_1: { 19 scanf("%[q]", &bye); 20 if (bye == 'q') { 21 return 0; 22 } 23 //文字読み込み(読み込まなければ飛ばす) 24 scanf("%[sincostan]", moji); 25 if ( !strcmp(moji,csin) && !strcmp(moji,ccos) && !strcmp(moji,ctan)) { 26 goto step1_1; 27 } 28 else if (strcmp(moji,csin) == 0) { 29 fun = 's'; 30 } 31 else if (strcmp(moji,ccos) == 0) { 32 fun = 'c'; 33 } 34 else if (strcmp(moji,ctan) == 0) { 35 fun = 't'; 36 } 37 //数字読み込み 38 scanf(" %lf", &ans); 39 //関数の計算 40 if (fun == 's') { 41 ans = sin(ans / 180 * PI); 42 } 43 else if (fun == 'c') { 44 ans = cos(ans / 180 * PI); 45 } 46 else if (fun == 't') { 47 ans = tan(ans / 180 * PI); 48 } 49 //リセット 50 op = '\0'; 51 memcpy(moji, "\0", 4); 52 fun = '\0'; 53 } 54 55 while (1) { 56 //演算子読み込み 57 step1_2: { 58 while (1) { 59 scanf("%[q]", &bye); 60 if (bye == 'q') { 61 return 0; 62 } 63 scanf(" %[+-*/]", &op); 64 if (op == '+' | op == '-' | op == '*' | op == '/') { 65 break; 66 } 67 else { 68 printf("ERROR\n"); 69 } 70 return 0; 71 } 72 } 73 //文字読み込み(読み込まなければ飛ばす) 74 scanf(" %[sincostan]", moji); 75 if ( !strcmp(moji,csin) && !strcmp(moji,ccos) && !strcmp(moji,ctan)) { 76 goto step1_2; 77 } 78 else if (strcmp(moji,csin) == 0) { 79 fun = 's'; 80 } 81 else if (strcmp(moji,ccos) == 0) { 82 fun = 'c'; 83 } 84 else if (strcmp(moji,ctan) == 0) { 85 fun = 't'; 86 } 87 //数字読み込み 88 scanf(" %lf", &num); 89 //関数の計算 90 if (fun == 's') { 91 num = sin(num / 180 * PI); 92 } 93 else if (fun == 'c') { 94 num == cos(num / 180 * PI); 95 } 96 else if (fun == 't') { 97 num == tan(num / 180 * PI); 98 } 99 //計算 100 switch (op) { 101 case'+': 102 ans += num; 103 break; 104 case'-': 105 ans -= num; 106 break; 107 case'*': 108 ans *= num; 109 break; 110 case'/': 111 ans /= num; 112 break; 113 } 114 //表示 115 printf("%f\n", ans); 116 //リセット 117 op = '\0'; 118 memcpy(moji, "\0", 4); 119 fun = '\0'; 120 num = 0; 121 } 122}

投稿2016/11/01 00:08

編集2016/11/01 02:54
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tokey

2016/11/01 06:23

二回目の処理はなくしたほうが綺麗ですよね。 ありがとうございます!
guest

0

if (moji != "sin" | "cos" | "tan") {

どこでこんなものを覚えたのか。
if (moji != "sin" | moji != "cos" | moji != "tan") {
と書きましょう。
それと、sinではないかor cosではないか or tanではないか ということはすべてtrueになりますね。

投稿2016/10/31 22:06

maiko0318

総合スコア876

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tokey

2016/11/01 06:20

なるほど!ありがとうございます。
WoodenHamlet

2016/11/08 09:40

if (moji != "sin" | moji != "cos" | moji != "tan") { どこでこんなものを覚えたのか。
guest

0

とりあえず動くようにしてみた(テストはあんまりしてない)
何度も strncmp するのが鬱陶しかったから削ったのと細かな修正くらいかな。enum はもう習ったんだろうか…?
define で一つずつ作ってもいいけど。

C

1#include <string.h> 2#include <stdlib.h> 3#include <stdio.h> 4#include <math.h> 5#include <time.h> 6#include <Windows.h> 7 8#define PI 3.1415926 9 10enum {T_NONE, T_SIN, T_COS, T_TAN,}; 11 12int main(void) 13{ 14 char inputBuff_1[17]; 15 char *inputBuff_2 = &inputBuff_1[1]; 16 char op; 17 double ang; 18 double num; 19 double ans = 0; 20 printf("\n///簡易関数電卓///\n" 21 "\t終了コマンド...q\n" 22 "\t新しく計算するなら、先頭に演算子をつけずに入力\n" 23 "\t続けて計算するなら、先頭に演算子をつけて入力\n\n"); 24 25 printf("%f\n", ans); // 最初の値はあった方が良いと思う(コマンドライン引数で渡せるようにするなど、拡張するかもしれないし) 26 27 while (inputBuff_1[0] != 'q') 28 { 29 char trigonometric = T_NONE; 30 op = '0'; 31 num = 0; 32 33 scanf(" %17s", inputBuff_1); 34 if (inputBuff_1[0] == '+' || inputBuff_1[0] == '-' || inputBuff_1[0] == '*' || inputBuff_1[0] == '/') { 35 op = inputBuff_1[0]; 36 } else if (strncmp(inputBuff_1, "sin", 3) == 0) { 37 trigonometric = T_SIN; 38 } else if (strncmp(inputBuff_1, "cos", 3) == 0) { 39 trigonometric = T_COS; 40 } else if (strncmp(inputBuff_1, "tan", 3) == 0) { 41 trigonometric = T_TAN; 42 } 43 44 if (trigonometric != T_NONE) { 45 // 三角関数の時 46 ang = atof(inputBuff_1 + 3); 47 if (trigonometric == T_SIN) { 48 num = sin(ang * PI / 180); 49 } else if (trigonometric == T_COS) { 50 num = cos(ang * PI / 180); 51 } else if (trigonometric == T_TAN) { 52 num = tan(ang * PI / 180); 53 } 54 } else { 55 // 三角関数以外の時 56 num = atof(inputBuff_2); 57 } 58 59 if (op == '+' | op == '-' | op == '*' | op == '/') { 60 switch (op) { 61 case '+': 62 ans += num; 63 break; 64 case '-': 65 ans -= num; 66 break; 67 case '*': 68 ans *= num; 69 break; 70 case '/': 71 ans /= num; 72 break; 73 74 } 75 printf("%f\n", ans); // 答えの表示部はまとめた方が良いような… 76 } else { 77 ans = num; 78 if (trigonometric != T_NONE) { 79 printf("%f\n", ans); // 答えの表示部はまとめた方が良いような… 80 } 81 } 82 } 83 return 0; 84}

投稿2016/11/08 10:11

WoodenHamlet

総合スコア306

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

お陰様で完成いたしました。
以下コード↓

#include <string.h> #include <stdlib.h> #include <stdio.h> #include <math.h> #include <time.h> #include <Windows.h> #define PI 3.1415926 int main(void) { char inputBuff_1[17]; char inputBuff_2[16]; char op; double ang; double num; double ans = 0; printf("\n///簡易関数電卓///\n" "\t終了コマンド...q\n" "\t新しく計算するなら、先頭に演算子をつけずに入力\n" "\t続けて計算するなら、先頭に演算子をつけて入力\n\n"); while (inputBuff_1[0] != 'q') { op = '0'; ang, num = 0; scanf(" %17s", inputBuff_1); if (inputBuff_1[0] == '+' | inputBuff_1[0] == '-' | inputBuff_1[0] == '*' | inputBuff_1[0] == '/') { op = inputBuff_1[0]; strcpy(inputBuff_2, inputBuff_1 + 1); strcpy(inputBuff_1, inputBuff_2); } if (strncmp(inputBuff_1, "sin", 3) == 0 | strncmp(inputBuff_1, "cos", 3) == 0 | strncmp(inputBuff_1, "tan", 3) == 0) { ang = atof(inputBuff_1 + 3); if (strncmp(inputBuff_1, "sin", 3)) { num = sin(ang * PI / 180); }else if (strncmp(inputBuff_1, "cos", 3)) { num = cos(ang * PI / 180); }else if (strncmp(inputBuff_1, "tan", 3)) { num = tan(ang * PI / 180); } } else { num = atof(inputBuff_1); } //2回目以降 if (op == '+' | op == '-' | op == '*' | op == '/') { switch (op) { case '+': ans += num; break; case '-': ans -= num; break; case '*': ans *= num; break; case '/': ans /= num; break; } printf("%f\n", ans); } //1回目 else { ans = num; if (strncmp(inputBuff_1, "sin", 3) == 0 | strncmp(inputBuff_1, "cos", 3) == 0 | strncmp(inputBuff_1, "tan", 3) == 0) { printf("%f", ans); } } } }

投稿2016/11/06 19:13

tokey

総合スコア22

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

WoodenHamlet

2016/11/08 07:37 編集

ang, num=0 これは ang; num=0; という意味になります(厳密には違いますが…詳しくは「C言語 カンマ」等で調べてください)。つまりangは初期化されませんがそれでいいですか?(コード読み込んでないのですが、危険なにおいがするので) やるなら ang = num = 0; がいいでしょうね(ただしこれはこれで、この記法が嫌いな人はいます) あと、途中で inputBuff_2 にコピーして inputBuff_1 に一文字消して持って行ってるけど、 char *inputBuff_2 として inputBuff_2 = &inputBuff_1[1]; としたらそんな操作いらないんじゃないかなぁと思ったり。
tokey

2019/12/06 04:46

理解しました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問