Java file io calculating average and storing in another file - java

I would appreciate knowing how to tackle this type of problems. Thank you in advance.
Here is the question.
The first line of the files contains two integer numbers ;
number-of-records exam-grade
number-of-records : indicates number of the records in the file.
exam-grade : indicates the grade of the exam.
The file follows by students name and their grades.
Sample File: test1.txt
Contains four records, and the exam is out of 80. The file follows by the name and grade of the students:
4 80
Mary 65.5
Jack 43.25
Harry 79.0
Mike 32.5
You have to develop the body of following method:
public static void readWrite(String srcfileName, String dstFileName)
That reads grades of each student from srcFileName, calculates their grade percent, indicates that if student passed or failed, and finally reports the class average, number of the students passed, and number of the students failed the exam and saves the result in dstFileName.
The output file for the previous test file should be:
Mary 81.88 passed
Jack 54.06 passed
Harry 98.75 passed
Mike 40.63 failed
class average:68.83
passed: 3
failed: 1
here is the code I wrote for it,
import java.util.*;
import java.io.*;
public class Lab10Quiz {
public static void main(String[] args) throws FileNotFoundException
{
// Test cases
readWrite("test1.txt", "out1.txt");
readWrite("test2.txt", "out2.txt");
}
/** copies the content of the srcFileName into dstFileName, and add the average of the number to the end of the dstFileName
#param srcFileName : souce file name contains double numbers
#param dstFileName : destination file name
*/
public static void readWrite(String srcFileName, String
dstFileName) throws FileNotFoundException {
// Your code goes here
File output = new File(dstFileName);
PrintWriter outPut = new PrintWriter(output);
double avg = 0;
int count = 0;
double tmp = 0;
Scanner in = new Scanner(new File(srcFileName));
while (in.hasNextDouble()) {
tmp = in.nextDouble();
avg += tmp;
outPut.println(tmp);
count ++;
}
avg = avg / count;
outPut.println("Average = " + avg);
outPut.close();
}
}

This code achieves what you want
double avg = 0;
int failCounter = 0;
String[] keywords = in.nextLine().split(" ");
int studentNumber = Integer.parseInt(keywords[0]);
double examValue = Double.parseDouble(keywords[1]);
for (int i = 0; i < studentNumber; i++) {
keywords = in.nextLine().split(" ");
String studentName = keywords[0];
double studentMark = Double.parseDouble(keywords[1]);
double grade = calculateTotalGrade(studentMark, examValue);
failCounter += (hasFailed(grade) ? 1 : 0);
avg += grade;
outPut.println(String.format("%s \t\t %.2f \t\t %s", studentName, grade, hasFailed(grade) ? "failed" : "passed"));
}
avg = avg / studentNumber;
outPut.println("class average: " + avg);
outPut.println("passed: " + (studentNumber - failCounter));
outPut.println("failed: " + failCounter);
And I extracted some of the logic to below methods.
private static double calculateTotalGrade(double grade, double examValue) {
return grade * 100 / examValue;
}
private static boolean hasFailed(double grade) {
return grade < 50;
}
To answer how to tackle this type of questions:
Look for the simplest way. In this case looping for a finite iterations was easier. So I went with the for loop.
The counter is already given, No need to re-calculate it.
If you are working on a computer, write a little code and test it.
Do more questions like these. (if you go through the first chapters of this book these questions will be easy)

Related

How to get average of test scores organized into columns in a file?

The file contains the data in the following format:
Name|Test1|Test2|Test3|Test4|Test5|Test6|Test7|Test8|Test9|Test10
John Smith|82|89|90|78|89|96|75|88|90|96
Jane Doe|90|92|93|90|89|84|97|91|87|91
Joseph Cruz|68|74|78|81|79|86|80|81|82|87
Suzanne Nguyen|79|83|85|89|81|79|86|92|87|88
I am trying to find out how to get the sum of each column (Ex. Test 1 = 82 + 92 + 68 + ...) to ultimately calculate the average score for each test.
This is how I parsed the file and did the other calculations:
public class TestAverages
{
private static int[] grades;
private static int[] testTotal;
private static int N;
private static double classTotal;
public static void main(String[] args) throws FileNotFoundException
{
File input = new File("TestData.txt");
Scanner in = new Scanner(input);
parseFile(in);
}
public static void parseFile(Scanner in) throws FileNotFoundException
{
TestAverages t = new TestAverages();
in.nextLine(); //skips the first line of text in file (labels)
double classAvg =0.0;
while(in.hasNextLine())
{
String line = in.nextLine();
String[] data = line.split("\\|");
String name = data[0];
grades = new int[data.length - 1];
N = grades.length;
for(int i = 0; i < N; i++)
{
grades[i] = Integer.parseInt(data[i + 1]);
}
System.out.println(name);
System.out.println("Student Average: " + t.getStudentAvg(grades) + "%\n");
classAvg = t.getClassAvg(grades);
System.out.println("Test Average: " + t.getTestAvg(grades) + "%\n");
}
System.out.printf("\nClass Average: %.2f%%\n", classAvg );
}
public double getStudentAvg(int[] grades)
{
double total = 0.0;
double avg = 0.0;
int N = grades.length;
for(int i = 0; i < N; i++){
total += grades[i];}
avg = total / N;
return avg;
}
public double getClassAvg(int[] grades)
{
double classTotal = getStudentAvg(grades) / N;
double classAvg =0.0;
classTotal += classTotal;
classAvg = classTotal;
return classTotal;
}
}
Please excuse my formatting if it's not up to par to the standard.
My main issue at the moment is how to extract the score for each test for each student and add everything up.
The test scores for each student are being calculated. What you need are the class average and the test average.
The test averages are the average scores on each test.
The student averages are the average test scores for each student
The class averages is how the overall class did on all the tests.
Consider three tests
test1 test2 test3 student average
student1 90 80 70 240/3
student2 100 90 90 280/3
student3 80 80 90 250/3
testAvg 270/3 250/3 250/3
class avg = (270 + 250 + 250)/9 or (240+280+250)/9
So you need to read in the values in such a way so as to facilitate making the other calculations. I would recommend either a Map<String,List<Integer>> for the data where the string is the students name and the list is the test scores for each student. Or you could use a 2D int array. But you need to save the scores so you can do the column average for the test scores. Most of the work is done.
Also, two problems I noticed. You call the method getTestAvg but don't declare it and you declare the method getClassAvg but never call it.
if you already know that there are 10 test total in the file , it should be easy .
you can let int[] testTotal = new int[10]; for testTotal[0] = sum-of-first-column , testTotal[1] = sum-of-second-column and so on . . .
you can read each line in and split them with "\\|" as regex
as you are cycling through lines , let testTotal[0] += data[1] , testTotal[1] += data[2] . . . testTotal[9] += data[10] since data[0] is the name of the student .

Make a class that represents an average of test scores

Make a class that represents an average of test scores. Make the class take an unlimited number of scores and calculate the number of tests taken along with the average.
I cannot seem to be able to figure out a way to store all the test scores as well as to count the amount of tests from the given file. At the moment this code will only count one of the tests as well as only store the last number given.
This file is given by the instructor and cannot be changed
public class TestScoresDemo {
public static void main(String[] args) {
TestScores t1 = new TestScores("Alice");
TestScores t2 = new TestScores("Bob");
t1.addTestScore(50);
t1.addTestScore(60);
t1.addTestScore(54);
t1.addTestScore(73);
t1.addTestScore(88);
t1.addTestScore(92);
t2.addTestScore(87);
t2.addTestScore(97);
t2.addTestScore(37);
t2.addTestScore(99);
System.out.println("-- Alice --");
System.out.println("Num tests taken: " + t1.getNumTestsTaken());
System.out.println("Average: " + t1.getAverage());
System.out.println("-- Bob --");
System.out.println("Num tests taken: " + t2.getNumTestsTaken());
System.out.println("Average: " + t2.getAverage());
}
}
End of file given by instructor.
The following is what I have so far.
import java.util.Scanner;
public class TestScores {
private String Name;
private double TotalScore;
private int NumScores;
private double Earned;
public TestScores(String name) {
Name = name;
}
public void addTestScore(double earned) {
Earned = earned;
}
public int getNumTestsTaken() {
NumScores = 0;
while (Earned < 100.0) {
NumScores++;
}
return NumScores;
}
public double getAverage() {
try (Scanner scanner = new Scanner(Name)) {
double sum = 0.0;
while (Earned <100.0) {
sum += Earned;
TotalScore = sum / NumScores;
break;
}
return TotalScore;
}
}
}
You aren't using the variable NumScores or TotalScore correctly. Furthermore, you should use the Java naming conventions for variables so change the first letter in the name to a lowercase letter and then use capitol letters, AKA camel case. Try the following
public TestScores(String name) {
this.name = name;
numScores = 0;
totalScore = 0.0;
}
public void addTestScore(double earned) {
totalScore += earned; //add to the running total
numScores++; //add to the count
}
public int getNumTestsTaken() {
return numScores; //simply return the counter
}
public double getAverage() {
return totalScore/numScores; //return the total scores added up divided by the count
}
There are 2 approaches to solve this question, both have been discussed in the comments above:
Use a list / array / collection to store each value
Sum the numbers overtime when new element is added
As your requirement says that TestScores class cannot be changed, then it leaves 1st approach out of the possible solutions1, that makes the only one viable answer the 2nd approach.
But before writing the answer I'll rescue #Turing85's comment
A remark on your overall code design: variable- and field-names should always start with a lowercase letter (private String Name; -> private String name;).
So, your TestScores attributes might become:
private String name;
private double totalScore;
private int numScores;
private double earned;
This will make your program easier to read for you and all of us. Read and follow Java naming conventions.
Now let's see what your program is doing right now:
t1.addTestScore(50); //earned = 50
t1.addTestScore(60); //earned = 60
t1.addTestScore(54); //earned = 54
What you want:
t1.addTestScore(50); //earned = 50
t1.addTestScore(60); //earned = 110
t1.addTestScore(54); //earned = 164
All you have to do (after changing variable names to start with lower case letters) is:
public void addTestScore(double earned) {
this.earned += earned; //This will be adding every number you send to it to the total
this.numScores++; //This keeps track of the number of tests taken
}
Now getNumTestsTaken method might become something like:
public int getNumTestsTaken() {
return numScores;
}
And your getAverage method to become something like this:
public double getAverage() {
return earned / numScores; //We already know the total amount earned as it's stored in "earned" variable and the number of scores stored in "numScores" so, this becomes a simple operation
}
For the rest of the code, I think it's OK.
1 I'm leaving the array / collection out of this answer, but making this answer a community-wiki in case someone wants to add it as well as an answer. However I already explained the reason why this is not suitable here (as per OP's requirements).

School Assignment Multidimensional Array Trouble

I am currently working on an assignment for my Java programming class. I seem to have got myself in a bit of a bind. Any assistance in helping me realize what I am doing wrong would be greatly appreciated.
Assignment
Write a program that does the following:
Put the data below into a multi-dimensional array
Prompts the user for the company they would like employee salary statistics.
Write a method that returns the average employee salary as a double. Pass the company number and employee Wages to this method.
Write a method that returns the total employee salary as an int. Pass the company number and employee Wages to this method.
Write a method that returns the number of employees as an int. Pass the company number and employee Wages to this method.
In the main method call the other methods and out put the results.
Keep in mind that I am still new and struggling to understand some of the principles of programming.
When I run the program I am getting locations instead of method calculations (bad output):
Here is what I have so far:
package salaries;
import java.util.Scanner;
public class Salaries {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//declare, instantiate, and define value of multi array [3] [12]
double [][] mSalary = { { 49920, 50831, 39430, 54697, 41751, 36110,
41928, 48460, 39714, 49271, 51713, 38903},
{ 45519, 47373, 36824, 51229, 36966, 40332,
53294, 44907, 36050, 51574, 39758, 53847},
{ 54619, 48339, 44260, 44390, 39732, 44073,
53308, 35459, 52448, 38364, 39990, 47373}};
//declare, instantiate, and define value
//of single array for company names
//and output values to user for selection
String [] company = { "Alhermit", "Logway", "Felter" };
for( int i = 0; i < company.length; i++ )
System.out.println( "Company " + i + " : " +company[i] );
Scanner scan = new Scanner( System.in );
int cCompany;
do{
//ouput for user to select a company
System.out.print("Select company: (0)" +company[0]+ ", (1)"
+company[1]+ "; (2)" +company[2]+ " > ");
//scan user input into cCompany
cCompany = scan.nextInt();
//call number method
num nums = new num();
nums.number(mSalary, cCompany);
//call total method
total sum = new total();
sum.total(mSalary, cCompany);
//call average method
avg cAvg = new avg();
cAvg.average(mSalary, cCompany);
//output statistics to user on selected company
System.out.println( "You have selected the company " + company[cCompany] + ". " );
System.out.println( company[cCompany] + " has " + nums + " of employees." );
System.out.println( "A total employee salary of " + sum + "." );
System.out.println( "The average employee salary is " + cAvg );
}
while( cCompany < 0 || cCompany > 2);
}
}
//total class to calculate
//salary of user selected company
class total {
public static int total( double [][] mSalary, int cCompany ){
//assign variables
int sum = 0;
//for loop to calculate salary total of user input company
for( int j = 0; j < mSalary[cCompany].length; j++ ){
sum += mSalary[cCompany][j];
}
//return statement
return sum;
}
}
//average class to calculate
//average of user selected company
class avg {
public static double average( double [][] mSalary, int cCompany){
//assign variables
int cAvg = 0;
int sum = 0;
int count = 0;
//totals the values for the selected company by
//iterating through the array with count.
while( count < mSalary[cCompany].length){
sum += mSalary[cCompany][count];
count +=1;
}
cAvg = sum / mSalary[cCompany].length;
return cAvg;
}
}
//number class to calculate amount of
//employees in user selected company
class num {
public static int number( double [][] mSalary, int cCompany){
//assign variables
int nums = 0;
//number of employees based on length of colomn
nums = mSalary[cCompany].length;
return nums;
}
}
nums, sum, and cAvg are all instances of classes that you have, you're printing out the instances of those classes.
(By the way - you should change the name of these classes. Classes start with a capital letter. It differentiates them from variables.)
There are two things wrong with this.
You are instantiating a class which contains no data and has no toString method.
You're instantiating a class which only has static methods to return the data from. You don't need to instantiate the class at all; instead, just print the result of the method call.
That would change at least one of these calls to something like:
System.out.println( company[cCompany] + " has " + num.number(mSalary, cCompany); + " of employees." );
I leave the rest as an exercise for the reader.

Calculating Avg, Max, and Min using a .txt input file with both integers and strings mixed

Please help. I've looked everywhere and am stumped on how to finish this program. I need to calculate the average, max, and min from a data input file. They need to look like this:
System.out.println("The average total score of the class is: " + total/27);
System.out.println(maxName + "got the maximum score of: " + maxVal);
System.out.println(minName + "got the maximum score of: " + minVal);
For the average I don't know why the while loop in my main isn't working. It calculates a value of zero. I also don't know how I can make it so the 27 isn't hard coded. For the max and min values, I have no clue about those. i don't even have a guess. A lot of things I've looked at for these use ways we haven't been taught (like a buffered something for instance, or using the Collections class which we haven't learned about that either. I just need a basic way of accomplishing these. I will include everything I have so far. Any help is appreciated. Thank you.
Input File:
9
Andy Borders
200
250
400
John Smith
120
220
330
Alvin Smith
225
300
278
Mike Borell
250
250
500
Jim Jones
325
325
155
Robert Fennel
200
150
350
Craig Fenner
230
220
480
Bill Johnson
120
150
220
Brent Garland
220
240
350
Main:
import java.util.Scanner;
import java.io.*;
public class Project5 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter the file name: ");
String fileName = in.nextLine();
try {
File file = new File(fileName);
Scanner inputFile = new Scanner(file);
String SnumStudents = inputFile.nextLine();
int numStudents = Integer.parseInt(SnumStudents);
Student [] studentList = new Student[numStudents];
for (int i = 0; i < numStudents; i++)
{
String line = inputFile.nextLine();
String score1 = inputFile.nextLine();
String score2 = inputFile.nextLine();
String score3 = inputFile.nextLine();
studentList [i] = new Student(line, Integer.parseInt(score1), Integer.parseInt(score2), Integer.parseInt(score3));
}
System.out.println("Name\t\tScore1\tScore2\tScore3\tTotal");
System.out.println("---------------------------------------------");
for (int i=0; i< studentList.length;i++){
System.out.println(studentList[i].getName() + "\t" + studentList[i].getScore1() + "\t" + studentList[i].getScore2() + "\t" + studentList[i].getScore3() + "\t" + studentList[i].getTotal());
}
System.out.println("---------------------------------------------");
System.out.println("The total number of students in this class is: " + studentList.length);
int total = 0;
while (inputFile.hasNextInt())
{
int value = inputFile.nextInt();
total = total + value;
}
System.out.println("The average total score of the class is: " + total/27);
System.out.println(maxName + "got the maximum score of: " + maxVal);
System.out.println(minName + "got the maximum score of: " + minVal);
inputFile.close();
} catch (IOException e) {
System.out.println("There was a problem reading from " + fileName);
}
finally {
}
in.close();
}
}
Student Class:
public class Student {
private String name;
private int score1;
private int score2;
private int score3;
private int total;
private double average;
public Student(String n, int s1, int s2, int s3){
name = n;
score1 = s1;
score2 = s2;
score3 = s3;
total = s1 + s2 + s3;
}
public String getName(){
return name;
}
public int getScore1(){
return score1;
}
public int getScore2(){
return score2;
}
public int getScore3(){
return score3;
}
public int getTotal(){
return total;
}
public double computeAverage(){
return average;
}
}
Your while loop is never getting executed. By the time you finish reading lines of the file in your for loop, there are no more lines of the file to consume. So, inputFile.hasNextInt() is never true.
The 27 is hard-coded because of the line
System.out.println("The average total score of the class is: " + total/27);
You need to change the 27 here to some variable that will represent the total number of scores.
You are storing all of the scores for each person. To find the min (max) you just need to go through each of the values and find the smallest (largest) one and store them.

Novice at Java. Loop to enter height of people and find tallest

I am studying loops and am attempting a sample question here to use only a loop to ask the user to enter in the name of the person, height in feet first, then inches and then to find the tallest. I understand how to do the majority of it.
Could anyone point out where I am going wrong? I began writing the code and realised that I can't declare the persons names without knowing how many people the user will enter. I can't get my head around it.
I want to prompt the user with the questions but also update it to person [2], person [3], person [4] etc. depending on how many people they entered in initially.
Apologies for not wording this correctly. Any help is appreciated. I understand lines 10, 11 and 12 are probably wrong.
class HeightTest
{
public static void main(String[] args)
{
int noOfPeople;
int index;
int feet;
int inches;
String personOne;
String personTwo;
String personThree;
System.out.print("Enter a number of people ");
noOfPeople = EasyIn.getInt();
for (index = 1; index <=noOfPeople; index++)
{
System.out.println("Enter the name of person " + index);
personOne = EasyIn.getString();
System.out.println("Enter feet portion for " + personOne);
feet = EasyIn.getInt();
System.out.println("Enter inches portion for " + personOne);
inches = EasyIn.getInt();
}
}
}
You have a very good start. All you need to do now is keep track of the heights that are entered, and compare them to the largest one input so far. If the height for the current loop iteration is larger than the current largest, store it as the largest.
In pseudocode:
int largestHeightInches = 0;
for( i = 1; i <= noOfPeople; index++ ) {
currentHeightFeet = GetInt();
currentHeightInches = GetInt();
currentHeight = currentHeightInches + currrentHeightFeet * 12;
if( largestHeightInches < currentHeight ) {
largestHeightInches = currentHeight;
}
}
You would have to create an array of Persons to acheive what you want.
Here's a snippet.
Create a class called Person
public class Person
{
int index;
int feet;
int inches;
String name;
}
create a main Test class to contain your main method, and do something like this
public class Main{
public static void main (String[] args)
{
// get the number of people in noOfPeople as you do now.
Person[] pArray= new Person[nOfPeople]
for(Person p: pArray)
{
System.out.println("Enter the name of person " + index);
p.name = EasyIn.getString();
// ...etc
}
}
}

Categories

Resources