CIS 150 Structs

Objectives

  • Explain what a struct is.
  • Define a struct.
  • Define a variable where the data type is a struct.
  • Explain what the dot operator does.
  • Use the dot operator to access members of a struct vbariable.
  • Use assignment to assign all the members of one struct variable to another of the same type.
  • Write and use functions that use a struct type variable as a parameter.
  • Write and use functions that return a struct data type.
  • Define a vector that has a struct as the data type.
  • Define an array that has a struct as the data type.
  • Use the at() function with a vector to access a struct data type.
  • Use an array index with an array to access a struct data type.
  • Write a for loop that will iterate through a vector and access the members of the vector.
  • Write a for loop that will iterate through an array and access the members of the array.

Structs

  • A struct is simply a collection of variables grouped together which can be referenced by a single variable and manipulated as a single item. Structs allow you to create your own new complex data types./
  • The dot operator allows you to access the individual members of a struct.
  • Struct variables can be passed to and returned from functions just like any other variable.

Declaring a Structure

When you declare a structure you are actually creating a new data type. The data type is a compound type since it contains several built in or primitive data types. Declarations of new structure data types can be made inside or outside functions. The best place to declare them, however is BEFORE function prototypes. This way they are available to be used in the prototypes or any of the functions in the program. Once you have declare the new type you can create as many variables of that type as you wish. Remember, just because a data type exists doesn't mean you have a variable of that type to use in your program. Think of the structure you declare the same way you think of int, float, bool or char. These data types are build into C++ so you didn't have to declare them, but the data type you created will work the same way as these built in types.

Once the data type has been created you can define as many variables of that type as you wish. These declarations go inside your functions. You declare, lay out, the data type once and then use that data type the same way you use any other variable data type. When creating an array of a structure data type, the syntax becomes a little more challenging. Say we have the following data type:

struct Student { char firstName[15]; char lastName[15]; float gpa; };

In main we can now declare an array of type Student:

int main() { Student kishStudent[5]; return 0; }

The above creates an array of 5 Student variables. Each element has 3 variables of its own:

kishStudent
[0] [1] [2] [3] [4]
firstName firstName firstName firstName firstName
lastName lastName lastName lastName lastName
gpa gpa gpa gpa gpa

The code to get to each to use a member of an element is:

kishStudent[index].firstName; kishStudent[index].lastName; kishStudent[index].gpa;

Struct examples

#include <iostream> using namespace std; struct Rectangle { int width, height; }; int calcArea(Rectangle r); int calcPerimeter(Rectangle r); Rectangle doubleRectangle(Rectangle r); int main() { Rectangle rect1, rect2; rect1.width = 5; rect1.height = 10; rect2.width = 7; rect2.height = 7; cout << "Rectangle 1: " << rect1.height << " by " << rect1.width << endl; cout << "\tArea = " << calcArea(rect1) << "\tPerimeter = " << calcPerimeter(rect1) << endl; cout << "Rectangle 2: " << rect2.height << " by " << rect2.width << endl; cout << "\tArea = " << calcArea(rect2) << "\tPerimeter = " << calcPerimeter(rect2) << endl; rect2 = rect1; // Now rectangle 2 will be the same as rectangle 1 cout << "Rectangle 2: " << rect2.height << " by " << rect2.width << endl; cout << "\tArea = " << calcArea(rect2) << "\tPerimeter = " << calcPerimeter(rect2) << endl; // Now create a bigger rectangle by doubling the dimensions r2 = doubleRectangle(r2); cout << "Rectangle 2: " << rect2.height << " by " << rect2.width << endl; cout << "\tArea = " << calcArea(rect2) << "\tPerimeter = " << calcPerimeter(rect2) << endl; return 0; } int calcArea(Rectangle r) { return r.width * r.height; } int calcPerimeter(Rectangle r) { return 2 * (r.width + r.height); } Rectangle doubleRectangle(Rectangle r) { Rectangle rNew; rNew.height = 2 * r.height; rNew.width = 2 * r.width; return rNew; }

Using structs with vectors and arrays

#include <iostream> #include <vector> using namespace std; struct Rectangle { int width, height; }; void displayRect(Rectangle r); int main() { const int SIZE = 3; Rectangle r, ar[SIZE]; vector<Rectangle> v; int i; for (i=0; i<SIZE; i++) { ar[i].width = 5 * (i+1); ar[i].height = 7 * (i+1); r.width = 3 * (i + 2); r.height = 4 * (i + 3); v.push_back(r); } for (i=0; i<SIZE; i++) displayRect(ar[i]); for (i=0; i<v.size(); i++) displayRect(v.at(i)); return 0; } void displayRect(Rectangle r) { cout << "Rectangle: " << r.width << " by " << r.height << endl; }

Another struct example

#include <iostream> #include <string> #include <iomanip> using namespace std; struct Student { char firstName[15]; char lastName[15]; float gpa; }; string getLine(string prompt, int minLength, int maxLength); void copyStringToCString(string source, char* destination, int arrayLength); int main() { const int SIZE = 5; Student kishStudent[SIZE]; string fName, lName; for (int i=0; i<SIZE; i++) { cout << "Entering data for student #" << (i+1) << endl; fName = getLine("First name: ", 1, 14); copyStringToCString(fName, kishStudent[i].firstName, 15); lName = getLine("Last name: ", 1, 14); copyStringToCString(lName, kishStudent[i].lastName, 15); cout << "GPA: "; cin >> kishStudent[i].gpa; cin.ignore(100, '\n'); } cout << "\n\nWhat was entered:\n"; cout << fixed << showpoint << setprecision(1); for (int i=0; i<SIZE; i++) { cout << kishStudent[i].lastName << ", " << kishStudent[i].firstName << " (" << kishStudent[i].gpa << ")\n"; } return 0; } string getLine(string prompt, int minLength, int maxLength) { bool valid = false; int length = 0; string str = ""; while (!valid) { cout << prompt; getline(cin, str); length = str.length(); if (length < minLength) { cout << "Error: Below minimum length of " << minLength << endl; } else if (length > maxLength) { cout << "Error: Above maximum length of " << maxLength << endl; } else { valid = true; } } return str; } void copyStringToCString(string source, char* destination, int arrayLength) { int charsToCopy = source.length(); if (charsToCopy >= arrayLength) charsToCopy = arrayLength - 1; for (int i=0; i<charsToCopy; i++) { *(destination+i) = source.at(i); } *(destination+charsToCopy) = '\0'; }