Tegu on näidega mille kommenteeritud lahendus toimub Programmeerimine 2 struktuuridele pühendatud tunnis.
Andmefaili vorming: <nimi> <hinne> , kus nimi on maksimaalselt 63 tähemärki ja koosneb ühest sõnast ning hinne on täisarv. Andmeväljad on eraldatud üksteisest tühikutega.
Märka, et nimepuhvri ületäitumise eest kaitset rakendatud pole (st kui failis nime pikkus 64 või enam tähemärki, kirjutatakse üle massiivi piiride). See võib põhjustada kas andmete riknemise või programmi kokkujooksu.
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); } } |