This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | Last revision Both sides next revision | ||
adt_example [2014/11/12 11:01] czerny |
adt_example [2014/11/12 11:52] czerny |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== StringList ADT ===== | + | ===== StringSet ADT ===== |
I want to give a simple example about creating **a**bstract **d**ata **t**ypes in Pelles C. | I want to give a simple example about creating **a**bstract **d**ata **t**ypes in Pelles C. | ||
Line 8: | Line 8: | ||
Therefore the implementor of an ADT writes an header file, the user may include. | Therefore the implementor of an ADT writes an header file, the user may include. | ||
- | In this example we will build a string list. We declare the ADT type name as: | + | In this example we will build a string set. We declare the ADT type name as: |
+ | <code c> | ||
+ | typedef struct _STRSET *STRSET; | ||
+ | </code> | ||
+ | |||
+ | 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. | ||
+ | |||
+ | <code c> | ||
+ | STRSET StrSetInit(void); | ||
+ | void StrSetFree(STRSET ss); | ||
+ | </code> | ||
+ | |||
+ | 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. | ||
+ | |||
+ | <code c> | ||
+ | void StrSetClear(STRSET ss); | ||
+ | int StrSetSize(STRSET ss); | ||
+ | </code> | ||
+ | |||
+ | The whole header file ''strset.h'' is: | ||
+ | |||
+ | <code c> | ||
+ | #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 | ||
+ | </code> | ||
+ | |||
+ | The user now is able to use the ADT: | ||
+ | |||
+ | <code c> | ||
+ | #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; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | 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'': | ||
+ | |||
+ | <code 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); } | ||
+ | </code> | ||
+ | |||
+ | As you can see, the secret struct | ||
+ | |||
+ | <code c> | ||
+ | struct _STRSET { | ||
+ | HDPA h; | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | 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 library has to be 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 [[http://forum.pellesc.de/|Pelles C forum]] to ask. |