ページ 11

照合

Posted: 2009年5月21日(木) 23:15
by Luck
こんばんは。
早速ですが、下記のプログラムで、おおよそ、
キーワードを入力して、そのキーワードを含む文字を探す
見つからない場合はNULLを返す。
と言う内容なのはわかりました。

おおよその把握しか出来てませんので、どなた様か解説をお願いできませんか?

:環境:
Windows XP
Visual C++2008 Expres Edition

#include<stdio.h>
#include<string.h>

char *search(char *,char *);

void main(void)
{
	static char text[/url]=" 文字列や文章等";
	char *p, *key="キーワード";

	p=search(text,key);   //特にこのあたりからよくわかりません。
	while (p!=NULL){
		printf("%s\n",p);
		p=search(p+strlen(key),key);
	}
}
char *search(char *text, char *key)
{
	int m,n;
	char *p;

	m=strlen(text);
	n=strlen(key);
	for(p=text;p<=text+m-n;p++){
		if(strncmp(p,key,n)==0)
			return(p);
	}
	return(NULL);
}
解説の程、よろしくお願いします。

Re:照合

Posted: 2009年5月22日(金) 00:01
by kazuoni
おおよそというよりは、
キーの文字列が含まれていたら、
文字列のそのキーを含むところから最後までを出力するですかね。
例えば
キー:int
文字列:intfloatintdoubleintchar

だと出力は
intfloatintdoubleintchar
intdoubleintchar
intchar

ですかね。

>//特にこのあたりからよくわかりません。
関数searchが理解できないということでしょうか?
おおよそこんなことをやってます。
・文字列とキーの長さを求める(それぞれm,n)
・「文字列」-「キー」の長さがキーの長さより小さくなったNULLをリターン
・「文字列」-「キー」の長さがキーの長さより大きい時、
 文字列の先頭からキーの長さ分、同じ文字があるかどうか比較(strncmp参照)
 ・キーと一致したら文字列の先頭のアドレスをリターン
 ・一致しなければポインタを進める。

例えば上の例なら、
search一回目

text="intfloatintdoubleintchar"
key="int"

m=24,n=3

p
↓
i ntfloatintdoubleintchar

strncmp=strcmp("int",key) 合致!

return p(=intfloatintdoubleintcharの先頭のアドレス)

二回目

text="floatintdoubleintchar"
key="int"

m=21,n=3

p
↓
f loatintdoubleintchar

strncmp=strcmp("flo",key)合致しない!

p
↓
l oatintdoubleintchar

strncmp=strcmp("loa",key)合致しない!

...以降繰り返す



...

p
↓
i ntdoubleintchar

strncmp=strcmp("int",key) 合致!

return p(=floatintdoubleintcharの初めに出てくるintのの先頭のアドレス)


ってな感じです。
探査終了の条件は、
条件はpの指すところから終わりまでの文字数が3をきったら
終了します。
今回の例でいえば、

p
↓
a r
の地点まできたら終了です。

Re:照合

Posted: 2009年5月22日(金) 20:21
by Luck
ご丁寧にありがとうございます。
searchについて詳しくわかりました。

同じところで迷っている友人に、わかりやすく説明したいのですが、
各行に何をしているかというコメントを付けていただけませんか?

自分は説明が下手で、なかなかうまく伝えられません。
図々しくてすみませんが、よろしくお願いします。

Re:照合

Posted: 2009年5月22日(金) 20:40
by kazuoni
コメントを書いてもらうよりは、
上で書いたことを自分の手で書きこんでいったほうが
間違いなく効率が良いです。
コメントを加えるといっても数行なので、大変ではないはずです。

Re:照合

Posted: 2009年5月22日(金) 21:34
by Luck
お返事ありがとうございます。
頑張ってコメント付けてみようと思います。

書いていただいた

・文字列とキーの長さを求める(それぞれm,n)
・「文字列」-「キー」の長さがキーの長さより小さくなったNULLをリターン
・「文字列」-「キー」の長さがキーの長さより大きい時、
 文字列の先頭からキーの長さ分、同じ文字があるかどうか比較(strncmp参照)
 ・キーと一致したら文字列の先頭のアドレスをリターン
 ・一致しなければポインタを進める。

ですが
p=search(text,key);
から
return(NULL);
}(最後)

で行われている処理でしょうか?

あと、ここのfor文あたりがちょっと理解しがたいです。
char *search(char *text, char *key)
{
	int m,n;
	char *p;

	m=strlen(text);
	n=strlen(key);
	for(p=text;p<=text+m-n;p++){ //←ここのfor文です。
		if(strncmp(p,key,n)==0)
			return(p);
	}
	return(NULL);
}




下らなくてすみませんが、お教え願います。

Re:照合

Posted: 2009年5月23日(土) 00:59
by kazuoni
> 書いていただいた
>
> ですが
> p=search(text,key);
> から
> return(NULL);
> }(最後)
>
> で行われている処理でしょうか?

search関数に入ってから抜けるまでに行われていることを書きました。
その下で、例を挙げて解説しています。

> あと、ここのfor文あたりがちょっと理解しがたいです。

No:33818より自分はうまく解説できる気がしません。。
まず、ペンで紙に書きながら処理を一つ一つ追っていってください。
自分で文字列とキーを用意して、
一回目にsearch関数に入ったらどうなるか見ていってください。
他人に言われるよりは、自分で理解していったほうが効率が良いです。
(さっきもこれ書きましたね・・・。)

もし違っていたら申し訳ないですが・・・。
以下のことは理解していますか?

・関数
・ポインタ
・文字列

もし理解できていないのならば、
一度基礎を学習してみてください。
でないと、根本が理解できず、他人に教えることは恐らくできません。

Re:照合

Posted: 2009年5月23日(土) 09:15
by たいちう
> searchについて詳しくわかりました。
>
> 同じところで迷っている友人に、わかりやすく説明したいのですが、
> 各行に何をしているかというコメントを付けていただけませんか?
>
> 自分は説明が下手で、なかなかうまく伝えられません。

「理解した」と「理解したつもり」の違いは自分では分かりにくいかもしれませんが、
人に説明しようとするときに、違いがはっきりします。
自分の言葉で説明できない以上は、まだ「理解できていない」としっかり認識し、
理解を深めてください。
私の言葉の定義だと(守秘義務とかのあれこれを除き)
「理解しているけど説明できない」という状況はありえません。

kazuoniさんが指摘されている「関数・ポインタ・文字列」についても、
「理解したつもり」なだけではないですか?
完全に理解するのはまだ先でも良いですが、ある程度は理解していないと
その上により高度な内容(今回のプログラムなど)を積み上げられません。

・基礎的な事を復習する
・他人に説明する

どちらも理解を深めるためには有効な手段です。
今回たまたま手を抜いているだけならいいのですが、
(コメントまで付けてもらおうとか)常に他力本願だと、
理解する力が育ちませんよ。
自分の理解度を分析することで、自力解決できる問題も増えるはずです。

# なんか説教モードに入ってしまったみたいですが投稿しちゃえ。
# それと「searchについて詳しくわかりました」というのは、
# きっと回答者に謝意を伝えたかったのもあるんだよね。