ページ 11

lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月11日(月) 13:51
by Haru
たびたび申し訳ないです!
Haruです・・・。
今回わからないところは、、、、また、というか、、まだワイルドカード
のプログラムです。
前回の[19015]の投稿で、Mistさんに教えて頂いた事はできるようになったのですが、、
(以下おしえて頂いた事)
___________________________________________________________
1: *abc
2: abc*
3: *abc*
だった場合です。

1,2は、ほぼアドバイス通りに作成しました。

1>>ファイル名の先頭部分から*を除く検索文字数分、同じかどうかmemcmpするだけです。

2>>検索文字列の*を除いた文字数を取得  ファイル名の文字数を取得
  検索文字数よりも少なければ不一致
  ファイル名の文字数から検索文字数を引いた位置からファイル名と検索文字でmemcmpする

_____________________________________________________________



3は*は0文字からで良いので単純に
検索文字がabcだった、場合にabcの文字列を含むファイルを読み取る。

とのように、考え、それは先に述べたように完成しました。

しかし、私の理解が悪かったのか、、、
(というか、ワイルドカードがどのように使えるのかちゃんと試しておくべきでした...orz)
例えば、myfile.cというファイルがあった場合に
  ls m*f*l*.*や、m*l* などのように検索した場合でも検索がHITするようにしたいのですが、、
一週間近く考えても、考えれば考えるほどわからなくなってきてしまいました。
もしよろしければ、度々すみませんが、アドバイス等をいただけますでしょうか?


p.s >>Mistさん 
   私の勘違いのためせっかく教えて頂いたのに申し訳無いです。
   これは、経験だと思い、後に活かすことが出来るようにします。
   






------
2番の手順は以下の通り

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月11日(月) 14:01
by Haru
一番下

>>------
>>2番の手順は以下の通り

は、コピペミスです(汗

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月11日(月) 16:50
by toyo
自分が作るとしたら
まず検索文字列を*で分割して文字列の配列を得るかな
配列の文字列で順番に strstr( )して最後の文字列まで NULL が返らなければ一致

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月11日(月) 17:00
by Haru
>>toyoさん

>>自分が作るとしたら
>>まず検索文字列を*で分割して文字列の配列を得るかな
>>配列の文字列で順番に strstr( )して最後の文字列まで NULL が返らなければ一致

分割というと、strtokですかね。
strstr関数は使えるかな?
と思い、一回調べたんですが、使い方がいまいちピンとこなくて諦めた関数でした(^^;
もう一度strstrを調べ直してから、再挑戦します!!
ありがとうございます!

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月11日(月) 17:53
by toyo
実際に作ってみたら配列にしなくてもよかったです
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
haystack : 被検索文字列
wild : *を含んだ検索文字列
戻り値 : 0 一致 : -1メモリ確保失敗 : -2 不一致
*/
#define WILD_CHAR '*'
#define DEBUG
int wildcard(char* haystack, char* wild) {
	char* start;
	char* end;
	// 検索文字列を書き換えるので作業用のバッファを確保してコピー
	char* buf = (char*)malloc(sizeof(char) * (strlen(wild) + 1));
	if (buf == NULL ) {
		return -1;
	}
	strcpy(buf, wild);
	start = buf;
	while (*start) {
		// '*'を探して見つかれば 0 に書き換える
		end = strchr(start, WILD_CHAR);
		if (end) {
			*end = '\0';
		}
		// デバッグ用出力
#ifdef DEBUG
		printf("haystack=%s needle=%s\n", haystack, start);
#endif
		// 文字列を探して一致しなければメモリ開放して戻る
		if ((haystack = strstr(haystack, start)) == NULL) {
			free(buf);
			return -2;
		}
		// 被検索文字列と検索文字列を更新する
		haystack += strlen(start);
		start += strlen(start) + 1;
	}
	free(buf);
	return 0;
}

int main(void) {
	char *moji1 = "*ab**c*def*gh*.*ijk*";
	char *moji2 = "abbc123def456gh4.ijk";
	if (wildcard(moji2, moji1) == 0) {
		printf("OK\n");
	}
	else {
		printf("NO\n");
	}

	return 0;
}

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月11日(月) 19:53
by フリオ
 
 これでどうでしょう。
#include <stdio.h>
#include <string.h>

int Search(const char *str, const char *pat)
{
	while(*str && *pat){
		if(*pat == '*'){
			while(*++ pat == '*') ;
			if(!*pat) return 1;
			if(!(str = strchr(str, *pat))) return 0;
		}
		else if(*pat != *str) return 0;
		str ++;
		pat ++;
	}
	while(*pat == '*') pat ++;
	return !*str && !*pat;
}

int main(void)
{
	char *str = "abbc123def456gh4.ijk";
	char *pat = "*ab**c*def*gh*.*ijk*";
	const char *result[/url] = {"不一致", "一致"};
	
	puts(str);
	puts(pat);
	puts(result[Search(str, pat)]);
	return 0;
}
 

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月12日(火) 10:27
by フリオ
 
 間違ってました。
これだと、
"abcda"に対して、"*a"が不一致になるので、だめです。
 

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月12日(火) 10:36
by Haru
toyoさん、フリオさんどうもありがとうございます!!
見させていただきました。
が、少しわからないところがあるので、宜しければ教えていただけないでしょうか?
恐らく、私のポインタの理解度が足りないのが原因かと、思われます。。

char* buf = (char*)malloc(sizeof(char) * (strlen(wild) + 1));

この1行では作業用のバッファをコピーするというのは理解できたのですが、
*(strlen...));の前の*はどういう意味なんでしょうか?


while (*start)

ここのwhileの後の(*start)とは、どのような条件が成り立ったら、
whileから抜けるという意味なのでしょうか?
ここのstartは今、*を含む検索文字列が代入されてるのですよね?


haystack += strlen(start);
start += strlen(start) + 1;

そしてここは、被検索文字列と検索文字列を更新するとありますが、
今の私にはわかりません。。。
startはDEBUGを見る限り、文字列の長さは0になってるのですよね?
自分でもう少し考えろといわれそうですが、この3つの文は今の私が考えた結果ではわかりませんでした。

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月12日(火) 11:10
by 御津凪
> char* buf = (char*)malloc(sizeof(char) * (strlen(wild) + 1));
char 型のサイズ × (wild の長さ + 1)、つまり、
wild の長さ + 1 の文字列長を char 型のサイズで掛け算しています。
そのサイズ分だけメモリから取得しています。
ちなみに +1 は終端文字(NULL文字)分です。

> while (*start)

*start は start の指している文字を表します。
この while 文では、 *start が0でない間繰り返されます。
つまり、
while (*start != 0)
あるいは
while (*start != '\0')
と同等です。
これは *start が終端文字になるまで繰り返すということです。

> haystack += strlen(start);
> start += strlen(start) + 1;
while 文の最初のほうで '*' を終端文字に置き換えているので、
ワイルドカード文字列の最初に '*' があった場合は文字列の長さが0になります。
上記の文は、haystack を現在の startの文字列長( '*' を終端文字に置き換えているのでそこまでの長さ)分
ずらしてから、 start を終端文字に置き換えた次の位置に移動しています。

疑問箇所だけ説明しましたが、これでなんとなくつかめたのではないでしょうか?
(他の方のコードを読み解くのも言語の勉強になります)

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月12日(火) 11:27
by Haru
>>被検索文字列と検索文字列を更新する

掛け算!!orz...。
てっきりポインタだとばっかり思い込んでました。

>>*start は start の指している文字を表します。
>>この while 文では、 *start が0でない間繰り返されます。
>>while (*start != 0)
>>while (*start != '\0')
>>と同等です。

なるほど。。。勉強になります!!


>>上記の文は、haystack を現在の startの文字列長( '*' を終端文字に置き換えているのでそこまでの長さ)>>分 ずらしてから、 start を終端文字に置き換えた次の位置に移動しています。

理屈は説明していただいてなんとなく理解できました!
・・・が、少しピンと来ないんでノートに書きまくって理解しようかな思います(^^;



>>疑問箇所だけ説明しましたが、これでなんとなくつかめたのではないでしょうか?
>>(他の方のコードを読み解くのも言語の勉強になります)

ありがとうございます!
本当に他の方のコードを読むと勉強になりますね!

御津凪さん解説していただいてありがとうございました!!

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月12日(火) 15:45
by フリオ
 
 改良しました。
#include <stdio.h>
#include <string.h>

int Match(const char *str, const char *pat)
{
	const char *w = NULL;
	
	while(*str){
		if(*pat == '*') w = pat ++;
		else if(*pat != *str){
			if(!w) return 0;
			pat = w + 1;
			str ++;
		}
		else{
			str ++;
			pat ++;
		}
	}
	while(*pat == '*') pat ++;
	return !*pat;
}

int main(void)
{
	char *str = "abcdab";
	char *pat = "*ab";
	const char *result[/url] = {"Unmatch", "Match!!"};
	
	puts(str);
	puts(pat);
	puts(result[Match(str, pat)]);
	return 0;
}
 

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月12日(火) 17:56
by フリオ
 
 ごめんなさい。
やっぱりだめです。文字列の探索で失敗してます。
 

Re:lsコマンド ワイルドカード //linux gcc

Posted: 2008年8月13日(水) 09:57
by Haru
>フリオさん

レス遅れてすみません!!
わざわざありがとうございます!