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

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

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

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

Q&A

解決済

4回答

3460閲覧

一致する文字列の数をカウントしたい

h_proc

総合スコア68

C

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

0グッド

0クリップ

投稿2019/02/12 09:01

ある文字列aのなかに、文字列bがいくつ含まれているかカウントする関数を作っています。

c

1#include<stdio.h> 2 3int count_key(char a[],char b[]); 4int count = 0; 5int count_key(char a[], char b[]) { 6 7 for (int i = 0; a[i] != '\0'; i++) { 8 if (a[i] == b[i]) { 9 count++; 10 } 11 else { 12 //NR 13 } 14 } 15 16 return count; 17} 18int main(void) { 19 printf("Please input some letters.\n"); 20 21 char input[200]; 22 char search[20]; 23 scanf("%s", input); 24 25 printf("Please input some words you want to find.\n"); 26 27 scanf("%s", search); 28 29 count_key(input, search); 30 31 printf("文字列%sは%d個含まれています。\n", search, count); 32 33 return 0; 34}

このようなコードを作ったのですが、配列と文字列の関係がよく分かっていないため、質問させていただきたいことが2つあります。
➀8行目のコードは、文字列bを構成している1文字ずつと一致する文字を文字列aから探していることにならないのでしょうか。例えば文字列inputに
youareyouyouareyou
と入力し、文字列search にyouを入力したら、
このコードだと、文字yが何個含まれているか探すことにならないのでしょうか。
➁上の例で実行してみた結果文字列youは3個含まれると表示されました。文字列aに何個youを入力しても実行結果はいつも3個です。なぜでしょうか。どう直したらよいのかも教えていただきたいです。

よろしくお願いいたします。

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

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

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

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

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

cateye

2019/02/12 09:12 編集

前(https://teratail.com/questions/173716)にも書いたのですが、scanf()は、最初の空白までしか読み込みません。"abc efg"を読むと文字列としては "abc" になりますがいいのですか?
h_proc

2019/02/12 09:58

文字列aには空白を入れずに入力をすることを想定しています。
guest

回答4

0

標準関数に文字列を比較したり、検索したりする関数がありますが、それを使わないで自分で書くとすると、

文字列を扱うためには、添え字を使いながら1文字ずつ見ていく必要があります(ポインタを使う方法もありますが)。
2つの文字列を使うので、forループを2つ使う必要があります。
2つの文字列の関連を調べるので、2つのforループは並列では無くて、入れ子(二重のforループ)にする必要があります。
こんな感じ。

C

1for(i=0; a[i]; i++){ 2 for(j=0; b[j]; j++){ 3 ・・・・

scanfについては他の方の回答の通り、fgetsにする必要があります。

投稿2019/02/12 13:10

otn

総合スコア84499

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

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

0

ベストアンサー

流れを想像で追ってみましょう.
a="youareyouyouareyou"
b="you"
とします.

C

11: for (int i = 0; a[i] != '\0'; i++) { 22: if (a[i] == b[i]) { 33: count++; 44: } 55: }

1: 1行目, i=0 で i が 0 になる. a[0]='y' なので a[0]!='\0' は成立. ループ実行
2: 2行目, a[0]='y', b[0]='y' なので成立. if 文の中を実行
3: 3行目, count ++ で ** count が 1 になる **
4: 4行目, if 文終了
5: 5行目, for 文繰り返し
6: 1行目, i ++ で i が 1 になる. a[1]='o' なので a[1]!='\0' は成立. ループ実行
7: 2行目, a[1]='o', b[1]='o' なので成立. if 文の中を実行
8: 3行目, count ++ で ** count が 2 になる **
9: 4行目, if 文終了
10: 5行目, for 文繰り返し
11: 1行目, i ++ で i が 2 になる. a[2]='u' なので a[2]!='\0' は成立. ループ実行
12: 2行目, a[2]='u', b[2]='u' なので成立. if 文の中を実行
13: 3行目, count ++ で ** count が 3 になる **
14: 4行目, if 文終了
15: 5行目, for 文繰り返し
16: 1行目, i ++ で i が 3 になる. a[3]='a' なので a[3]!='\0' は成立. ループ実行
17: 2行目, a[3]='a', b[3]='\0' なので不成立. if 文の中を実行 しない
18: 4行目, if 文終了
19: 5行目, for 文繰り返し
20: 1行目, i ++ で i が 4 になる. a[4]='r' なので a[4]!='\0' は成立. ループ実行
21: 2行目, a[4]='r', b[4]= 配列が終わっているため値不明 なので(256分の255の確率で)不成立. if 文の中を実行 しない
22: 4行目, if 文終了
23: 5行目, for 文繰り返し
24: 1行目, i ++ で i が 5 になる. a[5]='e' なので a[5]!='\0' は成立. ループ実行
25: 2行目, a[5]='e', b[5]= 配列が終わっているため値不明 なので(256分の255の確率で)不成立. if 文の中を実行 しない
26: 4行目, if 文終了
27: 5行目, for 文繰り返し

(略)

?: 5行目, for 文繰り返し
?: 1行目, i ++ で i が 18 になる. a[18]='\0' なので a[18]!='\0' は不成立. ループ終了

このように動いていると思います.
問題の箇所がお分かりでしょうか.
a の中で b を探す時, h_proc さんはどのように探されていますか?
ご自分の思考を意識して, その過程をコードと同じ粒度まで細分化できれば, どうすれば良いのか見えてくると思います.

投稿2019/02/12 09:52

編集2019/02/12 09:59
jimbe

総合スコア12632

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

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

h_proc

2019/02/12 10:02

ありがとうございます。 i=4の時にb[1]に戻って再度一致する文字列を検索させたいです。そのためにはまたループを使ったらよいのでしょうか。
h_proc

2019/02/12 10:27

int count_key(char a[], char b[]) { for (int k = 0; a[k] != '\0'; k++) { int n = 0; for (int i = 0; b[i] != '\0'; i++) { if (a[k] == b[i]) { n += 1; } else { n = n; } } if ((n % 3) == 0) { count++; } else { //NR } } return count; } このように書き換えてみたのですが、動かなかったです。ループの条件が間違っているのでしょうか。
mather

2019/02/12 10:28

横から失礼します。 a = "youayou" b = "you" のときにカウントは2になってほしいと思うのですが、このように次の先頭位置が必ず一致するとは限りませんよね?'y' が一致する場所を探す必要があるはずです。 また、配列は0番目から始まることにも注意しましょう。
jimbe

2019/02/12 11:17 編集

2重ループにするのは, 私の想像するコードとは一致しています. 含みがあるのは, この種のアルゴリズムは細かくは色々あると思われるからです. コードを修正されましたら, また流れを想像で追ってみてください. 想像が大変でしたら, 一行毎に printf を入れて, その場所で注目すべき変数の値を表示してみてください. 「この位置ではこの変数はこの値になっていて欲しいのに違う」となれば, なぜ違うのかを調べて修正し, また流れを追ってください. この繰り返しがデバッグの基本と思います.
h_proc

2019/02/13 13:09

コメントに書いたコードを一行ずつ表示させたところ、内側のループを繰り返しても、nの値が1のままで増加していないことが分かりました。nに1が足されない原因はどこにあるのでしょうか。教えていただきたけると嬉しいです。よろしくお願いいたします。
jimbe

2019/02/13 18:21

内側のループの中の if 文の条件に使用している変数は, h_proc さんの想像と同じだったでしょうか? a[k] と b[i] の比較ですが, ループの何周目に何処と何処の文字を比較するのかを表す, 添字 k と i の値の変化がとても重要です. 失礼な言い方になりますが, 良い所まで来ています. ここで気付けるかどうかが山場かと思います.
h_proc

2019/02/14 06:18

無事解決しました。丁寧に教えていただき、本当にありがとうございました。
guest

0

ヒントだけ書きます。
1.c言語の文字と文字列について理解すること。
2.文字列の比較には標準関数のstrcmpやstrncmpが使えること。
以上です。

投稿2019/02/12 09:29

ikapy

総合スコア1167

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

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

0

①一致する文字数を数えているだけです。
なので②"you"は3文字です。
scanf()の仕様を確認してください。あと、fgets()+strstr()で解決できるはずです。
使う(標準)関数は必ず仕様を確認するように d^^
C言語 標準関数

投稿2019/02/12 09:24

編集2019/02/12 09:37
cateye

総合スコア6851

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

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

cateye

2019/02/12 11:31

ヒントを一つ、何処まで探したか覚えておくようにしましょう。あと、"aaa"から"aa"を探す場合、1とするのか2とするのかを決めておきましょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問