#include <stdio.h> #include <stdlib.h> #include <string.h> #define WORD 100 #define EXPLAIN 200 #define TOPIC_WORD 50 #define TOPIC_NUM 7 typedef struct { char explain[EXPLAIN]; char word[WORD]; int miss_count; } IT; int question(IT *date, int *str_num, int *privious); int write_date(IT * date, char txt[], int str_num, int privious, int lap, char topic[]); void end_step(IT * date, int miss_subscript[], int try_count, int miss_count); void end_step(IT * date, int miss_subscript[], int try_count, int miss_count) { puts("\n-----結果-----"); printf("%3d /%3d 正解\n", try_count - miss_count, try_count); puts("\n~間違えたワード~"); for (int i = 0; i < miss_count; i++) { printf("No.%03d %s\n", miss_subscript[i] + 2, date[miss_subscript[i]].word); //+2は添え字の0と最上段の分 } } /** * * @retval 1 完走 * @retval 2 途中終了 * @retval 3 何もせずに終了 */ int question(IT *date, int *str_num, int *privious) { char finishEng[] = "fin"; char helpHatena[] = "?"; char remove[] = "remove"; int *miss_subscript = calloc(*str_num, sizeof(int)); //free ok int miss_count = 0; int try_count = 0; for (int i = *privious; i < *str_num; i++) { char buff[WORD]; int judge = 0; int judge_count = 0; int removeFlag = 1; printf("No.%03d %s\n", i + 2, date[i].explain); do { int help_call = 0; printf("入力 : "); scanf("%s", buff); // 途中終了 if (strcmp(buff, finishEng) == 0) { if (try_count == 0) { free(miss_subscript); return 3; } *privious = i; end_step(date, miss_subscript, try_count, miss_count); free(miss_subscript); return 2; } // 削除(削除だけして途中終了すると保存されない) else if (strcmp(buff, remove) == 0) { printf("削除(No.%03d %s %s)\n\n", i + 2, date[i].word, date[i].explain); for (int j = i; j < *str_num - 1; j++) { date[j].miss_count = date[j + 1].miss_count; strcpy(date[j].word, date[j + 1].word); strcpy(date[j].explain, date[j + 1].explain); } *str_num -= 1; i--; removeFlag = 0; continue; } // 答え表示 else if (strcmp(buff, helpHatena) == 0) { printf("答え : %s\n", date[i].word); date[i].miss_count++; miss_subscript[miss_count] = i; miss_count++; help_call++; } judge = strcmp(buff, date[i].word); if (judge != 0 && help_call == 0) { printf("違います。\n"); judge_count++; } if (judge_count == 3) { judge_count++; printf("答え : %s\n", date[i].word); date[i].miss_count++; miss_subscript[miss_count] = i; //わざわざ文字列コピーしなくても添え字番号分かれば参照できる miss_count++; } } while (judge != 0); if (removeFlag == 1) { puts("正解!!"); try_count++; } } end_step(date, miss_subscript, try_count, miss_count); free(miss_subscript); return 1; } int write_date(IT * date, char txt[], int str_num, int privious, int lap, char topic[]) { FILE *fp; if ((fp = fopen(txt, "w")) == NULL) { puts("ファイルを開けませんでした。"); return 0; } else { fprintf(fp, "%s %d %d %d\n", topic, str_num, privious, lap); //改行ないとだめみたい for(int i = 0; i < str_num; i++) { fprintf(fp, "%d %s %s\n", date[i].miss_count, date[i].word, date[i].explain); } return 1; } } int check_str(char str[TOPIC_NUM][TOPIC_WORD], char argv_check[]) { for (int i = 0; i < TOPIC_NUM; i++) { if (strcmp(str[i], argv_check) == 0) { return 1; } } return 0; } int main(int argc, char *argv[]) { char topic_str_none[TOPIC_NUM][TOPIC_WORD] = {"security", "law", "strategy", "activity", "network", "audit", "servicemanagement"}; char topic_str_txt[TOPIC_NUM][TOPIC_WORD] = {"security.txt", "law.txt", "strategy.txt", "activity.txt", "network.txt", "audit.txt", "servicemanagement.txt"}; char txt[TOPIC_WORD + 4]; //.txt分で+4 // segmetation faultになる if (argc == 1) { //必ずargcは1入ってる puts("コマンドラインから分野を指定しませんでしたね。"); int buff_num; for (int i = 0; i < TOPIC_NUM; i++) { printf("No.%d %s\n", i, topic_str_txt[i]); } printf("分野番号 : "); scanf("%d", &buff_num); // printf("%d\n", buff_num); チェック strcpy(txt, topic_str_txt[buff_num]); //argv[1]はNULL領域が確保されていない } else if (argc >= 2) { if (argv[1][0] >= '0' && argv[1][0] <= '9') { int topic_subscript = argv[1][0] - '0'; strcpy(txt, topic_str_txt[topic_subscript]); } else { strcpy(txt, argv[1]); } if (check_str(topic_str_none, argv[1])) { char addition[] = ".txt"; strcat(txt, addition); puts(".txtが付いていなかったので追記しました。"); } } putchar('\n'); FILE *fp; if ((fp = fopen(txt, "r")) == NULL) { puts("ファイルを開けませんでした。"); return 0; } else { int str_num; //配列の数 int privious; //前回終了した時の添え字 int lap; //何周目か char topic[TOPIC_WORD]; //分野のテーマ fscanf(fp, "%s %d %d %d", topic, &str_num, &privious, &lap); IT *date = calloc(str_num, 304); //free ok int subscript = 0; while ((fscanf(fp, "%d %s %s", &date[subscript].miss_count, date[subscript].word, date[subscript].explain)) == 3) { subscript++; } fclose(fp); /* 読み込みできているかチェック用 for (int i = 0; i < str_num; i++) { printf("%d %s %s\n", date[i].miss_count, date[i].word, date[i].explain); } */ printf("ITテスト -%s分野-\n", topic); puts("\"fin\"→途中終了"); puts("\"?\"→答え表示"); puts("\"remove\"→問題の削除"); printf("前回は"); if (privious == str_num) { printf("完走しています。%d周目に入ります。\n", lap + 1); privious = 0; lap++; } else { printf("%d番目です。\n\n", privious + 2); } int result = question(date, &str_num, &privious); if (result == 1) { privious = str_num; puts("\n完走おめでとう。"); } else if (result == 2) { puts("途中終了しました。"); } else if (result == 3) { puts("挑戦せずに終わりました。"); free(date); return 0; } char backUp[] = "backup"; char no[] = "しません"; char save[20]; printf("\n保存処理 (\"しません\"以外保存、\"backup\"→バックアップ更新) : "); scanf("%s", save); int write_check; if (strcmp(save, backUp) == 0) { char path[] = "../backup/"; // 1階層上にbackupフォルダを作成する必要がある strcat(path, txt); write_check = write_date(date, path, str_num, privious, lap, topic); puts("バックアップを申請しました。"); if (write_check == 1) { puts("バックアップに成功しました。"); } else { puts("バックアップに失敗しました。"); } } if (strcmp(save, no) != 0) { write_check = write_date(date, txt, str_num, privious, lap, topic); puts("保存を申請しました。"); if (write_check == 1) { puts("保存に成功しました。"); } else { puts("保存に失敗しました。"); } } else { puts("保存しませんでした。"); } free(date); } return 0; }