[WinForms] 계산기

00·2025년 2월 7일

프로젝트

목록 보기
6/14

1. 프로젝트 소개

  • 목표
    C# 윈도우 폼(Windows Forms)을 사용하여 기본적인 사칙연산 기능을 제공하는 계산기 애플리케이션을 개발합니다.

  • 사용 기술

    • C#
    • Windows Forms
  • 개발 환경

    • Visual Studio 2022
    • .NET Framework 4.7.2
  • 실행 결과

2. 기능 설명

  • 사칙연산
    덧셈, 뺄셈, 곱셈, 나눗셈의 사칙연산 기능을 제공합니다.
  • 연산자 우선순위
    곱셈과 나눗셈은 덧셈과 뺄셈보다 우선적으로 계산됩니다.
  • 연속 계산
    연산자를 연속해서 입력하여 계산을 이어갈 수 있습니다.
  • 결과 출력
    '=' 버튼을 클릭하면 계산 결과가 출력됩니다.
  • 전체 지우기
    'AC' 버튼을 클릭하면 현재까지 입력된 모든 내용이 지워집니다.
  • 0으로 나누기 방지
    0으로 나누려고 할 경우, 에러 메시지를 출력합니다.

3. 어려웠던 점과 해결 과정

  • 어려웠던 점 1
    연산자를 연속해서 입력할 경우, 이전 연산 결과를 유지하면서 계산을 이어가는 기능 구현에 어려움을 겪었습니다.

  • 해결 과정 1

    • currentOperator 변수를 사용하여 현재 연산자를 저장하고, operatorChangeFlag 변수를 사용하여 연산자 변경 여부를 확인했습니다.
    • ButtonResult_Click 메서드에서 currentOperator 값에 따라 적절한 연산을 수행하고, firstOperand 변수에 결과를 저장하도록 했습니다.
    • 각 연산자 버튼 클릭 이벤트에서 firstOperand 값을 업데이트하고, operatorChangeFlagtrue로 설정하여 다음 입력 시 기존 값을 초기화하도록 했습니다.
  • 어려웠던 점 2
    숫자 버튼을 클릭했을 때, 레이블에 숫자가 제대로 출력되지 않는 문제가 발생했습니다. 숫자 버튼을 클릭하면 "01", "012"와 같이 출력되었습니다.

  • 해결 과정 2:

    • 레이블의 초기값이 "0"이라는 문자열이었기 때문에, 숫자 버튼을 클릭하면 "0" 뒤에 숫자가 붙어 "01", "012"와 같이 출력되는 문제가 발생했습니다.
    • 이를 해결하기 위해, 숫자 버튼 클릭 이벤트에서 display.Text 값을 Int32.Parse() 메서드를 사용하여 정수형으로 변환한 후, 다시 ToString() 메서드를 사용하여 문자열로 변환하여 레이블에 출력하도록 코드를 수정했습니다.
    • 또한, 연산자 버튼을 클릭했을 때 operatorChangeFlag 변수를 true로 설정하여, 다음 숫자 버튼 클릭 시 레이블의 내용을 초기화하고 새로운 숫자를 입력받도록 했습니다.
private void ButtonOne_Click(object sender, EventArgs e)
{
    if (operatorChangeFlag == true)
    {
        display.Text = "";
        operatorChangeFlag = false;
    }

    string strNumber = display.Text += "1"; // "01"
    int intNumber = Int32.Parse(strNumber); // 1
    display.Text = intNumber.ToString(); // "1"
}

4. 배운 점

  • 열거형(Enum) 활용: 연산자를 효율적으로 관리하기 위해 enum을 사용하는 방법을 익혔습니다. enum 은 관련된 상수들을 묶어서 관리할 수 있게 해주는 자료형입니다.
    요일이나 성별, 계절과 같은 정해져있는 범위를 열거형으로 표현하면 0, 1, 2, 3...과 같은 숫자로 표현하는 것보다 가독성을 높일 수 있습니다. 그리고 정해진 범위 외의 값을 코드에 작성할 경우 컴파일 오류가 발생해서 오류의 원인을 보다 쉽게 찾을 수 있습니다.
    또한, enum 값을 사용하면 여기서는 쓰지 않았지만 switch 문과 같은 제어문에서 코드를 더욱 간결하게 작성할 수 있다는 장점이 있습니다. 저는 이 프로젝트에서 Operators 열거형을 사용하여 덧셈, 뺄셈, 곱셈, 나눗셈 등의 연산자를 정의하고, 코드 전반에서 이를 활용하여 연산자를 명확하고 효율적으로 관리했습니다.

  • 변수 및 플래그 활용: 연산 결과를 저장하고 연산자 변경 여부를 확인하기 위해 변수와 플래그를 적절히 활용하는 방법을 배웠습니다. 변수는 프로그램에서 데이터를 저장하는 공간이며, 플래그는 특정 상태를 나타내는 데 사용되는 변수입니다. 이 프로젝트에서는 currentOperator 변수를 사용하여 현재 연산자를 저장하고, operatorChangeFlag 변수를 사용하여 연산자 변경 여부를 확인했습니다.

  • 코드 가독성: 변수 및 함수 이름을 명확하게 작성하고(의미 그대로 작명), 주석을 추가하여 코드의 가독성을 높이는 방법을 배웠습니다. 코드 가독성은 코드를 이해하고 유지보수하는 데 매우 중요합니다. 이 프로젝트에서는 변수 및 함수 이름을 의미 있게 작성하고, 주석을 추가하여 코드의 기능을 명확하게 설명했습니다.

  • 예외 처리: 0으로 나누는 경우와 같은 예외 상황을 처리하는 방법을 익혔습니다. 예외 처리는 프로그램 실행 중 발생할 수 있는 예상치 못한 오류를 처리하는 방법입니다.
    저는 0으로 나누려고 할 경우, if 문을 사용하여 예외 상황을 확인하고, "0으로 나눌 수 없습니다."라는 에러 메시지를 출력하도록 했습니다. 이를 통해 DivideByZeroException 예외를 방지하고, 프로그램이 비정상적으로 종료되는 것을 막았습니다.


5. 디자인 및 코드 설명

(1) 컨트롤

레이블(Label)

  • 숫자와 계산 결과를 보여줄 레이블 컨트롤을 배치합니다. 속성창에서 속성값을 변경합니다. (Name) 속성값은 display, AutoSize 속성값은 False, Dock 속성값은 Top, Font 속성값을 조정합니다.

  • 계산기 기본 화면은 0이 띄워져 있으므로 Text 속성값은 0으로 변경하고, 오른쪽 끝부터 숫자가 입력되게끔 TextAlign은 MiddleRight으로 변경하여 오른쪽 정렬합니다.

TableLayoutPanel

  • 계산기의 버튼을 일정한 크기와 간격으로 배치하기 위해 TableLayoutPanel 컨트롤을 배치합니다. TableLayoutPanel은 컨트롤을 일정한 간격으로 배치할 때 사용합니다.

  • TableLayoutPanel의 행과 열을 4x4로 만듭니다.

버튼(Button)

  • 버튼(Button) 컨트롤을 TableLayoutPanel 내부에 넣어 계산기 버튼을 만듭니다. 이때 테이블 내에 배치된 버튼은 최대 크기가 테이블 내의 사각박스 안으로 제한됩니다.

  • 버튼을 선택해 속성창에서 속성값을 변경합니다. (Name) 속성값은 ButtonSeven, 글꼴은 편한대로(저는 레이블과 동일하게 굵게, 크기는 20), Text는 7로 수정합니다. 만든 버튼을 모든 칸에 복붙합니다.

  • 계산기와 동일한 모습으로 각 버튼의 속성값을 수정합니다.

  • 연산 결과를 출력하기 위한 = 버튼을 추가합니다. TableLayoutPanel 레이아웃 외부에 버튼 컨트롤을 복붙하고, (Name) 속성값은 ButtonResult, Dock 속성값은 Bottom으로 설정하여 화면 아래에 버튼을 고정시킵니다.

  • 버튼을 클릭할 때 이벤트를 추가하기 위해 각 버튼마다 Click 이벤트를 추가합니다.

(2) 소스코드

입력값 가져오기

  • 계산기 버튼 중 숫자를 누를 때 레이블에 숫자가 출력되는 부분을 먼저 구현합니다. display는 레이블의 (Name) 속성으로 변수로 접근할 때 사용합니다. 따라서 display.Text로 문자열을 입력하거나 추가하면 레이블에 해당 문자열이 출력됩니다. 숫자 1을 클릭하면 레이블에 1을 출력하고, 다시 숫자 1 버튼을 누르면 11이 출력되도록 코드를 작성합니다.
private void ButtonOne_Click(object sender, EventArgs e)
{
    display.Text += "1";
}
  • 숫자 버튼을 클릭했을 때, 레이블에 숫자가 제대로 출력되지 않는 문제가 발생했습니다. 숫자 버튼을 클릭하면 "01", "011"와 같이 출력되었습니다.

  • 이는 레이블의 초기값이 "0"이라는 문자열이었기 때문입니다. 이를 해결하려면 문자열을 Int32.Parse() 메서드를 사용하여 정수형으로 변환한 후, 다시 ToString() 메서드를 사용하여 문자열로 변환한 값을 레이블에 출력하도록 코드를 수정해야 합니다.

private void ButtonOne_Click(object sender, EventArgs e)
{
    string strNumber = display.Text += "1";
    int intNumber = Int32.Parse(strNumber);
    display.Text = intNumber.ToString();
}
  • 또한, 연산자 버튼을 클릭했을 때 operatorChangeFlag 변수를 true로 설정하여, 다음 숫자 버튼 클릭 시 레이블의 내용을 초기화하고 새로운 숫자를 입력받도록 했습니다.
private void ButtonOne_Click(object sender, EventArgs e)
{
    if (operatorChangeFlag == true)
    {
        display.Text = "";
        operatorChangeFlag = false;
    }

    string strNumber = display.Text += "1"; // "01"
    int intNumber = Int32.Parse(strNumber); // 1
    display.Text = intNumber.ToString(); // "1"
}

실행 결과

개선

  • 나누기 예외처리 기능 추가
    0으로 나누는 경우를 처리하기 위해 조건문을 추가했습니다. 만약 나눗셈 연산에서 두 번째 피연산자(secondOperand)가 0인 경우,"0으로 나눌 수 없습니다."라는 메시지를 출력합니다. 0이 아니라면 기존 로직대로 firstOperandsecondOperand로 나누고 결과를 출력합니다. 이는 DivideByZeroException 예외를 방지하고, 프로그램이 비정상적으로 종료되는 것을 막기 위한 처리입니다.

실행 결과

0개의 댓글