I am creating a reverse polish notation calculator in java that accepts file input. One of the requirements is that certain statistics are generated from the calculations too.
below are two snippets of my code.
public static int invalidlines = 0;
public static int validlines = 0;
public static int stats1 = 0;
private static Scanner input;
public static ArrayList<String> validList = new ArrayList<String>();
public static ArrayList<Integer> stats = new ArrayList<Integer>(); {
if (stats.isEmpty());
display("n/a");
}
static int sum(ArrayList<Integer> stats)
{
int value = 0;
for(int i : stats)
{
value += i;
}
return value;
}
Thats the code for my array lists.
static void fileInput() throws IOException
{
input = new Scanner(System.in);
try
{
String currentLine = new String();
int answer = 0;
//Open the file
display("Enter File Name: ");
FileInputStream fstream = new FileInputStream(input.nextLine()); // make a input stream
BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); // pass input stream to a buffered reader for manipulation
String strLine; // create string vars
//loop to read the file line by line
while ((strLine = br.readLine()) != null) { // Whilst the buffered readers read line method is not null, read and validate it.
currentLine = strLine;
if(strLine.trim().isEmpty())
{
display("You have entered a blank line, the program will now exit");
System.exit(0);
}
if(isValidLine(currentLine))
{
validList.add(currentLine);
validlines++;
String[] filearray = new String[3];
filearray = currentLine.split(" ");
int val1 = Integer.parseInt(filearray[0]);
int val2 = Integer.parseInt(filearray[1]);
display("Your expression is: " + filearray[0] + " " + filearray[1] + " " + filearray[2]);
switch(filearray[2]) {
case("+"):
answer = val1 + val2;
stats.add(answer);
break;
case("-"):
answer = val1 - val2;
stats.add(answer);
break;
case("/"):
answer = val1 / val2;
stats.add(answer);
break;
case("*"):
answer = val1 * val2;
stats.add(answer);
break;
}
display("Your calculation is " + filearray[0] + " " + filearray[2] + " " + filearray[1] + " = " + answer);
}
}
}
catch (FileNotFoundException e)
{
display("Please Enter a valid file name");
}
display("Evaluations Complete");
display("=====================");
display("Highest Result: " + Collections.max(stats));
display("Lowest Result: " + Collections.min(stats));
display("Aggregate Result: " + sum(stats));
display("Average Result: " + sum(stats) / validlines);
display("Total Valid Lines: " + validlines);
display("Total Invalid Lines: " + invalidlines);
}
I require it so that if there are no valid calculations from the text file that the highest, lowest and average result displays show as 'n/a' instead they bring the java error in my console shown below.
Exception in thread "main" java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(Unknown Source)
at java.util.Collections.max(Unknown Source)
at Assignment.fileInput(Assignment.java:156)
at Assignment.main(Assignment.java:177)
Replace
Collections.max(stats)
with
(!stats.isEmpty() ? Collections.max(stats) : "n/a")
(similarly for Collections.min)
You are also going to want to handle the case of validlines == 0 to avoid the division by zero error in / validlines.
Related
This is a project for school, and I am having difficulty figuring out why it is this way. We are to create a program that will put data into a text file, but whenever I run my code, it will output to the file, but it will be at line 224, and not start at the beginning. Does anyone know why this may be? Here is my code
import java.nio.file.*;
import java.io.*;
import java.nio.ByteBuffer;
import static java.nio.file.StandardOpenOption.*;
import java.util.Scanner;
import java.nio.channels.FileChannel;
public class CreateCustomerFile
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
Path file = Paths.get("C:\\Users\\brady\\IdeaProjects\\TestNew\\Customers.txt");
String s = "000, ,00000" + System.getProperty("line.separator");
String[] array;
byte[] data = s.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(data);
FileChannel fc = null;
final int recordSize = s.length(); //Size of record
final int recordNums = 1000; //Number of records stored in file
final String QUIT = "exit";
String custString;
int custNum;
String lastName;
String zipCode;
String fileNum;
try
{
OutputStream output = new BufferedOutputStream(Files.newOutputStream(file, CREATE));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
for(int count = 0; count < recordNums; ++count)
writer.write(s, 0, s.length());
writer.close();
}
catch(Exception e)
{
System.out.println("Error message: " + e);
}
try
{
fc = (FileChannel)Files.newByteChannel(file, READ, WRITE);
System.out.print("Enter customer number or 'exit' to quit >> ");
custString = input.nextLine();
while(!(custString.equalsIgnoreCase(QUIT)))
{
custNum = Integer.parseInt(custString);
buffer = ByteBuffer.wrap(data);
fc.position((long) custNum * recordSize);
fc.read(buffer);
s = new String(data);
array = s.split(",");
fileNum = array[0];
if(!(fileNum.equals("000")))
System.out.println("Sorry - customer " + custString + " already exists");
else
{
System.out.print("Enter the last name for customer #" + custNum + ": ");
lastName = input.nextLine();
StringBuilder sb = new StringBuilder(lastName);
sb.append(" ");
sb.setLength(6);
lastName = sb.toString();
System.out.print("Enter zip code: ");
zipCode = input.nextLine();
s = custString + "," + lastName + "," + zipCode + System.getProperty("line.separator");
data = s.getBytes();
buffer = ByteBuffer.wrap(data);
fc.position((long) custNum * recordSize);
fc.write(buffer);
}
System.out.print("Enter next customer number or 'exit' to quit: ");
custString = input.nextLine();
}
fc.close();
}
catch (Exception e)
{
System.out.println("Error message: " + e);
}
}
}
Your code needs more input validation, any user provided string input must be sized for the output field, no matter the input.
lastName is done correctly, but customer number and zip code are left to chance, and can throw off the record count in the file.
A customer id entered as "1" is 2 characters shorter than "001" thus upsetting the fixed length record for the remaining file.
This program gets user input for 2 teams and 2 results, separates them with the " : " delimiter, then stores them in the array, when the user enters the word "stop" it stops asking for user input and is meant to display the results and stats of the match (which is not yet added into the code). the problem I'm having is if I type more than one line of match results then type 'stop', it only displays the first line of user input back to the console and not any of the others? input example: "Chelsea : Arsenal : 2 : 1".
public static final String SENTINEL = "stop";
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
String hometeam = new String();
String awayteam = new String();
String homescore = new String();
String awayscore = new String();
int result0;
int result1;
System.out.println("please enter match results:");
// loop, wil ask for match results ( b < () )
for (int b = 0; b < 100; b++) {
String s = sc.nextLine();
// stop command
while (sc.hasNextLine()) { // better than the for loop
String line = sc.nextLine();
String results[] = s.split(" : "); // parse strings in between
// the
for (String temp : results) {
hometeam = results[0];
awayteam = results[1];
homescore = results[2];
awayscore = results[3];
}
// convert 'score' strings to int value.
result0 = Integer.valueOf(results[2]);
result1 = Integer.valueOf(results[3]);
if ("stop".equals(line)) {
System.out.println(Arrays.toString(results));
return; // exit
}
The reason that it outputs the first results you entered is because results is assigned to s.split(" : "). s never changes in the first iteration of the outer for loop, so s.split(" : ") never changes. Your results always holds the first match results!
You have written your code very wrongly.
First, why do you have a while loop inside a for loop? The for loop is redundant.
Second, you can't use arrays for this. Try an ArrayList. Arrays don't have the ability to change its size dynamically.
Third, I recommend you to create a class for this, to represent a MatchResult.
class MatchResult {
private String homeTeam;
private String awayTeam;
private int homeScore;
private int awayScore;
public String getHomeTeam() {
return homeTeam;
}
public String getAwayTeam() {
return awayTeam;
}
public int getHomeScore() {
return homeScore;
}
public int getAwayScore() {
return awayScore;
}
public MatchResult(String homeTeam, String awayTeam, int homeScore, int awayScore) {
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
this.homeScore = homeScore;
this.awayScore = awayScore;
}
#Override
public String toString() {
return "MatchResult{" +
"homeTeam='" + homeTeam + '\'' +
", awayTeam='" + awayTeam + '\'' +
", homeScore=" + homeScore +
", awayScore=" + awayScore +
'}';
}
}
Then, you can create an ArrayList<MatchResult> that stores the user input.
Scanner sc = new Scanner(System.in);
String hometeam;
String awayteam;
int homescore;
int awayscore;
ArrayList<MatchResult> list = new ArrayList<>();
System.out.println("please enter match results:");
while (sc.hasNextLine()) { // better than the for loop
String line = sc.nextLine();
if ("stop".equals(line)) {
System.out.println(Arrays.toString(list.toArray()));
return; // exit
}
String results[] = line.split(" : "); // parse strings in between
hometeam = results[0];
awayteam = results[1];
homescore = Integer.valueOf(results[2]);
awayscore = Integer.valueOf(results[3]);
list.add(new MatchResult(hometeam, awayteam, homescore, awayscore));
}
try just adding another array
string[] matches = new string[]{};
then input your values into the array. I am using b since that is the int variable in your loop. I also put in + " : "
matches [b] = hometeam.tostring() + " : " + awayteam.tostring() + homescore.tostring() + " : " + awayscore.tostring();
then change the print to
System.out.println(Arrays.toString(matches));
i think this should work, but I wasn't able to test it.
public static final String SENTINEL = "stop";
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
string[] matches = new string[]{};
String hometeam = new String();
String awayteam = new String();
String homescore = new String();
String awayscore = new String();
int result0;
int result1;
System.out.println("please enter match results:");
// loop, wil ask for match results ( b < () )
for (int b = 0; b < 100; b++) {
String s = sc.nextLine();
// stop command
while (sc.hasNextLine()) { // better than the for loop
String line = sc.nextLine();
String results[] = s.split(" : "); // parse strings in between
// the
for (String temp : results) {
hometeam = results[0];
awayteam = results[1];
homescore = results[2];
awayscore = results[3];
}
// convert 'score' strings to int value.
result0 = Integer.valueOf(results[2]);
result1 = Integer.valueOf(results[3]);
matches [b] = hometeam.tostring() + " : " + awayteam.tostring() + homescore.tostring() + " : " + awayscore.tostring();
if ("stop".equals(line)) {
System.out.println(Arrays.toString(matches));
return; // exit
}
Here is a simple loop to grab all data from user until "stop" is entered and display the output of the input
Scanner sc = new Scanner(System.in);
ArrayList<String[]> stats = new ArrayList<>(); //initialize a container to hold all the stats
System.out.println("please enter match results:");
while(sc.hasNextLine())
{
String input = sc.nextLine();
String[] results = input.split(" : ");
if(results.length == 4)
{
stats.add(results);
}
else if(input.equals("stop"))
break;
else
System.out.println("Error reading input");
}//end of while
for(int i = 0; i < stats.size(); i++)
{
try{
System.out.println(stats.get(i)[0] + " vs " + stats.get(i)[1] + " : " +
Integer.valueOf(stats.get(i)[2]) + " - " + Integer.valueOf(stats.get(i)[3]));
}catch (Exception e) {
//do nothing with any invalid input
}
}
Output
please enter match results:
r : b : 5 : 4
r : c : 7 : 10
j : g : 3 : 9
stop
r vs b : 5 - 4
r vs c : 7 - 10
j vs g : 3 - 9
I am doing this Java assignment for class, and for some reason this method keeps saying the symbol can not be found. The block of code below is what gave me the error. Not entirely sure as to why because I followed the book verbatim and there was no mention of it compiling with an error (usually there is an indication to look for that)
I added the rest of the assignment to the post. I wasnt sure if it was relative or not because I was getting the error before I wrote the second half of this that is being posted now. I'm not sure if the error has to do with calling the methods before the method is actually defined, but i tried switching the order and it did not make a difference when I compiled it.
import java.nio.file.*;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
import static java.nio.file.StandardOpenOption.*;
import java.util.Scanner;
import java.text.*;
public class CreateFilesBasedOnState
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
Path inStateFile = Paths.get("InStateCusts.txt");
Path outOfStateFile = Paths.get("OutofStateCusts.txt");
final String ID_FORMAT = "000";
final String NAME_FORMAT = " ";
final int NAME_LENGTH = NAME_FORMAT.length();
final String HOME_STATE = "WI";
final String BALANCE_FORMAT = "0000.00";
String delimiter = ",";
String s = ID_FORMAT + delimiter + NAME_FORMAT + delimiter
+ HOME_STATE + delimiter + BALANCE_FORMAT
+ System.getProperty("line.seperator");
final int RECSIZE = s.length();
FileChannel fcIn = null;
FileChannel fcOut = null;
String idString;
int id;
String name;
String state;
double balance;
final String QUIT = "999";
createEmptyFile(inStateFile, s);
createEmptyFile(outOfStateFile, s);
try
{
fcIn = (FileChannel) Files.newByteChannel(inStateFile,
CREATE,
WRITE);
fcOut = (FileChannel) Files.newByteChannel(outOfStateFile,
CREATE,
WRITE);
System.out.print("Enter customer account number >> ");
idString = input.nextLine();
while (!(idString.equals(QUIT)))
{
id = Integer.parseInt(idString);
System.out.print("Enter name for customer >> ");
name = input.nextLine();
StringBuilder sb = new StringBuilder(name);
name = sb.toString();
System.out.print("Enter state >> ");
state = input.nextLine();
System.out.print("Enter balance >> ");
balance = input.nextDouble();
input.nextLine();
DecimalFormat df = new DecimalFormat(BALANCE_FORMAT);
s = idString + delimiter + name + delimiter + state
+ delimiter + df.format(balance)
+ System.getProperty("line.separator");
byte[] data = s.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(data);
if (state.equals(HOME_STATE))
{
fcIn.position(id * RECSIZE);
fcIn.write(buffer);
}
else
{
fcOut.position(id * RECSIZE);
fcOut.write(buffer);
}
System.out.print( "Ener next cusomter account number or "
+ QUIT + " to quit >> ");
idString = input.nextLine();
}
fcIn.close();
fcOut.close();
}
catch (Exception e)
{
System.out.println("Error message: " + e);
}
}
public static void createEmtpyFile(Path file, String s)
{
final int NUMRECS = 1000;
try
{
OutputStream outputStr
= new BufferedOutputStream(Files.newOutputStream(file
, CREATE));
BufferedWriter writer
= new BufferedWriter(new OutputStreamWriter(outputStr));
for (int count = 0; count < NUMRECS; ++count) {
writer.write(s, 0, s.length());
}
writer.close();
}
catch (Exception e)
{
System.out.println("Error message: " + e);
}
}
}
What I want to do is make it so that when the program runs it will run the ordinary way but if the user selects that they want the display to be in html then it will run what the ordinary program would do but rather than display it in the console it will write what was going to appear in the console into a html file that the user specifies. Is this possible? I have code to accept the user input and have them specify what format they want it in as well as open the browser but I'm not sure if this could work. The code I have already is below:
import java.awt.Desktop;
import java.io.*;
import java.util.*;
public class reader {
static int validresults = 0;
static int invalidresults = 0;
// Used to count the number of invalid and valid matches
public static boolean verifyFormat(String[] words) {
boolean valid = true;
if (words.length != 4) {
valid = false;
} else if (words[0].isEmpty() || words[0].matches("\\s+")) {
valid = false;
} else if ( words[1].isEmpty() || words[1].matches("\\s+")) {
valid = false;
}
return valid && isInteger(words[2]) && isInteger(words[3]);}
// Checks to see that the number of items in the file are equal to the four needed and the last 2 are integers
// Also checks to make sure that there are no results that are just whitespace
public static boolean isInteger(String input) {
try {
Integer.parseInt(input);
return true;
}
catch (Exception e) {
return false;
}
}
// Checks to make sure that the data is an integer
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
while (true) { // Runs until it is specified to break
Scanner scanner = new Scanner(System.in);
System.out.println("Enter filename");
String UserFile = sc.nextLine();
File file = new File(UserFile);
if (!file.exists()) {
continue;
}
if (UserFile != null && !UserFile.isEmpty()){
System.out.println("Do you want to generate plain (T)ext or (H)TML");
String input = scanner.nextLine();
if (input.equalsIgnoreCase("H")) {
Desktop.getDesktop().browse(file.toURI());
} else if (input.equalsIgnoreCase("T")) {
processFile(UserFile);
} else {
System.out.println("Do you want to generate plain (T)ext or (H)TML");
}
}
}
}
// Checks how the user wants the file to be displayed
private static void processFile(String UserFile) throws FileNotFoundException {
String hteam;
String ateam;
int hscore;
int ascore;
int totgoals = 0;
Scanner s = new Scanner(new BufferedReader(
new FileReader(UserFile))).useDelimiter("\\s*:\\s*|\\s*\\n\\s*");
while (s.hasNext()) {
String line = s.nextLine();
String[] words = line.split("\\s*:\\s*");
// Splits the file at colons
if(verifyFormat(words)) {
hteam = words[0]; // read the home team
ateam = words[1]; // read the away team
hscore = Integer.parseInt(words[2]); //read the home team score
totgoals = totgoals + hscore;
ascore = Integer.parseInt(words[3]); //read the away team score
totgoals = totgoals + ascore;
validresults = validresults + 1;
System.out.println(hteam + " " + "[" + hscore + "]" + " " + "|" + " " + ateam + " " + "[" + ascore + "]");
// Output the data from the file in the format requested
}
else{
invalidresults = invalidresults + 1;
}
}
System.out.println("Total number of goals scored was " + totgoals);
// Displays the total number of goals
System.out.println("Valid number of games is " + validresults);
System.out.println("Invalid number of games is " + invalidresults);
System.out.println("EOF");
}
}
//This is where we'll write the HTML to if the user's chooses so
private static final String OUTPUT_FILENAME = "output.html";
public static void main(String[] args) throws IOException
{
final Scanner scanner = new Scanner(System.in);
final String content = "Foobar";
final boolean toHtml;
String input;
//Get the user's input
do
{
System.out.print("Do you want messages "
+ "written to (P)lain text, or (H)TML? ");
input = scanner.nextLine();
} while (!(input.equalsIgnoreCase("p")
|| input.equalsIgnoreCase("h")));
toHtml = input.equalsIgnoreCase("h");
if (toHtml)
{
//Redirect the standard output stream to the HTML file
final FileOutputStream fileOut //False indicates we're not appending
= new FileOutputStream(OUTPUT_FILENAME, false);
final PrintStream outStream = new PrintStream(fileOut);
System.setOut(outStream);
}
System.out.println(toHtml
? String.format("<p>%s</p>", content) //Write HTML to file
: content); //We're not writing to an HTML file: plain text
}
I need help with sort the inputfile/highscore i've tried Holder-comparator, Collections.Sort and im now trying to make it an array list so the highscore is sorted by time i have tried but failed, I am really stuck have been stuck for days. Anny sugestions would be lovely
import java.io.*;
import java.util.*;
public class game {
private static void start() throws IOException {
int number = (int) (Math.random() * 1001);
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(System.in));
Scanner input = new Scanner(System.in);
String scorefile = "p-lista_java";
int försök = 0;
int gissning = 0;
String namn;
String line = null;
String y;
String n;
String val ;
String quit = "quit";
String Gissning;
System.out.println("Hello and welcome to this guessing game" +
"\nStart guessing it's a number between 1 and 1000: ");
long startTime = System.currentTimeMillis();
while (true || (!( input.next().equals(quit)))){
System.out.print("\nEnter your guess: ");
gissning = input.nextInt();
försök++;
if (gissning == number ){
long endTime = System.currentTimeMillis();
long gameTime = endTime - startTime;
System.out.println("Yes, the number is " + number +
"\nYou got it after " + försök + " guesses " + " times in " + (int)(gameTime/1000) + " seconds.");
System.out.print("Please enter your name: ");
namn = reader.readLine();
try {
BufferedWriter outfile
= new BufferedWriter(new FileWriter(scorefile, true));
outfile.write(namn + " " + försök +"\t" + (int)(gameTime/1000) + "\n");
outfile.close();
} catch (IOException exception) {
}
break;
}
if( gissning < 1 || gissning > 1000 ){
System.out.println("Stupid guess! I wont count that..." );
--försök;
}
else if (gissning > number){
System.out.println(" Your guess is too high");
}
else
System.out.println("Your guess is too low");
}
try {
BufferedReader infile
= new BufferedReader(new FileReader(scorefile));
while ((line = infile.readLine()) != null) {
System.out.println(line);
}
infile.close();
} catch (IOException exception) {
}
System.out.println("Do you want to continue (Y/N)?");
val=reader.readLine();
if ((val.equals("y"))||(val.equals("Y"))){
game.start();
}
else
System.out.print("Thanks for playing");
System.exit(0);
}
public static void main (String[] args) throws IOException {
game.start();
}
}
There are many ways to achieve this. Probably the simplest one is to sort the scores before printing them to the screen. First, put the score lines in a list.
BufferedReader infile = new BufferedReader(new FileReader(scorefile));
List<String> scores = new ArrayList<String>();
while ((line = infile.readLine()) != null) {
scores.add(line);
}
infile.close();
Now you can sort the list. You can use the sort method of the Collections class, but you will have to use a custom Comparator for this. Since your highscores are formatted like <name>\t<steps>\t<time> you can split the lines at whitespaces, parse the third element as a number and compare those numbers.
Collections.sort(scores, new Comparator<String>() {
public int compare(String s1, String s2) {
int t1 = Integer.parseInt(s1.split("\\s")[2]); // time in s1
int t2 = Integer.parseInt(s2.split("\\s")[2]); // time in s2
return t1 - t2; // neg. if t1 < t2
}
});
This will sort the list of scores in-place, so now all that's left to do is to actually print the scores:
System.out.println("Name Steps Time");
for (String s : scores) {
String[] ps = s.split("\\s");
System.out.println(String.format("%-10s %5s %5s", ps[0], ps[1], ps[2]));
}