slanted W3C logo

Day 19 — Strings III

In today's lecture we look at the String accessor method substring, and the comparator methods indexOf (two versions). Several examples are given using fixed and variable-size codes.

Review: substring

String substring(int beginIndex)

Returns a new string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of this string.

Throws IndexOutOfBoundsException if beginIndex is negative or larger than the length of this string.

      String s = "James Gosling";

      String t = s.substring(0);
      String u = s.substring(1);
      String v = s.substring(s.length() - 1);
      String w = s.substring(s.length());
      output.printf("s: %s%nt: %s%nu: %s%nv: %s%nw: %s%n",
                    s, t, u, v, w);

The code fragment prints:

s: James Gosling
t: James Gosling
u: ames Gosling
v: g
w:

Statements such as:

      String s = "James Gosling";

      c = s.substring(-1);
      c = s.substring(s.length() + 1);

will cause an exception to be thrown.

Another Version of substring

String
substring(int beginIndex, int endIndex)


Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

Throws IndexOutOfBoundsException if beginIndex is negative, or endIndex is larger than the length of this string, or beginIndex is larger than endIndex.

      String s = "ABC";

      String t = s.substring(0, 1);
      String u = s.substring(0, 2);
      String v = s.substring(0, s.length());
      String w = s.substring(1, 1);
      output.printf("s: %s%nt: %s%nu: %s%nv: %s%nw: %s%n",
                    s, t, u, v, w);

The code fragment prints:

s: ABC
t: A
u: AB
v: ABC
w: 

Statements such as:

      String s = "ABC";

      String c;
      c = s.substring(-1, 1);
      c = s.substring(0, s.length() + 1);
      c = s.substring(2, 0);
      

will cause an exception to be thrown.

Comparator Methods

Comparator methods compare two String references. They also allow the client to find features in strings.

Commonly Used Comparators: indexOf

These two versions of indexOf allow the client to find the first occurrence of a character or substring in a string object.

int indexOf(int ch)

Returns the index within this string of the first occurrence of the specified character. If no such character occurs in this string, then -1 is returned.


int indexOf(String str)

Returns the index within this string of the first occurrence of the specified substring. If no such substring occurs in this string, then -1 is returned.

Examples with indexOf

The example from Day 18
Finding the index of the first 'e':

      String s = "Ada Lovelace";
      char target = 'e';
      int index = -1;
      for (int i = 0;
           i < s.length() && index < 0;
           i++)
      {
         if (s.charAt(i) == target)
         {
            index = i;
         }
      }

The loop can be replaced with an invocation of indexOf:

      String s = "Ada Lovelace";
      char target = 'e';
      int index = s.indexOf(target);  // index is 7

      index = s.indexOf('x');         // index is -1

Examples with indexOf

The client can look for a substring using indexOf:

      String s = "Ada Lovelace";
      String target = "lace";
      int index = s.indexOf(target);  // index is 8

      index = s.indexOf("ADA");       // index is -1
                                      // case sensitive

Commonly Used Comparators: indexOf

These two versions of indexOf allow the client to find the first occurrence of a character or substring in a string object starting from the client specified index.

int indexOf(int ch, int fromIndex)

Returns the index within this string of the first occurrence of the specified character, starting at the specified index. If no such character occurs in this string, then -1 is returned.


int indexOf(String str, int fromIndex)

Returns the index within this string of the first occurrence of the specified substring, starting at the specified index. If no such substring occurs in this string, then -1 is returned.

Examples with indexOf

Find the substring between the '*' characters.

      String s = "This is a *random* string";

      int first = s.indexOf('*');
      int second = s.indexOf('*', first + 1);

      String between = s.substring(first + 1, second);

Print the indexes of all of the 'e' characters.

      String s = "Tim Berners-Lee";  // WWW inventor
      char target = 'e';

      for (int index = s.indexOf(target);
           index != -1;
           index = s.indexOf(target, index + 1))
      {
         output.println(index);
      }

Simple Codes

A simple substitution cipher is a (bad) method of encrypting a text message where each character of the message is replaced with a different character. Simple substitution ciphers are easy to implement in Java using indexOf and charAt:

      final String ALPHA  = "abcdefghijklmnopqrstuvwxyz ";
      final String CIPHER = "ZEBRASCDFGHIJKLMNOPQTUVWXY ";

      String message = "keep this secret";
      String secret = "";
      for (int i = 0; i < message.length(); i++)
      {
         char c = message.charAt(i);
         int index = ALPHA.indexOf(c);
         secret = secret + CIPHER.charAt(index);
      }

The above code fragment prints: HAAM QDFP PABOAQ. It is also easy to decode the encrypted text:

      String decode = "";
      for (int i = 0; i < secret.length(); i++)
      {
         char c = secret.charAt(i);
         int index = CIPHER.indexOf(c);
         decode = decode + ALPHA.charAt(index);
      }
import java.io.PrintStream;

public class SimpleCode
{
   public static void main(String[] args)
   {
      PrintStream output = System.out;
      
      final String ALPHA  = "abcdefghijklmnopqrstuvwxyz ";
      final String CIPHER = "ZEBRASCDFGHIJKLMNOPQTUVWXY ";

      String message = "keep this secret";
      String secret = "";
      for (int i = 0; i < message.length(); i++)
      {
         char c = message.charAt(i);
         int index = ALPHA.indexOf(c);
         secret = secret + CIPHER.charAt(index);
      }
      output.println(secret);
      String decode = "";
      for (int i = 0; i < secret.length(); i++)
      {
         char c = secret.charAt(i);
         int index = CIPHER.indexOf(c);
         decode = decode + ALPHA.charAt(index);
      }
      output.println(decode);
   }
}

Fixed-Size Codes

You can use the same trick of keeping parallel strings to map between two different representations. For example, suppose you wanted a way to look up the number of days in each month:

      final String MONTHS = "JanFebMarAprMayJun" + 
                            "JulAugSepOctNovDec";

      final String DAYS   = "31 28 31 30 31 30 " + 
                            "31 31 30 31 30 31 ";

      final int SIZE = 3;

      String month = "Jun";
      int index = MONTHS.indexOf(month);   // index is 15
      String days = DAYS.substring(index,
                                   index + SIZE);

Can you find all of the months that have 30 days?

import java.io.PrintStream;

public class FixedSizeCode
{
   public static void main(String[] args)
   {
      PrintStream output = System.out;
      
      final String MONTHS = "JanFebMarAprMayJun" + 
                            "JulAugSepOctNovDec";

      final String DAYS   = "31 28 31 30 31 30 " + 
                            "31 31 30 31 30 31 ";

      final int SIZE = 3;
      
      for (int i = 0; i < 12; i++)
      {
         int startIndex = SIZE * i;
         int endIndex = startIndex + SIZE;
         int days = Integer.parseInt(DAYS.substring(startIndex, endIndex).trim());
         if (days == 30)
         {
            String month = MONTHS.substring(startIndex, endIndex);
            output.println(month + " has 30 days");
         }
      }
   }
}

Variable-Size Codes

Usually your code words will not have the same length. For example, suppose you have a 5-point scale that corresponds to some sort of rating:

   1      poor
   2      fair
   3     average
   4      good
   5    excellent

In this example, the code words range in length from 4 to 9. You can use the parallel strings trick, but you have to add spaces between the code words to make sure all of the words have 9 characters.

      final String RATING = "poor     " +
                            "fair     " +
                            "average  " +
                            "good     " +
                            "excellent";

      final String RANK   = "1        " +
                            "2        " +
                            "3        " +
                            "4        " +
                            "5        ";

      final int SIZE = 9;

      int rank = 4;
      int index = RANK.indexOf(String.valueOf(rank));
      String rating = RATING.substring(index,
                                       index + SIZE);
import java.io.PrintStream;

public class VariableSizeCode
{
   public static void main(String[] args)
   {
      PrintStream output = System.out;
      
      final String RATING = "poor     " +
      "fair     " +
      "average  " +
      "good     " +
      "excellent";
      
      final String RANK   = "1        " +
      "2        " +
      "3        " +
      "4        " +
      "5        ";
      
      final int SIZE = 9;
      
      for(int rank = 1; rank < 6; rank++)
      {
         int index = RANK.indexOf(String.valueOf(rank));
         String rating = RATING.substring(index,
            index + SIZE);
         output.println(rating);
      }
   }
}

To Do For Next Lecture

Continue reading Chapter 6.