The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

OK, this was amazing. I didn't know this.

After several years programming, I just found something very profound.

Look at this:

//package sathyaish.practice.utilities;

/*
I want to see how many expressions I can append to a single for-loop statement in Java.

        for ( int i = 0; i < args.length; i++, sb.append( args[i] ), sb.append(delimiter));

Spot the error in this.
*/
public class lfl /* long for loop */
{
    public static void main(String[] args)
    {
        if ( args.length == 0 )
            System.out.println("Usage lfl arg1 [arg2 [arg3...]]");

        java.lang.StringBuffer sb = new StringBuffer();
        for ( int i = 0; i < args.length; i++, sb.append( args[i] ), sb.append(" ") );
        System.out.println(sb.toString());
    }
}


Spot the reason for the ArrayIndexOutOfBoundsException.
Sathyaish Chakravarthy Send private email
Thursday, April 05, 2007
 
 
i++ is evaluated before args[i].

http://codeguru.earthweb.com/java/tij/tij0045.shtml
"In both the initialization and step portions of the control expression you can have a number of statements separated by commas, and those statements will be evaluated sequentially."

And I don't even know Java.
Mark Ransom Send private email
Thursday, April 05, 2007
 
 
You're right, Mark. Excellent!

I would never have run accross this if I hadn't tried it out in a practice session. That is because normally, I wouldn't have concatenated expressions in one single for-loop in real life code.

That was impressive.

:-)
Sathyaish Chakravarthy Send private email
Thursday, April 05, 2007
 
 
The third argument in a for loop is used to increment the counter. It is possible to execute additional code, but it's considered poor programming practice. This, for example, is valid...

for( i=0; i<MAX_VALUE; isNull( arg[i] ) ? i-- : i++ ) {

Which basically says if the current value of arg[i] exists, go on to the next arg element, otherwise go back one.

There is a potential problem - if arg[0] is null to start, you'll hit the same array index error. You're better off checking to see if arg[i] is null and doing something about it in the body of the for loop, like this...

for ( i=0; i<MAX_VALUE; i++ ) {
  do {
    arg[i] = getValueNeeded();
  } while isNull( arg[i] );
}
TheDavid
Thursday, April 05, 2007
 
 
Whoops, I think I reversed the order of the conditional in my first example. I think it should be "i++ : i--", I think true comes first in Java.
TheDavid
Thursday, April 05, 2007
 
 
Yes, the ?: operator goes like ( condition ? true : false ) in Java.

Of course, the real question is, "WHY are you doing this to that poor innocent programming language?"
mjfgates Send private email
Thursday, April 05, 2007
 
 
The real question here is why, for heaven's sake, are you incrementing and referencing the index variable separately in the increment phase of the for loop:

  for( int i = 0; i < args.length; i++,
      sb.append(args[i]), sb.append(" ") );

and why don't you have anything in the body of that loop (loops without bodies are, generally, considered poor programming pracitce). I would have written the loop thus:

  sb.append(args[0]);
  for(i = 1; i < args.length; i++)
  {
      sb.append(" ");
      sb.append(args[i]);
  }

which would eliminate both your array access bug AND the extraneous space at the end of the concatenated arguments. I'm not too familiar with Java, so I don't know if you can concatenate strings with the plus (+) operator. If that were possible, however, I would write the loop in a slightly shorter form thus:

  sb.append(args[0]);
  for(i = 1; i < args.length; i++)
      sb.append(" "+args[i]);

In either case, we have a loop with an actual body, we aren't shoehorning more stuff into the increment section of the for-loop header than is supposed to be there, we have made the loop more readable, we have more aesthetically pleasing output in the string buffer, and we have avoided a stupid programming error, all at the same time.
Jeff Dutky Send private email
Thursday, April 05, 2007
 
 
Jeff:  I believe he was experimenting to learn.  He wasn't giving us production code.  :P

Besides, your examples have an error.  What if there is no element 0.  :)

Thursday, April 05, 2007
 
 
To copy a string:

while( *dst++ = *src++ );
Donald Duck
Sunday, April 08, 2007
 
 
Since we're just playing, here's my take on a somewhat robust solution:

boolean first = true;
for(String arg : args) {
    if (first) {
        first = false;
    } else {
      sb.append(" ");
    }
    sb.append(arg.);
}
System.out.println(sb.toString());

The most general I can do is:

final public class StringUtil {
    public static String join(Iterable<?> iter, Object delim) {
        if (null == iter) {
            throw new IllegalArgumentException("Iterator may not be null");
        }
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Object o : iter) {
            if (first) {
                first = false;
            } else {
                sb.append(delim);
            }
            sb.append(o);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(join(java.util.Arrays.asList(args), " "));
    }
}

Most stuff is handled pretty well. Arrays could be handled better, maybe by overloading with join(Object[] iter, Object delim). Other than that I think it's pretty solid.
Peter Monsson Send private email
Saturday, April 14, 2007
 
 
Well, the join(Object[] ...) wouldn't help with primitive arrays, so just passing in java.util.Arrays.asList() on the array would be a better solution compared to overloading.
Peter Monsson Send private email
Saturday, April 14, 2007
 
 
for ( int i = 0; i < args.length; i++, sb.append( args[i] ), sb.append(" ") );

Spot the reason for the ArrayIndexOutOfBoundsException.

WLOG, let args.length be 10.  Consider the loop control after i=9: i++, sb.append(args[i]), sb.append(" ").  The first subexpression increments i to 10 (past the last args[] value), the second then dereferences args[10] and boom!

The test i<args.length is executed only after the increment part has been done.

Sincerely,

Gene Wirchenko
Gene Wirchenko Send private email
Tuesday, April 17, 2007
 
 
How many sequence points does java have?
entity Send private email
Sunday, April 22, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz