Lab 4: Doubly-Linked TTC Stations

This lab is part of Assignment 2. You are to complete the exercises here before arriving in lab on Monday/Tuesday. In lab, you and your partner will demonstrate your code to your TA, and get feedback. Your revised code is due on February 7 at noon.

Labs 3 and 4, together, form a simulation of the Bloor-Danforth TTC line. In Lab 3, we implemented the code for the trains and the passengers. In Lab 4, we will implement the code for the stations, and put everything together in a simulation.

As always, your code must comply with the CS 190 Style Specifications, and work on the ECF machines. The marking scheme for Assignment 2 is available here.

Part One: A Linked List of Stations

Download the files bloor_line.txt, station.c and test_station.c. Unlike our linked lists from Lab 3, the linked list of stations is doubly linked. You are to complete the following functions:

  1. void insert_station_after(struct station *node, struct station *new_node) -- inserts a new station new_node after node, linking node into the doubly-linked list.
  2. struct station* read_stations() -- reads the file bloor_line.txt using fscanf and converts each line into a doubly-linked list of stations, with the positions given from the file
  3. void add_passenger(struct station *curr_station) -- adds a single passenger to the station curr_station.
  4. void add_n_passengers(struct station *curr_station, int n) -- adds n many passengers to the station curr_station.
  5. int total_passengers(struct station *first) -- counts the total number of passengers in the entire linked list(i.e in all stations).
  6. double average_wait_time(struct station *first) -- returns the average wait time of all the passengers in all the stations. Note this is not the same as the average wait time at a given station, nor the average of those averages!
  7. struct station* get_station_at_pos(int position, struct station *first) -- returns the station located at position "position", NULL if a station is not found.
  8. void remove_all_stations(struct station **first) -- removes and frees the memory of all the stations in the linked list beginning with first. *first should be NULL by the end. NOTE: in addition to freeing the memory of a station, you will also have to free the memory of its list of passengers (if it exists), and its name -- for every time your program calls malloc it needs to call free.

You should compile this with gcc -Wall ttc.h passenger.c station.c test_station.c -o station or make passenger (if you're using the Makefile from lab 3).

The file test_station.c contains test cases for each method -- use them to test your code incrementally.

Part Two: Memory Management and Asserts

Last week, for lab 3, a number of methods said that you should assert various things about them. At the time, we hadn't covered the assert statement in class. Now that we have, go back to lab 3 and update those methods to use assert statements. The automarking of your lab 3 code will expect assert statements.

Another thing to do at this point is to verify all the memory your code has allocated gets freed by the end. Valgrind is a memory debugger, a tool for checking if your code contains any memory leaks. You can read more about Valgrind here and more on how to use it here.

Follow these steps on the command line:
make passenger
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --track-fds=yes ./passenger

You'll hopefully get something that ends with:

==2228== HEAP SUMMARY:
==2228== in use at exit: 0 bytes in 0 blocks
==2228== total heap usage: 9 allocs, 9 frees, 144 bytes allocated
==2228==
==2228== All heap blocks were freed -- no leaks are possible
==2228==
==2228== For counts of detected and suppressed errors, rerun with: -v
==2228== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

If Valgrind tells you that all heap blocks were freed, your remove_first_passenger and clear_passenger_list do not contain any memory leaks. If you don't get this message, go back and fix those method(s) listed by Valgrind -- you can comment/uncomment lines in test_passenger to narrow down which of those two methods have memory leaks.

Now we repeat this for trains:
make train
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --track-fds=yes ./train

If you've got a memory leak in your train code, go debug it until you're done. Once that's dealt with, it's onto stations:

make station
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --track-fds=yes ./station

Again, ensure that your stations are being properly freed. Recall that you will have to free the passenger lists and the station's name -- calling free on a station pointer will not do this for you!

It is vital that you fix any memory leaks before proceeding to Part Three. The TTC Simulation will grab a lot of memory if you run it for a long period of time; if you have any memory leaks, the simulation will crash.

Part Three: The Simulation

Download the file ttc.c. Read through ALL the code -- your TA will ask you to explain what it is doing. You have two methods to complete in it:

  1. void passengers_wait(struct station *kipling) -- this increments each passenger's waiting time by one minute, at every station.
  2. void enter_passengers(struct station *kipling) -- for each station, curr_station, this adds num_arriving_passengers many passengers to the station.

You can compile ttc.c with make ttc or gcc -Wall -O6 ttc.h passenger.c train.c station.c ttc.c -o ttc and run the file ./ttc -- use the test cases in test_cases_for_students to check your code.

Once you're done, set DEBUGGING to 0. This will run the simulation. Confirm that your output looks like something that ends with:

68: [t5235]
69: ||
70: || = (n = 128, avg = 0.6) VictioriaPark
71: ||
72: ||
73: [t5230]
74: ||
75: [t5225]
76: || = (n = 374, avg = 2.2) Warden
77: ||
78: ||
79: ||
80: ||
81: ||
82: [t5220] = (n = 69, avg = 0.0) Kennedy
---------- ANALYTICS --------
Simulated time elapsed (min): 6000
Total number of passengers: 5091
Average wait time of passengers (in min): 1.404832
Total number of trains: 18
Average distance between trains (in km): 3.764706

Also note the newly created file, data.csv that shows you the data about the train line over time. This file will be overrwitten each time you rerun ./ttc, so you might want to make some backups as you work on the report.

You'll want to play with this simulation, and the output data, for your report.

Commit your code before leaving your lab session on Monday/Tuesday.

Waiting to Talk to Your TA?

Get started on your Report!