digitalmars.D - Using writef to print strings that contain format specifiers
- Kramer (17/17) Jan 29 2005 While printing file names on my system using writef, I came across this ...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (5/11) Jan 29 2005 The first argument to writef is *not* a string, but a format specifier.
- Kramer (5/16) Jan 29 2005 D'oh!
- Nick (7/11) Jan 31 2005 This seems to be a common source of mistakes, and maybe something should...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (10/19) Jan 31 2005 Yes, seems like a good idea. In C, there is "puts" which does writeln.
- Walter (3/5) Jan 31 2005 std.c.stdio.fputs should do the trick.
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (3/11) Jan 31 2005 printf worked too, I was just wondering if I could do it with writef.
- Walter (3/13) Jan 31 2005 Not with writef, because the routines writef relies on assume UTF.
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (11/31) Feb 01 2005 Okay, so if I want to, for instance, convert strings then I need
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (5/29) Jan 31 2005 It doesn't work for wchar[] or dchar[], though ?
- Nick (12/19) Jan 31 2005 I was thinking more in the line of functions which can print anything, n...
- Sebastian Beschke (6/19) Jan 31 2005 This would mean adding another way to accomplish exactly the same as
- Nick (16/20) Jan 31 2005 Sure it is. You say
- Rev (9/20) Jan 31 2005 Your suggestion is good, but I think this an actual bug! Atleast in the ...
- Regan Heath (11/46) Jan 31 2005 I see what you're saying.. however:
- Rev (8/55) Feb 01 2005 IMHO, WYSIWYG strings should ignore both "escape sequences" and "format
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (16/28) Feb 01 2005 It would be more logical to have an output function that ignores format
- Regan Heath (16/45) Feb 01 2005 I agree, a WYSIWYG version of writef.
- Regan Heath (14/82) Feb 01 2005 I disagree (more below)
- pragma (3/12) Jan 29 2005 - EricAnderton at yahoo
While printing file names on my system using writef, I came across this file name: 311abc%20-%20tmb[1] (percent signs included) and received this error: 311abcError: std.format. I'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing? This will reproduce the error: -Kramer
Jan 29 2005
Kramer wrote:I'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing?The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --anders
Jan 29 2005
D'oh! Thanks! -Kramer In article <cth8jr$ni2$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...Kramer wrote:I'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing?The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --anders
Jan 29 2005
In article <cth8jr$ni2$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --andersThis seems to be a common source of mistakes, and maybe something should be done about it. We could for example have two additional functions called write()/writeln(), which do not accept format strings, but otherwise works as writef() and writefln()? Nick
Jan 31 2005
Nick wrote:Yes, seems like a good idea. In C, there is "puts" which does writeln. Such a "stupid" function should also be faster than the full writef ? I believe OutputStream has a bunch of overloaded "write()" functions, but there are no such alternatives in std.stdio as far as I can tell. I'm also wondering how you output an ubyte[] full of 8-bit characters ? Using "%s" just gives the "invalid UTF-8 sequence" error with writef... Input and output to non-Unicode/UTF is something of a pain, in general. But I suppose I can do it on the stdin/stdout streams instead of stdio. --andersThe first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C).This seems to be a common source of mistakes, and maybe something should be done about it. We could for example have two additional functions called write()/writeln(), which do not accept format strings, but otherwise works as writef() and writefln()?
Jan 31 2005
"Anders F Björklund" <afb algonet.se> wrote in message news:ctldek$ldr$1 digitaldaemon.com...I'm also wondering how you output an ubyte[] full of 8-bit characters ? Using "%s" just gives the "invalid UTF-8 sequence" error with writef...std.c.stdio.fputs should do the trick.
Jan 31 2005
Walter wrote:"Anders F Björklund" <afb algonet.se> wrote in message news:ctldek$ldr$1 digitaldaemon.com...printf worked too, I was just wondering if I could do it with writef. --andersI'm also wondering how you output an ubyte[] full of 8-bit characters ? Using "%s" just gives the "invalid UTF-8 sequence" error with writef...std.c.stdio.fputs should do the trick.
Jan 31 2005
"Anders F Björklund" <afb algonet.se> wrote in message news:ctm4u8$1ka2$1 digitaldaemon.com...Walter wrote:Not with writef, because the routines writef relies on assume UTF."Anders F Björklund" <afb algonet.se> wrote in message news:ctldek$ldr$1 digitaldaemon.com...printf worked too, I was just wondering if I could do it with writef.I'm also wondering how you output an ubyte[] full of 8-bit characters ? Using "%s" just gives the "invalid UTF-8 sequence" error with writef...std.c.stdio.fputs should do the trick.
Jan 31 2005
Walter wrote:Okay, so if I want to, for instance, convert strings then I need to go byte level with D - or call upon the C standard library... Since D only supports Unicode, and not any legacy encodings. Got it. Here is the code I used, after conversion:Not with writef, because the routines writef relies on assume UTF.printf worked too, I was just wondering if I could do it with writef.I'm also wondering how you output an ubyte[] full of 8-bit characters ? Using "%s" just gives the "invalid UTF-8 sequence" error with writef...std.c.stdio.fputs should do the trick.ubyte[] test = (args.length > 1) ? cast(ubyte[]) args[1] : TEST; char[] str = decode_string(test, mapping); writefln("UTF-8: %s", str); ubyte[] enc = encode_string(str, mapping); std.stream.stdout.writeString("8-bit: "); foreach(ubyte b; enc) std.stream.stdout.write(b); std.stream.stdout.writeLine("");The second *could* be replaced with printf, but I wanted to do it within the D library... It works OK, for translating to and from a ISO-8859-1 console. (for Latin-1, the "mapping" lookup is very simple one-to-one) --anders PS. Here were my translator functions:/// converts a 8-bit charset encoding string into unicode char[] decode_string(ubyte[] string, wchar[256] mapping); /// converts a unicode string into 8-bit charset encoding ubyte[] encode_string(char[] string, wchar[256] mapping);
Feb 01 2005
Nick wrote:This seems to be a common source of mistakes, and maybe something should be done about it. We could for example have two additional functions called write()/writeln(), which do not accept format strings, but otherwise works as writef() and writefln()?Here's one trivial implementation of those:import std.stdio; import std.stream; void write(char[] str) { std.stream.stdout.writeString(str); } void writeln(char[] str) { std.stream.stdout.writeLine(str); } void main() { writef("*** Hall\u00e5, "); writefln("V\u00e4rlden! ***"); write("%%% Hall\u00e5, "); writeln("V\u00e4rlden! %%%"); }It doesn't work for wchar[] or dchar[], though ? (You can't overload them, because of the literals) --anders
Jan 31 2005
In article <ctlfea$nh7$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...Nick wrote:I was thinking more in the line of functions which can print anything, not just strings. So writing eg. would do exactly the same as except it would be safe if str contains any '%'-characters. NickThis seems to be a common source of mistakes, and maybe something should be done about it. We could for example have two additional functions called write()/writeln(), which do not accept format strings, but otherwise works as writef() and writefln()?Here's one trivial implementation of those: [snip]
Jan 31 2005
Nick schrieb:I was thinking more in the line of functions which can print anything, not just strings. So writing eg. would do exactly the same as except it would be safe if str contains any '%'-characters.This would mean adding another way to accomplish exactly the same as writef does, which in general is a bad idea. It isn't easier to explain to a noob the difference between write/writef than between writef(str) and writef("%s", str). -Sebastian
Jan 31 2005
In article <ctlqte$17hd$1 digitaldaemon.com>, Sebastian Beschke says...This would mean adding another way to accomplish exactly the same as writef does, which in general is a bad idea.Why is that a bad idea? (I'm not contesting that it is, just asking.)It isn't easier to explain to a noob the difference between write/writef than between writef(str) and writef("%s", str).Sure it is. You say "Use write/writeln for output, eg. writeln(a,b,c). If you need specially formatted output, use the writef/writefln, eg. writefln("%-20s %5d", s, i);" But saying that you can't write eg. int i; cdouble d; MyNumberClass m; .. writefln(i, d, m); because m.toString might in theory return a '%' seems pretty counter-intuitive too me. Nick
Jan 31 2005
In article <cth8jr$ni2$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...Kramer wrote:Your suggestion is good, but I think this an actual bug! Atleast in the case of "WYSIWYG" strings. If r" " or its equivalent, ` `, identifies a WYSIWYG string, then it shouldn't matter what the content of that string is. I should be able to place any number of format specifiers or escape sequence in that sring and print out excactly what I fed it. Atleast that's what I'd expect from a so-called "WYSIWYG" string. RevI'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing?The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --anders
Jan 31 2005
On Mon, 31 Jan 2005 21:51:31 +0000 (UTC), Rev <Rev_member pathlink.com> wrote:In article <cth8jr$ni2$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...I see what you're saying.. however: I think the issue is with what a WYSIWIG string means/does. Currently it means that "escape sequences" will be treated literally. You took that to mean '%' was not evaluated/interpreted by writef, however, technically '%' is not an "escape sequence" but a "format specifier". r"a%b" and "a%b" are identical as neither contains an escape sequence. r"a\b" and "a\b" are not identical as the \ is literal in the former and escaped in the latter. ReganKramer wrote:Your suggestion is good, but I think this an actual bug! Atleast in the case of "WYSIWYG" strings. If r" " or its equivalent, ` `, identifies a WYSIWYG string, then it shouldn't matter what the content of that string is. I should be able to place any number of format specifiers or escape sequence in that sring and print out excactly what I fed it. Atleast that's what I'd expect from a so-called "WYSIWYG" string.I'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing?The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --anders
Jan 31 2005
In article <opslhmtbtt23k2f5 ally>, Regan Heath says...On Mon, 31 Jan 2005 21:51:31 +0000 (UTC), Rev <Rev_member pathlink.com> wrote:IMHO, WYSIWYG strings should ignore both "escape sequences" and "format specifiers". WYSIWYG does not mean "What You See Is What You Get: except for format specifiers." If I wanted to use format specifiers then I would not (and definitely should not) be using a WYSIWYG string. This is not only a rational way to think about WYSIWYG but also intuitive and consistent with both definition and user expectation. RevIn article <cth8jr$ni2$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...I see what you're saying.. however: I think the issue is with what a WYSIWIG string means/does. Currently it means that "escape sequences" will be treated literally. You took that to mean '%' was not evaluated/interpreted by writef, however, technically '%' is not an "escape sequence" but a "format specifier". r"a%b" and "a%b" are identical as neither contains an escape sequence. r"a\b" and "a\b" are not identical as the \ is literal in the former and escaped in the latter. ReganKramer wrote:Your suggestion is good, but I think this an actual bug! Atleast in the case of "WYSIWYG" strings. If r" " or its equivalent, ` `, identifies a WYSIWYG string, then it shouldn't matter what the content of that string is. I should be able to place any number of format specifiers or escape sequence in that sring and print out excactly what I fed it. Atleast that's what I'd expect from a so-called "WYSIWYG" string.I'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing?The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --anders
Feb 01 2005
Rev wrote:IMHO, WYSIWYG strings should ignore both "escape sequences" and "format specifiers". WYSIWYG does not mean "What You See Is What You Get: except for format specifiers." If I wanted to use format specifiers then I would not (and definitely should not) be using a WYSIWYG string. This is not only a rational way to think about WYSIWYG but also intuitive and consistent with both definition and user expectation.It would be more logical to have an output function that ignores format specifiers, than to try an bolt that attribute onto a char[]/wchar[]... The current "writef" is useful, but it's a little surprising that you need to double up every "%%" that you *didn't* intend as a formatter ? And I was wrong about the "first parameter", format specifiers can occur any time in a writef parameter list. So writef(100,"%") doesn't work. :( Just adding a matching std.stdio.write and std.stdio.writeln would be nice. Tried to do one myself, but the variadic args are a huge pain... Probably needs an extra argument to std.format.doFormat, or something ? ("pay attention to format characters", with a default of "please do") Just so that you can deactivate the '%' parsing, without rewriting all of the ugly little bits and warts of the big doFormat switch. So you can do something simple, like:import std.stdio; void main() { writeln("%%% Hello, World! %%%"); }Without having it choke on the percentages. --anders
Feb 01 2005
On Tue, 01 Feb 2005 13:36:10 +0100, Anders F Björklund <afb algonet.se> wrote:Rev wrote:I agree, a WYSIWYG version of writef.IMHO, WYSIWYG strings should ignore both "escape sequences" and "format specifiers". WYSIWYG does not mean "What You See Is What You Get: except for format specifiers." If I wanted to use format specifiers then I would not (and definitely should not) be using a WYSIWYG string. This is not only a rational way to think about WYSIWYG but also intuitive and consistent with both definition and user expectation.It would be more logical to have an output function that ignores format specifiers, than to try an bolt that attribute onto a char[]/wchar[]...The current "writef" is useful, but it's a little surprising that you need to double up every "%%" that you *didn't* intend as a formatter ?Not in my opinion, as that is part of the contract of the function.And I was wrong about the "first parameter", format specifiers can occur any time in a writef parameter list. So writef(100,"%") doesn't work. :(I know, I found this out a little while back and it surprised me that more people haven't complained. AFAIKS it means that it's impossible, without verifying all strings you pass in some way, to guarantee there isn't a miscreant %s present. Possible solutions: 1- make the first parameter the only format string, easy, but not nice. 2- have some way to identify a format string. ideally static hard coded strings would be format strings and string variables passed wouldn't, but could be identified as such explicitly. 3- verify every string passed somehow.Just adding a matching std.stdio.write and std.stdio.writeln would be nice. Tried to do one myself, but the variadic args are a huge pain... Probably needs an extra argument to std.format.doFormat, or something ? ("pay attention to format characters", with a default of "please do") Just so that you can deactivate the '%' parsing, without rewriting all of the ugly little bits and warts of the big doFormat switch. So you can do something simple, like:I'm sure someone here has the time and ability to produce one for us. :) Reganimport std.stdio; void main() { writeln("%%% Hello, World! %%%"); }Without having it choke on the percentages.
Feb 01 2005
On Tue, 1 Feb 2005 12:19:26 +0000 (UTC), Rev <Rev_member pathlink.com> wrote:In article <opslhmtbtt23k2f5 ally>, Regan Heath says...I disagree (more below)On Mon, 31 Jan 2005 21:51:31 +0000 (UTC), Rev <Rev_member pathlink.com> wrote:IMHO, WYSIWYG strings should ignore both "escape sequences" and "format specifiers".In article <cth8jr$ni2$1 digitaldaemon.com>, =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...I see what you're saying.. however: I think the issue is with what a WYSIWIG string means/does. Currently it means that "escape sequences" will be treated literally. You took that to mean '%' was not evaluated/interpreted by writef, however, technically '%' is not an "escape sequence" but a "format specifier". r"a%b" and "a%b" are identical as neither contains an escape sequence. r"a\b" and "a\b" are not identical as the \ is literal in the former and escaped in the latter. ReganKramer wrote:Your suggestion is good, but I think this an actual bug! Atleast in the case of "WYSIWYG" strings. If r" " or its equivalent, ` `, identifies a WYSIWYG string, then it shouldn't matter what the content of that string is. I should be able to place any number of format specifiers or escape sequence in that sring and print out excactly what I fed it. Atleast that's what I'd expect from a so-called "WYSIWYG" string.I'm guessing writef got tripped up because the % sign is used as part of a format string for writef. I tried taking the file name and putting single, double and the wysiwyg identifier "r" in front of it and tried to print it with writef, but I still get the error. Is there any way around this? I wouldn't have been able to anticipate thie file name on my system, so, maybe writef is not a good candidate for what I'm doing?The first argument to writef is *not* a string, but a format specifier. Thus, you need to use this instead: writefln("%s","311abc%20-%20tmb[1]") Works the same way as with printf (in C). --andersWYSIWYG does not mean "What You See Is What You Get: except for format specifiers."Correct, it doesn't. Not here or anywhere else that I know of. You're mixing two concepts here, the contents of the string, and what the function does with those contents. WYSIWYG strings, mean exactly that, the strings contents are exactly what you see. However, writef is not a 'WYSIWYG function'. It's design and contract specify that it will treat a '%' as a "format specifier", and it does.If I wanted to use format specifiers then I would not (and definitely should not) be using a WYSIWYG string.Again I think you're confusing the contents of the string, which is WYSIWYG, and the contract of the function.This is not only a rational way to think about WYSIWYG but also intuitive and consistent with both definition and user expectation.*If* writef was a WYSIWYG function then I'd agree with you. Regan
Feb 01 2005
In article <cth792$mc8$1 digitaldaemon.com>, Kramer says...Is there any way around this?This will reproduce the error:Try this instead:writefln("%s","311abc%20-%20tmb[1]");- EricAnderton at yahoo
Jan 29 2005