10. Strings and String Processing

10.8. Processing Each Character in a String

Many string-processing applications require you to process each character in a string. For example, to encrypt the string “hello” into “jgnnq”, we have to go through each letter of the string and change each character to its substitute.

These types of algorithms usually involve a counting loop bounded by

the length of the string. Recall that the length() method determines Counting loop algorithm

the number of characters in a String and that strings are zero indexed. This means that the first character is at index 0, and the last character is at index length()-1. For example, to print each character in a string on

 

a separate line, we would step through the string from its first to its last character and print each character::

,,

 

 

 

 

 

 

Counting bound

 

 

 

 

 

 

 

 

 

 

Off-by-one error


J

Note that our loop bound is k < str.length(), since the index of the last character of any String is length()-1. Note also the use of str.charAt(k) to retrieve the kth character in str on each iteration of the loop.

Note the use of pre- and postconditions in the method’s comment block. The precondition states that str has been properly initialized— that is, it is not null. The postcondition merely states the expected behavior of the method.

Off-by-One Error

A frequent error in coding counter-controlled loops is known as the off- by-one error, which can occur in many different ways. For example, if we had coded the loop boundary condition as k <= str.length(), this would cause an off-by-one error, because the last character

 

in str is at location length()-1. This would lead to a Java IndexOutOfBoundsException, which would be reported as soon as the program executed this statement.

The only way to avoid off-by-one errors is to check your loop bounds whenever you code a loop. Always make sure you have the loop counter’s initial and final values correct.

 

 

 

 

 

 

 

 

Method design

 

Algorithm design


Example: Counting Characters

As another example of an algorithm that processes each character in a string, consider the problem of computing the frequency of the letters in a given document. Certain text analysis programs, such as programs that analyze encrypted data and spam filters, perform this type of function.

The countChar() method will count the number of occurrences of any particular character in a String (Fig. 7.11). This method takes two parameters: a String parameter that stores the string being searched and a char parameter that stores the character being counted.

Begin by initializing the local variable, counter, to 0. As in the pre- vious example, the for loop here will iterate through each character of the String—from 0 to length()-1. On each iteration a check is made to see if the character in the kth position (str.charAt(k)) is the char- acter being counted. If so, counter is incremented. The method ends

 

,,

 

 

 

 

 

 

J

Figure 7.11: A method to count the occurrence of a particular character in a string.

 

by returning counter, which, when the method completes, will store an integer representing the number of ch’s in str.

Example: Reversing a String

Another interesting method that processes each character in a string is the reverse() method. This is a method that reverses the letters in a string. For example, the reverse of "java" is "avaj".

The algorithm for the reverse() method should use a simple count- Algorithm design

ing loop to reverse the letters in its String parameter. In this case, how- ever, we can process the string from right to left, beginning at its last char- acter and ending with its first character. That way we can just append each character, left to right, in the result string:

,,

 

 

 

 

 

 

 

 

J

Note that as in the other string-manipulation algorithms—for exam- ple, keywordSearch()—we should us a StringBuffer to store the method’s result. Thus we declare the result StringBuffer at the be- ginning of the method and convert it back into a String at the end of the method.

 

 

 

Algorithm design


Example: Capitalizing the First Letter

Another string manipulation method is the capitalize() method, which returns a String whose initial letter is capitalized but whose other letters are lowercase – for example, “Hello”. We use the static toUpperCase() and toLowerCase() methods from the Character class to convert individual letters. We could also have used the methods of the same name that we wrote in Section 5.8. The algorithm converts the first letter to upper case and then loops through the remaining letters converting each to lowercase:

,,

 

 

 

 

 

 

 

 

 

 

 

J

 

 

SELF-STUDY EXERCISES

EXERCISE 7.12 Write a Java program to test the methods described in this section. Organize the methods themselves into a single class, named StringProcessor, and design a second class to serve as the user inter- face. Because these methods are similar to the utility methods of the Math class, it would be useful to declare them static. The user interface should prompt the user to input a string and should then print out the result of passing that string to each of the methods we developed.

 

EXERCISE 7.13 Add a method to the StringProcessor class that will remove all blanks from a string. It should take a String parameter and should return a String result.

Miscellaneous String Methods

In addition to the several String class methods we have discussed— valueOf(), equals(), indexOf(), lastIndexOf(), charAt(), substring()—Table 7.2 shows some of the other useful methods in the String class. Note that because of what we said about the read-only na- ture of Strings, methods such as toUpperCase(), toLowerCase(), and trim() do not change their string. Instead they produce a new

 

ome useful String methods applied to the literal string ”Perfection.” ureExample

sWith(String suffix)"Perfection".endsWith("tion") true

rtsWith(String prefix)"Perfection".startsWith("Per") true rtsWith(String prefix, int offset)"Perfection".startsWith("fect",3) true perCase()"Perfection".toUpperCase() "PERFECTION"

werCase()"Perfection".toLowerCase() "perfection"

()"Perfection".trim() "Perfection"

 

 

 

string. If you want to use one of these methods to convert a string, you must reassign its result back to the original string:

,,

 

J