简体   繁体   中英

Initialisation of a variable inside a loop

class Spaces {
public static void main(String args[])
throws java.io.IOException{

    char ch;
    int space = 0;

    do {

        ch = (char) System.in.read();
        if (ch == ' ') space++;

    } while (ch != '.'); //Stop if fullstop is provided

System.out.println("No. of spaces: " + space);
}

The following code above is completely correct and is doing exactly what it is intended to do.(To read characters until fullstop is pressed, then tell the user how many spaces have been entered). Although if I initialise the variable outside the do-while loop like in the following code:

class Spaces {
public static void main(String args[])
throws java.io.IOException{

    char ch = (char) System.in.read();
    int space = 0;

    do {

        if (ch == ' ') space++;

    } while (ch != '.'); //Stop if fullstop is provided

System.out.println("No. of spaces: " + space);
}

The program is refusing to stop. When I enter the full stop, the program is not stopping. I do know that declaring a variable inside the loop would mean that it is unavailable elsewhere outside that loop. But variable declared outside the loop (like in second set of code) should work in the loop and elsewhere. So I am not getting why the second set of code is not valid (the program runs, there is no compiling error, but when full stop is entered it keeps going).

I also understand this is a very basic question compared to the ones that get asked here. But I honestly couldn't find an answer. Thank you in advance.

The second program does not work because you are taking the input only once, and since the value of ch != '.' is always true, the loop never stops. You should instead place the System.in.read() inside the loop, so that in every iteration, the program will stop for the user input, compare it with the condition and then decide if next iteration should be performed or not.

you cant take ch = (char) System.in.read(); out of the loop. because you always have to ask the system to get you the new character.

Try to print your character, you will find that you are always printing the first character and you are in infinite loop.

Whatever value was in ch when this loop started will remain there forever because there's nothing writing to it:

    do {

        if (ch == ' ') space++;

    } while (ch != '.'); //Stop if fullstop is provided

You have to call System.in.read() from inside the loop. Like this:

class Spaces {
public static void main(String args[])
throws java.io.IOException{

    char ch = 0;
    int space = 0;

    do {
        ch = (char) System.in.read();
        if (ch == ' ') space++;

    } while (ch != '.'); //Stop if fullstop is provided

    System.out.println("No. of spaces: " + space);
}

The way you did it only one charakter is read in.

And afaik i know you dont have to write a throws statement for the main method.

You are calling System.in.read() outside of the do...while loop, so it's value never updates. Entering a full stop will not make difference in the second code because the value of ch is never updated. It is always equal to the value you initialized it to (in the case of the second example, System.in.read() .

With regards to your confusion, a variable declared outside the loop can work in the loop, but it needs to be updated if you want to persist changes. for example:

int count=0;
for(int i=0; i<10; i++) {
    count++;
}
//count will be 10 now

As you saw in your question, this is why the first set of code works, because in

    char ch; 
    int space = 0;

    do {

        ch = (char) System.in.read(); //ch is updated
        if (ch == ' ') space++;

    } while (ch != '.'); 

ch is updated. you could also have

char ch = (char)System.in.read();
int space = 0;

do {

    ch = (char) System.in.read();
    if (ch == ' ') space++;

} while (ch != '.'); 

where you actually instantiate the variable outside of the loop, but again, the value must be updated within the loop.

Variable declaration is not the same as variable initialisation which is also not the same as setting or assigning a variable .

In both versions of your program the variable declaration is outside of the do-while loop. A variable declaration includes the variable type and the variable name, so both char ch; and char ch = (char) System.in.read(); declare the variable ch as type char .

Variable initialisation is assigning a value to the variable when it is declared. For example, try running this program.

int i; // declaration and initialisation to default value
System.out.println("The integer is: " + i);

Java has a default for the initial value of any variable. If you do not want to use this default, you can instead use your own value. In this example we declare the variable i as type int and initialise it to the value 5 .

int i = 5; // declaration and initialisation
System.out.println("The integer is: " + i);

Finally, after a variable is declared and initialised you may assign a new value to the variable. Note that when you assign a variable you do not state the type of the variable -- this is only done in declarations.

int i = 5; // declaration and initialisation
i = 6;     // assignment
System.out.println("The integer is: " + i);

Assigning a variable stores a value, and using a variable reads the stored value. Moving the variable outside of the loop as you have done would usually be okay. However, System.in.read() is not a usual expression because it is impure . This means that when you call System.in.read with the same arguments it does not always produce the same value. To demonstrate this, try running both versions of the example program.

Version A

int a = (int) System.in.read();
int b = (int) System.in.read();
System.out.println("a is: " + a);
System.out.println("b is: " + b);

Version B

int a = (int) System.in.read();
int b = a;
System.out.println("a is: " + a);
System.out.println("b is: " + b);

If you write program A you may be inclined to simplify the program by using the transitivity of equality. That is, if b = (int) System.in.read() and a = (int) System.in.read() then by transitivity, b = a . However, this only holds if System.in.read() produces the same value every time it is used, and because it is impure this is not the case.

Also notice that in program B you are not prompted twice for an input. This is because System.in.read is only called once to initialise the variable a . It is not called when a is used (ie read) to assign b or to print to the console with System.out.println . Also try running this program for clarity.

int a = (int) System.in.read();
System.out.println("a is: " + a);
a = (int) System.in.read();
System.out.println("a is: " + a);

Finally coming to your loop, the reason it may not terminate is because the value of ch is invariant . This means the value of ch does not change during execution of the loop.

// ch is declared and initialised
char ch = (char) System.in.read();
int space = 0;

// There are no assignments to ch in the loop, so it remains invariant 
// during the loop's execution. This means if `ch != '.'` tests true
// once it will continue testing true.
do {
    if (ch == ' ') space++;
} while (ch != '.');

// ch is declared and initialised
char ch;
int space = 0;

// ch is assigned during the loop to an impure expression and has the 
// potential to vary for each iteration of the loop. This means even
// if `ch != '.'` tests true once it may not test true next iteration.
do {
    ch = (char) System.in.read();
    if (ch == ' ') space++;
} while (ch != '.');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM