topic 11 – structures and unions. cisc105 – topic 11 introduction to structures we have seen...
Post on 20-Dec-2015
218 views
TRANSCRIPT
Topic 11 – Structures and Unions
CISC105 – Topic 11
Introduction to Structures We have seen that an array is a list of
the same type of elements. A structure is a collection of differing
data types. It is usually used to implement a record (as in a database record).
For example, a good use of a structure would be to represent a student’s record in a class / grading database.
CISC105 – Topic 11
Introduction to Structures For each student, the program needs to
store the student’s last, middle, and first names, their student ID number, their numerical grade (course average) and their final course grade.
Thus, for each student record, we need four strings (each name and the ID number), a float (numerical grade), and a character (letter grade).
CISC105 – Topic 11
Introduction to Structures Thus, we can define a structure to hold
a student record as:typedef struct {
char last[20];
char middle[20];
char first[20];
float numerical_grade;
char letter_grade;
} student_record;
CISC105 – Topic 11
Structures What this structure
definition does is to define a new data type, named student_record.
This new data type holds three strings of 20 characters each, one floating point number, and one character.
typedef struct {
char last[20];
char middle[20];
char first[20];
float numerical_grade;
char letter_grade;
} student_record;
First, we use the C keywordstypedef struct
to indicate that we aredefining a new structure.
Then, inside the braces,we list (declare) the membervariables that will compose
the structure.
Finally, we namethe structure and follow
it with a semicolon.
CISC105 – Topic 11
Structures A structure definition goes outside of
any function, including main(). This is similar to function prototypes
which precede main. A good idea is to place structure definitions immediately before function prototypes.
Once the structure definition is present, variables of the structure data type can now be declared inside functions.
CISC105 – Topic 11
Structures For example,
typedef struct {char last[20], middle[20], first[20];float numerical_grade;char letter_grade;
} student_record;
int main(){
float a, b, cstudent_record TopStudent;student_record others[175];int x, y, z;. . .
}
Here, we declare onevariable of type
student_record namedTopStudent.
Here, we declare anarray of 175 variables of type
student_record namedothers.
CISC105 – Topic 11
Structures Note that for each variable of type
student_record, we can store 3 strings, 1 floating point number, and one character.
So, the question remains…how do we access all of these variables contained within our new programmer-designed data type?
CISC105 – Topic 11
Structure Component Referencing To do this, we can use the direct
component selection operator, also known as a period “.”
In our previous example, to reference the last name string (named last) inside the variable TopStudent, we would write:
TopStudent.last
CISC105 – Topic 11
Structure Component Referencing
student_record TopStudent;student_record others[175];
strcpy(TopStudent.last,“Hall”);strcpy(TopStudent.middle,“Alan”);strcpy(TopStudent.first,“Michael”);TopStudent.numerical_grade = 100;TopStudent.letter_grade = ‘A’;
printf(“The top student was:\n”);printf(“%s %s %s who got a %f which is a %c.\n”, TopStudent.first, TopStudent.middle, TopStudent.last, TopStudent.numerical_grade, TopStudent.letter_grade);
CISC105 – Topic 11
Structure Component Referencing We can see that a structure
component (one of the variables that make up the structure) can be accessed using the “.” operator.
Thus, variable_name.component_name can be used in the exact same way as a “regular” variable of the same type.
CISC105 – Topic 11
Structure Component Referencing Looking at our previously example, TopStudent.numerical_grade can be used in any manner a float data type can be. TopStudent.letter_grade can be used just like any other character.
Also, others[9].numerical_grade can be used like any other float and others[9].letter_grade can be used just like any other char.
CISC105 – Topic 11
Array & Structure Referencing Notice that in the reference
others[9].letter_grade We can see that the “[]” array referencing
operator takes precedence over the structure referencing operator “.”
Thus, first we use the “[]” operator to get one student_record from the array of student_records and then we use the “.” operator to get the letter_grade floating point variable from within that student_record.
CISC105 – Topic 11
Structures as Function Arguments We can pass a structure into a function:
void print_record(student_record a){
printf(“Name: %s,%s %s\n”,a.last, a.first, a.middle);
printf(“Numerical Grade: %f\n”,a.numerical_grade);
printf(“Letter Grade: %c\n”,a.letter_grade);
}
CISC105 – Topic 11
Structures asFunction Arguments We could write a function to compare
two student records (1 if true, 0 else):
int compare_records(student_record a, student_record b){
if (strcmp(a.last,b.last) == 0 && strcmp(a.middle,b.middle) == 0 && strcmp(a.first,b.first) == 0 &&
a.numerical_grade == b.numerical_grade && a.letter_grade == b.letter_grade)
return 1;else
return 0;}
CISC105 – Topic 11
Structure Pointers Just like other variables, we can have
pointers that point to structures. As such, they will contain the address of the structure in memory.
student_record TopStudent;student_record *best_p;
best_p = &TopStudent;
CISC105 – Topic 11
Structure Pointers We can use pointers to structures
in the same way we can use pointers to other variables:
student_record TopStudent;student_record *best_p = &TopStudent;
strcpy((*best_p).last,”Hall”);(*best_p).numerical_grade = 100;
printf(“Student %s has a grade of %f.\n”, (*best_p).last,(*best_p).numerical_grade);
Notice that we have to put the pointerdereferencing operator “*” and the pointer
that is bring dereferenced (the pointername) inside parens “()”.
This is because the structure operator “.”has higher precedence than the pointer
operator “*”.
CISC105 – Topic 11
Structure Pointers We can also use structure pointers to make
a structure function output parameter:
int read_record(student_record *record_p){
int result;result = scanf(“%s %s %s %f %c”,
(*record_p).last,(*record_p).middle,(*record_p).first,&(*record_p).numerical_grade,&(*record_p).letter_grade);
if (result == 5) { return 1; }else { return 0; }
}
Notice the precedence.The “*” is put in parens so we evaluate it first.
This operator dereferences the pointer, which gives usa structure of type student_record. The “.” operator has
higher precedence than the “&” operator so it is evaluatednext, giving us the component. Finally, the “&” operator is
evaluated, giving the address that scanf needs.
CISC105 – Topic 11
Structure Pointers The precedence issue can get confusing.
As the “.” operator has higher precedence than the “*” operator, the pointer name and the dereferencing operator “*” must be put in parens if we want to access a structure component using a pointer.
Fortunately, C provides a much “cleaner” operator to remedy this confusing situation.
CISC105 – Topic 11
Structure Pointers C provides the indirect component selection
operator “->”. This is a dash followed by a greater-than sign, which forms an arrow-like operator.
This new, indirect operator takes a pointer to a structure variable on the left side and the component name to be accessed on the right side.
This is a contrast to the direct component selection operator “.” This operator takes a structure variable on the left side and the component name to be accessed on the right side.
CISC105 – Topic 11
Structure Pointers Thus, the following expressions are
equivalent:(*best_p).last best_p->last(*best_p).first best_p->first(*best_p).letter_grade
best_p->letter_grade
Note that either form is correct, however, the form on the right side is more clear and straight-forward.
CISC105 – Topic 11
Structure Pointers Thus, we can rewrite our function
output parameter example:int read_record(student_record *record_p){
int result;result = scanf(“%s %s %s %f %c”,
record_p->last,record_p->middle,record_p->first,&record_p->numerical_grade,&record_p->letter_grade);
if (result == 5) { return 1; }else { return 0; }
}
CISC105 – Topic 11
Functions Returning Structures Structures can also be used as
function return types:student_record read_record(void){
student_record input_record;result = scanf(“%s %s %s %f %c”,
input_record.last,input_record.middle,input_record.first,&input_record.numerical_grade,&input_record.letter_grade);
return input_record;}
CISC105 – Topic 11
Functions Returning Structures We would call this function is the
same manner as a function that returns any other datatype.
student_record record1;
record1 = read_record();
CISC105 – Topic 11
Unions A union is very similar to a structure,
except that where a structure contains all of the variables present in their definitions, a union contains any one of the variables present in their definitions.
A union is declared as:typedef union {
int wears_wig;char color[20];
} hair_data;
CISC105 – Topic 11
Unions
This definition says that a variable of type hair_data contains either an integer named wears_wig or a 20 character string named color.
A component of a union is accessed the same way a structure component is, using the “.” operator or the “->” operator.
typedef union {int wears_wig;char color[20];
} hair_data;
CISC105 – Topic 11
Unions Note that when a variable is declared that
is a union type, space is allocated in memory for the largest of the component variables.
If the program accesses the union variable using the integer component name, the memory for that union variable is treated as a integer. If the program accesses the union variable using the string component name, the memory for the union variable is treated as a string.
CISC105 – Topic 11
Unions Therefore, once a union variable is used,
i.e. it is referenced using one of its components, it is important to ONLY use that component name to reference the union variable in further statements.
If the program first uses the previous union using the component wears_wig (an integer), an integer will be stored at the memory allocated for that union variable.
CISC105 – Topic 11
Unions If, at a later point, the program references
the union using the component color (a string), it will attempt to find a string at the memory allocated for the union variable.
As we previously put an integer there, this will cause an unpredictable result.
So…for each union-type variable, use only one component. And use only that component for that variable throughout the program. Anything else will cause errors!
CISC105 – Topic 11
Summary A structure is a programmer-defined
datatype that is a record (a collection of variables of varying datatypes).
An individual component of a structure can be accessed using a structure variable name and the “.” operator.
We can make a pointer to a structure in the same way we can make a pointer to any other datatype.
CISC105 – Topic 11
Summary An individual component of a structure can
be access using a pointer to a structure and the “->” operator.
A union is similar to a structure except that containing all of the component variables, it contains ONE.
Once a union-type variable is declared and referenced using one of its components, that variable can only be referenced using that component throughout the program.