Next | Prev | Up | Top | Contents | Index

Variably Ordered Referencing of printf() Arguments

printf() and its variants can now refer to arguments in any specified order. Consider the following scenario: an application has chosen "house" from a list of objects and "white" from a list of colors. The application wishes to display this choice. The code might look like this:

char *obj, *color;
... /* make choices */ ...
printf("%s %s\n", color, obj);
The printf() call produces this:

white house
Even once we make sure that obj and color are localized strings, we are not quite finished. If our locale is Spanish, the printf() yields:

blanca casa
That is incorrect grammar; in Spanish, it should be:

casa blanca
The solution to this problem is variably ordered referencing of printf() arguments. The syntax of printf() format strings has been expanded to deal with this.

The original definition of printf() is that each conversion specification %T (where T represents any of the printf() conversion characters) is implicitly matched to an argument value by position. In order to deal with variably ordered strings, printf() allows an argument position index D to appear in the conversion specification following the %, so that where a format string contains %T , it can now contain %D$T. The value D, set off by a currency symbol ($), selects the argument from the argument list to be used. This means you can write

printf("2nd parameter is %2$s; the 1st is %1$s", p1, p2)
The second parameter is printed first, with the first parameter printed second. For example:

char *store = "Macy's";
char *obj = "a cup";
printf("At %1$s, I bought %2$s.\n", store, obj);
printf("I bought %2$s at %1$s.\n", store, obj);
This code displays

At Macy's, I bought a cup.
I bought a cup at Macy's.
In English, we are able to come up with strings suitable for either word order; in some other language, we might not be so lucky. Nor can we predict which order such languages might prefer. So the developer has no way of knowing how to create traditional printf() format strings suitable for all languages.

Developers should therefore use message catalogs for their printf() format strings that take linguistic parameters, and allow localizers to localize the format strings as well as text strings. This means that the localizer has much greater ability to create intelligible text. An internationalized version of the above code appears in Example 6-4.

Example 6-4 : Internationalized Code

/* internationalized (XPG/4) version */
char *form = catgets(msgd, set, formNum,
                   "At %1$s, I bought %2$s.\n");
char *store = catgets(msgd, set, storeNum, "Macy's");
char *obj = catgets(msgd, set, objNum, "a cup");
printf(form, store, obj);
The unlocalized (default) version would produce

At Macy's, I bought a cup.
A localized version might produce

Compré una tasa en Macy's.
In practice, variably ordered format strings are found only in message catalogs and not in default strings. The default string usually simply uses the parameters in the order they're given, without the new variable-order format strings.


Next | Prev | Up | Top | Contents | Index