|
| |
Part B: Practice with Strings
In this part of the assignment, you will write a program that accepts a set of
strings of
people's names, of the form:
For example, here's a set to work with:
"fred bloggs", "MARY STUART",
"eRIC SuttoN", "Francis Bailey",
"Archimedes von trapp", "Abel GRISWOLD",
"Jeffrey Guay", "Alan Swasinski",
"Leroy de la Grange", "Don Ho"
(I've intentionally mixed up the case of several of these
strings to ensure that you write the code to set the case
properly.)
Assume that:
-
the first and last names are separated by a single
space character
-
the first name does not contain any spaces
-
the last name may or may not contain one or
more spaces (for example, Bailey; von trapp, de la Grange)
Make sure that each string is properly
formatted:
Ensure that each string satisfies the following:
Explanation:
In some languages, last (family) names may consist of
multiple words. For example, in French, the name
"de la Grange" is a family name, and in
German, the name "von Trapp" is a family
name. Typically, the last word is a proper name
(often a place name) and so should have its first
letter upcased, while the words before it are not
proper names (they are often prepositions and/or
definite articles) and should not be upcased. The
words "de la" in French mean "of
the" or "from the", and the word
"von" in German means "of" or
"from".
Sort the names in ascending first name
order.
The order should be case
insensitive -- that is, the sort should not differentiate
between upper and lower case characters. Print out the
resulting array of strings.
Sort the names in ascending last name
order.
The order should be case
insensitive. Print out the resulting array of
strings.
Here are some skeleton Java sources which I expect you to start from. Note
that I've already done a lot of the work for you, since the main point of this
exercise is for you to learn how to use the String class. The
structure of the program is already present; all you have to do is fill
in the gaps with your code. Look for [fill
in here] indicators, for where you have to
supply code.
You can cut and paste from the following Java sources:
package names;
/**
* Class to represent a person's name.
*/
public class Name implements Comparable
{
/**
* Constructor
*/
public Name(String first, String last)
{
m_first = first;
m_last = last;
}
/**
* Returns whether the names are to be sorted
* by last name (true) or first name (false)
*/
public boolean isSortByLast()
{
return m_sortByLast;
}
/**
* Sets whether the names are to be sorted
* by last name (true) or first name (false)
*/
public void setSortByLast(boolean b)
{
m_sortByLast = b;
}
/**
* Compare this object with another object.
* (The other object must also be an instance of Name)
* NOTE: This comparison is case insensitive; that is,
* letters are sorted regardless of case.
*/
public int compareTo(Object o)
{
Name that = (Name) o;
String comp1, comp2;
int result = 0;
if (m_sortByLast)
{
[fill in here]
}
else
{
[fill in here]
}
return result;
}
/**
* Returns a string of the form:
* <first-name> <last-name>
* where the two parts of the name are separated by a space.
*/
public String toString()
{
return m_first + " " + m_last;
}
///// Private data //////
private boolean m_sortByLast = true;
private String m_first;
private String m_last;
}
|
package names;
import java.util.Arrays;
/**
* Class to test the sorting of Names.
*/
public class NamesTest
{
/**
* Main entry point.
*/
public static void main(String[] args)
{
Name[] names = new Name[m_names.length];
// populate the array with normalized names
for (int i = 0; i < m_names.length; i++)
{
String name = m_names[i];
String first = getFirstName(name);
String last = getLastName(name);
names[i] = new Name(first, last);
}
// Sort it by last name
Arrays.sort(names);
System.out.println(" Names sorted by last name:");
for (int i = 0; i < names.length; i++)
{
System.out.println(names[i]);
}
// Sort it by first name
for (int i = 0; i < names.length; i++)
names[i].setSortByLast(false);
Arrays.sort(names);
System.out.println(" Names sorted by first name:");
for (int i = 0; i < names.length; i++)
{
System.out.println(names[i]);
}
}
/**
* Extracts the first name from the specified name,
* normalizes it, and then returns it.
*/
private static String getFirstName(String name)
{
// Get rid of any leading or trailing space
[fill in here]
// Find the first space
[fill in here]
// Extract everything before it as the first name
[fill in here]
// Initial cap the entire first name
[fill in here]
// Return the first name
}
/**
* Extracts the last name from the specified name,
* normalizes it, and then returns it.
*/
private static String getLastName(String name)
{
// Get rid of any leading or trailing space
[fill in here]
// Find the first space
[fill in here]
// Extract everything beyond it as the last name
[fill in here]
// Find out whether it has an embedded space,
// & if it does, find the last one in the name
[fill in here]
if ([fill in here]) // No space found
{
// No space found, so just Init cap the entire last name
[fill in here]
}
else
{
// Space found, so extract the first part
[fill in here]
// and lowercase it
[fill in here]
// Now extract the last part
[fill in here]
// and init cap it
[fill in here]
// Then reconstruct the name again,
// from the first and last parts
[fill in here]
}
// Return the resulting normalized last name
[fill in here]
}
/**
* Utility method to take a string (name) and set the
* first character to uppercase, and all the other
* characters to lowercase.
*/
private static String initialCap(String name)
{
[fill in here]
}
//// Private data /////
// The initial list of un-normalized names.
private static String[] m_names =
{
"fred bloggs", "MARY STUART",
"eRIC SuttoN", "Francis Bailey",
"Archimedes von trapp", "Abel GRISWOLD",
"Jeffrey Guay", "Alan Swasinski",
"Leroy de la Grange", "Don Ho"
};
}
|
Notes on the Above:
The key to understanding this is to look up the java.lang.Comparable
interface in the javadocs (It's in JDK 1.2 on up). Class Name
implements the Comparable interface, which means that it's required to
implement the method:
public int compareTo(Object o)
This method is used by the Arrays.sort(names) method (also in JDK
1.2 on up).
(Note: for any of you who aren't using JDK 1.2 or higher -- please
upgrade!)
Here's what the JDK 1.2 docs say about the lang.util.Arrays
class's sort() method (I've underlined the critical point):
sort
public static void sort(Object[] a)
Sorts the specified array of objects into ascending order, according to the
natural ordering of its elements. All elements in the array must
implement the Comparable interface. Furthermore, all elements in the
array must be mutually comparable (that is, e1.compareTo(e2) must not throw
a ClassCastException for any elements e1 and e2 in the array).
This sort is guaranteed to be stable: equal elements will not be reordered
as a result of the sort.
The sorting algorithm is a modified mergesort (in which the merge is
omitted if the highest element in the low sublist is less than the lowest
element in the high sublist). This algorithm offers guaranteed n*log(n)
performance, and can approach linear performance on nearly sorted lists.
Parameters:
a - the array to be sorted.
Throws:
ClassCastException - if the array contains elements that are not mutually
comparable (for example, strings and integers).
See Also:
Comparable
You'll note that the above refers to the Comparable interface.
Here's what the JDK 1.2 docs say about the Comparable interface's compareTo
method:
compareTo
public int compareTo(Object o)
Compares this object with the specified object for order. Returns a negative
integer, zero, or a positive integer as this object is less than, equal to,
or greater than the specified object.
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
for all x and y. (This implies that x.compareTo(y) must throw
an exception iff y.compareTo(x) throws an exception.)
The implementor must also ensure that the relation is transitive:
(x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.
Finally, the implementer must ensure that x.compareTo(y)==0
implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for
all z.
It is strongly recommended, but not strictly required that (x.compareTo(y)==0)
== (x.equals(y)). Generally speaking, any class that implements the
Comparable interface and violates this condition should clearly indicate
this fact. The recommended language is "Note: this class has a natural
ordering that is inconsistent with equals."
Parameters:
o - the Object to be compared.
Returns:
a negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.
Throws:
ClassCastException - if the specified object's type prevents it from being
compared to this Object.
|