String Manipulation ? and OOP issue JAVA - java

Henlo,
My issue is that I have to create two objects using two different constructors:
public SmartHome(int size) {
smrtDev = new SmartDevice[size];
}
public SmartHome(SmartDevice[] values) {
smrtDev = values;
}
For the first one I've achieved it as so with this code snippet:
Scanner myObj = new Scanner(System.in);
System.out.println("Enter size of SmartHome: ");
int size = myObj.nextInt();
SmartHome firstSmartHomeObject = new SmartHome(size);
for(int i=0; i<size;i++) {
System.out.println("\nName: ");
String name = myObj.next();
System.out.println("\nLocation: ");
double location = myObj.nextDouble();
System.out.println("\nIs on?: ");
boolean switchedOn = myObj.nextBoolean();
firstSmartHomeObject.insertDevice(name, location, switchedOn);
}
The second insertDevice() takes in SmartDevice dev
and I have no idea how to do so. What I've attempted is to do SmartDevice dvc+(i) = new SmartDevice(name, location, switchedOn); at the end of the loop but have no idea on how to create dvc1/dvc2/dvc3 etc... , not even sure if this would be the correct way to tacle this problem :(

Supposed to do: :s
SmartDevice dvc = new SmartDevice(name, location, switchedOn); secondSmartHomeObject.insertDevice(dvc);

Related

Why am I getting "NoSuchElementException" When I can print everything from textfile?

I'm able to read everything from the text file and print the data yet I get a "No Such Element" Exception. All the solutions i've found say to use "HasNext" in while loop and yet it doesn't seem to work for me
public void fileReader() throws IOException {
String id;
String brand;
int yearOfManufacture;
int numSeats;
double rentalPerDay;
double insurancePerDay;
double serviceFee;
double discount;
String model;
String type;
String color;
ArrayList<Vehicle> vehicleArray = new ArrayList<>();
File file = new File("C:/Users/jockg/Downloads/Fleet (1).csv");
Scanner scan = new Scanner(file);
scan.useDelimiter("n/n");
while (scan.hasNext() || scan.hasNextDouble() || scan.hasNextInt()) {
id = scan.next();
System.out.println(id);
brand = scan.next();
System.out.println(brand);
model = scan.next();
System.out.println(model);
type = scan.next();
System.out.println(type);
yearOfManufacture = Integer.parseInt(scan.next());
System.out.println(yearOfManufacture);
numSeats = Integer.parseInt(scan.next());
System.out.println(numSeats);
color = scan.next();
System.out.println(color);
rentalPerDay = Double.parseDouble(scan.next());
System.out.println(rentalPerDay);
insurancePerDay = Double.parseDouble(scan.next());
System.out.println(insurancePerDay);
serviceFee = Double.parseDouble(scan.next());
System.out.println(serviceFee);
if (scan.next().equals("N/A")) {
discount = 0;
} else {
discount = Double.parseDouble(scan.next());
}
System.out.println(discount);
Car newCar = new Car(id, brand, yearOfManufacture, numSeats, rentalPerDay, insurancePerDay, serviceFee,
discount, model, type, color);
vehicleArray.add(newCar);
}
}
C001,Toyota,Yaris,Sedan,2012,4,Blue,50,15,10,10
C002,Toyota,Corolla,Hatch,2020,4,White,45,20,10,10
C003,Toyota,Kluger,SUV,2019,7,Grey,70,20,20,10
C004,Audi,A3,Sedan,2015,5,Red,65,10,20,10
C005,Holden,Cruze,Hatch,2020,4,Green,70,10,10,10
C006,BMW,X5,SUV,2018,7,White,100,25,20,10
C007,BMW,320i,Sedan,2021,5,Grey,75,10,15,N/A
C008,Ford,Focus,Sedan,2014,5,Red,45,10,10,N/A
C009,Ford,Puma,SUV,2015,5,Black,70,20,15,20
This is the Exception I get:
your CSV has actually two delimiters: comma and new line. Try: scan.useDelimiter(",|\\R");
discount is read twice for numeric values, try:
String discountStr = scan.next();
discount = discountStr.equals("N/A") ? 0 : Double.parseDouble(discountStr);
if (scan.next().equals("N/A")
might be your problem here. from what it looks like, this is not doing what you intend on doing.
When you call scan.next() it will read regardless of whether it is equal to "N/A"
you put an else statement after this and say discount = Double.parseDouble(scan.next() and I presume you are talking about the same scan.next() that you called in the initial if statement, but that line has already passed. You need to store this scan.next() in a variable and then check if it is "N/A".

Using a Method to update a 2D Array by finding a matching value and then updating with a different input variable

Lets say I have a public class called GameBoard that will be a two dimensional array with 4 rows and 5 columns. The spaces in the array are filed with String values from 1 to 20. A card will be drawn that has a name (King of Spades for example) . If the user inputs 15 I will store it in a String variable called userLocation. What would be the most efficient way to create a method that takes the input location and updates the array with the name of the Card? Would a for loop be most efficient?
public GameBoard() {
square = new String[4][5];
square[0][0] = new String("1");
square[0][1] = new String("2");
square[0][2] = new String("3");
square[0][3] = new String("4");
square[0][4] = new String("5");
square[1][0] = new String("6");
square[1][1] = new String("7");
square[1][2] = new String("8");
square[1][3] = new String("9");
square[1][4] = new String("10");
square[2][1] = new String("11");
square[2][2] = new String("12");
square[2][3] = new String("13");
square[3][1] = new String("14");
square[3][2] = new String("15");
square[3][3] = new String("16");
square[2][0] = new String(17);
square[3][0] = new String(18);
square[2][4] = new String(19);
square[3][4] = new String(20);
}
My preferred method as of now would look something like this but it gives me the error code "type mismatch:cannot convert string to boolean" under userLocation = board[i][j]
public String[][] updateBoard(String userLocation, Card card, String[][] board) {
for (int i = 0; i <4; i++)
{
for (int j = 0; j < 5; j++)
{
if(userLocation = board[i][j]) {
board[i][j] = card.name;
}
}
}
return board;
}
So the reason it will not compile is your = does not return a boolean expression. == would, but it's still not what you want, since you want to check if the String contents are the same, not if they're the same object, so use .equals.
But, no, I think you don't want to depend on strings to identify locations. What if you want to replace a card? And why look through everything when you need not?
Rather if i is some number between 1 and 20, identify the corresponding spot in the array by square[(i-1)/5][(i-1)%5]
That should bypass the issue you are having with matching strings.
So for example, your constructor becomes:
public GameBoard() {
square = new String[4][5];
for (int i=1; i<=20;i++){
square[(i-1)/5][(i-1)%5]=""+i;//initialize with 1 to 20 if you like
}
and userLocation is an int.

Reading a file and storing them into a 2D Array of Objects in Java?

I have a project in Java I am trying to do (for fun) but I am struggling in this step. I have cities I am trying to read from two countries, the United States and China and I am having trouble reading the file in. I am trying to use a delimiter to separate the cities in China and The United States.
Here is my text file "Cities.txt"
San Francisco 9874343 543443 193838
Los Angeles 3900000 52000 22000
Baltimore 622104 34423 1234
Houston 2196000 45444 29393
New York City 8500000 54000 27000
Philadelphia 1510000 654334 21343
Boston 6423344 345334 13443
Chicago 2719000 39000 19282
San Diego 1323343 432343 18374
Dallas 1258000 423343 17363 |
Beijing 21500000 32454 23454
Hangzhouu 9018000 32343 192828
Shanghia 24500000 432345 23444
GuangZhou 20800654 323455 298383
Wuhan 10670000 54344 302344
Swatow 5391028 43345 23235
Hong Kong 7234800 39039 278383
Macau 650900 34543 17364
Shenzhen 10630000 44343 19883
Zibo 2980000 49383 20009
Here is my main Java class. I also have a Cities class with a constructor, getters/setters and a toString();
static Cities[][] multi = new Cities[2][10];
public static void main(String[] args) throws FileNotFoundException {
System.out.println("The point of this program is to compare different cities in the two major superpower countries, \n The United States and China.");
System.out.println("The information in the cities in stored in a 2D array of Objects and is pre-created in a text files. \n Please pick an option to manipulate the information in the array.");
Scanner in = new Scanner(System.in);
String name = " ";
int population = 0;
double wage = 0.0;
int density = 0;
Cities cities = new Cities(name,population,wage,density);
boolean exit = false;
readcity(name);
String options = "1). Print all the cities. \n 2). Print just the united states cities. \n 3). Print just the China Cities \n 90). Exit program";
System.out.println(options);
int decide = in.nextInt();
while (!exit)
{
switch (decide) {
case 1:
{
printarray(name,population,wage,density);
}
case 2: {
}
case 3: {
}
case 90: {
exit = true;
}
}
}
}
public static Cities readcity(String fline)
{
try {
String name; int population; double wage; int density;
int countries = 2; int city = 10;
Scanner fileScan = new Scanner(new File("/src/Cities.txt"));
fileScan.useDelimiter("|");
while (fileScan.hasNext()) {
name = fileScan.next();
population = fileScan.nextInt();
wage = fileScan.nextDouble();
density = fileScan.nextInt();
Cities City = new Cities(name, population, wage, density);
return new Cities(name,population,wage,density);
}
fileScan.nextLine();
Cities City = readcity(fline);
multi[countries][city] = City;
return City;
}
catch(Exception e) {
System.out.println("Looks like there was an error.");
}
Cities City = readcity(fline);
return City;
}
public static void printarray(String name, int population, double wage, int density) throws FileNotFoundException{
Cities cities = new Cities(name,population,wage,density);
for (int row =0; row < multi.length; row++){
for (int column = 0; column < multi[row].length; column++){
System.out.println(multi[row][column]);
}
System.out.println();
}
cities.toString();
}
}
The method seems to be doing an infinite recursive call, but I am wondering how I would fix this. Would I do the same approach for two files and implement that way? Or would I take them out the method to read in the cities and implement them via a diffrent approach? I am weak with files handling and using a 2d array is even a heftier layer on top of that. Trying to fix my weaknesses so any help you can give me would be beneficial.
Well, where do I start...
Your readcity() method is calling itself recursively. I don't think this was the idea. Try removing these calls.
You initial call to readcity() is with the argument " ". Not sure what was the intention here.
Opening bracket "{" after "while (fileScan.hasNext())" is apparently lost in the code above.
In general, try naming your classes and variables according to their plurality. If an object is supposed to hold one city, its class should be called "City". If an object is supposed to hold a collection of cities, then you can call the class "Cities".
No need for recursion to read from file in this situation. I definitely recommend writing comments so that an outside user knows what everything is doing basically. Um. I would also make getting the data from the file easier since you don't have much experience with file handling I'm assuming?.
I reformatted the file to make things easier in a sense. That way you can get each information between the ',' by using split.
US:
San Francisco, 9874343, 543443, 193838
Los Angeles, 3900000, 52000, 22000
Baltimore, 622104, 34423, 1234
Houston, 2196000, 45444, 29393
New York City, 8500000, 54000, 27000
Philadelphia, 1510000, 654334, 21343
Boston, 6423344, 345334, 13443
Chicago, 2719000, 39000, 19282
San Diego, 1323343, 432343, 18374
Dallas, 1258000, 423343, 17363
China:
Beijing, 21500000, 32454, 23454
Hangzhouu, 9018000, 32343, 192828
Shanghia, 24500000, 432345, 23444
GuangZhou, 20800654, 323455, 298383
Wuhan, 10670000, 54344, 302344
Swatow, 5391028, 43345, 23235
Hong Kong, 7234800, 39039, 278383
Macau, 650900, 34543, 17364
Shenzhen, 10630000, 44343, 19883
Zibo, 2980000, 49383, 20009
and this is the class I made to read the data and store in a 2d array of cities.
public class CityReader {
public static void main(String[] args)
{
City[][] cities = new City[2][10];
readFileInto2D("src/Cities.txt",cities);
//User prompt on what they want to here?
print2DArray(cities);
}
public static void readFileInto2D(String filename,City[][] cities)
{
City city;
String name = "";
int population = 0;
int wage = 0;
int density = 0;
try {
Scanner scan = new Scanner(new File(filename));
String line;
String[] parsed;
//Read US:
if(scan.hasNext())
line = scan.nextLine();
//Keep track of rows
int indexer = 0;
//Keep track of columns
int indexer2 = 0;
while(scan.hasNext())
{
line = scan.nextLine();
if(line.contains("China"))
{
indexer += 1;//Go to next row
indexer2 = 0;//Start index at beginning of column.
line = scan.nextLine();//Read next line, ignore line with China.
}
parsed = line.split(", "); //This splits each line
//into an array of name,pop,wage,and density
name = parsed[0];
population = Integer.parseInt(parsed[1]);
wage = Integer.parseInt(parsed[2]);
density = Integer.parseInt(parsed[3]);
city = new City(name,population,wage,density);
cities[indexer][indexer2] = city;//Add to 2D Array.
indexer2++;
}
} catch (IOException ioe) {
// TODO Auto-generated catch block
ioe.printStackTrace();
}
}
public static void print2DArray(City[][] cities)
{
//row
for(int i = 0; i < cities.length; i++)
{
//column
for(int j = 0; j < cities[i].length;j++)
{
City city = cities[i][j];
//used getters to print information.
System.out.printf("%s %d %d %d\n",city.getName(),
city.getPopulation(),city.getWage(),
city.getDensity());
}
System.out.println();
}
}
}
Now this isn't perfect and a user can easily implement errors due to no error checking. This was more of showing one way to do it. The city class used is basic with just the constructor and getters and setters.

How to put values from a text file into an object array in java?

So I am trying to create an object array that from a text file. The objects I am placing in the array are people objects with 4 parameters. 1st name, last name, an ID number and a height. The text file has a certain number of lines and each element is separated by an exclamation mark. I am trying to take each of the 4 elements to create an object and then place that object into an object array. Here is my code up until now. Also because I am new to java, there is not a lot that I know so the code needs to be simple.
import java.io.File;
import java.io.IOException;
import java.util.*;
public class Participants {
public static void main(String[] args) {
String array[] = new String[35];
Object participants[] = new Object[35];
int count = 0;
int counter = -1;
try {
File myFile1 = new File("Participants.txt");
Scanner scan1 = new Scanner(myFile1);
while (scan1.hasNext()) {
counter++;
array[counter] = scan1.next();
}
} catch (IOException ioe) {
System.out.println("The file can not be read");
}
for (int i = 0; i < array.length; i++) {
StringTokenizer st = new StringTokenizer(array[i], "!");
while (st.hasMoreTokens()) {
People person = new People(st.nextToken(), st.nextToken(), st.nextToken(),
st.nextToken());
participants[i] = person;
}
}
}
}
I commented that your code basically looks okay. There are some problems I spotted, and I think you may be running into them. You are probably getting a
Exception in thread "main" java.lang.NullPointerException
at java.util.StringTokenizer.<init>(Unknown Source)
at java.util.StringTokenizer.<init>(Unknown Source)
at Participants.main(Participants.java:22)
because arrays[i] is empty in
StringTokenizer st = new StringTokenizer(array[i], "!");
which is because you allocate 35 entries:
String array[] = new String[35];
and the file contains less lines than that. At least, that's what I'm getting it with this input file:
A!B!C!D
E!F!G!H
I!J!K!L
which is to be expected.
If I change the first line of the input file into
A!B!C
I get
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at Text2ObjArray.main(Text2ObjArray.java:28)
which is because you only check once for a token, but then proceed to read four:
while (st.hasMoreTokens()) {
Person person = new Person(st.nextToken(), st.nextToken(), st.nextToken(), st.nextToken());
I'll update with a solution, if it is needed, but here are two suggestions:
1) use an ArrayList instead of an array[]:
2) Check what you parse: make sure there are 4 tokens per line, and deal with the exceptional case that they are not 4.
UPDATE
Basically, there's nothing wrong with your program. You already know "
How to put values from a text file into an object array in java?".
Your program runs just fine if you feed it a file with exactly 35 lines containing at least 3 exclamation marks each. If not, it throws the appropriate exceptions:
a NullPointerException if there are less than 35 lines and
an ArrayIndexOutOfBoundsException if there are more, and
a NoSuchElementException if there are less than 3 exclamation marks on any of the lines.
(Unless, there is a problem is in the People class which is unlikely if it is a POJO).
Your code only needed a few minor changes to make it work for files with other content. I've kept it simple:
import java.io.File;
import java.io.IOException;
import java.util.*;
public class Text2ObjArray {
public static void main(String[] args) {
Person[] participants = loadFile(new File(args.length > 0
? args[0] : "Participants.txt"));
for (Person p : participants)
System.out.println("Participant: " + p);
}
I split off main merely as good practice - see 'top-down' and 'bottom-up'.
To address the NullPointerException and ArrayIndexOutOfBoundsException We'll use an ArrayList instead of an array[] to keep track of the lines we read from the file. The advantage of an ArrayList is that it can grow and shrink, which is useful if you don't know for sure if "Participants.txt" always contains 35 lines.
Also it saves us from replacing our array with a bigger one when it's full. It's a cheap, handy upgrade from an array[], and all that has changed is writing
array.get(i) instead of array[i]
array.set(i,foo) instead of array[i]=foo and
array.add(foo) instead of array[counter++]=foo and
array.size() instead of array.length. It is a dynamic array, so you can insert into any position, remove etc.
private static Person[] loadFile(File file) {
List<String> lines = new ArrayList<>();
try (Scanner scan1 = new Scanner(file)) {
while (scan1.hasNext())
lines.add(scan1.next());
} catch (IOException e) {
System.out.println("File read error: " + e.getMessage());
}
This section is changed only in that it reads up to 4 tokens, dealing with the NoSuchElementException:
Person participants[] = new Person[lines.size()];
for (int i = 0; i < lines.size(); i++) {
StringTokenizer st = new StringTokenizer(lines.get(i), "!");
String[] fields = new String[4];
for (int k = 0; k < fields.length && st.hasMoreTokens(); k++)
fields[k] = st.nextToken();
participants[i++] = new Person(fields[0], fields[1], fields[2], fields[3]);
}
return participants;
}
}
To run it successfully you'll need to replace Person to People or use this Person class:
public class Person {
private String id;
private String lName;
private String fName;
private String height;
public Person(String id, String fName, String lName, String height) {
this.id = id;
this.fName = fName;
this.lName = lName;
this.height = height;
}
public String toString() {
return "Person[" + id + ": " + lName + ", " + fName + ", " + height + "]";
}
}
I hope that this has been helpful.

Sorting an array of students by last name alphabetically in Java

I currently have this program read the contents of a text file and calculate the averages and amount of test scores taken and print them out neatly in a small data table. These are the names, amount of quizes taken and average of each student:
James Tiberius Kirk 8 91.63
Buffy Summers 7 83.14
Tom Baker 15 100.00
Malcolm Reynolds 9 84.22
Elizabeth Bennet 9 93.33
John Blutarsky 9 0.00
Dorthy Gale 6 85.83
All of these Students are stored within the Array named Anames[]. I was wondering if it was at all possible to sort these students alphabetically by last name using the code that I have now. When I run the program it gives me the error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1927)
at text.reader.TextReader.compareLastNames(TextReader.java:117)
at text.reader.TextReader.main(TextReader.java:94)
Here is the code of my main class:
public static void main(String[] args)throws IOException{
Double score=0.0;
int b,j;
String tempfirst = "";
String templast = "";
Student Anames[] = new Student[30];
Student Temp[] = new Student [1];
int Stucount = 0;
Scanner reader = new Scanner(new File("quizScores.txt"));
boolean runProgram = true;
PrintWriter writer = new PrintWriter(new File("scoreReport.txt"));
//prints header for report
System.out.println("Name Number Quizes Quiz Socres");
writer.println("Name Number Quizes Quiz Socres");
//check to see if end of file string
while (!reader.hasNext("-10")){
String name="", first="", last="";
//gets the name from file
while(!reader.hasNextDouble()){
last = reader.next();
while (!reader.hasNextDouble()){
first = first+reader.next()+" ";
}
name=first+last;
}
//creates new student with given name
Student newStudent = new Student(first, last);
Anames[Stucount] = newStudent;
Stucount++;
//gets the quiz scores and makes sure does not averge in the end of file string.
while (reader.hasNextDouble()&& !reader.hasNext("-10")){
newStudent.addQuiz(reader.nextDouble());
}
//Prints out the formated data
System.out.printf("%-30s%4.0f%30.2f \n",newStudent.getName(), newStudent.getQuizNumber(), newStudent.getAverage());
writer.printf("%-30s%4.0f%30.2f",newStudent.getName(), newStudent.getQuizNumber(), newStudent.getAverage());
writer.println();
}
System.out.println("\n");
for (b = 0; b < Stucount; b++){
int INTEGERTEMP = b;
for (j= b+1; j < Stucount; j++){
int INTEGERTEMP2 = j;
if ((compareLastNames(Anames[INTEGERTEMP].getLAST(), Anames[INTEGERTEMP2].getLAST()))>0){
Temp[0] = Anames[b];
Anames[b] = Anames[j];
Anames[j] = Temp[0];
}
}
}
System.out.println("Name Number Quizes Quiz Socres");
for (int i = 0; i < Stucount; i++) {
System.out.printf("%-30s%4.0f%30.2f \n", Anames[i].getName(), Anames[i].getQuizNumber(), Anames[i].getAverage());
}
writer.close();
}
private static int compareLastNames(String a, String b){
int index_a = a.lastIndexOf(" ");
String surname_a = a.substring(index_a);
int index_b = b.lastIndexOf(" ");
String surname_b = b.substring(index_b);
int lastNameCmp = surname_a.compareToIgnoreCase(surname_b);
return lastNameCmp;
}
Here is the Student.java which contains most of the methods used:
public Student (String inName, String inLast){
studentName=inName;
studentLast = inLast;
quizAverage = 0;
quizScore=0;
numberQuizes=0;
}
public void addQuiz(double inQuiz){
quizScore += inQuiz;
numberQuizes++;
}
public double getAverage(){
quizAverage = quizScore/numberQuizes;
return quizAverage;
}
public String getName(){
return studentName+studentLast;
}
public double getQuizNumber(){
return numberQuizes;
}
public String getLAST(){
return studentLast;
}
You can use java.util.Arrays.sort(Student [] arr, Comparator<Student> comp) instead of your own compare code. In single line you can achieve it like this:
Student arr[];//considering this array you will populate
Arrays.sort(arr,new java.util.Comparator<Student>(){
public int compare(Student o1, Student o2) {
return o1.studentLast.compareTo(o2.studentLast);
}
});
//then the arr will be sorted with studentLast name
Let's work our way back from your exception to figure out where the problem is. First, it tells us we've got a StringIndexOutOfBoundsException on line 117; that is, the line (it might actually be the surname_b line, you've removed code from the class that means I can't match up the lines properly)
String surname_a = a.substring(index_a);
You'll notice the message from the exception helpfully tells us that the index used was -1. Let's take a look at why a.lastIndexOf(" "); would return -1. We see in the documentation for String that it returns -1 when the character does not occur in the String.
Now, let's work another step back in the Exception's stack trace to figure out why there's no space in that String. The Exception tells us to check line 94, where we see
if ((compareLastNames(Anames[INTEGERTEMP].getLAST(), Anames[INTEGERTEMP2].getLAST()))>0){
So, what's going on here? We're passing in the last names (and just the last names) from each of the students into our comparison function. The last names, for the most part, have no spaces in them.
So, how do we fix this? Well, you'll have to change your function to only take substrings of the surname if there actually is a space in them, i.e. if the index returned isn't -1.
Once you've got the comparison function done, I recommend looking at how to write an Object that implements the Comparable interface. This will allow you to use library sorting functions, which will be faster and less buggy than your own sorting functions (most likely!).

Categories

Resources