I am working on a small project that takes user input (match results) on one line, splits the input and outputs the same data in a different format. I am struggling to find a way to output the data in a specific format. As well as total games played, I want my program to produce a chart like output in the format
home_name [home_score] | away_name [away_score]
This is the code I have at the minute which allows users to input results line after line in the following format
home_name : away_name : home_score : away_score
until they enter stop, which breaks the loop (and hopefully soon outputs the data).
import java.util.*;
public class results {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int totalGames = 0;
String input = null;
System.out.println("Please enter results in the following format"
+ " home_name : away_name : home_score : away_score"
+ ", or enter stop to quit");
while (null != (input = scan.nextLine())){
if ("stop".equals(input)){
break;
}
String results[] = input.split(" : ");
for (int x = 0; x < results.length; x++) {
}
totalGames++;
}
System.out.println("Total games played is " + totalGames);
}
}
You can see here.
You can format your text as you wish.
The general syntax is
%[arg_index$][flags][width][.precision]conversion char Argument
numbering starts with 1 (not 0). So to print the first argument, you
should use 1$ (if you are using explicit ordering).
You can use regEx to parse the line:
(\w)\s(\w)\s|\s(\w)\s(\w)
Base on Java code from (from http://tutorials.jenkov.com/java-regex/matcher.html)
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatcherFindStartEndExample{
public static void main(String[] args){
String text = "Belenenses 6 | Benfica 0";
String patternString = "(\\w+)\\s(\\w+)\\s\\|\\s(\\w+)\\s(\\w+)";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);
while (matcher.find()){
System.out.println("found: " + matcher.group(1));
System.out.println("found: " + matcher.group(2));
System.out.println("found: " + matcher.group(3));
System.out.println("found: " + matcher.group(4));
}
}}
Use this code instead of your
String results[] = input.split(" : ");
for (int x = 0; x < results.length; x++) {
}
You should do things in two times :
1) retrieving information entered by the user and storing it in instances of a custom class : PlayerResult.
2) performing the output according to the expected format. You should also compute the max size of each column before creating the graphical table.
Otherwise you could have a ugly rendering.
First step :
List<PlayerResult> playerResults = new ArrayList<PlayerResult>();
...
String[4] results = input.split(" : ");
playerResults.add(new PlayerResult(results[0],results[1],results[2],results[3])
Second step :
// compute length of column
int[] lengthByColumn = computeLengthByColumn(results);
int lengthHomeColumn = lengthByColumn[0];
int lengthAwayColumn = lengthByColumn[1];
// render header
System.out.print(adjustLength("home_name [home_score]", lengthHomeColumn));
System.out.println(adjustLength("away_name [away_score]", lengthAwayColumn));
// render data
for (PlayerResult playerResult : playerResults){
System.out.print(adjustLength(playerResult.getHomeName() + "[" + playerResult.getHomeName() + "]", lengthHomeColumn));
System.out.println(adjustLength(playerResult.getAwayName() + "[" + playerResult.getAwayScore() + "]", lengthAwayColumn));
}
You can keep the games statistics by adding results array values to the finalResults ArrayList. And then outputting its results as stop input is entered.
For counting the total results per team HashMap<String, Integer> is the best choice.
Here is the complete code with comments to make it clear:
import java.util.*;
// following the naming conventions class name must start with a capital letter
public class Results {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int totalGames = 0;
String input;
System.out.println("Please enter results in the following format: \n"
+ "'HOME_NAME : AWAY_NAME : HOME_SCORE : AWAY_SCORE' \n"
+ "or enter 'stop' to quit");
// HashMap to keep team name as a key and its total score as value
Map<String, Integer> scoreMap = new HashMap<>();
// ArrayList for storing game history
List<String> finalResults = new ArrayList<>();
// don't compare null to value. Read more http://stackoverflow.com/questions/6883646/obj-null-vs-null-obj
while ((input = scan.nextLine()) != null) {
if (input.equalsIgnoreCase("stop")) { // 'Stop', 'STOP' and 'stop' are all OK
scan.close(); // close Scanner object
break;
}
String[] results = input.split(" : ");
// add result as String.format. Read more https://examples.javacodegeeks.com/core-java/lang/string/java-string-format-example/
finalResults.add(String.format("%s [%s] | %s [%s]", results[0], results[2], results[1], results[3]));
// check if the map already contains the team
// results[0] and results[1] are team names, results[2] and results[3] are their scores
for (int i = 0; i < 2; i++) {
// here is used the Ternary operator. Read more http://alvinalexander.com/java/edu/pj/pj010018
scoreMap.put(results[i], !scoreMap.containsKey(results[i]) ?
Integer.valueOf(results[i + 2]) :
Integer.valueOf(scoreMap.get(results[i]) + Integer.valueOf(results[i + 2])));
}
totalGames++; // increment totalGames
}
System.out.printf("%nTotal games played: %d.%n", totalGames); // output the total played games
// output the games statistics from ArrayList finalResults
for (String finalResult : finalResults) {
System.out.println(finalResult);
}
// output the score table from HashMap scoreMap
System.out.println("\nScore table:");
for (Map.Entry<String, Integer> score : scoreMap.entrySet()) {
System.out.println(score.getKey() + " : " + score.getValue());
}
}
}
Now testing with input:
team1 : team2 : 1 : 0
team3 : team1 : 3 : 2
team3 : team2 : 2 : 2
sToP
The output is:
Total games played: 3.
team1 [1] | team2 [0]
team3 [3] | team1 [2]
team3 [2] | team2 [2]
Score table:
team3 : 5
team1 : 3
team2 : 2
Related
I'm writing a simple vowel-counter and was wondering if there's a cleaner alternative (possibly a loop?) to replace all of the else if's when comparing s to the various vowels.
I can't think of a simple way to do this effectively as the number of each vowel must be shown individually. It would be very simple if it was just a total vowel count.
I'm quite new to Java so I don't know what can be used to clean this up. If this is the best option, then I am contempt -- but I love cleaning up code where it can be!
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int A = 0, E = 0, I = 0, O = 0, U = 0;
System.out.print("Type a single word > ");
String word = input.next();
for (int i = 0; i < word.length(); i++) {
String s = word.substring(i, i + 1);
if (s.equalsIgnoreCase("A")) { A++; }
else if (s.equalsIgnoreCase("E")) { E++; }
else if (s.equalsIgnoreCase("I")) { I++; }
else if (s.equalsIgnoreCase("O")) { O++; }
else if (s.equalsIgnoreCase("U")) { U++; }
}
int total = A + E + I + O + U;
System.out.println("\n'" + word + "' has...\n" + A + " A's\n" + E + " E's\n" + I + " I's\n" + O + " O's\n" + U + " U's\nTotal vowels: " + total + "\n");
input.close();
}
}
Input:
Coding
Output:
'Coding' has...
0 A's
0 E's
1 I's
1 O's
0 U's
Total vowels: 2
Here is a less repetitive way to code it, using an int array for the counts, and a string holding the sequence of vowels.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Type a single word > ");
String word = input.next();
String vowels = "AEIOU";
int[] counts = new int[vowels.length()];
int total = 0;
for (int i = 0; i < word.length(); i++) {
int index = vowels.indexOf(Character.toUpperCase(word.charAt(i)));
if (index >= 0) {
++counts[index];
++total;
}
}
System.out.printf("%n'%s' has...%n", word);
for (int i = 0; i < counts.length; ++i) {
System.out.printf("%s %s's%n", counts[i], vowels.charAt(i));
}
System.out.printf("Total vowels: %s%n", total);
}
}
Output:
Type a single word > Coding
'Coding' has...
0 A's
0 E's
1 I's
1 O's
0 U's
Total vowels: 2
You could avoid a lot of repetition by using a Map that associates vowels (keys) to their frequencies within the word passed at runtime (values).
It is worth noting that a LinkedHashMap is used in the below example as to preserve the insertion order of keys for printing at the end of the program - as would not be the case with a HashMap.
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Define Map to map vowels to frequencies
Map<Character, Integer> vowels = new LinkedHashMap<Character, Integer>();
vowels.put('A', 0);
vowels.put('E', 0);
vowels.put('I', 0);
vowels.put('O', 0);
vowels.put('U', 0);
// Get input from user
System.out.print("Type a single word > ");
String word = input.next();
// Iterate across word
for (int i = 0; i < word.length(); i++) {
String c = word.substring(i, i+1); // Get current char
for (Character key : vowels.keySet()) { // Iterate across vowels
if (c.equalsIgnoreCase(key.toString())) {
vowels.put(key, vowels.get(key)+1); // Increment vowel frequency if matched
break; // Break inner loop and move to next char in word
}
}
// Sum total
int total = 0;
for (Character key : vowels.keySet()) {
total += vowels.get(key);
}
// Print results to console
System.out.println("\'" + word + "\'" + " has...");
for (Character key : vowels.keySet()) {
System.out.println(vowels.get(key) + " " + key + "\'s");
}
System.out.println("Total vowels: " + total);
input.close();
}
}
}
My program takes user input to create a sport score table.
Its validation function prints "Invalid input" when the array "words" contains less than 4 elements
for (int i = 0; i < counter; i++) { // A loop to control the Array
String[] words = football_list[i].split(":"); // Splits the input into 4 strings
if (words.length != 4) { // If the length of the array elements does not equal 4 then print error message
System.out.println("Input was not valid");
When I enter an incorrect input FIRST, it then makes the rest of the following scores to be deemed equally incorrect even when they are correct - here is an example of what that looks like on the text console.
Home team : Away team : Home score : Away score
Leeds : Liverpool : 2 :
Home team : Away team : Home score : Away score
Leeds : Liverpool : 2 : 1
Home team : Away team : Home score : Away score
Leeds : Liverpool : 2 : 1
Home team : Away team : Home score : Away score
Leeds : Liverpool : 2 : 1
Home team : Away team : Home score : Away score
quit
Input was not valid
Input was not valid
Input was not valid
Input was not valid
Totals
------------------------- Total games played: 0*
END--
This is where I think the problem is:
for (int i = 0; i < counter; i++) {
String[] words = football_list[i].split(":"); 4 strings
if (words.length != 4) {
System.out.println("Input was not valid");
counter--;
i--;
} else {
System.out.println(words[0].trim() + " [" + words[2].trim() + "]" + " | " + words[1].trim() + " [" + words[3].trim() + "]"); // Formats and prints the output
System.out.println(" ");
System.out.println(" ");
System.out.println(" ");
System.out.println(" Totals ");
System.out.println("-------------------------");
System.out.println("Total games played: " + counter);
}
}
Don't decrement i inside the loop.
Because you decrement i and counter if input is invalid. And after that increase i in for-statement. In this case you are reading invalid row again and again while counter > i
To make things more readable and less error prone, you could simply use the length of your array to control your loop ending, and increment counter (starting at 0) only when the input is valid :
int counter = 0;
for (int i = 0; i < football_list.length; i++) { // A loop to control the Array
String[] words = football_list[i].split(":"); // Splits the input into 4 strings
if (words.length != 4) { // If the length of the array elements does not equal 4 then print error message
System.out.println("Input was not valid");
} else {
counter++;
System.out.println(words[0].trim() + " [" + words[2].trim() + "]" + " | " + words[1].trim() + " ["
+ words[3].trim() + "]"); // Formats and prints the output
}
}
I am getting this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at JavaProject.main(JavaProject.java:70)
Here is the code:
try
{
PrintWriter writer = new PrintWriter("Gamer Report Data.txt");
writer.println("Player: " + gamerName);
writer.println();
writer.println("-------------------------------");
String[] report = gamerReport.split(gamerReport, ':');
writer.println("Game:" + ", score=" + report[1] + ", minutes played=" + report[2] + report[3]);
writer.close();
} catch (IOException e)
{
System.err.println("File does not exist!");
}
I believed it to be something related to my for loop, but I have had no luck changing it around.
import java.util.Scanner;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.io.PrintWriter;
public class JavaProject {
private static char[] input;
#SuppressWarnings("null")
public static void main(String[] args) {
for (int b = 1; b < 100; b++) {
// this is making the code loop 100 times
int hrs, mins;
int[] gameCount;
int[] minutesPlayed = new int[100];
String gamerName, gamerReport;
// Main data storage arrays
String[] gameNames = new String[100];
int[] highScores = new int[100];
Scanner Scan = new Scanner(System.in);
// formatting for output and input
System.out.println("////// Game Score Report Generator \\\\\\\\\\\\");
System.out.println(" ");
// user enters name and then moves to next line
System.out.println("Enter Your Name");
gamerName = Scan.nextLine();
// user is given an example of input format
System.out.println("Input Gamer Information " + "Using Format --> Game : Achievement Score : Minutes Played");
System.out.println(" ");
System.out.println("Game : Achievement Score : Minutes Played");
gamerReport = Scan.nextLine();
String[] splitUpReport; // an array of string
splitUpReport = gamerReport.split(":"); // split the text up on the colon
int i = 0;
// copy data from split text into main data storage arrays
gameNames[i] = splitUpReport[0];
highScores[i] = Integer.parseInt(splitUpReport[1].trim());
minutesPlayed[i] = Integer.parseInt(splitUpReport[2].trim());
// output to file
try
{
PrintWriter writer = new PrintWriter("Gamer Report Data.txt");
writer.println("Player: " + gamerName);
writer.println();
writer.println("-------------------------------");
String[] report = gamerReport.split(gamerReport, ':');
writer.println("Game:" + ", score=" + report[1] + ", minutes played=" + report[2] + report[3]);
writer.close();
} catch (IOException e)
{
System.err.println("File does not exist!");
}
}
}
public static char[] getInput() {
return input;
}
public static void setInput(char[] input) {
JavaProject.input = input;
}
}
There are two problems with your code:
1)
String[] report = gamerReport.split(gamerReport, ':');
should be
String[] report = gamerReport.split(":");
as you did with splitUpReport (not sure why you're splitting again actually).
2) Arrays are zero-indexed, so the print statement should look like this:
writer.println("Game:" + ", score=" +report[0] +", minutes played="+ report[1] + report[2]);
The error in your code is being caused by this code in the try block:
String[] report = gamerReport.split(gamerReport, ':');
You are actually trying to split the gamerReport string using itself as a regex, with a limit of 58, which is the numerical value of the colon.
The result of this split is 2 empty String elements, which correspond to the match happening before and after the regex, which is the string itself.
The ArrayIndexOutOfBounds exception is happening when you try to access the third element from this array:
To fix your problem, just define the report array as follows:
String[] report = gamerReport.split(':');
As #shmosel pointed out, you might also want to change your array indices here as well:
writer.println("Game:" + ", score=" + report[0] +", minutes played="+ report[1] + report[2]);
this program attempts to scan a text file radio music log, and then match the songs to a directory of wav files. all files are named with the same convention: artist-title, ie: lukebryan-kickthedustup.wav. i swap the locations of the title and artist using the delimiter feature, which allows for easy comparison to the music log, which is already formatted the same way: title, artist.
now, lets say i'm searching the term "lovingyoueasyza", which is Loving You Easy by the Zac Brown Band... when it reaches the file in the directory with the assigned string "lovingyoueasyzacbrownband", it ignores it, even though it contains that string. you'll see i'm calling:
if(searchMe.contains(findMe))
yet it doesn't return a hit. it will return matches if the findMe string only contains the song title, but if any part of the artist title creeps into that string, it stops working. why!? for shorter titles its critical i be able to search for artist name as well, which is why i can't just search by song title.
i've tried using .trim() to no avail. here is some sample output of when a match is found:
searching term: "onehellofanamen"
comparing to: "onehellofanamendbrantleygilbert"
Match found!
value of findMe: onehellofanamen
value of searchMe: onehellofanamendbrantleygilbert
value of y: 49
value of x: 79
here is sample output of a failed attempt to match:
searching term: "lovingyoueasyza"
comparing to: "keepmeinminddzacbrownband"
searching term: "lovingyoueasyza"
comparing to: "lovingyoueasydzacbrownband"
searching term: "lovingyoueasyza"
comparing to: "nohurrydzacbrownband"
searching term: "lovingyoueasyza"
comparing to: "toesdzacbrownband"
searching term: "lovingyoueasyza"
this is what the findMe's go into the method as:
fileToProcess var is: C:\test\06012015.TXT
slot #0: topofhouridplac
slot #1: lovemelikeyoume
slot #2: wearetonightbil
slot #3: turnitoneliyoun
slot #4: lonelytonightbl
slot #5: stopset
slot #6: alrightdariusru
slot #7: lovingyoueasyza
slot #8: sundazefloridag
slot #9: stopset
the final output of matchesFound is like this:
Item Number: 0 ****TOP OF HOUR****
Item Number: 1 d:\tocn\kelseaballerini-lovemelikeyoumeanit.wav
Item Number: 2 null
Item Number: 3 null
Item Number: 4 null
Item Number: 5 ****STOP SET****
Item Number: 6 null
... through 82.
public static String[] regionMatches(String[] directoryArray,
String[] musicLogArray) throws InterruptedException {
String[] matchesFound = new String[musicLogArray.length];
String[] originalFileList = new String[directoryArray.length];
for (int y = 0; y < directoryArray.length; y++) {
originalFileList[y] = directoryArray[y];
System.out.println("o value: " + originalFileList[y]);
System.out.println("d value: " + directoryArray[y]);
}
for (int q = 0; q < originalFileList.length; q++) {
originalFileList[q] = originalFileList[q].replaceAll(".wav", "");
originalFileList[q] = originalFileList[q].replaceAll("\\\\", "");
originalFileList[q] = originalFileList[q].replaceAll("[+.^:,]", "");
originalFileList[q] = originalFileList[q].replaceAll("ctestmusic",
"");
originalFileList[q] = originalFileList[q].replaceAll("tocn", "");
originalFileList[q] = originalFileList[q].toLowerCase();
String[] parts = originalFileList[q].split("-");
originalFileList[q] = parts[1] + parts[0];
System.out.println(originalFileList[q]);
}
for (int x = 0; x < musicLogArray.length; x++) {
for (int y = 0; y < directoryArray.length; y++) {
//System.out.println("value of x: " + x);
//System.out.println("value of y: " + y);
String searchMe = originalFileList[y];
String findMe = musicLogArray[x];
int searchMeLength = searchMe.length();
int findMeLength = findMe.length();
boolean foundIt = false;
updateDisplay("searching term: " + "\"" + findMe+"\"");
updateDisplay("comparing to: " + "\"" + searchMe + "\"");
//for (int i = 0; i <= (searchMeLength - findMeLength); i++) {
if(searchMe.contains(findMe)){
updateDisplay("Match found!");
updateDisplay("value of findMe: " + findMe);
updateDisplay("value of searchMe: " + searchMe);
updateDisplay("value of y: " + y);
updateDisplay("value of x: " + x);
matchesFound[x] = directoryArray[y];
break;
// if (searchMe.regionMatches(i, findMe, 0, findMeLength)) {
// foundIt = true;
// updateDisplay("MATCH FOUND!: "
// + searchMe.substring(i, i + findMeLength));
//
// matchesFound[x] = directoryArray[y];
//
// break;
} else if (findMe.contains("stopset")){
matchesFound[x] = "****STOP SET****";
break;
} else if (findMe.contains("topofho")) {
matchesFound[x] = "****TOP OF HOUR****";
break;
}
}
//if (!foundIt) {
// updateDisplay("No match found.");
//}
}
//}
return matchesFound;
}
It seems to me that your music directory has a bunch of unwanted d's in the file where you put the pieces back together.
searching term: "lovingyoueasyza"
comparing to: "lovingyoueasydzacbrownband"
The comparing to string does not contain the search term because after "easy" there is a "d" which ruins the search which is why you are having errors including artist names.
Here:
searching term: "lovingyoueasyza"
comparing to: "lovingyoueasydzacbrownband"
In your second string, note that there is an extra d after easy.
So the second string does not contain the first string.
I think you are adding an extra 'd' when combining song name with the artist name.
The same thing is happening for all your other strings, e.g.
searching term: "onehellofanamen"
comparing to: "onehellofanamendbrantleygilbert"
which I suppose is one hell of an amen + the extra 'd' + brantley gilbert.
I need to display an output like this:
Enter an integer: 3
Number Squared Cubed
====== ======= =====
1 1 1
2 4 8
3 9 27
But instead, when I run the code, I get this output:
Number Squared Cubed
====== ======= =====
3 9 27
In other words, I need to display the powers of an integer,including the powers of the numbers less than or equal to the integer. The numbers of the lesser integers need to be listed but are not displayed along with the integer being entered. How do I fix the code to make sure it outputs all of the integers that are less than or equal to the integer being entered? There are no errors (i.e. red exclamation mark circles) but I need to figure out the proper calculation.
Here is the code:
====================
import java.util.Scanner;
public class Powers
{
public static void main(String[] args)
{
System.out.println("Welcome to the Squares and Cubes Table");
System.out.println();
Scanner sc = new Scanner(System.in);
String choice = "y";
while(choice.equalsIgnoreCase("y"))
{
// get the input from the user
System.out.println("Enter an Integer: ");
int integerNext = sc.nextInt();
System.out.println("Number" + " " + "Squared" + " " + "Cubed");
System.out.println("======" + " " + "======" + " " + "======");
for(int i = 1; i <= integerNext; i++)
{
i = integerNext;
int numberSquared = (int) Math.pow(i, 2);
int numberCubed = (int) Math.pow (i, 3);
String message = "\n" + i + " " + numberSquared + " " + numberCubed;
System.out.println(message);
System.out.println();
// see if the user wants to continue
System.out.print("Continue? (y/n): ");
choice = sc.next();
System.out.println();
}
}
}
}
Help is always appreciated. Thanks.
Firstly, as Nikhil said: "Remove the line i = integerNext; It is resetting the value of I and therefore only last row is printed".
Secondly, move the first closing curly brace to before getting user input - you want to run the loop, and only ask about continuing when that's finished, if I understand correctly.
Remove the line i = integerNext; It is resetting the value of I and therefore only last row is printed
Your are almost there. Since you are looping from 1 to integerNext (which is 3 in your text), the looping variable i will get the values [1,2,3] each iteration, so you don't have to set i manually. When you do:
i = integerNext;
you are setting i to 3, so the loop will finish when it reaches the loop condition.
You may also want to put the "Continue?" check outside the loop:
for (int i = 1; i <= integerNext; i++) {
int numberSquared = (int) Math.pow(i, 2);
int numberCubed = (int) Math.pow(i, 3);
String message = "\n" + i + " " + numberSquared + " " + numberCubed;
System.out.print(message);
}
// see if the user wants to continue
System.out.print("\nContinue? (y/n): ");
choice = sc.next();
System.out.println();
import java.util.Scanner;
public class SquaresAndCubes {
public static void main(String[] args)
{
// Welcome the user
System.out.println("Welcome to the Squares and Cubes table");
System.out.println();
Scanner sc = new Scanner(System.in);
String choice = "y";
do
{
// Get input from the user
System.out.print("Enter an integer: ");
int integer = sc.nextInt();
// Create a header
String header = "Number " + "Squared " + "Cubed " + "\n"
+ "====== " + "======= " + "===== ";
System.out.println(header);
int square = 0;
int cube = 0;
String row = "";
for (int i = 1; i <= integer; i++)
{
square = i * i;
cube = i * i * i;
row = i + " " + square + " " + cube;
System.out.println(row);
}
// See if the user wants to continue
System.out.print("Continue? (y/n): ");
choice = sc.next();
System.out.println();
}
while (!choice.equalsIgnoreCase("n"));
}
}
Basic way to do it with foor loop and some printlines
Scanner sc = new Scanner(System.in);
System.out.print("What number would you like to go up to? ");
int userInt = sc.nextInt();
System.out.println("");
System.out.println("Here is your table!");
System.out.println("");
System.out.println("number | squared | cubed");
System.out.println("------ | ------- | -----");
for (int i = 1; i <= userInt; i++){
System.out.println(i + " | " + (i * i) + " |" + " " +(i * i * i));
}