Commentary: Records

Steven Zeil

Last modified: Jul 8, 2017
Contents:

Often we have data items that we would like to group together.

1 Structs and Classes

In C++, a record is created using a struct or class.

In other programming languages, you are most likely to do this with classes.

Now, structs and classes go well beyond the ability to represent records. They can store functions (“function members”) as well as data members. But, in this module, we are only going to focus on the idea of a record as a way of organizing data fields.

Suppose, for example, that we were writing code that needed to work with times, perhaps to allow us to set and manage alarms. A record for “time” would have fields for the hours, minutes, and seconds. In C++, this could be done as:

struct Time {
  int hours;
  int minutes;
  int seconds;
};

or

class Time {
public:
  int hours;
  int minutes;
  int seconds;
};

The struct in C++ is actually a holdover from C, the parent language of C++. C++ introduced the class. A class in C++ can provide members that have varying levels of visibility (public, private, and protected) – the reasons for this are outside the scope of this module.

For now, we are only looking at “public” data members. The only difference between a struct and a class in C++ is that

If you are a Java Programmer

2 Working with Records

2.1 Accessing Fields

Fields are accessed by name, via the “.” operator:

struct Time {
  int hours;
  int minutes;
  int seconds;
};
  ⋮
Time t1;
t1.hours = 12;
t1.minutes = 0;
t1.seconds = 1;

int hourOfDay = t1.hours;
bool t1IsPM = (t1.hours >= 12); 
If you are a Python programmer.

2.2 Advantages

Some advantages of using records:

If you are a Java or Python programmer

2.3 Things We Cannot Do With Records

(At least, not by default.)

If we want to do those, we need to craft custom functions

3 Combining Data Structures

We now have two ways to build new data types from existing ones:

  1. Create an array of an existing type.

  2. Create a struct with existing types for the data members

We can combine structs and arrays with one another.

The challenge in working with these is

3.1 Structs Within Structs

We can use records as fields of other records:

struct Interval {
    Time start;
    Time stop;
};
⋮
Interval event;

we can chain dot expressions such as

event.stop.hours = event.start.hours + 1;

3.2 Structs Within Arrays

With a declaration like

Time setAlarms[maxAlarms];
int nextAlarm = ...;

we can combine indexing and dot selection, e.g.,

int nextHour = setAlarms[nextAlarm].hours;

Because setAlarms is an array of Time, the “outer” data structure is the array. So we can only do array-things to setAlarms, such as indexing into it with [nextAlarm].

That indexing operation gives us a single value of type Time. So we can then apply record-things, such as dot selection (“.hours”), to that.

3.3 Arrays Within Structs

The same principle applies if we want to use an array as a data member of a struct:

struct AlarmSystem {
    Time setAlarms[MaxAlarms];
    int numAlarms;
    Time clockTime;
};
  ⋮
AlarmSystem system;

This would allow us to write expressions like system.setAlarms[k].minutes

If we start with system, we have a struct. So we can only do struct-things to it, such as .setAlarms.

system.setAlarms is an array. So we can only do array-things to it, such as [k].

system.setAlarms[k] is a struct. So we can only do struct-things to it, such as .minutes.