Jump to page: 1 2 3
Thread overview
to printf or to writef? That is the question...
Feb 28, 2005
jicman
Feb 28, 2005
Ben Hinkle
Feb 28, 2005
jicman
Feb 28, 2005
Matthew
Feb 28, 2005
Derek
Feb 28, 2005
jicman
Feb 28, 2005
Derek Parnell
Feb 28, 2005
Regan Heath
Feb 28, 2005
Derek Parnell
Feb 28, 2005
Derek Parnell
Mar 01, 2005
Regan Heath
Mar 01, 2005
Regan Heath
Mar 01, 2005
Regan Heath
Mar 01, 2005
Regan Heath
Mar 02, 2005
Regan Heath
Mar 02, 2005
Regan Heath
Mar 01, 2005
Regan Heath
Mar 01, 2005
Derek Parnell
February 28, 2005
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é


February 28, 2005
"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é
>
> 


February 28, 2005
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é
>>
>> 
>
>


February 28, 2005
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
February 28, 2005
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


February 28, 2005
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
February 28, 2005
"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!



February 28, 2005
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
February 28, 2005
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
February 28, 2005
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
« First   ‹ Prev
1 2 3