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.
Related
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.
I working on a project that is based on reading a text from a file and putting it as objects in my code.
My file has the following elements:
(ignore the bullet points)
4
Christmas Party
20
Valentine
12
Easter
5
Halloween
8
The first line declares how many "parties" I have in my text file (its 4 btw)
Every party has two lines - the first line is the name and the second one is the number of places available.
So for example, Christmas Party has 20 places available
Here's my code for saving the information from the file as objects.
public class Parties
{
static Scanner input = new Scanner(System.in);
public static void main(String[] args) throws FileNotFoundException
{
Scanner inFile = new Scanner(new FileReader ("C:\\desktop\\file.txt"));
int first = inFile.nextInt();
inFile.nextLine();
for(int i=0; i < first ; i++)
{
String str = inFile.nextLine();
String[] e = str.split("\\n");
String name = e[0];
int tickets= Integer.parseInt(e[1]); //this is where it throw an error ArrayIndexOutOfBoundsException, i read about it and I still don't understand
Party newParty = new Party(name, tickets);
System.out.println(name+ " " + tickets);
}
This is my SingleParty Class:
public class SingleParty
{
private String name;
private int tickets;
public Party(String newName, int newTickets)
{
newName = name;
newTickets = tickets;
}
Can someone explain to me how could I approach this error?
Thank you
str only contains the party name and splitting it won't work, as it won't have '\n' there.
It should be like this within the loop:
String name = inFile.nextLine();
int tickets = inFile.nextInt();
Party party = new Party(name, tickets);
// Print it here.
inFile().nextLine(); // for flushing
You could create a HashMap and put all the options into that during your iteration.
HashMap<String, Integer> hmap = new HashMap<>();
while (sc.hasNext()) {
String name = sc.nextLine();
int tickets = Integer.parseInt(sc.nextLine());
hmap.put(name, tickets);
}
You can now do what you need with each entry in the HashMap.
Note: this assumes you've done something with the first line of the text file, the 4 in your example.
nextLine() returns a single string.
Consider the first iteration, for example, "Christmas Party".
If you split this string by \n all you're gonna get is "Christmas Party" in an array of length 1. Split by "blank space" and it should work.
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.
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.
I was trying to implement a java program to process user input from command line.The problem was one given in Algorithms book (sedgewick)
1.1.21 Write a program that reads in lines from standard input with each line contain- ing a name and two integers and then uses printf()
to print a table with a column of the names, the integers, and the
result of dividing the first by the second, accurate to three decimal
places. You could use a program like this to tabulate batting averages
for baseball players or grades for students.
I tried to implement this as follows..but I am stuck in storing the user input sothat it can be printed using printf() ..I thought Scanner would be appropriate for getting the user input..Still I can't seem to get the input stored for later use.
The class Stack is from sedgewick's book.
Any idea how to get this right?
Scanner input = new Scanner(System.in);
Stack st = new Stack();
while(input.hasNext()){
String tkn = input.next();
st.push(tkn);
if (st.size()==3){
int y = Integer.parseInt((String)st.pop());
int x = Integer.parseInt((String)st.pop());
String name = (String)st.pop();
System.out.println("name="+name+",x="+x+",y="+y);
}
}
By using the st.pop() it will remove and return the last item of the stack. If you dont want it to get removed you can use one ordered Collection like ArrayList and access the item by list.get or using an Iterator.
Another suggestion is to create one object to store the name and the y, x properties:
class MyObject {
private String name;
private int x;
private int y;
//... setter and getter methods for the properties
}
Suggestion for your code: it pushes the input in the Stack, then pop the items to create the MyObject and add to the list:
ArrayList listObjects = new ArrayList();
Scanner input = new Scanner(System.in);
Stack st = new Stack();
while(input.hasNext()){
String tkn = input.next();
st.push(tkn);
if (st.size()==3){
int y = Integer.parseInt((String)st.pop());
int x = Integer.parseInt((String)st.pop());
String name = (String)st.pop();
//create and add the object to the list for further use
listObjects.add(new MyObject(name, x, y));
System.out.println("name="+name+",x="+x+",y="+y);
}
}