www.digitalmars.com         C & C++   DMDScript  

D - replacements for printf and scanf?

reply Nikita Proskourine <Nikita_member pathlink.com> writes:
D currently uses printf for printing strings. This has a number of
disadvantages:
1. Number of arguments is not validated.
2. Types of arguments are not validated.
3. Non-primitive types can't be printed.

The solution could be something in the style of Java, with overridable
toString() in every object or in the style of C++ with << operators and streams.
Or it could be some intrinsic feature of D.

scanf has the same type of problems.

Something should be done about it. What do you think?

Nikita.
Jan 04 2004
next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
It's a topic that comes up often. Those of us who don't have problems with
printf - largely because we're recalcitrant old duffers who've had printf()
instincts honed by long and unhappy experience - are content with the
current situation. Those who do not are encouraged to propose an alternative
that is neither unacceptably verbose or unacceptably slow. There's little
doubt that D can support a good solution, so by all means have a go. :)

"Nikita Proskourine" <Nikita_member pathlink.com> wrote in message
news:btafe0$1sl$1 digitaldaemon.com...
 D currently uses printf for printing strings. This has a number of
 disadvantages:
 1. Number of arguments is not validated.
 2. Types of arguments are not validated.
 3. Non-primitive types can't be printed.

 The solution could be something in the style of Java, with overridable
 toString() in every object or in the style of C++ with << operators and

 Or it could be some intrinsic feature of D.

 scanf has the same type of problems.

 Something should be done about it. What do you think?

 Nikita.

Jan 04 2004
prev sibling next sibling parent reply Andy Friesen <andy ikagames.com> writes:
Nikita Proskourine wrote:
 D currently uses printf for printing strings. This has a number of
 disadvantages:
 1. Number of arguments is not validated.
 2. Types of arguments are not validated.
 3. Non-primitive types can't be printed.
 
 The solution could be something in the style of Java, with overridable
 toString() in every object or in the style of C++ with << operators and
streams.
 Or it could be some intrinsic feature of D.
 
 scanf has the same type of problems.
 
 Something should be done about it. What do you think?
 
 Nikita.

The trouble is implementing variable argument functions in a way that has no (or very little) runtime performance, and does not result in mounds of code. (either generated machine code, or source) Many, *many* solutions to this have been proposed. (I like XL's approach the best) -- andy
Jan 04 2004
parent reply kinghajj <kinghajj_member pathlink.com> writes:
printf() and scanf() are just fine IF u take the time to learn them! (though, I
do like std::cin for input...). printf() is better than std::cout (it's faster).
Jan 04 2004
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
kinghajj wrote:

 printf() and scanf() are just fine IF u take the time to learn them! (though, I
 do like std::cin for input...). printf() is better than std::cout (it's
faster).

printf is unsafe and has to do string parsing at runtime; cout is ugly. (subjective, I know) Just about every other modern language on the face of the earth offers something that's better than either. D should at least match them. -- andy
Jan 04 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Andy Friesen" <andy ikagames.com> wrote in message
news:btas77$m4k$1 digitaldaemon.com...
 kinghajj wrote:

 printf() and scanf() are just fine IF u take the time to learn them!


 do like std::cin for input...). printf() is better than std::cout (it's


 printf is unsafe and has to do string parsing at runtime; cout is ugly.
 (subjective, I know)

 Just about every other modern language on the face of the earth offers
 something that's better than either.  D should at least match them.

I'm not aware of any language that offers an efficient alternative to printf(). I look forward to seeing D be the first! :)
Jan 04 2004
prev sibling parent reply davepermen <davepermen_member pathlink.com> writes:
In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn them! (though, I
do like std::cin for input...). printf() is better than std::cout (it's faster).

Jan 05 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn them!


do like std::cin for input...). printf() is better than std::cout (it's




Not faster? I'd be very surprised if this was not true for the majority of test cases. Each output to cout has to go through significant locale management.
Jan 05 2004
parent reply davepermen <davepermen_member pathlink.com> writes:
cout is buffered, printf not.

but technically, the design of the streams in c++ need less runtime work than
printf.

they are as well typesave and extendable.

its true that cout itself is not that fast. but it has other reasons, _NOT_ the
"multiple function calls are slow" ones.. reasons that wouldn't mather in D

In article <btb7aj$1ihl$1 digitaldaemon.com>, Matthew says...
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn them!


do like std::cin for input...). printf() is better than std::cout (it's




Not faster? I'd be very surprised if this was not true for the majority of test cases. Each output to cout has to go through significant locale management.

Jan 05 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
 cout is buffered, printf not.

That's implementation-defined, and not a stipulated characteristic. In fact, printf is often implemented in terms of, or shares implementation with, fprintf (stderr).
 but technically, the design of the streams in c++ need less runtime work

 printf.

I don't find this credible. Have you implemented either/both, or equivalent functions?
 they are as well typesave and extendable.

No-one's contesting that. As with just about anything, the contest is between robustness and efficiency.
 its true that cout itself is not that fast. but it has other reasons,

 "multiple function calls are slow" ones.. reasons that wouldn't mather in

Disagree. There are several reasons for the high performance costs of the iostreams, only some of which pertain to the multiple calls.
 In article <btb7aj$1ihl$1 digitaldaemon.com>, Matthew says...
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn them!


do like std::cin for input...). printf() is better than std::cout




faster).


Not faster? I'd be very surprised if this was not true for the majority


test cases. Each output to cout has to go through significant locale
management.


Jan 05 2004
parent reply davepermen <davepermen_member pathlink.com> writes:
what ever you talk about. properly implemented concatenated calls can beat every
printf in terms of performance. possibly not in the design of the iostreams of
the c++ standard library, dunno (don't see any reason why), but definitely by
default.

the reason is simple: the multicall determines at COMPILE TIME how the string
has to look, how to convert what variable with wich function to what string
output (int2string, MyStoopidObj2string, char2string, float2string, etc), and
the only runtime workload are the actual needed conversions. they can even
inline rather well for some of them, etc.

printf ALWAYS parses runtime, determines and switches runtime what type to print
how, where. this can't be faster than compile time determining the same. it
simply can not. no way.

the mutliple function calls are actually done in printf as well (thought it is
often a switch statement, doesn't make it really bether..).

you don't gain anything with printf. show me what you gain.

In article <btbhri$23j9$1 digitaldaemon.com>, Matthew says...
 cout is buffered, printf not.

That's implementation-defined, and not a stipulated characteristic. In fact, printf is often implemented in terms of, or shares implementation with, fprintf (stderr).
 but technically, the design of the streams in c++ need less runtime work

 printf.

I don't find this credible. Have you implemented either/both, or equivalent functions?
 they are as well typesave and extendable.

No-one's contesting that. As with just about anything, the contest is between robustness and efficiency.
 its true that cout itself is not that fast. but it has other reasons,

 "multiple function calls are slow" ones.. reasons that wouldn't mather in

Disagree. There are several reasons for the high performance costs of the iostreams, only some of which pertain to the multiple calls.
 In article <btb7aj$1ihl$1 digitaldaemon.com>, Matthew says...
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn them!


do like std::cin for input...). printf() is better than std::cout




faster).


Not faster? I'd be very surprised if this was not true for the majority


test cases. Each output to cout has to go through significant locale
management.



Jan 05 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Asked and answered: "properly implemented concatenated calls"

You're absolutely right. It's just the case that iostreams is not, and I
believe cannot, beat printf in performance. I've implemented type safe and
very-high performance streaming libs in C++ (although the syntax was not
particularly welcoming).

I am hopeful that D will do what you assert is possible, and I agree should
be. It's just not easy, especially when one gets to working with objects,
whose strream-representation formats are often subject to runtime decisions.
The only way to do it is to prove it. :)

"davepermen" <davepermen_member pathlink.com> wrote in message
news:btbj4j$25cl$1 digitaldaemon.com...
 what ever you talk about. properly implemented concatenated calls can beat

 printf in terms of performance. possibly not in the design of the

 the c++ standard library, dunno (don't see any reason why), but definitely

 default.

 the reason is simple: the multicall determines at COMPILE TIME how the

 has to look, how to convert what variable with wich function to what

 output (int2string, MyStoopidObj2string, char2string, float2string, etc),

 the only runtime workload are the actual needed conversions. they can even
 inline rather well for some of them, etc.

 printf ALWAYS parses runtime, determines and switches runtime what type to

 how, where. this can't be faster than compile time determining the same.

 simply can not. no way.

 the mutliple function calls are actually done in printf as well (thought

 often a switch statement, doesn't make it really bether..).

 you don't gain anything with printf. show me what you gain.

 In article <btbhri$23j9$1 digitaldaemon.com>, Matthew says...
 cout is buffered, printf not.

That's implementation-defined, and not a stipulated characteristic. In


printf is often implemented in terms of, or shares implementation with,
fprintf (stderr).

 but technically, the design of the streams in c++ need less runtime



than
 printf.

I don't find this credible. Have you implemented either/both, or


functions?

 they are as well typesave and extendable.

No-one's contesting that. As with just about anything, the contest is between robustness and efficiency.
 its true that cout itself is not that fast. but it has other reasons,

 "multiple function calls are slow" ones.. reasons that wouldn't mather



D

Disagree. There are several reasons for the high performance costs of the
iostreams, only some of which pertain to the multiple calls.


 In article <btb7aj$1ihl$1 digitaldaemon.com>, Matthew says...
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn






(though, I
do like std::cin for input...). printf() is better than std::cout




faster).


Not faster? I'd be very surprised if this was not true for the




of
test cases. Each output to cout has to go through significant locale
management.




Jan 05 2004
parent reply davepermen <davepermen_member pathlink.com> writes:
if the way to determine is runtime, then it has to be. printf doesn't help as
well.

c++ streams _should_ be capable in being high performing. don't know why they
shouldn't (but i don't know much about them anyways..)

all we need is the ability to write operators as non-member-functions.

In article <btbkd6$27bd$1 digitaldaemon.com>, Matthew says...
Asked and answered: "properly implemented concatenated calls"

You're absolutely right. It's just the case that iostreams is not, and I
believe cannot, beat printf in performance. I've implemented type safe and
very-high performance streaming libs in C++ (although the syntax was not
particularly welcoming).

I am hopeful that D will do what you assert is possible, and I agree should
be. It's just not easy, especially when one gets to working with objects,
whose strream-representation formats are often subject to runtime decisions.
The only way to do it is to prove it. :)

"davepermen" <davepermen_member pathlink.com> wrote in message
news:btbj4j$25cl$1 digitaldaemon.com...
 what ever you talk about. properly implemented concatenated calls can beat

 printf in terms of performance. possibly not in the design of the

 the c++ standard library, dunno (don't see any reason why), but definitely

 default.

 the reason is simple: the multicall determines at COMPILE TIME how the

 has to look, how to convert what variable with wich function to what

 output (int2string, MyStoopidObj2string, char2string, float2string, etc),

 the only runtime workload are the actual needed conversions. they can even
 inline rather well for some of them, etc.

 printf ALWAYS parses runtime, determines and switches runtime what type to

 how, where. this can't be faster than compile time determining the same.

 simply can not. no way.

 the mutliple function calls are actually done in printf as well (thought

 often a switch statement, doesn't make it really bether..).

 you don't gain anything with printf. show me what you gain.

 In article <btbhri$23j9$1 digitaldaemon.com>, Matthew says...
 cout is buffered, printf not.

That's implementation-defined, and not a stipulated characteristic. In


printf is often implemented in terms of, or shares implementation with,
fprintf (stderr).

 but technically, the design of the streams in c++ need less runtime



than
 printf.

I don't find this credible. Have you implemented either/both, or


functions?

 they are as well typesave and extendable.

No-one's contesting that. As with just about anything, the contest is between robustness and efficiency.
 its true that cout itself is not that fast. but it has other reasons,

 "multiple function calls are slow" ones.. reasons that wouldn't mather



D

Disagree. There are several reasons for the high performance costs of the
iostreams, only some of which pertain to the multiple calls.


 In article <btb7aj$1ihl$1 digitaldaemon.com>, Matthew says...
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn






(though, I
do like std::cin for input...). printf() is better than std::cout




faster).


Not faster? I'd be very surprised if this was not true for the




of
test cases. Each output to cout has to go through significant locale
management.





Jan 05 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
 if the way to determine is runtime, then it has to be. printf doesn't help

 well.

 c++ streams _should_ be capable in being high performing. don't know why

 shouldn't (but i don't know much about them anyways..)

 all we need is the ability to write operators as non-member-functions.

That's something we need that is supported by a large number of issues, not just this one. It's an absolute must, and I can't seee Walter escaping us on this one. :)
 In article <btbkd6$27bd$1 digitaldaemon.com>, Matthew says...
Asked and answered: "properly implemented concatenated calls"

You're absolutely right. It's just the case that iostreams is not, and I
believe cannot, beat printf in performance. I've implemented type safe


very-high performance streaming libs in C++ (although the syntax was not
particularly welcoming).

I am hopeful that D will do what you assert is possible, and I agree


be. It's just not easy, especially when one gets to working with objects,
whose strream-representation formats are often subject to runtime


The only way to do it is to prove it. :)

"davepermen" <davepermen_member pathlink.com> wrote in message
news:btbj4j$25cl$1 digitaldaemon.com...
 what ever you talk about. properly implemented concatenated calls can



every
 printf in terms of performance. possibly not in the design of the

 the c++ standard library, dunno (don't see any reason why), but



by
 default.

 the reason is simple: the multicall determines at COMPILE TIME how the

 has to look, how to convert what variable with wich function to what

 output (int2string, MyStoopidObj2string, char2string, float2string,



and
 the only runtime workload are the actual needed conversions. they can



 inline rather well for some of them, etc.

 printf ALWAYS parses runtime, determines and switches runtime what type



print
 how, where. this can't be faster than compile time determining the



it
 simply can not. no way.

 the mutliple function calls are actually done in printf as well



it is
 often a switch statement, doesn't make it really bether..).

 you don't gain anything with printf. show me what you gain.

 In article <btbhri$23j9$1 digitaldaemon.com>, Matthew says...
 cout is buffered, printf not.

That's implementation-defined, and not a stipulated characteristic. In


printf is often implemented in terms of, or shares implementation




fprintf (stderr).

 but technically, the design of the streams in c++ need less runtime



than
 printf.

I don't find this credible. Have you implemented either/both, or


functions?

 they are as well typesave and extendable.

No-one's contesting that. As with just about anything, the contest is between robustness and efficiency.
 its true that cout itself is not that fast. but it has other





_NOT_ the
 "multiple function calls are slow" ones.. reasons that wouldn't





in
D

Disagree. There are several reasons for the high performance costs of




iostreams, only some of which pertain to the multiple calls.


 In article <btb7aj$1ihl$1 digitaldaemon.com>, Matthew says...
"davepermen" <davepermen_member pathlink.com> wrote in message
news:btb741$1hsd$1 digitaldaemon.com...
 In article <btaqtk$j8i$1 digitaldaemon.com>, kinghajj says...
printf() and scanf() are just fine IF u take the time to learn






(though, I
do like std::cin for input...). printf() is better than








(it's
faster).


Not faster? I'd be very surprised if this was not true for the




of
test cases. Each output to cout has to go through significant






management.






Jan 05 2004
prev sibling next sibling parent reply J Anderson <REMOVEanderson badmama.com.au> writes:
Nikita Proskourine wrote:

D currently uses printf for printing strings. This has a number of
disadvantages:
1. Number of arguments is not validated.
2. Types of arguments are not validated.
3. Non-primitive types can't be printed.

The solution could be something in the style of Java, with overridable
toString() in every object or in the style of C++ with << operators and streams.
Or it could be some intrinsic feature of D.

scanf has the same type of problems.

Something should be done about it. What do you think?

Nikita.


  

void print(int val) { //print val } void print(char[] val) { //print val } template printT(T) { void printT(T list) { //If list of arguments if (typeof(list) == typeof(...)) //Optimised away { foreach (val; list) { print(val); } } else { printf(list); //Single value } } } alias printT!(...).printT print; //... = a list of arguments. print("number = ", 50); //prints "number = 50" Users could add their own print's. Particular cases could be speciallised. The ... could be something else like typelist, the idea here is more important then the syntax. Actually the ... could be used in other syntax as well. void print(... list) { } It would differentiate from the c version because it's before, not after the variable. Anyway another term could be used. or parhaps a more wordy version: template print(T : ...) { void print(T list) { foreach (val; list) { print(val); } } } print!(char*, int)("number = ", 50); Anderson
Jan 05 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
J Anderson wrote:

 Nikita Proskourine wrote:

 D currently uses printf for printing strings. This has a number of
 disadvantages:
 1. Number of arguments is not validated.
 2. Types of arguments are not validated.
 3. Non-primitive types can't be printed.

 The solution could be something in the style of Java, with overridable
 toString() in every object or in the style of C++ with << operators 
 and streams.
 Or it could be some intrinsic feature of D.

 scanf has the same type of problems.

 Something should be done about it. What do you think?

 Nikita.


  

void print(int val) { //print val } void print(char[] val) { //print val } template printT(T) { void printT(T list) { //If list of arguments if (typeof(list) == typeof(...)) //Optimised away { foreach (val; list) { print(val); } } else { printf(list); //Single value } } } alias printT!(...).printT print; //... = a list of arguments. print("number = ", 50); //prints "number = 50" Users could add their own print's. Particular cases could be speciallised. The ... could be something else like typelist, the idea here is more important then the syntax. Actually the ... could be used in other syntax as well. void print(... list) { } It would differentiate from the c version because it's before, not after the variable. Anyway another term could be used. or parhaps a more wordy version: template print(T : ...) { void print(T list) { foreach (val; list) { print(val); } } } print!(char*, int)("number = ", 50); Anderson

void print(int val) { //print val } void print(char[] val) { //print val } the toString method could be used, but I requested that before for primitive types ;(
Jan 05 2004
prev sibling parent reply Georg Wrede <Georg_member pathlink.com> writes:
In this long thread I have not noticed anyone mentioning that
the format string in printf (and scanf) can be defined at 
runtime. I personally think this is the single most elegant
detail in printf. 

Still, I've never used it myself, and haven't actually seen
anyone else use it either. It can also be said that code 
that uses a varying format stirng in printf is bound to get
less readable and harder to debug than const format string
type printf. (I.e. the usual way of using it.)

This ability IMHO is the main reason why printf does runtime
parsing. If we were to decide on static format strings, then
the compiler could do the parsing for us. This would result
in the disappearance of several restrictions regarding a new
implementation of a printf equivalent.

Also, since printf is a C-function, it remains callable from
D, whatever happens. Knowing this, it might be a good idea to
design the "genuine D printing function" for the most prevalent
cases and usages. 

This would ultimately lead to a Pascal writeln like functionality.
But what's the harm with that? 

To gains some insight into why we already haven't implemented
something writeline alike, could someone explain if there are any
technical restrictions in D that make it hard to implement 
writeline as in Pascal? (Not that I'm advocating that we should,
but a good answer would go a long way to letting some of us 
understand the non-obvious issues involved.)
Jan 09 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Georg Wrede wrote:
 In this long thread I have not noticed anyone mentioning that
 the format string in printf (and scanf) can be defined at 
 runtime. I personally think this is the single most elegant
 detail in printf. 

Well, it can, but that's definately not what you would do in C due to memory management issues. In C++ or D, this is quite an option.
 Still, I've never used it myself, and haven't actually seen
 anyone else use it either. It can also be said that code 
 that uses a varying format stirng in printf is bound to get
 less readable and harder to debug than const format string
 type printf. (I.e. the usual way of using it.)

I know at least one use of it: software internationalisation, which btw leads to very silly sentenses in some languages, in which word order is not the same as in english! My native language is Russian, and i can remember some funny moments reading some messages in software translated this way! I think IBM OS/2 was the first major piece of software which broke up with it, and actually had a high-quality translation with correct word order. I think we need a better solution to that than printf, namely format with named placeholders! As to generic use, it doesn't make much sense to construct own printf format line, since we have language features which can abstract the working IO stream away - since that was probably the most important use back then. Also recall that you cannot construct a printf argument list this way.
 This ability IMHO is the main reason why printf does runtime
 parsing. If we were to decide on static format strings, then
 the compiler could do the parsing for us. This would result
 in the disappearance of several restrictions regarding a new
 implementation of a printf equivalent.

I bet it is not. It was a hack which allowed the compiler to be slim, and printf to accept variable number of arguments. Note that varags were not available as a language feature at the moment.
 Also, since printf is a C-function, it remains callable from
 D, whatever happens. Knowing this, it might be a good idea to
 design the "genuine D printing function" for the most prevalent
 cases and usages. 
 
 This would ultimately lead to a Pascal writeln like functionality.
 But what's the harm with that? 

The problem with Pascal writeln "function" was that it could not be defined in Pascal. It had to be a built in. In D it still has, because in-line array declarations don't work, and because there is no way to determine the length of variable arguments list, and because there is no good way one could specify automatic export conversion for a custom type. Making writeln built in, would mean that a user can't write his own writeln-like function - which the C/C++ community definately cannot accept. I believe one viable way now is opCall overload. Another thing would work, but Walter would not like it: overload opMod, opDiv or opSub, or maybe even the same opShl and opShr. Or rather opCat, which i would prefer. These operators are not commutative, and can thus be overloaded on the UDT through the _r equivalent!!! opMod can be overloaded to do named format replacement. -eye
Jan 10 2004