ワイルドカード

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Haru

ワイルドカード

#1

投稿記事 by Haru » 17年前

お久しぶりです。Haruです。
少しだけ、C言語はなれて違う勉強してましたが、戻ってきました...
と言うわけで、実はまだワイルドカードを作ってます...
'*'(0文字から何文字でも)と'?'(1文字)
はそれぞれできるようになったんですが、'*'と'?'を組合わせて
使う事が未だにできません。
どうか、アドバイスをお願いします。
int new_wild(char *entry, char *wild_name)
{
	int w_len , e_len, i = 0 , j = 0, g ;
	char *start , *start2 , *end , *end2;
	char *buf = (char*)malloc(sizeof(char)*(strlen(wild_name + 1)));

	if( buf == NULL )
	{
		free( buf );
		return 1;
	}
	
	w_len = strlen( wild_name );
	e_len = strlen( entry );

	if(( wild_name[0] != '*' ) && ( wild_name[0] != '?'))
	{
		if( wild_name[0] != entry[0]) //検索文字列と検索対象文字列の最初と最後の文字
		{               //が、同じか'?'か'*'でなければ不一致	              	free( buf );            
			return -1;
		}
	}
	if((wild_name[ w_len - 1 ] != '*' ) && ( wild_name[ w_len - 1 ] != '?'))
	{
		if(wild_name[ w_len - 1 ] != entry[ e_len - 1 ])
		{
			free( buf );
			return -1;
		}
	}
	strcpy( buf , wild_name );
	start = buf ;
	for(i = 0 ; i < w_len; i++)
	{
		if(wild_name == '*')
		{
			while( *start)
			{
				end = strchr( start ,'*' );
				if( end )
				{
					*end = '\0';
				}
				if(( entry = strstr( entry , start )) == NULL )
				{
					free( buf );
					return -2;
				}
				entry += strlen( start );
				start += strlen( start ) + 1 ;
			}
		}
		if(wild_name == '?')
		{	
			if(wild_name != '*') //検索文字列に*がなかった場合検索文字列と
			{            //対象文字列の長さを比較し違っていたら不一致
				if(w_len != e_len)
					return -1;
			}
			for( g = 0; g < w_len; g++)
			{
				if(entry[g] != wild_name[g])
				{
					if((wild_name[g] != '?') && (wild_name[g] != '*'))
					{	
						return -1;
					}
				}
			}
		}
		j++;
	}
printf("DEBUG i = %d  j = %d \n",i,j);
	return 0;
}

Haru

Re:ワイルドカード

#2

投稿記事 by Haru » 17年前

自己解決しました!!

Haru

Re:ワイルドカード

#3

投稿記事 by Haru » 17年前

解決にし忘れました(汗

toyo

Re:ワイルドカード

#4

投稿記事 by toyo » 17年前

質問しようと書き込みながらチェックしてると解決することがありますよね
気づいた点を
”freeを忘れないで”

Mist

Re:ワイルドカード

#5

投稿記事 by Mist » 17年前

自己解決された場合は、情報の共有として何が悪かったのか、どう直したか等を書いていただきたいです。
そうすることで、これから先Haruさんと似たような疑問をもたれた方がここにこられたとき、わざわざ質問しなくても過去ログを見ることで解決できるようになりますので。

Haru

Re:ワイルドカード

#6

投稿記事 by Haru » 17年前

>Mistさん 

すいません。このやり方だと無理だと思ったんで、考え方変えて作ってしまったんで、
もし考えてくださった方がいたら逆に申し訳ないな...と思い・・・つい(汗
と、いうのと、まだバグが残っているので...
すいませんでした。

>toyoさん 

ありますね!今回は質問の回答待ち中に、視点を変えて考えてたら、
意外と理論だけならあてはまるかも?と、思い考えたアルゴリズムを元に
作ってみたらうまくいきました!!


#ちなみにバグというのは、検索対象文字が、aaaaaといったような場合
#*aで調べると一文字目のaでマッチしてしまいます。
#同一文字が並んでいる文字列等に対応できません。


int new_wild(char *entry, char *wild_name)
{
int w_len , e_len, i = 0 , j = 0, g , check;
char *start , *start2 , *end , *end2;

w_len = strlen( wild_name );
e_len = strlen( entry );

if(( wild_name[0] != '*' ) && ( wild_name[0] != '?')) //検索文字列と検索対象文字列の最初と最後の文字が一致
{ //または'?'か'*'でなければ不一致
if( wild_name[0] != entry[0])
{
return -1;
}
}
if((wild_name[ w_len - 1 ] != '*' ) && ( wild_name[ w_len - 1 ] != '?'))
{
if(wild_name[ w_len - 1 ] != entry[ e_len - 1 ])
{
return -1;
}
}
do
{
if((j > w_len) || (i > e_len))
{
return -1;
}

//検索文字にwild_card*があった場合は、次の1文字を見る。

if(wild_name[j] == '*')
{
j++;
while(1)
{

//一文字先がワイルドカードでなければ、検索対象文字entryと、wild_cardの*の次の文字が一致するまで一文字づつ比較


if((wild_name[j] != '?') &&(wild_name[j] != '*'))
{
while(wild_name[j] != entry)
{
i++;
if(i > e_len)
{
return -1;
}
}
break;
}

//一文字先が?であった場合、?は1文字なので、wild_card、entry共に1文字づつ進む。

else if(wild_name[j] == '?')
{
i++;
j++;
if((j > w_len) || (i > e_len))
{
return -1;
}
}

//一文字先が*であった場合はwild_cardの更に1文字次の文字を見る

else if(wild_name[j] == '*')
{
j++;
if(j > w_len)
{
return -1;
}
}
}
}
//現在見ている文字が、ワイルドカード文字でなければ、比較し、一致していなければ不一致

else if(wild_name[j] != '?')
{
if(wild_name[j] != entry)
{
return -1;
}
}
i++;
j++;
}while(i < e_len || j < w_len);
return 0;
}

フリオ

Re:ワイルドカード

#7

投稿記事 by フリオ » 17年前

 
 これでどうでしょう。
対象文字列(str)と検索パターン(pat)を頭から順に比較するという
正攻法(力任せ?)で処理しています。
int Match(const char *str, const char *pat)
{
	const char *ast = NULL, *stmp;
	
	while(*str){
		if(*pat == '*'){
			if(!*++ pat) return 1;
			ast = pat;
			stmp = str;
		}
		else if(*pat == '?' || *pat == *str){
			str ++;
			pat ++;
		}
		else{
			if(!ast) return 0;
			pat = ast;
			str = ++ stmp;
		}
	}
	while(*pat == '*') pat ++;
	return !*pat;
}

Haru

Re:ワイルドカード

#8

投稿記事 by Haru » 17年前

>フリオさん

お返事遅くなってすみません
ありがとうございます。
早速考察してみます!それと、質問なんですが、
else
{
     if(!ast) return 0;
	pat = ast;
	str = ++ stmp;
}
この文のif(!ast)はどのような略なんでしょうか?

御津凪

Re:ワイルドカード

#9

投稿記事 by 御津凪 » 17年前

if(!ast)
は、
if(ast == NULL)
と同じです。

ココでは最初のパターンに一致しなかった時のみ 0 を返すはずです。

ちなみに、上の方のコードにも似たような部分があり、
if(!*++ pat)
は、
if(*++pat == NULL)
で、
++pat;
if(*pat == NULL)
と同じ意味です。

いけやん

Re:ワイルドカード

#10

投稿記事 by いけやん » 17年前

もうすでに御津凪さんが、答えられてますが(汗

素人の自分が答えるのも何ですが・・・

if(!ast)は
if(ast == NULL),if(ast == 0)と同じで偽の場合
逆にif(ast)と書けば
if(ast == TRUE),if(ast == 1)と同じで真の意味で使えた様な・・・気がします。

Haru

Re:ワイルドカード

#11

投稿記事 by Haru » 17年前

>御津凪

解説ありがとうございます!!
こうゆう、略した形を教えてくれるサイトとかって、ないですかね...(^^;
今グーグル先生に聞いてみたんですが、
聞き方が悪かったのか、知らないって言われちゃいました...orz


#2回目のソースpreタグ使い忘れました。見にくくてすいませんでした。

御津凪

Re:ワイルドカード

#12

投稿記事 by 御津凪 » 17年前

> if(ast == TRUE),if(ast == 1)と同じで真の意味で使えた様な・・・気がします。
真偽の判定基準は 0 か 1 かでは無く、
0 か非 0 かです。(ほとんどの場合)

なので、ココの例では、
if(ast == TRUE) 及び if(ast == 1)では
if(ast) と結果が変わります。

正しくは、
if(ast != NULL)
でしょう。

> こうゆう、略した形を教えてくれるサイトとかって、ないですかね...(^^;
> 今グーグル先生に聞いてみたんですが、
> 聞き方が悪かったのか、知らないって言われちゃいました...orz
確かに入門書でも見かけないですね。
しかし、どういう意味を持つのかを自分で書いて確認することは出来ます。
たとえば、
void show_if_result( int i ){
	if(i){printf("if(%d) -> true\n",i);}
	else {printf("if(%d) -> false\n",i);}
	if(!i){printf("if(!%d) -> true\n",i);}
	else  {printf("if(!%d) -> false\n",i);}
	if(i == 0){printf("if(%d == 0) -> true\n",i);}
	else      {printf("if(%d == 0) -> false\n",i);}
	if(i != 0){printf("if(%d != 0) -> true\n",i);}
	else      {printf("if(%d != 0) -> false\n",i);}
	if(i == TRUE){printf("if(%d == TRUE) -> true\n",i);}
	else         {printf("if(%d == TRUE) -> false\n",i);}
	if(i != TRUE){printf("if(%d != TRUE) -> true\n",i);}
	else         {printf("if(%d != TRUE) -> false\n",i);}
	/* 以下、試してみたい式を追加... */
}
のような関数をつくり、関数に色々な値を渡してみると、
どういう動作なのかが分かるかと思います。
もちろん int の部分を int* 変えて実行すると、今回の動作も分かってくると思います。
(この例ではprintfを使うので、コンソールアプリケーションで実行してください)

Haru

Re:ワイルドカード

#13

投稿記事 by Haru » 17年前

>御津凪さん

おわっ!!失礼しました!
「さん」をつけ忘れました!!


>...のような関数をつくり、関数に色々な値を渡してみると、
>どういう動作なのかが分かるかと思います。

ありがとうございます!
こんな風にして調べれば良いんですね!!
本当に勉強になります!

>>いけやんさん

入れ違いでレスを読み落としてました。
ありがとうございます!!

いけやん

Re:ワイルドカード

#14

投稿記事 by いけやん » 17年前

御津凪さん。すいません。
>真偽の判定基準は 0 か 1 かでは無く、
>0 か非 0 かです。(ほとんどの場合)
そうですね、0「以外」が返って来るんでしたね。

Haruさんすいません。
>if(ast != NULL)
御津凪さんのを参考に。

>こんな風にして調べれば良いんですね!!
確かに。

>>のような関数をつくり、関数に色々な値を渡してみると、
>>どういう動作なのかが分かるかと思います。
ためになります。

フリオ

Re:ワイルドカード

#15

投稿記事 by フリオ » 17年前

 
 一点だけ、

"if(*++pat == NULL)"ではなく、"if(*++pat == '\0')"です。
 

閉鎖

“C言語何でも質問掲示板” へ戻る