0

I hope there is at least one nice person who would like to help me - this topic is going to frustrate me a lot.

I have an issue to read data from console in specific composition, which means: in first row I have three signs separeted by space - 2 digits and 1 character. In second row there is line of String. Example:

1 2 E

WHUNDDLOOD

5 7 S

LRRMSDDD

I need to have them as type of byte (first two digits), character (last sign in first row) and a string (whole second line).

I tried to use Scanner, but it's not possible to read char from it. However I tried to use "charAt()" but... probably I'm tired about it.

Excerpt of my code:

while (stdin.hasNextLine()) {
    Scanner stdin = new Scanner(System.in);
    byte x = stdin.nextByte();
    byte y = stdin.nextByte();
    char h = stdin.next().charAt(0);
    String str = stdin.nextLine();
}

I got the InputMismatchException and last string is not even read. Can you help me?

Rafal Iwaniak
  • 151
  • 1
  • 11
  • you can simply read it as string and then go ahead from there. Java provides converting string to char Array char[] charArray = str.toCharArray(); – Acewin Feb 11 '16 at 21:05
  • Thanks Acewin for your response. But if I read first line as a string, i.e. String str = stdin.nextLine(); Then how can I get two byte value and char? – Rafal Iwaniak Feb 11 '16 at 21:12
  • BTW I executed your code and it seems the culprit is statement byte x = stdin.nextByte(); – Acewin Feb 11 '16 at 21:14

2 Answers2

2

Close, but you needed to clear the line after .next(). Without doing that, your loop read until the end of the line, then went back to the top of the loop where it expected a byte. You gave it a String, therefore throwing a InputMismatchException.

Scanner stdin = new Scanner(System.in);

do {
    byte x = stdin.nextByte();
    byte y = stdin.nextByte();
    char h = stdin.next().charAt(0);
    stdin.nextLine(); // read EOL
    String str = stdin.nextLine();

    System.out.printf("Output: [%s, %s, %s], %s\n", x, y, h, str);
} while (stdin.hasNextLine());

Run

1 2 E
WHUNDDLOOD
Output: [1, 2, E], WHUNDDLOOD
5 7 S
LRRMSDDD
Output: [5, 7, S], LRRMSDDD
OneCricketeer
  • 126,858
  • 14
  • 92
  • 185
  • Really? That sounds awesome :D Thanks! – Rafal Iwaniak Feb 11 '16 at 21:18
  • +1 for fixing the error in the question. Unfortunately, like most other code using `Scanner`, this will die a horrible death if input is not exactly to spec, because of lack of error handling. – Andreas Feb 11 '16 at 21:18
  • So what do you recommend to use here instead of Scanner? – Rafal Iwaniak Feb 11 '16 at 21:23
  • @cricket you should mention the reason why it had failed earlier for rafal. By using next____ methods he is setting expectation for the input to be of that specific type. If the expectation is not met it will give InputMisMatchException – Acewin Feb 11 '16 at 21:24
  • @rafal I will go with what Andreas suggested. parse your input yourself. Even though his answer seems to be complex you can quiet easily code differently based on his suggestion. But if you simply want to solve and remove the error cricket has already answered it for you. Thus both the answers are correct – Acewin Feb 11 '16 at 21:26
  • cricket did not understood your comment properly – Acewin Feb 11 '16 at 21:29
1

Best way to parse data like that, is to not really use the Scanner, but process the lines yourself. For that, regular expression will make it a lot easier.

Pattern row1pattern = Pattern.compile("([0-9])\\s+([0-9])\\s+([a-zA-Z])");
for (;;) {
    String line1 = (stdin.hasNextLine() ? stdin.nextLine() : "").trim();
    if (line1.isEmpty())
        break;
    String line2 = (stdin.hasNextLine() ? stdin.nextLine() : "").trim();
    Matcher m = row1pattern.matcher(line1);
    if (! m.matches() || line2.isEmpty()) {
        System.out.println("Bad input. Goodbye.");
        break;
    }
    byte digit1 = (byte)(m.group(1).charAt(0) - '0');
    byte digit2 = (byte)(m.group(2).charAt(0) - '0');
    char char1 = m.group(3).charAt(0);
    // now use digit1, digit2, char1, and line2, e.g.
    System.out.println(digit1 + ", " + digit2 + ", " + char1 + ", " + line2);
}

Output

1, 2, E, WHUNDDLOOD
5, 7, S, LRRMSDDD
Andreas
  • 138,167
  • 8
  • 112
  • 195