Partial solution to the realloc lab task. Shows how to read entries using realloc function.
**ptr: Using double pointers, returning count*ptr: Using int pointer, returning struct pointer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef REALLOC_SAMPLE_H #define REALLOC_SAMPLE_H #define LEN_CUR_CODE 5 #define LEN_NAME_MAX 32 #define DEFAULT_INPUT_FILE "candidates.txt" typedef struct { int index; char *fName; char *lName; char curriculum[LEN_CUR_CODE]; float points; } person; int ReadList(person **pData, char *fileName); void Output(person *candidatesList, int n); #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
/** * File: realloc_basecode.c * Author: Risto Heinsar * Created: 19.03.2014 * Edited: 22.03.2022 * * Description: The following code will demonstrate how to properly use realloc * to expand the memory that's already been allocated. * The file is a part of the IAX0584 lab task and provided as a * partial lab solution. It implements the less efficient (n + 1) * expansion strategy which is considered slow in real world. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "realloc_sample.h" int main(void) { char fileName[] = DEFAULT_INPUT_FILE; person *candidates = NULL; // nothing here at present int total; // read the file total = ReadList(&candidates, fileName); Output(candidates, total); // NB! The sample code does not include freeing the memory. // Everything that you allocate for must be freed before exiting the program! return EXIT_SUCCESS; } /** * Description: Function to read data from a file. During this, a dynamic * struct array will be created and expanded using realloc() * Parameters: Double pointer a struct, address of the allocated array will * be stored there. NB! The memory comes from the heap! * Pointer to a string with the file name * Return value: Returns an integer with the number of lines read from the file * Prerequisites: Datafile fields are separated with either a space * or a line change, without faulty data, max length of a string * is up to (LEN_NAME_MAX - 1) and no spaces in strings. */ int ReadList(person **pData, char *fileName) { // line counter and temporary variable (buffer) for index and points int count, index; float points; // temporary buffers for strings char fName[LEN_NAME_MAX], lName[LEN_NAME_MAX], curriculum[LEN_CUR_CODE]; // my main pointer that will keep the address of the allocated array person *pArr = NULL; // temporary pointer that i'm using to theck the return value of realloc() person *pTemp = NULL; // Opening the file and checking if it opened FILE *fp = fopen(fileName, "r"); if (fp == NULL) { perror("Error opening input file:"); exit(EXIT_FAILURE); } // initialize the line count to 0 - nothing read yet count = 0; // start by reading one line at a time into the buffers (no memory yet) while (fscanf(fp, "%d %s %s %s %f", &index, fName, lName, curriculum, &points) == 5) { // if a line was successfully read, expanding the memory by 1. Using // different pointers so i wouldn't lose the data location if expansion // fails and a NULL ptr is returned. pTemp = realloc(pArr, sizeof(person) * (count + 1)); // Check if it failed if (pTemp == NULL) { // TODO: Error behavior! // E.g. if you ant to free everything and exit, you should free: // - all the first names already allocated // - all the last names allocated // - the struct itself // then close the file and exit fclose(fp); exit(EXIT_FAILURE); } // expanding the memory area was successful, "unifying" the pointers // in case my data was moved and start copying the buffers into my // main struct array pArr = pTemp; // giving memory to the data field inside of the struct, // For strings we can use strdup to simplyfy this. We could also use // malloc + strcpy // It is advised to make a function out of this, especially if there // are many data fields! E.g. in Homework 2. (pArr + count)->fName = strdup(fName); if ((pArr + count)->fName == NULL) { // TODO: error behavior here } // numbers can be copied directly, there already is memory in the struct (pArr + count)->points = points; // another line successfully read count++; } // using the dbl pointer to make sure main() knows where my struct array is *pData = pArr; // close the file fclose(fp); // and return the number of lines read return count; } /** * Description: Prints out the list of candidates who applied, one per line. * Parameters: candidateList - pointer to the list of candidates * n - number of candidates in the list * Return value: none */ void Output(person *candidates, int n) { int i; printf("The candidates are:\n"); for (i = 0; i < n; i++) { // the fields which were incomplete are not printed at this point. printf("%d %s <last name> <curriculum> %.2f\n", (candidates + i)->index, (candidates + i)->fName, (candidates + i)->points); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef REALLOC_SAMPLE_H #define REALLOC_SAMPLE_H #define LEN_CUR_CODE 5 #define LEN_NAME_MAX 32 #define DEFAULT_INPUT_FILE "candidates.txt" typedef struct { int index; char *fName; char *lName; char curriculum[LEN_CUR_CODE]; float points; } person; person * ReadList(int *n, char *fileName); void Output(person *candidatesList, int n); #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
/** * File: realloc_basecode.c * Author: Risto Heinsar * Created: 19.03.2014 * Edited: 22.03.2022 * * Description: The following code will demonstrate how to properly use realloc * to expand the memory that's already been allocated. * The file is a part of the IAX0584 lab task and provided as a * partial lab solution. It implements the less efficient (n + 1) * expansion strategy which is considered slow in real world. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "realloc_sample.h" int main(void) { char fileName[] = DEFAULT_INPUT_FILE; person *candidates = NULL; // nothing here at present int total; // read the file candidates = ReadList(&total, fileName); Output(candidates, total); // NB! The sample code does not include freeing the memory. // Everything that you allocate for must be freed before exiting the program! return EXIT_SUCCESS; } /** * Description: Function to read data from a file. During this, a dynamic * struct array will be created and expanded using realloc() * Pointer to a string with the file name * Parameters: Pointer to an integer where to store the candidate count * Pointer to a string with the file name * Return value: Returns the structure pointer where the memory was allocated * and data stored at. * Prerequisites: Datafile fields are separated with either a space * or a line change, without faulty data, max length of a string * is up to (LEN_NAME_MAX - 1) and no spaces in strings. */ person * ReadList(int *n, char *fileName) { // line counter and temporary variable (buffer) for index and points int count, index; float points; // temporary buffers for strings char fName[LEN_NAME_MAX], lName[LEN_NAME_MAX], curriculum[LEN_CUR_CODE]; // my main pointer that will keep the address of the allocated array person *pArr = NULL; // temporary pointer that i'm using to theck the return value of realloc() person *pTemp = NULL; // Opening the file and checking if it opened FILE *fp = fopen(fileName, "r"); if (fp == NULL) { perror("Error opening input file:"); exit(EXIT_FAILURE); } // initialize the line count to 0 - nothing read yet count = 0; // start by reading one line at a time into the buffers (no memory yet) while (fscanf(fp, "%d %s %s %s %f", &index, fName, lName, curriculum, &points) == 5) { // if a line was successfully read, expanding the memory by 1. Using // different pointers so i wouldn't lose the data location if expansion // fails and a NULL ptr is returned. pTemp = realloc(pArr, sizeof(person) * (count + 1)); // Check if it failed if (pTemp == NULL) { // TODO: Error behavior! // E.g. if you ant to free everything and exit, you should free: // - all the first names already allocated // - all the last names allocated // - the struct itself // then close the file and exit fclose(fp); exit(EXIT_FAILURE); } // expanding the memory area was successful, "unifying" the pointers // in case my data was moved and start copying the buffers into my // main struct array pArr = pTemp; // giving memory to the data field inside of the struct, // For strings we can use strdup to simplyfy this. We could also use // malloc + strcpy // It is advised to make a function out of this, especially if there // are many data fields! E.g. in Homework 2. (pArr + count)->fName = strdup(fName); if ((pArr + count)->fName == NULL) { // TODO: error behavior here } // numbers can be copied directly, there already is memory in the struct (pArr + count)->points = points; // another line successfully read count++; } // using a pointer to store the number of lines that were read *n = i; // now just close the file fclose(fp); // and return the pointer to the struct array we just allocated return pArr; } /** * Description: Prints out the list of candidates who applied, one per line. * Parameters: candidateList - pointer to the list of candidates * n - number of candidates in the list * Return value: none */ void Output(person *candidates, int n) { int i; printf("The candidates are:\n"); for (i = 0; i < n; i++) { // the fields which were incomplete are not printed at this point. printf("%d %s <last name> <curriculum> %.2f\n", (candidates + i)->index, (candidates + i)->fName, (candidates + i)->points); } } |