Assignment 08

Task

Practice manipulating strings in the context of creating a new computer system user account.

Concepts: Invoking methods, parameters, return values, String methods, Math.random()
Textbook: 3.2, 3.5

Steps

Ask the user to enter their full name, which they then enter all at once at a single prompt. Their name must contain at least two words (that is, one internal space), but may contain more. (Don't let tricky users get by you by starting or ending their name with a space. Consider using the trim() method to prevent this.)

Print out the user's first name and their last name.

Then print out a username for the user. The username should be comprised of the first letter of their first name, and then up to 7 letters of their last name. (That is, a username cannot be longer than 8 characters, though it may be shorter.) The username should be all lowercase.

Then print out an initial password. This should be consist of a random digit, the user's first name uppercased, and two more random digits.

Each of the four outputs--first name, last name, username, and password--should be on their own line, clearly labeled. Labels should end in a ":" or "=", though spaces before or after this character are allowed.


Extra credit: A real user account creator would need to prevent names from containing tabs, punctuation, and other special characters. Since there is no easy String method to check for this sort of thing, you would need to use a loop to check that each character is acceptable. Since we have not covered loops yet, this is not required.

However, for those interested in attempting this for extra credit: your program should report an error if the name contains anything other than letters or spaces. (Hint: see the Character class in the API, particularly the isLetter method.)

Sample Output

D:\TA\grading\A08>java ZtomaszeA08
For a new account, enter your full name: Superman
Sorry, but your full name must include at least two words.

D:\TA\grading\A08>java ZtomaszeA08
For a new account, enter your full name: Clark Kent
First name: Clark
Last name: Kent
Username: ckent
Password: 8CLARK15

D:\TA\grading\A08>java ZtomaszeA08
For a new account, enter your full name: Zach M Tomaszewski

First name: Zach
Last name: Tomaszewski
Username: ztomasze
Password: 3ZACH30

D:\TA\grading\A08>java ZtomaszeA08
For a new account, enter your full name: p t barnum
First name: p
Last name: barnum
Username: pbarnum
Password: 1P66

D:\TA\grading\A08>java ZtomaszeA08
For a new account, enter your full name: Illegal. Chars@
Sorry, but your full name must contain only letters and spaces.

The last execution is an example of the extra credit checking for illegal characters.

What to Submit

Upload your UsernameA08.java file to Tamarin.

Grading [6 points]

1 - Compiles
Your program compiles successfully (no errors)
0.5 - Output formatting
Print first name, last name, username, and password one per line, each labelled appropriately. Labels end in a = or : character.
0.5 - Detects errors
Reports an error if the given full name is not valid (such as contains less than 2 words).
1.5 - First and last name
Correctly displays the first and last name; not thrown off by extra words, initial spaces, or trailing spaces.
1.5 - Username
Composed of first letter of the first name, then up to seven letters of the lastname, all lowercased.
1 - Password
Always formed by a random digit, the first name uppercased, and then 2 more random digits.
+1 - Prevents invalid characters
Your program does not accept names containing any characters other than letters and spaces.

FAQs

Some of these String methods listed in the API are really confusing!
Indeed, some of them use other classes (such as CharSequence) and complicated features (such as regular expressions) that we won't even cover in this class. But you don't need to use all the methods. You only need to learn the methods we discussed in lab: equals, equalsIgnoreCase, length, charAt, indexOf, lastIndexOf, substring, trim, toUpperCase, toLowercase. And you won't even need all of those to complete this particular assignment. (If you do find some other String methods you'd like to use that aren't in this list, though, feel free to do so.)
Warning: Don't use String's isEmpty() method though.
Tamarin is currently running Java 1.5; most of you are probably running Java 1.6. (If you want to check your version, type java -version on the command line.) There is one String method that some students find--isEmpty()--that was added in Java 1.6. If you use this method, your code will probably compile on your machine, but it won't compile when you upload it to Tamarin.

Therefore, I'm asking that you don't use this method in your code. Two alternatives to str.isEmpty() are str.length() == 0 and str.equals("")

How do I get the first and last names?
Since you don't know how many names the user will enter, you can't use next(). (Well, you could if you used a loop, but this is actually more complicated and doesn't give you practice with String methods.) Instead, use nextLine() to read in the full name. Trim the full name with trim() to remove any spaces at the beginning or end of the string.

Now, the first name ends at the first space. The last name starts one character after the last space. If you have only two words in the name, the first space and the last space will actually be the same character, but not so if you have more than two words.

So, find the position of the first space using indexOf, and then take a substring from the beginning of the string to that position. This substring is the first name. (If there is no space to be found, it means the user entered only one word, or even none at all. In this case, indexOf will return -1 as the position of the first space.)

Then find the position of the last space and take a substring from one more than this position to the end of the string. This substring is the last name.

To do all this, you'll need to use these String methods: trim, indexOf, lastIndexOf, substring, and (possibly) length.
How do I use a try/catch for InputMismatchException to print an error when there is only one name given?
You can't use a try/catch for this, since nextLine() never throws an exception. You get an InputMismatchException when you ask for a number but get a String. When you ask for a String, any sequence of characters will be considered valid by nextLine().

So, to detect one name, you need to use an if statement. The best place for this is right after you find the index of the first (or last, if you do that first) space. Remember indexOf will return -1 if it can't find what you're looking for. So, if firstSpace == -1, then there was no space, and thus not two words (assuming you trimmed the string before looking for a space, of course).

(Note that you could catch a StringIndexOutOfBoundsException here instead. However, this is bad practice. It's better to use an if statement as I just described to avoid generating the SIOOBE in the first place. Catching a SIOOBE when there is no space will also hide other potential indexing errors, such as when you get to forming the username, and thus make it harder to debug your own code.)

My program prints out my error messages but then keeps going.
If the user did not enter a name of at least two words, you need to print an error message. You need to use an if/else or some similar structure so that either your program prints the error message or it keeps going. Here's just one way you could do this:
  //read in name
  name = name.trim();
  //if (name contains no spaces) then:
    //print error message: user entered nothing or only one name
  //else:
    //the name is valid, so start processing it
    //the rest of your code goes here....
  }
My program crashes if the last name is too short.
Then you need to check the length of the last name before you try manipulating it. Use the length method. If it's 7 or fewer characters long, you can just add the whole last name to the username; otherwise (else), you'll need to take a substring of only the first 7 characters.
I'm having difficulty with the 2 digit random number.
If you just create a random int between 0 and 99 (inclusive), then about 1/10 the time it won't be a 2 digit number. You can either create a number between 10 and 99 (a little less of a random range, but it is acceptable), or else generate each (0 - 9) digit separately, appending each as you go.