Generic Container Implementation in C: A Case Study with Stack, Study notes of Programming Paradigms

A detailed explanation of implementing a generic container in c using a stack as an example. It includes the code for the stack structure, function implementations, and their explanations. It also discusses the importance of hiding the internals of an exposed data structure and the proper usage of the stack operations.

Typology: Study notes

2010/2011

Uploaded on 10/17/2011

larryp
larryp 🇺🇸

4.8

(34)

352 documents

1 / 52

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
ty p e d ef struct {
void *elem s;
int ele m Size;
int log L e n gt h;
int allo cL e n gt h;
} stack;
stac k.h
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34

Partial preview of the text

Download Generic Container Implementation in C: A Case Study with Stack and more Study notes Programming Paradigms in PDF only on Docsity!

typedef s

truc

t^ { void *e

lems; int e

lemSize; intlogLength

int a

llocLength

} stack

stack

.h

typedef s

truc

t^ { void *e

lems; int e

lemSize; intlogLength

int a

llocLength

} stack

stack

.h

Writing a generic container in pure C is hard, andit’s hard for two reasons:1.^

The language doesn’t offer any real support for encapsulation orinformation hiding. That means that the data structures exposeinformation about internal representation right there in the interfacefile for everyone to see and manipulate. The best we can do isdocument that the data structure should be treated as an abstractdata type, and that the client shouldn’t directly manage the fields.Instead, he should just rely on the functions provided to manage theinternals for him.

2.^

C doesn’t allow data types to be passed as parameters. That meansa generic container needs to manually manage memory in terms ofthe client element size, not client data type. This translates to abunch of malloc, realloc, free, memcpy, and memmove callsinvolving void *s. This is the very type of programming that makesC difficult.

typedef s

truc

t^ { void *e

lems; int e

lemSize; intlogLength

int a

llocLength

} stack

void S

tackNew(s

tack *s

,in

telemSize)

void S

tackDispose(s

tack *s

boo

l StackE mpty(const s

tack *s

void S

tackPush(s

tack *s

, const vo

id *

elemAddr)

void S

tackPop(s

tack *s

, vo

id *e

lemAddr

stack

.h

This is what you see as a client, but as a client, you shouldignore the internals of an exposed data structure unless thedocumentation explicitly says otherwise.

typedef s

truc

t^ { void *e

lems; int e

lemSize; intlogLength

int a

llocLength

} stack

void S

tackNew(s

tack *s

,in

telemSize)

void S

tackDispose(s

tack *s

boo

l StackE mpty(const s

tack *s

void S

tackPush(s

tack *s

, const vo

id *

elemAddr)

void S

tackPop(s

tack *s

, vo

id *e

lemAddr

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stack

intStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

stack }

.h

clien

t.c

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

val

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

val intStack

sizeo

f(int ) 4 0

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

0

val intStack

sizeo

f(int ) 4 1

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

0

val intStack

00 00 00 00

sizeo

f(int ) 4 2

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

1

val intStack

00 00 00 00

00 00 00 01

sizeo

f(int ) 4 2

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

2

val intStack

00 00 00 00

00 00 00 01

sizeo

f(int ) 4 3

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

3

val intStack

00 00 00 00

00 00 00 01

00 00 00 02

sizeo

f(int ) 4 4

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

3

val intStack

00 00 00 00

00 00 00 01

00 00 00 02

00 00 00 03

sizeo

f(int ) 8 5

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

4

val intStack

00 00 00 00

00 00 00 01

00 00 00 02

00 00 00 03

00 00 00 04

sizeo

f(int ) 8 5

int ma

in(i

nt a

rgc

, char *a

rgv

[])

int va

l; stackin

tStack

StackNew(&in

tStack

, sizeo

f(in

t));

for

(va

l = 0; va

l < 6

; va

l++)

StackPush(&

intS

tack

, &va

l);

whi

le (

!StackE mpty(&

intS

tack)

)^ {

StackPop(&

intS

tack

, &va

l);

prin

tf("Th

is^ jus

t popped: %d\n"

, va

l);

} StackDispose(&

intStack)

clien }

t.c

5

val intStack

00 00 00 00

00 00 00 01

00 00 00 02

00 00 00 03

00 00 00 04