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

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

ただいまの
回答率

90.53%

  • C#

    8820questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

**1+2+3のような、連続で計算がしたい。**

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 368
退会済みユーザー

退会済みユーザー

C#を始めて1週間足らずで、理解が追いついていないところも多々あるので、
お力をお貸しください。。。

現在、C#にて電卓の作成をしております。
ですが、どうにも
1+2+3のような、連続した計算のやり方がわかりません。
iPhoneの計算機のような計算がしたいです。

該当のソースコード

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        bool isFirst = true;
        decimal num1 = 0;

        //数字のボタンを押したとき
        private void Number_Click(object sender, EventArgs e)
        {
            if (sign != arithmetic.undefined && isFirst)
            {
                num1 = Convert.ToDecimal(textDisplay.Text);
                textDisplay.Text = "";
                isFirst = false;
            }

            if (textDisplay.TextLength == 10)
            {
                return;
            }

            textDisplay.Text =
                textDisplay.Text + ((Button)sender).Text;

        }

        //小数点を押したとき
        private void Dot_Click(object sender, EventArgs e)
        {
            if (textDisplay.Text.IndexOf(".") >= 0)
            {
                return;
            }
            textDisplay.Text = textDisplay.Text + ".";
        }

        //四則演算
        enum arithmetic
        {
            undefined,ADD,SUB,MUL,DIV
        };
    arithmetic sign = arithmetic.undefined;

        //足し算private void ADD_Click(object sender, EventArgs e)
        {
            sign = arithmetic.ADD;
            isFirst = true;
        }

        //引き算private void SUB_Click(object sender, EventArgs e)
        {
            sign = arithmetic.SUB;
            isFirst = true;
        }

        //掛け算private void MUL_Click(object sender, EventArgs e)
        {
            sign = arithmetic.MUL;
            isFirst = true;

        }

        //割り算private void DIV_Click(object sender, EventArgs e)
        {
            sign = arithmetic.DIV;
            isFirst = true;

        }

        //イコールを押したとき
        private void Equal_Click(object sender, EventArgs e)
        {
            decimal num2 = decimal.Parse(textDisplay.Text);
           decimal Result = 0;

            //switch構文
            switch (sign) {
                case arithmetic.ADD:
                    Result = num1 + num2;
                    break;
                case arithmetic.SUB:
                    Result = num1 - num2;
                    break;
                case arithmetic.MUL:
                    Result = num1 * num2;
                    break;
                case arithmetic.DIV:
                    Result = num1 / num2;
                    break;
                default:
                    num1 = num2;
                    break;
            }

            //結果表示
            textDisplay.Text = Result.ToString();
            isFirst = true;

            if (textDisplay.TextLength >= 11)
            {
                textDisplay.Text = "Error";

                //エラー時、クリアボタン以外を無効化する
                this.button0.Enabled = false;
                this.button1.Enabled = false;
                this.button2.Enabled = false;
                this.button3.Enabled = false;
                this.button4.Enabled = false;
                this.button5.Enabled = false;
                this.button6.Enabled = false;
                this.button7.Enabled = false;
                this.button8.Enabled = false;
                this.button9.Enabled = false;
                this.buttonEq.Enabled = false;
                this.Dot.Enabled = false;
                this.ADD.Enabled = false;
                this.SUB.Enabled = false;
                this.MUL.Enabled = false;
                this.DIV.Enabled = false;
            }

        }

        //クリアボタンを押したとき
        private void Clear_Click(object sender, EventArgs e)
        {
            textDisplay.Clear();

            this.button0.Enabled = true;
            this.button1.Enabled = true;
            this.button2.Enabled = true;
            this.button3.Enabled = true;
            this.button4.Enabled = true;
            this.button5.Enabled = true;
            this.button6.Enabled = true;
            this.button7.Enabled = true;
            this.button8.Enabled = true;
            this.button9.Enabled = true;
            this.buttonEq.Enabled = true;
            this.Dot.Enabled = true;
            this.ADD.Enabled = true;
            this.SUB.Enabled = true;
            this.MUL.Enabled = true;
            this.DIV.Enabled = true;
        }


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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2019/04/15 20:55

    解決したならベストアンサーを選択してください。
    完成までサポートするものではなく、一つの問題に対して一つの回答をするものです。

    キャンセル

回答 3

+2

1+2+3のような、連続した計算のやり方がわかりません。

ご提示のコードは数字や演算子のボタンがたくさんありそうなのでコードを読んだ限りで、実際には試していないのですが、例えば「1 + 2 + 3 - 4 =」などと入力されるケースでは演算子の次の整数(または小数)が確定したときに答えを求めて表示してしまえば良いと思います。例えば、

  1. "1" が入力されたら(最初なので)ただ、変数v1(名前は何でも良いし、プロパティで可)に保存する。表示もする。
  2. "+" が入力されたら演算子なので、"+"を保存する。(既にarithmetic signで使っていますよね)
  3. "2" が入力されたら既に整数v1 に値が保存されてあり、演算子"+"もあるので計算可能な状態とみなせる。1 + 2 を計算して答え3 を表示する。(表示タイミングは再考/この時点で表示してしまうと2桁以上の数値入力で破綻してしまうので不適切です - 追記をご覧ください)3は引き続き次の計算に使うため、変数v1 に保存する。
  4. "+" が入力されたら演算子なので、"+"を保存する。
  5. "3" が入力されたら変数v1 とarithmetic signで示される"+"で 3 + 3 を計算し、答6 を表示する。6は、引き続き次の計算に使うため、変数v1 に保存する。
  6. "-" が入力されたら演算子なので、"-"を保存する。
  7. "4" が入力されたら変数v1 とarithmetic signで示される"-"で 6 - 4 を計算し、答2 を表示する。2は、引き続き次の計算に使うため、変数v1 に保存する。
  8. "=" が入力されたら、答え表示完了の為の色々な処理をする。(既に答えは表示されてるけど)
    ...以下同じ

整数や小数、演算子が入力されるごとに逐一「今現在、どんな状態で何ができるか」を意識して処理すると良いです。「状態遷移」の考え方です。一例として参考にしてみてください。


コメントを受けて追記しました:2019/04/13 11:06
※オリジナルの回答を大きく編集してしまうと、コメントでいただいた指摘事項の対応が分かりづらくなると思いましたので、編集は最低限にしました。

数値の範囲と入力確定の問題(Zuishinさんのご指摘より):

回答では数値として1桁だけのものを例示してしまいましたが、当然そんなものでは実用にならないわけで、考慮不足であったことは失礼しました。2桁以上入力すると破綻しますので、少なくとも数値の入力を確定するのは次の演算子(+, -, * , /, =)入力時点とすべきでしょう。

演算子の優先順位の問題(YAmaGNZさんのご指摘より):

簡単な四則演算をする電卓でも、演算子の優先順位(乗除は加減を優先)を考慮するものとしないものがあります。

(1) 演算子の優先順位を考慮する電卓
iPhone(iOS12.2)の「計算機」やAndroid(6.0.x)標準の「電卓」で確認したところでは、優先順位を意識した動きになっていて、常に数式の全体を見て、再計算されます。(私はこれは今回初めて知りました)

使ってみて面白いと思ったのは、例えばAndroidで表示領域が大きいものでは2桁以上の値を入力すると逐次に再計算される、と言うことです。
「1 + 23 * 45」の場合、「1 + 2 で 3を表示」「1 + 23 で 24を表示」「1 + 23 * 4 で 93を表示」で「1 + 23 * 45 で1036を表示」と遷移していきます。

いずれにせよYAmaGNZさんのご指摘のように、入力された数式を何らかの方法ですべて覚えていて、終わりを示す演算子の入力(例えば=)が無ければ答えは出ないということになります。面倒ですが、単語分割(トークナイズ)など様々な検討事項が増えて、プログラミングトピック的には面白いとは思います。

(2) 演算子の優先順位を考慮しない電卓
一般的な実物の電卓では優先順位は考慮せず、逐次に計算されるものが多いようです。例えば 「1 + 2 * 3 = 9」となります。(手持ちのCanon HS-2200Aで確認)関数電卓などでは違うかもしれません。回答では勝手にこの動きを想定してしまいましたが、質問者さんのケースではどちらかを動作仕様として意識する必要があるかと思います。

尚、Windows (7と10で確認)の「電卓」では、メニューで選択するところの「普通の電卓」でこの動きとなり、「関数電卓」と「プログラマ」では優先順位を考慮する動きになっています。

逐次に答えが完成する、と言う意味ではこちらの方が簡単ではあります。

本件と直接関係あるとは限りませんが、teratailでも「電卓」に関して過去、様々な質問回答があったようです。teratail「電卓」で検索するとたくさん出てきます。改めて考えると、プログラミングの課題(なのか分かりませんが)として適切なもののひとつなのかもしれません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/13 07:39

    1 + 21 を計算する時には 1 + 3 22 と表示されると思いますが、iPhone の計算機はそういう表示の仕方なんでしょうか?

    キャンセル

  • 2019/04/13 07:50

    質問者さんが求めているレベルが「1+2*3=」と入力された時、結果が9なのか7なのかで変わってきますが
    前者であれば、3.の時点での演算ではなく、4.の時点で前に入力されたものを演算では?
    後者であれば、式が確定するまで演算できないことになりますが

    キャンセル

  • 2019/04/13 08:03

    Zuishinさん、YAmaGNZさん、ご指摘どうもありがとうございます。そのとおりだと思います。投稿した後、「そもそも1桁しか対応できず、入力を阻害するな」と自分でも思いましたが、ご指摘をうけて改めてiPhoneの電卓と普通の電卓の動きを確認しました。回答のフローは思慮が足りませんでした。訂正させていただきます。

    キャンセル

  • 2019/04/13 10:27 編集

    "1+2+3"でググると、とても面白い検索結果が出てきますね。
    一時期iPhoneの電卓では、1+2+3=24 ってなる現象が発生したらしいです。
    それを再現したいわけではないでしょうけど

    キャンセル

  • 2019/04/13 10:31

    機能が豊富すぎて使いこなせませんね
    https://mag.app-liv.jp/archive/79115

    キャンセル

  • 2019/04/13 10:32

    様々な電卓を確認していて(少なくとも私にとって)色々なことが分かりました。大変興味深いです。

    キャンセル

  • 2019/04/13 18:51

    質問者さんの要望は前者のほうみたいですね。
    それであれば、dodox86さんのおっしゃるように、状態遷移を考えて作っていけばいいかと思います。
    https://blog.goo.ne.jp/masaki_goo_2006/e/d77c7b85b3dbc04b1b36cf88eaf57d73
    こちらのように、キーを押したら、何がどう変わっていくか書き出すと分かりやすいかと思います。

    キャンセル

  • 2019/04/13 22:05

    皆様ありがとうございます。
    参考にさせていただき、考えてみたのですが理解ができておらず、どの部分にどのようなコードを書いたらいいのかがわかりません。
    もう少しヒントをいただけないでしょうか。

    キャンセル

  • 2019/04/13 23:34

    解決しました!!!
    残りの修正は、ぼちぼちとやっていきます。

    解答してくださった皆様、
    本当にありがとうございました!!!

    キャンセル

+2

ひょっとしたら、入力された計算式をまとめて計算する関数電卓的な動作にしたいのでしょうか?
Windowsの電卓の電卓モードと、関数電卓モードで1+2*3=を入力してみてください。
前者は9が、後者は7が返ってきます。
後者を実現するには文字列の計算式の計算結果を取得するが参考になると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

とりあえず、現状のソースから修正するとすればです。
例えば、下記の+を押したときの処理ですが

//足し算
private void ADD_Click(object sender, EventArgs e)
{
    sign = arithmetic.ADD;
    isFirst = true;
}


2番目の数字の入力の後に押された時は、signがarithmetic.undefined以外になっているかと思います。
ですので、押された時にsign != arithmetic.undefinedの場合、=を押された時の処理を行い、その後1つ目の数字入力後の+が押された時の状態に移行すればいいことになります。

//足し算
private void ADD_Click(object sender, EventArgs e)
{
    if(sign != arithmetic.undefined)
    {
        //=の時の処理
    }
    sign = arithmetic.ADD;
    isFirst = true;
}


ただし、+が連続で押された場合などの、各ボタンが正しい手順以外の操作が行われた時のことが考慮されていないので、そういった操作を行われた場合は無視するなどの処理が必要になるかと思います。
ここでも状態遷移をしっかり管理しておかないと、正しい動作なのか、誤った操作なのかが判断できません。
その管理を行おうとすると、ソースの修正はかなり必要になってくるはずです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C#

    8820questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。