Lab 07: C functions and strings

Due 11:59pm Wednesday November 9, 2011

Introduction

The program handin33 will only submit files in the cs33/labs/07 directory. (You should run update33 first to set up the directory and create any necessary files.)

Remember: You are encouraged to work with a partner.

Each program must follow these following guidelines:


  1. Write a program (power.c) that contains this function:

    float raiseRealToPower(float base, int exponent);

    This function will raise base the power exponent. The base can be any floating point value (negative, positive, zero) and the exponent can be any integer value (negative, positive, zero).

    After you have written this function, test that the function is working by displaying a table of the powers of 0.5 between -15 and +5. Your table should be similar, but necessarily exactly the same as this:

      -15    32768.00000
      -14    16384.00000
      -13     8192.00000
      -12     4096.00000
      -11     2048.00000
      -10     1024.00000
       -9      512.00000
       -8      256.00000
       -7      128.00000
       -6       64.00000
       -5       32.00000
       -4       16.00000
       -3        8.00000
       -2        4.00000
       -1        2.00000
        0        1.00000
        1        0.50000
        2        0.25000
        3        0.12500
        4        0.06250
        5        0.03125
    

  2. Write a program (called crypto.c) which implements several functions to allow for encrypting and decrypting text using a method that is just slightly better than a Caesar Cipher. The idea is that a shift value (an integer) and an initial key (a word or phrase, composed only of letters and spaces) is chosen to construct a key which will be used to encrypt a message. First, the initial key is manipulated to remove all duplicate letters and spaces to get a partial key. Next, we form the full key by appending any remaining letters in the alphabet that were not in the partial key to the end of the partial key in alphabetical order. Finally, we rotate the key to the left by shift value.

    For example, suppose the initial key is cs is fantastic and the shift value is 8.

    In the first step, we remove all duplicate letters and all spaces to get the partial key: csifant.

    Next, we append all the remaining letters in the alphabet, in order, to the end of the partial key to form the full key:
    csifantbdeghjklmopqruvwxyz

    Finally, we rotate the key to the left by the shift value. Rotating a string is like rotating bits: each time we rotate the string to the left, we move the left-most character to the end of the string. Since our shift value is 8, our final key becomes:
    deghjklmopqruvwxyzcsifantb

    To encrypt a string using this key, picture the full alphabet written above the rotated key:

    a b c d e f g h i j k l m n o p q r s t u v w x y z
    d e g h j k l m o p q r u v w x y z c s i f a n t b
    

    To encrypt, each letter of the message is first located in the top row (the alphabet, in order) and replaced by the letter in the bottom row (our rotated key). To decrypt, do the reverse.

    I have provided you with part of main to help with reading in strings, along with comments to help you understand what those lines do.

    Your task is to write 3 functions and a main program that tests the functions. The prototypes for your functions should be:


    Boolean makeKey(char key[], int shiftValue);
    void encrypt(char data[], char key[]);
    void decrypt(char data[], char key[]);

    The type void written before the function indicates that the function does not return a value.

    The function makeKey takes a string key as its first argument, which is the initial key from which to construct a rotated key, and an integer shiftValue as its second argument, which is the amount to rotate the key. Following the algorithm above, the function will remove duplicates, extend the string to a full key, then rotate it using the shift value. It returns FALSE if it is passed an empty string. Otherwise it returns TRUE. Use #define to define TRUE as 1 and FALSE as 0; use typedef to define the Boolean type (see cs33/class/11-03/leapyear.c).

    The function encrypt takes two arguments. The second argument, key, is a rotated key as prepared by makeKey. The first is a string (length less than or equal to 80 characters) to be encrypted. Nonalphabetic characters of data are not changed. The case (upper vs lower) of alphabetic characters should be preserved.

    The function decrypt reconstructs an original message from an encrypted string passed to it in data using the rotated key passed to it as a parameter. Again, the case of alphabetic characters should be preserved.

    makeKey is much harder to write than encrypt and decrypt. Start with the easier functions and test them using one (or both) of my keys shown below. Once you can successfully encrypt and decrypt, then go back and complete makeKey.

    You would not ordinarily show the full key or show the plain text when encrypting, but I do so here for illustrative purposes and your program should, too. Underlined words were entered from the keyboard while the prgoram was running.

    Enter the initial key: cs is fantastic
    Enter a shift value: 8
    Rotated key is: deghjklmopqruvwxyzcsifantb 
       Alphabet is: abcdefghijklmnopqrstuvwxyz
    
    Enter text to encrypt.  Stop encrypting with an empty line.
    
    To encryption and beyond!
    Sw jvgztxsowv dvh ejtwvh!
    
    CS is fantastic
    GC oc kdvsdcsog
    
    Enter text to decrypt.  Stop decrypting with an empty line.
    
    Sw jvgztxsowv dvh ejtwvh!
    To encryption and beyond!
    
    GC oc kdvsdcsog
    CS is fantastic
    
    
    Here's another run with another key you can try:
    Enter the initial key: The quick brown fox jumps over the lazy dog
    Enter a shift value: 13
    Rotated key is: fxjmpsvlazydgthequickbrown 
       Alphabet is: abcdefghijklmnopqrstuvwxyz
    
    Enter text to encrypt.  Stop encrypting with an empty line.
    
    November 3, 2011
    Thbpgxpu 3, 2011
    
    Enter text to decrypt.  Stop decrypting with an empty line.
    
    F ipjupc gpiifvp
    A secret message
    

    You may want to use some of the following C functions. My solution does not include them all, but I list them here for your reference. Be sure to use the man pages to figure out what header files you might need to include (e.g. string.h, etc):
    printf
    fgets
    strlen
    toupper
    tolower
    isupper
    islower
    strchr

    You can also type man string.h (or any other .h file provided by C, e.g. man ctype.h) to find out a list of functions provided by the .h file.

    HINT: The char type is really a one-byte integer which you are interpreting as an ASCII character. Therefore, if you set a char variable to have the value 'a', you're really setting it to 97 (hexademical 0x61). Therefore, if you then add 1 to that char, it's value is now 98, which you will interpret as the ASCII character 'b'.