none
계산기 사칙연산 구현관련 질문 RRS feed

  • 질문

  • 안녕하세요.

    uwp app 개발 학습을 위해서 간단한 계산기 앱을 개발하다가 막히는 부분이 생겨 질문을 올립니다.

    UI 디자인은 다음과 같이 구현했습니다.

    위의 디자인에서 다음의 요구사항을 충족하도록 코드를 구현하였습니다.

    • 마우스, 키보드 둘 다 이용가능할 것
    • 엔터키를 치면 결과가 나오게 할 것
    using Windows.UI.Xaml.Controls;
    using System.Windows.Input;
    
    // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
    
    namespace App1
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            string sMath;
            public MainPage()
            {
                InitializeComponent();
                btnOne.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnTwo.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnThree.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnFour.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnFive.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnSix.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnSeven.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnEight.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnNine.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnZero.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnClear.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnPlus.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnMinus.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnTimes.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                btnDiv.Click += new Windows.UI.Xaml.RoutedEventHandler(button_click);
                KeyDown += new Windows.UI.Xaml.Input.KeyEventHandler(NumKeyDown);
            }
    
            private void button_click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                Button btn = sender as Button;
                string s = (string)btn.Content;
                txtOutput.Text += s;
                if (btn == btnClear)
                    txtOutput.Text = "";
    
            }
            private void NumKeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
            {
                //define key-in
                if (e.Key >= Windows.System.VirtualKey.Number0 && e.Key <= Windows.System.VirtualKey.Number9)//number key
                    txtOutput.Text += ((int)e.Key - 48).ToString();
                else if (e.Key >= Windows.System.VirtualKey.NumberPad0 && e.Key <= Windows.System.VirtualKey.NumberPad9)//numeric keypad
                    txtOutput.Text += ((int)e.Key - 96).ToString();
                else if (e.Key == Windows.System.VirtualKey.Add)//operator + on numeric keypad
                    txtOutput.Text += "+";
                else if (e.Key == Windows.System.VirtualKey.Subtract)//operator - on numeric keypad
                    txtOutput.Text += "-";
                else if (e.Key == Windows.System.VirtualKey.Multiply)//operator * on numeric keypad
                    txtOutput.Text += "*";
                else if (e.Key == Windows.System.VirtualKey.Divide)//operator / on numeric keypad
                    txtOutput.Text += "/";
                else if (e.Key == Windows.System.VirtualKey.C)
                    txtOutput.Text = "";
    
                if (e.Key == Windows.System.VirtualKey.Enter)
                {
                    sMath = txtOutput.Text.ToString();
                    while(sMath.Length>0)
                    {
                        sMath = sMath.Replace(" ", "").Replace("=", "");
                        sMath = MathParcer.EvalExpression(sMath.ToCharArray()).ToString();
                    }
                    txtOutput.Text = sMath;
                }
                
            }
        }
        public class MathParcer
        {
            public static double EvalExpression(char[] expr)
            {
                return parseSummands(expr, 0);
            }
            private static double parseSummands(char[] expr, int index)
            {
                double x = parseFactors(expr, ref index);
                while (true)
                {
                    char op = expr[index];
                    if (op != '+' && op != '-')
                        return x;
                    index++;
                    double y = parseFactors(expr, ref index);
                    if (op == '+')
                        x += y;
                    else
                        x -= y;
                }
            }
            private static double parseFactors(char[] expr, ref int index)
            {
                double x = GetDouble(expr, ref index);
                while (true)
                {
                    char op = expr[index];
                    if (op != '/' && op != '*')
                        return x;
                    index++;
                    double y = GetDouble(expr, ref index);
                    if (op == '/')
                        x /= y;
                    else
                        x *= y;
                }
            }
            private static double GetDouble(char[] expr, ref int index)
            {
                string dbl = "";
                //to cover floating number
                while (expr[index] >= 48 && expr[index] <= 57 || expr[index] == 46)
                {
                    dbl = dbl + expr[index].ToString();
                    index++;
                    if (index == expr.Length)
                    {
                        index--;
                        break;
                    }
                }
                return double.Parse(dbl);
            }
        }
    }

    위 코드를 빌드하고 실행해봤더니 이런 현상이 일어나더군요.

    예를 들어 "123+456"을 치고 엔터키를 치면, 123+456이 화면에 찍힌 이후에 "="이 찍히면서 합의 결과가 찍혀야 하는데, 그러지 않고 "123+4561"이 찍힙니다.

    왜 이런 현상이 생기는지 제가 봐 가지고는 잘 모르겠네요.(디버깅을 돌려봐도 알 수가 없네요)

    고수님들의 지적 및 tip을 기다리겠습니다.

    • 편집됨 ohseihyung 2017년 11월 15일 수요일 오전 3:09
    2017년 11월 15일 수요일 오전 3:07

답변

  • 잘 모르겠지만, 대략 보면 Enter 키처리할 때, 아래 sMath에 123+456 이 들어가있다고 보고

                if (e.Key == Windows.System.VirtualKey.Enter) {
                    sMath
    = txtOutput.Text.ToString(); // 여기서 sMath에 123+456 이 들어간다고 가정하면,
                   
    while(sMath.Length>0)
                   
    {
                        sMath
    = sMath.Replace(" ", "").Replace("=", "");
                        sMath
    = MathParcer.EvalExpression(sMath.ToCharArray()).ToString();  // 여기서 sMath 는 579 가 될 것 같은 데요... 그럼 어케 되나요? while 루프를 빠져 나올 수 있나요?
                   
    }
                    txtOutput
    .Text = sMath;
               
    }

    이 부분을 함 점검해보시면 어떨지요 ...

    • 답변으로 표시됨 ohseihyung 2017년 11월 18일 토요일 오후 12:06
    2017년 11월 16일 목요일 오전 5:43

모든 응답

  • 잘 모르겠지만, 대략 보면 Enter 키처리할 때, 아래 sMath에 123+456 이 들어가있다고 보고

                if (e.Key == Windows.System.VirtualKey.Enter) {
                    sMath
    = txtOutput.Text.ToString(); // 여기서 sMath에 123+456 이 들어간다고 가정하면,
                   
    while(sMath.Length>0)
                   
    {
                        sMath
    = sMath.Replace(" ", "").Replace("=", "");
                        sMath
    = MathParcer.EvalExpression(sMath.ToCharArray()).ToString();  // 여기서 sMath 는 579 가 될 것 같은 데요... 그럼 어케 되나요? while 루프를 빠져 나올 수 있나요?
                   
    }
                    txtOutput
    .Text = sMath;
               
    }

    이 부분을 함 점검해보시면 어떨지요 ...

    • 답변으로 표시됨 ohseihyung 2017년 11월 18일 토요일 오후 12:06
    2017년 11월 16일 목요일 오전 5:43
  • 먼저 tip 감사드립니다. 

    이 경우에는 loop 자체가 필요가 없었는데 제가 뭐가 씌였는지 루프를 돌렸네요...ㅜ.ㅜ

    다음과 같이 해결했습니다.

    private void NumKeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
            {
                //define key-in on number or numeric keyboard
                if (e.Key >= Windows.System.VirtualKey.Number0 && e.Key <= Windows.System.VirtualKey.Number9)//number key
                    txtOutput.Text += ((int)e.Key - 48).ToString();
                else if (e.Key >= Windows.System.VirtualKey.NumberPad0 && e.Key <= Windows.System.VirtualKey.NumberPad9)//numeric keypad
                    txtOutput.Text += ((int)e.Key - 96).ToString();
                else if (e.Key == Windows.System.VirtualKey.Add)//operator + on numeric keypad
                    txtOutput.Text += "+";
                else if (e.Key == Windows.System.VirtualKey.Subtract)//operator - on numeric keypad
                    txtOutput.Text += "-";
                else if (e.Key == Windows.System.VirtualKey.Multiply)//operator * on numeric keypad
                    txtOutput.Text += "*";
                else if (e.Key == Windows.System.VirtualKey.Divide)//operator / on numeric keypad
                    txtOutput.Text += "/";
                else if (e.Key == Windows.System.VirtualKey.C)
                    txtOutput.Text = "";
    
                if((int)e.Key == 187)//equal(=) key
                {
                    string sMath = txtOutput.Text;
                    double result = MathParcer.EvalExpression(sMath.ToCharArray());
                    txtOutput.Text = sMath + "=" + result.ToString();
                }
            }
    거듭 팁 감사드립니다... 다만 아쉽다면 enter key로 하고 싶었는데 도저히 안 되네요...

    2017년 11월 18일 토요일 오후 12:06