본문 바로가기
코딩/잡다한 C언어

C언어로 간단하지만 있어 보이는 계산기 만들기

by jsjin 2023. 3. 30.
728x90

C언어로 1+3, 2-5, 3*4, 4/1 등 간단한 사칙연산을 하는 계산기를 만들어보자.

 

C언어에서 if문 또는 switch문을 배웠다면 간단히 만들 수 있다.

아래는 간단한 사칙연산을 입력받아 계산하는 C언어 코드이다.

#include <stdio.h>

int main() {
	int a, b, result = 0;
	char op;
	
	scanf("%d %c %d", &a, &op, &b);

	if (op == '+') {
		result = a + b;
	}
	else if (op == '-') {
		result = a - b;
	}
	else if (op == '*') {
		result = a * b;
	}
	else if (op == '/') {
		result = a / b;
	}

	printf("%d", result);

	return 0;
}

위 코드는 0으로 나누거나 사칙연산자 이외의 다른 값이 들어오는 등의 예외처리가 없다.

이는 if문을 더 추가해서 예외처리를 하면됨으로 넘어간다.

 

 

그러나 이 코드는 뭔가 멋이 없다.

if else문이나 switch문을 쓰는건 뭔가 초보같은 느낌이 들고 코드도 불편해 보인다....

 

이를 해결하기 위해 함수 포인터를 이용해보겠다.

C언어를 접한 사람이면 함수와 포인터에 대해 들어봤을 것이다.

 

함수 포인터는 함수의 주소를 저장하는 포인터다.

이를 이용하면 함수를 매개 변수로 전달하거나, 함수 포인터를 반환하는 함수 등을 만들 수 있다.

 

함수 포인터는 다음과 같이 선언한다.

반환 타입 (*포인터 변수명)(매개변수 타입);

 

간단한 예로 더하기 함수를 이용하는 함수 포인터를 만들어보자.

int add(int a, int b) {
    return a + b;
}

int main(){
	int (*func_ptr)(int, int); // 함수 포인터 선언

	func_ptr = add; // 함수 포인터에 함수 주소 저장

	int result = (*func_ptr)(3, 4); // 함수 포인터를 사용하여 함수 호출
}

func_ptr에 함수 포인터에 add라는 함수 주소를 저장한다.

그 후 함수 포인터에 저장된 add함수를 호출하며 매개변수 3과 4를 add에 전달한다.

add에서 3+4를 더하고 그 값을 반환하며 result에 저장한다.

 

그럼 함수 포인터에 여러 함수를 저장하고 연산자에 따라 원하는 함수를 불어오면 된다.

다음은 그 코드이다.

#include <stdio.h>

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }

int hash_operator(char op) {
    switch (op) {
    case '+': return 0;
    case '-': return 1;
    case '*': return 2;
    case '/': return 3;
    }
}

int main() {
    int (*operations[4])(int, int) = { add, subtract, multiply, divide};
    char op;
    int a, b, result = 0;

    scanf("%d%c%d", &a, &op, &b);

    int index = hash_operator(op);

    result = operations[index](a, b);
    printf("Result: %d\n", result);
    return 0;
}

사칙연산을 하는 add, subtract, multiply, divide라는 함수를 만들고 이를 operation이라는 함수 포인터에 그 주소를 저장했다.

이후 hash_operator에 연산자 기호를 전달해 '+'면 0, '-'면 1, '*'면 2, '/'면 3을 전달하게 한다.

 

왜 이 값을 전달했나면,

operations[0]은 add를  

operations[1]은 subtract을

operations[2]는 multiply를

operations[3]은 divide를 불러오기 때문이다.

 

operations 자체를 여러 함수를 저장하는 배열로 생각하면 된다.

 

이후 불러온 함수에 매개변수, 즉 계산할 값을 전달하면 각 함수에 따라 값을 전달한다.

 

 

그러나 난 이 코드도 싫다.

hash_operator의 switch문이 그냥 거슬리기 때문이다.

 

그래서 hash_operator를 없애보겠다.

 

이 코드에서 필요한 것은 결국 연산자에 따른 operations의 index 값이다.

그리고 index 값을 구하는 것이 hash_operator이다.

즉, 다른 방법으로 index 값을 구하면 되는 것이다.

 

여러 방법이 있겠지만 식을 이용해서 이를 구해보겠다.

 int index = (op == '+') * 1 + (op == '-') * 2 + (op == '*') * 3 + (op == '/') * 4 - 1;

C언어는 참일때 1의 값, 거짓일때 0의 값을 전달하게 된다.

 

위에서 +가 들어오면

(op == '+')는 참이므로 1의 값을 반환하고

(op == '-'), (op == '*'), (op == '/')는 거짓이므로 0의 값을 전달한다.

 

즉 연산자 종류에 따라 (op == ' (연산자) ')의 형태는 4개 중 참인 단 1개만 1의 값을 가지게 된다.

이 값에 인덱스 위치의 값을 곱하고 (배열의 첫 인덱스 값은 0에서 시작하므로) -1을 하면 원하는 인덱스 값을 구할 수 있다.

 

다음은 이를 적용한 코드이다.

#include <stdio.h>

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }

int main() {
    int (*operations[4])(int, int) = { add, subtract, multiply, divide};
    char op;
    int a, b, result = 0;

    scanf("%d%c%d", &a, &op, &b);

    int index = (op == '+') * 1 + (op == '-') * 2 + (op == '*') * 3 + (op == '/') * 4 - 1;

    result = operations[index](a, b);
    printf("Result: %d\n", result);
    return 0;
}

뭔가 훨 예뻐졌다. 

 

물론 예외처리는 따로 구현해야 한다.

728x90