Regulární výrazy , c# (Regex)

Odeslat odpověď

Smajlíci
:D :) :( :o :shock: :? 8) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen:

BBCode je zapnutý
[img] je zapnutý
[flash] je vypnutý
[url] je zapnuté
Smajlíci jsou zapnutí

Přehled tématu
   

Rozšířit náhled Přehled tématu: Regulární výrazy , c# (Regex)

od hippies » 3. 6. 2007 13:34

neccheš to hodit na wiki.matfyz.cz?

Univerzální pattern matching

od Xerxes » 31. 5. 2007 09:12

Omlouvám se za oživení starého tématu, ale doufám, že by to mohlo někomu pomoct. Všiml jsem si, že v zadání céčkovských zápočťáků často bývá nějaká forma grepu s různě silnými regulárními výrazy. Proto jsem si cvičně zkusil něco naimplementovat a napadlo mě toto:

Kód: Vybrat vše

// Struktura jedne polozky vzoru
struct TPattern
{
	int Min, Max;          // Minimalni a maximalni pocet vyskytu
	unsigned int Mask[8];  // Bitova maska povolenych znaku (256 bitu)
	struct TPattern *Next; // Dalsi polozka ve spojaku vzoru
};

// Vrati TRUE, pokud pasuje znak na polozku vzoru
// Pokud ch == 0, vraci vzdy FALSE kvuli detekci konce retezce
bool MatchChar(TPattern *pat, unsigned char ch)
{
	return ch && (pat->Mask[ch / 32] & (1 << (ch % 32)));
}

// Vrati TRUE, pokud retezec pasuje na zadany spojak vzoru
bool Match(TPattern *pat, const char *str)
{
	// Pokud vzor skoncil, uspesne se matchuje pouze konec retezce
	if(!pat)
		return *str == 0;

	// Napred musi pasovat prave Min znaku vzoru
	for(int i = 0; i < pat->Min; i++, str++)
		if(!MatchChar(pat, *str))
			return false;

	// Potom muze volitelne pasovat (Max - Min) znaku
	for(int i = pat->Min; i < pat->Max; i++, str++)
	{
		// Pokud by zbytek matchoval i bez volitelneho znaku, neni treba zkouset dal
		if(Match(pat->Next, str))
			return true;

		// Preskakovany volitelny znak musi byt zadaneho typu, jinak uz nic nenamatchujem
		if(!MatchChar(pat, *str))
			return false;
	}

	// Volitelne znaky preskoceny, matchuje zbytek?
	return Match(pat->Next, str);
}
Je to podle mého názoru docela jednoduchý, pochopitelný a snadno reprodukovatelný univerzální systém matchování vzorů. Zadaný řetězec matchuje se speciální strukturou, která je tvořena spojákem položek typu TPattern. Jedna polozka spojáku reprezentuje množinu povolených znaků a rozsah, kolikrát se může/musí v řetězci objevit. Doufám, že nic horšího (tedy nic, co by vyžadovalo silnější systém) se na zápočtech neobjeví.

Spoják vzorů je nutné vytvořit z původního řetězce vzoru. To už se zadání od zadání liší. Zde je pro ilustraci kód, který spoják vytvoří ze standardních wildcardů se speciálními znaky '*' a '?':

Kód: Vybrat vše

// Vytvori vzor matchujici zadany wildcard podle standardnich pravidel
TPattern *CompileWildcard(const char *wildcard)
{
	TPattern *first, *last;

	// Projde cely wildcard znak po znaku
	for(first = 0; *wildcard; wildcard++)
	{
		// Vytvori novou polozku vzoru
		TPattern *pat = new TPattern;
		memset(pat, 0, sizeof(TPattern));

		// Na zaklade znaku wildcardu vyplni polozku daty
		switch(*wildcard)
		{
		case '*':
			// Hvezdicka matchuje 0 az INT_MAX vyskytu jakehokoliv znaku
			pat->Min = 0;
			pat->Max = INT_MAX;
			memset(pat->Mask, 0xFF, 32);
			break;

		case '?':
			// Otaznik matchuje prave jeden vyskyt jakehokoliv znaku
			pat->Min = 1;
			pat->Max = 1;
			memset(pat->Mask, 0xFF, 32);
			break;

		default:
			// Cokoliv jineho matchuje prave jednou sebe sama
			pat->Min = 1;
			pat->Max = 1;
			pat->Mask[(unsigned char)*wildcard / 32] = (1 << ((unsigned char)*wildcard % 32));
		}
		
		// Zaradi polozku vzoru do spojaku
		if(!first)
		{
			first = pat;
			last = pat;
		}
		else
		{
			last->Next = pat;
			last = pat;
		}
	}

	// Vrati vytvoreny spojak
	return first;
}
Udělat takový spoják z něčeho se silnější syntaxí je sice pracnější, ale v zásadě nezáludné.

Díky za upozornění na případné chyby.

Poznámka: Poslední rekurze v Match() jde velmi jednoduše předělat na cyklus, ale takto mi to přijde pochopitelnější.

od hippies » 17. 3. 2007 00:27

Mno je to sice s kanonem na vrabecka, ale pripomel's mi material co jsem kdysi studoval: http://atrey.karlin.mff.cuni.cz/~0rfely ... zaver.html

treba ti to k necemu bude:D

od Lukas Mach » 16. 3. 2007 21:04

Zdrojak mam, ale v Prologu :-). Hodne to zalezi na tom, co vsechno maji ty regularni vyrazy umet. Docela dost se da ale udelat s jednoduchou rekurzi. Jako zdrojak v C mam jen matchovani wildcardu ("*zd*.c" matchne s "nazdar.c"):

Kód: Vybrat vše

int match(char *pat, char *str)
{
	switch(*pat) {
	case '\0':  return !*str;
	case '*':   return match(pat+1, str) ||
				*str && match(pat, str+1);
	case '?':   return *str && match(pat+1, str+1);
	default:    return *pat == *str && match(pat+1, str+1);
	}
}

Regulární výrazy , c# (Regex)

od Bojlerik » 16. 3. 2007 19:46

Neni tu náhoudou někdo, kdo má napsanej kód na jednoduchý vyhodnocovač regulárních výrazů v podobě konzolově orientované aplikace, vytvořený
na platformě .NET (v jazycích C# nebo Boo). Vím, že existuje fukce regex už v c# , ale ja ji potřebuju napsat sám :/ Všem, kteří poskytnou nějaký info moc díky

Nahoru