[백준] 10926번 : ??! - [C++]
https://www.acmicpc.net/problem/10926
- 문제
- 알고리즘 [접근 방법]
이 번 문제는 C++ 의 string 자료형을 쓰면 어렵지는 않은 문제다.
다만, C스타일로 char[] 에 담은 뒤, printf 형식에 ??!을 붙여 출력 할 경우에는 조금의 주의가 필요하다.
오늘은 이 부분에 대해 간략히 소개하고자 한다.
예로들어 char id[10] 에 abcd를 담았다고 가정보자.
그러면 위 우리가 일반적으로 생각하기에는 이런식으로 출력할 수가 있겠다.
printf("%s??!", id);
그러면 abcd??!가 출력 될 것 같지만, abcd| 가 출력된다. 왜 그런 것일까?
바로, 삼중자(Trigraph Sequence) 라는 녀석때문이다.
삼중자가 무엇이냐면, 쉽게 말해 특정 문자 패턴을 다른 문자로 치환하는 것을 의미한다. 좀 더 쉽게 이해하자면, 우리가 특정 키보드 조합을 통해 단축키를 설정하여 해당 키를 누르면 특정한 역할을 수행하듯, C와 C++(17 이전 버전)에서 특정 문자열을 다른 문자로 치환하는 문자 세트가 존재한다.
아래는 삼중자 시퀀스다.
삼중자 | 문장 부호 문자(치환 되는 문자) |
??= | # |
??/ | \ |
??' | ^ |
??( | [ |
??) | ] |
??! | | |
??< | { |
??> | } |
??- | ~ |
위와 같이 3개 문자 조합에 따라 특정 문자로 치환하게 된다.
위와 같은 삼중자 시퀀스가 존재하는 이유가 일부 언어권 문자셋 중에서 C언어의 표준 문자셋을 모두 받아들이지 못하는 문제로 인해 C언어에서 사용하는 표현식을 쓰지 못하는 경우가 발생하여 위와 같은 문자 셋을 만들었다고 한다.
그러면 삼중자도 있으니 이중자도 있지 않을까?
있다.
이중자 | 문장 부호 문자(치환 되는 문자) |
<: | [ |
:> | ] |
<% | { |
%> | } |
%: | # |
(여담으로 jsp를 다뤄보신 분이라면 익숙한 문법이 있을 것이다.)
다만, 위 문자셋을 다 외울 필요는 없다. 특히나 C++17부터는 삼중자는 없어졌기도 하고, string 클래스를 쓰면 되는 문제이기 때문에 C언어만 사용해야만 하거나, 특정 상황이 주어지는 것이 아닌 이상 안정성을 위해 string 클래스를 쓰는 것이 좋다.
또한 C언어도 요즘 대부분의 컴파일러에서는 위 기능을 꺼놓기 때문에 사실 그냥 출력해도 되는 경우가 많을 것이다. (무엇보다 코드를 읽기 어렵게 만든다는 치명적인 단점 때문에 점차 지원을 안하거나 해당 기능을 비활성화 해놓는 경우가 많다.)
그럼 위와 같은 삼중자가 주어질 때 어떻게 출력을 해야하나?
바로 물음표 사이에 역슬래시(\)를 넣으면 해결된다.
즉, ?\?! 이런식으로 해야 우리가 원하는 문자 그대로의 출력이 가능하다.
- 2가지 방법을 사용하여 풀이한다.
앞서 string을 쓰면 아주 간단하게 풀 수 있다고 했었다. 사실 string 클래스간 덧셈 연산자를 쓸 경우 두 문자열이 합쳐지기 때문에 설명을 따로 할 것이 없어 이 부분은 바로 코드로 보여주고자 별다른 해설은 하지 않았다.
그리고 위에서 설명한 삼중자를 고려한 풀이도 같이 보여주고자 한다.
1. string 클래스 사용
2. string 클래스 미사용
- 풀이
- 방법 1 : [string 클래스 사용]
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char const *argv[]) {
string id;
cin >> id;
id += "??!";
cout << id;
return 0;
}
가장 기본적인 방법이라 할 수 있겠다.
(정확히 말하자면, 위 ??! 에 대해서도 C++17 버전이 아닌 이상 += "?\?!" 로 푸는 것이 올바르다. 다만, 백준에서는 C++ 컴파일러에서 삼중자가 비활성화 되어있는지 그냥 통과되기 때문에 위와 같이 풀더라도 통과가 된다.)
- 방법 2 : [string 클래스 미사용]
위에서 그동안 설명했던 삼중자를 사용한 방법이다.
#include <stdio.h>
int main(int argc, char const *argv[]) {
char id[51];
scanf("%s", id);
printf("%s?\?!", id);
return 0;
}
쉽게 말해 C스타일로 풀기 위해서는 위와같이 풀어야 될 것이다.
- 성능
채점 번호 : 45245243 - 방법 2 : string 클래스 미사용
채점 번호 : 45245237 - 방법 1 : string 클래스 사용
- 정리
사실 이 번 문제는 사람마다 느끼는 점이 조금씩 다를 것이다.
C++ 혹은 C언어에서도 시스템에 의해 위와 같은 문자 치환 기능이 비활성화 된 경우 잘 알지 못했던 부분이라 어려웠을 수도 있고, string 클래스를 사용하여 풀려고 했다면 매우 쉬웠던 문제일 수도 있어 보인다.
사실 필자도 위 시퀀스를 다 기억하진 못하고, 가끔 물음표가 여러개 붙어야 할 때 혹시나 하고 검색하면서 삼중자인지 아닌지를 확인 하는지라.. 어느정도 이러한 것들이 있다~ 라는 정도만 알고 있으면 되지 않을까 싶다.
만약 어렵거나 이해가 되지 않은 부분이 있다면 언제든 댓글 남겨주시면 최대한 빠르게 답변드리겠다.
'C++ - 백준 [BAEK JOON] > 입출력과 사칙연산' 카테고리의 다른 글
[백준] 25083번 : 새싹 - [C++] (0) | 2022.07.06 |
---|---|
[백준] 18108번 : 1998년생인 내가 태국에서는 2541년생?! - [C++] (0) | 2022.07.01 |
[백준] 2588번 : 곱셈 - [C++] (6) | 2021.02.26 |
[백준] 10430번 : 나머지 - [C++] (5) | 2021.02.25 |
[백준] 10869번 : 사칙연산 - [C++] (0) | 2021.02.24 |