19 지역과 세계화

다른 나라와 문명은 소통하기 위한 다양한 관습을 갖는다. 이들 관습들은 날짜와 시간을 표현하기 위한 형식처럼 아주 간단한 것에서부터 매우 복잡한 것까지 소통되는 언어의 범위를 갖는다.

소프트웨어의 세계화는 사용자가 좋아하는 관습들에 적응하도록 프로그램 하는 것을 의미한다. ANSI C에서, 세계화는 지역을 가지고 작업된다. 각 지역은 관습들의 집합에서 각 목적을 위해 선택된 한가지 관습을 지정한다. 사용자는 지역을 선택함으로써(환경변수를 거쳐서) 관습의 집합을 선택한다.

모든 프로그램들은 그들의 환경의 일부로써 선택된 지역을 상속받는다. 주어진 프로그램은 선택된 지역에 따라서 만들어졌고, 그들은 사용자에 의해 선택된 관습을 따를 것이다.


19. 1 지역이 가진 효과

각 지역은 다음의 것을 포함해서, 여러 가지 목적을 위한 관습들을 정한다.

  • 무슨 다중 바이트 문자 시퀀스가 유용한것이고, 그들이 어떻게 해석되는가 ( 18장 [Extended Characters] 참조. )
  • 지역 문자 집합 안에 있는 문자들의 분류가 알파벳처럼 되어있는지, 그리고 대, 소문자 변환 관습이 있는지.
  • 지역 언어와 문자 집합을 위한 대조 시퀀스(5. 6절 [Collating Functions] 참조.
  • 수(numbers)와 통화량(currency amounts)의 형식 (19. 6절 [Numeric Formatting] 참조.
  • 날짜와 시간의 형식 ( 17. 2. 4절 [Formatting Date and Time] 참조.
  • 에러 메시지를 포함한, 출력을 위해서 사용하는 언어는 무엇인가. ( C 라이브러리는 당신이 이것을 행하도록 아직은 도움을 주지 않는다. )
  • 예/아니오 의 질문들에 사용자의 답변을 위해 사용하는 언어는 무엇인가.
  • 훨씬 복잡한 사용자 입력을 위해 사용하는 언어는 무엇인가. ( C 라이브러리는 아직까지 이것에 대한 도움을 주지 못하고 있다. )

정해진 지역에 적응하는 어떤 것은 라이브러리 서브루틴들에 의해 자동적으로 다루어진다. 예를 들어, 선택된 지역의 대조시퀀스를 사용하여 순서대로 맞출 필요가 있는 모든 프로그램들은 비교 문자열에 strcoll 이나 strxfrm을 사용할 수 있다.

지역의 다른 것들은 라이브러리의 이해력 밖에 있다. 예를 들어, 라이브러리는 당신 프로그램의 출력 메시지를 다른 언어로 자동적으로 해석할 수 없다. 사용자가 좋아하는 언어로 출력을 지원하는 유일한 방법은 직접 프로그램 하는 것이다. ( 우리는 이것을 더 쉽게 하기 위한 도구들이 주어지기를 희망한다. )

이 장은 현재의 지역을 갱신할 수 있고, 그것의 메커니즘을 설명한다. 정해진 라이브러리 함수들상에서 현재 지역의 효과들은 각각의 함수들에 대한 설명에서 좀더 상세하게 설명되어진다.


19. 2 지역 선택하기

사용자가 한 지역을 선택하기 위한 가장 간단한 방법은 환경변수 LANG를 설정하는 것이다. 이것은 모든 목적을 위해서 사용자에게 단일한 지역을 지정한다. 예를 들어, 한 사용자가 스페인에서 가장 표준인 관습을 사용하기 위해서 `espana-castellano'라고 이름이어진 가상 지역을 선택할 수 있다.

지역들의 집합은 사용자가 사용하고 있는 운영제체에 의존하여 지원되고, 그리고 그들의 이름들을 가지고 작업한다. 우리는 `C' 또는 `POSIX'라고 불리는 표준 지역을위한 것을 제외하고는, 무슨 지역들이 존재할 것인지에 대해서 어느 약속도 할 수 없다. 사용자는 다른 목적으로 다른 지역들을 지정하기 위한 옵션들을 가진다. _실제로, 여러 개의 지역들을 혼합하여 선택한다.

예를 들어, 사용자가 여러 가지 목적을 위해서 지역 `espana-castellano'를 선택하였지만, 통화의 형식을 위해서는 지역 'usa-english'를 선택할 수 있다. 이것은 통화량이 미국 달러로 표현되지만 만일 그 사용자가 스페인에서 일하고 있고, 스페인어를 사용하는 미국인이라면 뜻이 통할 것이다.

모든 지역들처럼 `espana-castellano' 와 `usa-english' 의 두 지역은 어떤 지역들에 적용하기 위한 모든 목적들을 위한 관습을 포함한다. 그렇지만, 사용자는 그들 목적중에서 특정한 몇 가지 목적을 위해서는 다른 지역을 사용하도록 선택할 수 있다.


19. 3 지역이 미치는 활동의 범주

지역을 제공하는 목적은 범주안에 묶어지므로, 사용자나 프로그램은 독립적으로 각 범주를 위해서 그 지역을 선택할 수 있다. 다음은 범주들의 리스트이다; 각각의 이름은 사용자가 설정할 수 있는 환경변수, 그리고 setlocale에 인수로서 사용할 수 있는 매크로 이름이다.

LC_COLLATE

이 범주는 문자열의 대조를 위해서 제공된다(함수 strcoll과 strxfrm); 5. 6절 [Collation Functions] 참조.

LC_CTYPE

이 범주는 문자들의 분류와 관습, 그리고 다중 바이트와 와이드 캐릭터들에게 제공된다; 4장 [Characters Handling]18장 [Extended Characters] 참조.

LC_MONETARY

이 범주는 통화의 값들을 형식화하는데 제공된다. 19. 6절 [Numeric Formatting] 참조.

LC_NUMERIC

이 범주는 통화가 아닌 숫자값들을 형식화하는데 제공된다; 19. 6절 [Numeric Formattin] 참조.

LC_TIME

이 범주는 날짜와 시간값들을 형식화하는데 제공된다; 17. 2. 4절 [Formattin Date and Time] 참조.

LC_ALL

이것은 환경변수가 아니다; 그것은 모든 목적들을 위해서 단일한 지역을 설정하는 setlocale에서 사용할 수 있는 매크로이다.

LANG

만일 이 환경변수가 정의되면, 그 값은 위의 변수들에 의해 무시되는 것을 제외하고는 모든 목적들을 위해 사용자에게 지역을 지정한다.


19. 4 프로그램은 지역을 어떻게 설정하는가

C 프로그램은 그 프로그램이 시작할 때 지역 환경변수들을 상속받는다. 이것은 자동적으로 발생한다. 그렇지만, 그들 변수들이 라이브러리 함수들에 의해 사용된 지역은 자동적으로 제어하지 않기 때문에, ANSI C는 모든 프로그램을 디폴트로 표준 `C'지역으로 시작하게 한다. 환경변수에 의해 정해진 지역들을 사용하기 위해서는, 당신은 setlocale을 호출해야만 한다. 그것을 다음과 같이 호출하라.

setlocale (LC_ALL, "");

적당한 환경변수들에 기초한 지역을 선택하도록 한다.

당신은 또한 일반적으로 사용하거나 또는 정해진 범주를 위한, 특정한 지역을 선택하기 위해서 setlocale를 사용할 수 있다. 이 절에 있는 심볼들은 헤더파일 `locale. h'에 정의되어 있다.

함수 : char *setlocale (int category, const char *locale)

setlocale 함수는 지역에 대한 범주 category를 위해서 현재의 지역을 설정한다. 만일 범주가 LC_ALL 이면, 이것은 모든 목적을 위해서 그 지역을 지정함을 말한다. 범주의 다른 가능한 값들은 개별적 목적으로 지정한다. (19. 3절 [Locale Categories] 참조. )
당신은 locale인수에 널 포인터를 사용함으로서, 현재의 지역을 알아내도록 이 함수를 사용할 수 있다. 이 경우에, setlocale는 범주 category를 위해서 선택된 현재의 지역의 이름을 가진 문자열을 반환한다. setlocale에 의해 반환된 문자열은 다음에 이어지는 호출에 의해 덧씌워질 수 있으므로, 만일 당신이 전에 호출된 setlocale의 결과를 저장하기를 원한다면 당신은 그 문자열의 복사본을 만들어야 할 것이다( 5. 4절 [Copying and Concatenation] 참조. )( 표준 라이브러리는 결코 setlocale 그 자체를 호출하지 않도록 보증된다. )
당신은 setlocale에 의해 반환된 문자열을 갱신하지 말아야 한다. 그것은 전에 호출된 setlocale에서 인수로써 사용했던 문자열과 동일하게 될 것이다.
당신이 범주 LC_ALL을 위해서 현재의 지역을 읽을 때, 그 값은 모든 범주를 위해서 선택된 지역들의 전체조합으로 기호화한다. 이 경우, 그 값은 단지 단일한 지역이름이 아니다. 실제로, 그것이 무엇일지에 대해서 우리는 말할 수 없다. 그러나 만일 당신이 setlocale의 다음 호출에 LC_ALL과 함께 같은 "지역이름"을 지정하면, 그 함수는 선택된 지역과 같은 조합을 저장한다.
locale인수가 널 포인터가 아닐 때, setlocale에 의해 반환된 문자열은 새로인 갱신된 지역을 반영한다. 만일 당신이 loclae에 비어있는 문자열을 지정하면, 이것은 적당한 환경변수를 읽고 그 값을 범주를 위한 지역을 선택하는데 사용한다는 의미이다. 만일 당신이 유용하지 않은 지역이름을 지정하면, setlocale는 널 포인터를 반환하고 현재의 지역은 변화되지 않는다.
다음은 당신이 새로운 지역으로 일시적인 변환을 위해서 setlocale를 어떻게 사용할 것인지에 대한 예제이다.
#include <stddef. h>
#include <locale. h>
#include <stdlib. h>
#include <string. h>
void
with_other_locale(char *new_locale, void (*subroutine)(int), int argument)
{
char *old_locale, *saved_locale;
/* 현재 지역의 이름을 얻어라. */
old_locale = setlocale (LC_ALL, NULL);
/* setlocale에 의해 변경되지 않은 이름을 복사하라 */
saved_locale = strdup (old_locale);
if (old_locale == NULL)
fatal ("Out of memory");
/* 이제 그 지역을 변경하고, 그것으로 어떤 자료를 하라 */
setlocale (LC_ALL, new_locale);
(*subroutine) (argument);
/* 원래의 지역을 다시 저장하라 */
setlocale (LC_ALL, saved_locale);
free (saved_locale);
}
 
이식성 노트 : 어떤 ANSI C 시스템들은 부가적인 지역 범주들을 정의할 수 있을 것이다. 이식성을 위해서, `LC_'로 시작하는 어느 심볼은 `locale. h'에 정의되었다고 생각하자.


19. 5 표준 지역들

모든 운영체제상에서 당신이 발견할 수 있는 지역의 이름은 오직 다음의 세 가지뿐이다:

"C"

이것은 표준 C 지역이다. 그것이 제공하고 있는 속성과 행동은 ANSI C 표준에 의해 지정되었다. 당신의 프로그램이 시작될 때, 그것은 처음에 디폴트로 이 지역을 사용한다.

"POSIX"

이것은 표준 POSIX 지역이다. 일반적으로 이것은 표준 C 지역을위한 다른으로 여겨지고 있다.

" "

이 빈(empty) 이름은 환경변수들에 기초한 지역을 선택함을 말한다. 19. 3절 [Locale Categories] 참조.

이름을 가진 지역들을 정의하고 구동하는 것은 보통 당신이 속한 시스템의 시스템관리자의 책임이다(또는 GNU C 라이브러리를 구동했던 사람. ) 어떤 시스템들은 사용자가 지역을 만들도록 허용할 수도 있지만, 우리는 이것에 대해서 논의하지 않겠다.

만일 당신의 프로그램이 `C'지역과는 다른 어떤 것을 사용할 필요가 있다면, 명백하게 어떤 비-표준 지역을 이름으로 지정하기보다는, 환경변수를 통해서 사용자가 정한 지역을 따르도록 한다면 좀 더 이식성이 있는 프로그램이 될 것이다. 다른 기계에서는 자신이 구동한 지역과는 다른 지역들의 집합을 가질지도 모른다는 것을 기억하라.


19. 6 숫자의 형식화

당신이 현재 지역의 관습을 사용해서 숫자나, 통화량을 형식화하길 원한다면, 그것을 어떻게 형식화할 것인지에 대한 정보를 얻도록 localeconv 함수를 사용할 수 있다. localeconv 함수는 헤더파일 `locale. h'에 선언되어 있다.

함수 : struct lconv * localeconv (void)

localeconv 함수는 현재의 지역에서 숫자와 통화 값이 어떻게 형식화되는지에 대한 정보가 포함된 요소를 가진 구조체를 가리키는 포인터를 반환한다. 당신은 그 구조체나 내용을 변경할 수 없다. 구조체는 localecnov의 다음 호출에 의해 덧씌워지거나, 호출된 setlocale에 의해 변경되지만, 라이브러리에 있는 어느 다른 함수들은 이 값을 변경할 수 없다.

데이터 타입 : struct lconv

이것은 localeconv에 의해 반환된 값의 데이터타입이다.
만일 구조체 struct lconv의 멤버가 char 형을 가진다면, 그리고 그 값이 CHAR_MAX 라면, 그것은 현재의 지역을위한 파라미터에 아무런 값이 없음을 의미한다.

 

19. 6. 1 일반적인 숫자 형식화 파라미터

다음은 struct lconv의 표준 멤버들이다; 다른 것이 있을 수도 있다.

    char *decimal_point

    char *mon_decimal_point

    통화량이 아닌것과 통화량을 형식화하는데 사용되는 소수점 분리자(separators)이다. `C' 지역에서는, 소수점의 값은 ". "이고, mon_decimal_point의 값은 ""이다.

    char *thousands_sep

    char *mon_thousands_sep

    통화량이 아닌것과 통화량을 형식화할 때, 소수점 왼쪽의 십진수의 한계그룹에 사용되는 분리자(separators)이다. `C' 지역에서, 이 둘 멤버들은 ""(빈 문자열)의 값을 갖는다.

    char *grouping

    char *mon_grouping

    grouping은 통화량이 아닌것에 적용되고 mon_grouping은 통화량에 적용해서 소수점왼쪽에 있는 숫자들을 어떻게 묶을 것인지를 정하는 문자열이다. 십진수 그룹들 분리하는데는 thousnads_sep나 mon_thousands_sep중에 하나를 사용하라.
    각 문자열은 세미콜론에 의해 분리된 십진수를 구성한다. 연속적인 숫자들(왼쪽부터 오른쪽으로)은 연속적인 그룹들( 소수점에서 시작하여, 오른쪽에서부터 왼쪽으로)의 크기를 준다. 문자열에서 마지막 숫자는 모든 남겨진 그룹들을 위하여 되풀이해서 사용되어진다. 만일 마지막 정수가 -1이라면, 그것은 더이상 묶을 것이 없거나_또는 남겨진 숫자들이 분리자가 없는 하나의 큰 그룹을 구성하고 있는, 다른 방법으로 놓여져 있음을 의미한다.
    예를 들어, 만일 묶음(grouping)이 "4; 3; 2"라면, 숫자 123456787654321을 위한 정확한 그룹은 `12', `34', `56', `78', `765', `4321' 이다. 이것은 2 숫자그룹과 3 숫자 그룹에 의해 선행된, 마지막에 있는 4 숫자그룹을 사용한다. 그 숫자는 분리자 `, '를 사용하여, `12, 34, 56, 78, 765, 4321'. 와 같이 출력되어진다.
    "3"의 값은 보통 미국에서 사용되어, 세 개 숫자들의 반복된 그룹들을 지적한다. 표준 `C' 지역에서, grouping 과 mon_grouping이 모두 ""의 값을 가지면, 이 값은 전혀 묶음을 하지 않음을 의미한다.

    chart_frac_digits

    char frac_digits in

    이것은 국제와 지역 형식 각각에서 통화 값을 나타내는데 있어서 얼마나 많은 소수부(소수점의 오른쪽)를 사용할 것인가를 나타낸다. (아주 자주, 두 개의 멤버들은 같은 값을 갖는다. )

표준 `C'지역에서, 이들 멤버 둘은 모두 "미지정"이라는 의미를 가진 CHAR_MAX 값을 갖는다. ANSI 표준은 당신이 이것을 발견했을 때 그 값으로 무엇을 할 것인지 말하지 않는다. ; 우리는 아무런 소수부가 출력되지 않는 것을 추천한다. ( 이 지역은 또한 mon_decimal_point를 위해 빈 문자열을 지정하는데, 그것은 어느 소수부 숫자들의 출력도 거부됨을 의미한다. )

 

19. 6. 2 통화 기호 ( Currency Symbol ) 출력하기

구조체 struct lconv의 멤버들은 통화 값을 확인하는 심볼들을 어떻게 출력할 것인지를 정한다_미국달러의 표시는 `$'으로 세계적으로 인정한다.

각 나라는 두 개의 표준 통화기호들을 가지고 있다. 지역 통화기호는 그 나라안에서 통상적으로 사용되는것이고, 세계 통화기호는, 명백하게 그 나라를 지정할 필요가 있을 때 그 나라의 통화기호로 나타내기 위해서 국제적으로 사용된다.

예를 들어, 많은 나라들은 그들의 통화단위로 달러를 사용하고, 국제적으로 다른 나라들과 거래를 할 때 미국 달러대신에 캐나달 달러로 거래할것인지 또는 오스트레일리아 달러로 거래할것인지를 정하는 것은 중요하다. 그러나 그 구문이 캐나다가 되도록 정해져있을 때, 달러의 양들은 캐나다 달러로 된다고 가정되므로 이것을 명백하게 만들 필요가 없다.

char *currency_symbol

선택된 지역을위한 통화기호. 표준 `C' 지역에서, 이 멤버는 "미지정"을 의미하는, ""(빈 문자열)의 값을 갖는다. ANSI 표준은 당신이 이것을 발견했을 때, 그 값으로 무엇을 하는지를 말하지 않는다. 우리는 당신이 적당한 멤버에서 발견한 어느 문자열을 출력하는 것처럼, 빈 문자열을 간단히 출력하도록 권장한다.

char *int_curr_symbol

선택된 지역을위한 국제 통화기호. int_curr_symbol의 값은 국제 표준 ISO 4217 코드들에 의해 결정된 세 개-문자의 약어로 구성된다. 국제표준 ISO 4217코드는 한-문자 분리자의 다음에 나타나는(거의 공백을 사용. ), 통화와 자금의 표현을 위한 것이다. 표준 `C'지역에서, 이 멤버는 "미지정"을 의미하는 ""(빈 문자열)의 값을 갖는다. 우리는 적당한 멤버에서 발견된 어느 다른 문자열을 출력하는것처럼 빈 문자열을 간단히 출력하기를 권장한다.
char p_cs_precedes
char n_cs_precedes

이들 멤버들은 만일 currency_symbol 문자열이 통화량의 값보다 선행하면 1이고, 그 문자열이 값보다 뒤에 나타나면 0이다. p_cs_precedes 멤버는 양의 값(또는 0)에 적용하고, n_cs_precedes 멤버는 음의 값에 적용한다. 표준 `C' 지역에서, 이 멤버 둘 모두는 "미지정"을 의미하는 CHAR_MAX의 값을 갖는다. ANSI 표준은 당신이 이 값을 발견할 때 무엇을 하는지를 말하지 않지만, 우리는 그 값 앞에 통화기호를 출력하기를 권장한다. 대부분의 나라에서 그렇게 사용한다. 즉 그들 멤버 안에 있는 모든 0이 아닌 값들을 유사하게 취급하라.

POSIX 표준은 그들 두 개의 멤버들을 currency_symbol은 물론 int_curr_symbol에도 적용한다. ANSI C 표준은 그들은 오직 currency_symbol에 적용됨을 내포하고 있는 것처럼 보여서_int_curr_symbol은 항상 나타내려는 양(amount)에 선행할 것이다. 우리는 그들이 국제통화기호를 출력하기 위해서 보통의 관습들과 매치될것이라고 짐작할 수 있다. 우리의 나타내려는 양(amount)에 항상 선행할 것이라고 추측한다. 만일 우리가 이해 가능한 답을 발견한다면, 우리는 그것을 그렇게 할 것이다.

  • char p_sep_by_space
  • char n_sep_by_space

그들 멤버들은 currency_symbol 문자열과 양(amount) 사이에 공백이 있으면 1이고 없으면 0이다. p_sep_by_space 멤버는 양의값(또는 0)에 적용되고, n_sep_by_space 멤버는 음의 값에 적용된다. 표준 `C' 지역에서, 이들 멤버 둘 모두는 "미지정"을 의미하는 CHAR_MAX의 값을 갖는다. ANSI 표준은 당신이 이 값들을 발견할 때 당신이 무엇을 할 것인지를 알리지 못한다; 우리는 공백을 출력하는 것 그것을 취급하기를 제안한다. 즉, 그들 멤버 안에 있는 모든 0이 아닌 값들은 유사하게 최급하라. 그들 멤버들은 오직 currency_symbol에 적용된다. 당신이 int_curr_symbol을 사용할 때, 당신은 결코 부가적인 공백을 프린트하지 않는다, 왜냐하면, int_curr_symbol 그 자체는 적당한 분리자를 포함하고 있기 때문이다.

POSIX 표준은 그들 두 개의 멤버들을 currency_symbol 처럼 int_curr_symbol에도 적용한다. 그러나 ANSI C 표준에 있는 예제들은 적당한 분리자를 포함한 int_curr_symbol로 currency_sumbol만이 오직 적용됨을 보여주고 있다_그래서 당신은 결코 부가적인 공백을 프린트하지 않을 것이다. 우리가 현재 알고있는 것에 기초하여, 우리는 당신이 국제 통화기호를 프린트하고 아무런 공백을 프린트하지 않을 때, 그들 멤버들을 무시하기를 권장한다.

 

19. 6. 3 금전( Money ) 부호를 프린트하기

구조체 struct lconv의 멤버들은 통화 값의 부호를 어떻게 프린트할 것인지를 지정한다.

char *positive_sign

char *negative_sign

그들은 양의값(또는 0) 와 통화량을 알리기위해 사용되는 문자열이다. 표준 `C' 지역에서, 그들 멤버 둘 모두는 "미지정"을 의미하는 ""(빈 문자열)의 값을 갖는다.
ANSI 표준은 당신이 이 값을 발견할 때 무엇을 하도록 말하지 않는다; 우리는 당신이 그것을 발견했을 때, 심지어 만일 그것이 비어있을 때라고, positive_sign을 프린트하기를 권장한다. 음의 값을 위해서는, nugative_sign과 positive_sign이 모두 비어있지 않다면 당신이 발견할 것으로negative_sign을 프린트하라, 이 경우에는 `-'이다. ( 전혀 어떤 부호라도 지시하는 것을 실패하면 나중에 이해할 수 없는 값이 되고 만다. )

char p_sign_posn

char n_sign_posn

0 통화기호와 통화량이 괄호가 쳐져있다.
1 통화기호와 통화량 앞에 부호 문자열을 출력하라.
2 통화기호와 통화량 뒤에 부호문자열을 출력하라.
3 통화기호 앞에 적당한 부호 문자열을 출력하라.
4 통화기호 후에 적당한 부호 문자열을 출력하라.

CHAR_MAX

"미지정" 두 개 멤버 모두는 표준 `C' 지역에서 이 값을 갖는다.

ANSI 표준은 CHAR_MAX 값이 있을 때 당신이 무엇을 해야하는지 말해주지 않는다. 우리는 통화기호 뒤에 부호를 출력하도록 권장한다.

국제적 통화 형식이거나 아닌것에 이들 멤버들의 적용이 당신에게 허용 될 것인지가 명백하지 않다. POSIX는 당신이 그렇게 하도록 하지만, ANSI C 표준에 있는 예제들은 당신이 그렇게 하지 않기를 제안한다. 우리는 통화량의 형식화를 위한 관습을 잘 알고 있는 누군가가 우리가 무엇을 권장할지를 우리에게 말해주기를 희망한다.