Programming in C
Lecture 8: DATA STRUCTURES
CHRIS STAFF
Dept. of Computer Science and Artificial Intelligence
University of Malta
Lecture Outline
Aims and Objectives
Data Structures
Structures and Functions
Arrays of Structures
Aims and Objectives
- Basics of Structures
- Structures as Parameters and Return Values
- Pointers and Structures
- Arrays of Structures
Data Structures
- A data structure is a collection of one or more variables, possibly of
different types, organised into a single "record" with a single name for easy
reference and manipulation
- A data structure could be used to hold personnel details, co-ordinates of a
complex 2- or 3-D shapes, etc.
- You can copy and assign to structures, pass them to functions, return them
from functions, and initialise them
- Structures are syntactically analogous to data types
- A structure can have a tag (a name for the data type) and variables can be
declared to be of that type
Basics
- Let's say that we want to create a data structure to manipulate x,y
co-ordinates
struct point {
int x;
int y;
};
- point is a structure with 2 members . Both members are
integers
- You have not created a variable called point - you have created a structure
- Note the semi-colon trailing the close brace - this is because you can also
declare variables to be of type point
- point is a tag. You can declare variables to be of
type point in either of
the following ways
struct point {
int x;
int y;
} pt1, pt2 ;
/* or */
struct point {
int x;
int y;
};
struct point pt1, pt2; /* once struct defined */
- Obviously, you can only refer to the structure by name if you have given it a
tag
- You can initialise the structure
struct point pt1 = {320, 200};
- Members can be referenced using the construct
structure_name.member
as in,
pt1.x
- You can include references to other structures in a struct definition
struct rect {
struct point pt1;
struct point pt2;
};
Structures and Functions
- There are a variety of ways of passing structures between functions
- As a unit
- As a pointer to the structure
- As individual members
- Which method is best depends on what you're going to do with the structure,
or its components
A function to make a structure out of variables
struct point makepoint(int x, int y)
{
struct point temp;
temp.x = x;
temp.y = y;
return temp;
}
- makepoint can now be used to initialise any point structure
- It can also be used to provide structure arguments to a function
struct rect screen;
struct point middle;
struct point makepoint(int, int);
screen.pt1 = makepoint(0,0);
screen.pt2 = makepoint(XMAX,YMAX);
middle = makepoint((screen.pt1.x + screen.pt2.x)/2,
(screen.pt1.y + screen.pt2.y)/2);
Structure Arithmetic
- Add two points
- Is a point inside a rectangle?
int ptinrect(struct point p, struct rect r)
{
return p.x >= r.pt1.x && p.x < r.pt2.x
&& p.y >= r.pt1.y && p.y < r.pt2.y;
- Ensuring that pt1(x, y) < pt2(x, y)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
struct rect canonrect(struct rect r)
{
struct rect temp;
temp.pt1.x = min(r.pt1.x, r.pt2.x);
temp.pt1.y = min(r.pt1.y, r.pt2.y);
temp.pt2.x = max(r.pt1.x, r.pt2.x);
temp.pt2.y = max(r.pt1.y, r.pt2.y);
return temp;
}
- If the structure is large, it is more efficient to pass a pointer to a
structure to a function, than to copy the entire structure
Pointers to Structures
- Declared in the usual way
struct point *pp;
- Members of the structure are referred to as
(*pp).x
- Brackets are important because . has higher precedence than *
- There is a shorthand notation for referring to members via pointers
(*pp).x == pp->x && (*pp).y == pp->y
- For example
struct point origin, *pp;
pp = &origin;
printf("origin is (%d, %d)\n", pp->x, pp->y);
Structure Arithmetic and Pointers
Arrays of Structures
- An array of structures is analogous to a file of records
- Once you read in (or initialise) an array of structures, you can change the
values of members before outputting it
Creating an array of structures
- Let's say you want to count the number of times certain words are encountered
in the input
- The words we want to keep a count of are
char *keyword[NKEYS] =
{"he", "i", "it", "she", "they", "we", "you"};
- The list will be sorted so that we can use the binsearch() function
to rapidly check through it
- We also want to have a second array to keep a count of the number of times
the key words are encountered
int keycount[NKEYS];
- Now, we could have these two separate arrays, and use a common array
subscript to cycle through the arrays (e.g., cell = baz(word, keyword) returns
the cell number in which word was found, and then keycount[cell]++)
- But because the relationship between the two arrays is rather strong, we
could combine them into a structure
struct key {
char *word;
int count;
} keytab[] = {
"i", 0,
"it", 0,
"he", 0,
"she", 0,
"they", 0,
"we", 0,
"you", 0
};
- So, each keytab[] element is composed of a structure of two members,
the first is a pointer to a character, and the second is an int
- C automatically computes the size of keytab[] because the array is being
initialised and the [] are left empty
- For convenience, keytab[] will be declared as a global variable, so it just
needs to be declared, and initialised in this case, outside of any function
- The main() function will call getword(), which will retrieve a word from the
input, and will then call binsearch() to check if it is a word that is to be
tracked. If it is, then the appropriate member in the structure will be
updated
The Program
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "keywords.h"/* assume keywords[] defined here */
#define MAXWORD 100 /* word can be max 100 chars long */
int getword(char *, int);
int binsearch(char *, struct key *, int);
main()
{
int n;
char word[MAXWORD];
while(getword(word, MAXWORD) != EOF)
if (isalpha(word[0]))
if ((n=binsearch(word, keytab, NKEYS))>=0)
keytab[n].count++;
for (n = 0; n < NKEYS; n++)
if (keytab[n].count > 0)
printf("%4d %s\",
keytab[n].count, keytab[n].word);
return 0;
}
/* iterative binsearch modified */
int binsearch(char *word, struct key tab[], int n)
{
int cond, low, high, mid;
low = 0;
high = n - 1;
while(low <= high) {
mid = (low+high) / 2;
if ((cond = strcmp(word, tab[mid].word))<0)
high = mid - 1;
else if (cond > 0)
low = mid + 1;
else
return mid;
}
return -1;
}
C can calculate the size of your structures