Topics to Cover

Compelling introduction

This lesson begins a big new topic for us:

User defined types, or structs as they are called in C++.

This is something that you have already felt the need for. Let's consider a few example problems. Each of these are things we can do (think about how), but only with difficulty. The problem is that in each case we are working with "physical" objects that do not have a corresponding built-in type in C++. Clearly, these problems scream out for the ability of the user to wrap up one or more existing types into one package and call it a new type. In C++, struct is the mechanism that allows you to do this.

Note: The string, ifstream, and ofstream objects that we've already been using are structs rather than built-in types.

The Simple Example of point

Let's take the simple example of our midpoint function. We decided that the existence of a type point would make such a function simple and natural. We need to wrap up a double for the x-coordinate and a double for the y-coordinate into a single object of a new type - point. Here's how that's accomlished in C++:

struct point   // Declares a new type called "point"
{
  double x;    // Says that a "point" contains 
  double y;    //   two doubles named x and y
};             // Don't forget the semicolon!

// An equivalent, simpler way of declaring "point" 
struct point   
{
  double x,y;
};

Q: Where should I give a struct definition?

It must appear before the main() function (more correctly, before you try to use an object of type point).

Q: How do I create a variable of type point?

Just as you create other variables! The following code declares a variable with name P of type point.

point P;

Q: How do you access double x within a point object named P?

P.x
Note: We'll start off simple by creating an object of type point, reading values into the object, and printing it out:

Quick check

Consider the code on the left.
  1. What is the type of P?
  2. What is the type of P.x?
  3. Is P an l-value?
  4. Is P.x an l-value?
Answers are given below (drag your mouse to see the answer).
1. point    2. double    3. yes    4. yes

int main()
{
  // Creates an object P of type point
  point P;

  // Reads & stores coordinate values
  cout << "Enter x-coord: ";
  cin >> P.x;
  cout << "Enter y-coord: ";
  cin >> P.y;

  // Writes out point P
  cout << "Point is (" << P.x
       << ',' << P.y << ")" << endl;

  return 0;
}

Q: Can you do cin >> P or cout << P?

Answer: No, because cin and cout know nothing about the type point!

Q: Then, how do I read in P?

Answer: cin >> P.x >> P.y;
Note that cin >> P.x works perfectly well, because cin is just reading into a double, which we know it does just fine.

(Important) Assignment and structs

Good news: You can use perform assignment by simply using the = operator even for user-defined objects! It just works!

So, the code on the right works nicely. We also will see that the midpoint function uses the pass-by-value for parameters a and b.


point P, Q;
P.x = 1.0; 
P.y = 2.0;
Q = P;
cout << "(" << Q.x << ", " << Q.y << ") << endl;

Writing a function with structs

Now, let's look at defining the function midpoint:

point midpoint(point a, point b)
{
  point m;
  m.x = (a.x + b.x)/2;
  m.y = (a.y + b.y)/2;
  return m;
}
Hopefully this code is pretty much self-explanatory. Notice that by wrapping up two doubles in the type point I can, in a sense, return two objects from a function! Take a look at this complete program that reads two points from the user and prints out their midpoint.
Note: The diagram on the right illustrates the call stack when we make a call like midpoint(P,Q).

Q: What is the type of midpoint(P,Q)?

Answer: point

Defining struct mid

Let's think about our example of Midshipmen names and alpha codes. We might define a mid as follows:

struct mid
{
  int alpha;
  string first, last;
};
Notice that this struct has three data members, one of type int and two of type string.

Reading midshipmen data from a file

Let's consider using this type in the following problem: The file Mids.txt contains the names and alpha codes of the Midshipmen in my two sections. I want to write a program that will read that data and store it in an array for later processing.

To test what I've done, we'll simply allow the user to enter an alpha, and we'll return the name of the Mid with that alpha, or an error message if none is found. Creating the array and reading in data from the file is easy:


// Create and array of 41 Mids
mid* A = new mid[41];

// Open file
ifstream fin("Mids.txt");

// Read in mids
for(int i = 0; i < 41; i++)
  fin >> ____________ >> _____________ >>  _____________;



Quick check: Consider the code on the left.
  1. Fill out the blanks so that the code works correctly.
  2. What is the type of new mid[41]?
  3. What is the type of A?
  4. What is the type of A[i]?
  5. What is the type of A[i].alpha?
  6. What is the type of A[i].first?
  7. What will be the value of A[0].alpha?
  8. What will be the value of A[0].last?
Answers are below (drag your mouse).
1. A[i].alpha   A[i].last    A[i].first
2. mid*     3. mid*     4. mid        5. int    
6. string   7. 166030   8. SHERIDAN
By the way: struct vs class

C++ has two names / keywords for user-defined types: struct and class. They are more or less the same (except that in structs members are public by default, and in classes they are private by default.

Of course that distinction won't make any sense at this point, but in case you come back and read this later ...), but historically come from different places. C++ gets struct from C, the language that C++ extends. The term class comes from "object-oriented programming", which is a style of programming C++ supports, but which we do not cover in this course.

We are going to use the keyword struct to get you familiar with what you'll see in the context of C programming in your Systems Programming course. Of course this means that in your Objected Oriented Programming course (taught using Java) the keyword class will be familiar.

Mandatory Practice Problem

Write a program that reads in Mids.txt (41 lines) and with alpha as input, prints out the name of the Midshipman.

Sample runs

$ ./a.out
Enter alpha: 185112
RAINEL NUNEZ
$ ./a.out
Enter alpha: 200000
No Mid with that alpha was found!
Solution

Other Practice Problems

  1. Write a program that reads in three points describing the vertices of a triangle and computes the midpoint triangle they define, i.e. the triangle whose vertices are the three midpoints of the previous triangle. A typical run of your program should look like:
    Enter triangle vertices: (0,0) (0,1) (1,0)
    Midpoint triangle verts: (0,0.5)(0.5,0.5)(0.5,0) 
    Notice how my solution defines functions for writing and reading points!
  2. How about something completely different: organizing data on our congressional representatives. This tab-separated values (tsv) file contains a bunch of information about all 538 members of the current House and Senate (source). Some of the code to read in this data is in this C++ program, but it's right now limited to just sorting by first name. Use a struct to write a program that prints out the 10 youngest congresspeople, first and last names. Here is my solution.