See on osaline lahendus realloc() tunnitööle. NB! Jälgi kommentaare, mitmetes kohtades on vaja teha täiendusi.
**ptr: lahendus, mis edastab struktuuri topeltviidana ja tagastab ridade arvu*ptr: Lahendus, mis edastab ridade arvu viida abil ning tagastab viida andmestruktuurile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef REALLOC_EXAMPLE_H #define REALLOC_EXAMPLE_H #define LEN_CUR_CODE 4 #define BUF_LEN 128 #define DEFAULT_INPUT_FILE "candidates.txt" typedef struct { int index; char *fName; char *lName; char curriculum[LEN_CUR_CODE + 1]; float points; } Person; int ReadList(Person **ppStudentData, char *fileName); void Output(Person *candidates, int n); #endif //REALLOC_EXAMPLE_H |
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 |
/** * File: realloc_example.c * Author: Risto Heinsar * Created: 19.03.2014 * Edited: 02.04.2024 * * 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_example.h" int main(void) { char fileName[] = DEFAULT_INPUT_FILE; Person *list = NULL; // nothing here at present // read the file int candidateCnt = ReadList(&list, fileName); Output(list, candidateCnt); // 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 **ppStudentData, char *fileName) { // Opening the file and checking if it opened FILE *fp = fopen(fileName, "r"); if (fp == NULL) { perror("Error opening input file:"); exit(EXIT_FAILURE); } // Main data pointer that's used locally Person *pData = NULL; // Temporary buffers for data during reading char bufFName[BUF_LEN], bufLName[BUF_LEN], bufCurrCode[BUF_LEN]; int bufInd; float bufPoints; // initialize the line count to 0 - nothing read yet int count = 0; // start by reading one line at a time into the buffers (no memory yet) while (fscanf(fp, "%d %s %s %s %f", &bufInd, bufFName, bufLName, bufCurrCode, &bufPoints) == 5) { // if a line was successfully read, expanding the memory by 1. Using a // temporary pointer to avoid losing memory address when realloc fails // during reading (returns NULL, old pointer valid) Person *pTemp = realloc(pData, sizeof(Person) * (unsigned)(count + 1)); // Check if it failed if (pTemp == NULL) { // TODO: Error behavior! // I.e. if you want 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); } // Make both pointers point at the memory location pData = pTemp; // Copy data from buffers to the struct array // Now allocate + copy data for the string buffers // Note 1: Both pData[i].member or (pData + i)->member can be used // Note 2: strdup() combines strlen, malloc and strcpy (pData + count)->fName = strdup(bufFName); if ((pData + count)->fName == NULL) { // TODO: error behavior here } // numbers can be copied directly, there already is memory in the struct (pData + count)->points = bufPoints; // another line successfully read count++; } // using the dbl pointer to make sure main() knows where my struct array is *ppStudentData = pData; // 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) { printf("The candidates are:\n"); for (int 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_EXAMPLE_H #define REALLOC_EXAMPLE_H #define LEN_CUR_CODE 4 #define BUF_LEN 128 #define DEFAULT_INPUT_FILE "candidates.txt" typedef struct { int index; char *fName; char *lName; char curriculum[LEN_CUR_CODE + 1]; float points; } Person; Person * ReadList(int *cnt, char *fileName); void Output(Person *candidates, 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 |
/** * File: realloc_example.c * Author: Risto Heinsar * Created: 19.03.2014 * Edited: 02.04.2024 * * 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_example.h" int main(void) { char fileName[] = DEFAULT_INPUT_FILE; int total; // read the file Person *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 *cnt, char *fileName) { // Opening the file and checking if it opened FILE *fp = fopen(fileName, "r"); if (fp == NULL) { perror("Error opening input file:"); exit(EXIT_FAILURE); } // Main data pointer that's used locally Person *pData = NULL; // Temporary buffers for data during reading char bufFName[BUF_LEN], bufLName[BUF_LEN], bufCurrCode[BUF_LEN]; int bufInd; float bufPoints; // Initialize the line count to 0 - nothing read yet int count = 0; // start by reading one line at a time into the buffers (no memory yet) while (fscanf(fp, "%d %s %s %s %f", &bufInd, bufFName, bufLName, bufCurrCode, &bufPoints) == 5) { // if a line was successfully read, expanding the memory by 1. Using a // temporary pointer to avoid losing memory address when realloc fails // during reading (returns NULL, old pointer valid) Person *pTemp = realloc(pData, sizeof(Person) * (unsigned)(count + 1)); // Check if it failed if (pTemp == NULL) { // TODO: Error behavior! // I.e. if you want 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); } // Make both pointers point at the memory location pData = pTemp; // Copy data from buffers to the struct array // Now allocate + copy data for the string buffers // Note 1: Both pData[i].member or (pData + i)->member can be used // Note 2: strdup() combines strlen, malloc and strcpy (pData + count)->fName = strdup(bufFName); if ((pData + count)->fName == NULL) { // TODO: error behavior here } // numbers can be copied directly, there already is memory in the struct (pData + count)->points = bufPoints; // another line successfully read count++; } // using a pointer to store the number of lines that were read *cnt = count; // now just close the file fclose(fp); // and return the pointer to the struct array we just allocated return pData; } /** * 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) { printf("The candidates are:\n"); for (int 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); } } |