티스토리 뷰

반응형

C# 프로그래밍, 계산기 편

안녕하세요! 제가 C#을 공부하면서 간단하게 계산기를 만들어 보았는데 아직 부족하지만 오늘 시간에는 계산기를 구현한 코드를 설명해보는 시간을 가져볼까 합니다. 먼저 제가 만들려는 계산기의 간단한 틀과 기능을 설명하겠습니다.


계산기에 들어갈 기능 중에서 연산 기능은 사칙연산인 더하기와 뺄셈, 곱셈, 나누기를 수행할 수 있도록 정하였고 사용자 값으로 입력할 수 있는 숫자로는 0부터 9까지로 정하였습니다. 또 연산된 결과를 나타내기 위해서 등호 기호를 사용하였고 수행한 과정과 결과를 날려버릴 클리어 기능도 추가로 표현하였습니다. 


이 연산 기능과 숫자들은 버튼으로 만들었고 그 과정과 결과를 지켜볼 수 있는 창을 하나 만들어서 UI를 표현하기로 정하였고 그 UI는 아래와 같습니다.


 

하얀색 창에 나오는 초기 값은 먼저 0으로 설정해두었습니다. 추가로 제가 만들려는 계산기에 틀에 대해서 말해야 할 것이 있습니다. 그건 '='(등호기호)에 대한 이야기로 다른 계산기들은 숫자를 입력하고 등호 기호를 누르면 그에 대한 결과가 나오는데 이 상태에서 다시 숫자를 입력하면 결과를 사라지고 새로운 연산을 수행하도록 하지만 저는 그 결과의 연장선으로 다시 숫자를 입력하면 그 결과에 붙어서 나오도록 계산기를 만들어보았습니다. 예를 들면 '3+3'의 결과는 '6'인데 여기서 숫자 '5'를 입력하면 '5'가 아니라 '65'가 보인다는 것입니다. 


이제부터는 계산기 코드에 사용된 필드와 메서드의 역할을 코드의 처음부터 한번 분석해보겠습니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
        
namespace WindowsFormsApp1
{
    public enum Operators { Add, Sub, Multi, Div }
 
    public partial class Calculator : Form
    {
        public int Result = 0;
        public bool isNewNum = true;
        public bool isBehindEqualKey = true;
        public bool isEqualLive = true;
        public int CalCount = 1;
        public Operators Opt = Operators.Add;
 
        public Calculator()
        {
            InitializeComponent();
        }
cs

 

클래스는 아무래도 계산기이니 'Calculator'로 이름을 만들어보았구요. 클래스 위쪽을 보면 enum 타입으로 'Operators'라는 이름으로 정의된 모습을 볼 수 있고 만든 enum 타입이 가질 수 있는 값은 'Add'와 'Sub', 'Multi', 'Div'로 사칙연산을 표현한 것으로 이는 나중에 연산자 버튼을 클릭했을 때 사용될 것입니다.


int형 변수인 'Result'는 입력된 숫자의 값과 연산된 값을 기억하는 변수이고 'CalCount'는 연산을 몇 번 수행했는지를 측정하는 변수입니다. 나머지는 bool형 변수로 'isNewNum'은 숫자 버튼을 누를 때 지금 상태가 새로운 값을 입력하는지를 나타낸 것이고 'isBehindEqualKey'와 'isEqualLive'는 등호 기호와 연관된 것으로 나중에 설명하고 아까 정의한 enum 타입을 'Opt'라는 이름으로 변수를 선언하였습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void NumButton1_Click(object sender, EventArgs e)
        {
            Button NumButton = (Button)sender;
            SetNum(NumButton.Text);
        }
 
        public void SetNum(string num)
        {
            if (isNewNum)
            {
                NumScreen.Text = num;
                isNewNum = false;
            }
            else
                NumScreen.Text += num;          
        }
cs


위의 'NumButton1_Click' 메서드는 숫자 버튼을 입력했을 때 발생하는 이벤트를 처리하는 메서드로 핸들러라고도 합니다. 0부터 9까지의 모든 숫자를 처리하기 위해서 object형으로 매개변수를 받아서 이 object형을 다시 Button형으로 바꾸는 작업을 하였습니다. 


그 다음에는 Button형의 텍스트 속성을 'SetNum' 메서드의 매개변수로 입력하는데 'SetNum' 메서드의 역할은 창에 숫자를 나타내는 것으로 'NumScreen.Text'에 문자열을 입력하면 해당하는 문자열을 창에 출력하게 됩니다. 여기서 if 문에 조건으로 'isNewNum'이 들어있는 이유는 아까 말했다시피 입력한 숫자가 새로운 피연산자인지를 판단하기 위함입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public void SetCal(Operators Opt)
        {
            int num = int.Parse(NumScreen.Text);
 
            switch (Opt)
            {
                case Operators.Add:
                    Result += num;
                    break;
                case Operators.Sub:
                    Result -= num;
                    break;
                case Operators.Multi:
                    Result *= num;
                    break;
                default:
                    Result /= num;
                    break;
            }
        }
 
        private void NumPlus_Click(object sender, EventArgs e)
        {
            if (!isNewNum)
            {
                if (CalCount > 1)
                    SetCal(Opt);
 
                CalCount++;
 
                Button optButton = (Button)sender;
 
                if (optButton.Text == "+")
                    Opt = Operators.Add;
                else if (optButton.Text == "-")
                    Opt = Operators.Sub;
                else if (optButton.Text == "*")
                    Opt = Operators.Multi;
                else
                    Opt = Operators.Div;
 
                if (isBehindEqualKey)
                {
                    Result = int.Parse(NumScreen.Text);
                    isBehindEqualKey = false;
                }
 
                isNewNum = true;
                isEqualLive = true;
            }
        }
cs


위의 사진은 입력받은 숫자를 연산하는 역할을 수행하는 'SetCal' 메서드와 연산자(+와 -, x, /) 버튼을 클릭하면 발생하는 이벤트 핸들러인 'NumPlus_Click'으로 모든 연산자 버튼을 클릭할 경우 'NumButton1_Click'와 같이 하나의 메서드로 버튼을 처리합니다. 


먼저 'NumPlus_Click'을 살펴보면 매개변수로 object형을 받는데 이를 아까와 같이 Button형으로 변환시켜주면 됩니다. 이 메서드의 경우 맨 처음에 if 문으로 'isNewNum'이 false 값일 때만 메서드의 내용을 처리하도록 하였는데 이는 등호 버튼을 누르고 이어서 연산자 버튼을 눌렀을 때 연산을 수행하지 않도록 예외처리를 한 것입니다.


그리고 'CalCount'가 1보다 큰 값일 때만 'SetCal' 메서드를 처리하는데 이는 연산을 수행하려면 최소 2개의 숫자가 입력되야한다고 여겨져서 그렇고 그리고 연산된 값을 가지는 'Result'가 초기 값이 0이라서 이렇게 처리했습니다. object형이 Button형으로 형 변환되면 연산자 버튼이 어떤 문자열을 가지고 있는지를 if ~ else if 문으로 판단해서 윗 부분에서 정의한 enum 타입으로 만들어진 변수 'Opt'에 문자열에 맞는 사칙연산을 대입합니다.


아래에 if 문으로 'isBehindEqualKey'를 검사해서 true 값일 때만 내용을 처리하는데 이 'isBehindEqualKey'는 연산자 버튼을 클릭하기 이전에 등호 버튼을 클릭하였는지를 나타낸 것으로 이 값이 true이면 연산된 값을 Result에 기억해서 연산을 이어가도록 만든 것이고 false이면 등호 버튼을 클릭할 때까지 계속 연산을 수행하도록 만든 것입니다. 연산자 버튼을 누르면 새로운 숫자를 입력할 수 있도록 'isNewNum'에 true 값을 대입하고 연산자 버튼을 눌렀으니 등호로 연산의 결과를 처리할 수 있다는 뜻인 'isEqualLive'에도 true 값을 대입해줍니다.


다시 'SetCal' 메서드로 이동하면 매개변수로 사칙연산 중에서 어떤 연산을 선택했는지를 알 수 있는 enum 타입의 Opt 변수를 받고 현재 창에 나와있는 숫자를 int형의 num 변수에 대입합니다. 이때 창에 있는 숫자는 string형이니 int형으로 변환하여서 대입해야만 합니다. 다음으로 switch 문을 사용해서 'Opt' 값을 조건으로 삼아서 Result과 num을 연산하도록 합니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
        private void NumResult_Click(object sender, EventArgs e)
        {
            if (!isNewNum)
            {
                if (isEqualLive)
                    SetCal(Opt);
 
                NumScreen.Text = Result.ToString();
                isBehindEqualKey = true;
                isEqualLive = false;
                isNewNum = false;
                CalCount = 1;
            }
        }
 
        private void NumClear_Click(object sender, EventArgs e)
        {
            Result = 0;
            isNewNum = true;
            isBehindEqualKey = true;
            isEqualLive = true;
            CalCount = 1;
            Opt = Operators.Add;
 
            NumScreen.Text = "0";
        }
cs


마지막으로 위에 두 개의 핸들러인 메서드를 보도록 하겠습니다. 'NumResult_Click' 핸들러는 등호 역할을 수행하고 'NumClear_Click' 핸들러는 클리어 역할을 수행합니다. 먼저 등호 역할을 수행하는 메서드를 설명하면 if 문에서 연산자 버튼의 핸들러와 같이 'isNewNum'이 false 값일 때만 내용을 처리하도록 합니다. 그 이유는 연산의 결과를 처리하도록 등호 버튼을 누르고 그 다음에도 등호 버튼을 누르거나 연산자 버튼을 눌러서 이상한 값이 처리되지 않도록 예외처리를 한 것입니다.


그리고 등호 버튼을 사용할 수 있는지를 나타내는 'isEqualLive'가 true인지를 검사하고 참이면 연산을 수행하는 메서드를 호출하여서 연산을 처리합니다. 그 다음에 그 결과인 Result를 string형으로 바꾸어서 창의 텍스트 속성에 대입하면 그 결과가 창에 나타날 것입니다.


그럼 등호 버튼을 눌렀으니 등호로 숫자의 연산을 처리하였는지를 나타내는 'isBehindEqualKey'에 true를 그리고 숫자를 입력하기까지 등호 버튼을 사용할 수 없도록 'isEqualLive'에 false를 또 숫자를 그 결과에 이어서 입력할 수 있도록 'isNewNum'에 false를 대입합니다. 또 이제는 연산이 끝났으니 다음 연산을 위해서 'CalCount'를 1로 초기화시킵니다.


클리어 역할을 수행하는 'NumClear_Click' 핸들러는 창에 나타난 연산된 값을 날려버리고 모든 조건을 맨 처음으로 돌려놓는 것이 목적이니 맨 처음의 코드에 있는 내용과 똑같이 입력하시면 됩니다. 이상으로 C#으로 계산기 만들기를 마치도록 하겠습니다. 아직 공부 중이라 알맞게 잘 설명한 건지 잘 모르겠습니다만 만약 잘못된 점이 있으면 지적해주시면 감사하겠습니다. 전체 코드는 아래에..


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
        
namespace WindowsFormsApp1
{
    public enum Operators { Add, Sub, Multi, Div }
 
    public partial class Calculator : Form
    {
        public int Result = 0;
        public bool isNewNum = true;
        public bool isBehindEqualKey = true;
        public bool isEqualLive = true;
        public int CalCount = 1;
        public Operators Opt = Operators.Add;
 
        public Calculator()
        {
            InitializeComponent();
        }
 
        private void NumButton1_Click(object sender, EventArgs e)
        {
            Button NumButton = (Button)sender;
            SetNum(NumButton.Text);
        }
 
        public void SetNum(string num)
        {
            if (isNewNum)
            {
                NumScreen.Text = num;
                isNewNum = false;
            }
            else
                NumScreen.Text += num;          
        }
 
        public void SetCal(Operators Opt)
        {
            int num = int.Parse(NumScreen.Text);
 
            switch (Opt)
            {
                case Operators.Add:
                    Result += num;
                    break;
                case Operators.Sub:
                    Result -= num;
                    break;
                case Operators.Multi:
                    Result *= num;
                    break;
                default:
                    Result /= num;
                    break;
            }
        }
 
        private void NumPlus_Click(object sender, EventArgs e)
        {
            if (!isNewNum)
            {
                if (CalCount > 1)
                    SetCal(Opt);
 
                CalCount++;
 
                Button optButton = (Button)sender;
 
                if (optButton.Text == "+")
                    Opt = Operators.Add;
                else if (optButton.Text == "-")
                    Opt = Operators.Sub;
                else if (optButton.Text == "*")
                    Opt = Operators.Multi;
                else
                    Opt = Operators.Div;
 
                if (isBehindEqualKey)
                {
                    Result = int.Parse(NumScreen.Text);
                    isBehindEqualKey = false;
                }
 
                isNewNum = true;
                isEqualLive = true;
            }
        }
 
        private void NumResult_Click(object sender, EventArgs e)
        {
            if (!isNewNum)
            {
                if (isEqualLive)
                    SetCal(Opt);
 
                NumScreen.Text = Result.ToString();
                isBehindEqualKey = true;
                isEqualLive = false;
                isNewNum = false;
                CalCount = 1;
            }
        }
 
        private void NumClear_Click(object sender, EventArgs e)
        {
            Result = 0;
            isNewNum = true;
            isBehindEqualKey = true;
            isEqualLive = true;
            CalCount = 1;
            Opt = Operators.Add;
 
            NumScreen.Text = "0";
        }
    }
}
 
cs


반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함