Structs (I)
Lecture 18
CptS 121 – Summer 2016 – Armen Abnousi
Struct
• We have worked with int, double, char data types
• Enumerated data types were essentially ints in the
background
• Arrays are collections of values from the same data type
(e.g. 100 int values in one int array)
• Sometimes we want to store a collection of different
data types
• We want to work with objects. Each object has different
attributes ( each can be of different type)
• We want to store records in a database. Each record can
have multiple fields (e.g. in a database of employees
each employee has: firstname, lastname, age, SSN,
phone#, address, degree, etc.). (Each field can have a
different data type).
Struct
• Struct is a user-defined data type that allows for
combining multiple items (possibly of different types
themselves)
• Using structs we can combine multiple variables
pertaining to one object into a single “package”. (this is
called encapsulation).
typedef struct {
char fname[10];
char lname[10];
int age;
double salary;
int employeeId;
} employee_t;
Struct - declaration
typedef struct {
char fname[10];
char lname[10];
int age;
double salary;
int employeeId;
} employee_t;
Name of the new data type
Different components of the
new data type
Used to declare a new
data type (like in enum)
Telling C that the new
data type is a struct
Struct - components
• We can have multiple data types for the components of
the struct: int, char, double, arrays or even enums!
typedef enum {
HS, BS, MS, PhD
} degree_t;
typedef struct {
char fname[10];
char lname[10];
degree_t degree;
double salary;
int employeeId;
} employee_t;
Accessing components of struct – (.) operator
• Now that we have the struct we can declare variables of
this type:
• employee_t emp1;
• To access individual components of a struct type
variable we use the selection operator .
emp1.age = 32;
emp1.degree = BS;
emp1.salary = 60000;
strcpy(emp1.fname, “John”);
Assignment operator (=) for structs
• We can use = to make a copy of a struct type variable
into another variable of the same type
employee_t emp1;
emp1.age = 32;
strcpy(emp1.name, “John”);
employee_t emp2;
emp2 = emp1;
= makes a copy of all the components of the struct variable
on the rhs, to the struct variable on the lhs.
Even if there is an array in the struct, it will create a copy of
that array and store for the lhs. (e.g. in the code above, both
emp1 and emp2 will have name = John. But these two Johns
come from different arrays; changing one won’t effect the
other).
Assignment operator (=) for structs
• We can use = to make a copy of a struct type variable
into another variable of the same type
employee_t emp1;
emp1.age = 32;
strcpy(emp1.name, “John”);
employee_t emp2;
emp2 = emp1;
= makes a copy of all the components of the struct variable
on the rhs, to the struct variable on the lhs.
Note that if a pointer is the copy of another pointer, then
they both refer to the same position!
int* ap; int* bp;int a;
ap = &a;
Assignment operator (=) for structs
• We can use = to make a copy of a struct type variable
into another variable of the same type
employee_t emp1;
emp1.age = 32;
strcpy(emp1.name, “John”);
employee_t emp2;
emp2 = emp1;
= makes a copy of all the components of the struct variable
on the rhs, to the struct variable on the lhs.
Note that if a pointer is the copy of another pointer, then
they both refer to the same position!
Now if you change the value in a, both pointers will be
affected.
int* ap; int* bp;int a;
ap = &a; bp = ap;
Assignment operator (=) for structs
• We can use = to make a copy of a struct type variable
into another variable of the same type
employee_t emp1;
emp1.age = 32;
strcpy(emp1.name, “John”);
employee_t emp2;
emp2 = emp1;
= makes a copy of all the components of the struct variable
on the rhs, to the struct variable on the lhs.
Note that if a pointer is the copy of another pointer, then
they both refer to the same position!
Now if you change the value in a, both pointers will be
affected.
int* ap; int* bp;int a;
ap = &a; bp = ap;
Assignment operator (=) for structs
Note that if a pointer is the copy of another pointer, then they both
refer to the same position!
Now if you change the value in a, both pointers will be affected.
typedef struct {
int* x;
} mytype_t;
int a = 2;
mytype_t t1;
t1.x = &a; /* component x of t1 will refer to a */
mytype_t t2;
t2 = t1; /* will copy all components of t1 into t2 */
a = 5;
printf(“t1: %d”, *t1.x); /* will print new value of a, 5 */
printf(“t2: %d”, *t2.x); /* will print new value of a, 5 */
Pointer component in two struct variables are referring to the same int
variable (because we used = operator). Remember this won’t be true
about array components; they will have two different array variables.
Assignment operator (=) for structs
• We can use = to make a copy of a struct type variable into
another variable of the same type
employee_t emp1;
emp1.age = 32;
strcpy(emp1.name, “John”);
employee_t emp2;
emp2 = emp1;
= makes a copy of all the components of the struct variable on
the rhs, to the struct variable on the lhs.
Note that if a pointer is the copy of another pointer, then they
both refer to the same position!
Now if you change the value in a, both pointers will be affected.
**Although arrays are implemented using pointers, there is a
difference between an array and a pointer. Array name without
an index is a pointer to the beginning of the array, but array
itself is a number of cells containing regular values like ints,
and not pointers (unless it is an array of pointers int* a[]).
Passing struct variables as function parameters
• We can send struct variables both as input or output
parameters just like standard data types int, double, char.
• We can also return a struct variable from a function.
• Sending as input argument to function printEmployee():
employee_t emp;
emp.age = 25;
printEmployee(emp);
• Returning it from function readEmployee():
employee_t readEmployee()
{
employee_t emp;
/* do something */
return emp;
}
Passing struct variables as function parameters
• Returning a struct variable as output parameter:
employee_t emp;
readEmployee( &emp );
void readEmployee( employee_t* emp )
{
(*emp).age = 25;
}
Instead of using *emp.age we can use indirect
component selection operator (->)
emp -> age = 25;
Indirect component selection operator
• (*emp).age is equivalent to emp -> age
• Write a function to scan the values for employee from the user interactively and return 0
if the operation was unsuccessful.
int scanEmployee( employee_t* emp )
{
int status = scanf(“%d%lf%s”, &emp -> age, &emp -> salary, emp -> name );
if ( status != 3 )
status = 0;
return status;
}
Example
• Create a struct for time with three integer components
for hour, minute and second.
• Write a function that scans a time value from the screen
(separated by spaces)
• Write a function that given a beginning time (bt) and an
integer showing elapsed time in seconds (te), computes
and returns the time after te seconds has passed from
the bt.
• Write a function that prints the time given a time struct
variable.
• Write a driver code to test the functions above.
Example – declare struct and scan
typedef struct
{
int sec, min, hour;
} daytime_t;
int scanTime(daytime_t* t)
{
int status;
printf("Enter hours, minutes and seconds separated by a space: ");
status = scanf("%d %d %d", &t->hour, &t->min, &t->sec);
if (status != 3)
{
status = 0;
}
return status;
}
Example – compute and print
daytime_t computeNewTime(daytime_t bt, int et)
{
daytime_t nt;
int newSeconds, newMinutes, newHours;
newSeconds = bt.sec + et;
nt.sec = newSeconds % 60;
newMinutes = bt.min + (newSeconds / 60);
nt.min = newMinutes % 60;
newHours = bt.hour + (newMinutes / 60);
nt.hour = newHours % 24;
return nt;
}
void printTime(daytime_t t)
{
printf("%d:%d:%d\n", t.hour, t.min, t.sec);
}
Example – main (test driver)
int main()
{
daytime_t bt, nt;
int status = scanTime(&bt);
if ( status != 0 )
{
nt = computeNewTime(bt, 97);
printTime(nt);
}
return 0;
}
Operator Precedence (page 576 of the textbook)
Operator Precedence
• Based on the table in the previous slide how will these
expressions be interpreted?
void fun(employee_t* emp)
{
*emp.age = 25;
}
Operator Precedence
• Based on the table in the previous slide how will these
expressions be interpreted?
void fun(employee_t* emp)
{
*emp.age = 25;
}
• because . has precedence over *, it will be interpreted
as *(emp.age) which implies that variable age in the
struct is a pointer that we are trying to use the indirect
reference operator on it, resulting in not compiling.
• Instead we should use (*emp).age or better we use the
indirect component access operator: emp -> age
References
• J.R. Hanly & E.B. Koffman, Problem Solving and Program
Design in C (8thed.), Pearson, 2016
• Andy O’Fallon’s lecture notes for CptS121
(http://eecs.wsu.edu/~aofallon/cpts121)
Top Related