[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

General Programming Concepts: Writing and Debugging Programs


Locale Subroutines

The locale of a process determines the way character collation, character classification, date and time formatting, numeric punctuation, monetary punctuation, and message output are handled. The following section describes how to set and access information about the current locale in a program using National Language Support (NLS).

Setting the Locale

Every internationalized program must set the current locale using the setlocale

subroutine. This subroutine allows a process to change or query the current locale by accessing locale databases.

When a process is started, its current locale is set to the C or POSIX locale. A program that depends on locale data not defined in the C or POSIX locale must invoke the setlocale

subroutine in the following manner before using any of the locale-specific information:

setlocale(LC_ALL, "");

Accessing Locale Information

The following subroutines provide access to information defined in the current locale as determined by the most recent call to the setlocale

subroutine:

localeconv

Provides access to locale information defined in the LC_MONETARY and LC_NUMERIC categories of the current locale. The localeconv subroutine retrieves information about these categories, places the information in a structure of type lconv as defined in the locale.h file, and returns a pointer to this structure.
nl_langinfo

Returns a pointer to a null-terminated string containing information defined in the LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, and LC_TIME categories of the current locale.
rpmatch

Tests for positive and negative responses. These are specified in the LC_MESSAGES category of the current locale. Responses can be regular expressions as well as simple strings. The rpmatch subroutine is not an industry-standard subroutine. Portable applications should not assume that this subroutine is available.

The localeconv and nl_langinfo subroutines do not provide access to all LC_*  categories.

The current locale setting for a category can be obtained by: setlocale(Category(char*)0). The return value is a string specifying the current locale for Category. The following example determines the current locale setting for the LC_CTYPE category:

char *ctype_locale; ctype_locale = setlocale(LC_CTYPE, (char*)0);

Examples

  1. The following example uses the setlocale

    subroutine to change the locale from the default C locale to the locale specified by the environment variables, consistent with the hierarchy of the locale environment variables:

    #include <locale.h>
    main()
    {
     
        char *p;
     
        p = setlocale(LC_ALL, "");
      
       /*
        **  The program will have the locale as set by the
        **  LC_* and LANG variables.
        */ 
     }
    
  2. The following example

    uses the setlocale

    subroutine to obtain the current locale setting for the LC_COLLATE category:

    #include <stdio.h>
    #include <locale.h>
      
    main()
    {
        char *p;
     
        /*  set the current locale to what is specified  */
        p = setlocale(LC_ALL, "");
        /*  The current locale settings for all the
        **  categories is pointed to by p
        */
     
        /*
        **  Find the current setting for the
        **  LC_COLLATE category
        */
        p = setlocale(LC_COLLATE, NULL);
        /*
        **  p points to a string containing the current locale
        **  setting for the LC_COLLATE category.
        */
      
     } 
    
  3. The following example

    uses the setlocale

    subroutine to obtain the current locale setting and saves it for later use. This action allows the program to temporarily change the locale to a new locale. After processing is complete, the locale can be returned to its original state.

    #include <stdio.h>
    #include <locale.h>
    #include <string.h>
      
    #define NEW_LOCALE "MY_LOCALE"
      
    main()
    {
        char *p, *save_locale;
     
        p = setlocale(LC_ALL, ""); 
        /*
        **  Initiate locale. p points to the current locale
        **  setting for all the categories
        */
     
        save_locale = (char *)malloc(strlen(p) +1); 
        strcpy(save_locale, p);
            /*  Save the current locale setting */ 
        p = setlocale(LC_ALL, NEW_LOCALE);
            /* Change to new locale */
      
        /*
        **  Do processing  ...
        */
     
         /*  Change back to old locale  */
        p = setlocale(LC_ALL, save_locale);  /* Restore old locale */
     
         free(save_locale);    /* Free the memory */
    }
    
  4. The following example

    uses the setlocale

    subroutine to set the LC_MESSAGES category to the locale determined by the environment variables. All other categories remain set to the C locale.

    #include <locale.h>
     
    main() 
    { 
        char *p;
     
        /*
        **  The program starts in the C locale for all categories.
        */
     
        p = setlocale(LC_MESSAGES, "");
     
         /*
        **  At this time the LC_COLLATE, LC_CTYPE, LC_NUMERIC,
        **  LC_MONETARY, LC_TIME will be in the C locale.
        **  LC_MESSAGES will be set to the current locale setting
        **  as determined by the environment variables.
        */
    }
    
  5. The following example

    uses the localeconv

    subroutine to obtain the decimal-point setting for the current locale:

    #include <locale.h>
     
    main()
    {
            struct lconv *ptr;
            char *decimal;
     
            (void)setlocale(LC_ALL, "");
            ptr = localeconv();
            /*
            ** Access the data obtained. For example,
            ** obtain the current decimal point setting.
            */
            decimal = ptr->decimal_point;
    }
    
  6. The following example

    uses the nl_langinfo

    subroutine to obtain the date and time format for the current locale:

    #include <langinfo.h>
    #include <locale.h>
    main()
    {
        char *ptr;
        (void)setlocale(LC_ALL, "");
        ptr = nl_langinfo(D_T_FMT);
    }
    
  7. The following example

    uses the nl_langinfo subroutine to obtain the radix character for the current locale:

    #include <langinfo.h>
    #include <locale.h>
     
    main()
    {
        char *ptr;
        (void)setlocale(LC_ALL, "");  /* Set the program's locale  */
        ptr = nl_langinfo(RADIXCHAR); /* Obtain the radix character*/
    }
    
  8. The following example

    uses the nl_langinfo subroutine to obtain the setting of the currency symbol for the current locale:

    #include <langinfo.h>
    #include <locale.h>
     
    main()
    {
        char *ptr;
        (void)setlocale(LC_ALL, "");  /* Set the program's locale  */
        ptr = nl_langinfo(CRNCYSTR);  /* Obtain the currency string*/
        /* The currency string will be "-$" in the U. S. locale. */
    }
    
  9. The following example

    uses the rpmatch

    subroutine to obtain the setting of affirmative and negative response strings for the current locale:

    The affirmative and negative responses as specified in the locale database are no longer simple strings; they can be regular expressions. For example, the yesexpr can be the following regular expression, which will accept an upper or lower case letter y, followed by zero or more alphabetic characters; or the character O followed by K. Thus, yesexpr may be the following regular expression:

    ([yY][:alpha:]*|OK) 
    

    The standards do not contain a subroutine to retrieve and compare this information. You can use the AIX-specific rpmatch(const char *response) subroutine.

    #include <stdio.h>
    #include <langinfo.h>
    #include <locale.h>
    #include <regex.h>
     
    int rpmatch(const char *);
        /*
        **  Returns 1 if yes response, 0 if no  response,
        ** -1 otherwise
        */
     
    main()
    {
        int  ret;
        char *resp;
     
    (void)setlocale(LC_ALL, "");
     
        do {
            /*
            ** Obtain the response to the query for yes/no strings.
            ** The string pointer resp points to this response.
            ** Check if the string is yes.
            */
        ret = rpmatch(resp);
     
        if(ret == 1){
            /* Response was yes. */
            /* Process accordingly. */
            }else if(ret == 0){
            /* Response was negative. */
            /* Process negative response. */
            }else if(ret<0){
            /* No match with yes/no occurred. */
            continue;
            }
        }while(ret <0);
    }
    
  10. The following example provides a method of implementing the rpmatch subroutine. Note that most applications should use the rpmatch subroutine in libc. The following implementation of rpmatch is just for illustration purposes.

    Note that nl_langinfo(YESEXPR) and nl_langinfo(NOEXPR) are used to obtain the regular expressions for the affirmative and negative responses respectively.

    #include <langinfo.h>
    #include <regex.h>
    /*
    ** rpmatch() performs comparison of a string to a regular expression
    ** using the POSIX.2 defined regular expression compile and match
    ** functions. The first argument is the response from the user and the
    ** second string is the current locale setting of the regular expression.
    */
    int rpmatch( const char *string)
    
     
     
     
    {
         int status;
         int retval;
         regex_t re;
         char *pattern;
     
         pattern = nl_langinfo(YESEXPR);
         /* Compile the regular expression pointed to by pattern. */
         if( ( status = regcomp( &re, pattern, REG_EXTENDED | REG_NOSUB )) != 0 ){
              retval = -2; /*-2 indicates yes expr compile error */
              return(retval);
         }
         /* Match the string with the compiled regular expression. */
         status = regexec( &re, string, (size_t)0, (regmatch_t *)NULL, 0);
         if(status == 0){
              retval = 1;   /* Yes match found */
         }else{    /* Check for negative response */
              pattern = nl_langinfo(NOEXPR);
              if( ( status = regcomp( &re, pattern,
                   REG_EXTENDED | REG_NOSUB )) != 0 ){
                        retval = -3;/*-3 indicates no compile error */
                        return(retval);
                   }
              status = regexec( &re, string, (size_t)0, 
                             (regmatch_t *)NULL, 0);
              if(status == 0)
                   retval = 0;/* Negative response match found */
         }else
                   retval = -1; /* The string did not match yes or no
                                  response */
         regfree(&re);
         return(retval);
    }
    

Related Information

National Language Support Subroutines Overview provides information about wide character and multibyte subroutines.

For general information about internationalizing programs, see Chapter 16, National Language Support and Locale Overview for Programming.

For more information about using locales, see Locale Overview for System Management in AIX 5L Version 5.1 System Management Guide: Operating System and Devices.

Character Set Description (charmap) source file format, Locale Definition source file format.

For specific information about locale categories and their keywords, see the LC_COLLATE category, LC_CTYPE category, LC_MESSAGES category, LC_MONETARY category, LC_NUMERIC category, and LC_TIME category.


[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]