STRUCTS Student Activity Sheet A Lego Mindstorms NXT Project Zero Activity 1 INTRODUCTION In software development, many different mindsets (paradigms) exist as a framework to solve different kinds of problems. The most intuitive paradigm and the paradigm you’ve been programming in is the procedural paradigm. This paradigm is great for certain problems, such as those that are sequentially-oriented. Another such paradigm is the object-oriented paradigm, which views a program as interactions between different types of objects. For example, a card object can be moved from a deck object to a player object. Likewise, a bank object can have multiple account objects and perform actions such as querying the account for information and deducting a maintenance fee from the account. C (and henceforth RobotC) does not natively support objects. However, they support a construct called a struct, which is similar to an object. A struct is a collection of variables that are related in some way to each other. The advantage of this setup is that you may logically organize variables. In this Project Zero activity, you will learn how to create structs, reference variables within structs, and how to use structs within functions. 2 LESSONS 2.1 CREATING A STRUCT Here is a sample struct. typedef struct { string name; int age; } person; This struct represents data about a person. This struct contains information about a person’s name and age. Here is another struct example: typedef struct { float x; float y; float z; } point; This struct represents a 3D Cartesian coordinate pair. With many points, you may also be able to define a plot, line, or partial function. Generally, structs are declared with the typedef struct as the first line, following with the struct’s variables. The last line should contain the closing brace and the name (type) of the struct. Remember that a semicolon and name must follow the last curly brace! 2.2 REFERENCING A STRUCT’S VARIABLES Declaring a struct for use is the same as declaring a variable for use. int scale; // Declares an integer named scale point vertex; // Declares a point named vertex To access a struct’s variables, use a dot between the struct’s name and variable. For example, point vertex; vertex.x = 0; // Takes vertex's x variable and makes it 0 vertex.y = 3; // Takes vertex's y variable and makes it 3 vertex.z = 4; // Takes vertex's z variable and makes it 4 float distance = sqrt(vertex.x * vertex.x + vertex.y * vertex.y + vertex.z * vertex.z); nxtDisplayTextLine(0, "Vertex Distance: %2.3f", distance); The first section declares a point named vertex and assigns the vertex’s variables to various variables. The second section calculates the (Pythagorean) distance to the vertex from the origin. The third section displays the distance on-screen. When I wanted the vertex’s x variable, I referenced it as vertex.x. Likewise, vertex’s y variable is referenced by vertex.y. 2.3 USING STRUCTS IN FUNCTIONS Struct types can be passed into functions just as normal variable types. For example, you could declare a function like this: float Distance(point p) This would create a function that takes a point as a parameter and returns a float. Using the point example from the previous section, we could extract the distance calculation into its own specific function: float Distance(point p) { sum = p.x * p.x; sum += p.y * p.y; sum += p.z * p.z; return sqrt(sum); } This technique only works for reading values. Inside the function, we cannot change the value of the passed in variable. Internally, a copy of the variable is made and is passed onward to us. This is called passing by value. To modify the values of a struct within a function, we need to request a struct by reference. To do that, we append an ampersand & before the variable name. Our previous example would become: float Distance(point &p) Here is a more demonstrative example: typedef struct { int count; } counter; void AddByVal(counter c) c.count++; } // No ampersand { void AddByRef(counter &c) // With ampersand { c.count++; } task main() { counter laps; nxtDisplayTextLine(0, "%d", laps.count); // Display 0 AddByVal(laps); nxtDisplayTextLine(0, "%d", laps.count); // Display 0 AddByRef(laps); nxtDisplayTextLine(0, "%d", laps.count); // Displays 1 } 3 ACTIVITY For this activity, you’ll define a note struct, which holds a frequency and duration. This note type will be used as a convenient grouping for a PlayTone() call. 3.1 PROVIDED CODE /* Structs.c */ // Create a note struct // Integer var for frequency // Integer var for duration /** * Plays the provided note * * @param n Note to play */ void PlayNote(note n) { // PlayTone using note's variables // Wait note's duration wait10Msec(n.duration); } /** * Program entry point */ task main() { // Declare notes a, b, and c // Note a is 440 for 500ms (50) a.frequency = 440; a.duration = 50; // Note b is 740 for 250ms (25) // Note a is 587 for 500ms (50) // Play notes a, b, and c in order }