6. Arrays, Structs, Pointers

6.1. Purpose

This activity introduces “more advanced” features of the C language; useful in building programs or implementing TI DriverLib functions.

6.2. Hardware and Tools

  • [Optional] MSP-EXP432P401R Launchpad Development Board or TI-RSLK Robotic Car

6.3. Preparation

Review the website descriptions for Arrays, Structs, and Pointers.

6.4. Instructions

The following steps will guide you through implementing and using arrays and structs. Pointers are also used, but to a much more limited extent.

Let’s first take a look at arrays.

6.4.1. Arrays

This task will build a multiplication table from the numbers contained in two arrays.

  1. First, download and import the course template project: TemplateProject.zip. You should rename the imported project to something like “Activity-Arrays.”

    • Alternatively: use the default template for an online C-Compiler. You may need to add #include<stdint.h> to the top of the default template for it to recognize the [u]intN_t types.

  2. Let’s create an array full of numbers. Copy and paste the below line such that the array variable, array1, will be a global variable.

    uint32_t array1[] = {1,2,3,4,5,6,7,8,9,10};
    

    This code will create an array of length 10 with the shown values.

  3. Let’s ensure that the array is created appropriately. Add the below for loop to print out each element of the array within the main function, just prior to the while(1). Compile and run the code to test (ensure the terminal is connected).

    uint8_t i;         // Loop count variable
    for(i=0;i<10;i++){ // Loop through the indices of the array
        printf("Element %u is:\t%u\r\n",i,array1[i]);
    }
    
  4. Now we need a second array. Create an empty second array of length 10 and then fill the array with random values between 0 and 20. You can use the for loop in the previous step to accomplish this. You should use the function rand() to generate the random values.

  5. Modify the printf statement to print out the values stored into the second array after they are generated. Compile and run the code to test.

  6. Now build out the multiplication table formed by our two arrays. We’ll need a 2D array to store the values into. Create an empty 2D array that is 10x10 (same size as each array). A 2D array may be created by using the format <type> var[m][n], where m and n are the dimension sizes.

  7. The easiest way to do fill the table is with two nested for loops, something like:

    uint8_t i,j;        // Two loop variables
    for(i=0;i<10;i++){  // Outer loop
        for(j=0;j<10;j++){  // Inner loop
            // In here we can use i and j to loop through elements,
            // where i and j will be the row/column index of the 2d matrix
        }
    }
    
  8. Add code to print out the multiplication table. You may remove the previous printf commands used. As this print is fairly complicated, the code to do so is provided below, with some portions missing, marked with ???.

    // This portion prints one of the input arrays column header (horizontal)
    printf("\n\n\t");   // Move down a couple lines and skip the first "column"
    for(i=0;i<10;i++){
        printf("\t%u",???); // Print each element in the array, one each column (tab)
    }
    printf("\r\n"); // move to the next line to print the table
    
    // This portion prints the other input array as the row headers (vertical)
    // and the multiplication table (2D array)
    for(i=0;i<10;i++){
        printf("\t%u",???); // Print the i-th element of the input array
        for(j=0;j<10;j++){
            printf("\t%u",???); // print all the elements of the i-th row for the table
        }
        printf("\r\n"); // move to next line
    }
    

    If all is successful, you should see output like below; where the blue box marks a set of input array elements, the red box marks the other set of input array elements, and the green box is the calculated multiplication table 2D array. Of course, this output assumes that both input arrays have the values 1-10 instead of one being random. It must be ensured that the multiplication table matches that of the input arrays used and that the table is not flipped

    ../_images/mult_table_output.png
  9. Finally, modify the length of the randomly generated array to 15. This will require that several items (for loop conditions) be adjusted as well to ensure the code still works appropriately.

Tip

At this point, you may have noticed that the “random numbers” that are being generated to fill the array are always the same sequence and therefore not actually random. See srand for information on how to avoid this situation. It is not necessary to fix this in this program.

6.4.2. Structs

  • This task will provide an example on how to use predefined structs in programming tasks. In this case, we will use a struct to store information about the set of homework grades below:

    Homework Gradebook Statistics

    Homework

    1

    2

    3

    4

    5

    Average

    94.2

    76.7

    84.5

    92.1

    66.3

    Std. Dev.

    10.8

    12.6

    15.9

    12.6

    27.3

    Minimum

    55

    40

    25

    45

    10

    Maximum

    100

    100

    100

    100

    100

    Submissions

    109

    106

    101

    99

    99

  1. First, let’s prepare another fresh template project: TemplateProject.zip. You should rename the imported project to something like “Activity-Structs”.

    • Alternatively: use the default template for an online C-Compiler.

  2. We don’t expect students to know how to create a struct in this course, just how to use them; therefore, a struct definition is given below for storing the homework information. Copy and paste this code above where function prototypes would exist.

    // This is one implementation for creating a custom struct variable type named "homework_t"
    typedef struct _homework_t {
        float average;      // The struct has a "field" for each value listed
        float stdev;        // in the "Homework Gradebook" table.
        uint8_t min;        // Note that the fields can be all different types
        uint8_t max;
        uint16_t subs;
    } homework_t;
    
  3. Now create a global variable and store the values of homework 1 from the table. The commands to store the values may be done within the main function.

    Tip

    The variable type to create the homework struct is homework_t. This should be used the exact same way that you would use uint32_t, etc.

    Tip

    Dot notation is used to assign values to each struct field; for example: struct_name.field. If CCS recognizes the type of the struct, then as you type the variable name followed by a period, CCS should pop up a list of the available fields. This features is extremely useful when using unfamiliar and/or complicated struct types.

  4. You may check if your work was correct by using the print statement below and replacing the ??? instances with the variable name you used. The Edit → Find/Replace… function may be useful in doing this.

    printf("Homework 1 Stats\r\n"
           "    Average: %.2f\r\n"
           "  Std. Dev.: %.2f\r\n"
           "    Minimum: %u\r\n"
           "    Maximum: %u\r\n"
           "Submissions: %u\r\n",
           ???.average,???.stdev,???.min,
           ???.max,???.subs);
    
  5. We could make a new homework_t variable for each homework; however, this implementation would be tedious and inflexible. Instead, it would make sense to make an array of homework_t variables, where index 0 is homework 1, index 1 is homework 2, etc. Make this array now as a global variable and populate at least two of the indices with homework stats. Make sure to leave the non-array homework_t variable created in step 3.

    Tip

    Accessing fields of an array element works the same way as if it was a single variable: array[n].field = value;.

  6. Modify the print statement such that all homework stats are printed consecutively. You’ll want to wrap the print statement in a for loop. You do not need to format the print statement to match the table format above, just print all of each homework’s stats one at a time.

6.4.3. Passing Structs as Pointers

  1. Add the following function to your struct program. This function calculates a homework average without the minimum grade included.

    // Prototype. Add above main function, below the homework_t definition.
    float remove_min_from_avg(homework_t *homework);
    
    // Declaration. Add below main function
    // This function calculates the average of a homework without the minimum grade.
    // The function will return the value of the new average.
    float remove_min_from_avg(homework_t *homework){
        float homework_sum = homework->average*homework->subs;
        homework_sum -= homework->min;
        return homework_sum/(homework->subs-1);
    }
    
  2. Using this function, calculate the modified average of homework 1 new float value. Use the single homework_t variable created in step 3, not the array created in step 5. You will need to use the & operated as discussed here: Pointers.

  3. Print out the value of the calculated average to verify it worked.

  4. Repeat the calculation for homework 2. This can be done using the homework array using the format &array[n].

6.4.4. Submit Work

Submit both final code files to the corresponding Gradescope activities. You should rename the files to an appropriate name prior to submission (e.g., arrays.c and structs.c).