Seeking assistance for assignment to average an array of grades - java

I'll copy/paste the assignment, and then the progress I've made thus far. I'm truly not looking for someone to do the assignment, only some assistance to point me in the right direction as to where I'm going wrong? The program is running without error, however it's returning multiple results for a student when it should only be returning one. I can modify the grades and have it produce different results, so I know the math is being done, however I don't know why it's giving multiple (and different) results for a single student. I have been going over the code and cannot determine where I'm going wrong. My best guess is that it's somewhere in the OutputGrade method, I just can't find it.
Instructions:
Create a Java class called student with the following instance variables:
• private String studentName;
• private int [] grades; //an array of grades
Include setter and getter methods to set and get these 2 properties. The setter method for the grades instance array variable — setGrades() — should take a single argument which is an array of int with the grades already filled in. setGrades() should be used if statement(s) to make sure that each grade value in the array parameter is valid (between 0 and 100) — you will need to use a loop in conjunction with the if-statement(s) to do this efficiently. If a grade is out of bounds, setGrades() should set that grade value to 0. The array that you pass to setGrades() must hold between 3 and 5 grades.
Include a method called outputGrade() that averages up all the grades in the student grades array and then uses a switch statement to output grade conversions based on the following criteria:
• For values from 0–59, your program should output: “Student has failed this class”
• For values from 60–69, your program should output: “Student gets a D”
• For values from 70–79, your program should output: “Student gets a C”
• For values from 80–89, your program should output: “Student gets a B”
• For values from 90–100, your program should output: “Student gets an A”
Where “Student” is the actual name of the student.
Create a test class called TestStudent that instantiates 3 students and sets their names and grades and then calls outputGrade() for each student. For your 3 students, 1 must have 3 grades, 1 must have 4 grades, and 1 must have 5 grades. This is so you will have 3 different array sizes to pass to setGrades(). Make sure that for 1 student, setGrades() is called with 1 grade value that is out of bounds (less than 0 or greater than 100).
Code:
public class TestStudent {
public static void main(String[] args) {
Student student1 = new Student();
int[] grades1 = {15, 50, 5};
student1.setStudentName("Ernest Craft");
student1.setGrades(grades1);
student1.outputGrades();
Student student2 = new Student();
int[] grades2 = {95, 95, 95, 95};
student2.setStudentName("Steve Jones");
student2.setGrades(grades2);
student2.outputGrades();
Student student3 = new Student();
int[] grades3 = {105, -1, 72, 90, 88};
student3.setStudentName("Mary Smith");
student3.setGrades(grades3);
student3.outputGrades();
} // end method main
} // end class TestStudent
Student class:
public class Student {
private String studentName;
private int[] grades;
//constructor
public Student() {
}
public void setStudentName(String name) {
studentName = name;
} // end method setStudentName
public String getStudentName() {
return studentName;
} // end method getStudentName
public void setGrades(int gradeArray[]) {
grades = gradeArray;
for (int i = 0; i < gradeArray.length; i++) {
if (gradeArray[i] < 0 || gradeArray[i] > 100) {
gradeArray[i] = 0;
} // end if
} // end loop
} // end method setGrades
public int[] getGrades() {
return grades;
} // end method getGrades
public void outputGrades() {
int gradesTotal = 0;
int gradesAverage;
char letterGrade;
for (int i : grades) {
gradesTotal += i;
} // end loop
gradesAverage = gradesTotal / (grades.length);
if (gradesAverage >= 0 && gradesAverage <= 59) {
letterGrade = 'F';
} else if (gradesAverage >= 60 && gradesAverage <= 69) {
letterGrade = 'D';
} else if (gradesAverage >= 70 && gradesAverage <= 79) {
letterGrade = 'C';
} else if (gradesAverage >= 80 && gradesAverage <= 89) {
letterGrade = 'B';
} else {
letterGrade = 'A';
} // end if statement
switch (letterGrade) {
case 'A':
System.out.println(studentName + " gets an A.");
case 'B':
System.out.println(studentName + " gets an B.");
case 'C':
System.out.println(studentName + " gets an C.");
case 'D':
System.out.println(studentName + " gets an D.");
case 'F':
System.out.println(studentName + " gets an F.");
} // end switch
} // end method outputGrades
} // end class Student
Thanks for taking a look!
Ben

You forgot the break statements from your switch. If you don't break, it'll just keep executing everything until the end of the block!
This somewhat confusing "feature" is a leftover from C, and in most cases you'll want to end all your cases with a break, return or throw.

Related

Confusion about how to process lines in a text file as they are read

So I was given the following GradedActivity class:
public class GradedActivity
{
private double score; // Numeric score
public void setScore(double s)
{
if (s < 0)
score = 0.0;
else if (s > 100)
score = 100.0;
else
score = s;
}
public double getScore()
{
return score;
}
public char getGrade()
{
char letterGrade;
if (score >= 90)
letterGrade = 'A';
else if (score >= 80)
letterGrade = 'B';
else if (score >= 70)
letterGrade = 'C';
else if (score >= 60)
letterGrade = 'D';
else
letterGrade = 'F';
return letterGrade;
} }
and I was tasked with generating a constructor that accepts values for points Obtaned and pointsTotal as arguments, initializes them, and sets the corresponding score (points obtained divided by points total), accessors and mutators for pointsobtained and total.
So here is what I came up with:
public class ProgrammingAssignment extends GradedActivity
{
public int pointsObtained;
public int pointsTotal;
public ProgrammingAssignment(int p, int t)
{
pointsObtained = p;
pointsTotal = t;
}
public int getPointsObtained()
{
return pointsObtained;
}
public int getPointsTotal()
{
return pointsTotal;
}
public double getScore()
{
return pointsObtained / pointsTotal;
}
public void setPointsObtained(int p)
{
pointsObtained = p;
}
public void setPointsTotal(int t)
{
pointsTotal = t;
}
}
Everything compiles without error, but getScore isn't computing obtained/total (it comes back 0) in my test class:
public class PADemo
{
public static void main(String[] args)
{
ProgrammingAssignment p1 = new ProgrammingAssignment(28,30);
GradedActivity p2 = new ProgrammingAssignment(0,30);
System.out.println (p1.getPointsObtained());
System.out.println (p1.getPointsTotal());
System.out.println (p1.getScore());
System.out.println (p1.getGrade());
System.out.println (p2.getScore());
System.out.println (p2.getGrade());
p1.setPointsObtained(25);
p1.setPointsTotal(40);
System.out.println (p1.getScore());
System.out.println (p1.getGrade() == 'F');
}
}
How do I obtain the score (points obtained/points total) with getScore()
Test class returns:
28
30
0.0
F
0.0
F
0.0
true
Cars waiting: [a A123TR, a Z23YTU, a R23EWQ, a ERW345, a B12GFT...
Does that look correct? Why would you have the "a " at the beginning? That is not part of the car license. The "a " and "d " need to be removed BEFORE you add the license to the garage or queue.
creates a stack for cars in a garage (Max of 7)
a queue for cars waiting (max of 5)
Your basic logic appears wrong (to me).
When you get an "a" you do one of two things:
if there are less than 7 cars in the garage you add the car to the garage.
If there are 7, then if then are less the 5 cars in the queue, you add the car to the "queue".
When you get a "d" you:
first remove the car from the "garagee",
then you check the "queue". If there are cars in the "queue" then you move the car from the "queue" to the "garage".
So the logic might be structure something like:
while (...)
{
...
String[] data = line.split(" ");
if (data[0].equals("a"))
processArrival( data[1] );
else if (data[0].equals("d"))
processDeparture( data[1] );
}
I used the String.split(...) method which was suggested in your last question because it is a better test then to test the whole String for a specific character and your two pieces of data are separated into the array ready for processing. The data will now be split into two pieces of data: a) function
b) license
I used separate methods because the code is easier to read and logic for each function is contained in individual methods.

Calculating a minimum in object arrays and then using it in another calculation

I'm trying to understand how to take an object array that contains objects that have a name and 4 numbers and finding the lowest test grade. I have this Student object that has a name, bonus points earned, test 1 grade, test 2 grade, and a test 3 grade. I need to make sure that all 3 test grades added together don't go over 300 points.
I then need to find the lowest test grade of the 3 entered grades for each student and then be able to add the bonus points to them and print out the new grade.
I was going to create a method to loop through the Student object array and find the lowest grade for each student, have it create a new array with just the lowest grades and add that to the bonus points earned for each student but I'm not actually sure how to go about doing that part. This is the code for the Student object I've created so far:
public class Student
{
private String name;
private int bonusPoints;
private int test1;
private int test2;
private int test3;
public static final int MAX_TOTAL = 300;
public Student(String n, int bP, int g1, int g2, int g3)
{
setName(n);
setBonus(bP);
setTest1(g1);
setTest2(g2);
setTest3(g3);
}
//Setters & getters
//Method to check total of all 3 test grades
public boolean checkTotal(Student[] array)
{
int total = 0;
for (int i = 0; i < array.length; i++)
{
total += //I'm not sure how to refer to test1 ,test2, and test3 here
}
if (total > MAX_TOTAL)
{
return false;
}
else
{
return true;
}
}
}
So in order to add the 3 test totals together and check if it exceeds a maximum value. I would do something like this.
public boolean checkTotal()
{
int total = this.test1 + this.test2 + this.test3;
return total > MAX_TOTAL;
}
When referring to a classes variables within that class you can use the 'this' keyword to refer to the current instance of that class.
So a method call of that object would look something like this:
Student studentOne = new Student("Foo",90,80,70,10);
if(!studentOne.checkTotal())
//do something
else
//do something else
Also when returning a boolean you don't need an if/else most of the time. You can simply put
return /*your boolean expression here*/;

Return more than one variable from a Java method

Your program must read the id number and gpa and transfer the data into two separate arrays. You can assume there will never be more than 1000 students in the file. Do you know why you must use two separate arrays? You may find it useful in this program to create additional arrays to complete the requirements of the program as described next.
Your program must do two distinctly different things correctly for full credit:
You must create a simple diagram to show how many students fall into each of 8 different categories. This type of diagram is known as a histogram and it is generally useful to show how data is distributed across a range.
For each student in the input file, you must display their S-number, gpa, and class rank. The S-number and gpa will already be in your arrays; however, you must calculate their class rank.
Here is the code I have so far:
public static void main(String[] args) throws Exception
{
Scanner gpadata;
String snum;
double gpa;
int groupNumber;
gpadata = new Scanner(new File("studentdata.txt"));
while (gpadata.hasNext())
{
snum = gpadata.next();
gpa = gpadata.nextDouble();
groupNumber = gpaGroup(gpa);
System.out.println("Student number, GPA, and group number"
+ " is: " + snum +
" " + gpa + " " + groupNumber);
}
}
//Method to categorize students GPA into 1 of 8 groups
public static int gpaGroup(double gpa)
{
//Declare all variables
int gpaGroup;
//Assign GPA a group number
if (gpa >= 0.0 && gpa < 0.5)
gpaGroup = 1;
else if (gpa >= 0.5 && gpa < 1.0)
gpaGroup = 2;
else if (gpa >= 1.0 && gpa < 1.5)
gpaGroup = 3;
else if (gpa >= 1.5 && gpa < 2.0)
gpaGroup = 3;
else if (gpa >= 2.0 && gpa < 2.5)
gpaGroup = 4;
else if (gpa >= 2.5 && gpa < 3.0)
gpaGroup = 5;
else if (gpa >= 3.0 && gpa < 3.5)
gpaGroup = 6;
else
gpaGroup = 7;
//Return int value of group number
return gpaGroup;
}
//Method to find number of students in each group
public static void studentsInGroup(int gpaGroup)
{
//Declare all variables
int gpaGroup1 = 0;
int gpaGroup2 = 0;
int gpaGroup3 = 0;
int gpaGroup4 = 0;
int gpaGroup5 = 0;
int gpaGroup6 = 0;
int gpaGroup7 = 0;
int gpaGroup8 = 0;
//Total students in each GPA group
if (gpaGroup == 1)
gpaGroup1++;
else if (gpaGroup == 2)
gpaGroup2++;
else if (gpaGroup == 3)
gpaGroup3++;
else if (gpaGroup == 4)
gpaGroup4++;
else if (gpaGroup == 5)
gpaGroup5++;
else if (gpaGroup == 6)
gpaGroup6++;
else if (gpaGroup == 7)
gpaGroup7++;
else
gpaGroup8++;
}
Can I modify my method to return more than one variable from a method (in public static void studentsInGroup(int gpaGroup) return values of number of students in each group)? Is this where arrays start to come in? From here I would write another method to round number of students in each category to the nearest ten, then use this to write a method for creating a histogram etc etc.
I have been trying my hardest to understand the concepts, but I have been struggling lately. This is one of my last assignments for the semester and I'd like to keep my A, and also understand what I'm doing.
Can I modify my method to return more than one variable from a method (in public static void studentsInGroup(int gpaGroup) return values of number of students in each group)?
Yes, you can. You can create an object that contains two variables. However, the instructions suggest a different solution.
Inside your loop, read the id and gpa, and immediately stick them in two separate arrays.
Here is a fragment:
snums = [];
gpas = [];
while (gpadata.hasNext())
{
snum = gpadata.next();
gpa = gpadata.nextDouble();
snums.append(snum);
gpas.append(gpa);
}
ensure you are doing the following. I'm not giving away any code here. Also not sure why they want you to use array only!?!
Breakdown your requirement and see what you need to achieve.
Start with reading each line from file
each line is separated by " " and has id_number and gpa
from the requirement, the file will not contain more than 1000 students(1000 lines). You may declare this as a static class level variable static String[] idnum_array = new String[1000]; and another array for gpa which is Double[]
read each line and then separate by using String.split(" ") method. The first variable is your id number and 2nd will be your gpa. you follow ?
maintain a separate counter to increment the array position each time you set these values in the two arrays you created in step 3.
Integer i = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] splitString = line.split(" ");
idnum_array[i] = String.valueOf(splitString[0]);
gpa_array[i] = Double.valueOf(splitString[1]);
i++;
}
Do you agree that if we do idnum_array[7] to return it's corresponding gpa result from gpa_array[7] for that student ?
How you choose to count the number of people in a certain group is upto you.
I would do the following
create a static class level variable static Integer[] group_array = new Integer[]{0,0,0,0,0,0,0,0}; // there are only 8 groups!
loop my gpa_array
have an if/else inside the loop to check which group it falls in
increment the value at that index by 1. group_array[index]++;
In the end I will have an array of 8 elements which will correspond to the 8 groups. [0,200,300,200,0,300,0,0,0]
You should end up with nearly 4 methods similar to this.
1. readDataFromFile(String fileName)
2. groupGPAIntoCategory()
3. drawHistogram()
4. calculateRank()
I would personally create a Student object from the very beginning.
It's just cleaner and readable. Make sure you have your try catch block to print your exceptions and always comment!

Java - ArrayIndexOutOfBounds Error on parallel arrays

I'm having a bit of trouble with this project:
We're given a text file of 5 students, with 4 number grades following each name in a separate line. We have to use our main method to read the file, then perform calculations in the gradebook class. However, from what others in class have been saying the method we're using is archaic at best, involving Parallel arrays. We don't really seem to have any other option though, so I'm making due with what I can. But near what I'm hoping is the end of this code, I've encountered a problem, where it says the index that contains the grades for students is out of bounds.
I've rewritten the readFile method in my main in quite a few different ways, but no matter what I still get these errors. Could anyone help me understand what's going on? I'll post everything I can.
I also apologize if I'm a bit slow/incapable with this, this is my first time coding java in months unfortunately.
Also, in the error I post, line 64 of the main class is: grades[test] = inputFile.nextDouble();
run:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at Package1.GradeBookDemo.readFile(GradeBookDemo.java:64)
at Package1.GradeBookDemo.main(GradeBookDemo.java:29)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
The following is my Main method:
import java.util.Scanner;
import java.io.*;
public class GradeBookDemo {
public static void main(String[] args) throws IOException {
// Create a new gradebook object
Gradebook gradeBook = new Gradebook();
//Read StudentInfo file for names and test scores using readFile method
readFile(gradeBook);
//Output Student data
for (int index = 1; index <= 5; index++)
{
System.out.println("Name: " + gradeBook.getName(index) +
"\tAverage Score: " + gradeBook.getAverage(index) +
"\tGrade: " + gradeBook.getLetterGrade(index));
}
}
// This method reads from the StudentInfo file
public static void readFile(Gradebook gradeBook) throws IOException
{
int nI = 0; // Name index
int gI = 4; // Grade index
// Create a string array to hold student names and another for grades
double[] grades = new double[gI];
// Access the StudentInfo text file
File sFile = new File("StudentInfo.txt");
// Create a scanner object to read the file
Scanner inputFile = new Scanner(sFile);
// Read StudentInfo
for(int student = 1; student <= 5; student++)
{
String name = inputFile.nextLine();
gradeBook.setName(student, name);
for (int test = 0; test < 4; test++)
{
grades[test] = inputFile.nextDouble();
}
}
// Close the file
inputFile.close();
}
}
And then the Gradebook class
public class Gradebook {
// Declare fields
private final int NUM_STUDENTS = 5;
private final int NUM_TESTS = 4;
// ArrayList for names of students - 5 in total
private String[] names = new String[NUM_STUDENTS];
// Array to store letter grades
private char[] grades;
// array to store each student's scores
private double[] scores1 = new double[NUM_TESTS];
private double[] scores2 = new double[NUM_TESTS];
private double[] scores3 = new double[NUM_TESTS];
private double[] scores4 = new double[NUM_TESTS];
private double[] scores5 = new double[NUM_TESTS];
// Method to set student's name
public void setName(int studentNumber, String name)
{
names[studentNumber-1] = name;
}
// Method sets student scores
public void setScores(int studentNumber, double[] scores)
{
switch(studentNumber)
{
case 1:copyArray(scores1,scores); break;
case 2:copyArray(scores2,scores); break;
case 3:copyArray(scores3,scores); break;
case 4:copyArray(scores4,scores); break;
case 5:copyArray(scores5,scores); break;
default:break;
}
}
// Returns the student's name
public String getName(int studentNumber)
{
return names[studentNumber-1];
}
// Returns student's average score
public double getAverage(int studentNumber)
{
double avg=0.0;
switch(studentNumber)
{
case 1:avg = calcAverage(scores1); break;
case 2:avg = calcAverage(scores2); break;
case 3:avg = calcAverage(scores3); break;
case 4:avg = calcAverage(scores4); break;
case 5:avg = calcAverage(scores5); break;
default:break;
}
return avg;
}
// Returns the student's letter grade
public char getLetterGrade(int studentNumber)
{
char lettergrade;
if(getAverage(studentNumber)>=90 && getAverage(studentNumber)<=100)
lettergrade = 'A';
else if(getAverage(studentNumber)>=80 && getAverage(studentNumber)<=89)
lettergrade = 'B';
else if(getAverage(studentNumber)>=70 && getAverage(studentNumber)<=79)
lettergrade = 'C';
else if(getAverage(studentNumber)>=60 && getAverage(studentNumber)<=69)
lettergrade = 'D';
else
lettergrade = 'F';
return lettergrade;
}
// Calculates the student's average
private double calcAverage(double[] scores)
{
double sum=0;
for(int i=0; i<scores.length; i++)
sum+=scores[i];
return sum/scores.length;
}
// Determines student's letter grade based on average score
public char LetterGrade(double average)
{
char lettergrade;
if(average>=90 && average<=100)
lettergrade = 'A';
else if(average>=80 && average<=89)
lettergrade = 'B';
else if(average>=70 && average<=79)
lettergrade = 'C';
else if(average>=60 && average<=69)
lettergrade = 'D';
else
lettergrade = 'F';
return lettergrade;
}
// Array copy method
private void copyArray(double[] to, double[] from)
{
System.arraycopy(from, 0, to, 0, from.length);
}
}
Here is the file the program is reading - StudentInfo.txt:
Joanne Smith
98
89
100
76
Will Jones
67
89
91
88
Kerry McDonald
78
79
88
91
Sam Young
88
98
76
56
Jill Barnes
94
93
91
98
You will get InputMismatchException
Reason
String name = inputFile.nextLine(); //Reads the current line, Scanner moves to next line
grades[test] = inputFile.nextDouble(); //Reads the next double value
You should be able to read first student name and grades without any issues. After reading 76, the scanner position is at the end of line 5. It didn't skip line 5.
So, when you try to read next student name by calling nextLine(). you will see "". and scanner moves to line 6.
So the next call to nextDouble() fails.
Quick fix
use Double.parseDouble(inputFile.nextLine()); for reading the double values here
This is a rather interesting "This can not happen" scenario.
From the comments I would guess that the code actually compiled has an error in the inner for-loop. You need to find which file you are actually compiling.
Try adding random
System.out.println("Got HERE!");
to your code and see if any of them are actually printed.
Because the code you show should not be able to give that exception.

Is this the correct way to use an IllegalArgumentException?

I'm trying to work on a Java assignment. This is what it asks:
Write a class named TestScores. The class constructor should accept an array of the test scores as its argument. The class should have a method that returns the average of the test scores. If an test score in the array is negative or greater than 100, the class should throw an IllegalArgumentException. Demonstrate. I need a file named TestScores and TestScoresDemo.
This is what I have so far. I know some of it is wrong and I need help fixing it:
class TestScores {
public static void checkscore(int s) {
if (s<0) throw new IllegalArgumentException("Error: score is negative.");
else if (s>100) throw new IllegalArgumentException("Error Score is higher then 100");
else if (s>89)throw new IllegalArgumentException("Your grade is an A");
else if (s>79 && s<90)throw new IllegalArgumentException("Your grade is an B");
else if (s>69 && s<80)throw new IllegalArgumentException("Your grade is an C");
else if (s>59 && s<70)throw new IllegalArgumentException("Your grade is an D");
else if (s<60)throw new IllegalArgumentException("Your grade is an F");
{
int sum = 0; //all elements together
for (int i = 0; i < a.length; i++)
sum += a[i];
}
return sum / a.length;
}
}
class TestScoresDemo {
public static void main(String[] args) {
int score = 0;
Scanner scanner = new Scanner(System.in);
System.out.print(" Enter a Grade number: ");
String input = scanner.nextLine();
score = Integer.parseInt(input);
TestScores.checkscore(score);
System.out.print("Test score average is" + sum);
}
}
I know the assignment calls for a try statement because in my book that's what I see with the IllegalArgumentException. Can anyone help me? I'm using Eclipse as an IDE.
Your TestScores class should have two members: a constructor that accepts an array of scores and a method that returns the average of the scores. The assignment isn't totally clear as to which of these should throw an IllegalArgumentException if a test score is out of range, but I'd make it the constructor (since that's what has the argument).
public class TestScores {
public TestScores(int[] scores) throws IllegalArgumentException {
// test the scores for validity and throw an exception if appropriate
// otherwise stash the scores in a field for later use
}
public float getAverageScore() {
// compute the average score and return it
}
}
You're on the right track with your TestScoresDemo class. It will first need to collect a set of scores into an array. Then it should construct a TestScores object. This is what needs to be inside a try/catch block because it can throw an exception. Then you just need to call getAverageScore() and do something with the result.
An exception is something used to define something that didn't go right on the normal flow of an application. You have to throw the IllegalArgumentException when the method checkScore is called and it finds any argument outside the range (between 0 and 100).
Your class should have this structure:
public class TestScore {
private int scores[]; //With setters and getters.
public TestScore(int scores[]) {
//Here, you set the scores array to the one on this class.
}
public int getAverage() {
//You do the average here, and since you need to iterate over the
//array to sum each value, you can check the value and if it's not
//ok you throw the IllegalArgumentException. No throws keyword
//required since this kind of exception (like NullPointerException
//and many others) are unchecked exceptions, meaning they can be
//thrown by a method and it does not need to specify them.
}
}
The test class should create a TestScore object with an int array as a parameter of its constructor. Then you make a testAverageScore method that has the try-catch statement on it, since it's required to call the getAverage method.
Hope that helps. Good luck!.
EDIT: IllegalArgumentException is an unchecked exception.
public class TestScores {
private final int[] scores;
public TestScores(int[] scores) {
this.scores = scores;
}
public int getAverage() {
int sum = 0;
if(scores.length == 0) {
return 0;
}
for(int score: scores) {
if(score < 0 || score > 100) {
throw new IllegalArgumentException("Score is not valid!");
}
sum += score;
}
return sum/scores.length;
}
}

Categories

Resources