How to Split a text file with no pattern - java

I am given a messy set of data and have to split the data into categories. The first line is tax rate, The following line is supposed to be "items," "number of items," and price (columns). I just need help splitting the data accordingly. Any help would be appreciated.
0.05 5
Colored Pencils 3 0.59
Notebook 5 0.99
AAA Battery 5 0.99
Java Book 5 59.95
iPhone X 2 999.99
iPhone 8 3 899.99.
import java.io.*;
import java.util.Scanner;
public class ShoppingBagClient {
public static void main(String[] args) {
File file = new File("data.txt");
shoppingBag(file);
}
public static void shoppingBag (File file) {
Scanner scan;
String itemName=" ";
int quantity = 0;
float price = 0;
int count = 0;
float taxRate;
ShoppingBag shoppingBag = new ShoppingBag(6, .5f);
try {
scan = new Scanner(new BufferedReader(new FileReader(file)));
String dilimeter;
while(count < 1) {
String line = scan.nextLine();
String[] arr = line.split(" ");
taxRate = Float.parseFloat(arr[0]);
}
while(scan.hasNextLine() && count > 0){
String line = scan.nextLine();
String delimeter;
String arr[] = line.split();
itemName = arr[0];
quantity = Integer.parseInt(arr[1]);
price = Float.parseFloat(arr[2]);
Item item =``` new Item(itemName, quantity, price);
shoppingBag.push(item);
System.out.println(itemName);
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}

#Henry's comment gives a good approach. If you know the structure of each line and that it is delimited in a consistent manner (e.g. single space-separated) then you can combine lastIndexOf and substring to do the job.
String delimiter = " ";
String line = scan.nextLine(); // "Colored pencils 3 0.59"
int last = line.lastIndexOf(delimiter); // "Colored pencils 3_0.59"
String price = line.substring(last + 1); // "0.59"
line = line.substring(0, last); // "Colored pencils 3"
last = line.lastIndexOf(delimiter); // "Colored pencils_3"
String quantity = line.substring(last + 1); // "3"
line = line.substring(0, last); // "Colored pencils"
String product = line;
This can be refactored to be tidier but illustrates the point. Be mindful that if lastIndexOf returns the final character in the line then substring(last + 1) will throw a StringIndexOutOfBoundsException. A check should also be taken for if lastIndexOf does not find a match in which case it will return -1.
Edit: The price and quantity can then be converted to an int or float as necessary.

Because the item name doesn't have any restrictions, and as shown can include both spaces and numbers, it would be difficult to start processing the line from the beginning. On the other hand processing from the end is easier.
Consider this change to your code:
String arr[] = line.split();
int len = arr.length;
double price = Float.parseFloat(arr[len - 1]);
double quantity = Integer.parseInt(arr[len - 2]);
String itemName = "";
for(int i = 0; i < len - 2; i++)
itemName += arr[i] + " ";
This works because you know the last element will always be the price, and the pre last will always be the quantity. Therefore the rest of the array contains the name.
alternatively you could use a java 8 implementation for acquiring the name:
itemName = Stream.of(values).limit(values.length -2).collect(Collectors.joining(" "));

Related

Why am I getting 'null' when I try to access my String Array?

I am simply trying to access my array(items[j]) which I filled by doing this:
for(int j = 0;j<items.length;j++){
for(int i = 0;i<prices.length;i++){
items[j] = x.next();
System.out.print(items[j] + ", ");
prices[i] = c.nextDouble();
System.out.printf("$%.2f \n", prices[i]);
The Code above works as intended, however a 'null' problem occurs when I try access the array(items[j]) outside the for loop.
Like this:
System.out.printf("%s, ", items[5]); //accessing 6th item on the menu(Coffee)
System.out.printf("$%.2f", prices[5]); //accessing 6th items price.(2.59)
My Output:
null, $2.59
It seems to work for the Prices array, just not for the Items array.
My Expected Output:
Coffee, $2.59
Here is my full code if there is any confusion:
int size = 1000;
String [] items = new String[10];
double [] prices = new double[size];
System.out.println(" ");
File fileText = new File("inventory.txt");
Scanner x = new Scanner(fileText);
x.useDelimiter("[^A-Za-z]+" + "[^A-Z a-z]+");
Scanner c = new Scanner(fileText);
c.useDelimiter("[^0-99.99]+");
try{
System.out.println("The items in inventory.txt are: ");
while(x.hasNext()&&c.hasNext()){
for(int j=0;j<items.length;j++){
for(int i = 0;i<prices.length;i++){
items[j] = x.next();
System.out.print(items[j] + ", ");
prices[i] = c.nextDouble();
System.out.printf("$%.2f \n", prices[i]);
}
}
}
x.close();
c.close();
}
catch(NoSuchElementException g){
System.out.println(" ");
}
System.out.printf("%s, ", items[5]); //accessing 6th item on the menu(Coffee)
System.out.printf("$%.2f", prices[5]); //accessing 6th items price.(2.59)
The text file my program is reading, (inventory.txt):
Espresso, 2.10
Mochaccino, 5.99
Irish Coffee, 7.99
Caffe Americano, 6.40
Latte, 1.99
Coffee, 2.59
Cappuccino, 3.50
blackCoffee, 8.90
whiteCoffee, 5.54
yellowCoffee, 4.80
greenCoffee, 6.12
purpleCoffee, 3.54
Try this. I avoided using the delimiters because they are not necessary and I removed a useless for-loop which was also contested in a comment by MarsAtomic...
What is the purpose of nesting your for loops like that? The data file doesn't suggest that each item has multiple prices... You can (and should) be reading a full line of data on each iteration of a single loop. Try that and then see if your problem doesn't magically go away.
public static void main(String[] args) throws FileNotFoundException {
int size = 1000, commaIndex = 0;
String[] items = new String[10];
double[] prices = new double[size];
File fileText = new File("inventory.txt");
Scanner c = new Scanner(fileText);
try {
System.out.println("The items in inventory.txt are: ");
while (c.hasNextLine()) {
for (int j = 0; j < items.length; j++) {
String line = c.nextLine();
// Empty line is scanned so i need to decrease j
// in order to have the right indexes for items and prices
if (line.isEmpty())
j--;
commaIndex = line.indexOf(",");
items[j] = line.substring(0, commaIndex);
prices[j] = Double.parseDouble(line.substring(commaIndex + 2));
}
}
c.close();
} catch (NoSuchElementException g) {
System.out.println(" ");
}
System.out.printf("%s, ", items[5]); //accessing 6th item on the menu(Coffee)
System.out.printf("$%.2f", prices[5]); //accessing 6th items price.(2.59)
}

BMI Calculator with name, weight, height, BMI and text using Array and for cycle

I would like to ask how do I do that when the cycle starts and go over again, the string variable name will increase by 1. This program is supposed to ask you how many patients are you going to write. If you write for ex. 10, then the cycle will go for 10 times and it will ask all those information I want and then add them to the array which I have already created called BMI. This whole program is supposed to print you a table which contains Name, Height in meters, weight in Kg, your calculated BMI and then text in what state of BMI are you ATM. The problem is how do I do it? I just started learning arrays and stuff like that and my teacher gave me this homework. I don't think that this homework is hard but just hard to understand what to do.
Things I already tried is creating a for cycle with String called name something like this: String name(); but that obviously did not work.
import java.util.Scanner;
class Pacient {
public static void main(String args[]){
int pole;
Scanner input = new Scanner(System.in);
String pacient;
System.out.print("Zadej kolik bude pacientu: "); //How many patients do you want? For ex. 10
pacient = input.nextLine();
input.nextLine();
pole = Integer.parseInt(pacient);
String[][] bmi = new String[4][pole]; //This is supposed to make an array with my patients.
double vaha; //weight
double vyska; //height
String jmeno; //name
double telo1, telo2; //body for calc.
String vysledek; //result
int i,x=0,j, pa=0, k=0; //some variables
bmi[0][0] = "Jmeno"; //First line of final table NAME
bmi[0][1] = "Vaha"; // WEIGHT
bmi[0][2] = "Vyska"; //HEIGHT
bmi[0][3] = "BMI"; //BMI based on calc.
bmi[0][4] = "Text"; //Final result
for(int y=1;y<pole;y++){
pa++;
x++;
System.out.print("Zadej svoje krestni jmeno: ");
jmeno = input.nextLine();
System.out.print("Zadej svoji vahu v Kg: ");
vaha = input.nextDouble();
System.out.print("Zadej svoji vysku v m: ");
vyska = input.nextDouble();
System.out.println("Vase informace byly uspesne ulozeny! ");
bmi[1][0] = jmeno; //These values should somehow increase but idk
how atm and be assign with the patient which
will be printed at the end.
bmi[1][1] = vaha2;
bmi[1][2] = vyska2;
bmi[1][3] = telo3;
bmi[1][4] = vysledek;
}
// System.out.println("Tisknu tabulku");
// telo1 = vyska * vyska; //Some calc. of BMI
// telo2 = vaha / telo1;
// if (telo2 < 18.5) { //Adding text to the result variable
// vysledek = "mate podvahu";
// } else if (telo2 < 25) {
// vysledek = "Jste v normach";
// } else if (telo2 < 30) {
// vysledek = "Nadvaha";
// } else {
// vysledek = "Obezita";
// }
// String telo3 = String.valueOf(telo2); //Converting to strings
// String vyska2 = String.valueOf(vyska);
// String vaha2 = String.valueOf(vaha);
System.out.println("--------------------------------------------------");
for(i=0;i<pole;i++) {
for(j = 0; j<5; j++) System.out.print(bmi[i][j] + " ");
System.out.println();
}
System.out.println("--------------------------------------------------");
}
}
Atm the program is just printing most of the time NULL NULL NULL NULL, and it does not match with the patient number. How do add all this code to for cycle and make it automatic convert int and double to strings and then print them correctly and assign them to the BMI Array. If you have any further questing, feel free to ask.
I have corrected the issues in code. Everything is explained step-by-step in comments. I have converted variable name in English for my understanding. If you have questions. Please ask.
import java.util.Scanner;
class Pacient {
private static Scanner input;
public static void main(String args[]) {
int numberOfPatients; // Variables that saves number of patient
// Asking user the number of patients
input = new Scanner(System.in);
System.out.print("How many patients do you want?: ");
// I have change this to nextInt
// From javadoc "Scans the next token of the input as an int"
// It is essentially next() + parseInt()
numberOfPatients = input.nextInt();
// nextInt() does not move cursor to next line
// using nextLine() here would move it to next line and close
// previous line otherwise it creates issue when you will use next/nextLine again
input.nextLine();
// String[][] array = new String[Rows][Columns];
// For each patient there is a row. Since in the code there is header
// as well that's why we need numberOfPatients + 1
String[][] bmi = new String[numberOfPatients + 1][5];
// All corresponding columns
bmi[0][0] = "Name"; // First line of final table NAME
bmi[0][1] = "Weight"; // WEIGHT
bmi[0][2] = "Height"; // HEIGHT
bmi[0][3] = "BMI"; // BMI based on calc.
bmi[0][4] = "Result"; // Final result
// Starting from 1. Skipping header
for (int y = 1; y <= numberOfPatients; y++) {
// Using y instead of an int. This way the loop will
// automatically move to next row
// Instead of saving it to variable and then to array
// I am saving it directly
System.out.print("Enter your first name: ");
bmi[y][0] = input.nextLine();
System.out.print("Enter your weight in Kg: ");
bmi[y][1] = input.nextLine();
System.out.print("Enter your height in m: ");
bmi[y][2] = input.nextLine();
// Using the information from above to calculate BMI
// Basically I am storing and calculating at the same time
// parseDouble converts String into double
// Math.pow(a,b) is powber function. a is base and b is exponent
double weight = Double.parseDouble(bmi[y][1]);
double heightSquare = Math.pow(Double.parseDouble(bmi[y][2]), 2);
double bmiCalculated = weight / heightSquare;
// Based on BMI assigning result in result column
bmi[y][3] = bmiCalculated + "";
if (bmiCalculated < 18.5) {
bmi[y][4] = "You are underweight";
} else if (bmiCalculated > 18.5 && bmiCalculated < 25) {
bmi[y][4] = "You are normal";
} else if (bmiCalculated > 25 && bmiCalculated < 30) {
bmi[y][4] = "You are overweight";
} else {
bmi[y][4] = "You are obese";
}
System.out.println("Your information has been saved successfully!");
}
System.out.println("--------------------------------------------------");
// In java 2D arrays are multiple 1D array stacked on each other
// bmi.length gives the number of rows
// Basically you iterate through each row and print each individual row
// like 1D array
for (int i = 0; i < bmi.length; i++) {
// bmi[i] gives ith row. Which is 1D array. So you can print it like normal array
for (int j = 0; j < bmi[i].length; j++)
System.out.print(bmi[i][j] + " ");
System.out.println();
}
System.out.println("--------------------------------------------------");
}
}
Your declaration of array and implementation is conflicting. You've fixed the first dimension and kept the second, variable. But you're using as if the first one is variable and second is fixed.
You should declare your array like
String[][] bmi = new String[pole+1][4];
pole+1 because you're using first row for table headings
Your first loop should look like this
for(int y = 1; y < pole+1; y++){
for(int z = 0; z < 4; z++){
String data="ask user for data";
bmi[y][z] = data; //similar for all
}
}
Your output for loop will also look like above.

Extracting integers from a string and store them in separate variables in java with substring and lastIndexOf(" ") methods

I'm having an issue with this particular program. To cut a long story short, what this program is supposed to do is to get input from a text file, in this case the names and scores of bowlers, and read data off of it. The issue I'm having is trying to extract the scores from the file and storing them in separate variables.
`
import java.util.*;
import java.io.*;
public class lab5{
public static void main (String args[]) throws IOException {
String bowler;
String name;
int score1 = 0, score2 = 0, score3 = 0;
int game = 0;
int average = 0;
//Scanner scan = new Scanner (new FileReader("bowl1.txt."));
Scanner scan = new Scanner (new File ("bowl1.txt"));
while (scan.hasNext()){
bowler = scan.nextLine();
System.out.println("\n" + bowler);
String charCheck = "";
String indent = "";
int count = bowler.length() - 1;
while (count <= bowler.length()){
indent = bowler.lastIndexOf(" ");
charCheck = bowler.substring(0,indent);
System.out.println(charCheck);
count++;
score1 = Integer.parseInt(charCheck);
score2 = Integer.parseInt(charCheck);
score3 = Integer.parseInt(charCheck);
}//end while
System.out.println(score1 + score2 + score3);
}//end fileScan while
}//end main
}//end class
I apologize that my code is a bit sloppy, but I am still learning some of the basics of java. Basically, the idea here is that I need to use the Substring and lastIndexOf(" ") methods to read the scores from the file, and then using Integer.parseInt() to turn them into integers.
(The file is called "bowl1.txt", and this is the data on it)
Atkison, Darren 188 218 177
Barnes, Chris 202 194 195
Dolan, Anthony 203 193 225
Easton, Charles 255 213 190
Any help or hints on what I'm missing would be greatly appreciated.
When you call bowler.substring(0, indent) you actually substring the name of the bowler, so it doesn't contains the scores.
If you want to get only the scores part of the string, use bowler.substring(indent + 1, bowler.length). You still have to break it to 3 different strings and convert each one of them into a integer.
Anyway, a better approach will be to split each line into an array of strings using String#split print the first strings, since it is the bowler name and then convert the last 3 into integers. You can also use Scanner#nextInt() and Scanner#nextString() methods, since the structure of the file is known.
Introduced a class Bowler to store each row of data. You can now use the list of bowler objects to continue your process. String.split() gives an array of Strings tokenized based on the character specified. Space has been used here to split.
import java.util.*;
import java.io.*;
public class lab5 {
public static void main(String args[]) throws IOException {
Scanner scan = new Scanner(new File("C:\\TEMP\\bowl1.txt"));
String bowler;
List<Bowler> bowlers = new ArrayList<Bowler>();
while (scan.hasNext()) {
bowler = scan.nextLine();
if (!bowler.trim().equals("")) {
System.out.println("\n" + bowler);
String[] tokens = bowler.split(" ");
Bowler b = new Bowler(tokens[0], tokens[1], Integer.parseInt(tokens[2]), Integer.parseInt(tokens[3]),
Integer.parseInt(tokens[4]));
bowlers.add(b);
}
} // end fileScan while
for (Bowler bow : bowlers) {
System.out.println(bow.score1 + ", " + bow.score2 + ", " + bow.score3);
}
}// end main
}// end class
class Bowler {
String firstName;
String lastName;
int score1;
int score2;
int score3;
public Bowler(String firstName, String lastName, int score1, int score2, int score3) {
this.firstName = firstName;
this.lastName = lastName;
this.score1 = score1;
this.score2 = score2;
this.score3 = score3;
}
}
Okay this is a straight forward method....it is done only using lastIndexOf(" ") and substring("") method as you said. but there are lot efficient and more easy ways as Narayana Ganesh mentioned above....this method also can be more
precised if you want....
import java.io.;
import java.util.;
public class test2
{
public static void main(String[] args)
{
String bowler;
String name;
int score1 = 0, score2 = 0, score3 = 0;
int game = 0;
int average = 0;
String filename = "bowl1.txt";
File textfile = new File(filename);
try{
Scanner scan = new Scanner(textfile);
while (scan.hasNextLine()){
bowler = scan.nextLine();
System.out.println("\n" + bowler);
String text1 = "";
String text2 = "";
int index=0;
int length = bowler.length();
index = bowler.lastIndexOf(" ");
text1 = bowler.substring(0,index);
text2 = bowler.substring(index+1,length);
score1 = Integer.parseInt(text2);
length = text1.length();
index = text1.lastIndexOf(" ");
text2 = text1.substring(index+1,length);
text1 = text1.substring(0,index);
score2 = Integer.parseInt(text2);
length = text1.length();
index = text1.lastIndexOf(" ");
text2 = text1.substring(index+1,length);
text1 = text1.substring(0,index);
score3 = Integer.parseInt(text2);
System.out.println(score1);
System.out.println(score2);
System.out.println(score3);
System.out.println("Total:"+(score1 + score2 + score3));
}
}catch(FileNotFoundException e){};
}
}

Exception in thread "main" java.lang.NumberFormatException: empty String

my program is meant to read from a txt and print certain parts of it. when i try to set Double d4 it gives me an error saying that string is
empty although it's not. and it's also not an issue of formatting since d1-5 worked fine when i removed the line. i also printed data[5] and that showed the proper line from the txt.
import java.util.Scanner;
import java.io.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
public class AAAAAA {
public static void main (String[] args)throws IOException {
final String fileName = "classQuizzes.txt";
//1)
Scanner sc = new Scanner(new File(fileName));
//declarations
String input;
double total = 0.0;
double num = 0;
double count = 0;
double average = 0;
String lastName;
String firstName;
double minimum;
double max;
//2) process rows
input = sc.nextLine();
System.out.println(input);
while (sc.hasNextLine()) {
String line = sc.nextLine();
System.out.println(line);
// split the line into pieces of data separated by the spaces
String[] data = line.split(" ");
// get the name from data[]
System.out.println("d5 " +data[4]);
firstName = data[0];
lastName = data[1];
Double d1 = Double.valueOf(data[2]);
Double d2 = Double.valueOf(data[3]);
Double d3 = Double.valueOf(data[4]);
Double d4 = Double.valueOf(data[5]);
Double d5 = Double.valueOf(data[6]);
// do the same...
System.out.println("data " + d3);
total += d1 + d2 + d3 + d5;
count++;
//find average (decimal 2 points)
System.out.println(count);
average = total / count;
System.out.println("Total = " + total);
System.out.println("Average = " + average);
//3) class statistics
//while
}
System.out.println("Program created by");
}
}
The line might not be empty, but when you split it at spaces, if there are two spaces in a row, you will get empty strings in the split. To prevent this, change
String[] data = line.split(" ");
to
String[] data = line.split(" *");
or, perhaps better, since it will deal with tabs and other white space:
String[] data = line.split("\\s*");
To track down these kinds of problems yourself (and to verify that I've diagnosed the problem correctly), you should print out each element of the split array, as well as verify the array length is what you expect.

Keep track of string matches to create a new ID

This is the prompt
Write a program that reads in a name and outputs an ID based on the name. The ID should be uppercase and formatted using the first three letters of the name and three digits starting at 005. The digits should be incremented by 5 if an ID already exists.
This is my code so far
import java.util.Scanner;
public class substring_match {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
int id = 5;
int repeatId = 5;
int nameCount = 1;
String[] nameArray = new String[5];
String name;
String subName = null;
for (int i = 0; i<nameArray.length; i++){
name = scan.nextLine();
subName = name.substring(0, 3);
nameArray[i] = subName;
}
for(int x = 0; x < nameArray.length; x++){
if(nameArray[x].substring(0, 3) == subName.substring(0,3)){
nameCount = nameCount + 1;
System.out.println("nameCount " + nameCount);
repeatId = nameCount * id;
if(repeatId == 5){
System.out.println(nameArray[x].toUpperCase() + "00" + repeatId);
}else{ // if repeatId is 10 or higher, won't need the extra 0
System.out.println(nameArray[x].toUpperCase() + "0" + repeatId);
}
}else{
System.out.println(nameArray[x].substring(0, 3).toUpperCase() + "00" + id);
}
}
}
}
I would probably consider doing this another way...
Have an empty hashmap<String sub, int multiplier>
Read in the name
Generate the subname
Fetch from or create subname in hashmap
If new, set multiplier to 1
If exists, increment multiplier
Return String.format(ā€œ%s%3dā€, subname, multiplier x 5).toUpperCase()
I would give you code but writing the above was hard enough on an iPad šŸ˜‚

Categories

Resources