C++ Structs

We have been mentioning defining our own data types for a while now. It’s time we learn to do that now.

Let’s start with a simple problem. We want to write a function that computes the simplest form of a fraction.

If you actually try to think of how to do this, you’ll quickly run into a problem: Fractions are represented by a numerator and a denominator. But functions can only return one value. If you’re willing to mess around, I’m sure some of you will be able to think of solutions to this question.

Using what you already know by now, I can imagine three tricks to get around this problem. The first way is to store return values in global variables and copy them over as soon as the function is done. A second way is to accept pointers and store the answers in the given addresses. And third, allocate some new memory, store the answer there, then return a pointer to that memory address. Any of these solutions will work, but they’re all needlessly complicated and bug-prone. (And they’re not the point of this section.)

Wouldn’t it be nice if we could just bundle variables together in a simple and elegant way? Then we could return those bundles so we’ll be able to return two variables. And taking that idea further, we can pass those bundles as arguments to functions, saving us lots of typing and error-prone code. What a wonderful world that would be if only we could bundle variables together.

Well I have good news for you! C++ supports exactly that through a feature called a struct! Another name you might read on the internet for a struct is a record, which is the term used for the same thing in a few older programming languages. To understand what a struct is, let’s look at some sample code.

  1. struct fraction {
  2. int numerator;
  3. int denominator;
  4. };

The sample code above defines a struct called fraction. In this case, fraction is a bundle of two int variables. The variables that it groups together are called its members. In this case, our fraction struct has two members called numerator and denominator. Let’s look at some sample code to see how we can use our new data type.

  1. #include <stdio.h>
  2. #include <algorithm>
  3. struct fraction {
  4. int numerator;
  5. int denominator;
  6. };
  7. int gcd(int a, int b) {
  8. // The GCD is the largest number both numbers are divisible by.
  9. int smaller = std::min(a, b);
  10. for (int i=smaller; i > 0; i--) {
  11. if (a % i == 0 && b % i == 0) {
  12. return i;
  13. }
  14. }
  15. return 1;
  16. }
  17. fraction simplify_fraction(fraction f) {
  18. // We simplify a fraction by dividing its numerator and denominator by their gcd.
  19. int g = gcd(f.numerator, f.denominator);
  20. fraction answer;
  21. answer.numerator = f.numerator / g;
  22. answer.denominator = f.denominator / g;
  23. return answer;
  24. }
  25. int main() {
  26. // create a new fraction called `unsimplified`
  27. fraction unsimplified;
  28. unsimplified.numerator = 15;
  29. unsimplified.denominator = 20;
  30. // create a new fraction called `simplified`
  31. fraction simplified = simplify_fraction(unsimplified);
  32. printf("The unsimplified version is %d / %d\n", unsimplified.numerator, unsimplified.denominator);
  33. printf("The simplified version is %d / %d\n", simplified.numerator, simplified.denominator);
  34. }

Looking at the sample code, you’ll see that members are accessed via the . operation. You will also notice that we passed fraction objects around as if they were any other data type. We will eventually learn how to do operations on our custom structs.

In the sample code above, f, unsimplified, answer, and simplified are called objects of our new data type fraction. So a struct is a definition of a data type, and an object is an occurrence of that data type. Sometimes you might also encounter the word instance which is synonymous to an object.

One common error: You need a semi-colon ; after the closing bracket } of the struct. Also you need a semi-colon ; at the end of each member declaration. So when you’re defining structs and you suddenly get a syntax error, that’s one of the most likely places to look.

One more thing I would like to note at this point is that for those of you who may have heard the term "data structure" before, this is not a data structure. struct is only a keyword in C++ that allows you to group variables together. We will be covering actual data structures later on, so hold on to your hats!