login register Sysop! about ME  

2020년 11월 14일 19시 52분 00초,     조회수 : 211
  제목 : RE : C# 계산기 구문 해석 좀 부탁드리겠습니다...ㅠㅠ
SEQ : 37142 글쓴이 : 레드플러스

작성 포맷 : TEXT 모드, 자동 줄바꿈 사용

재미있는게, 이 소스가 어디에서 공개된건지 모르지만^^

찾아보니, 몇몇 코드와 주석부분을 제외하고,

제가 2009년에 오프라인에서 강의하면서 동영상 강의를 촬영할 때 만든 소스네요...

결론적으로 말씀드려, 질문에 올려주신 소스에 지정된 설명(Comment)이면 충분할 것 같습니다.

그리고, C#에 입문했을 때에는 이 부분(괄호처리)이 어려울 거라 생각합니다.

제 강의 순서상 C# 기초는 이미 수십 시간 학습한 후 Windows Forms 강의가 진행되는 부분이라서요.

처음에는 "아, 이렇게하면 ~ 이렇게 나오는구나..." 형태로 학습을 진행하고,

나중에 C# 문법이 더 익숙해지면 그 때 다시 보셔도 좋을 것 같습니다.



using System;
using System.Windows.Forms;

namespace DotNetCalc
{
    public partial class DotNetCalc : Form
    {
        private string buffer; 

        public DotNetCalc()
        {
            InitializeComponent();
        }

        private void btnCommand_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            #region 각각의 버튼 클릭시 해당 문자열을 buffer에 담기
            if (btn == btnOne)
            {
                buffer += "1"; 
            }
            else if (btn == btnTwo)
            {
                buffer += "2";
            }
            else if (btn == btnThree)
            {
                buffer += "3";
            }
            else if (btn == btnFour)
            {
                buffer += "4";
            }
            else if (btn == btnFive)
            {
                buffer += "5";
            }
            else if (btn == btnSix)
            {
                buffer += "6";
            }
            else if (btn == btnSeven)
            {
                buffer += "7";
            }
            else if (btn == btnEight)
            {
                buffer += "8";
            }
            else if (btn == btnNine)
            {
                buffer += "9";
            }
            else if (btn == btnZero)
            {
                buffer += "0";
            }
            else if (btn == btnLeft)
            {
                buffer += "(";
            }
            else if (btn == btnRight)
            {
                buffer += ")";
            }
            else if (btn == btnPlus)
            {
                buffer += " + ";
            }
            else if (btn == btnMinus)
            {
                buffer += " - ";
            }
            else if (btn == btnMultiply)
            {
                buffer += " * ";
            }
            else if (btn == btnDivide)
            {
                buffer += " / ";
            }
            else if (btn == btnPoint)
            {
                buffer += ".";
            }
            #endregion
            txtExpression.Text = buffer; 
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            buffer = String.Empty;
            txtExpression.Text = ""; 
        }

        private void btnBackspace_Click(object sender, EventArgs e)
        {
            if (buffer.Length > 0)
            {
                // 마지막 한자리 삭제
                buffer = buffer.Substring(0, buffer.Length - 1);
                txtExpression.Text = buffer;  
            }
        }

        // 문자열로 지정된 수식을 실제 수식으로 변환 후 계산
        private void btnEnter_Click(object sender, EventArgs e)
        {
            // 문자열 수식에서 공백 제거
            string temp = txtExpression.Text.Replace(" ", "");
            if (String.IsNullOrEmpty(temp))
            {
                MessageBox.Show("수식을 입력하시오.");
                return;
            }
            this.txtExpression.Text += 
                " = \r\n\r\n" + MakeExpression(ref temp).ToString();
            buffer = ""; // 버퍼 초기화 
        }

        /// <summary>
        /// [4] 문자열로 지정된 계산식을 실제 계산식으로 변경
        /// </summary>
        /// <param name="str">3 * (2 + 3)</param>
        /// <returns>15</returns>
        public double MakeExpression(ref string str) {
            int index = 0; // 문자 위치
            // 구문 결과값 가져오기
            double value = Sentence(ref str, ref index); 
            while (index < str.Length) {
                switch (str[index]) {
                    case '+':
                        ++(index);
                        value += Sentence(ref str, ref index);
                        break;
                    case '-':
                        ++(index);
                        value -= Sentence(ref str, ref index);
                        break;
                    default: // 엉뚱한 값이 들어오는 경우                        
                        MessageBox.Show("잘못된 구문입니다.");
                        break;
                }
            }
            return value;
        }

        /// <summary>
        /// [3] 하나의 완성된 수식을 계산하는 메서드
        ///     (3 * 5) = 15
        /// </summary>
        /// <param name="str">(3 * 5)</param>
        /// <param name="index">0</param>
        /// <returns>15</returns>
        public double Sentence(ref string str, ref int index) {
            double value = GetNumber(ref str, ref index); // 첫번째 숫자  
            while (index < str.Length) {
                if (str[index] == '*') {
                    ++(index);
                    value *= GetNumber(ref str, ref index);
                }
                else if (str[index] == '/') {
                    ++(index);
                    value /= GetNumber(ref str, ref index);
                }
                else
                    break;
            } 
            return value;
        }

        /// <summary>
        /// [2] 문자열에서 첫번째 나오는 숫자형을 
        ///     실제 숫자형으로 변환시켜주는 함수
        /// </summary>
        /// <param name="str">(12.34+3)</param>
        /// <param name="index">1</param>
        /// <returns>12.34(숫자형)</returns>
        public double GetNumber(ref string str, ref int index) {
            double value = 0.0;
            // GetSubstring함수 호출해서 괄호안에 있는 문자열만 가져오기               
            if (str[index] == '(') {
                ++(index);
                string substr = GetSubstring(ref str, ref index);
                return MakeExpression(ref substr); // 괄호안의수식만 먼저 계산
            }
            while ((index < str.Length) && Char.IsDigit(str, index)) {
                value = 10.0 * value + Char.GetNumericValue(str[(index)]);
                ++(index);
            }
            if ((index == str.Length) || str[index] != '.') return value;
            double factor = 1.0;
            ++(index);
            while ((index < str.Length) && Char.IsDigit(str, index)) {
                factor *= 0.1;
                value = value + Char.GetNumericValue(str[index]) * factor;
                ++(index);
            }
            return value;
        }

        //[1] 괄호안에 있는 하위 문자열 추출 : (123+5) => 123+5만 추출
        public string GetSubstring(ref string str, ref int index) {
            string substr = ""; // 하위 문자열 저장                      
            int numL = 0; // 왼쪽 괄호의 개수
            int bufindex = index; // 인덱스의 시작 값 
            while (index < str.Length) {
                switch (str[index]) {
                    case ')':
                        if (numL == 0) {
                            char[] substrChars = new char[index - bufindex];
                            str.CopyTo(bufindex, substrChars, 0, substrChars.Length);
                            substr = new String(substrChars);
                            ++(index);
                            return substr;
                        }
                        else
                            numL--; // 왼쪽 괄호와 일치하는 오른쪽 괄호가 나타날 시 감소                      
                        break;
                    case '(':
                        numL++;
                        break;
                }
                ++(index);
            }
            MessageBox.Show("잘못된 구문입니다.");
            return substr;
        }
    }
}



  chmgx0405
  2020-11-16(14:54)
캐릭 이미지
답변주셔서 감사드립니다...
공부법 순서가 그럼 winform은 나중에 하고 기초문법부터 익힌후에 하는게 낫다는말씀이
신지...

  레드플러스
  2020-11-17(08:39)
캐릭 이미지
순서는 일반적으로 C# 콘솔 앱을 먼저하긴하는데요.
Windows Forms가 더 눈에 잘 들어오기에 윈폼부터 시작해도 좋습니다.
다만, 질문 주신 계산기 로직은 C# -> Windows Forms 순서로 학습하는 중간 단계이기
에,
제 경험상 따라하는 학생분들이 그리 어렵지 않게 넘어갔던 기억이 있습니다.
그리고, 소스 분석은 Visual Studio의 F11 단축키를 수십번 사용하면 분석하기에 도움이
됩니다.



제목 작성자 날짜 조회
C# 걔산기 구문해석좀 부탁드리겠습니다...ㅠㅠ chmgx0405 2020-11-13 172
RE : C# 계산기 구문 해석 좀 부탁드리겠습니다...ㅠㅠ (2) 레드플러스 2020-11-14 211

 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})