Large Arrays of dataType String - java

I hope everyone is doing okay. I'm still new to this developer stuff, and although I find it really interesting I'm beginning to see how it can get tedious if you don't keep track of what you are doing. Im working on an update for a mock ATM program. The new version reads from a .txt file to validate account information. Once it is validated you can either check the balance, deposit money, withdrawal money, or log out. Once you do your transaction, the program is suppose to update the old .txt file with the updated balance for that account. I finally got everything to work like it is suppose to, but when I go back and check the updated .txt file, that particular account was updated but the rest of the strings in the file were updated to null and I can't figure out why and what is causing my program to do that. I have a feeling that the problem is in the upDate method and I'm overlooking something. Below you can see my source code and below the output of what I am getting. Any explanation about the logic behind this error would be greatly appreciated.
import java.util.*;
import java.io.*;
public class ATM2 {
public static Scanner kbd = new Scanner(System.in);
/*
* This method reads the number of lines in the .txt file
* and returns the array size.
*/
public static int arraySize () {
int result = 0;
try
{
Scanner lineReader = new Scanner(new FileReader("ATMData.txt"));
int lineCount=0;
while(lineReader.hasNextLine())
{
String size;
size = lineReader.nextLine();
lineCount++;
}
lineReader.close();
return lineCount;
}
catch(FileNotFoundException e)
{
System.out.println("ERROR: FILE NOT FOUND");
return result;
}
}
//Method searches .txt file and returns String
//array with all account info.
public static String[] acctLine(int size){
String[] validAccounts = null;
try
{
Scanner lineReader = new Scanner(new FileReader("ATMData.txt"));
int lineCount=0;
String [] acctNums= new String[size];
while(lineReader.hasNextLine())
{
String lineInfo;
lineInfo = lineReader.nextLine();
acctNums[lineCount]=lineInfo;
lineCount++;
}
lineReader.close();
return acctNums;
}
catch(FileNotFoundException e)
{
System.out.println("ERROR: FILE NOT FOUND");
return validAccounts;
}
}
//Method updates the txt file with new acct information.
public static void acctUpdate (String[] validAccount, String fileName){
try
{
PrintWriter newFile = new PrintWriter(new FileWriter(fileName));
for(int i=0; i<validAccount.length; i++){
newFile.println(validAccount[i]);
}
newFile.close();
}
catch(Exception e){
System.out.println("ERROR: FILE NOT PRINTED");
}
}
/*The checkID method determines if acctNum is a valid account number
* and pwd is the correct password for the account. If the account information
* is valid, the method returns the current account balance, as a string.
* If the account information is invalid, the method returns the string "error"
*/
public static String checkID(String acctNum, String pwd, String [] validAccounts)
{
String result = "ERROR";
String acctString = "ERROR";
boolean foundIt = false;
for(int i=0; i<validAccounts.length; i++) //Loop compares the input data with array data.
{
acctString = validAccounts[i];
if (acctNum.equals(acctString.substring(0, acctString.indexOf(" "))) &&
pwd.equals(acctString.substring(acctString.indexOf(" ")+1,acctString.lastIndexOf(" ")))){
foundIt = true;
result = acctString.substring(acctString.lastIndexOf(" ") + 1);
}
}
if (foundIt) //If it's true it returns the acct. balance.
{
return result;
}
else
{
System.out.println("ERROR: INVALID ACCOUNT TYPE");
}
return result;
}
/* This method finds the array index of the desired account string.
* and returns the the index of the line
*/
public static int arrayIndex(String acctNum, String pwd, String [] validAccounts)
{
int accountPos=0;
Boolean foundIt = false;
//loop searches for the index of the array.
for(accountPos=0; accountPos<validAccounts.length && !foundIt; accountPos++)
{
if (acctNum.equals(validAccounts[accountPos].substring(0, validAccounts[accountPos].indexOf(" "))) &&
pwd.equals(validAccounts[accountPos].substring(validAccounts[accountPos].indexOf(" ")+1, validAccounts[accountPos].lastIndexOf(" "))))
{
foundIt = true;
}
}
return accountPos;
}
/*Method creates menu options and returns
*the choice selected by the user.
*/
public static int menu()
{
int menuChoice;
do
{
System.out.print("\nENTER TRANSACTION TYPE: CHOOSE 1-4."
+ " \n 1. Display Balance"
+ "\n 2. Deposit\n 3. Withdraw\n 4. Log Out\n");
menuChoice = kbd.nextInt();
if (menuChoice < 1 || menuChoice > 4){
System.out.println("error");
}
}while (menuChoice < 1 || menuChoice > 4);
return menuChoice;
}
/*Method displays the balance to the screen.
*/
public static void displayBalance(double balance)
{
System.out.printf("\nYOUR NEW BALANCE IS: $%.2f\n", balance);
}
/*Method calculates the deposit going in to account.
Returns the total deposit.
*/
public static double deposit(double orgBal, double depAmt)
{
return orgBal + depAmt;
}
/*Method that calculates the balance after the withdraw.
* returns a double with the amount withdrawn.
*/
public static double withdraw(double orgBal, double wdrlAmt)
{
if (wdrlAmt > orgBal)
{
return orgBal;
}
else
{
return orgBal-wdrlAmt;
}
}
public static void main(String[] args) {
String accNum, pass, fileName="ATMData.txt", origBal = "ERROR";
String acctInfo;
int count = 0, menuOption = 0, acctPos;
double depositAmt, withdrawAmt, currentBal;
String [] validAccounts =acctLine(arraySize());
/*loop that will count the number of login attempts
*you make and will exit program if it is more than 3.
*as long as oriBal equals an error.
*/
do{
System.out.println("PLEASE ENTER YOUR ACCOUNT NUMBER: ");
accNum = kbd.next();
System.out.println("ENTER YOUR PASSWORD: ");
pass = kbd.next();
origBal = checkID(accNum, pass, validAccounts);
count++;
acctPos = arrayIndex(accNum, pass, validAccounts)-1;
if (count >= 3 && origBal.equals("ERROR:")){
System.out.print("MAX LOGIN ATTEMPTS REACHED.");
System.exit(0);
}
else if (!(origBal.equals("ERROR"))){
System.out.println("\nYOUR CURRENT BALANCE IS: $ "+ origBal);
}
else
System.out.println(origBal);
}while(origBal.equals("ERROR"));
currentBal=Double.parseDouble(origBal);
/*this loop will keep track of the options that
*the user inputs in for the menu. and will
*give the option of deposit, withdraw, or logout.
*/
while (menuOption != 4)
{
menuOption=menu();
switch (menuOption)
{
case 1:
displayBalance(currentBal);
break;
case 2:
System.out.print("HOW MUCH DO WISH TO DEPOSIT: $ ");
depositAmt = kbd.nextDouble();
currentBal = deposit(depositAmt, currentBal);
displayBalance(currentBal);
break;
case 3:
System.out.print("HOW MUCH DO YOU WISH TO WITHDRAW: $ ");
withdrawAmt = kbd.nextDouble();
if (withdrawAmt > currentBal)
System.out.println("ERROR: YOU DON'T HAVE ENOUGH FUNDS TO COMPLETE"
+ " TRANSACTION."
+ " ENTER TRANSACTION TYPE: CHOOSE 1-4");
currentBal = withdraw(currentBal, withdrawAmt);
displayBalance(currentBal);
break;
case 4://Last option logs user out after it updates the ATMData.txt
acctInfo = accNum + " " + pass + " " + String.valueOf(currentBal);
validAccounts[acctPos]=acctInfo;
acctUpdate(validAccounts, fileName);
System.out.println("LOGOUT SUCCESSFULL.");
System.exit(0);
break;
default:
}
}
}
}
And this is what the .txt looked like before source code update. The only thing updated is the one line.
null
null
null
null
null
null
null
null
null
null
417927608 ;6FYE5l`LPX# 4101.13
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
Because we are passing by reference we only needed to declare the original array in the main program once. .
7560640 6Z[NVoee1S6 4424.43
04569505 f:H>wAr#<URH 4211.42
528859 ][[79_W?]=:< 724.26
973335820 Si>G7QMp?>e 3207.28
79154675 Y>vfTYwHm0J 3327.47
5554284 6n[^PwZUZlH 1028.66
58773836 28vcgSpwA01 3131.02
95873039 #4XwrN`T9 2598.28
1034703 n#HKk`mTar2Z 1176.75
10192851 X>ATvaR:qT 3857.89
417927608 ;6FYE5l`LPX# 3401.13
143260 s2UgJtSHYFmn 378.68
34729802 rh\<3rmk7Dm< 255.48
277791753 BR2=siCDi 345.75
1014748 PK?KTMjA63e 1196.16
496714922 M1=I`ve;Wjw 501.26
654156 AB`6cvO0ql: 4310.51
898250859 t^D90Nw?Ii 3876.05
971750 [9q_5AuLlJ 135.97
796678134 KwV^03p:WW=< 3453.65
39482807 C5?H?b9UplL 4109.48
401599 MvHL7Yv07bW 4356.96
8321377 Jc:<_ke9B: 930.90
152773 VQ6\[2k:uoj 3265.93
624426519 kralkKKEia3 4858.39
650002 Km2t\R3>3#G 1470.78
004509766 _0S`1qb^V 1332.24
0274647 WDhg3\p]w 3147.50
974502771 Q4GT<_s3D9CK 4464.22
281866 c_1F]#RpV^ 2952.03
381121 rOo?CiA[kwTs 4555.21
1549064 F7^eh=njp\r 430.24
841319 IBe^GTLGv 4050.76
6499423 tW9>r[s_<\ 1418.09
8579740 cdB12UrLU 2905.74
33581232 <os4;WcEqb 2455.32
725175174 nWjIeFLK3E 3118.08
592410029 RqgPT382p2Lk 3863.32
08274516 DDr?^vuNQ 1630.37
808471 Ow:8udlBrYP 2590.05
769854 0`lpWGrMkrG 2643.59
3591827 MmThLS1DdL5 2715.30
9001605 \n;rMknh7C 4074.83
10345766 N>^qBqhk?39J 539.43
504385 j0Rq=li0c^ 253.77
362335041 >^VN5oh?OSR 324.19
5728008 QZ>BZhGEv 4441.67
26102273 1XCWR;W?^b\ 4203.51
3317249 dmjLKbgZ? 1958.44
793249 5J>ApQZAB 1906.46
536461203 CP5U:f5\d[_p 3742.25
030298042 VBtHo909;QM 986.28
6111228 mmPgiDMALt 1348.95
621992 r7UmSJ\9j 1440.22
310072768 B1ccagCH3 4755.56
819894803 IXfcY9PZG1 4399.39
362945795 5LAdX_s^G 3624.28
99929088 `oHijc^J0u 4507.69
821671 s#OV>NYlacV 4125.72
72368663 Mi?wTcZ_#I 2845.24
22692406 uT05^2plu 2530.73
343817 pB;Glu5sVb7P 2168.28
5138360 877<cT4T;t 1562.15

You never write the previous account data into validAccounts. When you run String [] validAccounts = new String[arraySize()]; all of the string instances get set to null and only get changed when you update an account. What you need to do is when you start your program, read the existing text file into that String array and then just change the entries you need to. When you are done, write the String array to the file.

In your main method
String[] validAccounts = new String[arraySize()];
which means you have an array of NULL values, you need to assign the values data here rather than in another method, as when you pass the array you are passing a reference to this array rather than the data itself
so in arrayIndex
validAccounts = acctLine(arraySize()); will put the data in this method and when it returns this data is discarded.
You need to assign the data ONCE then pass this around without writing over it in methods
e.g. in main
String[] validAccounts = new String[arraySize()];
should be
String[] validAccounts = acctLine(arraySize());
You don't need to read it again in arrayIndex or checkID.
So read it once and store it, pass this data to the method and read from this data rather than a new file read
a simple example is this - you'll see the a = new int.... does not change a in original method, but assignment does in doesSomething
public static void main(String[] args) {
int[] a = {1,2,3};
doesNothing(a);
for (int i: a)
System.out.print(i);
doesSomething(a);
for (int i: a)
System.out.print(i);
}
static void doesNothing(int[] a) {
a = new int[]{4,5,6};
}
static void doesSomething(int[] a) {
a[0] = 7;
a[1] = 8;
a[2] = 9;
}

Related

Why does my method overwrite positions in my array

So I have this method here
while(oMenu == 1 || oMenu == 2){
oMeny = Kbd.readInt("\nClick 1 to make an account\nClick 2 to login\nClick 3 to exit the program");
if(oMeny == 1){
for(int i = 0; Account[i] != null; i++){
if(Account[i] == null){
pos = i;
}
}
Account[pos] = new Account();
}
if(oMeny == 2){
String s = Kbd.readString("Input your accountnumber: ");
for(int i = 0; Account[i] != null; i++){
if(Account[i] != null && s.equals(Account[i].getAccountNumber())){
System.out.println("Welcome!");
// Here is rest of my code , the "inner" menu that works menyMetod(iMeny,mMeny);
}
else{
System.out.println("There are no accounts with that given accountnumber!");
}
}
}
}
}
I want to understand why if I access the oMeny == 1 and make 2 accounts Why I can't seem to access the first one I make but rather the latest one? It seems that somehow my array "overwrites" the first empty position. Basically I want to find the first empty position in my array, so in the first case it's always index 0 and then the next time I make an account again, it should be Index 1 logically.
EDIT : Heres my code for the Account class
public class Account{
private int money, transactions;
private String AccountNumber;
public Account(){
money = Kbd.readInt("\nHow much money do you want to put in?");
AccountNumber = Kbd.readString("\nWhat account number do you want?");
}
The error is here:
for (int i = 0; accounts[i] != null; i++) {
if (accounts[i] == null)
The for loop repeats as long i points to a non-null entry. Therefore the if-condition is never true.
This becomes quickly obvious when you run the program line by line in a debugger.
Next time please provide a complete code example that can be compiled. Your code is full of error, It took me a lot of time to fix it before I was able to execute it.
Corrected code:
import java.util.Scanner;
class Main
{
static Scanner kbd = new Scanner(System.in);
static Account[] accounts = new Account[100];
static class Account
{
//public int money;
public String accountNumber;
public Account()
{
//System.out.println("\nHow much money do you want to put in?");
//money = Kbd.nextInt();
System.out.println("\nWhat account number do you want?");
accountNumber = kbd.next();
}
}
public static void main(String[] args)
{
int oMenu = 1;
int pos = 0;
while (oMenu == 1 || oMenu == 2)
{
System.out.println("\nClick 1 to make an account\nClick 2 to login\nClick 3 to exit the program");
oMenu = kbd.nextInt();
if (oMenu == 1)
{
for (int i = 0; i<accounts.length; i++)
{
if (accounts[i] == null)
{
accounts[i] = new Account();
break;
}
}
}
if (oMenu == 2)
{
System.out.println("Input your accountnumber: ");
String s = kbd.next();
Account found=null;
for (int i = 0; i<accounts.length; i++)
{
if (accounts[i] != null && s.equals(accounts[i].accountNumber))
{
found=accounts[i];
}
}
if (found!=null)
{
System.out.println("Welcome! nr. "+found.accountNumber);
}
else
{
System.out.println("There are no accounts with that given accountnumber!");
}
}
}
}
}
Notice how I also fixed the second for-loop.
You did not show the declaration or initialization of pos, so I think it is not working how you expect because you do not go into the for loop where Account[i] is null to set pos. Try this
if(oMenu == 1){
int pos = 0;
while (Account[pos] != null && pos < Account.length)
pos++;
if (pos < Account.length)
Account[pos] = new Account();
else{
//expand array and add account or throw error
}
}

Validating user input in arrays

Hey guys I am doing a project for school and am having a little trouble, I have a variable "reservationNumber" and im attempting to check if the number the user inputs is in the array, if not it returns a string saying the number was not found. It is working fine and displays the correct info when there is a valid input but when an invalid input is detected it gives a null.pointer.exception error. I tried writing it so that if the number is not detected the private method returns -1, then when I call the tickerInformation method, if that the variable 'ticket' returns -1 then it returns "invalid reservation number". This is where is error is being raised and only occurs when I enter an invalid number please help.
public void ticketInformation(String reservationNumber)
{
int ticket = searchArray(reservationNumber);
if (ticket == -1)
{
System.out.println("The reservation number entered was n0t found");
}
else
{
System.out.print("\n" + ticketSale[ticket].toString());
}
}
private int searchArray(String reservationNumber)
{
for (int i = 0; i < ticketSale.length; i++)
{
if (ticketSale[i].getReservationNumber().equals(reservationNumber))
{
return i;
}
}
return -1;
}
ticketSale[i].getReservationNumber().equals(reservationNumber) has an issue. Share the declaration and init for array "ticketSale". If ticketSale array is for abstract data type then why equal is called with String?
You didn't post the whole code but I think that when you enter invalid number as reservation number, it does not assigned to the related object's instance variable. So getReservationNumber() might be returning null.
Add a null check,
private int searchTicketSales(String reservationNumber) {
int reservationNumberIndex = -1;
for (int i = 0; i < ticketSale.length; i++) {
if (null != ticketSale[i].getReservationNumber() && ticketSale[i].getReservationNumber().equals(reservationNumber)) {
reservationNumberIndex = i;
break;
}
}
return reservationNumberIndex;
}
Best Regards,
Rakesh
Add a regex to validate that your input is a valid number "\\d+":
public void ticketInformation(String reservationNumber)
{
String regex = "\\d+";
if(!reservationNumber.matches(regex))
{
System.out.println("The reservation number entered was n0t found");
}
int ticket = searchArray(reservationNumber);
if(ticket == -1)
{
System.out.println("The reservation number entered was n0t found");
}
else
{
System.out.print("\n" + ticketSale[ticket].toString());
}
}
You might want to validate searchArray, particularly if it is not used interdependently from ticketInformation().

specifying the path for input data and output data

I am new in java and I have to use the code below but the code it does work because I have to specifying the path for input data and output data. The code is got it from the internet. please help me
class Svm_scale
{
private BufferedReader rewind(BufferedReader fp, String filename) throws IOException
{
fp.close();
return new BufferedReader(new FileReader(filename));
}
private void output_target(double value)
{
LnCount++;
if(y_scaling)
{
if(value == y_min)
value = y_lower;
else if(value == y_max)
value = y_upper;
else
value = y_lower + (y_upper-y_lower) *
(value-y_min) / (y_max-y_min);
}
formatterscaled.format(value+" ");
System.out.println(" Line Number "+LnCount + " ");
}
private void output(int index, double value)
{
count++;
double Threshold1=0,Threshold2=0;
Threshold1= Avg[index]+(STDV[index]/2);
Threshold2= Avg[index]-(STDV[index]/2);
if(value > Threshold1 )
value = 2;
else if(value < Threshold2 )
value = -2;
else
value = 0;
formatterscaled.format( formatter.format(value) + ",");
// System.out.println(" Counter "+count);
// }
}
String save_filename =Save1; // = null?
String restore_filename =null;
String scale_data_filename =Disc; // set this to the path where the output should be stored, e.g. = "C:\\temp\\scaled";
String data_filename =Libsvm; // set this to the path where the input can be get, e.g. = "C:\\temp\\inputdata"
These are the Strings you need to adapt in order that the program can read and write. Save1, Disc, Libsvm are not in your code, so it can only be guessed where they come from.
data_filename and scale_data_filename are required. save_filename seems to be optional and may be set to null.

Finding duplicates in an array of objects

The purpose of this project is to make a pokedex that adds and holds all the pokemon passed in by user input. When the user inputs a pokemon that is already stored in the pokedex the word "duplicate" is supposed to be printed to the console. The word duplicate is printed even though there are no actual duplicates within the object array. Here is my output from the console :
Welcome to your new PokeDex!
How many Pokemon are in your region?: 3
Your new Pokedex can hold 3 Pokemon. Let's start using it!
List Pokemon
Add Pokemon
Check a Pokemon's Stats
Sort Pokemon
Exit
What would you like to do? 2
Please enter the Pokemon's Species: red
Duplicate
Now here is all the code used that could possibly be making this error
import java.util.Scanner;
public class Project4 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Welcome to your new PokeDex!");
System.out.print("How many Pokemon are in your region?: ");
int size = input.nextInt();
Pokedex pokedex = new Pokedex(size);
System.out.println("\nYour new Pokedex can hold " + size + " Pokemon. Let's start using it!");
int choice = 0;
boolean done = false;
while (!done) {
System.out.println("\n1. List Pokemon\n2. Add Pokemon\n3. Check a Pokemon's Stats" + "\n4. Sort Pokemon\n5. Exit");
System.out.print("\nWhat would you like to do? ");
choice = input.nextInt();
switch (choice) {
case 1:
String[] pokemonList = pokedex.listPokemon();
if (pokemonList == null)
System.out.println("Empty");
else
for (int i = 0; i < pokemonList.length; i++) {
System.out.println((i + 1) + ". " + pokemonList[i]);
}
break;
case 2:
System.out.print("\nPlease enter the Pokemon's Species: ");
String species = input.next();
pokedex.addPokemon(species);
break;
}
}
}
}
In the following class I have the actual method that adds the pokemon and the constructor for Pokedex
public class Pokedex {
Pokemon[] pokedex;
String pokeArray[];
public Pokedex(int size) {
pokedex = new Pokemon[size];
pokeArray = new String[size];
}
public boolean addPokemon(String species) {
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++) {
if (pokedex[i] == null) {
pokedex[i] = stuff;
}
else if (i < pokedex.length && pokedex[i] != null) {
System.out.println("Max");
}
if (pokedex[i].getSpecies().equalsIgnoreCase(species)) {
System.out.print("Duplicate");
break;
}
}
return false;
}
}
Sorry for the mass amounts of code I just need help tracing where this unexpected result is coming from.
The reason it's doing that is because of this bit of code here:
public boolean addPokemon(String species)
{
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++)
{
if (pokedex[i] == null)
pokedex[i] = stuff;
else if (i < pokedex.length && pokedex[i] !=null)
System.out.println("Max");
if(pokedex[i].getSpecies().equalsIgnoreCase(species))
{
System.out.print("Duplicate");
break;
}
}
return false;
}
The problem is just a little bit of syntax missing. In your for loop, you check to see if
A) there are any empty spots in the array
B) if every element in the array up to the user inputted size is full
and C) if any element in the array matches the one we're trying to add.
The problem you're encountering is because your C is an if instead of an else if. Because A sees the index is null, it assigns the new Pokemon to the Pokedex. Then because C is an if instead of an else if, it runs after you assign the new Pokemon and sees the Pokemon we just added and says it's a duplicate. Changing it to an else if would fix this.
Also, since there was no break; in A, it would assign every element of the array to the first one entered, causing any further additions to call Max. I edited the code and this is what I had that worked for me:
public boolean addPokemon(String species)
{
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++)
{
if(pokedex[i] !=null && pokedex[i].getSpecies().equalsIgnoreCase(species))
{
System.out.println("Duplicate");
break;
}
else if (pokedex[i] == null)
{
pokedex[i] = stuff;
break;
}
else if(i + 1 == pokedex.length)
{
System.out.println("Max");
break;
}
}
return false;
}
Also, out of curiosity, why is the addPokemon() function a boolean? You return a value (albeit arbitrarily) and then never do anything with that value. You could just make it a void, have it return nothing, and it would work just as fine.

Exception organization assistance?

I had some success with this site, and I hope I find more excellent programmers to assist me.
So I am at my wit's end with this code. I am very new to programming, especially exceptions. I have looked very hard through my course material and sought help, but I have been quite unsuccessful. I am trying to create an improved parser that will override another parser. It reads a .txt file with student information of it including an ID, a name, a grade, and an optional email address and optional comment as tokens in a String separated by commas. The override checks for errors in each token and throws an exception called ParserException. The exception will check the code and then return an error message if the error is unfixable.
For example, if a student puts in an AB for the grade, the exception will flag and check if the input is a valid grade (which it is) and then return, if it is not, then it will throw a ParserException, in this case
throw new ParserException(ParserException.GRADE_INVALID_GRADE,lineIndex);
This shows that the does not work and sends out a message GRADE_INVALID on the line indexLine
I have a list of what I need to have as an output:
Any violation of the file format specified in the Input File Format Description section above should result in an ParcerException with an appropriate message
Duplicate IDs are not allowed
Grade values must be a float (92.0) or a letter grade and not an integer
I have all the code to correct and check for errors, but I cannot figure out how to get the try-catch to work. Here's is the override code:
#Override
public ParserResult parseLine(int lineIndex) {
String[] tokens = lines.get(lineIndex).split(",");
ArrayList<Integer> idList = new ArrayList<Integer>();
Integer studentId;
String name;
String grade;
String email;
String comments;
boolean isFloat;
float gradeFinal;
String editName;
studentId = new Integer(tokens[0]);
ParserResult result;
try{
return super.parseLine(lineIndex);
}
catch(ParserException e){
// Check reasonable number of tokens
if(tokens.length >= 3 && tokens.length <= 5){
name = tokens[1];
grade = tokens[2];
// Check the student ID
if(idList.contains(studentId)){
throw new ParserException(ParserException.DUPLICATE_ID, lineIndex);
}else{
idList.add(studentId);
}
// Check the grade
if(grade.trim().equalsIgnoreCase("A")){
gradeFinal = gradeA;
}else if(grade.trim().equalsIgnoreCase("AB")){
gradeFinal = gradeAB;
}else if(grade.trim().equalsIgnoreCase("B")){
gradeFinal = gradeB;
}else if(grade.trim().equalsIgnoreCase("BC")){
gradeFinal = gradeBC;
}else if(grade.trim().equalsIgnoreCase("C")){
gradeFinal = gradeC;
}else if(grade.trim().equalsIgnoreCase("CD")){
gradeFinal = gradeCD;
}else if(grade.trim().equalsIgnoreCase("D")){
gradeFinal = gradeD;
}else if(grade.trim().equalsIgnoreCase("F")){
gradeFinal = gradeF;
}else{
try{
Integer.parseInt(grade);
isFloat = false;
}
catch(Exception fl) {
isFloat = true;
}
if(isFloat){
if((Float.parseFloat(grade) < 100f) && (Float.parseFloat(grade) >= 0f)){
gradeFinal = Float.parseFloat(grade);
}else{
throw new ParserException(ParserException.GRADE_INVALID_GRADE,lineIndex);
}
}else{
throw new ParserException(ParserException.GRADE_INTEGER_VALUE,lineIndex);
}
}
// Check the name
if(name.split(" ").length > 3){
throw new ParserException(ParserException.UNKNOWN, lineIndex);
}else{
editName = name.trim().split(" ")[0];
}
result = new ParserResult(studentId, editName, gradeFinal);
// Checks the email
if(tokens.length >= 4){
email = tokens[3];
// Check for at sign
if(!email.contains("#")){
throw new ParserException(ParserException.UNKNOWN, lineIndex);
}
int count = 0;
// Counts number of # symbols
for(int i=0; i<email.length(); i++){
if(email.indexOf(i) == '#'){
count++;
}
}
if(count > 1){
throw new ParserException(ParserException.EMAIL_MULTIPLE_AT,lineIndex);
}
if(email.split(".").length == 2){
if(!(email.trim().split(".")[1].contains(".edu")) && !(email.trim().split(".")[1].contains(".com"))){
throw new ParserException(ParserException.EMAIL_NOT_EDU_OR_COM,lineIndex);
}else{
result.setEmail(email);
}
}
// Checks if email contains .com or .edu
// Checks the comments
if(tokens.length == 5){
comments = tokens[4];
result.setComment(comments);
}
}
return result;
}
}
// TODO Call Parser's parseLine() here to attempt to parse, catch any exceptions
return null;
}
The original parseLine that is overridden, but still used is:
public ParserResult parseLine(int lineIndex) {
String[] tokens = lines.get(lineIndex).split(",");
ParserResult result = new ParserResult(Integer.parseInt(tokens[0]),
tokens[1], Float.parseFloat(tokens[2]));
result.setEmail(tokens[3]);
return result;
}
Here is the main() file:
public static void main(String[] args){
// TODO Change the line below to use ImprovedParser
Parser parser = null;
try {
parser = new ImprovedParser(args[0]);
} catch (FileNotFoundException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
System.exit(-1);
}
List<ParserResult> results = parser.parse();
int count = results.size();
double sum = 0.0;
for (ParserResult result : results) {
sum += result.getGrade();
}
System.out.println("Number of valid input lines: " + results.size());
System.out.println("Number of invalid input lines: "
+ (parser.getLineCount() - results.size()));
System.out.println("Average grade: " + sum / count);
for (ParserResult result : results) {
System.out.println(result);
}
}
Lastly, here is the .txt file that is being read:
# student_id,name,grade,email
1234,Bob,92.0,bob#test.edu
4321,Alice,95.0,alice#test.edu
1111,Eve,80.0,eve#test.edu
1121,Barry,85.0,barrytest.edu
1131,Harry,86.0,h#rry#test.edu
1121,Larry,87.0,larry#test.edu
1141,Jim Song,88.0,jim#song.edu
1151,Jerry,77.0,jerry#test.net
1161,James,65.0,james#test.com
The last six inputs should cause exceptions, but I can't figure out how to organize it to work. The code ignores the line with # symbol.
Here is a sample successful output:
Number of valid input lines: 3
Number of invalid input lines: 0
Average grade: 89.0
1234, 92.0, Bob, bob#test.edu,
4321, 95.0, Alice, alice#test.edu,
1111, 80.0, Eve, eve#test.edu,
The major changes should be in the orverride method
Please help if you can, I sit at my desk still pondering possibilities, and your help will be most-appreciated.
Assuming ParseException has an error field being an int and someMethod() that throws ParseException:
try {
someMethod();
} catch (final ParseExeption ex) {
if (ex.getError() == ParseException.SOME_ERROR) {
// do something
} else if (ex.getError() == ParseException.OTHER_ERROR) {
// do something else
}
}
Note that it's usually better to use specific exceptions for specific error, something like SomeErrorParseException, OtherErrorParseException, ... (those can extends ParseException if you want) and try-catch like this:
try {
someMethod();
} catch (final SomeErrorParseException ex) {
// do something
} catch (final OtherErrorParseException ex) {
// do something else
}
Some reading: http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html
It seems that there is no code to actually cause the catch clause in the first place. Try adding a throw new ParserException(STUFF_HERE); when an error has been detected while reading the file.

Categories

Resources