www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - to printf or to writef? That is the question...

reply jicman <jicman_member pathlink.com> writes:
Greetings!

I am getting a little annoyed with printf.  But, I am more concerned with d,
than with printf.  Let us admired this complicated piece of code:

import std.stdio;
import std.string;
int main(char[][] args)
{
char[] tt = "Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version:
1.0Set-Cookie:";
char[][] temp = std.string.split(tt,"MIME");
writefln(temp[0]);
printf(temp[0]);
return (0);
}

results in this output:

15:29:20.09>test0
Web Server 2.1.2.56 created 8/14/01 6:33 PM
Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version: 1.0Set-Cookie:

which is very weird to me.  Why?  Well, because temp[0] should have the splited
part that result that writefln prints out.  Why is printf still looking at tt?
Or even a better question: why is temp[0] referring to tt when printf is calling
temp[0]?  These are questions that need answers. :-)

so, printf is going to be my last result from now on.  All of my print-outs will
be done with writef.

Please help me understand this.

thanks,

josé
Feb 28 2005
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"jicman" <jicman_member pathlink.com> wrote in message 
news:cvvv03$im1$1 digitaldaemon.com...
 Greetings!

 I am getting a little annoyed with printf.  But, I am more concerned with 
 d,
 than with printf.  Let us admired this complicated piece of code:

 import std.stdio;
 import std.string;
 int main(char[][] args)
 {
 char[] tt = "Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version:
 1.0Set-Cookie:";
 char[][] temp = std.string.split(tt,"MIME");
 writefln(temp[0]);
 printf(temp[0]);
 return (0);
 }

 results in this output:

 15:29:20.09>test0
 Web Server 2.1.2.56 created 8/14/01 6:33 PM
 Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version: 1.0Set-Cookie:

 which is very weird to me.  Why?  Well, because temp[0] should have the 
 splited
 part that result that writefln prints out.  Why is printf still looking at 
 tt?
 Or even a better question: why is temp[0] referring to tt when printf is 
 calling
 temp[0]?  These are questions that need answers. :-)

split returns slices of the original string and printf prints until it hits 0. If you are going to use printf try printf("%.*s",temp[0]); see http://www.digitalmars.com/d/faq.html#printf
 so, printf is going to be my last result from now on.  All of my 
 print-outs will
 be done with writef.

good idea.
 Please help me understand this.

 thanks,

 josé

 

Feb 28 2005
parent reply jicman <jicman_member pathlink.com> writes:
Thanks Ben.  Me and my lack of reading... :-)


Ben Hinkle says...
"jicman" <jicman_member pathlink.com> wrote in message 
news:cvvv03$im1$1 digitaldaemon.com...
 Greetings!

 I am getting a little annoyed with printf.  But, I am more concerned with 
 d,
 than with printf.  Let us admired this complicated piece of code:

 import std.stdio;
 import std.string;
 int main(char[][] args)
 {
 char[] tt = "Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version:
 1.0Set-Cookie:";
 char[][] temp = std.string.split(tt,"MIME");
 writefln(temp[0]);
 printf(temp[0]);
 return (0);
 }

 results in this output:

 15:29:20.09>test0
 Web Server 2.1.2.56 created 8/14/01 6:33 PM
 Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version: 1.0Set-Cookie:

 which is very weird to me.  Why?  Well, because temp[0] should have the 
 splited
 part that result that writefln prints out.  Why is printf still looking at 
 tt?
 Or even a better question: why is temp[0] referring to tt when printf is 
 calling
 temp[0]?  These are questions that need answers. :-)

split returns slices of the original string and printf prints until it hits 0. If you are going to use printf try printf("%.*s",temp[0]); see http://www.digitalmars.com/d/faq.html#printf
 so, printf is going to be my last result from now on.  All of my 
 print-outs will
 be done with writef.

good idea.
 Please help me understand this.

 thanks,

 josé

 


Feb 28 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"jicman" <jicman_member pathlink.com> wrote in message 
news:d0026v$mcl$1 digitaldaemon.com...
 Thanks Ben.  Me and my lack of reading... :-)

Don't worry about it. Every single person new to D does it. You'll find that the use of slices is one of the unique things that makes D truly (potentially) great. AFAIUI, Kris' Mango is able to do huge amounts of performance-sensitive stuff without allocating any memory as a consequence of it!
Feb 28 2005
prev sibling parent reply Derek <derek psych.ward> writes:
On Mon, 28 Feb 2005 20:29:55 +0000 (UTC), jicman wrote:

 Greetings!
 
 I am getting a little annoyed with printf.  But, I am more concerned with d,
 than with printf.  Let us admired this complicated piece of code:
 
 import std.stdio;
 import std.string;
 int main(char[][] args)
 {
 char[] tt = "Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version:
 1.0Set-Cookie:";
 char[][] temp = std.string.split(tt,"MIME");
 writefln(temp[0]);
 printf(temp[0]);
 return (0);
 }
 
 results in this output:
 
 15:29:20.09>test0
 Web Server 2.1.2.56 created 8/14/01 6:33 PM
 Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version: 1.0Set-Cookie:
 
 which is very weird to me.  Why?  Well, because temp[0] should have the splited
 part that result that writefln prints out.  Why is printf still looking at tt?
 Or even a better question: why is temp[0] referring to tt when printf is
calling
 temp[0]?  These are questions that need answers. :-)
 
 so, printf is going to be my last result from now on.  All of my print-outs
will
 be done with writef.
 
 Please help me understand this.

I'll give it a go ;-) My advice firstly though is to stop using printf, just use writef. Second advice, if you are writing out the contents of strings, always use a %s. This will help avoid embedded '%' in your input string. writefln("%s", temp[0]); Ok, printf assumes that strings are ASCII and zero-terminated. writef however uses D strings, and they look like a type of struct ... struct DString { uint length; char* data } So if you supply a D string to printf, it stops outputting when it finally reaches a zero 'char'. Now the split() routine returns a sliced string, that is it returns a D string that is actually pointing to the original string in tt but with a different length. split() is not returning a *copy* of tt, but a new reference to tt. However, this is not a problem for writef() because that uses the length information, but printf() does not use the length info. For example, let's say that tt look like this { 72; #07DE4E90 }. That is, it has a length of 72 and an address pointer to #07DE4E90. When you do the split() call, then temp[][] is now an array of two D strings... [ { 43; #07DE4E90 }, { 25; #07DE4EBF } ] No extra RAM has been used up by copying string data, instead you now have two new references into the original string. We don't have to concern ourselves with the true D string format as D does all this for us. -- Derek Melbourne, Australia
Feb 28 2005
next sibling parent jicman <jicman_member pathlink.com> writes:
Lovely! (The explanation, that is. :-))

thanks.

Derek says...
On Mon, 28 Feb 2005 20:29:55 +0000 (UTC), jicman wrote:

 Greetings!
 
 I am getting a little annoyed with printf.  But, I am more concerned with d,
 than with printf.  Let us admired this complicated piece of code:
 
 import std.stdio;
 import std.string;
 int main(char[][] args)
 {
 char[] tt = "Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version:
 1.0Set-Cookie:";
 char[][] temp = std.string.split(tt,"MIME");
 writefln(temp[0]);
 printf(temp[0]);
 return (0);
 }
 
 results in this output:
 
 15:29:20.09>test0
 Web Server 2.1.2.56 created 8/14/01 6:33 PM
 Web Server 2.1.2.56 created 8/14/01 6:33 PMMIME-version: 1.0Set-Cookie:
 
 which is very weird to me.  Why?  Well, because temp[0] should have the splited
 part that result that writefln prints out.  Why is printf still looking at tt?
 Or even a better question: why is temp[0] referring to tt when printf is
calling
 temp[0]?  These are questions that need answers. :-)
 
 so, printf is going to be my last result from now on.  All of my print-outs
will
 be done with writef.
 
 Please help me understand this.

I'll give it a go ;-) My advice firstly though is to stop using printf, just use writef. Second advice, if you are writing out the contents of strings, always use a %s. This will help avoid embedded '%' in your input string. writefln("%s", temp[0]); Ok, printf assumes that strings are ASCII and zero-terminated. writef however uses D strings, and they look like a type of struct ... struct DString { uint length; char* data } So if you supply a D string to printf, it stops outputting when it finally reaches a zero 'char'. Now the split() routine returns a sliced string, that is it returns a D string that is actually pointing to the original string in tt but with a different length. split() is not returning a *copy* of tt, but a new reference to tt. However, this is not a problem for writef() because that uses the length information, but printf() does not use the length info. For example, let's say that tt look like this { 72; #07DE4E90 }. That is, it has a length of 72 and an address pointer to #07DE4E90. When you do the split() call, then temp[][] is now an array of two D strings... [ { 43; #07DE4E90 }, { 25; #07DE4EBF } ] No extra RAM has been used up by copying string data, instead you now have two new references into the original string. We don't have to concern ourselves with the true D string format as D does all this for us. -- Derek Melbourne, Australia

Feb 28 2005
prev sibling next sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Derek wrote:

 Ok, printf assumes that strings are ASCII and zero-terminated. writef
 however uses D strings, and they look like a type of struct ...
 
 struct  DString { uint length; char* data }

Side note: Note that a D array is really: { size_t length; void* data; } That is, the "length" type of an array is *not* equal to uint! Not that the distinction is important on a 32-bit machine, but it will be once the language starts targetting 64-bits... Same goes for .sizeof and .alignof, and array indexes. Better get in the habit of writing size_t already ? See http://www.digitalmars.com/d/portability.html --anders
Feb 28 2005
parent Derek Parnell <derek psych.ward> writes:
On Mon, 28 Feb 2005 23:06:57 +0100, Anders F Björklund wrote:

 Derek wrote:
 
 Ok, printf assumes that strings are ASCII and zero-terminated. writef
 however uses D strings, and they look like a type of struct ...
 
 struct  DString { uint length; char* data }

Side note: Note that a D array is really: { size_t length; void* data; } That is, the "length" type of an array is *not* equal to uint! Not that the distinction is important on a 32-bit machine, but it will be once the language starts targetting 64-bits...

Anders is correct (of course). And the reason is found in object.d ... version (AMD64) { alias ulong size_t; alias long ptrdiff_t; } else { alias uint size_t; alias int ptrdiff_t; } On the other hand, if I have to start dealing with strings that have 18,446,744,073,709,551,616 characters in them, I'm sure I'm already in big trouble. ;-) -- Derek Melbourne, Australia 1/03/2005 9:59:15 AM
Feb 28 2005
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 1 Mar 2005 08:25:23 +1100, Derek <derek psych.ward> wrote:
 Second
 advice, if you are writing out the contents of strings, always use a %s.
 This will help avoid embedded '%' in your input string.

   writefln("%s", temp[0]);

IIRC all parameters of writefln are treated as format strings, meaning, if temp[0] above contains a %s, another parameter is expected. The only way around this is to process every string you print with the write functions, changing % to %%. On one hand this is bad(tm). You have to process all strings, there are many potential bugs/problems. On the other hand this is good(tm). You are able to use a format string anywhere eg. writefln("%5s",a,b,i,"%.6f",f); if probably more easily understood, and less prone to bugs (wrong format specifier) than: writefln("%5s %s %d %.6f",a,b,i,f); If the write functions could somehow tell a format string apart from a normal string. eg. char[] a = "%s and %s"; char[] b = "pass"; char[] c = "fail" writefln(f"%s and %s",b,c); writefln(format(a),b,c); this seems to be a pain to me, someone might forget to use format() on a var, of forget to prefix with f and wonder why it's not working. Perhaps the opposite is better. char[] a = "%s and %s"; char[] b = "pass"; char[] c = "fail" writefln("%s and %s",noformat(b),noformat(c)); writefln(a,noformat(b),noformat(c)); but then, it's more likely you have less format strings, so neither of these options seem very nice to me. Does anyone have any good ideas? Regan
Feb 28 2005
next sibling parent reply =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Regan Heath wrote:

 IIRC all parameters of writefln are treated as format strings, meaning, 
 if  temp[0] above contains a %s, another parameter is expected.

Not all parameters. *At every position*. But if one is "%s", the next is a string. So this is cool: writefln("%s", "%"); This is not: writefln("%s", "%", "%");
 The only way around this is to process every string you print with the  
 write functions, changing % to %%.

You don't need to change the strings, just the formats.
 On one hand this is bad(tm). You have to process all strings, there are  
 many potential bugs/problems.

Nope. "Only" the format ones (which is bad enough...)
 Does anyone have any good ideas?

I wrote a patch for a "writeln" function that was the same as writefln, but without the formats. (i.e. all strings are normal, no need to double up the percentages anywhere) writefln("Hello!"); writeln("100%"); It's working just great. You can still use variadic args: writeln(100, "%"); --anders
Feb 28 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 01 Mar 2005 00:21:16 +0100, Anders F Björklund wrote:

[snip]
 
 I wrote a patch for a "writeln" function that was the same
 as writefln, but without the formats. (i.e. all strings
 are normal, no need to double up the percentages anywhere)
 
 writefln("Hello!");
 writeln("100%");
 
 It's working just great. You can still use variadic args:
 
 writeln(100, "%");

Can you submit to Walter for inclusion into his Phobos, or maybe post it here for us? I suppose I could write one too, but if you've done the hard work already... ;-) -- Derek Melbourne, Australia 1/03/2005 10:26:57 AM
Feb 28 2005
parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Derek Parnell wrote:

 Can you submit to Walter for inclusion into his Phobos, or maybe post it
 here for us? I suppose I could write one too, but if you've done the hard
 work already... ;-)

I did. Haven't heard a thing. digitalmars.D/15627 As you might see, I took the short and simple road... :-) --anders
Feb 28 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 01 Mar 2005 12:10:54 +1300, Regan Heath wrote:

 On Tue, 1 Mar 2005 08:25:23 +1100, Derek <derek psych.ward> wrote:
 Second
 advice, if you are writing out the contents of strings, always use a %s.
 This will help avoid embedded '%' in your input string.

   writefln("%s", temp[0]);

IIRC all parameters of writefln are treated as format strings, meaning, if temp[0] above contains a %s, another parameter is expected.

I suspect you recall incorrectly ;-) Try this ... import std.stdio; void main() { writefln("%s", "%d", 1); } The output is ... %d1 and not %d11 if all strings were formatting strings. If writef is not processing a format string, and the next parameter *is* a format string, then is 'eats up' the following parameters according to the format string. So writef sees ("%s", "%d", 1) and assumes the first parameter is a potential format string, until if comes across the %s, when it now knows it is one. So it uses the %s to 'eat up' the next string "%d", until it comes to the end of the format string. The next parameter if looks at is then the next 'non-eaten' one, the integer 1!
 The only way around this is to process every string you print with the  
 write functions, changing % to %%.

So one does *not* have to convert all embedded % to %%.
 On one hand this is bad(tm). You have to process all strings, there are  
 many potential bugs/problems.

Which I've just shown is not an issue.
 On the other hand this is good(tm). You are able to use a format string  
 anywhere eg.
    writefln("%5s",a,b,i,"%.6f",f);
 
 if probably more easily understood, and less prone to bugs (wrong format  
 specifier) than:
    writefln("%5s %s %d %.6f",a,b,i,f);

That is a personal opinion. I actually prefer the version you do not prefer.
 If the write functions could somehow tell a format string apart from a  
 normal string.
 
 eg.
 
 char[] a = "%s and %s";
 char[] b = "pass";
 char[] c = "fail"
 
 writefln(f"%s and %s",b,c);
 writefln(format(a),b,c);
 
 this seems to be a pain to me, someone might forget to use format() on a  
 var, of forget to prefix with f and wonder why it's not working.

Good thing we don't need this after all ;-)
 Perhaps the opposite is better.
 
 char[] a = "%s and %s";
 char[] b = "pass";
 char[] c = "fail"
 
 writefln("%s and %s",noformat(b),noformat(c));
 writefln(a,noformat(b),noformat(c));
 
 but then, it's more likely you have less format strings, so neither of  
 these options seem very nice to me.
 
 Does anyone have any good ideas?

Yep, Leave it as it is. -- Derek Melbourne, Australia 1/03/2005 10:16:52 AM
Feb 28 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 1 Mar 2005 10:23:55 +1100, Derek Parnell <derek psych.ward> wrote:
 On Tue, 01 Mar 2005 12:10:54 +1300, Regan Heath wrote:

 On Tue, 1 Mar 2005 08:25:23 +1100, Derek <derek psych.ward> wrote:
 Second
 advice, if you are writing out the contents of strings, always use a  
 %s.
 This will help avoid embedded '%' in your input string.

   writefln("%s", temp[0]);

IIRC all parameters of writefln are treated as format strings, meaning, if temp[0] above contains a %s, another parameter is expected.

I suspect you recall incorrectly ;-) Try this ...

Sorry, I wasn't as clear as I should have been. If you use "%s" then the next argument is not treated as a format string, I know that. However, I still think there is a (perhaps small) problem eg. char[] a = "%s for a while"; writefln(a); sure, the above is engineered to show a problem, sure it's simple to see the problem in the above, but, this could occur in a more complex situation i.e. the string comes from 'elsewhere' You suggested always using "%s", that does work, it's the same thing we have to do with printf.. it's one of those "lessons" we learn, one that bites us on the a# % once, or more, until we learn it. I was hoping D could improve on it. Anders functions which do not use format strings at all are one way to solve the problem, but it means if you want to format some of your output you must make several function calls, perhaps this is the best we can do? I was hoping we could come up with something better.
 On the other hand this is good(tm). You are able to use a format string  
 anywhere eg.
    writefln("%5s",a,b,i,"%.6f",f);
  if probably more easily understood, and less prone to bugs (wrong  
 format specifier) than:
    writefln("%5s %s %d %.6f",a,b,i,f);

prefer.

Perhaps because you are used to it? This isn't really important anyway :) Regan
Feb 28 2005
parent reply =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Regan Heath wrote:

 Anders functions which do not use format strings at all are one way to  
 solve the problem, but it means if you want to format some of your 
 output  you must make several function calls, perhaps this is the best 
 we can do?

Mixing and matching different styles in one call sounds like a good way to get hopelessly confused about which rules apply... Having both in the language is good, but in one function ? Nah.
 I was hoping we could come up with something better.
 
 On the other hand this is good(tm). You are able to use a format 
 string  anywhere eg.
    writefln("%5s",a,b,i,"%.6f",f);
  if probably more easily understood, and less prone to bugs (wrong  
 format specifier) than:
    writefln("%5s %s %d %.6f",a,b,i,f);

That is a personal opinion. I actually prefer the version you do not prefer.

Perhaps because you are used to it? This isn't really important anyway :)

C has "printf", Java has "println" (but just got printf in JDK 1.5, before that you used methods and hairpulling to format Java output http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html) D could have *both*, and everyone is happy ? :-) Heck, you can even use the C++ bitshift operators if you prefer, since they're in Mango... http://svn.dsource.org/svn/projects/mango/trunk/doc/html/classStdio.html --anders
Feb 28 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 01 Mar 2005 01:32:00 +0100, Anders F Björklund <afb algonet.se>  
wrote:
 Regan Heath wrote:

 Anders functions which do not use format strings at all are one way to   
 solve the problem, but it means if you want to format some of your  
 output  you must make several function calls, perhaps this is the best  
 we can do?

Mixing and matching different styles in one call sounds like a good way to get hopelessly confused about which rules apply...

"styles"? I assume you mean, "printing with formatting" and "printing without formatting'? I don't think "printing without formatting" exists. Instead "printing in the default specified format" is what we do. I don't see how it's confusing to want to print 'a' in a specified format and 'b' in the default specified format in one function call. eg. printf("%d %f",a,b); prints a and b in the default format. printf("%05d %f",a,b); prints a in the specified format and b in the default format. You still have to know what the default format is.
 Having both in the language is good, but in one function ? Nah.

Perhaps. I'm not convinced yet. Regan
Feb 28 2005
parent reply =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= <afb algonet.se> writes:
Regan Heath wrote:

 Mixing and matching different styles in one call sounds like a
 good way to get hopelessly confused about which rules apply...

"styles"? I assume you mean, "printing with formatting" and "printing without formatting'?

Yes, as in printf(3) vs. java.lang.System.out.println
 I don't think "printing without formatting" exists. Instead "printing 
 in  the default specified format" is what we do.

Which was why I hacked "printing without formatting" in :-)
 I don't see how it's confusing to want to print 'a' in a specified 
 format  and 'b' in the default specified format in one function call. eg.
 
   printf("%d %f",a,b);
 
 prints a and b in the default format.
 
   printf("%05d %f",a,b);
 
 prints a in the specified format and b in the default format.
 
 You still have to know what the default format is.

Those are all good... (examples of using C-style printf) What I meant was confusing was when you mix and match, like in:
 writefln("%5s",a,b,i,"%.6f",f);

But that could just be me not being used to D's writef just yet... (not too strange really, since it hasn't been around all that long?) There's also *another* way (Java) of doing the same thing: System.out.println(a + " " + b); Which in D would become something like: std.stdio.writeln (std.string.toString(a) ~ " " ~ std.string.toString(b)); The formatting options totally sucks here, of course. (It's a "known bug" of Java, before JDK 1.5... :-) ) But it doesn't have any "problems" with percent strings ?
 Having both in the language is good, but in one function ? Nah.

Perhaps. I'm not convinced yet.

It's not like writef is going away, or anything... Full example:
 import std.stdio;
 import std.string;
 
 void main()
 {
   int a = 42;
   float b = 3.1415;
 
   writefln("%d %f",a,b);
   writeln(toString(a) ~ " " ~ toString(b));
 }

--anders
Mar 01 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 01 Mar 2005 11:52:33 +0100, Anders F Björklund <afb algonet.se>  
wrote:
 Regan Heath wrote:

 Mixing and matching different styles in one call sounds like a
 good way to get hopelessly confused about which rules apply...

I assume you mean, "printing with formatting" and "printing without formatting'?

Yes, as in printf(3) vs. java.lang.System.out.println
 I don't think "printing without formatting" exists. Instead "printing  
 in  the default specified format" is what we do.

Which was why I hacked "printing without formatting" in :-)

I think we're arguing semantics. I would say "printing with no formatting options". We probably mean the same thing.
 I don't see how it's confusing to want to print 'a' in a specified  
 format  and 'b' in the default specified format in one function call.  
 eg.
    printf("%d %f",a,b);
  prints a and b in the default format.
    printf("%05d %f",a,b);
  prints a in the specified format and b in the default format.
  You still have to know what the default format is.

Those are all good... (examples of using C-style printf) What I meant was confusing was when you mix and match, like in: > writefln("%5s",a,b,i,"%.6f",f); But that could just be me not being used to D's writef just yet... (not too strange really, since it hasn't been around all that long?)

I prefer the above as the arguments appear in the order they are printed.. no more counting args and format specifiers, ensuring they match up to the types passed, finding the one that appears 3rd, etc.
 There's also *another* way (Java) of doing the same thing:

 System.out.println(a + " " + b);

 Which in D would become something like:

 std.stdio.writeln
      (std.string.toString(a) ~ " " ~ std.string.toString(b));

 The formatting options totally sucks here, of course.
 (It's a "known bug" of Java, before JDK 1.5... :-) )

 But it doesn't have any "problems" with percent strings ?

True. But it's inefficient. It builds a new string in order to print it out.
 Having both in the language is good, but in one function ? Nah.


It's not like writef is going away, or anything...

True, and maybe having different functions is the best solution. We'll see.. Regan
Mar 01 2005
next sibling parent reply =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= <afb algonet.se> writes:
Regan Heath wrote:

 I don't think "printing without formatting" exists. Instead 
 "printing  in  the default specified format" is what we do.

Which was why I hacked "printing without formatting" in :-)

I think we're arguing semantics. I would say "printing with no formatting options". We probably mean the same thing.

I meant that stdio.writeln didn't use to exist ? But I added it. writef works like printf in C. writeln works like println in Java.
 There's also *another* way (Java) of doing the same thing:

 System.out.println(a + " " + b);

 Which in D would become something like:

 std.stdio.writeln
      (std.string.toString(a) ~ " " ~ std.string.toString(b));

 The formatting options totally sucks here, of course.
 (It's a "known bug" of Java, before JDK 1.5... :-) )

 But it doesn't have any "problems" with percent strings ?

True. But it's inefficient. It builds a new string in order to print it out.

Since Java is Designed-to-be-Slowâ„¢, it doesn't concern itself with such trivial matters (but + does have some optimizations to convert into StringBuffer.append and other such hacks*...) And in D, you can instead use the variadic args syntax: writeln(toString(a), " ", toString(b)); It still won't choke on any percentages or require "%s". Never said I copied it over from Java *exactly*, did I ? :-) --anders * PS. Here is what the Java disassembly looks like:
   Code:
    0:   bipush  42
    2:   istore_1
    3:   ldc     #9; //float 3.1415f
    5:   fstore_2
    6:   getstatic       #13; //Field java/lang/System.out:Ljava/io/PrintStream;
    9:   new     #16; //class StringBuffer
    12:  dup
    13:  invokespecial   #21; //Method java/lang/StringBuffer."<init>":()V
    16:  iload_1
    17:  invokevirtual   #25; //Method
java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
    20:  bipush  32
    22:  invokevirtual   #28; //Method
java/lang/StringBuffer.append:(C)Ljava/lang/StringBuffer;
    25:  fload_2
    26:  invokevirtual   #31; //Method
java/lang/StringBuffer.append:(F)Ljava/lang/StringBuffer;
    29:  invokevirtual   #35; //Method
java/lang/StringBuffer.toString:()Ljava/lang/String;
    32:  invokevirtual   #39; //Method
java/io/PrintStream.println:(Ljava/lang/String;)V
    35:  return

For the sample code, that we used earlier: public class p { public static void main(String[] args) { int a = 42; float b = 3.1415f; System.out.println(a + " " + b); } }
Mar 01 2005
next sibling parent =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= <afb algonet.se> writes:
Anders F Björklund wrote:

 I meant that stdio.writeln didn't use to exist ? But I added it.

 And in D, you can instead use the variadic args syntax:
     writeln(toString(a), " ", toString(b));
 It still won't choke on any percentages or require "%s".

 Never said I copied it over from Java *exactly*, did I ? :-)

Or that I implemented it correctly, for that manner... :-P In the patch it should be "continue" instead of "return", or it will just print the first string argument and stop.
 		if (ignorePercent)
 		{
 			foreach(dchar c; fmt)
 			    putc(c);
 		   	continue;
 		}

--anders
Mar 01 2005
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 01 Mar 2005 23:29:36 +0100, Anders F Björklund <afb algonet.se>  
wrote:
 Regan Heath wrote:

 I don't think "printing without formatting" exists. Instead  
 "printing  in  the default specified format" is what we do.

Which was why I hacked "printing without formatting" in :-)

formatting options". We probably mean the same thing.

I meant that stdio.writeln didn't use to exist ? But I added it.

I know! Forget it, it's not an important point that I was trying to make.
 writef works like printf in C.

No, it doesn't, not exactly, as I said before. printf only accepts the first string as a format string. writef treats every string parameter (unless it's a parameter specified by %s in a previous format string) as a format string. the difference is likely to cause a few bugs, till people get used to it.
 There's also *another* way (Java) of doing the same thing:

 System.out.println(a + " " + b);

 Which in D would become something like:

 std.stdio.writeln
      (std.string.toString(a) ~ " " ~ std.string.toString(b));

 The formatting options totally sucks here, of course.
 (It's a "known bug" of Java, before JDK 1.5... :-) )

 But it doesn't have any "problems" with percent strings ?

it out.

Since Java is Designed-to-be-Slowâ„¢, it doesn't concern itself with such trivial matters (but + does have some optimizations to convert into StringBuffer.append and other such hacks*...)

Sure. Hacks added to cover up bad design IMO. But really, this is totally beside the point.
 And in D, you can instead use the variadic args syntax:
 	writeln(toString(a), " ", toString(b));
 It still won't choke on any percentages or require "%s".

 Never said I copied it over from Java *exactly*, did I ? :-)

Never suggested you did. Regan
Mar 01 2005
parent reply =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= <afb algonet.se> writes:
Regan Heath wrote:

 writef treats every string parameter (unless it's a parameter specified 
 by  %s in a previous format string) as a format string.

I know... (discovered it the hard way, with the "invalid specifier") What I meant was that it still needs a format string, like printf does. Even if every other string parameter can now be a format, if need be...
 the difference is likely to cause a few bugs, till people get used to it.

It's just that some people find the format a bit hard in the beginning. Not having to scan for format % is a teeny bit faster too, I suppose ? Don't get me wrong, writef is good. But it could be overkill for some ? --anders
Mar 01 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 02 Mar 2005 01:14:15 +0100, Anders F Björklund <afb algonet.se>  
wrote:
 Regan Heath wrote:

 writef treats every string parameter (unless it's a parameter specified  
 by  %s in a previous format string) as a format string.

I know... (discovered it the hard way, with the "invalid specifier") What I meant was that it still needs a format string, like printf does. Even if every other string parameter can now be a format, if need be...

The fact that every other string can be a format string, means that for every string you want to print you have to use a format string eg "%s" _or_ know for certain the string contains no % in it. This seems like a step back to me, so, while writef is a step forward in most areas, here it's a step backward, it's harder to use correctly. Sure, there are advantages, I mentioned them earlier.
 the difference is likely to cause a few bugs, till people get used to  
 it.

It's just that some people find the format a bit hard in the beginning.

True.
 Not having to scan for format % is a teeny bit faster too, I suppose ?

Yep.
 Don't get me wrong, writef is good. But it could be overkill for some ?

Sure, don't get me wrong. I 'like' the new write function. My complaint is with writef. The new behaviour (as compared to printf) has both good and bad effects IMO. Can we remove the bad ones? leaving only good ones? Regan
Mar 01 2005
parent reply =?UTF-8?B?QW5kZXJzIEYgQmrDtnJrbHVuZA==?= <afb algonet.se> writes:
Regan Heath wrote:

 The fact that every other string can be a format string, means that for  
 every string you want to print you have to use a format string eg "%s"  
 _or_ know for certain the string contains no % in it.

I haven't read the article* that Walter wrote in DDJ about it (writef), but that does seem to be by design - if you read the description at: http://www.digitalmars.com/d/std_format.html
 My complaint is with writef. The new behaviour (as compared to printf) 
 has  both good and bad effects IMO. Can we remove the bad ones? leaving 
 only  good ones?

I think writef is OK, just wonder whatever happened to "readf" ? Waiting for a new DDJ issue, perhaps ? ;-) Or perhaps out varargs... Otherwise pointers is the only way to do a scanf(3) workalike in D. --anders * http://www.ddj.com/documents/ddj0501e/ ($$$)
 "printf Revisited"
 Walter Bright
 The D programming language addresses some shortcomings
 of C and C++’s venerable printf.

Mar 01 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Wed, 02 Mar 2005 01:52:38 +0100, Anders F Björklund <afb algonet.se>  
wrote:
 Regan Heath wrote:

 The fact that every other string can be a format string, means that  
 for  every string you want to print you have to use a format string eg  
 "%s"  _or_ know for certain the string contains no % in it.

I haven't read the article* that Walter wrote in DDJ about it (writef), but that does seem to be by design - if you read the description at: http://www.digitalmars.com/d/std_format.html

I agree it's working how it's supposed to work. I just don't like how it works. Regan
Mar 01 2005
prev sibling parent reply "Carlos Santander B." <csantander619 gmail.com> writes:
Regan Heath wrote:
 On Tue, 01 Mar 2005 11:52:33 +0100, Anders F Björklund <afb algonet.se>  
 wrote:
 
 There's also *another* way (Java) of doing the same thing:

 System.out.println(a + " " + b);

 Which in D would become something like:

 std.stdio.writeln
      (std.string.toString(a) ~ " " ~ std.string.toString(b));

 The formatting options totally sucks here, of course.
 (It's a "known bug" of Java, before JDK 1.5... :-) )

 But it doesn't have any "problems" with percent strings ?

True. But it's inefficient. It builds a new string in order to print it out.

There's no need to: if Anders' writeln works as I expect, it could become: std.stdio.writeln(a," ",b). Internally, it will create a new string, but so does writefln. _______________________ Carlos Santander Bernal
Mar 01 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 01 Mar 2005 17:16:26 -0500, Carlos Santander B.  
<csantander619 gmail.com> wrote:
 Regan Heath wrote:
 On Tue, 01 Mar 2005 11:52:33 +0100, Anders F Björklund  
 <afb algonet.se>  wrote:

 There's also *another* way (Java) of doing the same thing:

 System.out.println(a + " " + b);

 Which in D would become something like:

 std.stdio.writeln
      (std.string.toString(a) ~ " " ~ std.string.toString(b));

 The formatting options totally sucks here, of course.
 (It's a "known bug" of Java, before JDK 1.5... :-) )

 But it doesn't have any "problems" with percent strings ?

it out.

There's no need to: if Anders' writeln works as I expect, it could become: std.stdio.writeln(a," ",b). Internally, it will create a new string, but so does writefln.

You're right, and it does. This wasn't the point I was trying to make, we were side tracked. :) Regan
Mar 01 2005
prev sibling parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Derek wrote:

so, printf is going to be my last result from now on.
All of my print-outs will be done with writef.

Please help me understand this.

I'll give it a go ;-) My advice firstly though is to stop using printf, just use writef.

Well, just as long as one keeps them apart (C and D), all is OK...
 import std.c.stdio;
 
 int main()
 {
   char* s = "World";
   printf("Hello, %s!\n", s);
   return 0;
 }

vs.
 import std.stdio;
 
 void main()
 {
   char[] s = "World";
   writefln("Hello, %s!", s);
 }

Sometimes it is very useful to be able to write "C programs" in D. If nothing else, it makes porting much easier: http://www.algonet.se/~afb/d/gdtest.d --anders
Feb 28 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 01 Mar 2005 01:05:55 +0100, Anders F Björklund wrote:

 Derek wrote:
 
so, printf is going to be my last result from now on.
All of my print-outs will be done with writef.

Please help me understand this.

I'll give it a go ;-) My advice firstly though is to stop using printf, just use writef.

Well, just as long as one keeps them apart (C and D), all is OK...

As is my intention, :D
 import std.c.stdio;
 
 int main()
 {
   char* s = "World";
   printf("Hello, %s!\n", s);
   return 0;
 }

vs.
 import std.stdio;
 
 void main()
 {
   char[] s = "World";
   writefln("Hello, %s!", s);
 }


Seems to be a good reason to throw C away ;-)
 
 If nothing else, it makes porting much easier:
 http://www.algonet.se/~afb/d/gdtest.d
 

No doubt you are right, but I'm not intending to port any C/C++ code. I'm writing in D and I want to think in D. I'm happy to translate C to D, but not to copy it slavishly. -- Derek Melbourne, Australia 1/03/2005 11:10:36 AM
Feb 28 2005
parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Derek Parnell wrote:

Sometimes it is very useful to be able to write "C programs" in D.

Seems to be a good reason to throw C away ;-)

:-) (but perhaps a good enough reason to drop printf from object ?) One can write "C programs" in C++ too. (and way too many still do)
If nothing else, it makes porting much easier:
http://www.algonet.se/~afb/d/gdtest.d

No doubt you are right, but I'm not intending to port any C/C++ code. I'm writing in D and I want to think in D. I'm happy to translate C to D, but not to copy it slavishly.

Me neither, I just wanted a "quick start" to see whether my ports of big header files was working OK before I started adding D stuff. You probably still have to *interface* to C code/libraries, though ? --anders
Feb 28 2005