Bibliotek do DOSowych wildcardów w języku C.

3

Udało mi się napisać prostą bibliotekę w C (nazwałem ją Squirrel) służącą do dopasowywania DOSowych wildcardów:

short int squirrel(char* pattern,char* text);
short int squirrel_star(char* pattern,char* text);

short int squirrel(char* pattern,char* text){
	if(!*text){
		return 1;
	}else if(*pattern==*text || *pattern=='?'){
		return squirrel(++pattern,++text) || squirrel(++pattern,text);
	}else if(*pattern=='*'){
		return squirrel_star(++pattern,text);
	}else{
		return 0;
	}
}

short int squirrel_star(char* pattern,char* text){
	if(!*text && *pattern){
		return 0;
	}else if(squirrel(pattern,text)){
		return 1;
	}else{
		return squirrel_star(pattern,++text);
	}
}

Czy jest coś do ewentualnego poprawienia?

2
  1. Nigdzie nie sprawdzasz czy przypadkiem nie wyszedłeś poza pattern - co w sytuacji, gdy strlen(text) > strlen(pattern)?
  2. Niepotrzebnie wykorzystujesz rekurencję (jest to kłopotliwe w zrozumieniu algorytmu oraz może spowolnić wykonywanie programu) - spróbuj napisać squirrel z wykorzystaniem pętli.
  3. Przyjrzyj się dwukrotnemu wywołaniu ++pattern wewnątrz return squirrel(++pattern,++text) || squirrel(++pattern,text); - choć nie stanowi to undefined behavior (ponieważ || jest sequence point), to wygląda na błąd logiczny; na moje oko tamten fragment powinien wyglądać tak:
return squirrel(pattern + 1, text + 1);
2

Po pierwsze, wstawiłbym consty w parametrach. Po drugie, funkcję squirrel_star bym dał jako static, bo to chyba nie jest funkcja, która ma być używana z zewnątrz?
Poza tym, nigdzie nie sprawdzasz, czy nigdzie nie wkradł się jakiś NULL, ale rozumiem, że pewnie nie masz cennych cyklów na takie zabawy, a polityka fail early jest najlepsza (bo jest :D).

Co do uwagi z rekurencją, chyba interacyjna implementacja byłaby nawet czytelniejsza, nie tylko szybsza. Wydaje mi się, że nie ma problemu z różnicą długości, bo i tak na końcu są bajty zerowe, a jeśli jest tylko w jednym to wykryje, że są różne. Tylko pytanie czy * może dopasować pusty ciąg?

A tak generalnie to trudno powiedzieć, napisz testy. :)

2

@elwis, oto poprawiona wersja:

short int squirrel(const char* pattern,const char* text);
static short int squirrel_star(const char* pattern,const char* text);

short int squirrel(const char* pattern,const char* text){
	if(!pattern || !text){
		return 0;
	}else if(!*text){
		return 1;
	}else if(*pattern==*text || *pattern=='?'){
		return squirrel(++pattern,++text) || squirrel(++pattern,text);
	}else if(*pattern=='*'){
		return squirrel_star(++pattern,text);
	}else{
		return 0;
	}
}

static short int squirrel_star(const char* pattern,const char* text){
	if(!*text && *pattern){
		return 0;
	}else if(squirrel(pattern,text)){
		return 1;
	}else{
		return squirrel_star(pattern,++text);
	}
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1