Problem Set 2: Caesar

Evidence of a 5-point submission

  • Makes use of the isdigit function to check for a valid key using a method that will short-circuit (that is, end before checking every digit) if a non-digit is found
  • Checks for a non-negative key
  • Uses a robust and efficient method for calculating the ciphertext
    • Minimal code repeated, uses fewest values possible
    • No extraneous variables
    • (letter - base + key) % ALPHASIZE + base
    • Does not calculate % ALPHASIZE more than once
  • Uses isupper and islower functions
  • Prints the ciphertext out directly (no unnecessary variables)
  • Does not include 26 as a magic number

Evidence of a 4-point submission

  • Makes use of the isdigit function to check for a valid key using a method that will short-circuit (that is, end before checking every digit) if a non-digit is found
  • Checks for a non-negative key
  • Uses a reasonably efficient value for calculating the ciphertext (does not compute % ALPHASIZE more than once)
  • Uses isupper and islower functions
  • Prints the ciphertext out directly (no unnecessary variables)

Evidence of a 3-point submission

  • Uses a short-circuiting method to check the key
  • Calculates the shift using a reasonable and clear method (few unnecessary parentheses, few unnecessary or repeated variables, not all written on one line; may use intermediary variables to break up the length of the calculation)

Evidence of a 2-point submission

  • After error-handling in an if statement which returns 1, wraps the rest of the code in an unnecessary else statement
  • Checking for an entirely numeric key does not short-circuit
  • Calculates the shift using a confusing and/or unnecessary method

Evidence of a 1-point submission

  • After error-handling in an if statement which returns 1, wraps the rest of the code in an unnecessary else statement
  • Checking for an entirely numeric key does not short-circuit
  • Uses unnecessary variables and/or conditionals
  • Calculates the shift using a method that is very unclear

Example Implementations (Worse vs. Better)

Error Handling

Worse Implementation

The example below includes an unnecessary else statement.

if (argc != 2)
{
    printf("Usage: ./caesar key\n");
    return 1;
}
else
{
    // the rest of the program is written in this statement
    ...
}

Better Implementation

The example below error handles without unnecessary conditionals.

if (argc != 2)
{
    printf("Usage: ./caesar key\n");
    return 1;
}
...

Validate Key

Worse Implementation

Even though the example below uses the isdigit function, it will not short-circuit and therefore requires unnecessary computation.

int length = strlen(s);
int digitcount = 0;
for (int i = 0; i < length; i++)
{
    if (isdigit(s[i]))
    {
        digitcount += 1;
    }
}

if (digitcount == length)
{
    return 1;
}
else
{
    return 0;
}

Better Implementation

The example below will short circuit, and it uses the characters to represent numbers (as opposed to ASCII values).

int n = strlen(s);
for (int i = 0; i < n; i++)
{
    if (s[i] > '9' || s[i] < '0')
    {
        return 1;
    }
}

Best Implementation

The example below uses the isdigit function. Note also the use of the ! operator.

for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
    if (!isdigit(argv[1][i]))
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}

Calculate Shift

Worse Implementation

Note, the example below is from a student-defined rotate helper function. While this example does use an appropriate equation, it includes unnecessary conditionals, variables, and magic numbers.

if (isalpha(c))
{
    if (c < 91)
    {
        c = c - 65;
        char newchar = ((c + n) % 26);
        return newchar + 65;
    }
    else
    {
        c = c - 97;
        char newchar = ((c + n) % 26);
        return newchar + 97;
    }
}
else
{
    return c;
}

Better Implementation

In the example below, minimal code reused, handles uppercase, lowercase, and non-alphabetical characters uniquely. This example also does not require the use of an extra variable to store the ciphertext.

for (int i = 0, n = strlen(plaintext); i < n; i++)
{
    if (isupper(plaintext[i]))
    {
        printf("%c", ((plaintext[i] - 'A' + key) % ALPHASIZE + 'A'));
    }
    else if (islower(plaintext[i]))
    {
        printf("%c", ((plaintext[i] - 'a' + key) % ALPHASIZE + 'a'));
    }
    else
    {
        printf("%c", plaintext[i]);
    }
}