{"id":4208,"date":"2018-11-08T18:29:08","date_gmt":"2018-11-08T16:29:08","guid":{"rendered":"https:\/\/blue.pri.ee\/ttu\/?page_id=4208"},"modified":"2026-06-01T13:00:41","modified_gmt":"2026-06-01T11:00:41","slug":"struct_wrapper_dynamic","status":"publish","type":"page","link":"https:\/\/blue.pri.ee\/ttu\/programming-ii\/code-samples\/struct_wrapper_dynamic\/","title":{"rendered":"struct_wrapper_dynamic"},"content":{"rendered":"<p>The following example shows how to create a wrapper for a dynamically allocated array. This simplifies array access and size management &#8211; i.e. how many elements are stored, for how many is there room for, where is the data?<\/p>\n<p>For testing, an example file with workflow is provided, that can be used for the program&#8217;s input <span class=\"lang:c highlight:0 decode:true crayon-inline\">stdin<\/span> :<\/p>\n<ol>\n<li>An array that can hold two members is created<\/li>\n<li>Data for two members is entered<\/li>\n<li>An attempt is made to extend the array by adding three more members.<\/li>\n<\/ol>\n<p>The result of the third step depends on whether <span class=\"lang:c highlight:0 decode:true crayon-inline \">EXPANDABLE<\/span>\u00a0 macro is set to 1 or 0.<\/p>\n<p>To test with the provided data using stream redirection:<span class=\"lang:sh decode:true crayon-inline\">.\/program_name &lt; test_data.txt<\/span><\/p>\n<pre class=\"toolbar:1 lang:default decode:true\">2\r\n2\r\n0114 Rasmus Aare 38101012210 9.20\r\n0115 Tarmo Waldorf 38909091120 14.20\r\n3\r\n0116 Jane Kask 48511113320 12.20\r\n0117 Aare Kallas 38412124330 7.45\r\n0118 Alexandra Sepp 49105040334 15.00<\/pre>\n<p>The following code is given as source and header file. The previously mentioned\u00a0 <span class=\"lang:c highlight:0 decode:true crayon-inline\">EXPANDABLE<\/span>\u00a0 macro is in the source file. When setting the value to 1, <span class=\"lang:c highlight:0 decode:true crayon-inline\">realloc()<\/span>\u00a0 is used to expand the dynamic array . If it is set to 0, the structure size is fixed by the first prompt.<\/p>\n<p>Expanding the array is done using <span class=\"lang:c highlight:0 decode:true crayon-inline \">(n * 2)<\/span>\u00a0 method for reallocation.<\/p>\n<pre class=\"toolbar:1 lang:c decode:true\" title=\"wrapper.h\">\/**\r\n * File:        wrapper_struct.h\r\n * Author:      Risto Heinsar\r\n * Created:     28.02.2018\r\n * Edited:      01.06.2026\r\n *\r\n * Description: Header containing the Employee struct definition and the wrapper\r\n *              used to manage memory for Employee array\r\n *\/\r\n\r\n#ifndef WRAPPER_STRUCT_H\r\n#define WRAPPER_STRUCT_H\r\n\r\n#include &lt;stdio.h&gt; \/\/ Required for size_t\r\n\r\n#define EID_LEN 12\r\n#define MAX_NAME 256\r\n\r\ntypedef struct\r\n{\r\n    int code;\r\n    char fName[MAX_NAME];\r\n    char lName[MAX_NAME];\r\n    char eID[EID_LEN];\r\n    float wagePerHour;\r\n} Employee;\r\n\r\ntypedef struct\r\n{\r\n    Employee *db;\r\n    size_t limit;\r\n    size_t used;\r\n} EmployeeList;\r\n\r\nvoid AllocateList(EmployeeList *wf);\r\nvoid InsertMembers(EmployeeList *wf);\r\nvoid InsertMembersWithExpandability(EmployeeList *wf);\r\nvoid PrintMembers(EmployeeList wf);\r\nEmployee CreateMember();\r\n\r\n#endif \/\/ WRAPPER_STRUCT_H\r\n<\/pre>\n<pre class=\"toolbar:1 lang:c decode:true\" title=\"wrapper_struct_dynamic.c\">\/**\r\n * File:        wrapper_struct.c\r\n * Author:      Risto Heinsar\r\n * Created:     28.02.2018\r\n * Edited:      01.06.2026\r\n *\r\n * Description: The following example demonstrates two techniques regarding\r\n *              dynamic memory allocation.\r\n * \r\n *              First, a wrapper struct for dynamic array is demonstrated.\r\n *              This helps to keep track of the array size cleanly.\r\n * \r\n *              Second, expanding dynamic memory using (n * 2) strategy is\r\n *              shown, that will greatly improve allocation speed.\r\n *\/\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include \"wrapper_struct.h\"\r\n\r\n\/\/  Use 0 for non-expandable list, \r\n\/\/      1 for expandable using realloc.\r\n#define EXPANDABLE 1\r\n\r\nint main(void)\r\n{\r\n    EmployeeList workForce = {.db    = NULL, \r\n                              .limit = 0, \r\n                              .used  = 0};\r\n    AllocateList(&amp;workForce);\r\n\r\n    if (EXPANDABLE)\r\n    {\r\n        InsertMembersWithExpandability(&amp;workForce);\r\n        InsertMembersWithExpandability(&amp;workForce);\r\n    }\r\n    else\r\n    {\r\n        InsertMembers(&amp;workForce);\r\n        InsertMembers(&amp;workForce);\r\n    }\r\n\r\n    PrintMembers(workForce);\r\n    \r\n    free(workForce.db);\r\n    return 0;\r\n}\r\n\r\n\/**\r\n * Allocate an initial list, mostly for demonstrative purposes and compatibility\r\n * with both methods of inserting members (fixed and expandable)\r\n *\/\r\nvoid AllocateList(EmployeeList *wf)\r\n{\r\n    unsigned n;\r\n    \r\n    printf(\"For many employees is storage required?\\n\");\r\n    scanf(\"%u\", &amp;n);\r\n    \r\n    wf-&gt;db = calloc(n, sizeof(Employee));\r\n    if (wf-&gt;db == NULL)\r\n    {\r\n        perror(\"Error allocating memory\");\r\n        exit(EXIT_FAILURE);\r\n    }\r\n    \r\n    wf-&gt;limit = n;\r\n}\r\n\r\n\/**\r\n * Insert members to the structure array. This is only capable of adding members\r\n * until the array is full. It will also keep track of how many members have \r\n * been added. The array cannot be expanded using this function.\r\n *\/\r\nvoid InsertMembers(EmployeeList *wf)\r\n{\r\n    size_t n;\r\n    \r\n    printf(\"How many employees to add?\\n\");\r\n    scanf(\"%zu\", &amp;n);\r\n        \r\n    \/\/ Detect if employees array can't fit the requested number of employees\r\n    if (n &gt; wf-&gt;limit - wf-&gt;used)\r\n    {\r\n        fprintf(stderr, \"Error! %zu out of %zu slots are in use.\\n\", wf-&gt;used, \r\n                                                                     wf-&gt;limit);\r\n        fprintf(stderr, \"Storage left for %zu slots\\n\", wf-&gt;limit - wf-&gt;used);\r\n        return;\r\n    }\r\n    \r\n    for (size_t i = 0; i &lt; n; i++)\r\n    {\r\n        printf(\"Adding member %zu out of %zu\\n\", i + 1, n);\r\n        *(wf-&gt;db + wf-&gt;used) = CreateMember();\r\n        wf-&gt;used++;\r\n    }\r\n}\r\n\r\n\r\n\/**\r\n * Insert members to the structure array. This function will try to expand\r\n * the dynamically allocated array if possible. If expanding memory fails, \r\n * the program can be allowed to continue.\r\n *\/\r\nvoid InsertMembersWithExpandability(EmployeeList *wf)\r\n{\r\n    size_t n;\r\n\r\n    printf(\"How many employees to add?\\n\");\r\n    scanf(\"%zu\", &amp;n);\r\n\r\n    size_t i = 0;\r\n    while (i &lt; n)\r\n    {\r\n        \/\/ Detect if array is full and needs expanding\r\n        if (wf-&gt;limit &lt;= wf-&gt;used)\r\n        {\r\n            \/\/ let's make the new limit 2x from what we had\r\n            size_t newLimit = 2 * wf-&gt;limit;\r\n            printf(\"Attempting to expand array from %zu to %zu\\n\", wf-&gt;limit,\r\n                                                                   newLimit);\r\n            \/\/ Expand the array memory block\r\n            Employee *pTemp = realloc(wf-&gt;db, sizeof(Employee) * newLimit);\r\n\r\n            \/\/ Handle allocation failure\r\n            if (pTemp == NULL)\r\n            {\r\n                fprintf(stderr, \"Error: Memory allocation failed!\\n\");\r\n                fprintf(stderr, \"Previously allocated data is safe. \");\r\n                fprintf(stderr, \"Allocation exists for %zu items\\n\", wf-&gt;limit);\r\n                break;\r\n            }\r\n\r\n            \/\/ \"sync\" the pointers and update the limit\r\n            wf-&gt;db = pTemp;\r\n            wf-&gt;limit = newLimit;\r\n            printf(\"Allocation success! New limit is %zu\\n\", wf-&gt;limit);\r\n        }\r\n        \r\n        printf(\"Adding member %zu out of %zu\\n\", i + 1, n);\r\n        *(wf-&gt;db + wf-&gt;used) = CreateMember();\r\n        \r\n        wf-&gt;used++;\r\n        i++;\r\n    }\r\n}\r\n\r\n\r\n\/**\r\n * Creates a new struct member with data from user. The struct will be returned\r\n * so it can be added to the appropriate array later using the preferred method.\r\n *\/\r\nEmployee CreateMember()\r\n{\r\n    Employee newEmployee;\r\n    \r\n    \/* static variables are scope limited, but have global lifetime *\/\r\n    static int employeeCode = 0;\r\n    newEmployee.code = employeeCode++;\r\n    \r\n    printf(\"Enter first name:\\n\");\r\n    scanf(\"%s\", newEmployee.fName);\r\n    printf(\"Enter last name:\\n\");\r\n    scanf(\"%s\", newEmployee.lName);\r\n    printf(\"Enter Estonian identification number:\\n\");\r\n    scanf(\"%s\", newEmployee.eID);\r\n    printf(\"Enter wage per hour:\\n\");\r\n    scanf(\"%f\", &amp;newEmployee.wagePerHour);\r\n    return newEmployee;\r\n}\r\n\r\n\r\n\/**\r\n * Prints the list of members in the struct array\r\n *\/\r\nvoid PrintMembers(EmployeeList wf)\r\n{\r\n    printf(\"%zu out of %zu slots are in use\\n\", wf.used, wf.limit);\r\n    \r\n    if (wf.used &lt;= 0)\r\n    {\r\n        return;\r\n    }\r\n    \r\n    printf(\"%7s %12s %15s %15s %6s\\n\", \"code\", \"eID\", \"fName\", \"lName\", \"wage\");\r\n    for (size_t i = 0; i &lt; wf.used; i++)\r\n    {\r\n        printf(\"%7d %12s %15s %15s %6.2f\\n\", (wf.db + i)-&gt;code,\r\n                                             (wf.db + i)-&gt;eID, \r\n                                             (wf.db + i)-&gt;fName, \r\n                                             (wf.db + i)-&gt;lName, \r\n                                             (wf.db + i)-&gt;wagePerHour);\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following example shows how to create a wrapper for a dynamically allocated array. This simplifies array access and size management &#8211; i.e. how many elements are stored, for how many is there room for, where is the data? For testing, an example file with workflow is provided, that can be used for the program&#8217;s &hellip; <a href=\"https:\/\/blue.pri.ee\/ttu\/programming-ii\/code-samples\/struct_wrapper_dynamic\/\" class=\"more-link\">Loe edasi <span class=\"screen-reader-text\">struct_wrapper_dynamic<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":2361,"menu_order":18,"comment_status":"closed","ping_status":"closed","template":"page-templates\/code-width.php","meta":{"footnotes":""},"class_list":["post-4208","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4208","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/comments?post=4208"}],"version-history":[{"count":8,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4208\/revisions"}],"predecessor-version":[{"id":11447,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4208\/revisions\/11447"}],"up":[{"embeddable":true,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/2361"}],"wp:attachment":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/media?parent=4208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}