Structs (I) - Washington State University › ... › cpts121 › lectures › L18_structs_1.pdf ·...

Post on 27-Jun-2020

0 views 0 download

Transcript of Structs (I) - Washington State University › ... › cpts121 › lectures › L18_structs_1.pdf ·...

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)