Title: Introduction to C Lecture 8: Enum, and Structures
1Introduction to CLecture 8 Enum, and Structures
2Enumeration Types
- You can declare and name a finite set, for
example enum day sun, mon, tue, wed, thu, fri,
satand then use these as variable types. They
are const int default is 0, 1, 2..., but you
can change this for example, enum suit clubs
1, diamonds, hearts, spadesstarts at 1
instead of 0. - You can then declare variables enum day d1,
d2and use them if (d1 ! d2) / do
something... / - You can also declare the variables along with the
template enum outcome win, lose, tie, error
a, b, c - Note that the type is (for example) enum day the
name enum by itself is not a type. You can
typedef it, though typedef enum day
dayand thus you have variables of type day that
you can use directly. - See latter half of chapter 7 in KP for more on
this and paper-rock-scissors example in the
usual place on disk. Also poker example in h/w.
3Structures
- Structures provide a way of aggregating variables
of different types. For example struct card
int pips char suit can hold the
information relating to a playing card.
Structures can also contain floats, arrays,
pointers or anything else. - The variable type is struct card i.e. 2 words
not just card. (Its like long int in this
respect). Its common to use typedef which you
recall defines new variable types to define the
type card (in this instance) to be equivalent to
the type struct card typedef struct card
cardso that now the variable type really is just
card. We can then declare card c3, c4,
c5and so on. - We can initialise in the same way as for
arrays card c6 13,h / the king of
hearts / - We can write c2 c1which assigns to each
member of c2 the value of the corresponding
member of c1. - Structures can contain arrays. It is also useful
to have arrays of structures. Example card
deck52declares an array (of size 52) of
variables of type card the name of the array
is deck. It could of course have been x or
anything else.
4Accessing members of a structure
- Members of the structure are accessed with the
operator . (dot), as in -
- c1.pips 3
- c1.suit s
- Â
5Example Student grades
- Suppose we are interested in storing information
about a class of students. Definestruct
student char last_name int student_id char
grade -
6Example Student grades
- Suppose we are interested in storing information
about a class of students. Definestruct
student char last_name int student_id char
grade - int main(void) struct student tmp,
class100 /declaration .... tmp.grade
A tmp.last_name Casanova tmp.student_id
910017
7Example Student grades
- Suppose we are interested in storing information
about a class of students. Definestruct
student char last_name int student_id char
grade - int main(void) struct student tmp,
class100 /declaration .... tmp.grade
A tmp.last_name Casanova tmp.student_id
910017 - Now suppose we want to count the failing grades
- int fail(struct student class )
-
- int i, cnt 0
- Â for (i 0 i lt 100 i)
- cnt (classi.grade F)
- return cnt
-
8student grades, contd
- In reality you dont know how big the class is,
so youd want dynamic allocation struct student
class /... read in number of students
n.../ class (struct student )calloc(n,
sizeof(struct student)) - The structures would then be allocated
dynamically, much as we did last time for the 2D
matrices. - Similarly for the variable last_name within the
structure you might want to define a maximum
size, and have a string that long for all
students, or you might want to have strings of
the appropriate length defined as need dictates
and let the pointer just point to it.
9Pointers to structures
- Sometimes structures contain large amounts of
data and if they are passed as arguments to
functions, it can be very inefficient, as you
have to copy down everything within the
structure. - In addition, like other variables, structures are
passed by value to functions that are called, and
so they are not modified within the calling
environment, which is sometimes desirable. - It is therefore often necessary to use pointers
to structures. If this is the case, then the
structure member is not accessed with ., but
rather with -gt. So - pointer_to_structure-gtmember_name is equivalent
to - (pointer_to_structure).member_name
10Example Complex numbers
- Example suppose in header file complex.h we have
- Â
- struct complex
- double re / real part /
- double im / imag. part /
-
- typedef struct complex complex
- Â
- and then in another file,
- Â
- include complex.h
- Â
- void add(complex a, complex b, complex c)
- / a b c /
-
- a-gtre b-gtre c-gtre
- a-gtim b-gtim c-gtim
More to come in your homework!
11Using structures with functions
- Example Consider an employers database.struct
dept char dept_name25 int
dept_notypedef struct char
name25 int employee_id struct
dept department struct home_address a_ptr do
uble salary ..... employee_data - Note that struct employee_data contains a
variable of type struct dept as a member.
Because the compiler has to know the size of all
members, struct dept has to be defined
beforehand. - We also have a pointer to struct home_address.
As the compiler knows how big a pointer to a
structure is, there is no need to define struct
home_address beforehand. - Â
- Suppose we want to update some employee records.
Here are two possible ways
12Employee record update method 1
- Send structure e down to the function, modify it,
and return the modified structure for use in the
calling routine - e employee_data update(e)
- .....
- employee_data update(employee_data e)
-
- ....
- printf (Input the department number )
- scanf(d, n)
- / now access member of struct-within-struct...
/ - e.department.dept_no n
- .....
- return e
-
- Â
- This involves a lot of copying of structure
members down to the function and back again.
Theres a better way...
13Employee record update method 2
- Use pointers instead
- update(e)
- void update_employee(employee_data p)
-
- ....
- printf(Input the department number )
- scanf(d, n)
- p-gtdepartment.dept_no n
- .....
-
- Â
14Example Playing poker
- The program in ....lect9/poker is a model of a
poker-playing program. It repeatedly shuffles
and deals a set of five cards to each of six
players, and then calculates the probability that
a flush is dealt (i.e. that all five cards are of
the same suit). - Look at the code, and run it. The probability of
a flush (all cards the same suit) is 0.00198...
How close does this program come if you run it
several times? - Comment the code to ensure that you understand
all that is going on. - Note that the card structure in the code uses an
enumerated type to define the suit. Note also
that deck52 is an array, and the variable name
deck52 is therefore equivalent to a pointer
to the start of the array the whole array of 52
structures is not passed down with each function
call that has deck as an argument! - Modify the program by adding a function
is_straight( ), which tests whether a hand is a
straight (i.e. a continuous sequence of numbers
4, 5, 6, 7, 8 and so on). Print out the
probability of the straight in the same way as is
done for the flush.
15Linear linked lists
- Suppose you have 1000 employees in your company
you can keep an array of structures to manage all
of their records. However, if an employee
leaves, you will then have a gap in your array...
this would quickly become a cumbersome,
disorganised and inefficient system. - Â
- A way around this is through a linked list, based
on self-referential structures. Each structure
can contain a pointer to another structure the
next one in the list. It is then trivial to
remove items from the list simply make the
previous items pointer point to the subsequent
structure.
16Linked lists, contd
- This is how you implement it.
- struct list
- int data
- struct list next
-
- Â
- You can then have several variables of this type,
or pointers to them -
- struct list a, start_of_list, current_member
- Â
- The pointer variable next is called a link. The
last item in the list points to NULL. - Â
- You can also take this further sometimes, when
going through a list, it is useful to be able to
move backwards as well as forwards. This is done
with a so-called doubly linked list, where the
structure contains pointers to both the previous
and the next list members. - Â
- Heres an example of setting up a linked list.
Its a bit pointless, but it takes a string, and
stores the characters as the data elements in a
linked list.
17Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
18Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
This list only has characters in it, but of
course it could be anything
19Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
This variable next is the pointer to the next
structure in the list
20Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
Now weve defined what the structure looks like,
we write a function to do the work of filling it
21Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
First check that the string coming in isnt empty.
22Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
Allocate space for the first structure in the
list we call it head
23Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
Put data the first character of the string
into the first structure in the list
24Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
Our last link in the chain is called tail. To
start with, set it equal to head, the first one.
25Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
- As long as the characters keep coming,
- allocate space for the next structure well
need, - make the element next point to it
- fill the character element of this structure
26Linked list example
- struct linked_list char d struct
linked_list next -
- char string_to_list(char s )
-
- char head NULL, tail
- int i
- if (s0 ! '\0') head malloc(sizeof(struct
linked_list)) head-gtd s0 tail head
for (i 1 si ! '\0' i) - tail-gtnext malloc(sizeof(struct
linked_list)) - tail tail-gtnext
- tail-gtd si tail-gtnext NULL
return head
Allocate last pointer in the list to NULL. (We
could if we wished set it to head, to make the
list circular instead of linear).
27Binary trees
- Finally, let us mention an extension to the idea
of a linear linked list. In a binary tree, each
element has a pointer to two other elements, thus
making a tree-like structure - Access times when searching through the tree for
given elements are typically much faster than for
a linear list at each node you can find out
whether to turn left or right, as opposed to
a linear list which is accessed sequentially from
beginning to end.