Program 3: Family Database

CS100J Fall 2000

Due in Lecture, Thursday, September 28

Overview and Goals

In this assignment, you implement an interactive database that contains information about people: their names, sex, parents, spouses, and children.  Users enter new information and make queries by typing commands.

The program will be written in an object-oriented style (using classes, objects, and methods). We provide some code, and you must complete the program by adding new code, some of which involves adapting the supplied code.

Input

The input consists of zero or more commands (other than command q) followed by command q.  The commands are:

b name

Create a new b(oy) named name.

g name

Create a new g(irl) named name.

m name1  name2  

Record the m(arriage) of name1 and name2

s name1  name2  

Create a s(on) named name2  one of whose parents is named name1 . If name1 is male, he is the father and his significant other is the mother. Conversely, if name1 is female, she is the mother and her significant other is the father. 

d name1  name2  

Create a d(aughter) named name2  one of whose parents is named name1 . See command s for mother/father determination.

? name

Display information about the person named name.

p

List information about the entire p(opulation) in the database.

q

q(uit).

 

Assume that the input is well formed, i.e.,

(1)    Commands have appropriate numbers of parameters.

(2)    No social conventions need be imposed.

[Assume that the names of all people are unique, i.e., you will never be asked to enter two people into the database who have the same name.]

Output

Information about a particular person in the database should be displayed all on one line.  The output format for a married person is:

  name:n sex:s mom: n dad: n other: n kids: k

and the output format for an unmarried person is

  name:n sex:s mom: n dad: n kids: k

where each n is a name, s is either male or female, and k is a list of 1 or more names, or the word none.

Each command is prompted by the text "> ".

Sample Session

The database starts out empty. Here is a sample session:

> b tom

> g sue

> m tom sue

> d tom sarah

> s sue joe

> p

name:tom sex:male other:sue kids: joe sarah

name:sue sex:female other:tom kids: joe sarah

name:sarah sex:female mom:sue dad:tom kids: none

name:joe sex:male mom:sue dad:tom kids: none

> q

Notice that both tom and sue have two kids, joe and sarah.

Program Structure

Your program must be implemented as two separate classes --- class Person and an application class that is a client of class Person.

class Person

Class Specification

Class Person offers its clients exactly the public methods listed below, and no others. All new fields that you add to class Person should be private.

public Person(String s, Boolean m)  Construct a Person with name s and maleness m, e.g., evaluation of expression

new Person("tom", true)

creates a male Person named "tom".  The database can store records of up to 100 people.  Each attempt to create more than 100 people is ignored and outputs the message "over limit". [Assume that no person with name s has previously been created.]

public static int numberOfPeople()  Return the number of Person objects in the database.

public static Person intToPerson(int i)  Return the ith Person to have been created in the database. Return null is there is no such Person.

public String toString()   Return the string representation of a Person in the format described above.

public static void child(Person mom, Person dad, String s, Boolean m)  Construct a Person with name s and maleness m, and record that the "mother" and "father" of the person are mom and dad respectively. [Assume that mom and dad are married, and that it is acceptable for them to be called the "mother" and "father" of the child.]

public static void marry(Person p1, Person p2)   Record the information that p1 and p2 are married. [Assume p1 and p2 are distinct people, neither is already married, and that it is acceptable for them to be married to one another.]

public String name()  Return the name of a Person.

public boolean male()  Return true if a Person is male and false otherwise.

public Person other()   Return the "significant other" of a Person, i.e., the person to whom the Person is married.

Class Implementation

A partial implementation of class Person is given below.

Do not change either the constructor Person or the methods numberOfPeople and intToPerson. (In fact, they use some Java that you are not expected to understand yet.  However, you do not need to understand the implementation; it is sufficient just to understand the specifications.)

import java.io.*;

public class Person

{

  // max # of people in database.

    private final static int maxN = 100;

 

  // folks[0..n] are people in database.

  private static Person[] folks =

    new Person[maxN];

  private static int n = 0;

 

  private String name;  // person's name.

  private boolean male; // person's maleness.

      

// Construct Person named s of maleness m. 

public Person(String s, boolean m)

  {

    name = s;

    male = m;

    if ( n >= maxN )

       System.out.println("over limit");

    else {

       folks[n] = this;

       n++;

       }

  }

 

  // # of people in database.    

  public static int numberOfPeople()

  {

     return n;

  }

      

  // i-th Person in database.

  public static Person intToPerson(int i)

  {

    if (i < 0 || i >= n) return null;

    else return folks[i];

  }

      

  // string representation of a Person.

  public String toString()

  {

    String result;

    result = "name:"+ name;

    if (male)

      result = result + " sex:male";

    else

      result = result + " sex:female";

    return result;

  }

}

Developing the Program in Parts

Although it is a good idea to think through the program thoroughly before sitting down at a computer, it is an equally good idea to enter the program into the computer a little at a time, and test each little bit thoroughly before moving on.  Careful incremental testing will save you time. Although it is tempting to enter a lot of code all at once, this is not a win because it makes it harder to track down errors since you must deal with more untested code. You are urged to enter and test your program a little at a time.  Although you are free to break the problem into whatever steps you would like, we suggest the following:

Step 1.  Create a project using the CUCS Java Application stationery.  Copy the initial implementation of class Person into a file named Person.java and include it in your project.  Let the body of the application's main be

System.out.println(new Person( "tom", true));

Compile and run the program, which should output

name:tom sex:male

See the discussion on toString below if you don't understand why this code should produce the given output.

Step 2.  Implement a static method showPeople() in your application class (not in class Person) that prints out a line for each Person object.  Change the body of your application's main to:

new Person( "tom", true);

new Person( "sue", false);

showPeople();

Compile and run the program, which should output

name:tom sex:male

name:sue sex:female

Step 3. Implement the command loop, and commands b, g, p, and q. 

You will find it useful to know these facts:

(1)    method readString() of class TokenReader reads the next word of the input, and returns it as a String.

(2)    Let s and t be two String expressions.  The boolean expression

           s.equals(t)

is true if s and t are the same sequence of letters, and is false otherwise.  In contrast, the boolean expression

s==t

is true if and only if s and t both refer to the same String object.

You should now be able to support the following sample session:

> b tom

> g sue

> p

name:tom sex:male

name:sue sex:female

> q

 

Step 4.  Implement a method name()to provide read-only access to the private name field of a Person object.

Then implement method

static Person stringToPerson(String name)

in your application class (not in class Person) that returns a reference to the Person named name.  This method must search through the database to find a person with name name.  Assume that all names are unique. Use method numberOfPeople to know how many people there are in the database, and method intToPerson(i) to obtain a reference to the ith person in the database.

Then use stringToPerson to implement command ?.

Step 5.  Implement method marry (in class Person), command m, and extend toString appropriately.

Step 6.  Implement method child (in class Person), commands s and d, and extend toString appropriately --- temporarily assuming that no one ever has more than one child.

Step 7.  Extend your code to support couples with more than one child. A simple way to do this is to let each Person have a sibling field that refers to his or her next "older" sibling, if any, or null.  The next "older" sibling of a new child is just the current "youngest" child of one of the child's parents at the time the child is created.

Method toString

Every object has a public method toString() for converting it to a String. For example, if p is a variable containing a reference to an object, then System.out.println(p); is a legal statement: Java automatically calls p.toString() to get the string representation of p to print without your mentioning toString explicitly. If there is no definition of a public method toString(), some default text is printed.

It is good practice for each class to define an appropriate version of toString() for displaying its objects. The initial version of class Person has a definition of toString() that you should extend as you change the class.

What To Hand In

·         A printout of the final version of class Person and a printout of the application class.

·         A printout of a sample session that demonstrates the correctness of your implementation.  Note that the sample session given above is far from adequate.

Optional. Please feel free to write an elaborate private version of the assignment for additional practice and your own enjoyment, but please hand in a program that does not exceed our specifications. For example, throughout the write-up, various assumptions have appeared in square brackets.  You may wish to consider relaxing one or more of those assumptions in a manner you deem appropriate.  Relaxing some assumption may lead you to detect and report usage errors, whereas relaxing other assumptions may lead you to generalize the functionality of the database. 

Programs are due at the end of lecture on the day given above.  No late assignments will be accepted. Programs will not be accepted in Carpenter on the day they are due, but you may hand in your program to a consultant in Carpenter until the close of business the day before the program is due.  You must give the program to a consultant personally. Do not just leave it on a desk or table.

Program listings must be printed. Output must be printed and be exactly as produced by the program handed in. All printouts must be separate pages, without perforated edges, and stapled together in order.  The first comment in the program must contain your (and your partner's) name, Cornell ID#, section's day & time & instructor, and the assignment number.  These cannot be written in by hand.  You (both) must sign the first page of the program.