Week 01b: Abstract Data Types
Abstract Data Objects and Types |
Abstract Data Types | 2/74 |
A data type is …
... Abstract Data Types | 3/74 |
ADT interface provides
... Abstract Data Types | 4/74 |
ADT interfaces are opaque
... Abstract Data Types | 5/74 |
Typical operations with ADTs
Collections | 6/74 |
Common ADTs …
... Collections | 7/74 |
Collection structures:
... Collections | 8/74 |
Or even a hybrid structure like:
... Collections | 9/74 |
For a given collection type
ADOs and ADTs | 10/74 |
We want to distinguish …
Example: Abstract Stack Data Object | 11/74 |
Stack, aka pushdown stack or LIFO data structure
Assume (for the time being) stacks of char
Operations:
... Example: Abstract Stack Data Object | 12/74 |
Example of use:
Stack | Operation | Return value | ||
? | create | - | ||
- | push a | - | ||
a | push b | - | ||
a b | push c | - | ||
a b c | pop | c | ||
a b | isempty | false |
Exercise #1: Stack vs Queue | 13/74 |
Consider the previous example but with a queue instead of a stack.
Which element would have been taken out ("dequeued") first?
a
Stack as ADO | 15/74 |
Interface (a file named Stack.h
// Stack ADO header file void StackInit();// set up empty stack int StackIsEmpty();// check whether stack is empty void StackPush(char);// insert char on top of stack char StackPop();// remove char from top of stack
Note:
... Stack as ADO | 16/74 |
Implementation may use the following data structure:
... Stack as ADO | 17/74 |
Implementation (in a file named Stack.c
#include "Stack.h" #include <assert.h> #define MAXITEMS 10 static struct { char item[MAXITEMS]; int top; } stackObject;
|
|
assert(test)
Exercise #2: Bracket Matching | 18/74 |
Bracket matching … check whether all opening brackets such as '(', '[', '{' have matching closing brackets ')', ']', '}'
Which of the following expressions are balanced?
(a+b) * c
a[i]+b[j]*c[k])
(a[i]+b[j])*c[k]
a(a+b]*c
void f(char a[], int n) {int i; for(i=0;i<n;i++) { a[i] = (a[i]*a[i])*(i+1); }}
a(a+b * c
... Stack as ADO | 20/74 |
Bracket matching algorithm, to be implemented as a client for Stack ADO:
#include "Stack.h" bracketMatching(s): | Input stream s of characters | Output TRUE if parentheses in s balanced, FALSE otherwise | | for each ch in s do | | if ch = open bracket then | | push ch onto stack | | else if ch = closing bracket then | | | if stack is empty then | | | return FALSE// opening bracket missing (case 1) | | | else | | | pop top of stack | | | if brackets do not match then | | | return FALSE// wrong closing bracket (case 2) | | | end if | | | end if | | end if | end for | if stack is not empty then return FALSE// some brackets unmatched (case 3) | else return TRUE
... Stack as ADO | 21/74 |
Execution trace of client on sample input:
( [ { } ] )
Next char | Stack | Check | ||
- | empty | - | ||
( | ( | - | ||
[ | ( [ | - | ||
{ | ( [ { | - | ||
} | ( [ | { vs } ✓ | ||
] | ( | [ vs ] ✓ | ||
) | empty | ( vs ) ✓ | ||
eof | empty | - |
Exercise #3: Bracket Matching Algorithm | 22/74 |
Trace the algorithm on the input
void f(char a[], int n) { int i; for(i=0;i<n;i++) { a[i] = a[i]*a[i])*(i+1); } }
Next bracket | Stack | Check | ||
start | empty | - | ||
( | ( | - | ||
[ | ( [ | - | ||
] | ( | ✓ | ||
) | empty | ✓ | ||
{ | { | - | ||
( | { ( | - | ||
) | { | ✓ | ||
{ | { { | - | ||
[ | { { [ | - | ||
] | { { | ✓ | ||
[ | { { [ | - | ||
] | { { | ✓ | ||
[ | { { [ | - | ||
] | { { | ✓ | ||
) | { | FALSE |
... Stack as ADO | 24/74 |
Sidetrack: Character I/O Functions in C (requires <stdio.h>
int getchar(void);
int
EOF
int putchar(int ch);
ch
EOF
putchar('A')
putchar((int)'A')
Compilation and Makefiles |
Compilers | 26/74 |
Compilers are programs that
gcc
... Compilers | 27/74 |
Compilation/linking with gcc
gcc -c Stack.cproduces Stack.o, from Stack.c and Stack.h gcc -c bracket.cproduces bracket.o, from bracket.c and Stack.h gcc -o rbt bracket.o Stack.olinks bracket.o, Stack.o and libraries producing executable program called rbt
Note that stdio,assert
gcc
-c
-o
Make/Makefiles | 28/74 |
Compilation process is complex for large systems.
How much to compile?
make
... Make/Makefiles | 29/74 |
Example multi-module program …
... Make/Makefiles | 30/74 |
make
Makefile
A dependency specifies
target : source1 source2 … commands to build target from sources
e.g.
game : main.o graphics.o world.o gcc -o game main.o graphics.o world.o
Rule: target is rebuilt if older than any sourcei
... Make/Makefiles | 31/74 |
A Makefile
game : main.o graphics.o world.o gcc -o game main.o graphics.o world.o main.o : main.c graphics.h world.h gcc -Wall -Werror -c main.c graphics.o : graphics.c world.h gcc -Wall -Werror -c graphics.c world.o : world.c gcc -Wall -Werror -c world.c
Things to note:
game
main.o
:
gcc …
... Make/Makefiles | 32/74 |
If make
prompt$ make world.o gcc -Wall -Werror -c world.c
If no args, build first target in the Makefile
prompt$ make gcc -Wall -Werror -c main.c gcc -Wall -Werror -c graphics.c gcc -Wall -Werror -c world.c gcc -o game main.o graphics.o world.o
Exercise #4: Makefile | 33/74 |
Write a Makefile
From ADOs to ADTs | 34/74 |
Abstract Data Objects
Stack.c
stackObject
Pointers |
Sidetrack: Numeral Systems | 36/74 |
Numeral system … system for representing numbers using digits or other symbols.
... Sidetrack: Numeral Systems | 37/74 |
Decimal representation
… | 1000 | 100 | 10 | 1 |
… | 103 | 102 | 101 | 100 |
... Sidetrack: Numeral Systems | 38/74 |
Binary representation
… | 8 | 4 | 2 | 1 |
… | 23 | 22 | 21 | 20 |
... Sidetrack: Numeral Systems | 39/74 |
Hexadecimal representation
… | 4096 | 256 | 16 | 1 |
… | 163 | 162 | 161 | 160 |
Exercise #5: Conversion Between Different Numeral Systems | 40/74 |
101011
74
2D
273
43
1001010
45
111
... Sidetrack: Numeral Systems | 42/74 |
Conversion between binary and hexadecimal
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 |
8 | 9 | A | B | C | D | E | F |
1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
Exercise #6: Conversion Between Binary and Hexadecimal | 43/74 |
1011111000101001
1011111000101001
10111101011100
10111101011100
12D
BE29
2F5C
100101101
Memory | 45/74 |
Computer memory … large array of consecutive data cells or bytes
If we declare a variable called
|
|
... Memory | 46/74 |
Example:
int k; int m; printf("address of k is %p\n", &k); printf("address of m is %p\n", &m);
address of k is BFFFFB80 address of m is BFFFFB84
This means that
Note the use of k
BFFFFB80
BFFFFB83
m
BFFFFB84
BFFFFB87
%p
... Memory | 47/74 |
When an array is declared, the elements of the array are guaranteed to be stored in consecutive memory locations:
int array[5]; for (i = 0; i < 5; i++) { printf("address of array[%d] is %p\n", i, &array[i]); }
address of array[0] is BFFFFB60 address of array[1] is BFFFFB64 address of array[2] is BFFFFB68 address of array[3] is BFFFFB6C address of array[4] is BFFFFB70
Application: Input Using scanf() | 48/74 |
Standard I/O function scanf()
scanf()
printf()
%d
#include <stdio.h> … int answer; printf("Enter your answer: "); scanf("%d", &answer);
%f
%lf
double
float e; printf("Enter e: "); scanf("%f", &e);
scanf()
scanf()
scanf()
Exercise #7: Using scanf | 49/74 |
Write a program that
Pointers | 50/74 |
A pointer …
The number of memory cells needed for a pointer depends on the computer's architecture:
0x0000
0xFFFF
0x00000000
0xFFFFFFFF
... Pointers | 51/74 |
Suppose we have a pointer p
char
c
Assuming that the pointer p
c
... Pointers | 52/74 |
Now that we have assigned to p the address of variable c
*
c
p
*p = 'T';// sets the value of c to 'T'
*
... Pointers | 53/74 |
Things to note:
// a potential pointer to any object of type char char *s;// a potential pointer to any object of type int int *p;
p
x
*p
x
Examples of Pointers | 54/74 |
int *p; int *q;// this is how pointers are declared int a[5]; int x = 10, y; p = &x;// p now points to x *p = 20;// whatever p points to is now equal to 20 y = *p;// y is now equal to whatever p points to p = &a[2];// p points to an element of array a[] q = p;// q and p now point to the same thing
Exercise #8: Pointers | 55/74 |
What is the output of the following program?
1 #include <stdio.h> 2 3 int main(void) { 4 int *ptr1, *ptr2; 5 int i = 10, j = 20; 6 7 ptr1 = &i; 8 ptr2 = &j; 9 10 *ptr1 = *ptr1 + *ptr2; 11 ptr2 = ptr1; 12 *ptr2 = 2 * (*ptr2); 13 printf("Val = %d\n", *ptr1 + *ptr2); 14 return 0; 15 }
Val = 120
... Examples of Pointers | 57/74 |
Can we write a function to "swap" two variables?
The wrong way:
void swap(int a, int b) { int temp = a;// only local "copies" of a and b will swap a = b; b = temp; } int main(void) { int a = 5, b = 7; swap(a, b); printf("a = %d, b = %d\n", a, b);// a and b still have their original values return 0; }
... Examples of Pointers | 58/74 |
In C, parameters are "call-by-value"
swap()
a
b
main()
... Examples of Pointers | 59/74 |
Can we write a function to "swap" two variables?
The right way:
void swap(int *p, int *q) { int temp = *p;// change the actual values of a and b *p = *q; *q = temp; } int main(void) { int a = 5, b = 7; swap(&a, &b); printf("a = %d, b = %d\n", a, b);// a and b now successfully swapped return 0; }
Pointers and Arrays | 60/74 |
An alternative approach to iteration through an array:
int a[6]; int *p = &a[0]; while (p <= &a[5]) { printf("%2d ", *p); p++; }
... Pointers and Arrays | 61/74 |
Pointer-based scan written in more typical style
Note: because of pointer/array connection a[i] == *(a+i)
Sidetrack: Pointer Arithmetic | 62/74 |
A pointer variable holds a value which is an address.
C knows what type of object is being pointed to
sizeof
int a[6];// address 0x1000 int *p; p = &a[0];// p contains 0x1000 p = p + 1;// p now contains 0x1004
... Sidetrack: Pointer Arithmetic | 63/74 |
For a pointer declared as T *p;
T
A
p = p + k;
k
p
A + k*sizeof(T)
k
Example:
int a[6];(addr 0x1000) char s[10];(addr 0x2000) int *p;(p == ?) char *q;(q == ?) p = &a[0];(p == 0x1000) q = &s[0];(q == 0x2000) p = p + 2;(p == 0x1008) q++;(q == 0x2001)
Arrays of Strings | 64/74 |
One common type of pointer/array combination are the command line arguments
prompt$ ./seqq 10 20
then seqq
"10", "20"
... Arrays of Strings | 65/74 |
prompt$ ./seqq 10 20
Each element of argv[]
char *
\0
... Arrays of Strings | 66/74 |
More detail on how argv
prompt$ ./seqq 5 20
... Arrays of Strings | 67/74 |
main()
int main(int argc, char *argv[]) { ...
argc
argc == 1
argv[]
argv[0]
argv[1],argv[2],…
<stdlib.h>
atoi(char *s)
atof(char *s)
float
Exercise #9: Command Line Arguments | 68/74 |
Write a program that
#include <stdio.h> #include <stdlib.h> void collatz(int n) { printf("%d\n", n); while (n != 1) { if (n % 2 == 0) n = n / 2; else n = 3*n + 1; printf("%d\n", n); } } int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s [number]\n", argv[0]); return 1; } int n = atoi(argv[1]); if (n > 0) collatz(n); return 0; }
... Arrays of Strings | 70/74 |
argv
⇒ Alternative prototype for main()
int main(int argc, char **argv) { ...
Can still use argv[0]
argv[1]
Pointers and Structures | 71/74 |
Like any object, we can get the address of a struct
&
typedef char Date[11];// e.g. "03-08-2017" typedef struct { char name[60]; Date birthday; int status;// e.g. 1 (≡ full time) float salary; } WorkerT; WorkerT w; WorkerT *wp; wp = &w;// a problem … *wp.salary = 125000.00;// does not have the same effect as w.salary = 125000.00;// because it is interpreted as *(wp.salary) = 125000.00;// to achieve the correct effect, we need (*wp).salary = 125000.00;// a simpler alternative is normally used in C wp->salary = 125000.00;
Learn this well; we will frequently use it in this course.
... Pointers and Structures | 72/74 |
Diagram of scenario from program above:
... Pointers and Structures | 73/74 |
General principle …
If we have:
SomeStructType s, *sp = &s;
then the following are all equivalent:
s.SomeElem sp->SomeElem (*sp).SomeElem
Summary | 74/74 |
Makefile
Produced: 22 Nov 2018