This is a sample that will be written together in programming 2 in the class dedicated to structures.
Data file format isĀ <name> <grade> , where the name can consist from up to 63 characters and be a single word. Grade must be an integer. Data fields are separated by spaces.
Notice, that there is no guards for buffer overflow – if you enter 64 or more characters for the name, it will write beyond the bounds of the array and can cause data corruption or the program crashing.
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 |
/** * File: struct_file.c * Author: Risto Heinsar * Created: 10.01.2021 * Last edit: 13.02.2025 * * Description: Reads student data from a file into a struct array. * Name of the file passed as first argument * * Compile using --std=c99 or later. */ #include <stdio.h> #include <stdlib.h> /* 1 to enable printing debug statements, 0 to silence them */ #define DEBUG 1 /* Predefined array limits */ #define STR_MAX_LEN 64 #define STUDENT_MAX_CNT 32 /* Options for command line args */ #define ARGS_CNT 2 #define ARGS_EXEC_NAME argv[0] #define ARGS_FILE_NAME argv[1] typedef struct { char name[STR_MAX_LEN]; int grade; } Student; int ReadData(char *fName, Student *students, int readingLimit); void PrintData(Student *students, int cnt); int main(int argc, char **argv) { /* Check that argument was passed*/ if (argc != ARGS_CNT) { fprintf(stderr, "DBG: Usage: %s [data_file]\n", ARGS_EXEC_NAME); return EXIT_FAILURE; } /* Create struct array */ Student studentGrades[STUDENT_MAX_CNT]; /* Read student data from file */ int studentCnt = ReadData(ARGS_FILE_NAME, studentGrades, STUDENT_MAX_CNT); /* Print student data */ PrintData(studentGrades, studentCnt); return EXIT_SUCCESS; } /** * Description: Reads student data from a file into a struct array * * Parameters: fName - name of the file for input data * students - struct array to store the data * readingLimit - maximum entries to read (struct array length) * * Return: Number of studens read from the file */ int ReadData(char *fName, Student *students, int readingLimit) { FILE *fStudents = fopen(fName, "r"); if (fStudents == NULL) { /* Prints custom message + system error message from errno to stderr */ perror("Error! Cannot open input file"); /* Returns 0 students read from the file, allows program to continue */ return 0; /* Alternative: kill the program */ // exit(EXIT_FAILURE); } if (DEBUG) printf("Opened '%s' for reading student data\n", fName); /* Counter for number of students from file */ int cnt = 0; while (fscanf(fStudents, "%s %d", students[cnt].name, &students[cnt].grade) == 2) { /* Debugging print to check if input was read successfully */ if (DEBUG) printf("DBG: from file (%d): %s %d\n", cnt + 1, students[cnt].name, students[cnt].grade); /* Student successfully read, increment student count */ cnt++; /* Avoid overflowing the array */ if (cnt >= readingLimit) { fprintf(stderr, "ERROR: File is too long! Allowed max is %d!\n" "Reading of the file has been stopped, continuing " "with a partial dataset!\n", readingLimit); break; } } /* Close the input file */ fclose(fStudents); if (DEBUG) printf("DBG: Reading finished, got %d entries\n", cnt); /* Returns number of students read */ return cnt; } /** * Description: Prints the Student array contents * * Parameters: students - student data * cnt - num of students in data array * * Return: none */ void PrintData(Student *students, int cnt) { /* Handling of no students */ if (cnt <= 0) { fprintf(stderr, "Error! Student db is empty!\n"); return; } printf("Student list contains %d students:\n", cnt); for (int i = 0; i < cnt; i++) { printf("%s %d\n", students[i].name, students[i].grade); } } |