Title image Project #1

Project 1: An Introduction to C (due Friday Feb 16 at midnight)

Let's start writing the code to support a set of mathematical functions. Some of them will be used in future fish-schooling simulation code. We will then write code to practice using input/output functionality in C. I have written these instructions as if you have nothing set up or running on NSCC.
  1. Get ready to code!
    1. Log onto nscc (the head node of the cluster)
          ssh -Y nscc.colby.edu
    2. Start XEmacs (xemacs &)
    3. Download the tarball of Project 1 code using cURL

      curl -O http://cs.colby.edu/courses/S18/cs336/projects/proj01/proj01.tar

    4. Expand the proj01 code: tar -xf proj01.tar
    5. Open the files in XEmacs and browse through them. Notice the prototypes in the header file, the various definitions in my_math.c, and the structure of the test functions in test_my_math.c.
    6. Log onto "your" node of nscc (ssh n3) so you are ready to compile and link. Navigate to the proj01 directory.
    7. Compile and run the test program:
          make test_my_math
  2. Build a set of mathematical and statistical functions that you can use in later projects. This will involve adding a set of functions to my_math.c. They will begin with scalars and then transition to arrays. I strongly recommending testing as you go! To do so, add code to test_my_math.c to implement a test function for each function in my_math.c, making sure the test function uses a well-chosen set of inputs that will represent the range of inputs the function should work for.

    For each of the following functions, put the function prototype in my_math.h, implement the function in my_math.c, and add an appropriate test function to test_my_math.c. Then compile and run test_my_math to verify that the output is correct.

    • Add a function distance to my_math (i.e. put the prototype in the .h file and the definition in the .c file) and an appropriate test function in test_my_math.c. The function prototype should be:
      // return the Euclidean distance from (x1,y1) to (x2,y2)
      float distance(float x1, float y1, float x2, float y2);
    • Write functions that determine whether an int is odd or even. The function prototypes should be
      // Return 1 if n is odd. Return 0 if n is not odd.
      int isOdd( int n );
      // return 1 if n is even. Return 0 if n is not even.
      int isEven( int n );

      Note: To get used to using ints instead of booleans in control statements, write your test code that uses if-statements to print whether or not a number is odd/even.

    • Add a countNans function:
          // return the number of Nans in the array.
          int countNans(float *array, int N);
    • Add a max function:
          // Return the maxium value in the array (of length N)
          float max(float *array, int N);
    • Add a sum function:
          // Return the sum of the N floats in the array.
          float sum(float *array, int N);
    • Add a mean function:
          // Return the mean value of N floats in the array.
          float mean(float *array, int N);
    • Add a std function:
          // Return the standard deviation of N floats in the array.
          // Note: This uses the Bessel correction.
          float std(float *array, int N);
    • Add a swapArraysfunction. This function is meant to swap to arrays of floats, i.e. to float * values. Recall that we need to be sent the address of the value we are swapping, so the type we need to pass in is float **. The function prototype should be:
          // swap the pointers a and b
          void swapArrays(float **a, float **b);

    To test this funciton, I suggest you add at least createAscendingArray and createDescendingArray. They create arrays and fill them with data. Use these functions to make your test-writing simpler.

    Here is the code for createAscendingArray.

    float *createAscendingArray(int N) {
      float *ret = malloc(sizeof(float)*N);
      int i;
      for (i=0; i<N; i++)
        ret[i] = (float)i;
      return ret;
  3. Demonstrate your understanding of memory.

    Let's spend a short amount of time making sure we understand the memory model of C. Here is your opportunity to play around and to get credit for it. Let's write additional functions in test_my_math.c that are intended to break the program.

    1. Draw the memory before and after two float arrays are swapped. As in class, assume the variables are stored on the stack and the contents are stored on the heap. Assume that before the swap, array a contains 1,2,3 and array b contains 4,5,6.
    2. There is a fantastic tool called Valgrind that can help identify memory usags errors. It is installed on NSCC, so you can use it to run your test program and then get a report about any memory leaks. Type the following command.
      valgrind ./test_my_math

      If your output includes the phrase All heap blocks were freed -- no leaks are possible then you can pat yourself on the back. If not, use the information in the message to detect and fix any errors.

      For more information about how to use the valgrind program, see their Quick Start Guide. Or use the man page (type man valgrind on the command line and press "q" when you decide to stop reading the copious amount of information they have.

    3. Write a function that "tests" one of your math functions, but which gives the wrong value for the length N. What goes wrong? What can you infer from the memory?
  4. Practice basic input operations.

    Create a new file practice_io.c. Your goal will be to take in a command line argument that determines how many times you print "Hello, World!" to the terminal.

    1. Include stdlib.h and stdio.h
    2. Write a main program that takes in command line arguments:
          int main(int argc, char* argv[]) {
    3. If there aren't enough command line arguments (at least 2 -- one for the filename, one for the first argument), then write a usage statement and return.
    4. If there are, then use atoi to convert the first argument (argv[0]) from a string to an integer. Store it in a variable (e.g. numHellos
    5. Print Hello, World! to the terminal numHellos times, making sure each greeting is on its own line (i.e. don't forget \n).
    6. Test your program by typing make practice_io, fixing any bugs, then running it. .e.g.
          ./practice_io 2 
      should yield this output
          Hello, World!
          Hello, World!

Suggested Extensions

Writeup and Handin

To hand in your project, you will gather all of the necessary files into a proj01 directory.

  1. In the CS world, it is standard practice to include a file named README.txt that accompanies code that programmers are sharing with others. It should be well-organized in a way that readers can easily know the usage and the outputs of every C file. We will be following that practice in CS336. Create a text file named README.txt that contains a brief description of each code file in the directory as well as instructions for how to make and run the main programs. Here is the example README file from CS333 last semester. You do not need to draw the directory structure, but you should list all the code files in the directory and put a short description (3-10 words) next to each filename.
  2. Create a second file for your project report. Get into the habit of using a file format that will allow you to include images (and possibly tables). For future projects, you will need to include graphs in your reports. This week, it should be relatively short and it should be formatted like a CS15X, CS231, CS251 wiki page is (a short summary, a short description of the tasks along with answers to any questions asked in the task instructions, a list of any extensions you completed, and a list of sources you used and people you collaborated with). This week, the only required image is of your drawing of memory. Also, this week, please me how much time you spent on this project outside of class.
  3. You should hand in all code necessary to run your solutions. Place all necessary .h, .c, and Makefile files in the proj01 directory. Stephanie will probably want to compile and run the code. It should be possible to do so without looking for any more files.

Zip (or tar) up the directory and put it in your Private folder on Courses/CS336.