Detecting a particular user input without first processing it in a while loop

Viewed 80

I have this program where the user inputs x amount of grades, then the program divides the sum of the grades by the number of inputs taken. It should also find the highest and lowest grades entered. When the user is finished, he/she types in -1 to end the program. However, I am having some issues with it.

  1. The program adds -1 to the average which skews all my results.
  2. I can't figure out how to calculate the minimum value in the list. It always counts -1 as the minimum value.

Here is the code below:

import java.util.Scanner;

public class Lab4_EnteringGrades
{
    public static void main (String a[]) 
    {    
         Scanner kb = new Scanner(System.in); 
  
         double average = 0;
         double gradesSum = 0;
         int grade = 0; 
         int numTests = 0;
         int maxValue = 0;
         int minValue = 0;
 
        
         while (grade != -1)
         {
             gradesSum += grade; 
             numTests += 1; 
             average = gradesSum / numTests;
        
             System.out.print("Enter a grade: ");
             grade = kb.nextInt();
              
             while ((grade < -1) || (grade > 100))
             {
                 System.out.println("Invalid grade.");
                 System.out.print("Enter a grade: ");
                 grade = kb.nextInt();
             }     
     
             if (grade > maxValue)
                 maxValue = grade;
         
             if (grade < maxValue)
                 minValue = grade;
          }
     
         System.out.printf("\nTotal number of tests: %d", numTests);
         System.out.printf("\nThe average is %.1f", average);
         System.out.printf("\nThe max value is %d", maxValue);
         System.out.printf("\nThe min value is %d", minValue);
    }
}

  
  
2 Answers

I made few changes -

  1. Initialization of minValue and maxValue , in your original code, minValue was -1 and grade could not be less than -1, hence you always saw minValue as -1. In general, if you want min and max vales, it is better to initialize like I did here.

  2. Moved the logic of calculating grade, average AFTER user has entered the grade in order not to mess up the average.

  3. Your original code was:

if (grade < maxValue)

I changed this to be if (grade < minValue). I believe it was a typo.

import java.util.Scanner;

public class Lab4_EnteringGrades {
    public static void main (String a[])
    {
        Scanner kb = new Scanner(System.in);

        double average = 0;
        double gradesSum = 0;
        int grade = 0;
        int numTests = 0;
        int maxValue = Integer.MIN_VALUE;
        int minValue = Integer.MAX_VALUE;


        while (true)
        {

            System.out.print("Enter a grade: ");
            grade = kb.nextInt();

            while ((grade < -1) || (grade > 100))
            {
                System.out.println("Invalid grade.");
                System.out.print("Enter a grade: ");
                grade = kb.nextInt();
            }
            if (grade == -1) {
                break;
            }

            gradesSum += grade;
            numTests += 1;
            average = gradesSum / numTests;


            if (grade > maxValue)
                maxValue = grade;

            if (grade < minValue)
                minValue = grade;
        }

        System.out.printf("\nTotal number of tests: %d", numTests);
        System.out.printf("\nThe average is %.1f", average);
        System.out.printf("\nThe max value is %d", maxValue);
        System.out.printf("\nThe min value is %d", minValue);
    } }

The problems are that

  1. You do gradesSum += grade; before reading the first grade, when grade is still 0.
  2. You do if (grade < maxValue) after the user has entered grade=-1;, thus always find that -1 is smaller.
  3. You compare the grade to maxValue both for checking max and min
  4. Since you initialize minValue=0, you won't ever find a smaller value (except -1), so you should initialize it to something larger

You can move all the code that processes the grade until after you've read it, and then break if the user enters -1:

import java.util.Scanner;

public class Lab4_EnteringGrades
{
public static void main (String a[])
  {
  Scanner kb = new Scanner(System.in);

  double average = 0;
  double gradesSum = 0;
  int grade = 0;
  int numTests = 0;
  int maxValue = 0;
  int minValue = 101;

  while (true)
     {
     System.out.print("Enter a grade: ");
     grade = kb.nextInt();

     while ((grade < -1) || (grade > 100))
        {
        System.out.println("Invalid grade.");
        System.out.print("Enter a grade: ");
        grade = kb.nextInt();
        }

     // Stop if the user entered -1
     if (grade == -1) break;

     gradesSum += grade;
     numTests += 1;
     average = gradesSum / numTests;

     if (grade > maxValue)
        maxValue = grade;

     if (grade < minValue)
        minValue = grade;
     }

  System.out.printf("\nTotal number of tests: %d", numTests);
  System.out.printf("\nThe average is %.1f", average);
  System.out.printf("\nThe max value is %d", maxValue);
  System.out.printf("\nThe min value is %d", minValue);
  }
}

The while(true) { if(..) break; } is slightly awkward though. You can improve the code further by creating a separate function for reading input:

import java.util.Scanner;

public class Lab4_EnteringGrades
{
  public static int readGrade(Scanner kb) {
    System.out.print("Enter a grade: ");
    int grade = kb.nextInt();

    while ((grade < -1) || (grade > 100))
    {
      System.out.println("Invalid grade.");
      System.out.print("Enter a grade: ");
      grade = kb.nextInt();
    }
    return grade;
  }

  public static void main (String a[])
  {
    Scanner kb = new Scanner(System.in);

    double average;
    double gradesSum = 0;
    int grade;
    int numTests = 0;
    int maxValue = Integer.MIN_VALUE;
    int minValue = Integer.MAX_VALUE;

    // Common idiom for reading a grade until it's -1
    while ((grade = readGrade(kb)) != -1) {
      gradesSum += grade;
      numTests += 1;

      if (grade > maxValue)
        maxValue = grade;

      if (grade < minValue)
        minValue = grade;
    }
    // Consider handling the case of numTests == 0
    average = gradesSum / numTests;

    System.out.printf("\nTotal number of tests: %d", numTests);
    System.out.printf("\nThe average is %.1f", average);
    System.out.printf("\nThe max value is %d", maxValue);
    System.out.printf("\nThe min value is %d", minValue);
  }
}
Related