add examples to map.h documentation

Mon, 17 Mar 2025 20:44:17 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 17 Mar 2025 20:44:17 +0100
changeset 1249
aad755d296a7
parent 1248
fc5e63b04281
child 1250
80a1d63ede19

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:

mercurial