import java.util.Scanner;

/**
 * Demonstrates a number of ways of printing one word of a string per line.
 *
 * @author Zach Tomaszewski
 * @version 18 Mar 2008
 */
public class PrintOneWordPerLine {

  /**
   * Shows results for each method in this class.
   */
  public static void main(String[] args) {

    String hello = "This is my string of many words.";
    PrintOneWordPerLine.charByChar(hello);
    PrintOneWordPerLine.wordByWord(hello);
    PrintOneWordPerLine.byReplacing(hello);
    PrintOneWordPerLine.usingScanner(hello);

    //Note that the above methods assume a string is well-behaved.
    //What if it has tabs, newlines, and/or multiple spaces between words?
    //Then this happens:
    String robust = "  This  is my    String \tof\n many words.";
    System.out.println("\nBROKEN EXAMPLE: ");
    PrintOneWordPerLine.charByChar(robust);

    //But these methods can gracefully handle even this kind of input
    System.out.println("\nROBUST EXAMPLES: ");
    PrintOneWordPerLine.usingScanner(robust);  //as above
    PrintOneWordPerLine.charByCharRobust(robust);
  }


  public static void charByChar(String str) {
    //goes through the string, character by character.
    //Prints a \n for each space
    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) == ' ') {
        System.out.println();
      } else {
        System.out.print(str.charAt(i));
      }
    }
    System.out.println();
  }

  public static void wordByWord(String str) {
    //Uses only indexOf and substring to grab a word at a time.
    //(still only as robust as charByChar)
    int wordStart = 0;
    int wordEnd = str.indexOf(' ');
    while (wordEnd != -1) {
      System.out.println(str.substring(wordStart, wordEnd));
      wordStart = wordEnd + 1;
      wordEnd = str.indexOf(' ', wordStart);
    }
    //Print last word
    System.out.println(str.substring(wordStart, str.length()));
  }

  public static void byReplacing(String str) {
    //rather than going by charByChar, let a method do the same thing for us
    str = str.replace(" ", "\n");
    System.out.println(str);
  }

  public static void usingScanner(String str) {
    //You can use a scanner to read from a string as well as a stream
    //Remember that next() will ignore surrounding whitespace
    Scanner scan = new Scanner(str);
    while (scan.hasNext()) {
      System.out.println(scan.next());
    }
  }

  public static void charByCharRobust(String str) {
    //goes through the string, character by character.
    //Prints a single \n for each whole group of white space characters
    str = str.trim();
    for (int i = 0; i < str.length(); i++) {
      if (Character.isWhitespace(str.charAt(i))) {
        while (Character.isWhitespace(str.charAt(i + 1))) {
          //skip over all white space chars
          i++;
        }
        System.out.println();
      } else {
        System.out.print(str.charAt(i));
      }
    }
    System.out.println();
  }
}

