PS (C, C++)

[백준/C & C++] 1541 잃어버린 괄호

최연재 2022. 11. 26. 00:09

https://www.acmicpc.net/problem/1541

 

1541번: 잃어버린 괄호

첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다

www.acmicpc.net

 c 

#include <stdio.h>
#include <string.h>

int main()
{
	char str[51], op[50];
	int num[50], n=0,o=0, num1=0, check = 1;
	scanf("%s", str);

	for (int i = 0; str[i] != '\0'; i++)
	{
		if (str[i] == '+' || str[i] == '-')
		{
			op[o++] = str[i];
			num[n++] = num1;
			num1 = 0;
		}
		else num1 = num1 * 10 + (str[i] - '0');
	}
	num[n] = num1, num[n+1] = op[o] = '\0';
	int result = num[0], k=1;

	for (int i = 0; i < o; i++, k++)
	{
		if (op[i] == '+')
		{
			if (check == 1)result += num[k];
			else result -= num[k];
		}
		else
		{
			result -= num[k];
			if (check == 1) check = 0;
		}
	}
	printf("%d", result);
	return 0;
}

c++

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
	char op[51], str[51];
	int result = 0, num1 = 0, num[51] = {0,}, o = 0, n = 0, k = 1, check = 1;

	cin >> str;
	for (int i = 0; i < strlen(str); i++)
	{
		if (str[i] == '+' || str[i] == '-')
		{
			op[o++] = str[i];
			num[n++] = num1;
			num1 = 0;
		}
		else num1 = num1 * 10 + (str[i] - '0');
	}

	num[n] = num1;
	result = num[0], num[n + 1] = op[o] = '\0';
	for (int i = 0; i < o; i++, k++)
	{
		if (op[i] == '+')
		{
			if (check == 1) result += num[k];
			else result -= num[k];
		}
		else
		{
			result -= num[k];
			if (check == 1) check = 0;
		}
	}

	cout << result;
	return 0;
}

코드 설명

먼저 이 문제에서는 괄호를 사용하는 횟수에는 제한이 없다!

그래서 고려해야 할 사항은 하나인데, 식에서 - 숫자 뒤에 +가 오는지, -가 오는지만 고려하면 된다. 

만약에 식이 10-20-30이면 답은 있는 그대로 계산해서 -40이다. 그런데 10-20+30이라면 20+30을 괄호로 묶어서 10-(20+30)이 되고 이 결과도 앞의 식처럼 -40이다.

 

 +가 오는 경우에는 그냥 더해주면 되고, - 숫자 뒤에 오는 부호의 경우를 고려하면 다음과 같다. - 숫자 - 숫자 이면 그냥 빼주면 되고, - 숫자 + 숫자의 경우에는 -(숫자+숫자) = -숫자-숫자가 된다. 즉 -가 한 번이라도 등장했다면 그 뒤에 오는 연산자와 상관없이 숫자들을 계속 빼면 된다! 

 

그래서 코드를 위와 같이 작성했다. 나는 피연산자와 연산자를 각각 배열에 먼저 저장해준 뒤에 계산을 진행했다. 

식을 입력받고 식이 끝날 때까지 반복문을 돈다. str[i]가 부호인 경우에는 그 앞에서 숫자가 끝난 것이니 num1을 피연산자 배열에 저장한 후 num1을 0으로 만든다. 그리고 부호도 연산자 배열에 넣어준다. 이때 배열[인덱스++]의 형태로 작성해서 인덱스 값을 증가시켜준다.  부호가 아닌 경우에는 계속 숫자인 것이므로 num1 = num1*10 + (str[i]- '0') 을 해준다. 

10을 곱하는 것은 자릿수가 증가함을 뜻하고, 현재 식은 문자열이므로 숫자형태로 바꿔주기 위해 str[i]에서 '0'을 빼줬다. 

 

반복문이 끝난 후에는 현재 저장되어 있는 num1 값을 연산자 배열에 저장한다. (식의 마지막은 숫자이고, 숫자를 피연산자 배열에 넣는 것은 부호가 나타났을 경우이기 때문에 이 코드가 없으면 마지막 수가 연산자배열에 저장되지 않는다.)

결과에 첫 번째 숫자를 대입한다. (다른 숫자들은 부호가 나타난 후에 덧셈하거나 뺄셈하는데 식의 첫 번째 숫자는 식에서 가장 먼저 등장하기에 필요한 코드이다. 그리고 만약에 식에 부호가 없을 경우를 고려하는 코드이기도 하다.)

 

연산자의 횟수만큼 반복문을 돌면서 결과를 구한다. 

연산자가 +인 경우에는 이전에 - 가 있었는지 확인한다. 없었다면(check == 1)  result에서 피연산자를 더하고 그렇지 않을 경우에는 피연산자를 빼준다. 연산자가 -인 경우에는 일단 피연산자를 빼준다. check는 -의 등장을 의미하는 변수인데 식에서 -가 처음 등장했을 때는 check에 저장되어 있는 값이 1이다. 이제 -가 등장했기 때문에 check 를 0으로 한다. 반복문을 다 돈 후에는 result를 출력하고 프로그램을 종료한다.

 

 

  

느낀 점

처음에는 어떻게 풀어야 할지 몰랐는데, 직접 예시를 만들고 값을 구하니 두 번째 for문을 어떻게 작성할지 쉽게 파악할 수 있었다. 풀어본 뒤에는 백준 질문에 올라와있는 경우들을 몇 개 실행해보고 맞게 나온 걸 확인하고 제출했다. 한 번에 통과해서 기분이 좋았다.

 

처음에는 피연산자, 연산자를 저장하는 배열을 만들지 않고, 결과를 구하는 반복문 내에서 그때그때 값을 구해가도록 코드를 작성했는데, 내가 짠 코드는 깔끔하지도 않았고, 제대로 작동하지 않아서 배열들을 만드는 것으로 방향을 틀었다. 방향을 틀었던 것은 좋은 선택인 것 같다!  후위 표기법 문제를 풀면서 사용했던 방법을 다시 사용했는데 앞으로 유사한 문제가 나오면 바로 피연산자와 연산자 배열을 각각 만들어서 문제를 풀 생각이다.