2

When I run this code, the lines after the while loop are never executed. I've done testing inside the loop itself, and as far as i can tell the loop itself is completing, the method just never moves on to the following line.

I am aware there are multiple similar topics, but most seem to reference proper string comparisons and infinite loops.

Example input for this would be:

Maria 1 2 3 4

Output should be:

Maria's GPA is 2.50.

Any help would be appreciated.

public static void printGPA(){
  Scanner console = new Scanner(System.in);

  String studentName = "";
  int counter = 0;
  int gpa = 0;

  System.out.print("Enter a student record: ");

  while (console.hasNext()){
    if (console.hasNextInt()){
      gpa += console.nextInt();
      counter += 1;
    } else {
      studentName = console.next();
    }
  }

  System.out.print(studentName + "'s GPA is ");
  System.out.printf("%.2f.", ((double)gpa / (double)counter));      
}
6
  • Cannot reproduce. As an aside, there's a bug on the last line. You need to cast either gpa or counter to double before the division; otherwise, the result will be truncated to integer. Commented Aug 18, 2014 at 19:21
  • possible duplicate of Java while loop terminates after one interation with scan.nextLine(); method Commented Aug 18, 2014 at 19:24
  • @NPE Fixed the casting, thanks. Commented Aug 18, 2014 at 19:31
  • Are you entering the data "Maria 1 2 3 4" in 1 line or are there "newlines" after each value like: "Marie\n1\n2\n3\n4\n"? Judging from the current answers there is already some confusion. Commented Aug 18, 2014 at 20:26
  • @bvdb All the data is entered on one line, separated by spaces, then enter is pressed at the end. Commented Aug 18, 2014 at 20:31

4 Answers 4

1

while (console.hasNext()){ is a blocking call that waits for input. If the stream is not terminated it is assumed that there is more. System.in reads from your keyboard and that stream should never be closed and therefor the "hasNext()" call will wait indefinitely.

The fix is to do this:

Scanner sc = new Scanner(System.in);
System.out.print("Enter a student record: ");
String str = sc.nextLine();
StringTokenizer st = new StringTokenizer(str);

while (st.hasMoreTokens()) {
    String token = st.nextToken();
    // try to parse the token as an integer with try-catch Integer.parseInt()
    try {
        int num = Integer.parseInt(token);
        gpa += num;
        counter++;
    } catch (NumberFormatException e) {
        // if it fails, assume it's the name of the student
        studentName = token;
    }
}

// We only read a single line and we're not asking how much more there is.
Sign up to request clarification or add additional context in comments.

1 Comment

Is there an advantage to this method as opposed to creating a second Scanner object (see andyb2793's answer)?
1

I think your problem is that you need another scanner. The first scanner is going to grab everything in the input stream. Here's an idea, scan the entire line of input and throw it into a string. Then scan that string with another scanner. Here is my proposed solution:

     public static void main(String[] args)
     {
        Scanner console = new Scanner(System.in);
        String studentName = "";
        int counter = 0;
        double gpa = 0;



        System.out.print("Enter a student record: ");
        String myInput = console.nextLine();
        Scanner scan2 = new Scanner(myInput);

        while (scan2.hasNext()){
        if (scan2.hasNextInt()){
        gpa += scan2.nextInt();
        counter += 1;
        } 
        else {
      studentName = scan2.next();
    }
  }

  System.out.print(studentName + "'s GPA is ");
  System.out.printf("%.2f.", (double)(gpa / counter));    
  }

This should work, it worked for me although I needed to change the data type of gpa to double to get the proper calculation. I know just reposting code may not seem helpful, but I felt it was an easier to show you rather than try and explain it. Hope this helps!!!!

1 Comment

I didn't copy paste his code, but the idea itself was valid and worked.
0

(Addition to Xabster's answer) Since the scanner stream will keep on looking forever and doesn't know when you stop, another solution is to introduce an exit word, such as "done". That means it will keep on taking in numbers until you say done.

 public static void printGPA(){
  Scanner console = new Scanner(System.in);
  String studentName = "";
  int counter = 0;
  int gpa = 0;

  System.out.print("Enter a student record: ");
  String input = "";
  while (true){
    input=console.next();
    if (input.equals("done"))
      break;
    try
    {
      gpa += Integer.parseInt(input);
      counter += 1;
    }
    catch (NumberFormatException e)
    {
      studentName = input;
    }
  }

  System.out.print(studentName + "'s GPA is ");
  System.out.printf("%.2f.", ((double)gpa / (double)counter));      
}

Input:

Maria 1 2 3 4 done

Comments

0

The loop is going infinite and keeps waiting. Add some condition that will break the loop ->

while (console.hasNext()){
if (console.hasNextInt()){
    int num = console.nextInt();
    if ( num == -99){
        break;
    }
  gpa += num;
  counter += 1;
 } else {
  studentName = console.next();
 }
}

Then enter -> "Maria 1 2 3 4 -99"

Or you can add the logic to break the loop after counter reaches 4.

    while (console.hasNext()) {
        if (console.hasNextInt()) {

            gpa += console.nextInt();
            counter += 1;
            if (counter == 4) {
                break;
            }
        } else {
            studentName = console.next();
        }
    }

2 Comments

I don't think it is looping infinitely though. I tested by putting in a second counter that prints its value right before closing the while loop, and it was running exactly as many times as it should.
what I meant was, the console.hasNext() keeps waiting for next input so you have to break it somehow. That's why I suggested the above solution. Try below to see its reading your inputs -> int num = console.nextInt(); gpa += num; System.out.println("Scanned " + num);

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.