

現在C#で電卓を作成しているのですが、Funcを使用しても上手に動きません。

やりたいこととしては、`1*2*3`のような、連続した計算になります。  
演算子ボタンを押したとき、答えが出るようにしたいです。

初めは演算子ボタンの中にイコールの処理を入れたのですが、Funcを使えば短く簡潔に書けると言われました。SUBとADDはまだ書き換えていません。クリアボタンを押したときの処理も書き換え中です。

以下が該当のコードになります。

[code]

      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 == 12) {
                    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){
                if (sign != arithmetic.undefined) {
                    decimal num2 = Convert.ToDecimal(textDisplay.Text);
                    decimal Result = 0;
                    Result = num1 + num2;
                    textDisplay.Text = Result.ToString();
                }
                sign = arithmetic.ADD;
                isFirst = true;
            }
            private void SUB_Click(object sender, EventArgs e)
            {
                if (sign != arithmetic.undefined) {
                    decimal num2 = Convert.ToDecimal(textDisplay.Text);
                    decimal Result = 0;
                    Result = num1 - num2;
                    textDisplay.Text = Result.ToString();
                }
                sign = arithmetic.SUB;
                isFirst = true;
            }
            private void MUL_Click(object sender, EventArgs e){
                Func<decimal, decimal, decimal> MUL = (num1, num2) => {
                    return num1 * num2;
                };
                sign = arithmetic.MUL;
                isFirst = true;          
            }  
    
            private void DIV_Click(object sender, EventArgs e){
                Func<decimal,decimal,decimal> DIV = (num1,num2) => {
                    return num1 / num2;
                }
    ;            sign = arithmetic.DIV;
                isFirst = true;
            }
            private void Equal_Click(object sender, EventArgs e){
                decimal num2 = Convert.ToDecimal(textDisplay.Text);
                decimal Result = 0;
                try {
                    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;
                    }
                }
                catch(DivideByZeroException) {
                    textDisplay.Text = "0では割れません";{
                        return;
                    }
                }
    
                textDisplay.Text = Result.ToString();
                isFirst = true;
    　　　　　　　  if (textDisplay.TextLength >= 13) {
                    textDisplay.Text = "桁数超過";  
    
                    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){
    
                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;
            }
        }
    }
    
    
[/code]


CC BY-SA 4.0
2019-04-16T02:41:12.787
54199
2019-04-16T13:08:48.130
2019-04-16T08:18:57.363
32930
32930
question
c#
C#での電卓作成について


画面には結果/入力中の数値を表示するためのTextBox(`textDisplay`)が1つと、[0]〜[9]の数値ボタン、[.][+][-][×][÷][=][Clear]のボタンがある。

現在のあなたのコードでの動作はこんな感じ:

[code]

    操作 TextBoxの表示    
    [1] 1
    [*] (変化無し)
    [2] 2
    [*] (変化無し)
    [3] 3
    [=] 6 (2*3の結果が表示される)
    
[/code]

と言った感じでしょうか。手元にWinFormの実行環境がないので、コードだけ見て書いていますから、誤りがあったら知らせてください。

望まれる動作はこんな感じ:

[code]

    操作 TextBoxの表示    
    [1] 1
    [*] (変化無し)
    [2] 2
    [*] 2 (1*2の結果が表示される)
    [3] 3
    [=] 6 (2*3の結果が表示される…ここでの`2`は1回目の計算結果)
    
[/code]

と言ったところでしょうか。

* * *

『「現在はこういう操作をするとこういう動作になってしまう」「本当はこんな操作をするとこうなってほしい」という事柄をできるだけ具体的に記述する』と言うのは例えばですが、上記のようなことを記述してほしいと言うことです。

私のこの回答は一部推定で書いているので、使い物にならないかもしれませんが、このレベルでどんな動作にしたいのかを記述していただければ、お望みの回答を書けるような方はたくさんいらっしゃると思います。

* * *

あなたの`MUL_Click`には、何らかの計算を行ってその結果を表示するようなコードは一切ないのですから、現在の動作は当たり前の結果だと思いませんか?

演算キーが押されたときには1個前の計算を行わないといけないのですから、それをどこかに覚えていないといけません。あなたのコードの中では`sign`なんてフィールドがあるようですが、`sign`に「1個前の計算」なんて意味はありませんからやめた方が良いですね。

例えば`Func`(`FUNC`ではないはずです。大文字小文字を区別する言語を使うのですから、その辺の感覚はしっかり持ってください)を使うんならこんなフィールドとメソッドを付け加えてやります。

[code]

            private Func<decimal, decimal, decimal> pendingOperation = null;
    
            private void doPendingOperation() {
                if( pendingOperation != null ) {
                    try {
                        decimal num2 = Convert.ToDecimal(textDisplay.Text);
                        decimal result = pendingOperation(num1, num2);
                        textDisplay.Text = result.ToString();
                    }
                    catch(DivideByZeroException) {
                        textDisplay.Text = "0では割れません";
                        return;
                    }
                    if (textDisplay.TextLength >= 13) {
                        textDisplay.Text = "桁数超過";  
    
                        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;
                    }
                }
            }
    
[/code]

演算ボタンを押したら必ずこのメソッドを呼ぶとともに`pendingOperation`を更新します。

[code]

            private void MUL_Click(object sender, EventArgs e){
                doPendingOperation();
                Func<decimal, decimal, decimal> mul = (num1, num2) => {a
                    return num1 * num2;
                };
                pendingOperation = mul;
                isFirst = true;          
            }  
    
            private void DIV_Click(object sender, EventArgs e){
                doPendingOperation();
                Func<decimal,decimal,decimal> div = (num1,num2) => {
                    return num1 / num2;
                };
                pendingOperation = div;
                isFirst = true;
            }
    
[/code]

イコールボタンを押した時の処理もほとんどこのメソッドを呼ぶだけで済みます。

[code]

            private void Equal_Click(object sender, EventArgs e){
                doPendingOperation();
                pendingOperation = null;
                isFirst = true;
            }
    
[/code]

実行どころか、コンパイルが通るかどうかも確認していませんので、あちこち細かい修正が必要になるかもしれませんが、試してみてください。

また、「これは私が期待する動作とは違う」と言う場合には、ご質問を編集して、できるだけ具体的にどんな動作にしたいのかを記述してください。

* * *

**修正**

コメントでいただいた状態での動作が確認できました。「`sign`は使わない」なんて上記の回答中に書いたのに、`Number_Click`中で`sign`を参照している部分を放置してしまっていました。

[code]

            private void Number_Click(object sender, EventArgs e)
            {
                if (isFirst)
                {
                    var str1 = textDisplay.Text == "" ? "0" : textDisplay.Text;
                    num1 = Convert.ToDecimal(str1);
                    textDisplay.Text = "";
                    isFirst = false;
                }
                if (textDisplay.TextLength == 12)
                {
                    return;
                }
                textDisplay.Text =
                   textDisplay.Text + ((Button)sender).Text;
            }
    
[/code]

…とでも修正すれば、とりあえず計算自体ができないなんてことはなくなるかと思います。お試しください。

(すでにお分かりかと思いますが、ADD, SUB, Clearについては、何も手を入れていません。ご自身で修正していってください。)


CC BY-SA 4.0
2019-04-16T04:39:06.370
54201
2019-04-16T13:08:48.130
2019-04-16T13:08:48.130
13972
13972
54199
answer