Mon, 17 Mar 2025 20:44:17 +0100
add examples to map.h documentation
relates to #451
docs/Writerside/topics/map.h.md | file | annotate | diff | comparison | revisions |
--- a/docs/Writerside/topics/map.h.md Sun Mar 16 15:23:45 2025 +0100 +++ b/docs/Writerside/topics/map.h.md Mon Mar 17 20:44:17 2025 +0100 @@ -29,11 +29,159 @@ > This allows you to write clean code without checking for `NULL`-pointer everywhere. > You still need to make sure that the placeholder is replaced with an actual map before inserting elements. -## Overview +## Examples + +```C +#include <stdio.h> +#include <cx/hash_map.h> + +int main() { + CxMap *contacts = cxHashMapCreateSimple(CX_STORE_POINTERS); + + // Build a small phone book + cxMapPut(contacts, "John", "123-0815"); + cxMapPut(contacts, "Jane", "987-4711"); + cxMapPut(contacts, "Michelle", "555-3141"); + cxMapPut(contacts, "Oliver", "000-9999"); + + // Retrieve a phone number + const char *janes_phone = cxMapGet(contacts, "Jane"); + printf("The number of Jane is: %s\n", janes_phone); + + // Update number + cxMapPut(contacts, "Jane", "987-1337"); + + // Remove and retrieve number + cxMapRemoveAndGet(contacts, "Jane", &janes_phone); + printf("The number of Jane was: %s\n", janes_phone); + janes_phone = cxMapGet(contacts, "Jane"); + if (janes_phone == NULL) printf("Jane's number was deleted.\n"); + + // Iterate through the contact list + CxMapIterator iter = cxMapIterator(contacts); + cx_foreach(CxMapEntry *, entry, iter) { + cxstring name = cx_strn(entry->key->data, entry->key->len); + const char *phone = entry->value; + printf("%.*s: %s\n", (int) name.length, name.ptr, phone); + } + + cxMapFree(contacts); + + return 0; +} +``` + +The above example illustrates basic operations with a map. + +In the first part we add several entries to the map. +Then the example shows retrieval, updating, and removal of information. +The last part shows how to iterate over the pairs of the map and how to recover the string from the key. + +In real world situations, however, it is quite unlikely that you will use a map to store string literals. +The next example shows a more realistic program, where it is necessary to store strings based on user input. + +```C +#include <stdio.h> +#include <string.h> +#include <cx/hash_map.h> + +int main() { + // store strings in the map... + CxMap *contacts = cxHashMapCreateSimple(sizeof(cxmutstr)); + // ...which are automatically freed when removed + cxDefineDestructor(contacts, cx_strfree); + + // build a small interactive program + const unsigned buffer_size = 256; + char input[buffer_size]; + bool running = true; + + while (running) { + puts("\n*** Contacts - Menu ***"); + puts("1) Add entry"); + puts("2) Look up entry"); + puts("3) Remove entry"); + puts("4) Show all entries"); + puts("0) Exit"); + fputs("> ", stdout); -<warning> -TODO: example -</warning> + if (fgets(input, buffer_size, stdin)) { + if (input[1] != '\n') { + puts("Please select a menu item.\n"); + } else if (input[0] == '1') { + fputs("Name > ", stdout); + if (fgets(input, buffer_size, stdin)) { + // Copy the name (alternative: use 2nd input buf) + cxmutstr name = cx_strdup( + cx_strn(input, strcspn(input, "\n"))); + fputs("Phone > ", stdout); + if (fgets(input, buffer_size, stdin)) { + // add the entry, note that only the contents + // of the cxmutstr are copied, not the string + // data - therefore we have to call cx_strdup + cxmutstr phone = cx_strdup( + cx_strn(input, strcspn(input, "\n"))); + // note, that we can simply use the cxmutstr + // for the name as key, because cxMapPut uses + // generic selection + cxMapPut(contacts, name, &phone); + } + cx_strfree(&name); + } + } else if (input[0] == '2') { + fputs("Name > ", stdout); + if (fgets(input, buffer_size, stdin)) { + // Look up the name + input[strcspn(input, "\n")] = '\0'; + cxmutstr *phone = cxMapGet(contacts, input); + if (phone == NULL) { + puts("No record."); + } else { + printf("Result: %.*s\n", + (int) phone->length, phone->ptr); + } + } + } else if (input[0] == '3') { + fputs("Name > ", stdout); + if (fgets(input, buffer_size, stdin)) { + // Remove the entry + // Since we registered cx_strfree as destructor, + // the memory is automatically freed + input[strcspn(input, "\n")] = '\0'; + if (cxMapRemove(contacts, input)) { + puts("No such record."); + } else { + puts("Removed."); + } + } + } else if (input[0] == '4') { + // Almost the same iteration loop as above ... + CxMapIterator iter = cxMapIterator(contacts); + cx_foreach(CxMapEntry *, entry, iter) { + cxstring name = cx_strn(entry->key->data, + entry->key->len); + // ... except that here we get cxmutstr* + cxmutstr *phone = entry->value; + printf("%.*s: %.*s\n", + (int) name.length, name.ptr, + (int) phone->length, phone->ptr); + } + } else if (input[0] == '0') { + running = false; + } else { + puts("Please select a menu item.\n"); + } + } else { + running = false; + } + } + + // this will free all remaining strings that are in the map + cxMapFree(contacts); + + return 0; +} +``` > In the following Sections, the type for the key is denoted `KeyType`. > All functions are implemented as generics, so that the following types are supported: