COMP 2401/2001 (W13) [NEW DUE DATE]

All of the coding questions are given here (Problems 1-3). Two more questions will appear but they will not be coding questions.

Assignment 3 - Due Friday, March 8st at 6pm, Early submission Friday, March 1st at 6pm, Early early submission Wednesday, February 27th at 6pm

Submit a single file UserID.assignment3.tar to cuLearn with all the files specified below.

Your grade for this assignment will be based on correctness and style.


  1. Create text a file with the name "myemail" that has a single line in it, consisting of your email address. Something like "firstname_lastname@carleton.ca" (or your hotmail or gmail or hellokittymail or ...). Do not include the quotes in the name of the file or in your email address. This must be a plain text file (with no extension).

    The results of the correctness tests will be emailed to the email address that you put in this file.


For each of the programming problems below, your main() function will simply include another file (which has the code you use to drive your program or the code that we use to test your types and functions). For example, for Problem X, in your submitted file problemX.c, your main function must look like
int main(int argc, char* argv[]){ 
   #include "mainX"
}
The code you use to drive your program (or to test your program) be in a file called mainX, for Problem X. You may (or may not) be required to also submit this mainX file.

You must include a Makefile in your submitted tar file. Follow the same names that was have used in assignments 1 and 2 (i.e., program1.c should generate the executable p1). We will be using your makefile to compile your code. Make sure you use the makefile and make sure it works.


  1. You will implement a stack data structure that holds instances of a person data type. Define the data types in your program as follows:

    // datatype for the stack
    typedef XYZ PersonStack;
    
    // datatype for Person
    typedef struct Person_type Person;
    struct Person_type{
       char* name;
       int   age;
    };
    
    where XYZ is to be determined by you.

    You must have the following functions implemented for your stack:

    PersonStack createStack()
      // Creates an instance of an empty stack
    
    
    bool isEmpty(const PersonStack* stack)
      // Returns true if the stack is empty, false otherwise.
      // Include  to get the bool/true/false macros
      // to make working booleans more friendly
    
    
    unsigned short stackSize(const PersonStack* stack)
      // Returns 0 if the size of the stack is zero
      // Returns 0 if the size of the stack is larger
      //           than can be stored in an unsigned short
      // Returns the size of the stack otherwise
    
    
    void pushPerson(PersonStack* stack, Person p)
     // Adds Person p to the stack passed into the function
    
    
    void push(PersonStack* stack, char* name, int age)
     // adds a Person, defined by name and age, 
     // to the stack passed into the function
    
    
    Person pop(PersonStack* stack)
     // Removes and returns the Person currently on the top
     // of the stack passed into the function
     // Precondition: stack must have size >= 1
    
    void print(const PersonStack* stack)
      // Prints the contents of the stack to the screen
      // in order from the top to the bottom of the stack
      // The output for each person should be a single line
      // "name : age \n"
      // (name followed by colon followed by age followed by newline)
    
    
    void reverse(PersonStack* stack)
      // reverses the order of the stack
    
    
    void kill(PersonStack* stack)
      // remove all Persons from the given stack
      // (and free all memory)
    
    
    Your stack must make use of dynamic memory allocation for your stack. You can use a linked list or you can use a dynamic array for your implementation. In either case, all data (the persons) in your stack must be stored in the heap. You must use malloc (or calloc or realloc) in your implementation. You must free all your memory. You will lose marks if there are memory leaks in your code.

    Add the file problem1.c to your tar file. Your file should have all the datatype definitions and function definitions. Do not submit your main1 file. We will test your datatype and functions with our own.

    Note: be sure to test your code well!

    Make sure you don't have any memory leaks. Use valgrind when testing your code. (We will be testing with valgrind.)


  2. Implement the following two functions:

    void reverse(char* line, int start, int end)
    // Reverses the substring in line starting from
    // index start up to but not including index end
    // If end < start do nothing
    // If start or end extends beyond the size of the 
    // string, reverse all of the string characters that 
    // are in this range.
    
    
    typedef enum {Ascending, Descending} Order;
    
    void sort(char* line, int start, int end, Order order)
    // sorts the characters in the substring of line
    // starting from index start up to but not including
    // index end.  The characters are sorted by ASCII value
    // in the direction given by order. 
    // If end < start do nothing
    // If start or end extends beyond the size of the 
    // string, sort all of the string characters that 
    // are in this range.
    
    The input line in each function will be a string. (Not just an array of chars.)

    Use the enumeration given. In your main2 file, include code to thoroughly test your two functions. The code should display (to the console) appropriate information about the tests and a summary of the results. Even if your functions do not work properly, you can still receive marks for your testing code (as long as your program compiles and runs).

    Make sure you don't have any memory leaks. Use valgrind when testing your code. (We will be testing with valgrind.)

    Add the file problem2.c and main2 to your tar file.


  3. Use the following enumeration and implement the following functions:

    
    typedef enum {Ascending, Descending} Order;
    
    void sort(char* line[], int length, int start, int end, Order order)
    // sorts the strings (words) lexicographically in line 
    // starting from index start up to but not including index end.  
    // Use the strcmp function from  to compare 
    // two strings.
    // The input length is the size of the array line.
    // Sort the strings in the direction given by order.
    // If end < start do nothing
    // If start or end extends beyond the size of the 
    // string, sort all of the strings that 
    // are in this range.
    
    
    void sortsort(char* line[], int length, int start, int end, Order order)
    // Essentially the same function as sort (above) except
    // that the strings being sorted (the strings with index 
    // in the range [start, end-1]) are slightly modified.
    // If the strings are being sorted in ascending order,
    // the "smallest" string (in the range being sorted) has
    // a single "+" added to the end of the string.  The second
    // "smallest" has "++" added to the end, etc.  The "largest"
    // string has (end-start) "+"'s added.
    // If the strings are being sorted in descending order, 
    // the "largest" has a "-" added to the end of it, the "smallest"
    // has end-start "-"'s added.
    
    
    Use the enumeration given. In your main3 file, include code to test your sort function only. (Do not include the code to test sortsort.) The code should display (to the console) appropriate information about the tests and a summary of the results. Again, even if your function does not work properly, you can still receive marks for your testing code (as long as your program compiles and runs).

    Typo in original example. Input is changed and correct now.

    For example, if line is the array {"cat", "dog", "eel", "boy", "dot", "abc"} , then after calling sort(line,1,5,Descending), the array is {"cat", "eel", "dot", "dog", "boy", "abc"}.

    Make sure you don't have any memory leaks. Use valgrind when testing your code. (We will be testing with valgrind.)

    Add the file problem3.c and main3 to your tar file.


  1. A quick note about the -> operator. When dealing with pointers, structs, and structure fields, the precedence of * (dereference) is lower than field access (dot operator).

    If we have a pointer to a structure, call it ptr, that has a field x, in order to access that field, we would have to explicitly dereference ptr first and then get the field value like

    (*ptr).x ;
    
    This is annoying, and the -> operator does this dereference and field access in one step for us. So, the equivalent would be
    ptr->x ;
    
    Answer the questions given in this pdf. For this problem you should physically hand in a hardcopy of your solution. (Whether it is hand written or typeset.)


Last modified : February 15, 2013