Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any alternative for printf?

I have to create a software that must work on several *nix platforms (Linux, AIX, ...).

I need to handle internationalization and my translation strings are in the following form:

"Hi %1, you are %2." // English
"Vous êtes %2, bonjour %1 !" // French

Here %1 stand for the name, and %2 for another word. I may change the format, that's not an issue.

I tried to use printf() but you cannot specify the order of the parameters, you just specify their types.

"Hi %s, you are %s"
"Vous êtes %s, bonjour %s !"

Now there is no way to know which parameter to use for replacement of %s: printf() just uses the first one, then the next.

Is there any alternative to printf() that deals with this ?

Note: gettext() is not an option.

like image 270
ereOn Avatar asked Oct 12 '10 09:10

ereOn


People also ask

What is alternative of printf?

puts() The function puts() is used to print the string on the output stream with the additional new line character '\n'. It moves the cursor to the next line. Implementation of puts() is easier than printf().

Is it OK to use printf in C++?

In the big picture, printf is not compatible with C++ streams. C++ streams allow you to easily convert your console output to a file. (Although you can do similar with fprintf ).

Can we use print instead of printf in C?

Hey printf() is a built in function in C which is bundled in header file stdio. h(STANDARD INPUT OUTPUT). It is used to print something on console screen. But as you asked for print(), according to me there is no such function in C language, it must be in other programming or web language.

What is the difference between printf () and puts ()?

Definition. printf is a C function to print a formatted string to the standard output stream, which is the computer screen. In contrast, “puts” is a C library function that writes a string to stdout or standard output. Thus, this is the fundamental difference between printf and puts.

Is there an alternative to printf in C++?

If you are looking for some alternatives, you might consider {fmt} too. The GNU C++ compiler g++ checks printf arguments at compile-time. If you specify -Wall on the command line, it issues a warning if it detects a mismatch. So if you are using this compiler, you can use printf without worrying.

What are the best alternatives to printify?

Check out the full Printify review if you'd like to learn more. Spocket is an interesting alternative to Printful. Unlike other solutions that act like a design system and marketplace in one, Spocket is an app that integrates with WooCommerce and Shopify stores.

Is printf type safe in practice?

Depending on the compiler you use, printf will be type safe in practice because many compilers can parse and check your format strings. My recommendation is to ignore iostreams; they're a mess.

What is the difference between sprintf and snprintf?

printf is just as safe as snprintf. The snprintf function is provided to guard against the buffer overrun errors that sprintf (not printf) is vulnerable to. @Chipster: did you read my comment?


2 Answers

I don't mean to be the bearer of bad tidings but what you're proposing is actually a bad idea. I work for a company that take i18n very seriously and we've discovered (painfully) that you cannot just slot words into sentences like that, since they often make no sense.

What we do is to simply disconnect the error text from the variable bits altogether, so as to avoid these problems. For, example, we'll generate an error:

XYZ-E-1002 Frobozz not configured for multiple zorkmids (F22, 7). 

And then, in the description of the error, you state simply that the two values in the parentheses at the end were the Frobozz identifier and the number of zorkmids you tried to inflict on it.

This leaves i18n translation as an incredibly easy task since you have, at translation time, all of the language elements you need without worrying whether the variable bits should be singular or plural, masculine or feminine, first, second, or third declension (whatever the heck that actually means).

The translation team simply has to convert "Frobozz not configured for multiple zorkmids" and that's a lot easier.


For those who would like to see a concrete example, I have something back from our translation bods (with enough stuff changed to protect the guilty).

At some point, someone submitted the following:

The {name} {object} is invalid 

where {name} was the name of a object (customers, orders, etc) and {object} was the object type itself (table, file, document, stored procedure, etc).

Simple enough for English, the primary (probably only) language of the developers, but they struck a problem when translating to German/Swiss-German.

While the "customers document" translated correctly (in a positional sense) to Kundendokument, the fact that the format string had a space between the two words was an issue. That was basically because the developers were trying to get the sentence to sound more natural but, unfortunately, only more natural based on their limited experience.

A bigger problem was with the "customers stored procedure" which became gespeichertes Verfahren der Kunden, literally "stored procedure of the customers". While the German customers may have put up with a space in Kunden dokument, there is no way to impose gespeichertes Verfahren der Kunden onto {name} {object} successfully.

Now you may say that a cleverer format string would have fixed this but there are several reasons why that would be incorrect:

  • this is a very simple example, there are likely to be others more complex (I'd try get some examples but our translation bods have made it clear they have more pressing work than to submit themselves to my every whim).
  • the whole point of the format strings is to externalise translation. If the format strings themselves are specific to the translation target, you've gained very little by externalising the text.
  • developers should not have to concern themselves with format strings like {possible-pre-adjectives} {possible-pre-owner} {object} {possible-post-adjectives} {possible-post-owner} {possible-postowner-adjectives}. That is the job of the translation teams since they understand the nuances.

Note that introducing the disconnect sidesteps this issue nicely:

 The object specified by <parameter 1>, of type <parameter 2>, is invalid.     Parameter 1 = {name}.     Parameter 2 = {object}. Der sache nannte <parameter 1>, dessen art <parameter 2> ist, ist falsch.      Parameter 1 = {name}.     Parameter 2 = {object}. 

That last translation was one of mine, please don't use it to impugn the quality of our translators. No doubt more fluent German speakers will get a good laugh out of it.

like image 197
paxdiablo Avatar answered Sep 24 '22 20:09

paxdiablo


POSIX printf() supports positional arguments.

printf("Hi %1$s, you are %2$s.", name, status);
printf("Vous êtes %2$s, bonjour %1$s !", name, status);
like image 32
Ignacio Vazquez-Abrams Avatar answered Sep 21 '22 20:09

Ignacio Vazquez-Abrams