Reading in from a file and adding to 2D array - java

I have two different programs, one which contains a method "addGrade" designed to add a new grade to a 2D array (gradeTable). One array of the 2D array is the category each grade should be in, and the second element is the grades for each category. Here is that program:
public class GradeBook {
private String name;
private char[] categoryCodes;
private String[] categories;
private double[] categoryWeights;
private double[][] gradeTable;
public GradeBook(String nameIn, char[] categoryCodesIn,
String[] categoriesIn, double[] categoryWeightsIn) {
name = nameIn;
categoryCodes = categoryCodesIn;
categories = categoriesIn;
categoryWeights = categoryWeightsIn;
gradeTable = new double[5][0];
}
public boolean addGrade(String newGradeIn) {
char row = newGradeIn.charAt(0);
int grade = Integer.parseInt(newGradeIn.substring(1));
double[] oldArr = gradeTable[row];
double[] newArr = Arrays.copyOf(oldArr, oldArr.length + 1);
newArr[newArr.length - 1] = grade;
gradeTable[row] = newArr;
return row != 0;
}
The second program reads in a file as a command argument. The bolded text represents the grades being read in. The letter stands for that category each grade should be in, and the number is the actual grade. The file is
Student1
5
a Activities 0.05
q Quizzes 0.10
p Projects 0.25
e Exams 0.30
f Final 0.30
**a100 a95 a100 a100 a100
q90 q80 q100 q80 q80 r90
p100 p95 p100 p85 p100
e77.5 e88
f92**
In the second program, I'm trying to loop through each grade in the file and call the addGrade method on it so it will be added to the 2D array. I'm unsure of how to call the method for each individual grade. Also, I'm pretty sure my addGrade method isn't right. Any help would be appreciated. This is the second program:
public class GradeBookApp {
String fileName = "";
String name = "";
char[] categoryCodes = new char[5];
String[] categories = new String[5];
double[] categoryWeights = new double[5];
double[][] gradeTable;
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
System.out.println("Reading file \"" + args[i] + "\"."
+ "\n\tCreating GradeBook object."
+ "\n\tAdding grades to GradeBook object."
+ "\nProcessing of file complete.");
fileName = args[i];
Scanner scanFile = new Scanner(new File(fileName));
name = scanFile.nextLine();
int catCodes = Integer.parseInt(scanFile.nextLine());
for (i = 0; i < catCodes; i++) {
String[] all = scanFile.nextLine().split(" ");
if(all.length == 3 && all[0].length() == 1 && all[2].matches("(\\d+\\.\\d+)")){
categoryCodes[i] = all[0].charAt(0);
categories[i] = all[1];
categoryWeights[i] = Double.parseDouble(all[2]);
}
}
GradeBook myGB = new GradeBook (name, categoryCodes,
categories, categoryWeights);

You'd be better off with having each list of grades as an ArrayList<Double> rather than a double[]. It's very hard work on the JVM (and on the programmer!) having to copy the whole array each time so that you can increase its length and add a new one. If you use an ArrayList<Double> gradeList, then you can just
gradeList.add(grade);
without needing to do all the copying.
I would also consider having the larger structure as a Map rather than an array. So rather than having a two-dimensional array, you could have a HashMap<Character,List<Double>> that maps the row onto the list of grades for that row. That avoids having to convert between characters and doubles, which you're currently (implicitly) doing.
Finally, the addGrade() method ought to take a char and a double (a row and a new grade), rather than a String: you're making a lot of work for yourself with having to process inappropriate data structures.
Once you've done this, calling addGrade for each item should be fairly easy. Once you've extracted a String representing a particular grade (say, String gr = "e77.5") then you can add to the list inside your HashMap gradeMap like this:
char row = gr.charAt(0);
double grade = Double.parseDouble(gr.substring(1));
gradeMap.get(row).add(grade);
I think you'll need to supply more info if you need more help than that.

You stated that you need to read from a file, but none of your code is actually reading from a file. This should be your first step. Try looking at BufferedReader documentation as well as numerous posts on this site regarding proper methods to perform file IO operations.
I'm assuming your storing your grades in the 2D gradeTable array like: {Category, grade}. You will need to read each row in your file(BufferedReader has methods for this), parse the string (Look at the String documentation, specifically split or substring/indexOf methods) into category and grade, and then populate your array.
Look into using more dynamic data structures, such as ArrayList. This will allow you to expand the size as you add more grades, as well as not having to copy your array into a new array every time the size expands.

Related

Way to scan contents of a singular array index?

There is an array in my code that includes the names to random items delimited by a /n (i think). the splitLines[] array is an organizational method that collects strings and integers separated by a delimiter in a file. The file is formatted as
<<Prize’s Name 0>>\t<<Prize’s Price 0>>\n
<<Prize’s Name 1>>\t<<Prize’s Price 1>>\n
My goal is to assign each line in the contents of splitLines[0] and splitLines[1] to its own index in separate arrays. The splitLines[0] array is formatted as
<<Prize's Name 0>>/n
<<Prize's Name 1>>/n
and the splitLines[1] array is formatted as
<<Prize's Price 0>>/n
<<Prize's Price 1>>/n
The process here is messy and convoluted, but as I am still learning the inner workings of arrays (and java as a language), I have yet to find a way that successfully reads through the array index and picks out each and every word and assigns it to another array. So far I have tried setting up a Scanner that takes splitLines[] as a parameter, but I am unsure whether fileScanner.next{Int,Line,Double, etc.}() is capable of reading into the array index at all. I am unsure how to proceed from here. Here is the block that I have so far
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.Math;
public class DrewCarey {
public static void main(String[] args) throws FileNotFoundException {
{
int min = 0;
int max = 52;
int randomIndex = (int)Math.floor(Math.random()*(max-min+1)+min);
String[] aPrize = new String[53];
int[] aPrice = new int[53];
final String DELIM = "\t";
Scanner fileScanner = new Scanner(new File("PrizeFile.txt"));
String fileLine = fileScanner.nextLine();
String[] splitLines = fileLine.split(DELIM);
String temp = "drew";
while(fileScanner.hasNextLine())
{
for(int i=0;i<aPrize.length;i++)
{
fileLine = fileScanner.nextLine();
splitLines = fileLine.split(DELIM);
if(fileLine.split(DELIM) != splitLines)
{
// String name = splitLines[0];
// int price = Integer.parseInt(splitLines[1]);
//splitLines[0] = aPrize[i];
// price = aPrice[i];
System.out.println(splitLines[0]);
// splitLines[0] = temp;
// splitLines[1] = temp;
}
}
}
fileScanner.close();
} ```
Your file/data is formatted in a very strange way which will cause all manner of issues, also are you splitting with "\n" or "/n" it is conflicting in your question. You should NOT use "\n" for the split because it is confused with an actual JAVA newline chracter. So assuming the file data is a single line that looks like this with "/n" and "/t":
<<Prize’s Name 0>>/t<<Prize’s Price 0>>/n <<Prize’s Name 1>>/t<<Prize’s Price 1>>/n <<Prize’s Name 2>>/t<<Prize’s Price 2>>/n <<Prize’s Name 3>>/t<<Prize’s Price 3>>/n <<Prize’s Name 4>>/t<<Prize’s Price 4>>
Then you can correctly split the first line of the file as shown below. The biggest problem in your code is that you only split with the "t" DELIM, never with the "n" delim. The below code solves this problem by splitting with "/n" first, then we split the resulting line with the "/t" and simply assign each part of the split to the aPrize and aPrice array.
//Add "\n" delim
final String DELIM_N = "/n ";
final String DELIM_T = "/t";
//We will use two string arrays in this demo for simplicity
String[] aPrize = new String[53];
String[] aPrice = new String[53];
Scanner fileScanner = new Scanner(new File("PrizeFile.txt"));
//Get first line
String fileLine = fileScanner.nextLine();
//Split line with "/n"
String[] splitLines = fileLine.split(DELIM_N);
//loop through array of split lines and save them in the Prize and Price array
for (int i = 0; i < splitLines.length; i++)
{
//Split each itom with "/t"
String[] splitItems = splitLines[i].split(DELIM_T);
//Check that each line does not have unexpected items
if (splitItems.length > 2)
{
System.out.println("Unexpected items found");
}
else
{
//Insert your code here to clean the input and remove the << and >> around items and parse them as an int etc.
//Assign the items to the array
//index 0 is prize
aPrize[i] = splitItems[0];
//and index 1 is price
aPrice[i] = splitItems[1];
}
}
//Complete. Print out the result with a loop
System.out.println("File read complete, Data split into two arrays:");
for (int i = 0; i < 10; i++)
{
System.out.println("Prize at index "+ i +" is: " + aPrize[i]);
System.out.println("Price at index "+ i +" is: " + aPrice[i]);
}
The output is as follows:
File read complete, Data split into two arrays:
Prize at index 0 is: <<Prize’s Name 0>>
Price at index 0 is: <<Prize’s Price 0>>
Prize at index 1 is: <<Prize’s Name 1>>
Price at index 1 is: <<Prize’s Price 1>>
...
I didn't understand your concern completely.
Try using ArrayList implementation of List instead of array.
Example:
List<String> aPrice = new ArrayList<>();
aPrice.add("some string");
You cant add more elements to array. ArrayList internally uses array,
but has methods to extend the number of elements stored.
You can retrieve elements by index as well.
You can use Arrays.asList() method to convert array to list if required.
You can check out the docs for more : ArrayList Documentation

how to print Scanner element using parallel arrays in java?

I am new to learning about parallel arrays and want to know how to effectively print content/elements using parallel array only, I tried but couldn't get it to work and function the way I want.
The task is: The program inputs an integer from the user representing how many peoples’ information will be entered. Then, the program inputs the information one person at a time (name first, then age), storing this information in two related arrays.
Next, the program inputs an integer representing the person on the list whose information should be displayed (to get information for the first person, the user would enter ‘1’). The program makes a statement about the person’s name and age.
Although I got the name and age to work until the integer the user inputs, but after that I am not sure how to do
Sample input:
4
Vince
5
Alexina
8
Ahmed
4
Jorge
2
2 // I am confused about this part, how would I make it so that it prints the desired name,
//for example with this input, it should print:
Sample output:
Alexina is 8 years old
My code:
import java.util.Scanner;
class Example {
public static void main (String[] args) {
Scanner keyboard = new Scanner(System.in);
int[] numbers = new int[keyboard.nextInt()];
for (int x = 0; x < num.length; x++){
String[] name = {keyboard.next()};
int[] age = {keyboard.nextInt()};
}
int num2 = keyboard.nextInt();
System.out.println(); // what would I say here?
}
}
You need to rewrite your code so your arrays aren't being assigned within the loop. You want to add values to the arrays, not reset them each time, and you want to be able to access them afterwards. Below is a modified version of your code:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int num = keyboard.nextInt();
keyboard.nextLine(); //you also need to consume the newline character(s)
String[] name = new String[num]; //declare the arrays outside the loop
int[] age = new int[num];
for (int x = 0; x < num; x++){
name[x] = keyboard.nextLine(); //add a value instead of resetting the array
age[x] = keyboard.nextInt();
keyboard.nextLine(); //again, consume the newline character(s) every time you call nextInt()
}
int num2 = keyboard.nextInt() - 1; //subtract one (array indices start at 0)
System.out.println(name[num2] + " is " + age[num2] + " years old"); //construct your string with your now-visible arrays
}
As I think you have to think about the local and global variable usage in java.In brief,
Local variables can only use within the method or block, Local variable is available only to method or block in which it is declared.
For example:
{
int y[]=new Int[4];
}
this y array can be accessed within the block only.
Global Variable has to be declared anywhere in the class body but not inside any method or block. If a variable is declared as global, it can be used anywhere in the class.
In your code you try to create arrays and use them out of the For loop. But your arrays are valid only inside the For loop. After every loop runs all info is lost.there will be new array creation for every iteration of For loop.
therefore, In order to access and save the information you have to declare your arrays before the For loop and access and store data using iteration number as the index. finally, to print the data you gathered, you have to scan new input as integer variable.then you can access your arrays as you wanted.
//For example
int [] age=new int[4]; //global -Can access inside or outside the For loop
int[] numbers = new int[keyboard.nextInt()];
for (int x = 0; x < 4; x++){
age[x] = keyboard.nextInt(); //Local
}
int num2 = keyboard.nextInt();
System.out.println(age[num2]); // Here you have to access global arrays using num2 num2
}
}

Java - Transferring Data from txt file into arrays

I am currently trying to work on a program that uses student ID's and GPA's (taken from a txt file) and uses these to do numerous other things like categorize the students into 1 of 8 categories based on GPA ranges, make a histogram of the students in each group, and also rank the students by GPA. The first thing I need to do however is transfer the student ID's and GPA's into two separate arrays.
I know the syntax for creating an array is as follows:
elementType[] arrayRefVar = new elementType[arraySize]
However, I still don't know how to pass the data that is read from the file into two separate arrays. The code I have to read the data from the txt file is as follows:
public static void main(String[] args) throws Exception // files requires exception handling
{
String snum;
double gpa;
Scanner gpadata = new Scanner(new File("studentdata.txt"));
while (gpadata.hasNext()) // loop until you reach the end of the file
{
snum = gpadata.next(); // reads the student's id number
gpa = gpadata.nextDouble(); // read the student's gpa
System.out.println(snum + "\t" + gpa); // display the line from the file in the Output window
}
}
So my question is: how do I pass this information into two separate arrays? I apologize if my question is hard to understand, I am extremely new to programming. I have been stumped on this program for a long time now, and any help would be extremely appreciated! Thank you.
You can create two arrays before the while loop, and then add each element inside the loop to each array. But there is one problem with this approach: we don't know the number of values, thus we cannot create a fixed-sized array for this. I suggest to use ArrayList instead, which can grow as needed. Something like this:
public static void main(String[] args) throws FileNotFoundException {
Scanner gpadata = new Scanner(new File("studentdata.txt"));
List<String> IDs = new ArrayList<>();
List<Double> GPAs = new ArrayList<>();
while (gpadata.hasNext()) // loop until you reach the end of the file
{
String snum = gpadata.next(); // reads the student's id number
double gpa = gpadata.nextDouble(); // read the student's gpa
IDs.add(snum);
GPAs.add(gpa);
System.out.println(snum + "\t" + gpa); // display the line from the file in the Output window
}
// Use IDs and GPAs Lists for other calculations
}
A more better approach to use a Map to "pair" a GPA to a Student ID.
Edit:
After you clarified that the max record number never be more than 1000, I modified my solution to use arrays instead of Lists. I didn't change the variable names so you can compare the solutions easily.
public static void main(String[] args) throws FileNotFoundException {
Scanner gpadata = new Scanner(new File("studentdata.txt"));
String[] IDs = new String[1000];
double[] GPAs = new double[1000];
int counter = 0;
while (gpadata.hasNext()) // loop until you reach the end of the file
{
String snum = gpadata.next(); // reads the student's id number
double gpa = gpadata.nextDouble(); // read the student's gpa
IDs[counter] = snum;
GPAs[counter] = gpa;
System.out.println(snum + "\t" + gpa); // display the line from the file in the Output window
counter++;
}
// Use IDs and GPAs Lists for other calculations
}
Note that we need a counter (aka. index) variable to address the array slots.

Storing strings in arrays and splitting strings

I'm having a Java issue on a uni assignment. We've been given a file that has a set of information listed as such (there's more, this is just a formatting example):
57363 Joy Ryder D D C P H H C D
72992 Laura Norder H H H D D H H H
71258 Eileen Over C F C D C C C P
For the life of me, I can't work out how to store this in an array, AND I need it split because the letters need to be converted to a number and averaged, which will then need to be stored into a second array.
I'm new-ish to Java, so a lot of the types of things that require an import at the start of the code are unknown to me, so explaining the code changes in any replies would be greatly appreciated. The code I have so far is as follows:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class StudentGPA_16997761 {
public static void main(String[] args) throws FileNotFoundException {
Scanner kb = new Scanner(System.in);
//get file
System.out.print("Please enter the name of the file containing student information: ");
String gradeFile = kb.next();
Scanner grades = new Scanner(new File(gradeFile));
if (new File(gradeFile).exists()) {
while (grades.hasNextLine()) {
System.out.println(grades.nextLine());
}
}
//student identification number, a first name, a surname, then 8 individual alphabetic characters that represent the
//unit grades for the student. Hence, each line of data in the text file represents a student and the grades
//they achieved in 8 units of study
//need to make array to hold student information
//need to make array that holds student id and GPA
}
}
I know that it works, as the System.out.println prints out the lines as I expected them to be read, but I can't figure out how to store them. I think I miiight be able to get the split working, but that'll still need the array/arraylist first...
You can split a string into an array using a delimiter. In your example, if all first and last names do not contain spaces themselves, you can do the following:
while (grades.hasNextLine()) {
String line = grades.nextLine();
String[] parts = line.split(" ");
// get the basics
String id = parts[0];
String firstname = parts[1];
String lastname = parts[2];
// extract the grades
int size = parts.length - 3;
String[] gradelist = new String[size];
System.arraycopy(parts, 3, gradelist, 0, size);
// do something with the grades
}
Java is especially good at OOP - Object Oriented Programming. Each line of your input file is a student, which is a perfect example of an object you can define. Let's define a Student class that holds the desired information:
public class Student{
public final int ID;
public final String name;
private LinkedList<Character> grades;
private double grade;
public Student(int i; String n, String[] g){
ID = i;
name = n;
grades = new LinkedList<Character>();
for(String s : g){
grades.add(s.charAt(0));
}
//Do parsing to turn a list of letters into a grade here...
}
public double getGrade(){
return grade;
}
}
Then you can construct students to store the information as you read it. Put this where your current while loop is in your given code.
LinkedList<Student> students = new LinkedList<Student>();
while (grades.hasNextLine()) {
String[] line = grades.nextLine().split("\\s");
Student s = new Student(Integer.parseInt(line[0]),
line[1] + " " + line[2],
Arrays.copyOfRange(line, 3, line.length));
students.add(s);
}
Then do work on students as necessary.

Inventory Array

I'm working on a program that acts as a type of book store inventory. The program reads in a list of information from a text file that looks like this:
1234567 31.67 0
1234444 98.50 4
1235555 27.89 2
1235566 102.39 6
1240000 75.65 4
1247761 19.95 12
1248898 155.91 0
1356114 6.95 17
1698304 45.95 3
281982X 31.90 5
The first number represents the ISBN number and is the type String, the second number is the price and is type double, and the final number is the number of copies in stock and is an int.
The program is supposed to read in this information, storing it into an array (more steps follow, but this is the first thing I'm having trouble with).
The code I have so far looks like this:
import java.util.Scanner;
import java.io.*;
public class Store {
public static void main(String[] args) {
String[] books = new String[15];
String product;
readInventory();
}
public static void readInventory() {
java.io.File file = new java.io.File("../instr/prog4.dat");
Scanner fin = new Scanner(file);
String isbn;
double price;
int copies;
String[] books = new String[14];
while (fin.hasNext()) {
isbn = fin.next();
price = fin.nextDouble();
copies = fin.nextInt();
}
}
}
I'm having trouble figuring out how to store these three different pieces of information into a single line (for each item like is depicted in the file) in a single dimensional array.
One thought I had was to created something like this,
String product = (isbn + price + copies);
And then try to add this to the array like,
String[] books = product;
But as I'm sure you can probably sport, this didn't work. Any suggestions would be greatly appreciated. I'm still really new to this and it's been a while since I've worked with arrays.
I'm having trouble figuring out how to store these three different pieces
of information into a single line
How about using nextLine()
String[] books = new String[14];
int index = 0;
while (fin.hasNextLine()) {
books[index] = fin.nextLine();
index++;
}
From there you can pull out each String and split it around the spaces
String[] parts = books[0].split(" ");
Now you can cast each part to its respective type
String isbn = parts[0];
double price = Double.parseDouble(parts[1]);
int numberInStock = Integer.parseInt(parts[2]);
Beware this is a long way around and will cause problems if your file contains variable amounts of books. Also, to do this for all books will require some loops.

Categories