THE SYLLABUS TASK
What you need to build
Create a program to process student results from user input.
Full syllabus requirements: classes, fields and methods
Subject count (0–10), then one mark per line if positive. Zero count throws DivideByZeroException; marks outside 0–100 or nonfinite values throw InvalidMarksException. Grade thresholds match the ten-student example.
UNDERSTAND THE IDEA
Explanation
Validation occurs before a result is displayed. The zero-count exception prevents computing an undefined average, while a mark exception stops processing an invalid marks list.
Both custom types extend Exception. The driver prints total, average and grade only after calculate returns successfully, so partial input never produces a misleading final result.
TURN THE IDEA INTO STEPS
Step-by-step algorithm
- Read the subject count.
- Throw the zero-subject exception before division.
- Read each mark and validate its range and finiteness.
- Compute total and average only after all marks pass.
- Catch custom exceptions or malformed numeric input with clear messages.
SEE THE CORE OPERATION
Flowchart
This chart focuses on the named operation or core OOP decision. Diamonds show conditions; labeled branches show outcomes. Read it with the complete algorithm and source for input handling and other operations. Scroll within the diagram on a phone.
Validate student result input
Main.java
import java.util.*;
public class Main {
private static final Scanner IN = new Scanner(System.in).useLocale(Locale.ROOT);
static String text() {
if (!IN.hasNextLine()) throw new IllegalArgumentException("Incomplete input.");
String value = IN.nextLine().trim();
if (value.isEmpty() || value.length() > 200) throw new IllegalArgumentException("Text must have 1–200 characters.");
return value;
}
static int integer(int low, int high) {
int value = Integer.parseInt(text());
if (value < low || value > high) throw new IllegalArgumentException("Integer out of range.");
return value;
}
static double number(double low, double high) {
double value = Double.parseDouble(text());
if (!Double.isFinite(value) || value < low || value > high) throw new IllegalArgumentException("Number out of range.");
return value;
}
static void money(String label, double value) { System.out.printf(Locale.ROOT, "%s: %.2f%n", label, value); }
static class InvalidMarksException extends Exception {
private static final long serialVersionUID=1L;
InvalidMarksException(){super("Marks must be finite values from 0 to 100.");}
}
static class DivideByZeroException extends Exception {
private static final long serialVersionUID=1L;
DivideByZeroException(){super("Subject count cannot be zero.");}
}
static double[] calculate(int subjects) throws InvalidMarksException,DivideByZeroException {
if(subjects==0)throw new DivideByZeroException();
double total=0;
for(int i=0;i<subjects;i++){
double mark=Double.parseDouble(text());
if(!Double.isFinite(mark)||mark<0||mark>100)throw new InvalidMarksException();total+=mark;
}
return new double[]{total,total/subjects};
}
public static void main(String[] args){
try{
int subjects=integer(0,10);double[] result=calculate(subjects);double average=result[1];
String grade=average>=90?"A":average>=80?"B":average>=70?"C":average>=60?"D":average>=40?"E":"F";
money("Total",result[0]);money("Average",average);System.out.println("Grade: "+grade);
}catch(InvalidMarksException|DivideByZeroException e){System.out.println(e.getMessage());}
catch(IllegalArgumentException e){System.out.println("Invalid input: "+e.getMessage());}
}
}
Copy a source file or download the project to preserve its file names.
USE THE RIGHT ENVIRONMENT
How to compile and run
Install a JDK (Java 11 or newer; JDK 17 is suitable), extract this project’s ZIP into its own folder, then open a terminal in that folder.
javac -encoding UTF-8 Main.java
java MainThe standalone source is named Main.java and its entry class is Main. You may also paste it into an online Java compiler and supply the sample input there. Choose Java explicitly; these pages do not change the site compiler or import code automatically.
Each experiment has its own folder because many use the public class Main. Compile and run one experiment at a time.
UNDERSTAND THE JAVA CODE
Line-by-line explanation
These steps follow the exact Java source above. Related statements are grouped; line numbers count blank lines and restart for each file. Start with main to follow execution, then open the constructors, methods or event handlers it uses.
Main.java
Lines 1–4Import utilities and create the shared input reader
import java.util.*;
public class Main {
private static final Scanner IN = new Scanner(System.in).useLocale(Locale.ROOT);java.util.* imports utility type names such as Scanner, Locale and collections. Main is the public class matching Main.java. The private static final IN field holds one shared Scanner for System.in; final prevents replacing that reference. The scanner uses Locale.ROOT.
Lines 5–10Read one nonempty trimmed input line
static String text() {
if (!IN.hasNextLine()) throw new IllegalArgumentException("Incomplete input.");
String value = IN.nextLine().trim();
if (value.isEmpty() || value.length() > 200) throw new IllegalArgumentException("Text must have 1–200 characters.");
return value;
}text checks whether a line exists, reads it and removes leading/trailing whitespace. Reject empty text and lengths above 200 by throwing IllegalArgumentException. Otherwise return the string. One field is read per line, so these helpers do not mix nextInt with leftover newlines.
Lines 11–15Parse and range-check an integer field
static int integer(int low, int high) {
int value = Integer.parseInt(text());
if (value < low || value > high) throw new IllegalArgumentException("Integer out of range.");
return value;
}Integer.parseInt converts the returned string to int or throws NumberFormatException, a subtype of IllegalArgumentException. Reject values outside the caller’s inclusive low/high limits, then return the accepted integer.
Lines 16–20Parse and range-check a finite decimal field
static double number(double low, double high) {
double value = Double.parseDouble(text());
if (!Double.isFinite(value) || value < low || value > high) throw new IllegalArgumentException("Number out of range.");
return value;
}Double.parseDouble reads the string as a double. Double.isFinite rejects NaN and infinities as well as the explicit low/high range check. Return only a finite accepted value; exceptions transfer control to a matching catch block.
Line 21Format a labelled numeric result consistently
static void money(String label, double value) { System.out.printf(Locale.ROOT, "%s: %.2f%n", label, value); }money is a formatting helper: %s prints the label, %.2f prints two decimal places, and %n ends the line. Locale.ROOT fixes locale-sensitive formatting. The helper can also display non-currency quantities; it does not change the stored value.
Lines 22–29Define two checked exception classes
static class InvalidMarksException extends Exception {
private static final long serialVersionUID=1L;
InvalidMarksException(){super("Marks must be finite values from 0 to 100.");}
}
static class DivideByZeroException extends Exception {
private static final long serialVersionUID=1L;
DivideByZeroException(){super("Subject count cannot be zero.");}
}Both custom classes extend Exception and provide specific messages through super. serialVersionUID is a serialization-version identifier. These checked exceptions must be declared or caught; they are distinct from input parsing errors.
Lines 30–32Declare possible failures and reject zero subjects first
static double[] calculate(int subjects) throws InvalidMarksException,DivideByZeroException {
if(subjects==0)throw new DivideByZeroException();
double total=0;calculate declares both checked exceptions with throws. Rejecting subjects == 0 before computing an average prevents division by zero. total starts at zero.
Lines 33–36Validate each mark before adding it
for(int i=0;i<subjects;i++){
double mark=Double.parseDouble(text());
if(!Double.isFinite(mark)||mark<0||mark>100)throw new InvalidMarksException();total+=mark;
}Read the mark as text and parse a double. Reject NaN, infinities and values outside 0–100 with InvalidMarksException. Only accepted values contribute to total.
Lines 37–38Return total and average together
return new double[]{total,total/subjects};
}The new double array has total at index 0 and total/subjects at index 1. A zero subject count cannot reach this return because it threw earlier.
Lines 39–43Calculate the grade after a successful result
public static void main(String[] args){
try{
int subjects=integer(0,10);double[] result=calculate(subjects);double average=result[1];
String grade=average>=90?"A":average>=80?"B":average>=70?"C":average>=60?"D":average>=40?"E":"F";
money("Total",result[0]);money("Average",average);System.out.println("Grade: "+grade);main accepts 0–10 subjects so zero can demonstrate the custom exception. After calculate succeeds, read the average, test grade thresholds downward and display the two numeric results.
Lines 44–47Handle domain exceptions separately from input errors
}catch(InvalidMarksException|DivideByZeroException e){System.out.println(e.getMessage());}
catch(IllegalArgumentException e){System.out.println("Invalid input: "+e.getMessage());}
}
}The multi-catch prints either custom exception’s message. A separate IllegalArgumentException catch handles bad numeric strings and helper range failures. The final braces close main and Main.
FOLLOW THE STATE
Dry run
- Two marks 80 and 90 yield total 170 and average 85, grade B.
- A mark 101 triggers InvalidMarksException.
- A count of zero triggers DivideByZeroException before reading marks.
- Neither failed case prints a total or grade.
CHECK THE BEHAVIOUR
Sample input & output
These outputs were captured by running the exact delivered Java project.
Sample 1
2
80
90
Total: 170.00
Average: 85.00
Grade: B
Sample 2
0
Subject count cannot be zero.
Sample 3
2
50
101
Marks must be finite values from 0 to 100.
Common mistakes
- Do not print partial totals after a validation failure.
- Use a custom type, not an unrelated built-in exception, for the stated condition.
- Reject NaN as well as numeric out-of-range values.
WHY THIS GROWTH RATE?
Time and space complexity
O(s) validation/summing for s subjects; O(1) extra numeric state.
Every valid mark is read, checked and added once. The loop is linear in subject count, while grade selection checks a fixed number of thresholds.
The calculation does not retain a marks array; it keeps the running sum and returns two numeric results. Input text storage and exception runtime costs are separate.
These bounds describe the implemented data processing. Input/output text length, scheduling, framework rendering and runtime/library internals are identified separately where they matter. Educational limits bound the actual examples.
PREPARE FOR YOUR LAB VIVA
Related viva questions & answers
Try answering aloud, then expand to check your reasoning. Questions focus on this program’s classes, state and behavior.
Why is the zero-subject condition checked before reading marks?
There is no valid denominator for the average. Checking immediately gives the specified custom exception and avoids unnecessary input consumption.
Why does the code explicitly test Double.isFinite for a mark?
NaN can evade ordinary less-than/greater-than range comparisons, and infinities are not valid marks. The finiteness check closes those cases.
Why are results printed after calculate returns?
Successful return confirms that every required mark was accepted. An exception prevents the driver from presenting a partial total as a complete result.
What is the difference between InvalidMarksException and NumberFormatException here?
The custom exception reports a parsed numeric value violating the marks contract. NumberFormatException reports text that cannot be parsed as a number.
Why can one catch handle both custom exceptions?
The multi-catch alternatives are separate exception types, and both need the same message-display behavior. Their individual types still describe different failures.
Does the running-total design need an array of all marks?
No. Each accepted mark contributes immediately to the sum. Total and average can be calculated with constant extra numeric storage.