ページ 1 / 1
ワイルドカード
Posted: 2008年9月09日(火) 10:51
by Haru
お久しぶりです。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;
}
Re:ワイルドカード
Posted: 2008年9月09日(火) 16:56
by Haru
自己解決しました!!
Re:ワイルドカード
Posted: 2008年9月09日(火) 16:58
by Haru
解決にし忘れました(汗
Re:ワイルドカード
Posted: 2008年9月09日(火) 18:54
by toyo
質問しようと書き込みながらチェックしてると解決することがありますよね
気づいた点を
”freeを忘れないで”
Re:ワイルドカード
Posted: 2008年9月09日(火) 19:28
by Mist
自己解決された場合は、情報の共有として何が悪かったのか、どう直したか等を書いていただきたいです。
そうすることで、これから先Haruさんと似たような疑問をもたれた方がここにこられたとき、わざわざ質問しなくても過去ログを見ることで解決できるようになりますので。
Re:ワイルドカード
Posted: 2008年9月10日(水) 09:52
by Haru
>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:ワイルドカード
Posted: 2008年9月10日(水) 16:03
by フリオ
これでどうでしょう。
対象文字列(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;
}
Re:ワイルドカード
Posted: 2008年9月11日(木) 10:26
by Haru
>フリオさん
お返事遅くなってすみません
ありがとうございます。
早速考察してみます!それと、質問なんですが、
else
{
if(!ast) return 0;
pat = ast;
str = ++ stmp;
}
この文のif(!ast)はどのような略なんでしょうか?
Re:ワイルドカード
Posted: 2008年9月11日(木) 10:37
by 御津凪
if(!ast)
は、
if(ast == NULL)
と同じです。
ココでは最初のパターンに一致しなかった時のみ 0 を返すはずです。
ちなみに、上の方のコードにも似たような部分があり、
if(!*++ pat)
は、
if(*++pat == NULL)
で、
++pat;
if(*pat == NULL)
と同じ意味です。
Re:ワイルドカード
Posted: 2008年9月11日(木) 11:00
by いけやん
もうすでに御津凪さんが、答えられてますが(汗
素人の自分が答えるのも何ですが・・・
if(!ast)は
if(ast == NULL),if(ast == 0)と同じで偽の場合
逆にif(ast)と書けば
if(ast == TRUE),if(ast == 1)と同じで真の意味で使えた様な・・・気がします。
Re:ワイルドカード
Posted: 2008年9月11日(木) 11:08
by Haru
>御津凪
解説ありがとうございます!!
こうゆう、略した形を教えてくれるサイトとかって、ないですかね...(^^;
今グーグル先生に聞いてみたんですが、
聞き方が悪かったのか、知らないって言われちゃいました...orz
#2回目のソースpreタグ使い忘れました。見にくくてすいませんでした。
Re:ワイルドカード
Posted: 2008年9月11日(木) 11:23
by 御津凪
> 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を使うので、コンソールアプリケーションで実行してください)
Re:ワイルドカード
Posted: 2008年9月11日(木) 11:36
by Haru
>御津凪さん
おわっ!!失礼しました!
「さん」をつけ忘れました!!
>...のような関数をつくり、関数に色々な値を渡してみると、
>どういう動作なのかが分かるかと思います。
ありがとうございます!
こんな風にして調べれば良いんですね!!
本当に勉強になります!
>>いけやんさん
入れ違いでレスを読み落としてました。
ありがとうございます!!
Re:ワイルドカード
Posted: 2008年9月11日(木) 12:00
by いけやん
御津凪さん。すいません。
>真偽の判定基準は 0 か 1 かでは無く、
>0 か非 0 かです。(ほとんどの場合)
そうですね、0「以外」が返って来るんでしたね。
Haruさんすいません。
>if(ast != NULL)
御津凪さんのを参考に。
>こんな風にして調べれば良いんですね!!
確かに。
>>のような関数をつくり、関数に色々な値を渡してみると、
>>どういう動作なのかが分かるかと思います。
ためになります。
Re:ワイルドカード
Posted: 2008年9月11日(木) 21:55
by フリオ
一点だけ、
"if(*++pat == NULL)"ではなく、"if(*++pat == '\0')"です。