{"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":"2024-02-13T13:54:09","modified_gmt":"2024-02-13T11:54:09","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 to another structure, which helps to manage the size of a structure &#8211; how many elements are in total and for how many is there room for? Wrapper structure holds those numbers and additionally it holds the pointer to the structure array which we allocate dynamically.<\/p>\n<p>To test the program workflow, you have been provided with a sample data file. With the sample data, it creates a structure that can hold 2 members. Then it says it wishes to insert two members and enters the details for those. After this, it attempts to increase it by 3 new data lines. Depending on the implementation used, the result will differ. To try out the test data, use stream redirection (<span class=\"lang:sh decode:true crayon-inline\">.\/program &lt; test_data.txt<\/span>\u00a0)<\/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 files are given: .c file and the header file. There&#8217;s a macro in the codefile called EXPANDABLE, which value decides if the structure can be resized during reading or not. When setting the value to 1, it uses realloc() to expand the memory area. If it is set to 0, the structure size is fixed and cannot be increased.<\/p>\n<p>The expanding is done with the principle, that each time the amount of memory is increased by 2x<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"toolbar:1 lang:c decode:true\" title=\"wrapper.h\">#ifndef WRAPPER_H\r\n#define WRAPPER_H\r\n\r\n#define EID_LEN 12\r\n#define MAX_NAME 2511\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    unsigned limit;\r\n    unsigned used;\r\n} employee_list;\r\n\r\nvoid AllocateList(employee_list *wf);\r\nvoid InsertMembers(employee_list *wf);\r\nvoid InsertMembersWithExpandability(employee_list *wf);\r\nvoid printMembers(employee_list wf);\r\nemployee CreateMember();\r\n\r\n#endif \/\/ WRAPPER_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:      13.02.2024\r\n *\r\n * Description: The following code will demonstrate a couple of hints on allocating\r\n *              memory in C.\r\n *              First of all, it will demonstrate the use of a wrapper structure\r\n *              which will give better control over size management. In this case,\r\n *              it will track how many memory slots are in use and how many are\r\n *              there in total. This allows to keep the data neatly together\r\n *              and avoid array overflows.\r\n *              Secondly, this code also demonstrates a possibility to safely\r\n *              expand the storage using reallocation. The reallocate step is 2x\r\n *              of what it was previously, so it would be more optimal in speed.\r\n *\/\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include \"wrapper.h\"\r\n\r\n\/\/  Use 0 for non-expandable list, 1 for expandable using realloc.\r\n#define EXPANDABLE 1\r\n\r\nint main(void)\r\n{\r\n    employee_list workForce = {NULL, 0, 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(employee_list *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 = (employee *)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 been\r\n * added. The array cannot be expanded using this function\r\n *\/\r\nvoid InsertMembers(employee_list *wf)\r\n{\r\n    unsigned n;\r\n    \r\n    printf(\"How many employees to add?\\n\");\r\n    scanf(\"%u\", &amp;n);\r\n    \r\n    if (n &lt;= wf-&gt;limit - wf-&gt;used)\r\n    {\r\n        for (int i = 0; i &lt; n; i++)\r\n        {\r\n            printf(\"Adding member %d out of %d\\n\", i + 1, n);\r\n            *(wf-&gt;db + wf-&gt;used) = CreateMember();\r\n            wf-&gt;used++;\r\n        }\r\n    }\r\n    else\r\n    {\r\n        printf(\"Error! %d out of %d slots are in use. Storage left for %d \"\r\n               \"Employees\\n\", wf-&gt;used, wf-&gt;limit, wf-&gt;limit - wf-&gt;used);\r\n    }\r\n\r\n}\r\n\r\n\/**\r\n * Function to create a new struct member with data. 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    printf(\"Enter employee code:\\n\");\r\n    scanf(\"%d\", &amp;newEmployee.code);\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 * Prints the list of members in the struct array\r\n *\/\r\nvoid printMembers(employee_list wf)\r\n{\r\n    printf(\"%d out of %d slots are in use\\n\", wf.used, wf.limit);\r\n    printf(\"%7s %12s %15s %15s %6s\\n\", \"code\", \"eID\", \"fName\", \"lName\", \"wage\");\r\n    \r\n    for (int 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, (wf.db + i)-&gt;fName, (wf.db + i)-&gt;lName,\r\n               (wf.db + i)-&gt;wagePerHour);\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 it is possible. The reallocate will be done\r\n * safely. If for some reason the expansion fails, the program can be allowed to\r\n * continue\r\n *\/\r\nvoid InsertMembersWithExpandability(employee_list *wf)\r\n{\r\n    unsigned n;\r\n\r\n    printf(\"How many employees to add?\\n\");\r\n    scanf(\"%u\", &amp;n);\r\n\r\n    int i = 0;\r\n    while (i &lt; n)\r\n    {\r\n        \/\/ first lets create some code that detects if array is full\r\n        if (wf-&gt;limit == wf-&gt;used)\r\n        {\r\n            \/\/ let's make the new limit 2x from what we had\r\n            int newLimit = 2 * wf-&gt;limit;\r\n            printf(\"We ran out of memory. Trying to expand array from %d to %d\\n\",\r\n                   wf-&gt;limit, newLimit);\r\n\r\n            \/\/ reallocate the new memory\r\n            employee *pTemp = realloc(wf-&gt;db, sizeof(employee) * newLimit);\r\n\r\n            \/\/ check if we were successful\r\n            if (pTemp != NULL)\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 %d\\n\", wf-&gt;limit);\r\n            }\r\n            else\r\n            {\r\n                printf(\"Allocation failed. Old limit of %d is being used\\n\",\r\n                       wf-&gt;limit);\r\n            }\r\n        }\r\n\r\n        \/\/ Check if we are have capacity to write new data\r\n        if (wf-&gt;used &lt; wf-&gt;limit)\r\n        {\r\n            printf(\"Adding member %d out of %d\\n\", i + 1, n);\r\n            *(wf-&gt;db + wf-&gt;used) = CreateMember();\r\n            wf-&gt;used++;\r\n            i++;\r\n        }\r\n        else\r\n        {\r\n            printf(\"Unfortunately the program ran out of memory.\\n\"\r\n                   \"Expansion of the employee list has been aborted\\n\"\r\n                   \"You can continue with what you have so far\\n\");\r\n            break;\r\n        }\r\n\r\n    }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following example shows how to create a wrapper to another structure, which helps to manage the size of a structure &#8211; how many elements are in total and for how many is there room for? Wrapper structure holds those numbers and additionally it holds the pointer to the structure array which we allocate dynamically. &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":1,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4208\/revisions"}],"predecessor-version":[{"id":9232,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4208\/revisions\/9232"}],"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}]}}