August 18, 2001
Argh, no!  Printf and scanf are ugly remnants of C's limitations.  Printf made sense in the ANSI C days, but it and its terribly potential for runtime crashes and subtle bugs have no place in a modern language.

C#'s solution is an interesting good compromise, something like:

    print("{1} picked up {2} {3}s",person,count,item);

The HUGE advantages are:

1. It is typesafe. The parameters must be convertable to strings, and their type isn't (redundently or incorrectly) specified in the format string."

2. It's easily localizable to other human languages because arguments can be reordered.  This is really critical for shipping software internationally, where the order of nouns, verbs, etc., vary.

An even slightly better approach is to have a new "concatenate with formatting" operator which takes a formatting string and a variant and returns a new string.  For example:

    "{1} picked up {2} {3}s" $ person $ count$item

The $ operator has the following effects:

    "{1} picked up {2} {3}s" $ "tim" = "Tim picked up {1} {2}s"
    "Tim picked up {1} {2}s" $ 12 = "Tim picked up 12 {12}'s"
    "Tim picked up 12 {1}s" $ "marble" = "Tim picked up 12 marbles"

Therefore

    "{1} picked up {2} {3}s" $ "tim" $ 12 $ "marbles" = "Tim picked up 12
marbles"

This is very general, and could be extended with other appropriate natural language features useful to localization such as pluralization.

-Tim

"Richard Krehbiel" <rich@kastle.com> wrote in message news:9lgkos$251p$1@digitaldaemon.com...
> For goodness' sake, don't take printf from C verbatim.
>
> The programmer himself must match the format specifier to the data type. The programmer himself must align the number of the format specifiers to
the
> number of arguments.
> The programmer himself must align the positions of the format specifiers
to
> the positions of arguments.
>
> Make a printf where the format specifier is adjacent to the variable.
>
> I have a function that works this way:
>
>     my_printf("a=%d", (int)a, " b=%d", (int)b, (char *)NULL);
>
> i.e. it takes a format strng containing *one* argument; the arguments(s) following are for that format specifier; multiple pairs of format/argument can be supplied.
>
> Perhaps in D, the end of the variable argument list to Dprintf can be
known,
> rather than having the programmer be diligent to add the NULL at the end every time.  Actually, if you add Real Macros, printf can be a macro which knows the number and data types of the arguments:
>
>     Dprintf("a=", a, " b=", b, "\n");
>
> --
> Richard Krehbiel, Arlington, VA, USA
> rich@kastle.com (work) or krehbiel3@home.com (personal)


August 18, 2001
In article <grobbins-09E5EF.22074416082001@news.digitalmars.com>, "Grobbins" <grobbins@badaddress.znet.com> wrote:

>>  I know it's not typesafe, but printf is soooo useful that it's
>> worth giving up ideological purity for it! -Walter
> 
> I also love using printf and sprintf from a convenience standpoint, but it's poison for internationalization because it hardcodes in the parameter order.  Any localizer will point out that string substitution in commercial code requires that parameters be able to be reordered.
> 
> For example,
> 
>   printf("%s %d", pMonth, nDay); // July 3
> 
> frequently becomes
> 
>   printf("%d de %s", nDay, pMonth); // 3 de Julio
> 
> during localization, but printf precludes reordering of the parameters in the string without recompiling.

Huh?  With a decent printf, and message catalog library, you write:

   printf (_("%s %d"), pMonth, nDay);

And your translator adds the following to their message catalog:

  "%2$d de %1$s"

I've been using this for years.

> Unfortunately, few C programmers realize this, so they assume that using printf for generating strings is reasonable.

Printf is good.  Provided you have a fully featured version.  Take a look at the manual for GNU glibc-2.1 (or later) and GNU gettext-0.10.35 (or later) for examples.  I am working on a portable standalone printf library that doesn't require dragging around all of glibc's libio to work on substandard vendor C libraries... follow the links in my .sig.

My one complaint about the C99 API is that there is no way to expose a printf function to a parsed language, since the calling conventions vary between implementations.  Say I parse the following tokens:

   SYM:printf LITERAL:( STR:"%s %d" SYM:pMonth SYM:nDate LITERAL:)

How do I leverage the libc printf calls to format this for me?  Often passing
an array containing the addresses of pMonth and nDate cast to void* to
vsprintf works, but that is not portable to plenty of common vendor C
libraries. How many times have you seen interpreters that reimplement the
whole <%n$fw.ps> parsing code? Every implementation of awk I have ever
seen for a start...

There needs to be a new class of API calls to explicitly support that, say:

   int printfv (char[] format, void*[] args);
   int sprintfv (char[] buffer, char[] format, void*[] args);
   etc.

Cheers,
	Gary.
-- 
  ())_. Gary V. Vaughan     gary@(oranda.demon.co.uk|gnu.org)
  ( '/  Research Scientist  http://www.oranda.demon.co.uk       ,_())____
  / )=  GNU Hacker          http://www.gnu.org/software/libtool  \'      `&
`(_~)_  Tech' Author        http://sources.redhat.com/autobook   =`---d__/
August 18, 2001
In article <pan.2001.08.18.16.54.49.707.31584@oranda.demon.co.uk>, "Gary V. Vaughan" <gary@oranda.demon.co.uk> wrote:
> Huh?  With a decent printf, and message catalog library, you write:
>    printf (_("%s %d"), pMonth, nDay);
> And your translator adds the following to their message catalog:
>   "%2$d de %1$s"

Some recent compilers do support that or a variant, and no doubt it's a huge help for translators faced with printf'd strings.  In working on Windows and Mac software, I've yet to see it used.  It does open the door to software bugs being introduced by translators who get wrong the rewriting of the format strings, though.

The C# solution mentioned elsewhere in this thread appears to be quite a bit better, as it is less prone to mistakes introduced by coders or translators, and is also more readable.

Greg Robbins
August 18, 2001
In article <grobbins-05C120.11345718082001@news.digitalmars.com>, "Grobbins" <grobbins@badaddress.znet.com> wrote:

> In article <pan.2001.08.18.16.54.49.707.31584@oranda.demon.co.uk>, "Gary V. Vaughan" <gary@oranda.demon.co.uk> wrote:
>> Huh?  With a decent printf, and message catalog library, you write:
>>    printf (_("%s %d"), pMonth, nDay);
>> And your translator adds the following to their message catalog:
>>   "%2$d de %1$s"
> 
> Some recent compilers do support that or a variant, and no doubt it's a huge help for translators faced with printf'd strings.

It is a property of the C library.  The %n$s positional specifiers were introduced before SVR4 (about 10 years ago was the first time I saw it), and are part of the C99 standard specification and POSIX standard -- and probably some others that I am not aware of.

There are still systems that don't support them, but that is what my standalone implementation is for... ;-)

> In working on
> Windows and Mac software, I've yet to see it used.  It does open the
> door to software bugs being introduced by translators who get wrong the
> rewriting of the format strings, though.

Isn't Mac OS a BSD deriviant?  Perhaps BSD didn't introduce it until they added POSIX compliance.  I would be surprised if `man printf' doesn't describe it.  Windows does pay lip service to the prevelant standards, so it may even be present there -- but you're right that it is quite possibly missing.  My implementation already compiles with cygwin, so a port to MSVCRT ought not to be too difficult.

> The C# solution mentioned elsewhere in this thread appears to be quite a bit better, as it is less prone to mistakes introduced by coders or translators, and is also more readable.

  print ("{1} picked up {2} {3}s",  person,count,item);
  printf("%1$s picked up %2$d %3$s",person,count,item);

Aesthetically there is little between them,  I'm sure we would soon get used to whichever we end up using.  But I wonder how ugly the c# variant is if I want to mix argument specifiers and literal parenthesised numbers though?  And are the literals visually distinct from the real specifiers?  Does c# offer justification, sign alignment, padding, precision, radix conversion etc.?  I do agree that the type safety of the c# implementation is better than C's api, but as far as the interface goes that could be achieved by changing the final specifier character...

Cheers,
	Gary.
-- 
  ())_. Gary V. Vaughan     gary@(oranda.demon.co.uk|gnu.org)
  ( '/  Research Scientist  http://www.oranda.demon.co.uk       ,_())____
  / )=  GNU Hacker          http://www.gnu.org/software/libtool  \'      `&
`(_~)_  Tech' Author        http://sources.redhat.com/autobook   =`---d__/
August 19, 2001
Christophe de Dinechin wrote:
> 
> For starters, print << "i = " << i is ugly.
> 
> But then, count the function calls. In the statement above, you have two. In the case of printf, you have one. Function calls (in particular through shared libraries) tend to be expensive things.

	That's a cop out.  printf is one function call with many more under the
covers.  The insert operation make it explicit.  I'm not fixed on the
insert idea, print is a beauty in perl, but saying the has more calls is
a bit wrong.

> As I documented in another thread, I state that the correct model is:
>     print "i=", i
> 
> Formatting is a different topic. There are many choices, all of them can be made type safe and using a single function call to the output function.

I have yet to see a formatting syntax I like.  The closest is the FORMAT stuff in perl and that's UGLY.

Dan
August 20, 2001
a wrote:

> Christophe de Dinechin wrote:
> >
> > For starters, print << "i = " << i is ugly.
> >
> > But then, count the function calls. In the statement above, you have two. In the case of printf, you have one. Function calls (in particular through shared libraries) tend to be expensive things.
>
>         That's a cop out.  printf is one function call with many more under the
> covers.  The insert operation make it explicit.  I'm not fixed on the
> insert idea, print is a beauty in perl, but saying the has more calls is
> a bit wrong.

I am not talking about run-time, I am talking about code bloat: cout<< duplicates code at call site (in your program), whereas printf and writeln keep it in the library. So while the number of calls being _executed_ will be close, the number of instructions required in you C++ program will be way higher.


> > As I documented in another thread, I state that the correct model is:
> >     print "i=", i

Christophe

September 11, 2001
a wrote:
[snipped]
> 
> I have yet to see a formatting syntax I like.  The closest is the FORMAT stuff in perl and that's UGLY.

How about the COBOL's 'using' and 'pix'?
September 11, 2001
Cesar Rabak wrote:
> 
> a wrote:
> [snipped]
> >
> > I have yet to see a formatting syntax I like.  The closest is the FORMAT stuff in perl and that's UGLY.
> 
> How about the COBOL's 'using' and 'pix'?

	ACK!  Foul creature!  Daemon BE GONE!  Do not tempt me to say why I
dislike this for I would have to admit I know enough COBOL to hate it!

Dan
November 04, 2001
I too think printf is evil, it's way too easy to screw up and get at best bad output, at worst a crash.  Just 2 days ago we found this bug in our C++ code:

SimpleString item;
const char* name;

printf("%s%s", name, item);

And amazingly enough, this actually worked!  The only reason it worked was that SimpleString was an object consisting of only one const char*, so when it copied the SimpleString to the stack as a parameter to printf, it looked just like a raw const char*.  But it was scary to find out the compiler was letting that crap through without any warnings.

I think string formatting should be separated entirely from output.  That way someone can make a new output function that takes a string as parameter, without having to reimplement formatting.  You could generically format a string, and use it either as a string or as parameter to some output function.

I suggest:

string Format(whatever formatting specification parameters goes in here);

void Print(string);

Actually I'm all in favor of just having all types be able to define a conversion to string, and having some generic functions that take a string as parameter and return a different string, such as:

string PadLeft(string, int field_width);
string PadRight(string, int field_width);
string Center(string, int field_width);
string LeadingZeros(string, int field_width);

Then we could just use the string concatenation operator to build our strings anywhere we want, for any purpose, not just output.

I also think that Print shouldn't be in the core language specification, mainly because *not all platforms can provide output functionality*!!! Think embedded systems.  Think MS Windows, where the only output you usually have is OutputDebugString (only viewable with a debugger or DrWatson) or MessageBox or drawing graphics into a window.  Not all programs are stdio oriented.

Print belongs in a OS-specific library.

Sean

"Tim Sweeney" <tim@epicgames.com> wrote in message news:9lkg18$2o6b$1@digitaldaemon.com...
> Argh, no!  Printf and scanf are ugly remnants of C's limitations.  Printf made sense in the ANSI C days, but it and its terribly potential for
runtime
> crashes and subtle bugs have no place in a modern language.
>
> C#'s solution is an interesting good compromise, something like:
>
>     print("{1} picked up {2} {3}s",person,count,item);
>
> The HUGE advantages are:
>
> 1. It is typesafe. The parameters must be convertable to strings, and
their
> type isn't (redundently or incorrectly) specified in the format string."
>
> 2. It's easily localizable to other human languages because arguments can
be
> reordered.  This is really critical for shipping software internationally, where the order of nouns, verbs, etc., vary.
>
> An even slightly better approach is to have a new "concatenate with formatting" operator which takes a formatting string and a variant and returns a new string.  For example:
>
>     "{1} picked up {2} {3}s" $ person $ count$item
>
> The $ operator has the following effects:
>
>     "{1} picked up {2} {3}s" $ "tim" = "Tim picked up {1} {2}s"
>     "Tim picked up {1} {2}s" $ 12 = "Tim picked up 12 {12}'s"
>     "Tim picked up 12 {1}s" $ "marble" = "Tim picked up 12 marbles"
>
> Therefore
>
>     "{1} picked up {2} {3}s" $ "tim" $ 12 $ "marbles" = "Tim picked up 12
> marbles"
>
> This is very general, and could be extended with other appropriate natural language features useful to localization such as pluralization.
>
> -Tim
>
> "Richard Krehbiel" <rich@kastle.com> wrote in message news:9lgkos$251p$1@digitaldaemon.com...
> > For goodness' sake, don't take printf from C verbatim.
> >
> > The programmer himself must match the format specifier to the data type. The programmer himself must align the number of the format specifiers to
> the
> > number of arguments.
> > The programmer himself must align the positions of the format specifiers
> to
> > the positions of arguments.
> >
> > Make a printf where the format specifier is adjacent to the variable.
> >
> > I have a function that works this way:
> >
> >     my_printf("a=%d", (int)a, " b=%d", (int)b, (char *)NULL);
> >
> > i.e. it takes a format strng containing *one* argument; the arguments(s) following are for that format specifier; multiple pairs of
format/argument
> > can be supplied.
> >
> > Perhaps in D, the end of the variable argument list to Dprintf can be
> known,
> > rather than having the programmer be diligent to add the NULL at the end every time.  Actually, if you add Real Macros, printf can be a macro
which
> > knows the number and data types of the arguments:
> >
> >     Dprintf("a=", a, " b=", b, "\n");
> >
> > --
> > Richard Krehbiel, Arlington, VA, USA
> > rich@kastle.com (work) or krehbiel3@home.com (personal)
>
>


1 2
Next ›   Last »