www.digitalmars.com         C & C++   DMDScript  

D - printf

reply "Richard Krehbiel" <rich kastle.com> writes:
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)
Aug 16 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
I know printf is the function that everyone loves to hate <g>, but I confess
I think printf is one of the great features of C and I'm just not willing to
give up the wonderful convenience and power of it. Believe me, I've thought
about it. I know it's not typesafe, but printf is soooo useful that it's
worth giving up ideological purity for it! -Walter

"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

 number of arguments.
 The programmer himself must align the positions of the format specifiers

 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

 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)

Aug 16 2001
next sibling parent reply Matt Busigin <mbusigin helios.spang.org.uk> writes:
Walter wrote:
 I know printf is the function that everyone loves to hate <g>, but I confess
 I think printf is one of the great features of C and I'm just not willing to
 give up the wonderful convenience and power of it. Believe me, I've thought
 about it. I know it's not typesafe, but printf is soooo useful that it's
 worth giving up ideological purity for it! -Walter

(Apologies for the crap quoting, I haven't used newsgroups in 5 or 6 years, and I am using Mozilla instead of something sane like tin) I do agree that format strings with varargs. Perhaps we can come up with a typesafe solution... Maybe include format strings inside the actual string implementation?
Aug 16 2001
parent "Walter" <walter digitalmars.com> writes:
"Matt Busigin" <mbusigin helios.spang.org.uk> wrote in message
news:3B7C5043.2050905 helios.spang.org.uk...
 Walter wrote:
 I know printf is the function that everyone loves to hate <g>, but I


 I think printf is one of the great features of C and I'm just not


 give up the wonderful convenience and power of it. Believe me, I've


 about it. I know it's not typesafe, but printf is soooo useful that it's
 worth giving up ideological purity for it! -Walter

(Apologies for the crap quoting, I haven't used newsgroups in 5 or 6 years, and I am using Mozilla instead of something sane like tin) I do agree that format strings with varargs. Perhaps we can come up with a typesafe solution... Maybe include format strings inside the actual string implementation?

Every time I try this, it just winds up looking ugly. (Also, lots of what I use printf's for are debugging. It is so convenient to just bang out a printf and not worry about types, after all, it's usually just temporary anyway.)
Aug 16 2001
prev sibling next sibling parent reply "erk" <ebf users.sourceforge.net> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9lh357$2n8u$1 digitaldaemon.com...
 I know printf is the function that everyone loves to hate <g>, but I

 I think printf is one of the great features of C and I'm just not willing

 give up the wonderful convenience and power of it. Believe me, I've

 about it. I know it's not typesafe, but printf is soooo useful that it's
 worth giving up ideological purity for it! -Walter

What is wrong with creating a typesafe facillity (similar to C++'s iostreams) that would be used as following: int i = 35; print << "i = " << i; rather than the much more complicated and entirely unsafe: int i = 35; printf("i = %d", i); I also find the former much clearer and easier to read. I know it is possible to introduce typesafe streams such as this (as C++ is a working example). If the relative complexity of C++ streams is a source of objection by some, it might even be worthwhile considering ways of simplifying the C++ model -- as D is starting from a (relatively) clean slate, afterall. - Eric Friedman
Aug 16 2001
next sibling parent reply Christophe de Dinechin <descubes earthlink.net> writes:
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.

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.


Christophe


erk wrote:

 "Walter" <walter digitalmars.com> wrote in message
 news:9lh357$2n8u$1 digitaldaemon.com...
 I know printf is the function that everyone loves to hate <g>, but I

 I think printf is one of the great features of C and I'm just not willing

 give up the wonderful convenience and power of it. Believe me, I've

 about it. I know it's not typesafe, but printf is soooo useful that it's
 worth giving up ideological purity for it! -Walter

What is wrong with creating a typesafe facillity (similar to C++'s iostreams) that would be used as following: int i = 35; print << "i = " << i; rather than the much more complicated and entirely unsafe: int i = 35; printf("i = %d", i); I also find the former much clearer and easier to read. I know it is possible to introduce typesafe streams such as this (as C++ is a working example). If the relative complexity of C++ streams is a source of objection by some, it might even be worthwhile considering ways of simplifying the C++ model -- as D is starting from a (relatively) clean slate, afterall. - Eric Friedman

Aug 16 2001
parent reply a <hursh infonet.isl.net> writes:
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
Aug 19 2001
next sibling parent Christophe de Dinechin <descubes earthlink.net> writes:
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
Aug 20 2001
prev sibling parent reply Cesar Rabak <csrabak uol.com.br> writes:
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'?
Sep 10 2001
parent a <a b.c> writes:
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
Sep 10 2001
prev sibling parent "kaffiene" <kaffiene xtra.co.nz> writes:
The C++ iostream libraries are appalling.  It's fine if you want cout << i;
but something requiring format changes, padding changes, floating point
accuracy specification, etc... turns a one line printf statement into a
half-page cout nightmare with a method call against the stream for each
individual format change.

Peter.


"erk" <ebf users.sourceforge.net> wrote in message
news:9li454$kbu$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9lh357$2n8u$1 digitaldaemon.com...
 I know printf is the function that everyone loves to hate <g>, but I

 I think printf is one of the great features of C and I'm just not


 to
 give up the wonderful convenience and power of it. Believe me, I've

 about it. I know it's not typesafe, but printf is soooo useful that it's
 worth giving up ideological purity for it! -Walter

What is wrong with creating a typesafe facillity (similar to C++'s iostreams) that would be used as following: int i = 35; print << "i = " << i; rather than the much more complicated and entirely unsafe: int i = 35; printf("i = %d", i); I also find the former much clearer and easier to read. I know it is possible to introduce typesafe streams such as this (as C++

 a working example).  If the relative complexity of C++ streams is a source
 of objection by some, it might even be worthwhile considering ways of
 simplifying the C++ model -- as D is starting from a (relatively) clean
 slate, afterall.

  - Eric Friedman

Aug 17 2001
prev sibling next sibling parent reply Grobbins <grobbins badaddress.znet.com> writes:
  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. A localizable string formatting function ends up looking like printlocalized("%1 %2", param1, param2) so the parameters can be reordered in the format string or even omitted from the format by the translation team without the code needing to be recompiled. Unfortunately, few C programmers realize this, so they assume that using printf for generating strings is reasonable. Greg Robbins
Aug 16 2001
parent reply "Gary V. Vaughan" <gary oranda.demon.co.uk> writes:
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__/
Aug 18 2001
parent reply Grobbins <grobbins badaddress.znet.com> writes:
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
Aug 18 2001
parent "Gary V. Vaughan" <gary gnu.org> writes:
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__/
Aug 18 2001
prev sibling parent Charles Hixson <charleshixsn earthlink.net> writes:
Walter wrote:
 I know printf is the function that everyone loves to hate <g>, but I confess
 I think printf is one of the great features of C and I'm just not willing to
 give up the wonderful convenience and power of it. Believe me, I've thought
 about it. I know it's not typesafe, but printf is soooo useful that it's
 worth giving up ideological purity for it! -Walter
 ...
 

Printf has a lot going for it. The only thing I've been able to imagine that could be better would be a buffer processing version. This would includ the current version as one special form, but would also have buffer fill (i.e., "clear the current buffer, and put this string in for processing") So, in addition to: Print.f (fmtString, itms...) one would have the specialized forms: Print.c (fmtString); :: create a print buffer with contents fmtString. Print.p (pos, itm); :: process the format string, replacing the pos-th item with itm according to the specified format. and, of course, Print.doIt; :: print out the current format string, as processed.
Aug 17 2001
prev sibling next sibling parent Axel Kittenberger <axel dtone.org> writes:
Pascals write() function was the best output mechanism I've ever seen, 
however it's difficult to implement.

For Pascal it was a hack in the compiler itself, the user could not 
even declare himself a function that behaved like write() or writeln()
Aug 17 2001
prev sibling parent reply "Tim Sweeney" <tim epicgames.com> writes:
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

 number of arguments.
 The programmer himself must align the positions of the format specifiers

 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

 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)

Aug 17 2001
parent "Sean L. Palmer" <spalmer iname.com> writes:
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

 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

 type isn't (redundently or incorrectly) specified in the format string."

 2. It's easily localizable to other human languages because arguments can

 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

 number of arguments.
 The programmer himself must align the positions of the format specifiers

 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


 can be supplied.

 Perhaps in D, the end of the variable argument list to Dprintf can be

 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


 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)


Nov 03 2001