[C] wchar_t로 한글 출력 문제 ㅜㅜ

익명 사용자의 이미지

#include
#include
#include
#include

int main(){
wchar_t s[10];
wscanf(L"%s", s);
wprintf(L"%s\n", s);
printf("%d\n", s[0]);
printf("%d\n", s[1]);

return 0;
}

이걸 실행하고 '가'를 입력하면


176
161

위와 같이 출력되고
'a'를 입력하면

a
97
0

이렇게 출력되는데요. s[1]이 0이 아니라는건 s[0]이랑 s[1]이 모두 '가'를 표현하는데 쓰이고 있다는건가요??
wchar_t 한칸이 한글 한 글자를 표현하는걸로 알고있는데 아닌가요? ㅠㅠ

익명 사용자의 이미지

> wchar_t 한칸이 한글 한 글자를 표현하는걸로 알고있는데 아닌가요? ㅠㅠ

아닙니다. 한 글자가 몇 바이트를 차지할 지는 사용하는 인코딩에 따라 달라집니다. 그리고 wchar_t 의 크기는 컴파일러마다 다릅니다. 따라서 포터블한 코드를 짜기 위해서는 wchar_t 는 그냥 사용하지 않는다고 생각하십시오. 한글을 사용하기 위한 가장 좋은 방법은 유니코드를 사용하는 것이고 유니코드 인코딩중에서도 utf-8이 가장 일반적으로 쓰입니다. char 배열을 가지고 유니코드 문자열을 표현하세요. 문자를 하나 하나 다룬다거나 문자열을 자르거나 할 필요가 있을 때에는 iconv나 utf8proc과 같이 유니코드를 다룰 수 있는 문자열 라이브러리를 사용하세요. 그냥 몇 바이트 단위로 자른다거나 해서 해결될 일이 아닙니다.

익명 사용자의 이미지

> 한 글자가 몇 바이트를 차지할 지는 사용하는 인코딩에 따라 달라집니다.

추가로, 한 인코딩에서도 글자에 따라서 사용하는 바이트가 달라질 수 있습니다. 예를 들어서 utf-8에서는 한 글자가 1 바이트 또는 2바이트, 4바이트를 차지할 수 있습니다. 유니코드를 직접 다루는 일은 간단한 일이 아니니 말씀드린 라이브러리들을 사용하시는 것이 좋습니다.

Prentice의 이미지

이미 알고 계시겠지만 다른 분들을 위해 적어보자면

UTF-8에서 한글 음절은 (U+AC00-D7A3 영역에서) 3바이트입니다.

수정: 유니코드 코드포인트 중에 뒷쪽 끝에(?) 오는 애들은 5바이트 이상도 가능하다고 생각했는데 아닌가 보네요.

 의 이미지

'가'가 176, 161으로 나타내어진다면 십중팔구 CP949겠네요.
그렇다면 마이크로소프트 컴파일러를 쓰고 계시겠군요.

wchar_t가 아마도 2바이트일 텐데도 이와 같은 결과가 나오는 이유는 locale 설정 때문입니다.
디폴트로 "C" locale을 사용하게 되는데 이건 말 그대로 "minimal ANSI conforming environment for C translation" 이거든요.

locale에 대한 복잡한 설명은 링크로 대신하지요. 아래와 같이 바꾸면 바라시는 대로 돌아갈 겁니다.

#include <stdio.h>
#include <wchar.h>
#include <locale.h>	// 추가됨
 
int main() {
	wchar_t s[10];
	setlocale(LC_ALL, "");	// 추가됨
	wscanf(L"%s", s);
	wprintf(L"%s\n", s);
	printf("%d\n", s[0]);
	printf("%d\n", s[1]);
	return 0;
}

저라고 locale을 아주 잘 아는 건 아닙니다만, 원래 language/country_region/code_page 등으로 locale을 지정해 주어야 하는데
빈 문자열을 넣으면 적절히 implementation-defined native environment으로 들어간다고 합니다.
어차피 특정 locale를 지정하는 게 목적이 아니니까 별 문제 없겠지요.
자세한 내용은 아래 링크들 참조:

https://msdn.microsoft.com/en-us/library/x99tb11d.aspx
https://msdn.microsoft.com/en-us/library/hzz3tw78.aspx

아무튼 이렇게 하면 2바이트 wchar_t에 utf-16으로 인코딩된 문자들이 담기게 됩니다만, 여전히 한 가지 주의하실 점은 utf-16 역시 가변 길이 인코딩이라는 겁니다.

https://en.wikipedia.org/wiki/UTF-16

한글 문자를 포함하여 BMP에 속한 문자들은 문제가 없지만, 문자 하나가 wchar_t 하나로 나타내어질 거라는 가정을 함부로 한다면
언젠간 누군가 Supplementary Planes에 속하는 문자들(e.g., 몇몇 emoji 문자 등)을 쑤셔넣어서 프로그램을 깨트릴지도...?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.