Project 3: Train Station

Due: Thursday, March 31, 2016 by 9:00PM


Updated TrainStation.cpp

A new version of TrainStation.cpp is available on GL and from the links on this web page (the old version is still available: TrainStation_old.cpp). The new version updates the destructor ~TrainStation() and the function removeTrain():

Adding and Removing Cars

The addCar() and removeCar() functions should maintain the correct order of the cars and the dependencies between cars, but they do not have guarantee the validity of the train (that it has one or more locomotives and at least one coach car — this is done by the isValid() function).

Warning from Train() and TrainCar() Constructors

When compiling with -Wall you will receive a warning about the order of intialization of class variables in Train and TrainCar. You may ignore these warnings, or you may change the order of the items in the initialization list to remove the warnings.


Since this project makes extensive use of dynamic memory, it is important that you test your program for memory leaks using valgrind:

  valgrind mytest

If you have no memory leaks, you should see output like the following:

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

The important part is “in use at exit: 0 bytes 0 blocks,” which tells me all the dynamic memory was deleted before the program exited. If you see anything other than "0 bytes 0 blocks" there is probably an error in one of your destructors.


The objectives of this project are:

  1. To implement a linked-list data structure,
  2. To practice using C++ class syntax,
  3. To practice implementing member functions,
  4. To practice implementing overloaded operators, and
  5. To practice object-oriented thinking.


Linked lists are a fundamental and widely-used data structure. In this project, you will implement a linked list to store the cars of a train in their proper order. As cars are added to the train, your implementation must ensure that they are inserted at the correct position within the list; similarly, when a car is removed from a train, you must check that the remaining cars are still in their proper position, and re-position them if necessary.

For our purposes, a train consists of six different types of cars: locomotives, coach cars, business class cars, sleeping cars, snack cars, and dining cars; a train must have at least one locomotive and one coach car, but the other car types are optional. The car types, along with a value NoType, are defined as an enumeration in the file TrainCar.h:

typedef enum { Locomotive, CoachClass, BusinessClass, DiningCar, SnackCar, SleepingCar, NoType } cType; 

There are a number of rules regarding the location of each type of car within the train. The locomotives and passenger cars must be in this order:

  1. Locomotive(s)

    There may be one or more locomotives. They must be the first non-dummy nodes of the linked list.

  2. BusinessClass

    BusinessClass cars are optional, but if they are present, must be the first cars after the locomotives.

  3. CoachClass

    Every train must have at least one CoachClass car. If there are no business class cars, then they are immediately after the locomotives; otherwise, they follow the business class cars, possibly separated by a SnackCar (see below).

  4. SleepingCar

    SleepingCars, like business class cars, are optional. They are always the last cars in the train, following the coach cars and dining car.

The Snack and Dining cars have their own special placement rules:
  1. SnackCar

    A SnackCar is optional; there can be at most one.

    If the train has both business class and coach class, the SnackCar must be placed between coach and business.

    If the train has no business class, then the SnackCar must be placed in the middle of the coach class cars; if there is an odd number of coach class cars, it should be placed closer to the locomotives.

  2. DiningCar

    A train has a DiningCar if and only if it has one or more sleeping cars. The DiningCar should be placed between the coach cars and the sleeping cars.

The TrainCar class is defined in TrainCar.h and implemented in TrainCar.cpp. It is equivalent to the Node class in other linked-list examples you have seen: it has one data field (the car type) and a pointer to the next TrainCar object. The TrainCar class is nearly complete, but you do need to implement the overloaded operator<< to complete it.

The "meat" of the linked list is in the Train class defined in Train.h and implemented in Train.cpp. The Train class stores basic information a bout a train, including it's number, destination, and departure time and also has a pointer to the first (dummy) node of the linked list. It implements all the functions necessary to insert and remove cars in a Train and has an overloaded operator<< that prints a character graphic representation of the train. You are given implementations of two Train constructors, but you must implement the remainder of the class.

Finally, there is a small Time class that you must implement from scratch (no files are provided). The Time class is used to represent train departure times, to do simple arithmetic with times, and to output times in a nice format.


Your assignment is to complete the implementations of the TrainCar and Train classes and to write a Time class from scratch.

The TrainCar class is defined in TrainCar.h and implemented in TrainCar.cpp. You only need to implement the overloaded insertion operator to complete the class.

The Train class is defined in Train.h and implemented in Train.cpp. Only the constructors are provided; you must implement the remaining functions. Do not forget to implement the destructor ~Train() ~TrainCar().

The Time class must be written "from scratch." The class is used to store, compare, and output times on a 24-hour clock. The interface must be in Time.h, the implementation must be in Time.cpp, and the class must have the following features:

  1. Two integer variables: one to store hours, the other to store minutes.
  2. Default constructor sets hours and minutes to 0.
  3. Non-default constructor sets hours and minutes to specified values; must check that specified values are valid.
  4. Overloaded operator<< must print times with a colon between hours and minutes and with zero-padding of single-digit hours or minutes.
  5. Overloaded operator+ to add minutes to a time object. For example,
          Time t(13, 55);
          cout << t + 7 << endl;
    should print "14:02".
  6. Overloaded operator< to compare two Time objects. For example,
          Time t0(13, 55);
          Time t1(14, 00);
          bool b = (t0 < t1);       // b gets value true
          bool c = ((t0 + 7) < t1); // c gets value false

Your classes must work with the provided TrainStation class:

This class creates several "tracks," assigns trains to the tracks, prints scheduled departures, etc. In addition, one test file is provided, station_test.cpp, which exercises all the class in the projects (TrainStation, Train, TrainCar, and Time). As with previous projects, you should do lots of additional testing — station_test.cpp is just one example of a test program.

Implementation Issues

Here are some issues to consider and pitfalls to avoid:

Submitting your program

You should submit these files to the proj3 subdirectory:

You do not need to submit TrainCar.h, TrainStation.h, TrainStation.cpp, or station_test.cpp because these files should not have changed.

If you followed the directions in setting up shared directories, then you can copy your code to the submission directory with:

    cp Train.h Train.cpp TrainCar.cpp Time.h Time.cpp mytest.cpp ~/cs202proj/proj3/

You can check that your program compiles and runs in the proj3 directory, but please clean up any .o and executable files. Again, do not develop your code in this directory, and do not keep the only copy of your program here.

If you are submitting late, you need to copy to proj3-late1, or proj3-late2 instead of proj3. Make sure you understand the course late submission policy.