質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

871閲覧

配列を使って入力した文字列を分解して、その中から特定の単語が一致した際に返事をするようにしたい。

KZK13

総合スコア43

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/06/20 07:17

編集2020/06/20 17:51

例えば入力された文字列から”映画”という単語を見つけて一致したら、”どんな映画が好きなんですか?”と返事をするようなプログラムを作りたいです。
しかし、入力した文字列をトークンに分けると思うのですが、入力した文字列を配列で定義に沿って分けて、
その配列内の文字と映画という文字が一致した時に返事が来るようにする部分の、入力した文字列をトークンに分けるという部分がどう作ってよいのかわかりません。

環境はVS2019、DXライブラリ、Windows10です。

#include "DxLib.h" #include <string> int konnnitiwasound = 0; int situreisimasitasound = 0; char String[256]; char StringA[256]; int InputHandle; int InputHandleA; int modoru = 0; std::string input; std::string message; std::string messageA; char deta1[] = { "私" }; char deta2[] = { "は" }; char deta3[] = { "映画" }; char deta4[] = { "が" }; char deta5[] = { "好き" }; int duration = 0; int konnnitiwa = 0; int sitaidou = 0; int sitaidouA = 0; int mozicount = 0; int mozicount2 = 0; int mozicount3 = 0; int rireki = 0; int rireki2 = 0; int LEFTmark = 0; const char* str[2] = { "どんな映画が好きなんですか?","申し訳ございません! "};//ここで文字を直接書いてるので、この文字のバイト数が各posmozi[]に入るだけ int frame[2] = { 10,10};//次の一文字が出るまでのカウンタとして働いている、ここの数値を変えることで文字が一文字ずつ出るまでの間隔を設定できる。 int posmozi[20];//文字のバイト数が入る箱を表している。 int countS[2];//次の文字が出るまでのカウントするためのもの int z;//関数drawString外でも使えるように外にも定義を書いた。zの数値は関係なく、文字列が入った数列がif文により同じ変数zの時にframe[z]と同じになるまで+1されていったり、+2バイトor+1バイトされていくため、 //文字が一文字ずつ入っていく、なんでzの変数に値を入れて動かす必要がないのだ。ちなみにfor (z = 0; z < 3; ++z)で書いてしまうとキーAを押した際のif文に関係なく関数drawStringの最初のzどこかに値が入っただけで繰り返しを開始してしまうため、今回のように同じ変数zの時にフレームを利用して描画するようにした。 char c = str[z][posmozi[z]];//関数drawString外でも使えるように外にも定義を書いた。 void drawString(int z, int x, int y, int color) { c = str[z][posmozi[z]];//posmozi[z] if (countS[z] == 0 && c != '\0') posmozi[z] += IsDBCSLeadByte(c) ? 2 : 1; if (++countS[z] == frame[z]) countS[z] = 0; DrawFormatString(x, y, color, "%.*s", posmozi[z], str[z]); DrawFormatString(300, 300, (0,0,255), "countS[0]は%d", countS[0]); } const char* str2[2] = { "どんな映画が好きなんですか?","申し訳ございません! " };//ここで文字を直接書いてるので、この文字のバイト数が各posmozi[]に入るだけ int frame2[2] = { 10,10 };//次の一文字が出るまでのカウンタとして働いている、ここの数値を変えることで文字が一文字ずつ出るまでの間隔を設定できる。 int posmozi2[20];//文字のバイト数が入る箱を表している。 int countS2[2];//次の文字が出るまでのカウントするためのもの int z2;//関数drawString外でも使えるように外にも定義を書いた。zの数値は関係なく、文字列が入った数列がif文により同じ変数zの時にframe[z]と同じになるまで+1されていったり、+2バイトor+1バイトされていくため、 //文字が一文字ずつ入っていく、なんでzの変数に値を入れて動かす必要がないのだ。ちなみにfor (z = 0; z < 3; ++z)で書いてしまうとキーAを押した際のif文に関係なく関数drawStringの最初のzどこかに値が入っただけで繰り返しを開始してしまうため、今回のように同じ変数zの時にフレームを利用して描画するようにした。 char c2 = str[z2][posmozi[z2]];//関数drawString外でも使えるように外にも定義を書いた。 void drawString2(int z2, int x, int y, int color) { c = str2[z2][posmozi2[z2]];//posmozi[z2] if (countS2[z2] == 0 && c2 != '\0') posmozi2[z2] += IsDBCSLeadByte(c2) ? 2 : 1; if (++countS2[z2] == frame2[z2]) countS2[z2] = 0; DrawFormatString(x, y, color, "%.*s", posmozi2[z2], str2[z2]); DrawFormatString(300, 400, (0, 0, 255), "countS2[0]は%d", countS2[0]); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { SetGraphMode(1500, 780, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 // DXライブラリの初期化 if (DxLib_Init() == -1) return -1; SetFontSize(42); //サイズを42に変更 // 描画先を裏にする SetDrawScreen(DX_SCREEN_BACK); // キー入力ハンドルを作る(キャンセルなし全角文字有り数値入力じゃなし) //MakeKeyInputは開発者の方が一回呼び出せば使えるように作ったのでループ内には書かない。 InputHandle = MakeKeyInput(50, FALSE, FALSE, FALSE); // 作成したキー入力ハンドルをアクティブにする SetActiveKeyInput(InputHandle); // キー入力終了待ちループ // (ProcessMessageをループごとに行う) while (ProcessMessage() == 0) { // 画面の初期化 ClearDrawScreen(); //まずは描画する部分から作る。 // 入力モードを描画 DrawKeyInputModeString(640, 480); // 入力途中の文字列を描画 DrawKeyInputString(0, 0, InputHandle); //その後にif文での分岐を考える。 // 入力が終了している場合は終了 //ループ内とは言えエンターキー一回でCheckKeyInputが呼べればいい。 //エンターキーが押されていないとき?の部分。 if (CheckKeyInput(InputHandle) != 0) { // 入力された文字列を取得 char buffer[256];// // 入力された文字列を取得 GetKeyInputString(buffer, InputHandle); input = buffer; DrawString(0, 0, input.c_str(), GetColor(255, 255, 255)); if (strcmp(input.c_str(), "映画") == 0) { // message = "どんな映画が好きなんですか?"; konnnitiwasound = LoadSoundMem("line-girl1-konnichiha1.mp3"); PlaySoundMem(konnnitiwasound, DX_PLAYTYPE_BACK); ++mozicount; sitaidou = sitaidou + 50; if (mozicount > 0 && mozicount < 2) { z = 0; } if (mozicount > 1 && mozicount < 3) { z2 = 0; } if (mozicount > 2 && mozicount < 4) { z2 = 0; } messageA = message; } else { message = "申し訳ございません!"; situreisimasitasound = LoadSoundMem("line-girl1-moushiwakegozamasen1.mp3"); PlaySoundMem(situreisimasitasound, DX_PLAYTYPE_BACK); ++mozicount; sitaidou = sitaidou + 50; if (mozicount > 0 && mozicount < 2) { z = 1; } if (mozicount > 1 && mozicount < 3) { z2 = 1; LEFTmark = 12; } if (mozicount > 2 && mozicount < 4) { z2 = 1; } } //duration = 1; // 再度インプットハンドルをアクティブにする SetActiveKeyInput(InputHandle); // 入力文字列を初期化する SetKeyInputString("", InputHandle); } // DrawFormatString(100, 150, GetColor(255, 255, 0), "ProcessMessage()は%d,modoruは%d", ProcessMessage(), modoru); DrawFormatString(0, 150, GetColor(255, 255, 0), "zは%d,z2は%d,konnnitiwaは%d,sitaidouは%d,mozicountは%d",z, z2,konnnitiwa, sitaidou, mozicount); DrawFormatString(0, 250, GetColor(255, 255, 0), "mozicount2は%d,input.c_str()は%d, LEFTmarkは%d", mozicount2, input.c_str(), LEFTmark); //新しい言葉の処理 if (rireki == 0) { //文字カウントが1の時 if (mozicount > 0 && mozicount < 2) { drawString(z, 10, 100, GetColor(5, 255, 255)); } } if (rireki == 0) { //文字カウントが2の時 if (mozicount > 1 && mozicount < 3) { drawString2(z2, 10, 100, GetColor(255, 255, 255)); drawString(z, 10, 100+50, GetColor(5, 255, 255)); } } //文字カウントが3の時 if (mozicount > 2&&mozicount < 4) { drawString2(z2, 10, 150+50, GetColor(255, 255, 255)); rireki = 1; } // 裏画面の内容を表画面に反映させる ScreenFlip(); } // 用済みのインプットハンドルを削除する DeleteKeyInput(InputHandle); // 画面の初期化 ClearDrawScreen(); // 裏画面の内容を表画面に反映させる ScreenFlip(); // キー入力待ち // WaitKey(); //ループないやループから出た後で何かしらの問題が発生したら終了する。 // DXライブラリの使用終了 DxLib_End(); // 終了 return 0; }

for文を使い編集してみました。3と入力するとどんな映画が好きなんですか?と出ますが、適当に14356と入力すると無反応です。14356をループして3を見つけたら反応すると思ったのですが。
2020/06/20に編集したプログラム

2020/06/21に編集したプログラム

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

if (strcmp(input.c_str(), "映画") == 0) {

コレをこーする:
if ( input.find("映画") != std::string::npos ) {

投稿2020/06/20 08:19

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KZK13

2020/06/20 08:27

ありがとうございます。 まるで文字列から特定の言葉を抽出するような複雑な過程を挟むと思っていたのですが、 std::string::nposを書き足しただけとは驚きました。 どうやってstd::string::nposの存在を調べたのですか? 多分C++の関数とは思うのですが、難しいことがここまで簡単にできるC++には恐ろしさすら感じます。 またできればなぜ編集後のforの文法ではだめなのか理由が知りたいです。
KZK13

2020/06/20 09:03

ちなみに、C++の関数の力を使い、入力した言葉からプログラムが自ら文字列を作るようなプログラムは組めないでしょうか?
episteme

2020/06/20 11:59 編集

> どうやってstd::string::nposの存在を調べたのですか? マニュアルに書いてある。 > 編集後のforの文法ではだめなのか理由が知りたいです。 for (i = 0; i < 3; ++i) { if (strcmp(input.c_str(), "3") == 0) { これ↑のこと? 逆に伺いますが、strcmp(input.c_str(), "3") == 0 が真となる条件は? > 、C++の関数の力を使い、入力した言葉からプログラムが自ら文字列を作るようなプログラムは組めないでしょうか? 「入力した言葉からプログラムが自ら文字列を作る」の意味がわかりません。 入力: "XXX" に対して単に "へー、XXXなんですか。すごいですねー" を作るのなら C でもできるけど、 そんなこっちゃないんでしょ?
KZK13

2020/06/20 13:51

説明が下手ですみません。 例えば、映画が好きです!と入力すると 映画、好き、という言葉からプログラムが映画が好きですという入力に対して、 どんな映画が好きなんですか?とか最近のおすすめの映画は何ですか?と聞き返すようなプログラムを組めないかなと思いました。 もちろん、入力: "XXX" に対して単に "へー、XXXなんですか。すごいですねー"という返事を人工知能?というかプログラム自体が考えて返事するのも良いと思います。
episteme

2020/06/20 15:50 編集

"映画は好きじゃない" / "映画が好きなんですか?" / ”「あなたが大好き」という映画を観ました" に対してはどう反応するんです? 日本語の語彙と文法の解釈抜きに、ただ単語を抽出するだけでは無理じゃないかしら。 自然言語の理解ってものすごく難しいはず(真面目/厳密/正確にやるなら)。 特に日本語は膠着語だから語順で判断できないし。
KZK13

2020/06/20 14:52 編集

確かにその通りです。シンプルに解決できないかなといろいろ考えてはいるのですが、とても難しいです。 >>strcmp(input.c_str(), "3") == 0 が真となる条件は? input.c_str()に入力された文字列の中に3が入っていた場合、真になる。としたかったのですが、 どうやら3のみ入力したときにしか真にならないとなりました。 書いたようにしかプログラムが動かないのは承知しています。 編集後のプログラムで行いたかったことは、入力した文字列(例えば123など)が配列に入り、その文字列をいくつかの配列に分けます。a[0]が1、a[1]が2、a[2]が3と分けて、とあらかじめ用意していた文字の配列(例えば3)と比較した時に、入力した数字とa[2]の3が一致するので、真になるようなプログラムと組みたかったです。 関数を使えば簡単に解決できますが、関数ではなく、実際に以上のような過程の配列の部分を勉強のために書きたいと思いました。
episteme

2020/06/20 15:02

>> strcmp(input.c_str(), "3") == 0 が真となる条件は? > input.c_str()に入力された文字列の中に3が入っていた場合、真になる。としたかったのですが、 > どうやら3のみ入力したときにしか真にならないとなりました。 そのとおり。 strcmp(x, y) では xにyが含まれているか は判定できません。 > 関数を使えば簡単に解決できますが、関数ではなく、実際に以上のような過程の配列の部分を勉強のために書きたいと思いました。 だったら ”簡単に解決できる(であろう)やりかたで正しく動作することを確認" してから 実際に以上のような過程の配列の部分を勉強のために書けばいいじゃない。 「XX使えばうまくいく」を確認せずに 「XXを自分で書いてみよう」はナンセンスじゃない? 学習のしかたが間違っていませんか?
KZK13

2020/06/20 15:26

学習の仕方が間違っていました。 ただ私の場合、関数もまともに扱えないですし、だからといって一からコードも書けません。 私のような人間は一から作るのではなく、関数の使い方をもっと勉強して使う側になるしかないのだと思います。 あの、関数strcmpの中身がどのようになっているのかを表したコードなどはサイトにないでしょうか?
episteme

2020/06/20 15:48 編集

https://hisasys.com/clang-strcmp-self-made/ > 関数もまともに扱えないですし、だからといって一からコードも書けません。 諦めるのですか? 人様から貰ったコードのツギハギであなたの望むプログラムが作れるのですか? 関数をまともに扱えないと望むプログラムは作れないでしょ? 一からコード書けないと望むプログラムは作れないでしょ?
KZK13

2020/06/20 16:25

諦めたくはないですが、 私はepistemeさんのように賢くありません。 現実を見ないと理想ばかりにすがることになります。 人様からもらったコードをツギハギで作ることは良いことではないですが、私にはこんなやり方しか出来ません。
KZK13

2020/06/20 16:27

コードが載せてあるサイトをどうもありがとうございます。
episteme

2020/06/20 16:33

> 人様からもらったコードをツギハギで作ることは良いことではないですが、私にはこんなやり方しか出来ません。 良い悪い以前に、不可能じゃありませんか?
KZK13

2020/06/20 16:41

はい、不可能です。 何も言い返せません。 epistemeさんのようなベテランの方に相談しないと私は何も出来ない腑抜けです。
episteme

2020/06/20 16:57

ならば諦めるか、作れるようになるかの二択です。貰ったコードのツギハギでは作れないんだから。
KZK13

2020/06/20 17:01 編集

諦めは悪いので、出来の悪い頭で諦めることのないように作りたいというのが願望です。 ツギハギで仮に作れても何も楽しいことはないです。 こんな私の話に付き合って頂きありがとうございます。
episteme

2020/06/20 17:17

ではその願望を実現してください。他の誰でもない、「あなた」の責務です。
kazuma-s

2020/06/20 17:33

https://hisasys.com/clang-strcmp-self-made/ 残念ながらこのリンクにある strcmp のコードは規格違反です。 printf("%d\n", strcmp("ab", "aア")); printf("%d\n", my_strcmp("ab", "aア")); 結果の正負が異なります。 C の規格書 JIS X3010:2003 (ISO/OEC 9899:1999) には、 ------------------------------------------------------------- 7.21.4比較関数 比較関数 memcmp,strcmp 及び strncmp が返す 0 以外の値の符号は, 比較対象のオブジェクトにおいて最初に異なる文字の対(いずれの文字の 型も unsigned char として解釈する。)の値の差の符号によって決定する。 ------------------------------------------------------------- とあるのに、unsigned char ではなく、char で比較しているからです。
KZK13

2020/06/20 18:11 編集

epistemeさん、kazuma-sさん解答ありがとうございます。 epistemeさんから頂いたサイトのプログラムは if (*s1 == '\0') { return 0; } の部分が原因であるためか入力した文字、あるいは文字列が一致した際に0の値が返されるので、その時点で関数の呼び出しが終了してしまうと思います。なので、 編集後の if (my_strcmp(input.c_str(), "映画") == 0&& my_strcmp(input.c_str(), "好きです") == 0)の部分で映画という単語は一致しますが、二つ目の好きですという単語は一致以前に関数が終了してしまうため真になりません。 どうか真でも関数が終了しないように書けないでしょうか。
KZK13

2020/06/21 04:12

// 自作文字列比較関数 int my_strcmp(const char* s1, const char* s2) { // 先頭から走査して差があればループ終了 for (; *s1 == *s2; s1++, s2++) { // 終了前に終端文字が見つかったら差分なし if (*s1 == '\0') { return 0; } } return *s1 > * s2 ? 1 : -1; } ってことは、おっしゃる様に*s1 == *s2; s1++, s2++の部分は文字が一致した際にお互いが繰り上がるだけで判断はしていまいのでしょうか? 確かに*s1 == *s2; s1++, s2++の時の処理内容が書いていなうため判断できないのは当然だと思います。 サイトありがとうございます。載せて頂いたサイトのstrstrを使えばよいのでしょうか?
episteme

2020/06/21 04:56

> おっしゃる様に*s1 == *s2; s1++, s2++の部分は文字が一致した際にお互いが繰り上がるだけで判断はしていまいのでしょうか? それわざわざ訊くこと? > 載せて頂いたサイトのstrstrを使えばよいのでしょうか? それわざわざ訊くこと? 許しをもらわんとなんもできんの?
KZK13

2020/06/21 05:07

いえ、そうではなく。strstrを使いましたが、プログラムが正しく動かなかったので、strstrでいいのかなと返しました。 >>*s1 == *s2; s1++, s2++の部分は文字が一致した際にお互いが繰り上がるだけで判断はしていまいのでしょうか? いや、見れば一発でわかるのでわざわざ聞くことではありませんでした。
KZK13

2020/06/21 05:12

質問自体は解決したので、ここはベストアンサーにして、再度新しい質問を作ります。
episteme

2020/06/21 05:12

> プログラムが正しく動かなかったので、strstrでいいのかなと返しました。 僕は strstr で正しく動くことを確認しました。
episteme

2020/06/21 05:15

それわざわざ訊くこと?
KZK13

2020/06/21 05:23

すいません。なにかしら私の不手際でstrstrを使ったにも関わらず正しく動くことを確認できませんでした。
episteme

2020/06/21 07:37

> if ( strcmp(input.c_str(), "映画") == 0) { コレを strstr 使って 「input.c_str() が "映画" を含むか判定する」 だけ。
guest

0

入力した文字列をトークンに分けるという部分がどう作ってよいのかわかりません。

そこをどうするのか、まずはあなたが決めましょう。
日本語のベタ打ち文を単語に分ける、というのは、ここでちょっと回答して実装できるってもんじゃありません
日本語解析を頑張ってください、としかいいようがないですね

投稿2020/06/20 07:29

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KZK13

2020/06/20 08:11

なるほど、やはり難しいですよね。 どうもありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問