CS107 - Lab 6

Java Programming (arrays, strings)

In this lab you will work on arrays and strings in Java.

As you read and try to figure out each problem, look over the examples that we did in class. They will answer many of the questions you may have. Also, there will be things which we did not explicitly discuss in class, and which I'll expect you to figure out by yourselves.

Always start by thinking of the problem top-down. Split it into logical steps, and write one step at a time. Then compile it, and check if it does what you want. Write your code incrementally! This will save you much trouble.

As a computer scientist the goal is not to memorize the details of how you do things (actually, many computer scientists have very bad memories), but rather to develop your problem solving skills. Keep all your documentation close by, check all the files and all the handouts that you want, check the web for documentation if you like, whatever (which does not violate the honor code); the goal is to solve the problems, learn how to think, and be able to do it faster next time around! And, last but not least, I hope you have fun!!

If your program compiles, but when run it does not give you quite the desired output, then we say that it has bugs. Try to debug it. Try to understand what happens, what are the instructions that are being executed, in what order. To debug, people use lots of "print" instructions. For instance, if something wrong happens in a loop, then print out the values of the variables that are relevant to the loop; this will help you understand how values change in each iteration.

Before you raise your hand for help, try to understand what happens with your program. If it is a compile problem, read the messages on the screen; the compiler tries to give you a hint of what went wrong; can you figure out what it's telling you?

Don't forget to pay attention to issues of programming style: indentation, comments, descriptive names, spaces (see handouts). If you develop a good programming style, programming will come easier to you (plus, I wont take points off). And it will be easier for others to help you.

As usual, work individually, and call me if you need help. You are encouraged to discuss ideas and techniques broadly with other class members, but not specifics. Discussions should be limited to questions that can be asked and answered without using any written medium (e.g. pencil and paper or email). You should at no point look at the screen of your colleagues.

Enjoy!


  1. Counting the number of occurences of a letter in a string. In this problem you will ask the user for a text and a query character, and count how many times that character occurs in the text. Your program should allow the user to enter as many characters as they wish, and query them.

    The very first thing you should do is tell the user what the program does, and ask them for a text. Then ask them for a query character. At the end, after printing how many occurences of that letter, ask them if they have another letter that they want to query (the text remains the same), and get a new response. If the user says 'yes', then you should ask for a new letter, et cetera. If the user says 'no', the loop (and the program) should terminate.

    Your program will contain two while-loops, one inside the other. The code that explains the program and reads the text from the user will be outside the outer repetition loop. The outer loop will ask the user for query letters, and print the answer. Inside the outer repetition loop, you will write the code which counts how many times a letter occurs in the text (the inner loop).

    To check the length of a string you will use a method on strings called length:

    int length()
    
    Returns the length of the string.
    
    Example:
    String s = "strings";
    
    int l = s.length(); //this assigns value 7 to l
    

    We have seen readString, which reads a word. To read a whole line, use readLine:

    ReadStream r = new ReadStream();
    String s;
    s = r.readLine();     // read a whole line from input
    

    To test whether a letter occurs in a string you will use another method on Strings, called charAt. This is a method that returns a character (letter) of a string, at a specified position.

    char charAt(int index) 
    
    Returns the char value at the specified index.
    
    Example: consider the string s = "computers". Then s.charAt(0) will return the first character of "computers", namely c. Similarly, s.charAt(1) will return the second character, namely o, and so on.

    Since the method returns a chracter, you can assign the value returned to a variable of type char. Check out the example below.

    String s; 
    char c;
    int i; 
    ... 
    i  = 10; 
    c = s.charAt(i); 
    if (c == 'a')
         System.out.println("The letter at position " + i + " is a"); 
    ...
    

  2. Cryptology using Caesar's cypher. Cryptology is the science of "secret codes". Messages are encoded before they are sent out to keep their content secret if they are intercepted by the wrong parties; they are decoded when they are received to retrieve the original information.

    The most famous instances of cryptology occur in military history, beginning with Julius Caesar of the Roman Empire, who developed the Caesar Cypher, and certainly including the German Enigma code cracked by the Allies during World War II (by Alan Turing, a British mathematician and computer scientist).

    Transmitting information securely has taken a modern turn with electronic commerce on the Internet and concerns over protection of consumer credit card information and other personal data.

    A Caesar cypher, also called a shift cypher, involves shifting each character in the message to another character some fixed distance farther along in the alphabet. Specifically, let s be some integer between 1 and 25 that represents the amount of the shift. Each letter in the message is encoded as the letter that is s units farther along in the alphabet, with the last s letters of the alphabet shifted in a cycle to the first s letters.

    For example, if s=3, then a is encoded as d, b is encoded as e, etc. Notice that you have to wrap-around the end of the alphabet so that x is encoded as a, and z is encoded as c.

    To shift a character you can simply use +, that is, 'a' + 1 is 'b'. However, 'z'+1 is not 'a', but the character that comes after 'z'; to see what that is, you could try to print System.out.print("z+1 is " + ('z'+1))). Thus you will need to take care of rolling-over.

    Decoding a message requires knowing s. For example, knowing that s=3, the code word dupb is decoded as army.

    Write a program that reads a word consisting only of lower case letters from the user and encodes it using Caesar cypher with s=3. I suggest that you use a constant variable for s, for instance final int SHIFT = 3;.

    You have already seen Strings, and some methods that you can use on them. In this program you will need to modify a word, that is, the cypher; you will need to ability to set the characters in the cypher, one by one, to the desired coded value. Strings do not offer this functionality; that is to say, are imutable, they cannot be modified.

    In this program you will see a new class StringBuffer. A StringBuffer is like a String, but it lets you change the contents. One of the basic methods of StringBuffer is append:

    void append(char ch) // appends ch to the string buffer 
    Example:
    StringBuffer sb = new StringBuffer(); 
    sb.append('x');
    sb.append('y'); 
    sb.append('z'); 
    System.out.println(sb); // prints xyz
    

    Use the following skeleton for your program:

    /* 
    ...
    */
    public class Crypto {
            
        public static void main (String args[]) {
    
    	       //print welcoming message and describe the program to user
    		System.out.println("Welcome to cryptomaster!");
    		...
    	
    		//declare the variables
    		ReadStream r = new ReadStream();
    		String original;  //original message 
    		StringBuffer cypher;    //encrypted message
    
    
    		//read the message
    		System.out.print("Enter the message..... ");
    		original = r.readString(); 
    		r.readLine();
    		...
    
    
    		//encode the message; that is, examine every character
    		//of message in order, shift it, and append it in
    		//order into cypher.
    		cypher = new StringBuffer();
    		int i = 0; 
    		while (i < original.length()) {
    		     ...
    		}				
    
    
    		//print out the cypher, character by character
    			System.out.print("Encrypted message: ");
    			...
    
    	} //end of main
    } //end of class
    
    Extra challenge/credit: After encoding the message, decode it. The goal is to obtain the original message. What does the following translate to? frpsxwhuvflhqfh lv vr frro

  3. The palindrome problem. A palindrome is a word that reads the same forward and backward, like
    abba 
    ala
    Campus motto: Bottoms up, Mac.
    Madam, in Eden, I'm Adam.
    Naomi, sex at noon taxes, I moan.
    Never odd or even.
    
    For examples of more involved palindromes check out this.

    Write a program that checks whether a string entered by the user is a palindrome, or not. The program should start by printing a welcome, explanatory message. Then it should ask the user to enter a string. Then it should check whether the string is a palindrome, and finally print the result.

    Don't worry about punctuation and spaces in the input (extra credit).

    Your program should ignore make no distinction between lower and upper case letters.

    To ignore upper v.s. lower case, I suggest that you use a method on Strings called toLowerCase(). This converts the string to a new string, in which all characters are lower case.

    String	toLowerCase() 
              
    Converts all of the characters in this String to lower case.
    
    For example, if s = "HeLlo.", then s.toLowerCase() returns a new string "hello.". Here is an example:
    String name, lowerCaseName; 
    
    //set a value for name
    ...
    
    lowerCaseName =	name.toLowerCase(); 
    //now the string lowerCaseName is the lower-case version of the string name
    
    ...
    

    As always, use a top-down, incremental approach. I suggest that you start by assuming that the string input by the user has no spaces, is all lower case, and contains no punctuation or dot at the end. Once you get this to work well, refine your code to ignore upper v.s. lower case difference.

    Extra challenge (and extra credit :)): Make your program ignore spaces and punctuation. To check whether a character is not an alphabet letter, you can use character arithmetic:

    char ch; 
    ...
    if ((ch < 'a') || (ch > 'z')) {
           //this will be true if ch is not an alphabet letter between 'a' and 'z'
    
    }
    
    


What to turn in:

Send me only the .java files (not the entire folder), all in the same email, as attachments.