먼저 우리가 흔히 아는 특수문자는 반각문자 입니다. (키보드에 존재하는 특수문자 !@#$% 등등) 전각문자는 윈도우 한자 키를 사용하여 생성된 특수문자입니다. (123abc?!등등)

전각문자를 사용해도 표현은 되지만 문자 사이의 간격이 반각보다 커서 가독성 문제나 123과 같은 숫자가 전각일 경우, 문자로 인식되는 것등의 문제가 있습니다. 

따라서 파이썬에서 전각문자를 반각문자로 변경하는 방법은 아래와 같습니다.


# 전각문자
full = '!'
# 반각문자
half = '!'
# 전각문자와 반각문자의 차이
diff = '0xfee0'
# 전각문자 블랭크
blank = '0x3000'

# 16진수인 ascii code
hex_ascii_full = ord(full)
hex_ascii_half = ord(half)
hex_ascii_diff = int(diff, 16)
hex_ascii_blank = int(blank, 16)

# 16진수 형태의 string
hex_full = hex(hex_ascii_full)
hex_half = hex(hex_ascii_half)
hex_blank = hex(hex_ascii_blank)

# 전각일 경우 전각 기준인 값을 차감해 반각으로 변경
if hex_ascii_full >= hex_ascii_diff:
    result = hex_ascii_full - hex_ascii_diff
# 빈칸이 전각일 경우는 위 공식에 어긋나므로 강제로 반각형태의 빈칸을 지정
elif hex_ascii_full == hex_ascii_blank:
    result = hex_blank


assert chr(result) == '!'


파이썬3은 string이 전부 unicode입니다. 따라서 ord() 함수를 사용하여 문자열을 아스키코드로 변환할 수 있습니다. (= Hexadecimal Ascii Code) 다음 변환된 아스키 코드를 hex()로 감싸면 원하는 유니코드표(=16진수)의 값을 확인할 수 있게 됩니다. 이러한 작업을 한 다음, 비교문을 통해 0xfee0 값 보다 큰 값은 전부 전각문자이므로 16진수 형태의 문자와 차를 구하게 되면 반각문자를 구하게 될 수 있습니다. 계산된 전각문자는 16진수이므로 내장함수인 chr() 함수를 사용해 우리가 알고있는 문자로 변환을 하면 끝입니다. 

만약 반각 → 전각 문자로 변경하고자 하면 0xfee0 값 보다 작은 값을 찾아, 더해주면 됩니다.


삽질

코드는 다른 언어에 비해 간단하다고 할 수 있는데 가장 기본인 파이썬3의 모든 string이 unicode이다 이 부분을 까먹으면 혼돈에 빠지게 됩니다.


1. 먼저 첫 번째로 한 삽질은 str.encode('unicode_escape') 를 사용해 문자를 unicode 형식으로 변경할 수 있습니다. 하지만 변경된 문자는 b'\\uac00' 와 같은형식으로 바이트 타입입니다. 혹시나 해서 바이트 타입을 벗기면 \uac00 와 같은 string 타입이 나오게 됩니다.. 만약 반각일 경우는 \u가 없는 바이트 타입이 나오게 됩니다. 이러한 방식은 전각 ↔ 반각 변경에 전혀 쓸 수 없습니다. (하려면 할 순 있지만 코드가 방대하고 어려워지게 됩니다.)

2. 두 번째로는 바이트로 변경하여 전각문자와 반각문자의 차이값인 0xfee0 만큼 빼려고 시도했습니다. 하지만 바이트는 더하거나 뺄 수없고 시프트로 자리값을 밀어야 합니다. 이 방법 또한 구현하기 복잡하고 디버깅이 어려워 바로 포기했습니다.



간단한 문제를 다양한 방법으로 삽질을 통해 해결하긴 했지만 가장 기본인 파이썬3의 모든 string이 unicode이다 가 제일 중요합니다.

+ Recent posts