1

How do I split a line of user input into separate strings and store, for example, if the input format was as follows (for a results chart)..

home_name : away_name : home_score : away_score

How would I go about splitting the input into 4 different parts and storing separately? (User will be prompted to input in the above format only, and I'm using a while loop to continue to ask for line results until user enters stop).

gv555
  • 19
  • 6
  • 4
    tokenizer or .split function – Luminous_Dev Jan 04 '17 at 21:54
  • 2
    Like [this](http://stackoverflow.com/questions/3481828/how-to-split-a-string-in-java). But do you have control over the input process? That long string seems difficult/error prone. – Andrew S Jan 04 '17 at 21:56
  • No, it's a question i'm trying to get my head around, the input has to be in one line and in that specified format, for example a typical input will look like manchester united : chelsea : 3 : 2 – gv555 Jan 04 '17 at 22:01
  • Once I have figured out how to store the input data for later referral I will work on validation – gv555 Jan 05 '17 at 12:25

3 Answers3

4

If the format of your input data is consistent then you can simply use a pattern like : and do the following:

public static void main(String[] args) {
    /* Scan Inputs */
    Scanner in = new Scanner(System.in);

    /* Input String */
    String input = null;

    /* Create StringBuilder Object */
    StringBuilder builder = new StringBuilder();

    String[] headers = { "home_name: ", "away_name: ", "home_score: ",
            "away_score: " };
    while (null != (input = in.nextLine())) {
        /* Break if user enters stop */
        if ("stop".equalsIgnoreCase(input)) {
            break;
        }

        /* Trim the first and the last character from input string */
        input = input.substring(1, input.length() - 1);

        /* Split the input string using the required pattern */
        String tokens[] = input.split(" : ");

        /* Print the tokens array consisting the result */
        for (int x = 0; x < tokens.length; x++) {
            builder.append(headers[x]).append(tokens[x]).append(" | ");
        }
        builder.append("\n");
    }

    /* Print Results & Close Scanner */
    System.out.println(builder.toString());
    in.close();
}

Note that here I have used substring() function to get rid of < and > in the starting and ending of the input string before splitting it using the given pattern.

Input:

<manchester united : chelsea : 3 : 2>
<foobar : foo : 5 : 3>
stop

Output:

home_name: manchester united | away_name: chelsea | home_score: 3 | away_score: 2 | 
home_name: foobar | away_name: foo | home_score: 5 | away_score: 3 | 
user2004685
  • 9,548
  • 5
  • 37
  • 54
  • 1
    Brilliant, and I can somehow worm this into a while loop to keep prompting user for another line until user enters stop? – gv555 Jan 04 '17 at 22:52
  • @gv555 Yes, you can do it easily by using a `Scanner` to capture the user inputs using the console or maybe a file. Please refer to the updated code. – user2004685 Jan 04 '17 at 23:00
  • 1
    Thank you so much! Last question, how can I modify the output? I'd like it on one line and is it possible to make the output grow as the user enters more results, for example a typical output could look like home_name [home_score] | away_name [away_score] and it will grow a line at a time as the results are entered? – gv555 Jan 05 '17 at 11:53
  • @gv555 You can do it using the `StringBuilder`. Please see the updated answer. Also, if you think this helped you solve the problem then please accept the answer by clicking on the greyed out tick mark just below the voting counter of this answer. – user2004685 Jan 05 '17 at 17:46
1

In some cases, the input could be a little 'inconsistent': blanks not provided or changes produced by new versions. If is the case, it is possible apply some protection with regular expressions.

public static void main(String[] args) {

    boolean validInput = false; 

    String input = "<home_name : away_name : home_score : away_score>";

    String pattern = "<.*:.*:.*:.*>";
    Pattern r = Pattern.compile(pattern);
    Matcher m = r.matcher(input);
    validInput = m.matches();

    if(validInput) {
        input = input.substring(1, input.length() - 1);
        String tokens[] = input.split("\\s*:\\s*");

        for (int x = 0; x < tokens.length; x++) {
            System.out.println(tokens[x]);
        }

    } else {
        System.out.println("Input is invalid");
    }
}
Alex Javarotti
  • 106
  • 1
  • 6
  • Any other tips on validation? I'd like to know how to check if say one of the team names is missing or if one of the scores isn't a valid integer number? – gv555 Jan 05 '17 at 15:40
  • @gv555 We could change the regular expressions in order to avoid the missing of values and identify data type inconsistency. The pattern can be change to this one: `String pattern = <\\s*\\S+\\s*:\\s*\\S+\\s*:\\s*\\d+\\s*:\\s*\\d+\\s*>";` _The new pattern requires at least one non-white-space character (\S) in the first and second fields and at least one decimal digit (\d) in the third and forth fields. The extra white-space characters are allowed._ – Alex Javarotti Jan 05 '17 at 23:43
0

If the format is exactly as you've described, a fairly efficient way to parse it is this:

public static void main(String[] args) {
    String line = "<Raptors : T-Rexes : 5 : 10>";

    final int colonPosition1 = line.indexOf(':');
    final int colonPosition2 = line.indexOf(':', colonPosition1 + 1);
    final int colonPosition3 = line.indexOf(':', colonPosition2 + 1);

    final String homeName = line.substring(1, colonPosition1 - 1);
    final String awayName = line.substring(colonPosition1 + 2, colonPosition2 - 1);
    final int homeScore = Integer.parseInt(line.substring(colonPosition2 + 2, colonPosition3 - 1));
    final int awayScore = Integer.parseInt(line.substring(colonPosition3 + 2, line.length() - 1));

    System.out.printf("%s: %d vs %s: %d\n", homeName, homeScore, awayName, awayScore);
}
Chai T. Rex
  • 2,972
  • 1
  • 15
  • 33