Finishing the Password Checker
[comp1110-70] - Fabian Muehlboeck
Finishing the Password Checker
[comp1110-70]- Fabian Muehlboeck
Definition 1. The char type
[comp1110-0V] - Liam O'Connor
Definition 1. The char type
[comp1110-0V]- Liam O'Connor
The type char (characters) is for single symbols (a letter, a number, a newline, etc.). Strings are sequences of characters. In Java, we write characters with single-quotes, unlike Strings which require double-quotes. For example, the first character of the string "Hello" is 'H'. To get the nth character of a string, use the method charAt(), for example: "Hello".charAt(0) == 'H'.
Characters themselves are just numbers, where each symbol has a number according to this ASCII table (the story is more complicated for non-English characters, but this suffices for now). In particular, note that the digit character '4' and the number 4 are very different numbers, however the digits occur consecutively in the ASCII table, so we can convert digit characters to their associated number by subtracting the digit '0', that is: '4' - '0' == 4.
The module class Character includes a variety of useful functions for working with char, including Character.isLetterOrDigit() and Character.isDigit().
2. Loop invariants
[comp1110-0W] - Liam O'Connor, Fabian Muehlboeck
2. Loop invariants
[comp1110-0W]- Liam O'Connor, Fabian Muehlboeck
A loop invariant is a property that must be true of your variables at the start and end of each iteration of a loop. It typically takes the form of an equation or logical formula that relates the values of your variables together. They're not part of the programming language, but I will often write them down in a comment.
When I speak of the loop invariant for a particular loop, I'm looking for a loop invariant that describes the variables with enough detail to be useful to show that my function is correct.
When writing a loop, it is often helpful to figure out what the loop invariant is, as this will help you to convince yourself (and others) that the code you wrote is correct.
For example, the loop invariant for Example [comp1110-0U] is that pos <= pwd.length() and that every character at an odd position in pwd[0..pos-1] is uppercase. Here pwd[0..pos-1] refers to a substring of pwd, including the — it is not valid Java, but just notation for me to write a loop invariant.
This is true initially, as pos is zero and pwd[0..-1] is the empty string. Furthermore, it is true before and after each iteration, as we increase pos by 2 only after checking that pwd[pos] is uppercase.
Finally, when the loop terminates not via the early return, that means that the loop guard must be false, i.e pos >= pwd.length(). Combined with our invariant that pos <= pwd.length(), we can conclude that pos == pwd.length() when the loop finishes. This means that, when the loop finishes, the other part of our invariant 'every character at an odd position in pwd[0..pos-1] is uppercase' refers to pwd[0..pwd.length()-1] which is just pwd. Thus, we can use loop invariants to show that our function computes the result it's supposed to.
Example 3.
smileyOK
[comp1110-0X] - Liam O'Connor, Fabian Muehlboeck
Example 3. smileyOK
[comp1110-0X]- Liam O'Connor, Fabian Muehlboeck
To implement the check that the emoji "O_O" (we called this "smiley" because the original proposal was for a smiley-face, but that turned out to conflict with the uppercase constraint) is present for Example [comp1110-0O], we must once again loop through each character in the password.
However, seeing as the emoji "O_O" is three characters long, we can exit the loop as soon as we reach pwd.length() - 2, as it would be impossible to see the emoji "O_O" in a string of length less than 3. If we find the word, we immediately exit the loop and return true.
I included the important parts of the loop invariant for the above loop. We always know that "O_O" is not the parts of pwd up to the next position (because in that case, it would have had to start in the previous position, pos-1). Before the loop runs, i is zero, so there is no position less than i to start from (thereby making the invariant true trivially). For each iteration, we increase i by one only after we check that the emoji "O_O" does not start there, thus maintaining the invariant. Thus, when the loop is over without early return and i == pwd.length() - 2, we can conclude that the emoji "O_O" does not appear anywhere in the string, and therefore return false.
Warning.
- Liam O'Connor, Fabian Muehlboeck
Warning.
- Liam O'Connor, Fabian Muehlboeck
We should always be careful to test edge cases. Why is it safe to put an empty string "" as input for pwd here?