Yahoo Answers is shutting down on May 4th, 2021 (Eastern Time) and beginning April 20th, 2021 (Eastern Time) the Yahoo Answers website will be in read-only mode. There will be no changes to other Yahoo properties or services, or your Yahoo account. You can find more information about the Yahoo Answers shutdown and how to download your data on this help page.

java help?

Hi, I am working on a java program where a user enters some values. The format entered by the user is in the form of String + int + int + double. The problem is if the string is more than one word it doesn't work correctly. I'm using:

myScanner.next();

myScanner.nextInt();

myScanner.nextInt();

myScanner.nextDouble();

I think the whitespace is messing everything up. How would I go about taking the string as any number of words without messing up the next int?

Update:

Thanks for the help General Cucombre, but I actually figured out a way to do it with a while loop.

string = myScanner.next();

while(!myScanner.hasNextInt()){

string += " " + myScanner.next();

}

2 Answers

Relevance
  • BalRog
    Lv 5
    1 decade ago
    Favorite Answer

    I am as big a fan of regular expressions as the next guy, but in this case they are overkill. Or at least, a RE to parse the whole record is overkill.

    If the numbers are space delimited and you have reasonable confidence that a every line is going to end in two ints and a double, then you can just use the String.split() method and then parse the string from back to front as follows:

    ------------------

    String record = "John Paul Jones 25 7 88.0";

    String[] parts = record.split(" "); //split along spaces

    assert parts.length > 3; // ensures record has enough parts

    double d3 = parseDouble(parts[parts.length - 1];

    int i2 = parseInt(parts[parts.length - 2];

    int i1 = parseInt(parts[parts.length - 3];

    StringBuilder sb = new StringBuilder(parts[0]);

    for(int i = 1; i < parts.length - 3; i++) {

    sb.append(" ").append(parts[i]);

    }

    String s0 = sb.toString();

    ------------------

    The argument to the split method is actually a regular expression too, so if your delimiter is a bit sloppy you can just use the appropriate RE syntax:

    • multiple spaces between parts instead of just one space: record.split(" +")

    • multiple tabs OR spaces: record.split("[\t ]+")

    etc., etc.

    This gives some of the flexibility of REs without having to manage a huge RE that describes the whole record.

    -----------

    ASIDE to the General: With all due respect to your rank :-), if you can rely on the record ENDING with two ints and a double and if the split delimiter is properly defined, then the split-based parser I outlined above works just fine.

    For example, it correctly parses every one of your "split-breaking" records.

    Your record pattern RE is not that long or complicated to you (or me), but try writing its meaning out in plain English and you might see that it could be pretty daunting to a RE novice.

    Yes, as we have both pointed out, String.split() does also use regular expressions, but the regular expressions tend to be much simpler than those used by the Pattern class. Compare:

    • "^(.*)\\s+(\\d+)" + "\\s+(\\d+)" + "\\s+([\\d\\.]+)$"

    ..... (Pattern and Matcher).

    • " +"

    ..... (String.split() equivalent with the parsing I showed)

    Now, one advantage to using Pattern and Matcher classes is that they COULD be used to pre-validate the whole record. However:

    A) You are not using them that way

    B) Your "double" RE, "\\s+([\\d\\.]+)$", does not suffice to validate a double. For example " ......." or " 1.2.3.4.5" would match the pattern you are using. "\\s+(\\d+(\\.\\d+)?)$" would be better but still not complete. I think that this would do the job:

    "\\s+(" + "(\\d+(\\.\\d*)?)|(\\.\\d+)" + ")$"

    -----------

    ASIDE to rettix: The General's second sample record in his "added" section will break record parsing using your "hasNextInt"-based while loop.

  • 1 decade ago

    Regular expressions are more elegant and reliable way to achieve the result you're seeking:

    import java.util.regex.*;

    public class test15 {

    public static void main(String[] args) {

    String input = "Aloyisius Julius Markus 5 5 2.5";

    Pattern pattern = Pattern.compile(

    "^(.*)\\s+(\\d+)" + "\\s+(\\d+)" + "\\s+([\\d\\.]+)$"

    );

    Matcher matcher = pattern.matcher(input);

    if (matcher.matches()) {

    System.out.println("Field 1: "+matcher.group(1));

    System.out.println("Field 2: "+matcher.group(2));

    System.out.println("Field 3: "+matcher.group(3));

    System.out.println("Field 4: "+matcher.group(4));

    }

    }

    }

    ---- added ----

    I can see a point in RE being overkill, but employing them in this case will still pay off - the actual RE is not that huge or complicated. Also, just to make it clear - split() utilizes regular expressions as well.

    I don't know about subject area, but consider this input (let's say those are artist names or book names):

    50 Cent 400 800 18.95

    Catch 22 500 1000 29.99

    Conan O'Brien 800 500 49.99

    nextInt() or split()-type parser will choke on those, while regex will take them without problems.

Still have questions? Get your answers by asking now.