Advanced C Programming

Autumn 2016 :: ECE 264 :: Purdue University

This is for Fall 2016 (8 years ago)
Due 9/29

Malloc + structs

Goals

This assignment has the following objectives:
  1. Learn how use structures for data encapsulation
  2. Practice programming with dynamic memory (i.e., malloc)
  3. Practice debugging memory errors
  4. Learn how use structures for data encapsulation
  5. Practice putting a semicolon (";") after your struct statement :)
Note: The next few assignments will be based on this one.

Overview

Scenario: Your team will soon choose a leader. You will be given a list of names and a separate list of each person's "favorite" person on the team. You must create software that can calculate the new leader.

Warm-up exercises

This assignment includes a warm-up exercise to help you get ready. This accounts for 10% of your score for HW07. Scoring will be relatively light, but the usual base requirements apply.

To get the starter files, type this: 264get hw07

For the warm-up, you will create a struct type for a name (first and last). Your type will be called struct Name and it will have two members: first (a char*) and last (a char*). Next, you will create two swap functions: swap_first_last(…) swaps the first and last name in a given struct Name instance. swap_names(…) swaps two struct Name instances using pass-by-address.

In warmup.c, you must replace every /* TODO */ comment with code. The only output is as shown. Fill in the rest of the code to make it work.

Doing the assignment

Here is the overview of what you are creating. (Some specifics have been moved to Requirements.)

Note: Type the declarations into your file manually. Do not copy-paste. (You learn more from typing code manually.)

When you are finished, it will look like this.

initial state of project files
Reminder: Your test cases must be your own. Do not copy these or any other test cases.

Requirements

  1. Your submission must contain each of the following files, as specified:
    file contents
    team.c functions
    create team(int population, char✶ names[], int✶ favorites)
    return type: struct Team
    Return a struct Team object.
    population is the number of people in the team, and is always ≥1.
    names is an array of size population containing the names of the team members. Each name is at least one character long, plus the null terminator (i.e., not "").
    favorites is an array of size population containing the indices of each person's favorite, such that names[i] is favorites[i].
    • The struct Person objects this creates, and the name attribute of each will need to be on the heap. (See the Q&A.)
    • A person may be their own favorite.
    • Calling create_team(…) will result in exactly population + 1 calls to malloc(…).
    • The struct Team object this returns will be on the stack, even though the struct Person objects, and the name attributes they refer to, are on the heap.
    free team(struct Team✶ team)
    return type: void
    Free all heap memory referred to by the team, directly or indirectly, including the struct Person objects inside, and the name attribute of each.
    pick leader(struct Team✶ team)
    return type: struct Person✶
    Return the address of the most popular person, i.e., the struct Person that is the favorite of the greatest number of people in the team.
    • If there is a tie, pick the one with the smallest index.
    team.h struct type definitions
    struct Person
    This should have at least two fields: name (a string) and favorite (address of a struct Person object). You may have other fields if you wish, but other fields are not required or necessary.
    struct Team
    This should have at least two fields: people (array of struct Person objects) and population (int, number of people on the team). You may have other fields if you wish, but other fields are not required or necessary.
    forward declarations
    forward declarations of all functions in your team.c
    You will need at least three (one for each of the functions defined in your team.c, but you may have others if you like. (See Q1.)
    test_team.c functions
    main(int argc, char✶ argv[])
    return type: int
    Test all of the code in your team.c. Reminder: Do not copy test cases from the screenshot or anywhere else.
    warmup.c type definitions
    struct Name
    functions
    print name(struct Name name)
    return type: void
    We provide this. Do not modify it.
    main(int argc, char✶ argv[])
    return type: int
    We provide this. Do not modify it, except where it says /* TODO */.
    swap first last(…)
    return type: void
    swap names(…)
    return type: void
  2. Only the following external header files, functions, and symbols are allowed in your team.c.
    header functions/symbols allowed in…
    stdbool.h bool, true, false team.c, test_team.c, warmup.c
    stdio.h fputc, fputs, stdout test_team.c, warmup.c
    printf test_team.c
    stdlib.h malloc, free, NULL team.c, test_team.c, warmup.c
    EXIT_SUCCESS, EXIT_FAILURE, free test_team.c, warmup.c
    assert.h assert team.c, test_team.c, warmup.c
    All others are prohibited unless approved by the instructor. Feel free to ask if there is something you would like to use.
  3. Submissions must meet the code quality standards and the policies on homework and academic integrity.

How much work is this?

This assignment is difficult. It won't require a lot of code, but expect to spend some time debugging and understanding the concepts.

Q&A

  1. What is a forward declaration?
    A forward declaration is just the top line of a function definition, which specifies its signature. Examples can be found in your textbook on page 155 (Figure 4-5) and page 165 (Figure 4-12).

    For example, in HW04, if you wanted to put everying in one file, you could do so like this. The forward declarations let the compiler know what is coming, even before it has read the full function definition.
    void mintf(int n, int radix, char* prefix);    // <--- forward declaration
    void print_integer(const char* format, ...);   // <--- (aka "function declaration")
    
    // Test code
    int main(int argc, char* argv[]) {
      // […]
    }
    
    void print_integer(const char* format, ...) {  // <--- function definition
      // […]
    }
    
    void mintf(int n, int radix, char* prefix) {   // <--- function definition
      // […]
    }
    
  2. Why must the struct Person objects be on the heap?
    You don't know in advance (i.e., at compile time) how many you will need.
  3. Why must the name field of each struct Person be on the heap?
    The string that was passed to create_team(…) might not exist later.
  4. What is the form of the team returned by create_team(…)?
    The structure created by the example in the screenshot will look like this:

Updates

9/25: Corrected filename test_team.c (not teamtest.c).

9/26: Clarified where person name should reside, and how population==0 should be handled; added diagram; corrected return type of print_name(…) in warmup.c; moved most specification details to the Requirements table and elaborated on some items.

9/28: NULL and assert(…) are allowed.