By the end of this module, for simple programs, you will be able to:
Explore how arrays are used with chars and strings.
Practice programming with such arrays.
3.0 Audio:
3.0 Arrays of chars
Working with a
char
array is similar to what we did with
int
arrays or
double
arrays.
Consider this example:
public class CharArrayExample {
public static void main (String[] argv)
{
char[] word = {'a', 'l', 'o', 'h', 'a'};
for (int i=0; i<word.length; i++) {
System.out.println (word[i]);
}
}
}
Here, the empty square brackets after the reserved
word
char
indicate the declaration of an array of
char's:
char[] word = {'a', 'l', 'o', 'h', 'a'};
The actual variable (our choice of variable name) is
word:
char[] word = {'a', 'l', 'o', 'h', 'a'};
And, in this case, we are specifying the array contents
at the time of declaration:
char[] word = {'a', 'l', 'o', 'h', 'a'};
We could have, alternatively, assigned each array entry:
Notice the syntax for specifying the size of
an array whose elements are to be assigned later:
char[] word = new char [5];
We are using the reserved word
new
here.
3.1 Exercise:
Type up the above
(in MyCharArrayExample.java)
but change the "aloha" to your own greeting, or a primal
scream if you prefer.
Let's do something more interesting in the next example:
public class CharArrayExample2 {
public static void main (String[] argv)
{
char[] word = {'d', 'e', 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e'};
char c = 'e';
for (int i=0; i<word.length; i++) {
if (word[i] == c) {
System.out.println ("Found 'e'");
}
}
}
}
Here, we are examining each entry in the array to see if equals
(the
== comparison)
a given character.
Instead of defining the comparison with
c
separately, we could have written
for (int i=0; i<word.length; i++) {
if (word[i] == 'e') {
System.out.println ("Found 'e'");
}
}
3.2 Exercise:
Type up the above
(in MyCharArrayExample2.java)
but change the word to "aloha" and look for 'a' instead of 'e'.
3.3 Exercise:
In MyCharArrayExample3.java,
change the word to "dereference" and, instead of
printing e's, count the number of occurences
of the character e.
Next, let's count the number of vowels in a word:
public class CharArrayExample4 {
public static void main (String[] argv)
{
char[] word = {'f', 'a', 'c', 'e', 't', 'i', 'o', 'u', 's'};
int vowelCount = 0;
for (int i=0; i<word.length; i++) {
if ( (word[i] == 'a') || (word[i] == 'e') || (word[i] == 'i') ||
(word[i] == 'o') || (word[i] == 'u') ) {
vowelCount ++;
}
}
System.out.println ("Number of vowel's: " + vowelCount);
}
}
3.4 Exercise:
In module3.pdf,
draw a table that traces the values of the variables, showing
what happens in the loop.
3.5 Exercise:
In MyCharArrayExample4.java,
we'll perform the comparison a little more smartly. Here's an
outline:
public class MyCharArrayExample4 {
public static void main (String[] argv)
{
char[] word = {'f', 'a', 'c', 'e', 't', 'i', 'o', 'u', 's'};
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
int vowelCount = 0;
for (int i=0; i<word.length; i++) {
// Write your code here
}
System.out.println ("Number of vowel's: " + vowelCount);
}
}
Write an inner for-loop that will compare against each vowel
and update the count accordingly.
3.6 Video:
3.1 Arrays of strings
Let's start with an example:
public class StringArrayExample {
public static void main (String[] argv)
{
String[] someStrings = {"Hello", "World!"};
for (int i=0; i<someStrings.length; i++) {
System.out.println (someStrings[i]);
}
}
}
Once again, the square brackets following
String
indicate an array of that type:
String[] someStrings = {"Hello", "World!"};
In this case our variable name is
someStrings.
Initialization is similar to other types of arrays. Here,
of course, each array entry is an entire string,
delimited by double-quotes.
String[] someStrings = {"Hello", "World!"};
Once again, we could done array creation and assignment
separately:
Notice the syntax for specifying the size of
an array whose elements are to be assigned later:
String[] someStrings = new String [2];
Here's another example:
public class StringArrayExample2 {
public static void main (String[] argv)
{
String[] someStrings = {"dereference", "engineer", "ee cummings"};
int eCount = 0;
for (int i=0; i<someStrings.length; i++) {
// The i-th string's length:
int L = someStrings[i].length();
// For the i-th string, pull out each letter to compare against 'e'
for (int j=0; j<L; j++) {
char c = someStrings[i].charAt(j);
if (c == 'e') {
eCount ++;
}
}
}
System.out.println (eCount);
}
}
The outer-loop goes through the strings one by one.
For each such string, we examine all the characters in
the string:
The inner loop starts at 0.
And ends at the length of the current string, which
we've captured in
L.
Notice that
char c = someStrings[i].charAt(j);
retrieves (a copy of -- it's not removed from the string)
the j-th character in the current (i-th) string.
A slightly more compact way of writing the same code:
for (int i=0; i<someStrings.length; i++) {
for (int j=0; j<someStrings[i].length(); j++) {
if (someStrings[i].charAt(j) == 'e') {
eCount ++;
}
}
}
Here, we've dispensed with the additional variables we used
earlier:
L.
and
c.
What's important to notice:
Because
someStrings[i]
is the i-th entry of an array of strings,
someStrings[i]
is a string!
This means, we can go "inside the box" and use the
things we've been using with strings such as
char c = someStrings[i].charAt(j);
and
int k = someStrings[i].length();
In the latter case, for example, we are obtaining the length
of the i-th string and is a shorter way than
String s = someStrings[i];
int k = s.length();
3.7 Exercise:
In MyStringArray3.java,
examine each string in an array to see if it starts and ends
with the same letter, and print only those strings that
start and end with the same letter. Here's an outline:
public class MyStringArray3 {
public static void main (String[] argv)
{
String[] someStrings = {"alfafa", "river", "edge", "nope"};
// Write your code here:
}
}
Clearly, this should print "alfafa", "river" and "edge".
3.8 Audio:
3.2 Converting a string into an array of chars
Using
toCharArray()
in a string,
one can pull out (a copy of) the letters of a string into
an array:
public class StringToChars {
public static void main (String[] argv)
{
String s = "Avast ye scallywags!";
char[] letters = s.toCharArray ();
for (int i=0; i<letters.length; i++) {
System.out.print (letters[i]);
}
System.out.println ();
}
}
This is useful when we want to manipulate the letters.
As an example, let's sort the letters in a word:
Note: we can't change the letters inside a string.
What we'll need to do: pull out the letters into an array
and sort the letters within that array.
How to sort? We'll use this idea:
Find the (alphabetically) smallest letter and put that in
the first spot in the array.
Then find the next smallest letter.
And so on.
For example:
Suppose we want to sort the letters
s h a l o m
We want to search through for the letter that should go into
the first position:
s h a l o m
and swap that with whatever is there now:
a h s l o m
That's done and we don't look back.
Next we scan from "h" onwards for the smallest.
a h s l o m
Nothing is smaller than h, so we leave it there.
Now look from "s" onwards:
a h s l o m
The smallest is "l" so swap that with "s"
a h ls o m
The next letter is "s" (which got moved):
a h l s o m
and the smallest among the remaining is "m"
a h l s o m
After that swap:
a h l m o s
Then, we look from "o" onwards:
a h l m o s
Nothing is smaller so it stays.
Lastly, there's "s" but nothing to its right. And so we're done:
a h l m o s
(Remember the ahlmos?)
Here's sample code using a different word whose letters we
wish to sort:
public class CharSort {
public static void main (String[] argv)
{
// A string whose letters we want to sort:
String w = "Cowabunga";
// Pull the letters out into a char array:
char[] letters = w.toCharArray ();
for (int i=0; i<letters.length-1; i++) {
// Start by assuming i-th letter is the smallest.
char smallest = letters[i];
// We'll need to record the position where the smallest occurs.
int smallestIndex = i;
// Now try each position to the right of the i-th position:
for (int j=i+1; j<letters.length; j++) {
// If the letter here is smaller than the smallest so far
// then update the smallest and its location.
if (letters[j] < smallest) {
smallest = letters[j];
smallestIndex = j;
}
}
// We now know the smallest and where it occurs.
// Next: swap char at i with char at smallestIndex
char temp = letters[i];
letters[i] = letters[smallestIndex];
letters[smallestIndex] = temp;
}
// Print result.
for (int i=0; i<letters.length; i++) {
System.out.print (letters[i]);
}
System.out.println ();
}
}
This is a bit long so let's work through this in steps.
3.9 Exercise:
Type and execute the above program.
Let's now explain:
First, the easy parts:
// This part pulls out the letters:
String w = "Cowabunga";
char[] letters = w.toCharArray ();
// ... the sorting part we'll explain later ...
// Print result.
for (int i=0; i<letters.length; i++) {
System.out.print (letters[i]);
}
System.out.println ();
OK, now let's focus on the outer loop:
for (int i=0; i<letters.length-1; i++) {
// We want to get the i-th smallest letter
// and put that in letters[i]
letters[i] = ... (somehow find the i-th smallest letter)
}
The first thing to observe is that this sorts the array because:
The 0-th smallest letter (the smallest of all letters) will
end up in
letters[0].
The next smallest will end up in
letters[1].
And so on.
That means the array will be sorted.
Now let's focus on getting the i-th smallest.
Suppose we are able to find the location of the
smallest letter, then we could swap that letter into the i-th location:
Suppose i=2 and the location of the smallest is 5.
Move whatever's at location 5 into location 2.
Move whatever's at location 2 into location 5.
Now we have the smallest in location 2.
So, here's the swap:
for (int i=0; i<letters.length-1; i++) {
// We want to get the i-th smallest letter
// and put that in letters[i]
// Suppose the i-th smallest occurs at position smallestIndex.
// We swap to get that one into letters[i].
char temp = letters[i];
letters[i] = letters[smallestIndex];
letters[smallestIndex] = temp;
}
All that's left is to find the i-th smallest.
for (int i=0; i<letters.length-1; i++) {
// Default is what's at i:
char smallest = letters[i];
int smallestIndex = i;
// Look to the right of i (from i+1 onwards)
for (int j=i+1; j<letters.length; j++) {
// Compare with smallest so far (in the smallest variable)
// and update smallest and position if needed.
}
// Do the swap etc (we've seen this) ...
}
3.10 Exercise:
In module3.pdf,
trace through the program drawing out the array at each
step, as well as the values of the key variables:
i,
j,
smallest,
smallestIndex.
Even though this is tedious, it will be worth it.
Understanding sorting will help you understand how to
work with many types of array problems.
3.11 Video:
3.12 Exercise:
In StrangeComparison.java
use the following template:
public class StrangeComparison {
public static void main (String[] argv)
{
// Two strings:
String w1 = "verbose";
char[] letters1 = w1.toCharArray ();
String w2 = "observe";
char[] letters2 = w2.toCharArray ();
// Sort the letters of the first string:
// Sort the letters of the second string:
// Now letters1 and letters2 are sorted.
// Compare the corresponding chars in letters1
// and letters2 to see if the two arrays are equal:
}
}
What is the relationship between two words whose sorted arrays are
exactly equal? And, therefore, what have we developed
an algorithm to detect?
3.3 Fun with string arrays
Let's examine a list of all words from another language
and perform some simple analysis.
As our example, we'll use a language that's been heard
by many around the world. Here are some words in that language:
What we'll do is count the number of words that use
apostrophes:
public class KlingonCount {
public static void main (String[] argv)
{
// Get the full list of words:
String[] words = WordTool.getKlingonWords ();
// Set up counter:
int numWordsWithQuotes = 0;
for (int i=0; i<words.length; i++) {
int quoteCount = 0;
for (int j=0; j<words[i].length(); j++) {
char c = words[i].charAt (j);
if (c == '\'') {
quoteCount ++;
}
}
if (quoteCount > 0) {
numWordsWithQuotes ++;
}
}
// Print
System.out.println ("Total # words: " + words.length);
System.out.println ("# with quotes: " + numWordsWithQuotes);
}
}
3.13 Exercise:
In Klingon2.java,
modify the above to identify the ratio (as a decimal) of words
with "u" in them to all the words. Make sure you cast the integers into
double's before
computing the ratio. Which vowel is used more than others
in Klingon?
You will need
WordTool.java
and
klingonwords.txt.
3.4 A mystery demystified
Consider this program:
public class CommandLineArguments {
public static void main (String[] argv)
{
for (int i=0; i<argv.length; i++) {
System.out.println (argv[i]);
}
}
}
3.14 Exercise:
Type up and execute the program in the usual way:
$ java CommandLineArguments
What do you see? Then, type the following at the terminal:
$ java CommandLineArguments 1 two hello there!
Thus, we now understand why there was an array of strings:
Java wanted a way to allow users of your program to
enter what are called command line arguments.
Think of these as options or input to provide the
program.
These are collected together and given to you
in the array of strings.
3.15 Exercise:
At the command line, type in
$ ls
Then, type in this variation:
$ ls -1
The output is different (one file per line).
As you can see,
ls
is just another program like
CommandlineArguments,
which can read past the name of the program to
see what additional things the user typed.
It is common for terminal (command-line) programs to
feature lots of options.
Most options use a minus sign like above. This is merely
Unix tradition.
3.5 Reading and writing
From here on, we will assume you will absorb whitespace conventions
directly from the examples provided.
For example, you should have inferred the whitespace conventions
for square brackets:
We write
char temp = letters[i];
but not
char temp = letters [ i ];
nor even
char temp = letters [i] ;
Going forward, we will only highlight a few things
regarding reading and writing that might not
be apparent from the examples.
Strings over multiple lines:
It's often more readable when a long list of strings uses
one line per string.
String[] wordsWithNoVowels = {
"glyph", // sculpture term
"gypsy",
"lymph", // medical term
"myrrh",
"psych",
"rhythm",
"syzygy" // astronomy term
};
Choosing variable names:
This is somewhat a combination of convention (i for for-loop
variable) as art, analogous to how an editor crafts section
titles or article subheadings.
Consider some code we wrote earlier:
String w = "Cowabunga";
char[] letters = w.toCharArray ();
for (int i=0; i<letters.length-1; i++) {
char smallest = letters[i];
int smallestIndex = i;
for (int j=i+1; j<letters.length; j++) {
// ... etc
Here, some variable names like
w
carry no meaning by themselves.
Yet, others like
smallestIndex
clearly do.
How to choose what to do?
Generally, workhorse variables that we're all used to,
like the
i's
and
j's
in for-loops are single letter.
When a variable is key to understanding an idea,
like
smallestIndex
above, it's best to be a bit verbose and make the meaning clear.
At the same time, we shouldn't go overboard as in:
thisIsTheIndexWhereTheSmallestLetterOccurs
3.6 When things go wrong
3.16 Exercise:
What are the two syntax errors below?
String[] words = {"Beep", "Keep", "ee cummings"};
for (int i=0; i<words.length(); i++) {
if (words[i].length > 4) {
System.out.println (words[i]);
}
}
3.17 Exercise:
The program below wishes to identify words that have
a letter that occurs at least twice in succession
like "ee" in "beep".
What is the logical error below?
String w = "ee cummings";
char[] letters = w.toCharArray ();
boolean hasLetterPair = false;
for (int i=0; i<letters.length; i++) {
if (letters[i] == letters[i+1]) {
hasLetterPair = true;
}
}