質問: 解決できない問題があります。 buffer2に保存した文章が入りません。 あの後、覚えてという言葉の後で○○は◇◇であるという形式にすることで文章をメモに記憶させることはできました。 その次に覚えさせた文章から特定の言葉が含まれていた場合、その文章を少し改造したものを表示するというプログラムを作ろうとしています。 まず、「覚えて」と入力した後に 例えば、「ジュニーは戦場へ行くという映画は面白い。」、「明日は晴れ。」、「どすこいはお相撲。」と入力してエンターキーを押します。 するとtxtに「ジュニーは戦場へ行くという映画は面白い。」、「明日は晴れ。」、「どすこいはお相撲。」と保存されます。 その後に「どんな映画が好きですか?」と入力すると、メモから if (my_str2(buffer2, "映画")) という条件により「映画」を含んだ文章を読み込み、 「ジュニーは戦場へ行くという映画は面白い。」をbuffer2に入れて「ジュニーは戦場へ行くという映画は面白い。」と返すようにします。 しかし、実際に実行するとbuffer2の方で文章が読み込めていますが、「ジュニーは戦場へ行くという映画は面白い。」という結果は表示されませんでした。 if (my_str2(buffer2, "映画")) という条件により「映画」を含んだ文章を読み込み、表示できると思っていました。しかし、**実際は「映画」という言葉をメモから読み込んで一致させただけで、「映画」という言葉を含んだ文章を表示させるための処理が書かれていませんでした。** また、どうやったら太い黒文字で書いたような処理ができるのかの書き方がわかりません。 どうか私が書けるヒントとなるサンプルのプログラムなど頂けないでしょうか。 期待する結果: 「映画」という言葉を含んだ文章である"ジュニーは戦場へ行くという映画は面白い。"が画面に出力されるというのが期待です。 以下は画像です。 ![「どんな映画が好きですか?」の入力後](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/0e1b049ba7410697c2fa5f5a48ab880b.png) ![「どんな映画が好きですか?」の入力後で実行した後の値](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/10b3bea3032923fb529b43e05a52e90e.png) コードです 汚いかもしれませんが、必要最低限の部分のみでコードを編集しました。 短くしたコードです すいません、kazuma-sさん、編集後のプログラムでもなぜかエラーが起きます。 私のビルドの仕方が悪いのかもしれません。 ![エラーメッセージが出てしまいます。](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/89c119c9a00eed465ae1ccd8a0db0327.png)
回答: memo.txt ``` 「ジョニーは戦場へ行った」という映画は面白い。 明日は晴れ。 どすこいはお相撲。 映画館はどこも満席。 休日はおうちで映画鑑賞。 ``` ``` #pragma warning(disable: 4996) #include "DxLib.h" int readMemo(char **memo, int n) { FILE *fp = fopen("memo.txt", "r"); if (fp == NULL) return 0; int i; char buf[256]; memo[0] = ""; for (i = 1; i < n && fgets(buf, sizeof buf, fp); i++) memo[i] = strdup(buf); fclose(fp); return i; } void drawMemo(char **memo, int n) { int x = 10, y = 420, color = GetColor(0, 255, 0); for (int i = 1; i < n; i++) { DrawFormatString(x, y, color, "%2d: %s", i, memo[i]); y += 30; } } int findMemo(char **memo, int n, char *str) { if (str[0] != '\0') for (int i = 0; i < n; i++) if (strstr(memo[i], str)) return i; return 0; } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetGraphMode(1280, 720, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリの初期化 SetDrawScreen(DX_SCREEN_BACK); // 描画先を裏画面にする SetFontSize(24); // フォントサイズを 24に変更 char *memo[10]; int n_memo = readMemo(memo, 10); if (n_memo == 0) { DxLib_End(); return 1; } int n_show = 0; int kih = MakeKeyInput(256, FALSE, FALSE, FALSE); // key input handle SetActiveKeyInput(kih); char buf[256] = ""; int input_color = GetColor(255, 255, 0); int show_color = GetColor(255, 0, 255); int buf_color = GetColor(0, 255, 255); while (ProcessMessage() == 0) { ClearDrawScreen(); // 画面の初期化 DrawKeyInputModeString(1200, 0); // 入力モードを描画 DrawString(10, 30, "入力: ", input_color); DrawKeyInputString(80, 30, kih); // 入力途中の文字列を描画 if (CheckKeyInput(kih) != 0) { // 入力完了なら GetKeyInputString(buf, kih); // 入力文字列を取得 n_show = findMemo(memo, n_memo, buf); // メモを検索 SetActiveKeyInput(kih); SetKeyInputString("", kih); } DrawFormatString(10, 80, buf_color, "検索文字列: %s", buf); DrawFormatString(10, 110, show_color, "検索結果: %s", memo[n_show]); drawMemo(memo, n_memo); // メモを表示 ScreenFlip(); // 裏画面の内容を表画面に反映させる } DeleteKeyInput(kih); DxLib_End(); return 0; } ``` **追記** `memo[0] = "";` や `or` でエラーにならなかったのは、 私のコンパイラが Visual C++ 2017 のものであったからだと思われます。 `memo[0] = (char *)"";` に変更したのはエラーメッセージに 「error C2440: '=': 'const char [1]' から 'char *' に変換できません。」 とあったからです。キャスト (char *) により強制的に変換させました。 他にコードについての疑問点はありませんか? 完全に理解されましたか? おまけ ``` #pragma warning(disable: 4996) #include // fopen, fgets, fclose, printf, puts #include // strdup, strstr, strchr, strcmp, strlen #define MEMO_FILE "memo2.txt" enum { SEARCH, MEMORY }; // 検索モード、記憶モード int getline(char *buf, int size, FILE *fp) { if (!fgets(buf, size, fp)) return EOF; char *p = strchr(buf, '\n'); if (p) *p = '\0'; return strlen(buf); } int readMemo(char **memo, int size) { FILE *fp = fopen(MEMO_FILE, "r"); if (fp == NULL) return 0; int i; char buf[256]; memo[0] = (char *)""; for (i = 1; i < size && getline(buf, sizeof buf, fp) >= 0; i++) memo[i] = strdup(buf); fclose(fp); return i; } int saveMemo(char **memo, int n) { FILE *fp = fopen(MEMO_FILE, "w"); if (fp == NULL) return 1; for (int i = 1; i < n; i++) fprintf(fp, "%s\n", memo[i]); fclose(fp); return 0; } void drawMemo(char **memo, int n) { for (int i = 1; i < n; i++) printf("%2d: %s\n", i, memo[i]); } int addMemo(char **memo, int size, int n, const char *str) { if (n >= size) return 1; memo[n++] = strdup(str); return 0; } int findMemo(char **memo, int n, char *str) { for (int i = 0; i < n; i++) if (strstr(memo[i], str)) return i; return 0; } int main() { char *memo[100]; memo[0] = (char *)""; int n_memo = 1; int mode = SEARCH; puts("コマンド: 記憶、検索、表示、保存、取得、終了"); while (1) { char buf[256]; printf("入力: "); if (getline(buf, sizeof buf, stdin) < 0) break; if (buf[0] == '\0') continue; if (!strcmp(buf, "終了")) break; else if (!strcmp(buf, "記憶")) mode = MEMORY; else if (!strcmp(buf, "検索")) mode = SEARCH; else if (!strcmp(buf, "表示")) drawMemo(memo, n_memo); else if (!strcmp(buf, "保存")) saveMemo(memo, n_memo); else if (!strcmp(buf, "取得")) n_memo = readMemo(memo, 100); else if (mode == MEMORY) { if (addMemo(memo, 100, n_memo, buf)) puts(" 追加できません"); else n_memo++; } else { // mode == SEARCH int n_find = findMemo(memo, n_memo, buf); if (n_find > 0) printf(" 検索結果: %s\n", memo[n_find]); else printf(" 「%s」は見つかりません\n", buf); } } return 0; } ``` **追記2** 解決済みになってしまいましたが、どのようにして解決したのですか? 「覚えて」のあと、記憶させる文字列を複数入力し、「映画」で検索するコードが 書けたのなら、それを提示してください。 私の回答のコメント欄に、 「これから読ませていただくので疑問はその後に答えさせて頂けないでしょうか。」 と書いたことを実行してください。 おまけのコードで、「入力: 」よりも現在のモードを表示したほうがよいので 次のように変更してください。 ``` - printf("入力: "); + printf(mode == MEMORY ? "記憶: " : "検索: "); ```