diff options
| author | Filip Wandzio <contact@philw.dev> | 2026-03-01 11:29:12 +0100 |
|---|---|---|
| committer | Filip Wandzio <contact@philw.dev> | 2026-03-01 11:29:12 +0100 |
| commit | a2afca302c68b8b5d7c3bec13378180b60a3ac17 (patch) | |
| tree | 0c7424a1847ff91f61ab439b5e497e5a093639b2 | |
| download | ysnp-a2afca302c68b8b5d7c3bec13378180b60a3ac17.tar.gz ysnp-a2afca302c68b8b5d7c3bec13378180b60a3ac17.zip | |
Scaffold project
Signed-off-by: Filip Wandzio <contact@philw.dev>
| -rw-r--r-- | .gitignore | 205 | ||||
| -rwxr-xr-x | build/exam | bin | 0 -> 34952 bytes | |||
| -rw-r--r-- | build/questions.txt | 42 | ||||
| -rwxr-xr-x | build/test_questions | bin | 0 -> 34688 bytes | |||
| -rw-r--r-- | data/questions.txt | 42 | ||||
| -rw-r--r-- | include/questions.h | 20 | ||||
| -rw-r--r-- | include/utils.h | 8 | ||||
| -rw-r--r-- | src/main.c | 83 | ||||
| -rw-r--r-- | src/questions.c | 92 | ||||
| -rw-r--r-- | src/utils.c | 34 | ||||
| -rw-r--r-- | tests/test_questions.c | 24 |
11 files changed, 550 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d483172 --- /dev/null +++ b/.gitignore | |||
| @@ -0,0 +1,205 @@ | |||
| 1 | # Created by https://www.toptal.com/developers/gitignore/api/cmake,c++ | ||
| 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=cmake,c++ | ||
| 3 | |||
| 4 | ### C++ ### | ||
| 5 | # Prerequisites | ||
| 6 | *.d | ||
| 7 | |||
| 8 | *.csv | ||
| 9 | # Compiled Object files | ||
| 10 | *.slo | ||
| 11 | *.lo | ||
| 12 | *.o | ||
| 13 | *.obj | ||
| 14 | |||
| 15 | # Precompiled Headers | ||
| 16 | *.gch | ||
| 17 | *.pch | ||
| 18 | |||
| 19 | # Compiled Dynamic libraries | ||
| 20 | *.so | ||
| 21 | *.dylib | ||
| 22 | *.dll | ||
| 23 | |||
| 24 | # Fortran module files | ||
| 25 | *.mod | ||
| 26 | *.smod | ||
| 27 | |||
| 28 | # Compiled Static libraries | ||
| 29 | *.lai | ||
| 30 | *.la | ||
| 31 | *.a | ||
| 32 | *.lib | ||
| 33 | |||
| 34 | # Executables | ||
| 35 | *.exe | ||
| 36 | *.out | ||
| 37 | *.app | ||
| 38 | |||
| 39 | ### CMake ### | ||
| 40 | CMakeLists.txt.user | ||
| 41 | CMakeCache.txt | ||
| 42 | CMakeFiles | ||
| 43 | CMakeScripts | ||
| 44 | Testing | ||
| 45 | Makefile | ||
| 46 | cmake_install.cmake | ||
| 47 | install_manifest.txt | ||
| 48 | compile_commands.json | ||
| 49 | CTestTestfile.cmake | ||
| 50 | _deps | ||
| 51 | |||
| 52 | ### CMake Patch ### | ||
| 53 | CMakeUserPresets.json | ||
| 54 | |||
| 55 | # External projects | ||
| 56 | *-prefix/ | ||
| 57 | |||
| 58 | ### Intellij+all ### | ||
| 59 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider | ||
| 60 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | ||
| 61 | |||
| 62 | # User-specific stuff | ||
| 63 | .idea/**/workspace.xml | ||
| 64 | .idea/**/tasks.xml | ||
| 65 | .idea/**/usage.statistics.xml | ||
| 66 | .idea/**/dictionaries | ||
| 67 | .idea/**/shelf | ||
| 68 | |||
| 69 | # AWS User-specific | ||
| 70 | .idea/**/aws.xml | ||
| 71 | |||
| 72 | # Generated files | ||
| 73 | .idea/**/contentModel.xml | ||
| 74 | |||
| 75 | # Sensitive or high-churn files | ||
| 76 | .idea/**/dataSources/ | ||
| 77 | .idea/**/dataSources.ids | ||
| 78 | .idea/**/dataSources.local.xml | ||
| 79 | .idea/**/sqlDataSources.xml | ||
| 80 | .idea/**/dynamic.xml | ||
| 81 | .idea/**/uiDesigner.xml | ||
| 82 | .idea/**/dbnavigator.xml | ||
| 83 | |||
| 84 | # Gradle | ||
| 85 | .idea/**/gradle.xml | ||
| 86 | .idea/**/libraries | ||
| 87 | |||
| 88 | # Gradle and Maven with auto-import | ||
| 89 | # When using Gradle or Maven with auto-import, you should exclude module files, | ||
| 90 | # since they will be recreated, and may cause churn. Uncomment if using | ||
| 91 | # auto-import. | ||
| 92 | # .idea/artifacts | ||
| 93 | # .idea/compiler.xml | ||
| 94 | # .idea/jarRepositories.xml | ||
| 95 | # .idea/modules.xml | ||
| 96 | # .idea/*.iml | ||
| 97 | # .idea/modules | ||
| 98 | # *.iml | ||
| 99 | # *.ipr | ||
| 100 | |||
| 101 | # CMake | ||
| 102 | cmake-build-*/ | ||
| 103 | |||
| 104 | # Mongo Explorer plugin | ||
| 105 | .idea/**/mongoSettings.xml | ||
| 106 | |||
| 107 | # File-based project format | ||
| 108 | *.iws | ||
| 109 | |||
| 110 | # IntelliJ | ||
| 111 | out/ | ||
| 112 | |||
| 113 | # mpeltonen/sbt-idea plugin | ||
| 114 | .idea_modules/ | ||
| 115 | |||
| 116 | # JIRA plugin | ||
| 117 | atlassian-ide-plugin.xml | ||
| 118 | |||
| 119 | # Cursive Clojure plugin | ||
| 120 | .idea/replstate.xml | ||
| 121 | |||
| 122 | # SonarLint plugin | ||
| 123 | .idea/sonarlint/ | ||
| 124 | |||
| 125 | # Crashlytics plugin (for Android Studio and IntelliJ) | ||
| 126 | com_crashlytics_export_strings.xml | ||
| 127 | crashlytics.properties | ||
| 128 | crashlytics-build.properties | ||
| 129 | fabric.properties | ||
| 130 | |||
| 131 | # Editor-based Rest Client | ||
| 132 | .idea/httpRequests | ||
| 133 | |||
| 134 | # Android studio 3.1+ serialized cache file | ||
| 135 | .idea/caches/build_file_checksums.ser | ||
| 136 | |||
| 137 | ### Intellij+all Patch ### | ||
| 138 | # Ignore everything but code style settings and run configurations | ||
| 139 | # that are supposed to be shared within teams. | ||
| 140 | |||
| 141 | .idea/* | ||
| 142 | |||
| 143 | !.idea/codeStyles | ||
| 144 | !.idea/runConfigurations | ||
| 145 | |||
| 146 | ### macOS ### | ||
| 147 | # General | ||
| 148 | .DS_Store | ||
| 149 | .AppleDouble | ||
| 150 | .LSOverride | ||
| 151 | |||
| 152 | # Icon must end with two \r | ||
| 153 | Icon | ||
| 154 | |||
| 155 | |||
| 156 | # Thumbnails | ||
| 157 | ._* | ||
| 158 | |||
| 159 | # Files that might appear in the root of a volume | ||
| 160 | .DocumentRevisions-V100 | ||
| 161 | .fseventsd | ||
| 162 | .Spotlight-V100 | ||
| 163 | .TemporaryItems | ||
| 164 | .Trashes | ||
| 165 | .VolumeIcon.icns | ||
| 166 | .com.apple.timemachine.donotpresent | ||
| 167 | |||
| 168 | # Directories potentially created on remote AFP share | ||
| 169 | .AppleDB | ||
| 170 | .AppleDesktop | ||
| 171 | Network Trash Folder | ||
| 172 | Temporary Items | ||
| 173 | .apdisk | ||
| 174 | |||
| 175 | ### macOS Patch ### | ||
| 176 | # iCloud generated files | ||
| 177 | *.icloud | ||
| 178 | |||
| 179 | ### Windows ### | ||
| 180 | # Windows thumbnail cache files | ||
| 181 | Thumbs.db | ||
| 182 | Thumbs.db:encryptable | ||
| 183 | ehthumbs.db | ||
| 184 | ehthumbs_vista.db | ||
| 185 | |||
| 186 | # Dump file | ||
| 187 | *.stackdump | ||
| 188 | |||
| 189 | # Folder config file | ||
| 190 | [Dd]esktop.ini | ||
| 191 | |||
| 192 | # Recycle Bin used on file shares | ||
| 193 | $RECYCLE.BIN/ | ||
| 194 | |||
| 195 | # Windows Installer files | ||
| 196 | *.cab | ||
| 197 | *.msi | ||
| 198 | *.msix | ||
| 199 | *.msm | ||
| 200 | *.msp | ||
| 201 | |||
| 202 | # Windows shortcuts | ||
| 203 | *.lnk | ||
| 204 | |||
| 205 | # End of https://www.toptal.com/developers/gitignore/api/intellij+all,macos,windows | ||
diff --git a/build/exam b/build/exam new file mode 100755 index 0000000..988b751 --- /dev/null +++ b/build/exam | |||
| Binary files differ | |||
diff --git a/build/questions.txt b/build/questions.txt new file mode 100644 index 0000000..b462db6 --- /dev/null +++ b/build/questions.txt | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #GENERAL | ||
| 2 | 1. Zasady bezpieczeństwa informacji w przedsiębiorstwie. | ||
| 3 | 2. Istota audytu. | ||
| 4 | 3. Podmioty prawa cywilnego – osoba fizyczna a osoba prawna. | ||
| 5 | 4. Rodzaje i formy zawierania umów. | ||
| 6 | 5. Procedury zakładania własnego przedsiębiorstwa. | ||
| 7 | 6. Przyczyny i rodzaje upadłości przedsiębiorstw. | ||
| 8 | 7. Prawa i obowiązki pracownika i pracodawcy. | ||
| 9 | 8. Ochrona baz danych. | ||
| 10 | 9. Rozwój gospodarczy a poziom życia społeczeństwa w świetle podstawowych mierników makroekonomicznych. | ||
| 11 | 10. Rynek pracy uwarunkowania, problemy, tendencje. | ||
| 12 | 11. Polityka fiskalna państwa. | ||
| 13 | 12. Polityka monetarna państwa. | ||
| 14 | 13. Globalizacja i jej wpływ na sytuację gospodarczą. | ||
| 15 | 14. Ocena członkostwa w Unii Europejskiej w wymiarze ekonomicznym i społecznym. | ||
| 16 | 15. Rynek pracy – uwarunkowania, problemy, tendencje. | ||
| 17 | #MAJOR | ||
| 18 | 1. Zarządzanie projektem informatycznym – istota, etapy, zadania. | ||
| 19 | 2. Czynniki wyboru systemu informatycznego. | ||
| 20 | 3. Interesariusze i ograniczenia w projektach informatycznych. | ||
| 21 | 4. Metodyki zarządzania projektem informatycznym. | ||
| 22 | 5. Znaczenie baz i hurtowni danych dla podejmowania decyzji. | ||
| 23 | 6. Funkcje raportowania, analizy i eksploracji danych. | ||
| 24 | 7. Narzędzia, metody wykorzystywane w obszarze Business Intelligence. | ||
| 25 | 8. Zagrożenia i metody ochrony informacji i infrastruktury w przedsiębiorstwie. | ||
| 26 | 9. Bezpieczeństwo informatyczne i identyfikacja zagrożeń w przedsiębiorstwie. | ||
| 27 | 10. System zarządzania bezpieczeństwem. | ||
| 28 | 11. Na czym polega złożoność obliczeniowa algorytmów. | ||
| 29 | 12. Charakterystyka baz danych -cechy, przykłady. | ||
| 30 | 13. Obiekty bazodanowe, pojęcie klucza, typy danych (przykłady). | ||
| 31 | 14. Wykorzystanie systemów wspomagania decyzji w przedsiębiorstwie. | ||
| 32 | 15. Systemy ekspertowe -budowa, znaczenie, wykorzystanie. | ||
| 33 | 16. Internet rzeczy -istota działania, zalety, wady, wykorzystanie. | ||
| 34 | 17. Zagrożenia w systemach Internetu rzeczy. | ||
| 35 | 18. Uczenie maszynowe – analiza pojęcia, działanie, wykorzystanie. | ||
| 36 | 19. Ograniczenia i problemy w uczeniu maszynowym. | ||
| 37 | 20. Metody uczenia maszynowego. | ||
| 38 | 21. Charakterystyka, bezpieczeństwo aplikacji internetowych i mobilnych. | ||
| 39 | 22. Technologie backendowe i frontendowe -różnice, przykłady. | ||
| 40 | 23. System operacyjny: rola, działanie, budowa, rodzaje. | ||
| 41 | 24. Integracja systemów informatycznych. | ||
| 42 | 25. Wymień i krótko omów wybrane zagrożenia cybernetyczne. | ||
diff --git a/build/test_questions b/build/test_questions new file mode 100755 index 0000000..04dac40 --- /dev/null +++ b/build/test_questions | |||
| Binary files differ | |||
diff --git a/data/questions.txt b/data/questions.txt new file mode 100644 index 0000000..b462db6 --- /dev/null +++ b/data/questions.txt | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #GENERAL | ||
| 2 | 1. Zasady bezpieczeństwa informacji w przedsiębiorstwie. | ||
| 3 | 2. Istota audytu. | ||
| 4 | 3. Podmioty prawa cywilnego – osoba fizyczna a osoba prawna. | ||
| 5 | 4. Rodzaje i formy zawierania umów. | ||
| 6 | 5. Procedury zakładania własnego przedsiębiorstwa. | ||
| 7 | 6. Przyczyny i rodzaje upadłości przedsiębiorstw. | ||
| 8 | 7. Prawa i obowiązki pracownika i pracodawcy. | ||
| 9 | 8. Ochrona baz danych. | ||
| 10 | 9. Rozwój gospodarczy a poziom życia społeczeństwa w świetle podstawowych mierników makroekonomicznych. | ||
| 11 | 10. Rynek pracy uwarunkowania, problemy, tendencje. | ||
| 12 | 11. Polityka fiskalna państwa. | ||
| 13 | 12. Polityka monetarna państwa. | ||
| 14 | 13. Globalizacja i jej wpływ na sytuację gospodarczą. | ||
| 15 | 14. Ocena członkostwa w Unii Europejskiej w wymiarze ekonomicznym i społecznym. | ||
| 16 | 15. Rynek pracy – uwarunkowania, problemy, tendencje. | ||
| 17 | #MAJOR | ||
| 18 | 1. Zarządzanie projektem informatycznym – istota, etapy, zadania. | ||
| 19 | 2. Czynniki wyboru systemu informatycznego. | ||
| 20 | 3. Interesariusze i ograniczenia w projektach informatycznych. | ||
| 21 | 4. Metodyki zarządzania projektem informatycznym. | ||
| 22 | 5. Znaczenie baz i hurtowni danych dla podejmowania decyzji. | ||
| 23 | 6. Funkcje raportowania, analizy i eksploracji danych. | ||
| 24 | 7. Narzędzia, metody wykorzystywane w obszarze Business Intelligence. | ||
| 25 | 8. Zagrożenia i metody ochrony informacji i infrastruktury w przedsiębiorstwie. | ||
| 26 | 9. Bezpieczeństwo informatyczne i identyfikacja zagrożeń w przedsiębiorstwie. | ||
| 27 | 10. System zarządzania bezpieczeństwem. | ||
| 28 | 11. Na czym polega złożoność obliczeniowa algorytmów. | ||
| 29 | 12. Charakterystyka baz danych -cechy, przykłady. | ||
| 30 | 13. Obiekty bazodanowe, pojęcie klucza, typy danych (przykłady). | ||
| 31 | 14. Wykorzystanie systemów wspomagania decyzji w przedsiębiorstwie. | ||
| 32 | 15. Systemy ekspertowe -budowa, znaczenie, wykorzystanie. | ||
| 33 | 16. Internet rzeczy -istota działania, zalety, wady, wykorzystanie. | ||
| 34 | 17. Zagrożenia w systemach Internetu rzeczy. | ||
| 35 | 18. Uczenie maszynowe – analiza pojęcia, działanie, wykorzystanie. | ||
| 36 | 19. Ograniczenia i problemy w uczeniu maszynowym. | ||
| 37 | 20. Metody uczenia maszynowego. | ||
| 38 | 21. Charakterystyka, bezpieczeństwo aplikacji internetowych i mobilnych. | ||
| 39 | 22. Technologie backendowe i frontendowe -różnice, przykłady. | ||
| 40 | 23. System operacyjny: rola, działanie, budowa, rodzaje. | ||
| 41 | 24. Integracja systemów informatycznych. | ||
| 42 | 25. Wymień i krótko omów wybrane zagrożenia cybernetyczne. | ||
diff --git a/include/questions.h b/include/questions.h new file mode 100644 index 0000000..75bc751 --- /dev/null +++ b/include/questions.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #pragma once | ||
| 2 | #include <stddef.h> | ||
| 3 | |||
| 4 | typedef struct { | ||
| 5 | char **general; | ||
| 6 | char **major; | ||
| 7 | size_t general_count; | ||
| 8 | size_t major_count; | ||
| 9 | } QuestionSet; | ||
| 10 | |||
| 11 | /** | ||
| 12 | * Load questions from file. | ||
| 13 | * Returns EXIT_SUCCESS or EXIT_FAILURE. | ||
| 14 | */ | ||
| 15 | int load_questions(const char *filename, QuestionSet *qs); | ||
| 16 | |||
| 17 | /** | ||
| 18 | * Free all allocated memory in QuestionSet. | ||
| 19 | */ | ||
| 20 | void free_questions(QuestionSet *qs); | ||
diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..74c0ca1 --- /dev/null +++ b/include/utils.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #pragma once | ||
| 2 | #include <stddef.h> | ||
| 3 | |||
| 4 | void print_line(void); | ||
| 5 | void wait_enter(const char *msg); | ||
| 6 | char ask_yes_no(const char *msg); | ||
| 7 | void now_str(char *buf, size_t size); | ||
| 8 | size_t rand_index(size_t max); | ||
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..33d4b39 --- /dev/null +++ b/src/main.c | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <time.h> | ||
| 4 | #include <sys/stat.h> | ||
| 5 | #include <sys/types.h> | ||
| 6 | |||
| 7 | #include "questions.h" | ||
| 8 | #include "utils.h" | ||
| 9 | |||
| 10 | int main(void) { | ||
| 11 | srand((unsigned)time(NULL)); | ||
| 12 | |||
| 13 | // utwórz katalog data/ jeśli nie istnieje | ||
| 14 | struct stat st = {0}; | ||
| 15 | if (stat("data", &st) == -1) { | ||
| 16 | #ifdef _WIN32 | ||
| 17 | _mkdir("data"); | ||
| 18 | #else | ||
| 19 | mkdir("data", 0755); | ||
| 20 | #endif | ||
| 21 | } | ||
| 22 | |||
| 23 | QuestionSet qs; | ||
| 24 | if (load_questions("data/questions.txt", &qs) != EXIT_SUCCESS) { | ||
| 25 | fprintf(stderr, "Error: cannot load questions file\n"); | ||
| 26 | return EXIT_FAILURE; | ||
| 27 | } | ||
| 28 | |||
| 29 | FILE *csv = fopen("data/results.csv", "a"); | ||
| 30 | if (!csv) { | ||
| 31 | perror("CSV open"); | ||
| 32 | free_questions(&qs); | ||
| 33 | return EXIT_FAILURE; | ||
| 34 | } | ||
| 35 | |||
| 36 | int limit = 0; | ||
| 37 | printf("Time limit (sec, 0 = unlimited): "); | ||
| 38 | if (scanf("%d", &limit) != 1) limit = 0; | ||
| 39 | wait_enter(NULL); | ||
| 40 | |||
| 41 | size_t total = 0, correct = 0; | ||
| 42 | char cont = 'y'; | ||
| 43 | |||
| 44 | while (cont == 'y' || cont == 'Y') { | ||
| 45 | const char *g = qs.general[rand_index(qs.general_count)]; | ||
| 46 | const char *m = qs.major[rand_index(qs.major_count)]; | ||
| 47 | |||
| 48 | print_line(); | ||
| 49 | printf("GENERAL:\n%s\n\nMAJOR:\n%s\n", g, m); | ||
| 50 | print_line(); | ||
| 51 | |||
| 52 | wait_enter("Press ENTER to start..."); | ||
| 53 | time_t start = time(NULL); | ||
| 54 | |||
| 55 | wait_enter("Press ENTER when done..."); | ||
| 56 | double duration = difftime(time(NULL), start); | ||
| 57 | |||
| 58 | if (limit > 0 && duration > limit) | ||
| 59 | printf("Time exceeded!\n"); | ||
| 60 | |||
| 61 | char ans = ask_yes_no("Correct? (y/n): "); | ||
| 62 | if (ans == 'y' || ans == 'Y') correct++; | ||
| 63 | total++; | ||
| 64 | |||
| 65 | char ts[32]; | ||
| 66 | now_str(ts, sizeof(ts)); | ||
| 67 | fprintf(csv, "\"%s\",\"%s\",\"%s\",%c,%.0f\n", ts, g, m, ans, duration); | ||
| 68 | |||
| 69 | printf("Score: %zu/%zu (%.1f%%)\n", | ||
| 70 | correct, total, | ||
| 71 | total ? (double)correct / total * 100 : 0.0); | ||
| 72 | |||
| 73 | cont = ask_yes_no("Next? (y/n): "); | ||
| 74 | } | ||
| 75 | |||
| 76 | printf("\nSession score: %.1f%%\n", | ||
| 77 | total ? (double)correct / total * 100 : 0.0); | ||
| 78 | |||
| 79 | fclose(csv); | ||
| 80 | free_questions(&qs); | ||
| 81 | |||
| 82 | return EXIT_SUCCESS; | ||
| 83 | } | ||
diff --git a/src/questions.c b/src/questions.c new file mode 100644 index 0000000..88671a7 --- /dev/null +++ b/src/questions.c | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | #include "questions.h" | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | #include <string.h> | ||
| 5 | |||
| 6 | #define MAX_LINE 512 | ||
| 7 | |||
| 8 | static int add_question(char ***arr, size_t *count, const char *text) { | ||
| 9 | char **tmp = realloc(*arr, (*count + 1) * sizeof(char *)); | ||
| 10 | if (!tmp) | ||
| 11 | return EXIT_FAILURE; | ||
| 12 | *arr = tmp; | ||
| 13 | |||
| 14 | (*arr)[*count] = malloc(strlen(text) + 1); | ||
| 15 | if (!(*arr)[*count]) | ||
| 16 | return EXIT_FAILURE; | ||
| 17 | |||
| 18 | strcpy((*arr)[*count], text); | ||
| 19 | (*count)++; | ||
| 20 | return EXIT_SUCCESS; | ||
| 21 | } | ||
| 22 | |||
| 23 | int load_questions(const char *filename, QuestionSet *qs) { | ||
| 24 | if (!filename || !qs) | ||
| 25 | return EXIT_FAILURE; | ||
| 26 | |||
| 27 | FILE *f = fopen(filename, "r"); | ||
| 28 | if (!f) | ||
| 29 | return EXIT_FAILURE; | ||
| 30 | |||
| 31 | qs->general = NULL; | ||
| 32 | qs->major = NULL; | ||
| 33 | qs->general_count = 0; | ||
| 34 | qs->major_count = 0; | ||
| 35 | |||
| 36 | char line[MAX_LINE]; | ||
| 37 | enum { NONE, GENERAL, MAJOR } mode = NONE; | ||
| 38 | |||
| 39 | while (fgets(line, sizeof(line), f)) { | ||
| 40 | line[strcspn(line, "\n")] = '\0'; | ||
| 41 | if (line[0] == '\0') | ||
| 42 | continue; | ||
| 43 | |||
| 44 | if (strcmp(line, "#GENERAL") == 0) { | ||
| 45 | mode = GENERAL; | ||
| 46 | continue; | ||
| 47 | } | ||
| 48 | if (strcmp(line, "#MAJOR") == 0) { | ||
| 49 | mode = MAJOR; | ||
| 50 | continue; | ||
| 51 | } | ||
| 52 | |||
| 53 | int res = EXIT_FAILURE; | ||
| 54 | switch (mode) { | ||
| 55 | case GENERAL: | ||
| 56 | res = add_question(&qs->general, &qs->general_count, line); | ||
| 57 | break; | ||
| 58 | case MAJOR: | ||
| 59 | res = add_question(&qs->major, &qs->major_count, line); | ||
| 60 | break; | ||
| 61 | default: | ||
| 62 | continue; // ignore lines before section | ||
| 63 | } | ||
| 64 | |||
| 65 | if (res != EXIT_SUCCESS) { | ||
| 66 | fclose(f); | ||
| 67 | free_questions(qs); | ||
| 68 | return EXIT_FAILURE; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | fclose(f); | ||
| 73 | return (qs->general_count && qs->major_count) ? EXIT_SUCCESS : EXIT_FAILURE; | ||
| 74 | } | ||
| 75 | |||
| 76 | void free_questions(QuestionSet *qs) { | ||
| 77 | if (!qs) | ||
| 78 | return; | ||
| 79 | |||
| 80 | for (size_t i = 0; i < qs->general_count; i++) | ||
| 81 | free(qs->general[i]); | ||
| 82 | for (size_t i = 0; i < qs->major_count; i++) | ||
| 83 | free(qs->major[i]); | ||
| 84 | |||
| 85 | free(qs->general); | ||
| 86 | free(qs->major); | ||
| 87 | |||
| 88 | qs->general = NULL; | ||
| 89 | qs->major = NULL; | ||
| 90 | qs->general_count = 0; | ||
| 91 | qs->major_count = 0; | ||
| 92 | } | ||
diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..c139929 --- /dev/null +++ b/src/utils.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | #include <time.h> | ||
| 5 | |||
| 6 | void print_line(void) { | ||
| 7 | printf("--------------------------------------------------\n"); | ||
| 8 | } | ||
| 9 | |||
| 10 | void wait_enter(const char *msg) { | ||
| 11 | if (msg) | ||
| 12 | printf("%s", msg); | ||
| 13 | int c; | ||
| 14 | while ((c = getchar()) != '\n' && c != EOF) | ||
| 15 | ; | ||
| 16 | } | ||
| 17 | |||
| 18 | char ask_yes_no(const char *msg) { | ||
| 19 | char c = 'n'; | ||
| 20 | printf("%s", msg); | ||
| 21 | if (scanf(" %c", &c) != 1) | ||
| 22 | c = 'n'; | ||
| 23 | int flush; | ||
| 24 | while ((flush = getchar()) != '\n' && flush != EOF) | ||
| 25 | ; | ||
| 26 | return c; | ||
| 27 | } | ||
| 28 | |||
| 29 | void now_str(char *buf, size_t size) { | ||
| 30 | time_t t = time(NULL); | ||
| 31 | strftime(buf, size, "%Y-%m-%d %H:%M:%S", localtime(&t)); | ||
| 32 | } | ||
| 33 | |||
| 34 | size_t rand_index(size_t max) { return max ? (size_t)(rand() % max) : 0; } | ||
diff --git a/tests/test_questions.c b/tests/test_questions.c new file mode 100644 index 0000000..c605c1a --- /dev/null +++ b/tests/test_questions.c | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #include "questions.h" | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | |||
| 5 | int main(void) { | ||
| 6 | QuestionSet qs; | ||
| 7 | |||
| 8 | if (load_questions("data/questions.txt", &qs) != EXIT_SUCCESS) { | ||
| 9 | fprintf(stderr, "TEST FAILED: cannot load file\n"); | ||
| 10 | return EXIT_FAILURE; | ||
| 11 | } | ||
| 12 | |||
| 13 | if (qs.general_count == 0 || qs.major_count == 0) { | ||
| 14 | fprintf(stderr, "TEST FAILED: empty sets\n"); | ||
| 15 | free_questions(&qs); | ||
| 16 | return EXIT_FAILURE; | ||
| 17 | } | ||
| 18 | |||
| 19 | printf("TEST OK: loaded %zu general, %zu major\n", qs.general_count, | ||
| 20 | qs.major_count); | ||
| 21 | |||
| 22 | free_questions(&qs); | ||
| 23 | return EXIT_SUCCESS; | ||
| 24 | } | ||
