{"id":4645,"date":"2019-11-05T00:38:24","date_gmt":"2019-11-04T22:38:24","guid":{"rendered":"https:\/\/blue.pri.ee\/ttu\/?page_id=4645"},"modified":"2025-04-02T22:08:30","modified_gmt":"2025-04-02T20:08:30","slug":"realloc_base-2","status":"publish","type":"page","link":"https:\/\/blue.pri.ee\/ttu\/programming-ii\/code-samples\/realloc_base-2\/","title":{"rendered":"realloc() partial solution"},"content":{"rendered":"<p>Partial solution to the realloc lab task. Shows how to read entries using realloc function.<\/p>\n<div class=\"su-tabs su-tabs-style-default su-tabs-mobile-stack\" data-active=\"1\" data-scroll-offset=\"0\" data-anchor-in-url=\"no\"><div class=\"su-tabs-nav\"><span class=\"\" data-url=\"\" data-target=\"blank\" tabindex=\"0\" role=\"button\">**ptr: Using double pointers, returning count<\/span><span class=\"\" data-url=\"\" data-target=\"blank\" tabindex=\"0\" role=\"button\">*ptr: Using int pointer, returning struct pointer<\/span><\/div><div class=\"su-tabs-panes\"><div class=\"su-tabs-pane su-u-clearfix su-u-trim\" data-title=\"**ptr: Using double pointers, returning count\">\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">#ifndef REALLOC_EXAMPLE_H\r\n#define REALLOC_EXAMPLE_H\r\n\r\n#define LEN_CUR_CODE 4\r\n#define BUF_LEN 128\r\n#define DEFAULT_INPUT_FILE \"candidates.txt\"\r\n\r\ntypedef struct\r\n{\r\n\tint index;\r\n\tchar *fName;\r\n\tchar *lName;\r\n\tchar curriculum[LEN_CUR_CODE + 1];\r\n\tfloat points;\r\n} Person;\r\n\r\nint ReadList(Person **ppStudentData, char *fileName);\r\nvoid Output(Person *candidates, int n);\r\n\r\n#endif \/\/REALLOC_EXAMPLE_H\r\n<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"lang:c decode:true\" title=\"realloc_base.c\">\/**\r\n * File:        realloc_example.c\r\n * Author:      Risto Heinsar\r\n * Created:     19.03.2014\r\n * Edited:      02.04.2024\r\n *\r\n * Description: The following code will demonstrate how to properly use realloc\r\n *              to expand the memory that's already been allocated.\r\n *              The file is a part of the IAX0584 lab task and provided as a\r\n *              partial lab solution. It implements the less efficient (n + 1)\r\n *              expansion strategy which is considered slow in real world.\r\n *\/\r\n\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n#include \"realloc_example.h\"\r\n\r\nint main(void)\r\n{\r\n    char fileName[] = DEFAULT_INPUT_FILE;\r\n    Person *list = NULL; \/\/ nothing here at present\r\n\r\n    \/\/ read the file\r\n    int candidateCnt = ReadList(&amp;list, fileName);\r\n\r\n    Output(list, candidateCnt);\r\n\r\n    \/\/ NB! The sample code does not include freeing the memory.\r\n    \/\/ Everything that you allocate for must be freed before exiting the program!\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n\r\n\/**\r\n * Description:     Function to read data from a file. During this, a dynamic\r\n *                  struct array will be created and expanded using realloc()\r\n * Parameters:      Double pointer a struct, address of the allocated array will\r\n *                  be stored there. NB! The memory comes from the heap!\r\n *                  Pointer to a string with the file name\r\n * Return value:    Returns an integer with the number of lines read from the file\r\n * Prerequisites:   Datafile fields are separated with either a space\r\n *                  or a line change, without faulty data, max length of a string\r\n *                  is up to (LEN_NAME_MAX - 1) and no spaces in strings.\r\n *\/\r\nint ReadList(Person **ppStudentData, char *fileName)\r\n{\r\n    \/\/ Opening the file and checking if it opened\r\n    FILE *fp = fopen(fileName, \"r\");\r\n    if (fp == NULL)\r\n    {\r\n        perror(\"Error opening input file:\");\r\n        exit(EXIT_FAILURE);\r\n    }\r\n    \r\n    \/\/ Main data pointer that's used locally\r\n    Person *pData = NULL;\r\n    \r\n    \/\/ Temporary buffers for data during reading\r\n    char bufFName[BUF_LEN], bufLName[BUF_LEN], bufCurrCode[BUF_LEN];\r\n    int bufInd;\r\n    float bufPoints;\r\n    \r\n    \/\/ initialize the line count to 0 - nothing read yet\r\n    int count = 0;\r\n    \r\n    \/\/ start by reading one line at a time into the buffers (no memory yet)\r\n    while (fscanf(fp, \"%d %s %s %s %f\", &amp;bufInd, bufFName, bufLName, \r\n                                         bufCurrCode, &amp;bufPoints) == 5)\r\n    {\r\n        \/\/ if a line was successfully read, expanding the memory by 1. Using a \r\n        \/\/ temporary pointer to avoid losing memory address when realloc fails\r\n        \/\/ during reading (returns NULL, old pointer valid)\r\n        Person *pTemp = realloc(pData, sizeof(Person) * (unsigned)(count + 1));\r\n\r\n        \/\/ Check if it failed\r\n        if (pTemp == NULL)\r\n        {\r\n            \/\/ TODO: Error behavior!\r\n            \/\/ I.e. if you want to free everything and exit, you should free:\r\n            \/\/       - all the first names already allocated\r\n            \/\/       - all the last names allocated\r\n            \/\/       - the struct itself\r\n            \r\n            \/\/ then close the file and exit\r\n            fclose(fp);\r\n            exit(EXIT_FAILURE);\r\n        }\r\n\r\n        \/\/ Make both pointers point at the memory location\r\n        pData = pTemp;\r\n\r\n        \/\/ Copy data from buffers to the struct array\r\n\r\n        \/\/ Now allocate + copy data for the string buffers\r\n        \/\/ Note 1: Both pData[i].member or (pData + i)-&gt;member can be used\r\n        \/\/ Note 2: strdup() combines strlen, malloc and strcpy\r\n        (pData + count)-&gt;fName = strdup(bufFName);\r\n        if ((pData + count)-&gt;fName == NULL)\r\n        {\r\n            \/\/ TODO: error behavior here\r\n        }\r\n\r\n        \/\/ numbers can be copied directly, there already is memory in the struct\r\n        (pData + count)-&gt;points = bufPoints;\r\n\r\n        \/\/ another line successfully read\r\n        count++;\r\n    }\r\n    \/\/ using the dbl pointer to make sure main() knows where my struct array is\r\n    *ppStudentData = pData;\r\n\r\n    \/\/ close the file\r\n    fclose(fp);\r\n\r\n    \/\/ and return the number of lines read\r\n    return count;\r\n}\r\n\r\n\r\n\/**\r\n * Description:    Prints out the list of candidates who applied, one per line.\r\n * Parameters:     candidateList - pointer to the list of candidates\r\n *                 n - number of candidates in the list\r\n * Return value:   none\r\n *\/\r\nvoid Output(Person *candidates, int n)\r\n{\r\n    printf(\"The candidates are:\\n\");\r\n    for (int i = 0; i &lt; n; i++)\r\n    {\r\n        \/\/ the fields which were incomplete are not printed at this point. \r\n        printf(\"%d %s &lt;last name&gt; &lt;curriculum&gt; %.2f\\n\", (candidates + i)-&gt;index,\r\n                                                        (candidates + i)-&gt;fName,\r\n                                                        (candidates + i)-&gt;points);\r\n    }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<div class=\"su-tabs-pane su-u-clearfix su-u-trim\" data-title=\"*ptr: Using int pointer, returning struct pointer\">\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">#ifndef REALLOC_EXAMPLE_H\r\n#define REALLOC_EXAMPLE_H\r\n\r\n#define LEN_CUR_CODE 4\r\n#define BUF_LEN 128\r\n#define DEFAULT_INPUT_FILE \"candidates.txt\"\r\n\r\ntypedef struct\r\n{\r\n\tint index;\r\n\tchar *fName;\r\n\tchar *lName;\r\n\tchar curriculum[LEN_CUR_CODE + 1];\r\n\tfloat points;\r\n} Person;\r\n\r\nPerson * ReadList(int *cnt, char *fileName);\r\nvoid Output(Person *candidates, int n);\r\n\r\n#endif\r\n<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"lang:c decode:true\" title=\"realloc_base.c\">\/**\r\n * File:        realloc_example.c\r\n * Author:      Risto Heinsar\r\n * Created:     19.03.2014\r\n * Edited:      02.04.2024\r\n *\r\n * Description: The following code will demonstrate how to properly use realloc\r\n *              to expand the memory that's already been allocated.\r\n *              The file is a part of the IAX0584 lab task and provided as a\r\n *              partial lab solution. It implements the less efficient (n + 1)\r\n *              expansion strategy which is considered slow in real world.\r\n *\/\r\n\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n#include \"realloc_example.h\"\r\n\r\nint main(void)\r\n{\r\n    char fileName[] = DEFAULT_INPUT_FILE;\r\n    int total;\r\n\r\n    \/\/ read the file\r\n    Person *candidates = ReadList(&amp;total, fileName);\r\n\r\n    Output(candidates, total);\r\n\r\n    \/\/ NB! The sample code does not include freeing the memory.\r\n    \/\/ Everything that you allocate for must be freed before exiting the program!\r\n\r\n    return EXIT_SUCCESS;\r\n}\r\n\r\n\/**\r\n * Description:     Function to read data from a file. During this, a dynamic\r\n *                  struct array will be created and expanded using realloc()\r\n *                  Pointer to a string with the file name\r\n * Parameters:      Pointer to an integer where to store the candidate count\r\n *                  Pointer to a string with the file name\r\n * Return value:    Returns the structure pointer where the memory was allocated\r\n *                  and data stored at.\r\n * Prerequisites:   Datafile fields are separated with either a space\r\n *                  or a line change, without faulty data, max length of a string\r\n *                  is up to (LEN_NAME_MAX - 1) and no spaces in strings.\r\n *\/\r\nPerson * ReadList(int *cnt, char *fileName)\r\n{\r\n    \/\/ Opening the file and checking if it opened\r\n    FILE *fp = fopen(fileName, \"r\");\r\n    if (fp == NULL)\r\n    {\r\n        perror(\"Error opening input file:\");\r\n        exit(EXIT_FAILURE);\r\n    }\r\n    \/\/ Main data pointer that's used locally\r\n    Person *pData = NULL;\r\n    \r\n    \/\/ Temporary buffers for data during reading\r\n    char bufFName[BUF_LEN], bufLName[BUF_LEN], bufCurrCode[BUF_LEN];\r\n    int bufInd;\r\n    float bufPoints;\r\n    \r\n    \/\/ Initialize the line count to 0 - nothing read yet\r\n    int count = 0;\r\n    \r\n    \/\/ start by reading one line at a time into the buffers (no memory yet)\r\n    while (fscanf(fp, \"%d %s %s %s %f\", &amp;bufInd, bufFName, bufLName, \r\n                                         bufCurrCode, &amp;bufPoints) == 5)\r\n    {\r\n        \/\/ if a line was successfully read, expanding the memory by 1. Using a \r\n        \/\/ temporary pointer to avoid losing memory address when realloc fails\r\n        \/\/ during reading (returns NULL, old pointer valid)\r\n        Person *pTemp = realloc(pData, sizeof(Person) * (unsigned)(count + 1));\r\n\r\n        \/\/ Check if it failed\r\n        if (pTemp == NULL)\r\n        {\r\n            \/\/ TODO: Error behavior!\r\n            \/\/ I.e. if you want to free everything and exit, you should free:\r\n            \/\/       - all the first names already allocated\r\n            \/\/       - all the last names allocated\r\n            \/\/       - the struct itself\r\n            \r\n            \/\/ then close the file and exit\r\n            fclose(fp);\r\n            exit(EXIT_FAILURE);\r\n        }\r\n\r\n        \/\/ Make both pointers point at the memory location\r\n        pData = pTemp;\r\n\r\n        \/\/ Copy data from buffers to the struct array\r\n\r\n        \/\/ Now allocate + copy data for the string buffers\r\n        \/\/ Note 1: Both pData[i].member or (pData + i)-&gt;member can be used\r\n        \/\/ Note 2: strdup() combines strlen, malloc and strcpy\r\n        (pData + count)-&gt;fName = strdup(bufFName);\r\n        if ((pData + count)-&gt;fName == NULL)\r\n        {\r\n            \/\/ TODO: error behavior here\r\n        }\r\n\r\n        \/\/ numbers can be copied directly, there already is memory in the struct\r\n        (pData + count)-&gt;points = bufPoints;\r\n\r\n        \/\/ another line successfully read\r\n        count++;\r\n    }\r\n    \r\n    \/\/ using a pointer to store the number of lines that were read\r\n    *cnt = count;\r\n \r\n    \/\/ now just close the file\r\n    fclose(fp);\r\n \r\n    \/\/ and return the pointer to the struct array we just allocated\r\n    return pData;\r\n}\r\n\r\n\r\n\/**\r\n * Description:    Prints out the list of candidates who applied, one per line.\r\n * Parameters:     candidateList - pointer to the list of candidates\r\n *                 n - number of candidates in the list\r\n * Return value:   none\r\n *\/\r\nvoid Output(Person *candidates, int n)\r\n{\r\n    printf(\"The candidates are:\\n\");\r\n    for (int i = 0; i &lt; n; i++)\r\n    {\r\n        \/\/ the fields which were incomplete are not printed at this point. \r\n        printf(\"%d %s &lt;last name&gt; &lt;curriculum&gt; %.2f\\n\", (candidates + i)-&gt;index,\r\n                                                        (candidates + i)-&gt;fName,\r\n                                                        (candidates + i)-&gt;points);\r\n    }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Partial solution to the realloc lab task. Shows how to read entries using realloc function.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":2361,"menu_order":15,"comment_status":"closed","ping_status":"closed","template":"page-templates\/code-width-wide.php","meta":{"footnotes":""},"class_list":["post-4645","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4645","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=4645"}],"version-history":[{"count":3,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4645\/revisions"}],"predecessor-version":[{"id":9979,"href":"https:\/\/blue.pri.ee\/ttu\/wp-json\/wp\/v2\/pages\/4645\/revisions\/9979"}],"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=4645"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}