www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - need help

reply "Boris Wang" <nano.kago hotmail.com> writes:
int main( char[][] args )
{
 foreach( char[] arg; args[1 .. args.length] )
 {
     printf( "%.*s ", arg );
 }

 for ( int i = 0; i < args.length; i++ )
 {
     printf("%.*s ", args[i] );
 }

 return 0;
}

The first printf can't display the information, and the second do.

I use dmd 0.154, XP SP2.
Apr 24 2006
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Boris Wang" <nano.kago hotmail.com> wrote in message 
news:e2k46n$1dkm$1 digitaldaemon.com...
 The first printf can't display the information, and the second do.

Uhh, yes it does. For me, anyway. But I think the real question here is - why are you using printf instead of writef? ;) int main( char[][] args ) { foreach( char[] arg; args[1 .. args.length] ) { writef( arg, ' ' ); } writefln(); for ( int i = 1; i < args.length; i++ ) { writef( args[i], ' ' ); } return 0; } (These print identical lines for me.)
Apr 24 2006
parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jarrett Billingsley schrieb am 2006-04-25:
 "Boris Wang" <nano.kago hotmail.com> wrote in message 
 news:e2k46n$1dkm$1 digitaldaemon.com...
 The first printf can't display the information, and the second do.

Uhh, yes it does. For me, anyway. But I think the real question here is - why are you using printf instead of writef? ;)

<snip>
  for ( int i = 1; i < args.length; i++ )
  {
   writef( args[i], ' ' );
  }

That's usually not a good idea(unchecked format strings...), instead use: for ( int i = 1; i < args.length; i++ ) { writef("%s ", args[i]); } Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFETcyD3w+/yD4P9tIRAoLlAJsHZWWhbEADKVfC3blCpG0cY9HStwCeNWZZ IL9fNNCb5TazTmklf8blE3c= =nRGq -----END PGP SIGNATURE-----
Apr 24 2006
next sibling parent Hasan Aljudy <hasan.aljudy gmail.com> writes:
Thomas Kuehne wrote:
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
 Jarrett Billingsley schrieb am 2006-04-25:
 
"Boris Wang" <nano.kago hotmail.com> wrote in message 
news:e2k46n$1dkm$1 digitaldaemon.com...

The first printf can't display the information, and the second do.

Uhh, yes it does. For me, anyway. But I think the real question here is - why are you using printf instead of writef? ;)

<snip>
 for ( int i = 1; i < args.length; i++ )
 {
  writef( args[i], ' ' );
 }

That's usually not a good idea(unchecked format strings...), instead use: for ( int i = 1; i < args.length; i++ ) { writef("%s ", args[i]); } Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFETcyD3w+/yD4P9tIRAoLlAJsHZWWhbEADKVfC3blCpG0cY9HStwCeNWZZ IL9fNNCb5TazTmklf8blE3c= =nRGq -----END PGP SIGNATURE-----

or writef( arg ~ ' ' );
Apr 25 2006
prev sibling next sibling parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Thomas Kuehne wrote:
 That's usually not a good idea(unchecked format strings...)

Huh? In what kind of situation are the following two not equivalent? writef("%s", s); writef(s); Regardless of the type of s, these surely work the same way, right? Some test code to argue my point: -- import std.stdio; template func(TYPE) { void func(TYPE s) { writef("'", s, "'"); writef(" and "); writef("'%s'", s); writefln(); }} class Foo { char[] toString() { return "fooclass"; } } void main() { func("asdf"); func(1234); func(true); func('n'); func(0.1234); func(new Foo()); } -- In func's output, what's on the left side of the "and" is the same as on the right, in all six cases.
Apr 25 2006
next sibling parent xs0 <xs0 xs0.com> writes:
Deewiant wrote:
 Thomas Kuehne wrote:
 That's usually not a good idea(unchecked format strings...)

Huh? In what kind of situation are the following two not equivalent? writef("%s", s); writef(s); Regardless of the type of s, these surely work the same way, right? Some test code to argue my point: -- import std.stdio; template func(TYPE) { void func(TYPE s) { writef("'", s, "'"); writef(" and "); writef("'%s'", s); writefln(); }} class Foo { char[] toString() { return "fooclass"; } } void main() { func("asdf"); func(1234); func(true); func('n'); func(0.1234); func(new Foo()); } -- In func's output, what's on the left side of the "and" is the same as on the right, in all six cases.

func("%s%s%s"); :) xs0
Apr 25 2006
prev sibling parent reply =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Deewiant wrote:

That's usually not a good idea(unchecked format strings...)

Huh? In what kind of situation are the following two not equivalent?

When the string contains format characters (that would be '%')
 writef("%s", s);
 writef(s);
 
 Regardless of the type of s, these surely work the same way, right?

import std.stdio; void main() { char[] s = "100%"; writef(s); } ==> Throws an error: 100Error: std.format invalid specifier import std.stdio; void main() { char[] s = "100%"; writef("%s", s); } ==> This works OK. I suggested adding a function "write", that *didn't* parse for format characters (and the matching "writeln" function), but it was ignored... import std.stdio; void main() { char[] s = "100%"; write(s); } digitalmars.D/15627 --anders
Apr 25 2006
parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Anders F Bj鰎klund wrote:
 When the string contains format characters (that would be '%')
 

Ah, of course. Thanks for reminding me, to xs0 as well.
Apr 25 2006
parent =?ISO-8859-15?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Deewiant wrote:

When the string contains format characters (that would be '%')

Ah, of course. Thanks for reminding me, to xs0 as well.

Printf has the same problem. I bet you could trigger some real nice buffer overflows by abusing this "feature"... IMNSHO: Telling newcomers to use printf("Hello") or writef("World") will just make them shoot themselves in the foot later on. Whenever you introduce either, you need to talk about "formats". Which is why it's better if there's an alternative *without* ? Like in C: #include <stdio.h> int main(int argc, char* argv[]) { puts("Hello, World!"); return 0; } But that's just what I thought about the issue, nothing new. (And no, it's not a problem for strings without the percent) --anders
Apr 25 2006
prev sibling parent BCS <BCS_member pathlink.com> writes:
In article <6uu0i3-m2i.ln1 birke.kuehne.cn>, Thomas Kuehne says...
Jarrett Billingsley schrieb am 2006-04-25:
  for ( int i = 1; i < args.length; i++ )
  {
   writef( args[i], ' ' );
  }

That's usually not a good idea(unchecked format strings...), instead use: for ( int i = 1; i < args.length; i++ ) { writef("%s ", args[i]); } Thomas

This has bit me more than once. Maybe there should be a writef that won't do formatting (writefn("%s", 123); prints "%s123")
Apr 25 2006
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Apr 2006 11:13:58 +0800, Boris Wang <nano.kago hotmail.com>  
wrote:
 int main( char[][] args )
 {
  foreach( char[] arg; args[1 .. args.length] )
  {
      printf( "%.*s ", arg );
  }

  for ( int i = 0; i < args.length; i++ )
  {
      printf("%.*s ", args[i] );
  }

  return 0;
 }

 The first printf can't display the information, and the second do.

 I use dmd 0.154, XP SP2.

The first one skips the first arg, to include the first arg use: foreach( char[] arg; args[0 .. args.length] ) { printf( "%.*s ", arg ); } Apart from that they produce identical output for me. Regan
Apr 24 2006
parent reply "Boris Wang" <nano.kago hotmail.com> writes:
You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] ) and more, when i run the followed code: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length - 1 ] ) { printf( "%s ", cast(char*)arg ); } } it even produce a assert: Error: AssertError Failure hello_my.d(10) "Regan Heath" <regan netwin.co.nz> ??????:ops8jr1mr223k2f5 nrage.netwin.co.nz...
 On Tue, 25 Apr 2006 11:13:58 +0800, Boris Wang <nano.kago hotmail.com> 
 wrote:
 int main( char[][] args )
 {
  foreach( char[] arg; args[1 .. args.length] )
  {
      printf( "%.*s ", arg );
  }

  for ( int i = 0; i < args.length; i++ )
  {
      printf("%.*s ", args[i] );
  }

  return 0;
 }

 The first printf can't display the information, and the second do.

 I use dmd 0.154, XP SP2.

The first one skips the first arg, to include the first arg use: foreach( char[] arg; args[0 .. args.length] ) { printf( "%.*s ", arg ); } Apart from that they produce identical output for me. Regan

Apr 24 2006
next sibling parent reply "Boris Wang" <nano.kago hotmail.com> writes:
The suitable explain is :
  args[ leftLimit .. rightLimit ]

  the leftLimit is the first index, and the rightLimit is the
last index + 1, just equal with args.length.

but we used to write the following code:

  for ( int i = 0; i < len - 1; i ++ )

....


"Boris Wang" <nano.kago hotmail.com>
写入消息新闻:e2kdlg$1p04$1 digitaldaemon.com...
 You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] ) and more, when i run the followed code: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length - 1 ] ) { printf( "%s ", cast(char*)arg ); } } it even produce a assert: Error: AssertError Failure hello_my.d(10) "Regan Heath" <regan netwin.co.nz> ??????:ops8jr1mr223k2f5 nrage.netwin.co.nz...
 On Tue, 25 Apr 2006 11:13:58 +0800, Boris Wang <nano.kago hotmail.com> 
 wrote:
 int main( char[][] args )
 {
  foreach( char[] arg; args[1 .. args.length] )
  {
      printf( "%.*s ", arg );
  }

  for ( int i = 0; i < args.length; i++ )
  {
      printf("%.*s ", args[i] );
  }

  return 0;
 }

 The first printf can't display the information, and the second do.

 I use dmd 0.154, XP SP2.

The first one skips the first arg, to include the first arg use: foreach( char[] arg; args[0 .. args.length] ) { printf( "%.*s ", arg ); } Apart from that they produce identical output for me. Regan


Apr 24 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Apr 2006 14:10:26 +0800, Boris Wang <nano.kago hotmail.com>  
wrote:
 The suitable explain is :
   args[ leftLimit .. rightLimit ]

   the leftLimit is the first index, and the rightLimit is the
 last index + 1, just equal with args.length.

Or rather, that rightLimit is one past the last item you want to include. To include the entire array you use 0 and array.length.
 but we used to write the following code:

   for ( int i = 0; i < len - 1; i ++ )

To access items in the slice args[0..args.length] you would use this for loop: for(int i = 0; i < args.length; i++) {} or one of these foreach statements: foreach(int i, char[] arg; args) {} foreach(char[] arg; args) {} foreach(arg; args) {} Regan
 "Boris Wang" <nano.kago hotmail.com> 脨 
 麓脠毛脧没脧垄脨脗脦脜:e2kdlg$1p04$1 digitaldaemon.com...
 You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] ) and more, when i run the followed code: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length - 1 ] ) { printf( "%s ", cast(char*)arg ); } } it even produce a assert: Error: AssertError Failure hello_my.d(10) "Regan Heath" <regan netwin.co.nz> ??????:ops8jr1mr223k2f5 nrage.netwin.co.nz...
 On Tue, 25 Apr 2006 11:13:58 +0800, Boris Wang <nano.kago hotmail.com>
 wrote:
 int main( char[][] args )
 {
  foreach( char[] arg; args[1 .. args.length] )
  {
      printf( "%.*s ", arg );
  }

  for ( int i = 0; i < args.length; i++ )
  {
      printf("%.*s ", args[i] );
  }

  return 0;
 }

 The first printf can't display the information, and the second do.

 I use dmd 0.154, XP SP2.

The first one skips the first arg, to include the first arg use: foreach( char[] arg; args[0 .. args.length] ) { printf( "%.*s ", arg ); } Apart from that they produce identical output for me. Regan



Apr 25 2006
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Apr 2006 13:55:21 +0800, Boris Wang <nano.kago hotmail.com>  
wrote:
 You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] )

That is not true. In D, arrays are indexed from 0 and when slicing the start index is inclusive and the end index is not. Meaning, for example that: args[0..2] is a slice of items 0, and 1, but _not_ 2. If you use args.length-1 you will _not_ include the last item of the array in the slice. If you want the whole array then the end index must be the array length (AKA the index of the item past the end of the array)
 and more, when i run the followed code:

 import std.stdio;

 int main( char[][] args )
 {
  foreach( char[] arg; args[0 .. args.length - 1 ] )
  {
   printf( "%s ", cast(char*)arg );
  }
 }

 it even produce a assert:

 Error: AssertError Failure hello_my.d(10)

The assert has nothing to do with the array slice and everything to do with the missing return value in main. Try: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length] ) { printf( "%s ", cast(char*)arg ); } return 0; } However, you should be aware that using cast(char*) on a char[] and passing the result to printf is dangerous. It's only working in this case because the arguments are already null terminated, try this: import std.file; import std.string; int main( char[][] args ) { foreach( int i,char[] arg; splitlines(cast(char[])read("bug11.txt")) ) { printf( "%d. %s\n", i,cast(char*)arg ); } return 0; } (you'll need to create a bug11.txt containing a few lines of text) you should notice that the first printf shows the entire file, this is because the splitlines array contains non-null terminated char[] arrays. To safely pass them to functions expecting char* you should use toStringz, eg. import std.file; import std.string; int main( char[][] args ) { foreach( int i,char[] arg; splitlines(cast(char[])read("bug11.txt")) ) { printf( "%d. %s\n", i,toStringz(arg) ); } return 0; } Regan
Apr 25 2006
next sibling parent "Boris Wang" <nano.kago hotmail.com> writes:
Best regards to you!

Thanks

"Regan Heath" <regan netwin.co.nz> 
??????:ops8jx4rqc23k2f5 nrage.netwin.co.nz...
 On Tue, 25 Apr 2006 13:55:21 +0800, Boris Wang <nano.kago hotmail.com> 
 wrote:
 You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] )

That is not true. In D, arrays are indexed from 0 and when slicing the start index is inclusive and the end index is not. Meaning, for example that: args[0..2] is a slice of items 0, and 1, but _not_ 2. If you use args.length-1 you will _not_ include the last item of the array in the slice. If you want the whole array then the end index must be the array length (AKA the index of the item past the end of the array)
 and more, when i run the followed code:

 import std.stdio;

 int main( char[][] args )
 {
  foreach( char[] arg; args[0 .. args.length - 1 ] )
  {
   printf( "%s ", cast(char*)arg );
  }
 }

 it even produce a assert:

 Error: AssertError Failure hello_my.d(10)

The assert has nothing to do with the array slice and everything to do with the missing return value in main. Try: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length] ) { printf( "%s ", cast(char*)arg ); } return 0; } However, you should be aware that using cast(char*) on a char[] and passing the result to printf is dangerous. It's only working in this case because the arguments are already null terminated, try this: import std.file; import std.string; int main( char[][] args ) { foreach( int i,char[] arg; splitlines(cast(char[])read("bug11.txt")) ) { printf( "%d. %s\n", i,cast(char*)arg ); } return 0; } (you'll need to create a bug11.txt containing a few lines of text) you should notice that the first printf shows the entire file, this is because the splitlines array contains non-null terminated char[] arrays. To safely pass them to functions expecting char* you should use toStringz, eg. import std.file; import std.string; int main( char[][] args ) { foreach( int i,char[] arg; splitlines(cast(char[])read("bug11.txt")) ) { printf( "%d. %s\n", i,toStringz(arg) ); } return 0; } Regan

Apr 25 2006
prev sibling parent reply "Boris Wang" <nano.kago hotmail.com> writes:
"Regan Heath" <regan netwin.co.nz> 
??????:ops8jx4rqc23k2f5 nrage.netwin.co.nz...
 On Tue, 25 Apr 2006 13:55:21 +0800, Boris Wang <nano.kago hotmail.com> 
 wrote:
 You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] )

That is not true. In D, arrays are indexed from 0 and when slicing the start index is inclusive and the end index is not. Meaning, for example that: args[0..2] is a slice of items 0, and 1, but _not_ 2. If you use args.length-1 you will _not_ include the last item of the array in the slice. If you want the whole array then the end index must be the array length (AKA the index of the item past the end of the array)
 and more, when i run the followed code:

 import std.stdio;

 int main( char[][] args )
 {
  foreach( char[] arg; args[0 .. args.length - 1 ] )
  {
   printf( "%s ", cast(char*)arg );
  }
 }

 it even produce a assert:

 Error: AssertError Failure hello_my.d(10)

The assert has nothing to do with the array slice and everything to do with the missing return value in main. Try: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length] ) { printf( "%s ", cast(char*)arg ); } return 0; }

Why not a complie error, but a runtime error?
 However, you should be aware that using cast(char*) on a char[] and 
 passing the result to printf is dangerous. It's only working in this case 
 because the arguments are already null terminated, try this:

 import std.file;
 import std.string;

 int main( char[][] args )
 {
  foreach( int i,char[] arg; splitlines(cast(char[])read("bug11.txt")) )
  {
      printf( "%d. %s\n", i,cast(char*)arg );
  }
  return 0;
 }

 (you'll need to create a bug11.txt containing a few lines of text)

 you should notice that the first printf shows the entire file, this is 
 because the splitlines array contains non-null terminated char[] arrays. 
 To safely pass them to functions expecting char* you should use toStringz, 
 eg.

 import std.file;
 import std.string;

 int main( char[][] args )
 {
  foreach( int i,char[] arg; splitlines(cast(char[])read("bug11.txt")) )
  {
      printf( "%d. %s\n", i,toStringz(arg) );
  }
  return 0;
 }

 Regan 

Apr 25 2006
parent "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 25 Apr 2006 15:51:03 +0800, Boris Wang <nano.kago hotmail.com>  
wrote:
 "Regan Heath" <regan netwin.co.nz>
 ??????:ops8jx4rqc23k2f5 nrage.netwin.co.nz...
 On Tue, 25 Apr 2006 13:55:21 +0800, Boris Wang <nano.kago hotmail.com>
 wrote:
 You are right, the args array begin from index 0, but

   foreach( char[] arg; args[0 .. args.length] )

This should not be right, it should be : foreach( char[] arg; args[0 .. args.length - 1] )

That is not true. In D, arrays are indexed from 0 and when slicing the start index is inclusive and the end index is not. Meaning, for example that: args[0..2] is a slice of items 0, and 1, but _not_ 2. If you use args.length-1 you will _not_ include the last item of the array in the slice. If you want the whole array then the end index must be the array length (AKA the index of the item past the end of the array)
 and more, when i run the followed code:

 import std.stdio;

 int main( char[][] args )
 {
  foreach( char[] arg; args[0 .. args.length - 1 ] )
  {
   printf( "%s ", cast(char*)arg );
  }
 }

 it even produce a assert:

 Error: AssertError Failure hello_my.d(10)

The assert has nothing to do with the array slice and everything to do with the missing return value in main. Try: import std.stdio; int main( char[][] args ) { foreach( char[] arg; args[0 .. args.length] ) { printf( "%s ", cast(char*)arg ); } return 0; }

Why not a complie error, but a runtime error?

I believe the rationale is that it is not possible for the compiler to detect all possible situations with 100% certainty. I suspect Walter came to that conclusion adding this sort of compile time detection to his C/C++ compiler. Regan
Apr 25 2006