Jump to content

variable assignment within conditional statement

- - - - -

  • Please log in to reply
10 replies to this topic

#1
existentialist

existentialist

    Newbie

  • Members
  • PipPip
  • 14 posts
I just need some clarification about this technique and its usage. I think the String from readLine() is being checked against null and subsequently assigned to str, and processed. It doesn't make sense for it to be assigned and then checked after. I don't remember where I heard this, but I thought it was bad style to use an assignment within a conditional statement, but if so, then how else could this be written?

try 

{

    BufferedReader in = new BufferedReader(new FileReader("filename") );

    String str;

    while ( (str = in.readLine() ) != null) 

       	process(str);

    in.close();

} 

catch (IOException e) 

{

	//do nothing

}

I've searched around for more information on this, but I've mostly found ternary operator examples (irrelevant) and definite assignments (way over my head, but seems irrelevant too).

#2
existentialist

existentialist

    Newbie

  • Members
  • PipPip
  • 14 posts
also, this code looks almost identical.
		try 
		{
		    BufferedReader in = new BufferedReader(new FileReader("file.txt") );
		    StringBuffer buf = new StringBuffer();
		    while ( (buf.append(in.readLine() ) ) != null) 
		       	System.out.println(buf);
		    in.close();
		}
		catch (IOException e) 
		{
			//do nothing
		}
but it goes into what seems to be an infinite loop.
If any one can shed some light on this, please enlighten us.

#3
Vladimir

Vladimir

    Learning Programmer

  • Members
  • PipPipPip
  • 79 posts
Assignment in if is OK for Java, because Java does not allow you write something like this by mistake (code updated, thanks nicckk):


String str = "not test";

if (str = null) { // oops, = instead of ==, but compiler will show you error, because it only accepts boolean value here

    // process

}


but you still can write this:


		boolean condition = false;

		if (condition = true) { // oops, = instead of ==, but compiler can't help you

		     System.out.println("Oops");

		}


but typically above code will look like this:


		boolean condition = false;

		if (condition) {

                    //

		}


So your first code is OK for Java, but still can be problem in rare situations. Other languages that does not have strong type checking use some tricks to avoid this problem, for example PHP:


$condition = true;

if (true = $condition) { // note reverse order, you can't assign to true, so interpreter will show error

     // process

}


But in Java there is no need for it.

Edited by Vladimir, 07 November 2010 - 12:09 PM.


#4
nicckk

nicckk

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 629 posts
[quote name='Vladimir']Assignment in if is OK for Java, because Java does not allow you write something like this by mistake:



#5
existentialist

existentialist

    Newbie

  • Members
  • PipPip
  • 14 posts
The first code i posted works fine, but I'm not exactly sure what's going on in the language that it's OK. Like i said, I assume that the assignment is made first
str = in.readLine()
and then somehow "str" is checked not to be null
( (str = in.readLine() ) != null) 
But if that's the case, then why does an assignment on StringBuffer instead of String fail.
while ( (buf.append(in.readLine() ) ) != null) 

		       	process(buf);
I've run this code with process(), actually just a simple System.out.println(). And like I can't figure out why the top one works, and the bottom one fails. It prints out the file, then a bunch of nulls, and then what looks like a bunch of whitespace, and never ends.

#6
existentialist

existentialist

    Newbie

  • Members
  • PipPip
  • 14 posts
The test file i used was just one line, every letter a-z lowercase. I set a breakpoint at the StringBuffer declaration; buf is constructed with value[16]. BufferedReader in was constructed with cb[8192]. At the first iteration of while condition, a-z are read into the StringBuffer and it autoexpands to length 34. At the println() within while loop, a-z are printed out as expected. But it when the condition is checked again, it doesn't terminate. Somehow, BufferedReader.readLine() is not returning null as it did when a String is assigned readLine() 's return value. The next iteration prints a-z with 1 null, then a-z with 2 nulls, etc..
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyznull
abcdefghijklmnopqrstuvwxyznullnull
abcdefghijklmnopqrstuvwxyznullnullnull
abcdefghijklmnopqrstuvwxyznullnullnullnull
abcdefghijklmnopqrstuvwxyznullnullnullnullnull
abcdefghijklmnopqrstuvwxyznullnullnullnullnullnull
abcdefghijklmnopqrstuvwxyznullnullnullnullnullnullnull
abcdefghijklmnopqrstuvwxyznullnullnullnullnullnullnullnull
abcdefghijklmnopqrstuvwxyznullnullnullnullnullnullnullnullnull

Maybe this is a waste of time, since BufferedReader already buffers the input readLine() is delimited by /n, and usually only reads 1 line, about idk 100 lines max? I just don't understand what's going on here. Really, I just want to know what's up with the whole assignment within a condition, and can and can't be done there.

#7
Vladimir

Vladimir

    Learning Programmer

  • Members
  • PipPipPip
  • 79 posts
nicckk, you are completely right. My example is bad, but I hope it demonstrates my point. I will update it to test for null.

existentialist, Here you assign return value of readLine() method to variable str and then compare variable str with null (expressions inside parentheses are evaluated first).

( (str = in.readLine() ) != null)

but here you pass return value of method readLine() to append(), then you compare return value of method append() with null:

( (buf.append(in.readLine() ) ) != null) 

But there is one problem. Method append() returns reference to itself (i.e. return this), not the string you just appended. You can check docs here: StringBuffer (Java 2 Platform SE 5.0)

#8
existentialist

existentialist

    Newbie

  • Members
  • PipPip
  • 14 posts
so how can i append to a StringBuffer in a condition?
 while ( !(buf.append(in.readLine() ).equals("null") ) )
still does the same thing, the contents of buf are being checked against String "null". But what I should really be doing is checking buf's last 4 char's for "null" for termination. But that means that the word "null" could never be read from the stream (eg, if stream were source code).
Right?

#9
Vladimir

Vladimir

    Learning Programmer

  • Members
  • PipPipPip
  • 79 posts
Almost right.
1. null is not string. From docs:

Quote

null is the reserved constant used in Java to represent a void reference i.e a pointer to nothing.
So you can't write null to buffer (write nothing, ok, nothing will be written) . You still can read null, but this has special meaning (end of stream, no value etc). To test for null you should use comparison: obj == null, obj != null
2. Your code from first post is very good quality. I guess you found it at tutorial and it's good enough to use it. As I said, assignment within conditional statement has bad moments, but in Java they are almost safe and are widely used.
3. You should not write as much code as possible in one line. Later you will not able to read such code. Now you are trying to write code within loop condition, which reads line, tests it for null and writes to buffer. That is really bad.

#10
existentialist

existentialist

    Newbie

  • Members
  • PipPip
  • 14 posts
yeah, but...

Quote

If str is null, then the four characters "null" are appended.
StringBuffer (Java 2 Platform SE 5.0)
which is why, it was printing like this

abcdefghijklmnopqrstuvwxyz

abcdefghijklmnopqrstuvwxyznull

abcdefghijklmnopqrstuvwxyznullnull

abcdefghijklmnopqrstuvwxyznullnullnull

abcdefghijklmnopqrstuvwxyznullnullnullnull

abcdefghijklmnopqrstuvwxyznullnullnullnullnull

abcdefghijklmnopqrstuvwxyznullnullnullnullnullnull

abcdefghijklmnopqrstuvwxyznullnullnullnullnullnullnull

abcdefghijklmnopqrstuvwxyznullnullnullnullnullnullnullnull

abcdefghijklmnopqrstuvwxyznullnullnullnullnullnullnullnullnull


though i agree that
 while ( !(buf.append(in.readLine() ).equals("null") ) ) 
is bad style, and obviously doesn't do what was intended

to get this to terminate when EOF is reached (when readLine returns null)
i've got this so far, and it works

		try 

		{

		    BufferedReader in = new BufferedReader(new FileReader("file.txt") );

		    StringBuffer buf = new StringBuffer();

		    while ( !( (buf.append(in.readLine() ) ).substring(buf.length() - 4).equals("null") ) ) 

		       	System.out.println(buf);

		    in.close();

		}

		catch (IOException e) 

		{

			//do nothing

		}

which, as you mentioned (3), is a long and difficult to read condition
I understand the whole assignment thing now (as you can see from the unnecessarily long example)
but how can i rewrite this code

#11
Vladimir

Vladimir

    Learning Programmer

  • Members
  • PipPipPip
  • 79 posts
I did not checked code, but in general it should be ok (and it's very similar to your first post):

                    String line = "";

		    while ((line = in.readLine()) != null) {

                        buf.append(line);

		       	System.out.println(buf);

                    }

If you strongly want to get rid of assignment (I think we discussed it enough :) ) you can rewrite it like this:

                    String line = "";

		    while (true) {

                        line = in.readLine();

                        if (line == null) {

                            break; // stop our infinitive loop

                        }

                        buf.append(line);

		       	System.out.println(buf);

                    }

As you see second variant is almost two times longer. That's why first variant is usually preferred.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users