1

I want to create a method that iterates through any String (that is one word long) one character at a time and prints out every character on a new line using delimiters. To do this, I read all about regular expressions (this post helped me the most for learning them), and the Java documentation on how to compile a Pattern to use in a Scanner (here and here). After learning all of this, I created the following code:

    public static void stringPrinter(String whole){
      Pattern p = Pattern.compile(".{1}");
      Scanner scan = new Scanner(whole);
      scan.useDelimiter(p);
      for (int i = 0; i < whole.length(); i++){
          System.out.println(scan.next());
      }
    }

I then ran a test of it with this line:

stringPrinter("okay");

Now in my head, this should work as follows:

  • It takes in a String and sets it to the variable name whole.
  • It compiles a Pattern saved to the variable p, that is comprised of any one character.
  • It creates a Scanner object that is set to scan the String whole.
  • It sets the delimiter of the scanner to that Pattern p that we defined (so it will stop after every one character it finds).
  • It will run a loop that will run exactly as many times as their are characters in the String whole.
  • The statement that it will run that many times finds one character, and then prints that out to the console.

So I would expect the output 'o', 'k', 'a', and 'y' each on their own lines.

But the actual output it gives is:

. 


 Exception in thread "main" java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Unknown Source)
    at java.util.Scanner.next(Unknown Source)
    at WholeNumber.stringPrinter(WholeNumber.java:37)
    at WholeNumber.main(WholeNumber.java:28)
    .

(Except that there are not those periods. There are just three blank lines on top and a blank line beneath. I added those periods so the whitespace would show up here).

I assume that the stack trace has something to do with it iterating one extra time but there not being a new character. Yet even if I comment out the second to last line of my code (where the for loop is declared) I still get this output:

 .

(just a blank line)

So could someone help me figure out what's going on? I'm really not sure what's wrong with this program. Any help is appreciated so thanks in advance!

P.S. And yes, I checked this post before posting this question. It confirmed my impression that . should check for any character and {1} after it should make sure it is looking for exactly one character.

Community
  • 1
  • 1
Guy
  • 602
  • 1
  • 9
  • 20
  • Do you want to _iterate_ over a string one character at a time, or do you want to _read_ one character at a time from the console? – Tim Biegeleisen Dec 08 '16 at 02:35
  • Oh, sorry, I guess I want to read one character at a time from the String that the method takes in and then **output** it to the console. – Guy Dec 08 '16 at 02:38
  • 1
    `for (int i=0; i < input.length(); ++i) { System.out.println(input.charAt(i)); }` – Tim Biegeleisen Dec 08 '16 at 02:39
  • 1
    @Guy There are many simpler ways to print out a String char-by-char, is there a reason for doing it the hard way? – Scary Wombat Dec 08 '16 at 02:41
  • Oh, I guess not. I wasn't really aware of the .charAt() method when writing this. But since this was for a quiz, I wasn't supposed to look up the exact way to do it. – Guy Dec 08 '16 at 02:55
  • 1
    But I suppose even if I do accomplish it a different way, my question can still be answered, right? – Guy Dec 08 '16 at 02:57

2 Answers2

1

So could someone help me figure out what's going on?

Sure. Ex ante note: The delimiting pattern ".{1}" is equivalent to "." (there's no added value in defining that an element occurs one time).

The key to understanding your code's behavior are these sentences from the Scanner docs:

The next() and hasNext() methods … first skip any input that matches the delimiter pattern, and then attempt to return the next token. …

Depending upon the type of delimiting pattern, empty tokens may be returned. … The delimiting pattern "\\s" could return empty tokens since it only passes one space at a time.

So, since the delimiting pattern matches any character, each character (o k a y) in the whole String is a delimiter, and the three empty tokens in between are returned by next().

To truly get each character as a token, we can use the empty delimiting pattern: .compile("").

Armali
  • 14,228
  • 13
  • 47
  • 141
  • 1
    Wow, thanks for the answer on a really old question! So it looks like I was parsing the string using each character as the point at which it would skip and it would get the next piece of the string that wasn't the delimiter (AKA nothing). Makes sense to me! – Guy Jun 08 '18 at 17:29
-1

You can turn the string into a character array with string.toCharArray()

Then you can iterate over each of the characters and print it

This_Is_Alex_
  • 305
  • 1
  • 6