1

I am relatively new to Java, I have some troubles with running this do-while loop.

Problem 1

Write a program that allows the user to convert a temperature given in degrees from either Celsius to Fahrenheit or Fahrenheit to Celsius. Use the following formulas: Degrees_C = 5 (Degrees_F − 32) / 9 Degrees_F = (9 (Degrees_C) / 5) + 32 Prompt the user to enter a temperature and either a C or c for Celsius or an F or f for Fahrenheit. Convert the temperature to Fahrenheit if Celsius is entered, or to Celsius if Fahrenheit is entered. Display the result in a readable format. If anything other than C, c, F, or f is entered, print an error message and stop.

Problem 2

Let’s continue Problem 1, but use a loop so the user can convert other temperatures. If the user enters a letter other than C or F—in either uppercase or lowercase—after a temperature, print an error message and ask the user to reenter a valid selection. After each conversion, ask the user to type Q or q to quit or to press any other key to repeat the loop and perform another conversion

public class Lab_4 {

    public static void main(String arg[]) {
        Scanner input = new Scanner(System.in);
        double F; //Fahrenheit
        double C; //Celsius
        String method; 
        boolean keepGoing = true; 
        do {            
            System.out.println("Choose a method:  ");
            System.out.println("(F)  Fahrenheit to Celsius.  ");
            System.out.println("(C)  Celsius to Fahrenheit.  ");
            System.out.println("(Q)  Exit the loop.  ");
            method = input.nextLine();
            if (method.charAt(0) == 'f' || method.charAt(0) == 'F') {
                System.out.println("Method F");
                System.out.println("Enter the temperature in Fahrenheit:  ");
                F = input.nextDouble();
                C = 5 * (F - 32) / 9;
                System.out.println("Temperature in Celsius:  " + C); }
            if (method.charAt(0) == 'c' || method.charAt(0) == 'C') {
                System.out.println("Method C");
                System.out.println("Enter the temperature in Celsius:  ");
                C = input.nextDouble();
                F = (9 * C / 5) + 32;
                System.out.println("Temperature in Fahrenheit:  " + F); }
            if (method.charAt(0)== 'q' || method.charAt(0)== 'Q') {
                keepGoing = false; 
                System.out.println("Exiting the loop!  "); }
            else {
                //if index 0 doesn't equal to C, F, Q, it's out of range. 
                System.out.println("Method is out of range!  ");
            }
        }while(keepGoing = true);
        input.close();
    }
}

The loop will keep going until I enter Q or q to exit out. So I have to enter Q in order to exit the loop, but instead I got an error message right after I got the conversion value, it simply doesn't run through the loop. The program just doesn't go through the while loop.

enter image description here

Try 2, still errors

package Lab_4;

import java.util.Scanner;

    public class Lab_4 {

        public static void main(String arg[]) {
            Scanner input = new Scanner(System.in);
            double F; //Fahrenheit
            double C; //Celsius
            String method; 
            boolean keepGoing = true; 
            do {            
                System.out.println("Choose a method:  ");
                System.out.println("(F)  Fahrenheit to Celsius.  ");
                System.out.println("(C)  Celsius to Fahrenheit.  ");
                System.out.println("(Q)  Exit the loop.  ");
                method = input.nextLine();
                if (method.charAt(0) == 'f' || method.charAt(0) == 'F') {
                    System.out.println("Method F");
                    System.out.println("Enter the temperature in Fahrenheit:  ");
                    F = input.nextDouble();
                    C = 5 * (F - 32) / 9;
                    System.out.println("Temperature in Celsius:  " + C); }
                else if (method.charAt(0) == 'c' || method.charAt(0) == 'C') {
                    System.out.println("Method C");
                    System.out.println("Enter the temperature in Celsius:  ");
                    C = input.nextDouble();
                    F = (9 * C / 5) + 32;
                    System.out.println("Temperature in Fahrenheit:  " + F); }
                else if (method.charAt(0)== 'q' || method.charAt(0)== 'Q') {
                    keepGoing = false; 
                    System.out.println("Exiting the loop!  "); }
                else {
                    //if index 0 doesn't equal to C, F, Q, it's out of range. 
                    System.out.println("Method is out of range!  ");
                }
            }while(keepGoing);
            input.close();
        }
    }
Y. Chen
  • 29
  • 4
  • 2
    try changing the 2nd and 3rd ifs to `else if ` – AWinkle Oct 06 '15 at 21:32
  • If put if else instead of if and fix the while(keepGoing), but the program is still not reading because Java apparently can't read the String index (out of range). – Y. Chen Oct 07 '15 at 00:39

4 Answers4

5

You have a typo:

}while(keepGoing = true);

Should be:

}while(keepGoing == true);

or just:

}while(keepGoing);

Explanation

keepGoing = true, even inside a condition, does assign keepGoing to true and returns its value (always true in this case).

In the other hand, keepGoing == true asks for comparison between keepGoing and true being equal in value.

Dici
  • 22,025
  • 5
  • 34
  • 74
lilezek
  • 5,800
  • 19
  • 43
  • 1
    I would add that this should actually be `while (keepGoing)` for a nicer code. And I would add a comma :) – Dici Oct 06 '15 at 21:24
  • 1
    Not just for a nicer code. Exactly to avoid this potential problem, one should avoid comparing booleans. – RealSkeptic Oct 06 '15 at 21:28
  • While you are correct in explaining why the while condition needs to be corrected, that does not answer the OP's original question. (Though it probably will answer a future question.) – Mage Xy Oct 06 '15 at 21:38
  • If you think they have a typo, vote to close as such. – Sotirios Delimanolis Oct 06 '15 at 21:49
  • @NikG OP just posted 2 problems, and no question. I replied to the last part *So I have to enter Q in order to exit the loop, but instead I got an error message right after I got the conversion value, it simply doesn't run through the loop.* – lilezek Oct 06 '15 at 21:52
  • 1
    @lilezek If that's the case, you answered incorrectly. A non-terminating while loop doesn't cause errors on its own; it just goes on forever (which is a logical error, not a compile or runtime error). The reason he got the error is because he entered a blank string as input, as you can see on the screenshot he attached to the question. – Mage Xy Oct 06 '15 at 22:00
  • @NikG I though OP forced an empty string error to exit the loop, after seeing that Q key was not exiting the loop. – lilezek Oct 06 '15 at 22:01
2

Code Logic Errors

While Loop

Your while loop is assigning keepGoing to true after every iteration. This means your loop is going to continue forever. Since you don't break on any of the conditions, I'm assuming you don't want that behavior.

If Statements

Your if statments will cause errors because they are not dependent on each others. You currently have it written like so (simplified):

if (method.charAt(0) == 'some_letter')
    // do something
if (method.charAt(0) == 'some_other_letter')
    // do something else
else
    // show error

The problem is that the first if condition is checked independently of the second. That means that if your first condition (method.charAt(0) == 'some_letter') is true, you'll still get the error message because that "else" is tied to the second if statement, which will be false (since the first character can't be two different characters).

The correct way to write this is like so (again, simplified):

if (method.charAt(0) == 'some_letter')
    // do something
else if (method.charAt(0) == 'some_other_letter') // NOTE the else on this line
    // do something else
else
    // show error

Doing it this way ties all the conditions together so only one of them is executed.

Scanner Issues

As for the actual error message you got: That happened because method was a blank string. A blank string has a length of 0, thus making 0 an invalid index, and therefore method.charAt(0) will cause a StringIndexOutOfBounds error.

But why is method blank after running through the first loop? Well, it's a bit of a "gotcha" for beginners. Scanner.nextLine() will retrieve the rest of the current line. One "line", as far as the Scanner is concerned, is everything up until the next newline character (the hidden character that you get when you press enter... \n). Scanner.nextDouble() on the other hand only grabs the next number... but does NOT consume the newline character.

What's happening in your program is that once you prompt the user for some value to convert, it adds an extra newline character that doesn't get consumed. Let's step through a simplified example:

do {
    System.out.println("Choose your method")
    method = Scanner.nextLine(); 

    // User enters "f", then presses enter. This means the Scanner's buffer
    // contains "f\n". nextLine will read everything up to "\n" (which is everything)
    // then consumes the newline character. Afterwards, the Scanner's buffer 
    // is completely empty. 

    if ((method.charAt(0) == 'f') || (method.charAt(0) == 'F'))
    {
        double F = Scanner.nextDouble();

        // User enters "12", then presses enter. The Scanner's buffer now contains
        // "12\n". nextDouble will read in "12", but will NOT consume the 
        // newline character. Afterwards, the Scanner's buffer will contain "\n".
    }

    // Loop ends here. You start from the top and call Scanner.nextLine.
    // However, the Scanner's buffer still has "\n" at this point, so 
    // nextLine will grab everything up to the newline (in other words, a blank string)
    // and then consume the already existing newline. Since you do no error
    // checking to make sure method has length > 0, your program crashes.
}

So how do you fix this? It's actually pretty easy. After you call Scanner.nextDouble(), simply call Scanner.nextLine() to consume the newline character.

In addition, I would suggest adding a check to make sure that the user's input is valid (i.e., not an empty string). This way, your program will not crash.

For more information and/or a better explanation, see the following question: Skipping nextLine() after using next(), nextInt() or other nextFoo() methods

Community
  • 1
  • 1
Mage Xy
  • 1,693
  • 28
  • 33
  • @Y.Chen The only way to prevent it is to guard against invalid inputs. The way I would do it to add one more if statement before any of the others: `if (method.length() == 0) continue;`. That statement will simply skip one iteration of the loop, meaning that nothing will be displayed at all until the user enters an input with a length greater than none. Alternatively, instead of continue, you can display an error, use some default value, or do anything else that you think is logical for your program. – Mage Xy Oct 07 '15 at 13:20
  • @Y.Chen Please see my edited answer. The problem you were having is related to `Scanner.nextDouble()`... luckily, fixing it is pretty simple. – Mage Xy Oct 07 '15 at 14:23
1

keepGoing = true is assignment in Java, not boolean condition, change to keepGoing == true, or simple while(keepGoing )

Safwan Hijazi
  • 2,001
  • 2
  • 14
  • 29
0

The indexOutOfBoundsException is due the empty String in your case "method"

method.charAt(0)

to avoid this you can put immediately after taking input from console

method = input.nextLine();

then add below if statement

if(!method.equals(""))

or check the length of the string

if(method.length() > 0)
// your code goes here

Moreover, the while statement is assigning the value "true" to boolean "keepgoing" instead it should be

while(keepgoing)
AMG
  • 5
  • 3