Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat are the formal and practical constraints on the values in 'struct lconv' describing a locale?
    primarykey
    data
    text
    <h2>Background</h2> <p>The C99 standard, section 7.11, describes the <code>&lt;locale.h&gt;</code> header and its contents. In particular, it defines <code>struct lconv</code> and says that:</p> <blockquote> <p>[...] In the "C" locale, the members shall have the values specified in the comments.</p> <pre><code>char *decimal_point; // "." char *thousands_sep; // "" char *grouping; // "" char *mon_decimal_point; // "" char *mon_thousands_sep; // "" char *mon_grouping; // "" char *positive_sign; // "" char *negative_sign; // "" char *currency_symbol; // "" char frac_digits; // CHAR_MAX char p_cs_precedes; // CHAR_MAX char n_cs_precedes; // CHAR_MAX char p_sep_by_space; // CHAR_MAX char n_sep_by_space; // CHAR_MAX char p_sign_posn; // CHAR_MAX char n_sign_posn; // CHAR_MAX char *int_curr_symbol; // "" char int_frac_digits; // CHAR_MAX char int_p_cs_precedes; // CHAR_MAX char int_n_cs_precedes; // CHAR_MAX char int_p_sep_by_space; // CHAR_MAX char int_n_sep_by_space; // CHAR_MAX char int_p_sign_posn; // CHAR_MAX char int_n_sign_posn; // CHAR_MAX </code></pre> </blockquote> <p>Section 7.11.2.1 "The localeconv() function" goes on to say:</p> <blockquote> <p>The members of the structure with type <code>char *</code> are pointers to strings, any of which (except <code>decimal_point</code>) can point to <code>""</code>, to indicate that the value is not available in the current locale or is of zero length. [...] The members with type char are nonnegative numbers, any of which can be <code>CHAR_MAX</code> to indicate that the value is not available in the current locale.</p> </blockquote> <p>It goes on to discuss each of the members. You can see 4 groups of 3 members, one representative group being <code>p_cs_precedes</code>, <code>p_sep_by_space</code> and <code>p_sign_posn</code>.</p> <blockquote> <p><code>char p_cs_precedes</code><br> Set to 1 or 0 if the currency_symbol respectively precedes or succeeds the value for a nonnegative locally formatted monetary quantity.</p> <p><code>char p_sep_by_space</code><br> Set to a value indicating the separation of the currency_symbol, the sign string, and the value for a nonnegative locally formatted monetary quantity.</p> <p><code>char p_sign_posn</code> Set to a value indicating the positioning of the positive_sign for a nonnegative locally formatted monetary quantity.</p> </blockquote> <p>The details of the interpretation of <code>p_sign_posn</code> are given; they are not material to this question.</p> <p>The standard also gives some examples of how to interpret these types.</p> <p>If you find the original C99 standard (ISO/IEC 9899:1999) be aware that both TC1 (International Standard ISO/IEC 9899:1999 Technical Corrigendum 1, published 2001-09-01) and TC2 (International Standard ISO/IEC 9899:1999 Technical Corrigendum 2, published 2004-11-15) make changes to §7.11.2.1 (but TC3 does not). However, the changes neither address nor affect the answers to the questions I'm about to ask.</p> <hr> <h2>Questions</h2> <p>My first two questions are about the four triples (cs_precedes, sep_by_space, and sign_posn), and the others more general questions about what constitutes a valid locale:</p> <ol> <li>Is it feasible or sensible to have one or two of the members of a triple with the CHAR_MAX designation while the other members have values in the normal range (0-1, 0-1, 0-4)?</li> <li><p>If it is sensible, how should the combinations be interpreted?</p> <p>Two combinations (all values set to <code>CHAR_MAX</code>, as in the <code>"C"</code> locale, and all values set validly) are defined; it is the other 6 hybrid settings that I'm curious about.</p></li> <li><p>Is a locale properly formed if the triples are defined but the relevant currency symbol is not?</p></li> <li>Is a locale properly formed if the monetary decimal point is not defined but the currency symbol is defined.</li> <li>If the sign position is not 0 (indicating that a value is surround by parentheses), is a locale properly formed if the currency symbol is set but both the positive and negative sign strings are empty?</li> <li>Does it make sense for the positive triple to be defined when the negative triple is not?</li> </ol> <hr> <p>My inclination is to answer:</p> <ol> <li>No; either all or none of the members of a triple should be set to CHAR_MAX.</li> <li>Not applicable given the answer to (1).</li> <li>No.</li> <li>No (but there is a borderline case for the old Italian currency (lire) where there were no fractions and so no decimal point was needed; that could be handled with a condition that the monetary decimal point is only needed if <code>frac_digits</code> or <code>int_frac_digits</code> is greater than zero).</li> <li>No.</li> <li>No.</li> </ol> <p>An implementation might then enforce these rules, but it is conceivable that another implementation would interpret the rules differently and come to a different conclusion.</p> <p>What say you?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. COIs it an acceptable answer to pick "none of the above?" As in, don't use C locales for formatting currency, since the odds of someone's locale matching their one-and-only preferred monetary unit and notation format are exceptionally low…?
      singulars
    2. COHmmm, not really, though I can see some justice in your position. A sensible set of interfaces to the formatting functions would include two variants, rather like `printf()` and `fprintf()`; the simpler interface would use the current locale while the one-argument-more-complex version would take a 'const struct lconv *` argument. When your locale does what you need, use the simpler functions. When it doesn't, derive a `struct lconv` structure that is appropriately populated and use that. One merit of this is that the 'locale provided' versions are rigorously testable; the others are not.
      singulars
    3. COThe other half of the answer your question, @BRPocock, would be "if you don't use the locale, how do you get your currency values formatted?" and "how do you specify the format to be used?". The only alternative I'm aware of is the `strfmon()` function mentioned in the bounty notes, and its sidekick `strmon_l()` (which takes a `locale_t` as defined in POSIX, rather than `struct lconv`, but is otherwise similar in concept). Or write your own, homebrew code...
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload