S-111
  • Home
  • Lectures
  • Problem Sets
  • Sections
  • Syllabus
  • Schedule
  • Staff
  • Resources
  • Canvas
  • Ed Discussion
  • Gradescope

Section 6

Agenda

  • Take lecture questions
  • Review exercises
  • Java exercises

Review exercises

Review of for loops over strings

Recently, you wrote various string manipulation and string printing methods, many of which used for loops and string methods like charAt(). Today we will review one of the methods from the last section to fully understand how they work.

Recall the padString() method from Tuesday, which took a string str and an integer maxLength and printed the string with padding on the left such that the total number of printed characters was exactly maxLength. If the string’s length was greater than or equal to maxLength, the string would be printed with no padding. A potential solution is included below.

public static void padString(String str, int maxLength) {
    int numSpaces;

    if (str.length() >= maxLength) {
        numSpaces = 0;
    } else {
        numSpaces = maxLength - str.length();
    }

    for (int i = 0; i < numSpaces; i++) {
        System.out.print(" ");
    }

    System.out.println(str);
}

This solution contains a straightforward use of the loop “template” you saw in lecture. For the calculated value of numSpaces, the for loop will run numSpaces times, printing one space each time.

Here’s another possible solution.

public static void padString(String str, int maxLength) {
    for (int i = 0; i < maxLength - str.length(); i++) {
        System.out.print(" ");
    }

    System.out.println(str);
}

This version is more complex, but produces the same result. The key idea of this solution is that, if the expression maxLength - str.length() is zero or a negative number, no spaces should be printed before the string and the for loop will fail the test i < maxLength - str.length() immediately. The previous solution made explicit this check by using a conditional.

Ultimately it is up to you to choose your approach for solving a problem like this, but while the first solution is longer, it is much easier to understand and debug.

More Review of Procedural Decomposition

  1. Suppose we need to write a program which computes the price that a person would pay for a restaurant buffet. The program must ask the user for any information that may be needed to compute and print the price. The pricing scheme for the buffet is as follows:

    Children

    • $15 per child over 5 years old
    • free for children 5 years old and younger

    Adults

    • $30 per adult (18 and older)
    • $20 per adult (18 and older) with coupon

    Senior citizens

    • $18 per senior citizen (65 years and older)
    • $10 per senior citizen (65 years and older) with coupon

    This is an example of a problem where the logic is non-trivial; we need to use conditional execution to decide how to proceed. The program should behave differently depending on the age of the customer and whether or not they have a coupon. To do this, we can use conditional execution structures such as if, else if, and else. To accomplish this, you should develop the program in several steps:

    • Begin with an unstructured solution to the problem that has all of the code in the main method. The unstructured solution can be found here.

    • Next, factor out the code that is common to multiple cases. It is better to put duplicated code outside of if, else if, or else blocks (either before or after) rather than repeating it several times.

    • Create a fully structured solution that uses procedural decomposition. In other words, you should break out pieces of your code into methods and call those methods when appropriate from your main() method.

    You may find it helpful to refer to the ticket pricing example or coffee shop example from the lecture notes on conditional execution in solving this problem. 1

Additional exercises

  1. Write a method encode() that takes a string str that we will assume consists of lowercase letters and an integer offset and returns a new string where each letter of str is shifted ahead offset spaces in the alphabet. For example, encode("andrew", 3) should return "dqguhz" since:

    • 'a' shifted ahead by 3 letters is 'd'
    • 'n' shifted ahead by 3 letters is 'q'
    • 'd' shifted ahead by 3 letters is 'g'
    • 'r' shifted ahead by 3 letters is 'u'
    • 'e' shifted ahead by 3 letters is 'h'
    • 'w' shifted ahead by 3 letters is 'z'

    The method should work for strings that contain lowercase letters; don’t worry about other types of characters. Make sure that the shifting “wraps around” — in other words, encode("zzz", 1) should evaluate to "aaa"! 2

  2. Write a method decode() that takes a string str and an integer offset and reverses the changes that encode() made to encode the string. In other words, the following code fragment should output preserved:

    String str = "preserved";
    String encoded = encode(str, 6);
    String decoded = decode(encoded, 6);
    System.out.println(decoded);
    

    Try to make your decode() method as short as possible. In fact, it is possible to write the method using only one line! 3


  1. RestaurantPrice2.java ↩

  2. The method is included below. There are several other alternative solutions, including one that uses a conditional to check if adding the offset to the existing character code causes it to go past the code for 'z'.

    public static String encode(String str, int offset) {
        String encoded = "";
    
        /*
         * We're taking advantage of the fact that the ASCII
         * character codes for the alphabet are sequential and
         * ascending from the code for 'a', as you learned
         * in Problem Set 1. In addition, we are making the
         * assumption stated in the question that we only
         * handle lowercase letters.
         */
        for (int i = 0; i < str.length(); i++) {
            int alphabetPosition = str.charAt(i) - 'a';
            int newPosition = (alphabetPosition + offset) % 26;
            char newChar = (char)('a' + newPosition);
    
            encoded += newChar;
        }
    
        return encoded;
    }
    

    ↩

  3. The method is included below. There are several other alternative solutions, including one that uses a conditional to check if subtracting the offset to the existing character code causes it to go before the code for 'a'.

    public static String decode(String str, int offset) {
        if(offset > 26){
            offset = offset % 26;
        }
        String decoded = "";
    
        /*
         * If subtracting the offset from a character goes to a
         * character that comes before 'a', then
         * alphabetPosition - offset will be negative, and
         * so will (alphabetPosition - offset) % 26.
         * We can wrap *back* around to the end of the alphabet
         * by adding this negative value to 26, which represents the
         * end of the alphabet.
         */
        for (int i = 0; i < str.length(); i++) {
            int alphabetPosition = str.charAt(i) - 'a';
            int newPosition = (26 + (alphabetPosition - offset)) % 26;
            char newChar = (char)('a' + newPosition);
    
            decoded += newChar;
        }
    
        return decoded;
    }
    

    ↩

Last updated on July 2, 2025.