java problem (read file and create objects) - java

I have a java problem I need to do and i'm not sure how to do it. This is the problem:
Your task is to complete the given program by writing a method named readData and a class named Person.
The readData method is written inside the Customers class. The purpose of the program is to read customer
information from a file called customers.txt, make a new object out of each customer and finally print the information of all customers on the screen.
In the file, each customer is stored on its own line. The file contains the name and social security number of each customer. The Person class has one String-type attribute that stores the person's information (name and social security number).
A toString method must be written inside the Person class, which returns the person's information. The readData method gets an array as a parameter in which the created persons are placed. The purpose of the method is to create an object out of each customer in the file and place it into the array. The method returns the number of people in the file.
That's the instruction (above) and below is the pre-made code that I can't edit (except after the "your code here" part):
import java.io.*;
import java.util.*;
import java.util.Scanner;
public class Customers {
public static void main(String[] args) throws IOException {
Person[] people = new Person[100];
int peopleAmount = readData(people);
for(int i = 0; i < peopleAmount; i++) {
System.out.println(people[i]);
}
}
// Your code here
Example output:
James 030377-2651
John 111177-1731
Robert 161280-1822
Michael 121160-1362
William 141075-16
If too busy to give a full answer, some info on how to make it is fine too. The instruction text wasn't in english originally so sorry if it has weird grammar.

Assuming that the contents of file customers.txt is the same as the example output in your question, here is my implementation. I'm guessing that you can only use classes that you have learned about and I'm also guessing that you have not yet learned about the stream API in java so hopefully the below code is acceptable within the limitations of your assignment.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Customers {
private static int readData(Person[] people) throws IOException {
int count = 0;
if (people != null && people.length > 0) {
try (FileReader fr = new FileReader("customers.txt");
BufferedReader br = new BufferedReader(fr)) {
String line = br.readLine();
while (line != null) {
String[] parts = line.split(" ");
Person p = new Person(parts[0], parts[1]);
people[count] = p;
count++;
if (count >= people.length) {
break;
}
line = br.readLine();
}
}
}
return count;
}
public static void main(String[] args) throws IOException {
Person[] people = new Person[100];
int peopleAmount = readData(people);
for(int i = 0; i < peopleAmount; i++) {
System.out.println(people[i]);
}
}
}
class Person {
String name;
String ssn;
public Person(String name, String ssn) {
this.name = name;
this.ssn = ssn;
}
public String toString() {
return name + " " + ssn;
}
}
Method readData must be a static method since it is called from method main which is a static method.
Method readData reads file customers.txt line by line. Each line contains a name followed by a single space and followed by a social security number. According to your example output both name and social security number contain no spaces. If that is not the case, then the above code will not work.
Method split will create a two element array from a line of the file. The first array element is the name and the second is the social security number. Then I create a Person object and place it in the people array.

Related

Why am I getting Exception in thread error?

I am trying to make this program That uses the scanner method. A user would type their name, then the ScannerToolclass would store that information into the guess string varible. An Object is created in the portation class as ScannerTool cool = new ScannerTool(); for both the justPoints() and post() methods. The portation class takes the objects and store what the user types into a String variable called hope as String hope = cool.scannerT() it then takes what the user types and executes an if statement. I create an object for the portation class and ScannerTool inside the MainTest and then I run it from MainTest class.
My problem is that when I run this program it throws an exception error:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at ScannerTool.scannerT(ScannerTool.java:7)
at portation.justPoints(portation.java:12)
at MainTest.main(MainTest.java:20)
However, when i dont use the portation class and just go from ScannerTool to MainTest with the same code from portation it works. The weird part is that when I do it the original way there are no errors presented at the lines, only when I execute the whole program
What I tried: I tried to change the return types in the methods in portation from int and string to void, that didn't work. I tried looking at the lines that said where the error occured, but that didn't help becuase everything looked correct. Since it's not throwing actual errors on the IDE before running i'm at a loss.
the code:
The code that works:
MainTest
public class MainTest {
public static void main(String [] args) {
ScannerTool scan = new ScannerTool();
//portation damn = new portation ();
System.out.print("What your name my guy? ");
String hope = scan.scannerT();
int points = 0; // taken from the portation class
if (hope.equals("chris")){
points = points + 1;
}else {
points = 0;
}
System.out.println("the name " + hope + " is cool");
if(hope.equals("chris")) {
System.out.println("for your name being chris I award you one point!");
}else {
System.out.println("but, you get no points for that name");
} //taken from the portation class
System.out.println(points);
//damn.post();
//damn.justPoints();
}
}
portation: not in use
ScannerTool:
import java.util.*;
public class ScannerTool {
public String scannerT() {
Scanner message = new Scanner(System.in); //User input
String guess = message.nextLine(); // storing what the user inputted in a string variable
message.close(); //closed the scanner object
return guess; // returned user input
}
}
the code that doesn't work
MaintTest:
public class MainTest {
public static void main(String [] args) {
ScannerTool scan = new ScannerTool();
portation damn = new portation ();
System.out.print("What your name my guy? ");
String hope = scan.scannerT();
damn.post();
damn.justPoints();
}
}
portation:
public class portation {
public void justPoints() {
ScannerTool cool = new ScannerTool(); // created an object from the ScannerTool
String hope = cool.scannerT(); //stored the ScannerTool answer the user inputed from the guess string
int points = 0; //setup the points variable
if (hope.equals("chris")){
points = points + 1;
}else {
points = 0;
}
System.out.println(points);
}
public void post() {
ScannerTool cool = new ScannerTool(); // created an object from the ScannerTool
String hope = cool.scannerT(); //stored the ScannerTool answer the user inputed from the guess string
System.out.println("the name " + hope + " is cool"); //printed what the user typed
if(hope.equals("chris")) {
System.out.println("for your name being chris I award you one point!");
}else {
System.out.println("but, you get no points for that name");
}
}
}
ScannerTool:
import java.util.*;
public class ScannerTool {
public String scannerT() {
Scanner message = new Scanner(System.in); //User input
String guess = message.nextLine(); // storing what the user inputted in a string variable
message.close(); //closed the scanner object
return guess; // returned user input
}
}
when I use the way that doesn't work this is what runs:
What your name my guy? chris
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at ScannerTool.scannerT(ScannerTool.java:7)
at portation.post(portation.java:21)
at MainTest.main(MainTest.java:9)
What would be the answer I'm looking for? I would like to know, why am I getting this error and what do I need to do to fix it?
The problem comes from the fact that System.in is a specific InputStream - it is static and only created once. In your case, you read from it once and immediately close it (when you close the Scanner). When you try to read from a closed stream, it will throw an exception, NoSuchElementException in this case. When working with files it usually isn't a problem because you could always create a new InputStream.
What you need to do here is to make sure you will close the InputStream only when you're done with reading everything. You could make the Scanner variable static, create a new method for closing it and call it only when you're done with reading.

Storing data in an Array and outputting that data

I am working on a program that stores data in an Array from the user and outputs that data.
For example:
An input:
Happy HAPPY#foo.com
The output:
NAME: Happy
EMAIL: HAPPY#foo.com
I was hoping someone could look at what I've got so far and give me a pointer on how to continue. I know I have to use the scanner class and scan.nextLine, I'm not sure what comes next. I understand I don't have much, I'm not looking for someone to complete this, but maybe someone who can give me some pointers or point me in the right direction. I believe I have the correct base to my program.
My Code So Far:
import java.util.ArrayList;
import java.util.Scanner;
public class Program5 {
void loadContacts()
{
Scanner scan = new Scanner(System.in);
System.out.println(scan.nextLine());
scan.close();
}
void printContacts()
{
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Program5 program5 = new Program5();
program5.loadContacts();
program5.printContacts();
}
}
Better name the class "person" or like this, but nevermind for the explanation :
public class Program5 {
private String name;
private String mail;
public Program5(){}
void loadContacts(){
Scanner scan = new Scanner(System.in);
System.out.println("Please enter a name and a mail like this : name email#email.com (separate with ' ')");
String[] line = scan.nextLine().split(" ");
while(line.length!=2){
System.out.println("Again, enter a name and a mail like this : name email#email.com (separate with ' ')");
line = scan.nextLine().split("/");
}
this.setName(line[0]);
this.setMail(line[1]);
scan.close();
}
void printContacts() {
System.out.println("NAME : "+this.name+"\nEMAIL : "+this.mail);
}
public static void main(String[] args) {
Program5 program5 = new Program5();
program5.loadContacts();
program5.printContacts();
}
public void setName(String name) {
this.name = name;
}
public void setMail(String mail) {
this.mail = mail;
}
}
In the loadyou ask the user, check it he enter 2 element separate by '/' and if yes store them as attributes to be able to get them in another method ;)
You should have a global varible to store the name and the email. Try adding these lines on the top of the code. after public class Program5 {.
private String Name, Email;
The you must assing this values to void loadContacts(). Spliting the string you read.
void loadContacts()
{
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
String arr[] = input.split("\\s+");
Name = arr[0];
Email = arr[1];
scan.close();
}
And finally on void printContacts().
void printContacts()
{
System.out.println("NAME: " + Name + "\nEMAIL: " + Email);
}
Here is the code runnig: http://ideone.com/mjyfHK
You can do a variety of things.
You can make loadContacts() and printContacts() static methods, and also change loadContacts() so that it returns an Array or 2D array or however you choose to represent a name-email pair. Then change printContacts()` to take in that type and iterate through that Array to print out each name/email pair. This solution is a bit more work but you won't have to create an object of the same class within the main method of that class.
or
You can keep your method as they are and instead create a new field for the program class, called contacts and it would be of the type that you choose for representing name/email pairs. You would add items to contacts in loadContacts() and iterate through it in printContacts(). Then you don't have to change anything in your main method.

Using the Scanner class to read a scanner string

I have a problem creating a student class which contains a constructor which takes a Scanner string of a format "Brookes 00918 X12 X14 X16 X21". The conditions should be that there should be a student name and student number and the course codes should start with an "X". I have thrown IncorrectFormatExceptions in the case that they are not satisfied. However when I create a test class and enter a string and press enter , for example "abc 123" it doesn't produce an output which is usually the case.
Update: I've changed the code to use a String array tokens however now with the toString() method using "123 abc X12" it gives a Null Pointer Exception. It works when I put "123 abc" in the constructor
Update:Seems to work now forgot to initialize the arrayList
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Student extends UniversityPerson{
private String studentNumber="";
private List<String> courses=new ArrayList<String>();
private String studentName="";
public int checkNoofletters(char[] chararray){
int noofletters=0;
for (char c:chararray){
if (Character.isLetter(c)){
noofletters++;
}
}
return noofletters;
}
public String courseListinStr(){
String stringo="";
for (String c:courses){
stringo+=c;
stringo+=" ";
}
return stringo;
}
public Student(Scanner scanner) throws IncorrectFormatException{
int studentNumberCount=0;
int studentNameCount=0;
Scanner s=scanner;
String input=s.nextLine();
String[] tokens=input.split("\\s");
for (int i=0; i<tokens.length; i++){
char[] chars=tokens[i].toCharArray();
if (checkNoofletters(chars)==chars.length){//if the number of letters is equal to the character length
if (studentNameCount==1){throw new IncorrectFormatException("Can only have 1 student name");}
studentNameCount++;
this.studentName=tokens[i];
continue;
}
if (tokens[i].matches("[0-9]+")){//add to the studentNumbers list
if (studentNumberCount==1){throw new IncorrectFormatException("Can only have 1 student number");}
studentNumberCount++;
this.studentNumber=tokens[i];
continue;
}
if (!tokens[i].startsWith("X")){
throw new IncorrectFormatException("Course code must start with an 'X'");
}
System.out.println(tokens[i]);
courses.add(tokens[i]);
}
if (studentNumber=="" || studentName==""){
throw new IncorrectFormatException("Must have 1 student Number and Student Name");
}
}
#Override
public String toString() {
//return String.format("%s %s", studentName,courseListinStr());
return String.format("Student: %s %s", studentName,studentNumber);
}
#Override
public boolean equals(Object o) {
// TODO Auto-generated method stub
return false;
}
}
The best way would be to do something like this:
Scanner s=scanner;
String input = s.nextLine();
String[] tokens=input.split("\\s");
Now you can test all your conditions:
if (tokens.size() < yourNumber) throw new Exception("add here");
if (tokens[2].charAt(0)!='X') throw new Exception("add here");
and so on; it should be rather easy to create your Student Object based on your requirements.
Your program is full of errors and I'll list some of them after answering why it doesn't print anything: if you dump all threads you'll see that the main thread is stuck at next(), which blocks until next token is available, and effectively never leaves the constructor of the first student
if (s.hasNextInt()){
studentNumbers.add(s.nextInt());
s.next();
continue; // <--------- this line
}
I think this is not the only error in your program, so maybe you'd better throw the entire parsing away and restart from scratch.
You should create exactly one Scanner object for each input stream, not one for parsed object
You should not pass the scanner to the Student constructor
You should not put any algorithm in a constructor: make a separate object instead
To simplify your program introduce a Parser class
public class Parser {
public Parser(Reader in) {}
public boolean hasNext() {}
public Student next() {}
}
and inside next() make the parser deal with entire lines (Scanner.hasNextLine and Scanner.nextLine()) instead of individual tokens, otherwise you'll have to define a custom protocol to mean EOR (end of record)
Dealing with lines is easier to think about, program and test. Once you have the full record, you can further tokenize it with a simple String.split(), or directly use regular expressions.
I didn't go through, your whole code. But, I would suggest you to use StringTokenizer or split function and store it in temp array. Then, traverse through your temp array and validate the data.

Declaring an object array in java (code included)?

public class Pig {
private int pigss;
private Pig[] pigs;
public Pig[] pigNumber (int pigss)
{
pigs = new Pig [pigss];
return pigs;
}
Code that includes main method:
public class animals{
public static void main(String[] args){
Pig cool = new Pig();
Scanner keyboard = new Scanner (System.in);
System.out.println("How many pigs are there?");
int pigss = Integer.parseInt( keyboard.nextLine() );
cool.pigNumber(pigss);
//This is where I have trouble. I want to use the array pigs here in the main method, this is what i tried:
Pig[] pigs = cool.pigNumber(pigss);
I then tried to use a for loop and assign values (String) to the index of arrays (pigs[]). But the error that gives me is: cannot convert from String to Pig. Any tips are appreciated. THank you.
for(int j = 0; j < pigs.length; j++)
{
System.out.println("What is the pig " + (j+1) + "'s name");
pigs[j] = keyboard.nextLine();
}
Your pigs will need an attribute to contain the string values you are trying to pass:
public class Pig {
private String name;
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
Then when you want to assign this string value to your pig:
int indexOfPig = 0; // Or whatever it is supposed to be
pigs[indexOfPig].setName("I am a string");
In java you can only use ints as the indexes of arrays
It is saying 'cannot convert from String to Pig' because you can't do that!
If you want somehow convert a String to a Pig, you are going to need to write some code to do the conversion. For example, you might write a constructor that creates a new Pig from some kind of description. Or you might write a method that looks up a Pig by name or number or something.
It is hard to offer any more concrete advice because you don't tell us what is in the string values ... or how you expect the strings to become pigs. (The only suggestion I have is to try Macrame :-) )
Pig doesn't have a name member or even method that accepts a string. Also you are trying to assign a String(keyboard.nextline() to a Pig(pigs[j].
Add an attribute name to your pig.
class Pig{
public String name:
public void Pig(String name){
this.name = name;
}
}
Then assign a new instance of Pig in the loop.
pigs[j] = new Pig(keyboard.nextLine());
Also get rid of the useless class pigNumber. All you need is an ArrayList of Pigs. The array list can be dynanically sized.
List<Pig> pigs = new ArrayList<Pig>
so your loop could be something like
String name = ""
while(true){
name = keyboard.readline();
if(name== "stop"){
break;
}
pigs.add(new Pig(names);
}
Then getting the number of pigs is a simple
System.out.println(pigs.length());

How to parse Bank information into particular format, plus java questions

Doing a java assignment in CSE 205 at ASU, and I'm having a hard time understanding parsing. I've looked through our online textbook, and parsing rarely comes up and it's never given a full explanation. I've looked through the java api documentation a few times and I never understand what it's saying, so I hope someone isn't too frustrated as to explain how to do it.
The class is:
BankParser
The BankParser class is a utility class that will be used to create bank objects from a string. The BankParser class cannot be instantiated. It has the following method:
public static Bank bankParser(String lineToParse)
The bankParser method's argument will be a string in the following format:
bankName/bankID/city,state
A real example of this string would be:
Bank Arizona/10001/Phoenix,AZ
The bankParser method will parse this string, pull out the information, create a new bank object, set the attributes of the object, and return it.
So far this is my setup:
public class BankParser {
public static Bank bankParser(String lineToParse) {
}
}
Also, in my Bank class I have this toString method:
public String toString() {
String printInfo = ("\nBank name:\t" + bankName + "\nBank ID:\t" + bankID + "\nBank address:\t" + bankAddress + "\n");
return printInfo;
It gives me 2 markers in eclipse: that this overrides java.lang.Object.toString, and that the return type is missing. What does this all mean?? The return type is String, I don't see what the problem is with that, but the override I'm clueless
EDIT; This is what I've come up with for bankParser
public static Bank bankParser(String lineToParse) {
String[] returnValue = lineToParse.split("/");
Bank temp = new Bank();
temp.setbankName(returnValue[0]);
temp.setbankID(returnValue[1]);
temp.setbankAddress = (returnValue[2]); //this one won't work, see below
return temp;
}
}
And THESE are the methods in Bank and Address that apply to bankParser
public void setBankName(String bank1) {
bankName = bank1;
}
public void setBankID(String bankID1) {
bankID = bankID1;
}
public void setBankAddress(String city, String state) {
bankAddress.setCity(city);
bankAddress.setState(state);
}
In Address.java:
public void setCity(String city1) {
city = city1;
}
public void setState(String state1) {
state = state1;
}
I would use library like Apache Common CSV for reading and writing.
Reader in = new StringReader("bankName/bankID/city,state");
Iterable<CSVRecord> parser = CSVFormat.newBuilder()
.withDelimiter('/')
.parse(in);
for (CSVRecord csvRecord : parse) {
...
}
Your bankParser method is empty. It needs to return a Bank object, and Java will complain until you do this. You could always have it return null for now til, make it at least a compilable stub you figure this out:
public static Bank bankParser(String lineToParse) {
Bank returnValue = null;
// TODO: create a Bank object, assign to returnValue
return returnValue;
}
As for your override bit, are you getting an error message? Or a warning? The code you've posted seems kosher, so it should compile. Please show the actual full message.
As for your actual parsing, I'd use String#split("/") to split the lineToParse into an array of tokens and then work with each token, create arguments for a Bank constructor call and create a Bank object.
i.e., code to show the concept:
String text = "Bank Arizona/10001/Phoenix,AZ";
String[] tokens = text.split("/");
System.out.println(java.util.Arrays.toString(tokens));

Categories

Resources