StringSet ADT

I want to give a simple example about creating abstract data types in Pelles C.

This example could be very much expanded. But I tried to leave it as simple as possible to show the principle case.

The user should see the ADT as a black box. He has not to know anything about internal structures nor the implementation of the ADT. All he knows and should use is the name of the ADT and its exported functions.

Therefore the implementor of an ADT writes an header file, the user may include.

In this example we will build a string set. We declare the ADT type name as:

typedef struct _STRSET *STRSET;

All the user can see is, that STRSET is a pointer to an unknown struct _STRSET.

We will provide a set of access functions. First there are two functions who serve as cunstructors and destructores of the ADT. StrSetInit() creates an emty string set and StrSetFree() frees the string set.

STRSET	StrSetInit(void);
void	StrSetFree(STRSET ss);

We further provide some functions to insert a string in the ADT: StrSetInsert() and to retrieve its address: StrSetGetPtr().

We also add some utility functions. StrSetSize() returns the number of strings in the set and StrSetClear() deletes all the strings in the set, but not the string set itself.

void	StrSetClear(STRSET ss);
int	StrSetSize(STRSET ss);

The whole header file strset.h is:

#ifndef STRSET_H
#define STRSET_H
 
typedef struct _STRSET *STRSET;
 
STRSET	StrSetInit(void);
void	StrSetClear(STRSET ss);
void	StrSetFree(STRSET ss);
int	StrSetInsert(STRSET ss, int nPosition, char *s);
int	StrSetSize(STRSET ss);
char*	StrSetGetPtr(STRSET ss, int nPosition);
 
#endif // STRSET_H

The user now is able to use the ADT:

#include <stdio.h>
#include <string.h>
#include "strset.h"
 
char *input(char *b)
{
	printf("> ");
	scanf("%s", b);
	return b;
}
 
int main(int argc, char *argv[])
{
	int i=0;
	char buf[100] = "";				// declare a temporary buffer
	STRSET	S = StrSetInit();			// declare the string set
 
	while (strcmp(input(buf), "quit")) 
		StrSetInsert(S, i++, buf);		// insert the string in the set
 
	for (i=0; i<StrSetSize(S); i++)			// loop over all the strings in the set
		puts(StrSetGetPtr(S, i));		// get and display each string
 
	StrSetFree(S);					// free the string set
	return 0;
}

Ok! That is all from the users point of view!

However, the implementor has to create the ADT. He does this in a separate module strset.c which could be compiled to a static library, to hit its content.

To perform this task we will use the DPA functions in COMCTL32.lib.

Here is strset.c:

#include <windows.h>
#include <commctrl.h>
#include "strset.h"
 
#pragma  comment(lib, "comctl32.lib")
 
struct _STRSET {
	HDPA h;
};
 
STRSET StrSetInit(void)
{
	STRSET ss = malloc(sizeof(struct _STRSET));
 
	if (ss) ss->h = DPA_Create(10);
	return ss;
}
 
void StrSetClear(STRSET ss)
{
	if (ss) 
		for (int i=0; i<DPA_GetPtrCount(ss->h); i++) {
			free(DPA_GetPtr(ss->h, i));
			DPA_DeletePtr(ss->h, i);
		}
}
 
void StrSetFree(STRSET ss)
{
	if (ss) {
		StrSetClear(ss);
		free(ss);
	}
}
 
int StrSetInsert(STRSET ss, int nPosition, char *s)
{
	char *b = NULL;
 
	if (ss && s) {
		b = malloc(strlen(s)+1);
		strcpy(b,s);
		return DPA_InsertPtr(ss->h, nPosition, b);
	} return -1;
}
 
int StrSetSize(STRSET ss) { return DPA_GetPtrCount(ss->h); }
 
char *StrSetGetPtr(STRSET ss, int nPosition) { return DPA_GetPtr(ss->h, nPosition); }

As you can see, the secret struct

struct _STRSET {
	HDPA h;
};

is very simple in this case. It only holds a DPA handle.

Because the COMCTL32.LIB is needed, we instruct the linker to link against it, with the #pragma directive. So our user has not to know what additional libraries are used.

All our ADT functions with the exception of StrSetInit() use a first parameter of type STRSET. And all this access functions have to verify that this parameter is valid (not NULL).

If you have any questions? Use the Pelles C forum to ask.