Sunteți pe pagina 1din 8

10.

iruri i expresii regulate


I. iruri de caractere
Clasa string (alias C# pentru System.String) reprezint un ir de caractere a
crui valoare, odat stabilit, nu mai poate fi modificat (iruri imutabile). De fapt,
metodele care modific un obiect ir de caractere returneaz un nou obiect ir de
caractere. Pentru operaiile uzuale cu iruri de caractere (comparri, inserri, cutri,
nlocuiri, adugri, conversii, formatri...) .NET Framework pune la dispoziie i alte
clase, precum StringBuilder, StringFormat i StringCollection.
Se consider un prim exemplu:
using System;
namespace pnoro{
class Aplicatie{
public static void Main(string[] args){
//un sir nul
string s1 = null;
//un sir initializat
//sunt doua siruri identice "egale"?
string s2="astra 19E";
string s3="astra 19E";
if (s2 == s3)
Console.WriteLine("egale prin ==");
else
Console.WriteLine("diferite prin ==");
if (s2.Equals(s3))
Console.WriteLine("egale prin Equals");
else
Console.WriteLine("diferite prin Equals");
Console.WriteLine((object)s2 == (object)s3); //True
//cele doua siruri sunt literali
//ce se intampla daca avem o variabila sir?
string s33 = string.Copy(s2);
Console.WriteLine((object)s2 == (object)s33); //False
//inlocuirea unui caracter
string s4 = "Am un receiver strong 6155.";
string s5 = s4.Replace('s','S');
Console.WriteLine(s3);

//inserarea unui subsir
s1="drbox";
s1=s1.Insert(2, "eam");
Console.WriteLine(s1);
//obiectele string se pot manipula ca tablouri de caractere
s1 += " 500s";
for (int i=0; i<s1.Length; ++i)
Console.Write("{0, -2}", s1[i]);
Console.WriteLine();
//se poate concatena un string cu orice alt tip, utilizand +
string s6 = s1 + " costa " + 200 + " euro";
Console.WriteLine(s6);
Console.ReadLine();
}
};
}
2
Deoarece irurile de caractere sunt imutabile, sistemul pstreaz irurile ntr-o
locaie comun i elimin duplicatele. Din acest motiv, atunci cnd compar dou
obiecte string iniializate pe baza aceluiai literal, operatorul == returneaz true, n
contradicie cu comportamentul su uzual. Se mai observ c s2 i s3 sunt referine
ctre aceeai zon de memorie, dovad a faptului c se elimin duplicatele. Doar la
crearea explicit a unei variabile ir se obine un nou obiect string!
Metodele String.Format i Console.WriteLine sunt guvernate de aceleai reguli
de formatare. Specificaiile de format sunt date sub forma {N [,M][:sir]}, unde:
N este indexul (ncepnd de la 0) argumentului ce trebuie formatat;
M indic limea regiunii ce va conine valoarea formatat, implicit aliniat la
dreapta; dac M este negativ, alinierea se face la stnga;
sir este o secven de coduri de formatare; dac lipsete, formatarea este
realizat de ctre metoda ToString a obiectului cruia i se aplic specificaia de
format curent.
Astfel, urmtoarele instruciuni afieaz acelai rezultat:
Console.WriteLine(100);
Console.WriteLine("{0}", 100);
Console.WriteLine("{0:D3}", 100);
Console.WriteLine(string.Format("100"));
Console.WriteLine(string.Format("{0}",100));
Console.WriteLine(string.Format("{0:D3}",100));

Codurile (numerice) de formatare iau forma Xn, unde n este precizia (numrul
de zerouri/cifre semnificative de la dreapta punctului zecimal) iar X unul dintre
caracterele de format din urmtorul tabel:
Caracter
de format
Interpretare
C, c Moned (currency).
D, d ntreg zecimal.
E, e Exponent.
F, f Reprezentare n virgul fix.
G, g General; 15 cifre pentru double i 7 cifre pentru float.
N, n Numr; similar cu F, adugndu-se , pentru a separa miile.
P, p Procent.
R, r Rotunjire pentru reprezentrile n virgul mobil; garanteaz faptul c un
numr convertit ntr-un ir va fi parsat napoi n exact acelai numr.
Se testeaz dac, utiliznd G, valoarea este parsat napoi; n caz de
insucces, valoarea este formatat cu 17/9 cifre.
Dac este prezent, precizia este ignorat.
X, x Hexazecimal.
3
Dac specificaiile standard de format nu sunt suficiente, se pot construi
propriile specificaii utiliznd marcatori pentru a preciza numrul minim i maxim de
cifre utilizate, locul i apariia semnului negativ precum i apariia unui text n
interiorul numrului:
Marcator Scop Descriere
0 Afieaz 0 Afieaz zerouri nesemnificative dac
reprezentarea are mai puine cifre dect numrul
zerourilor din format.
# Afieaz cifr nlocuiete cu cifrele semnificative.
. Punct zecimal Afieaz punctul zecimal.
, Separator de grup Separ miile.
% Procent Afieaz semnul procentual.
E+0, e+0 Notaie eponenial
E-0, e-0 Notaie eponenial
\ Literal caracter Utilizat n secvenele tradiionale de formatere
precum \n.
ABC Literal ir de
caractere
Afieaz un ir.
ABC Literal ir de
caractere
Afieaz un ir.
; Separator de seciune Specific output diferit dac valoarea numeric
este negativ, 0 sau pozitiv.

double j = 1234.345678;
//afiseaza partea intreaga (cifrele semnificative)
Console.WriteLine("{0:#}", j);
//afiseaza numarul, cu 3 zecimale
Console.WriteLine("{0:.000}", j);
//afiseaza numarul, cu 2 zecimale
Console.WriteLine("{0:0000.00}", j);
//afiseza un 0 nesemnificativ, separatorul de mii si 3 zecimale
Console.WriteLine("{0:00,000.000}", j);
j = -1234.345678;
//afisaj alternativ pozitiv/negativ
Console.WriteLine("{0:00,000.000;minus 00,000.0}", j);
j=0;
//afisaj alternativ pozitiv/negativ/0
Console.WriteLine("{0:00,000.000;minus 00,000.0;ZERO}", j);

Executnd acest fragment de program, se obine:
1234
1234.346
1234.35
01,234.346
minus 01,234.3
ZERO
Se remarc rotunjirea efectuat atunci cnd s-au afiat doar dou zecimale!
4
Pentru tipurile numerice, metoda ToString produce o reprezentare ir de
caractere a unui numr; complementara ei este metoda Parse.
int k = int.Parse("12345");
double dd = double.Parse(" -1,234.5678 ");
Console.WriteLine("k={0} dd={1}", k, dd);

Atunci cnd se dorete ca s se efectueze un set de modificri asupra unui
acelai ir, se utilizeaz System.Text.StringBuilder:
using System;
using System.Text;
namespace pnoro{

class Aplicatie{
public static void Main(string[] args){
StringBuilder sb = new StringBuilder("dream");
sb.Replace('d','D');
sb.Insert(sb.Length, "Box 500s ");
sb.Append(" is running Linux!");
string s = sb.ToString();
Console.WriteLine(s);
//un tablou de caractere utilizate ca separatori de cuvinte
char[] separatori = new Char[]{' '};
//separarea unui sir in cuvinte cu Split
foreach (string ss in s.Split(separatori))
Console.WriteLine(ss);
Console.ReadLine();
}
};
}

Executnd acest program, se observ un neajuns n utilizarea metodei Split:
deoarece ntre 500s i is sunt dou spaii, apare un rnd liber. Acest neajuns poate fi
eliminat prin utilizarea expresiilor regulate.

II. Expresii regulate
Expresiile regulate ofer o modalitate flexibil, puternic i eficient de a
procesa textul. Limbajul expresiilor regulate din C#, proiectat compatibil cu cel din
Perl 5, include caractere literal (normale) i metacaractere; cele mai utilizate
metacaractere i semnificaiile lor sunt prezentate n urmtorul tabel:
Metacaracter Semnificaie
. Orice caracter, cu excepia lui \n.
[list] Un singur caracter din list.
[^list] Un singur caracter, care nu este n list.
[char
1
-char
2
] Un singur caracter, din intervalul specificat.
\w Caracter liter sau cifr: [a-zA-Z0-9]
\W Caracter care nu este liter sau cifr.
5
\s Caracter spaiu: [ \n\r\t\f]
\S Caracter care nu este spaiu.
\d Caracter cifr: [0-9]
\D Caracter care nu este cifr
^ nceputul unei linii de text.
$ Sfritul unei linii de text.
\b n limita unui cuvnt.
\B n afara limitei unui cuvnt.
* 0 sau mai multe potriviri.
+ 1 sau mai multe potriviri.
? 0 sau 1 potriviri.
{n} Exact n potriviri.
{n,} Cel puin n potriviri.
{n,m} Cel puin n potriviri, dar nu mai mult de m potriviri.
() Captureaz subirul ce se potrivete, sub forma unui grup.
(?<nume>) Captureaz subirul ce se potrivete, sub forma unui grup cu nume.
| Operaia SAU logic.

Observaii:
Atunci cnd un literal ir de caractere conine metacaractere de forma \c,
deoarece acestea nu sunt secvene escape, literalii trebuie prefixai cu
caracterul @.
Pentru a afia \c se utilizeaz \\c.

Expresiile regulate sunt implementate n clasa Regex din spaiul de nume
System.Text.RegularExpression; obiectele Regex sunt i ele imutabile. Pentru a separa
n cuvinte un ir de caractere, se apeleaz metoda Regex.Split; de data aceasta, lista
separatorilor se transmite direct constructorului clasei Regex, sub forma unei expresii
regulate:
using System;
using System.Text.RegularExpressions;

namespace pnoro{

class Aplicatie{
public static void Main(){
string s = "Dreambox 500s is running Linux!";
//acceasi problema: despartirea intre 2 spatii consecutive
Regex er1 = new Regex(" ");
foreach (string cuvant in er1.Split(s))
Console.WriteLine(cuvant);
//utilizam o alta expresie regulata: [ ]+
Regex er2 = new Regex("[ ]+");
foreach (string cuvant in er2.Split(s))
Console.WriteLine(cuvant);
6
//se generalizeaza pentru orice caracter spatiu: [\s]+
Regex er3 = new Regex(@"[\s]+");
foreach (string cuvant in er3.Split(s))
Console.WriteLine(cuvant);
Console.ReadLine();
}
};
}

Se observ c Regex.Split elimin caracterele spaiu; ce se ntmpl dac
asupra irului de caractere trebuie s operm doar nite modificri i trebuie s
pstrm delimitatorii pentru alte procesri? Se utilizeaz (), care captureaz/pstreaz
un subir sub forma unui grup:
using System;
using System.Text.RegularExpressions;

namespace pnoro{
class Aplicatie{
public static void Main(){
//un singur spatiu intre 500s si is
string s = "Dreambox 500s is running Linux!";
//pastreaza spatiul
Regex er1 = new Regex("( )");
foreach(string cuvant in er1.Split(s))
Console.WriteLine(cuvant);
//pasteaza orice caracter spatiu
Regex er2 = new Regex(@"(\s)");
foreach(string cuvant in er2.Split(s))
Console.WriteLine(cuvant);
Console.ReadLine();
}
};
}

Un obiect Match reprezint rezultatul unei operaii de cutare/potrivire a unui
ablon descris de o expresie regulat. Un obiect Match este imutabil, iar clasa Match
nu posed nici un constructor public; din acest motiv, un obiect Match se poate obine
doar apelnd metoda Regex.Match.
Clasa Match pstreaz i ofer acces la subirurile extrase n procesul de
cutare, la irul n care se caut i la expresia regulat n uz, fcnd astfel posibil
renceperea cutrii din punctul n care cutarea anterioar s-a oprit (n cazul n care
ablonul este prezent de mai multe ori n irul n care se caut) prin intermediul
metodei Match.NextMatch. Acest proces poate fi descris mai simplu utiliznd clasa
MatchCollection, ale crei instane sunt returnate de Regex.Matches:
7
using System;
using System.Text.RegularExpressions;

namespace pnoro{

class Aplicatie{
public static void Main(){
//un singur spatiu intre 500s si is
string s = "Dreambox 500s is running Linux!";
//cauta prima aparitie a lui 'in'
Regex er = new Regex("in");
Match m1 = er.Match(s);
if (m1.Success)
Console.WriteLine("Am gasit \'{0}\' la pozitia {1}.",m1.Value, m1.Index);
//cauta toate apairiile lui 'in'
Match m2;
for(m2=er.Match(s);m2.Success;m2=m2.NextMatch())
Console.WriteLine("Am gasit \'{0}\' la pozitia {1}.", m2.Value, m2.Index);
//cauta toate aparitiile lui 'in' utilizand MatchCollection
MatchCollection mc = er.Matches(s);
foreach (Match m in mc)
Console.WriteLine("Am gasit \'{0}\' la pozitia {1}", m.Value, m.Index);
Console.ReadLine();
}
};
}

O expresie regulat poate fi descompus n mai multe grupuri; de exemplu,
ablonul (i(n))g conine grupurile n, in i ing. Un astfel de grup este descris de
ctre clasa Group. Clasa Match pune la dispoziie proprietatea Groups, care
returneaz un obiect GroupCollection, prin intermediul cruia pot fi accesate
grupurile individuale:
using System;
using System.Text.RegularExpressions;
namespace pnoro{
class Aplicatie{
public static void Main(){
string s1 = "Dreambox 500s is running Linux!";
//cauta prima aparitie a lui 'ing'
//grupurile n in si ing
Regex er1 = new Regex("(i(n))g");
Match m1 = er1.Match(s1);
GroupCollection gc = m1.Groups;
foreach(Group g in gc)
Console.WriteLine("Am gasit \'{0}\' la pozitia {1}", g.Value, g.Index);
string s2 = "Dreambox:Linux";
//grupuri cu nume
//primul grup se numeste 'NUME', al doilea grup se numeste 'SO'
Regex er2 = new Regex("(?<NUME>\\w+):(?<SO>\\w+)");
Match m2 = er2.Match(s2);
//colectia de grupuri este indexata
//index sir de caractere
Console.WriteLine("{0} <-> {1}", m2.Groups["NUME"].Value,
m2.Groups["SO"].Value);
Console.ReadLine();
}
};
}
8
Proprietatea Group.Captures returneaz un obiect CaptureCollection; explicit,
se poate scrie astfel:
using System;
using System.Text.RegularExpressions;
namespace pnoro{
class Aplicatie{
public static void Main(){
string s = "Dreambox 500s is running Linux ing!";
//cauta prima aparitie a lui 'ing'
Regex er = new Regex("(i(n))g");
Match m = er.Match(s);
GroupCollection gc = m.Groups;
//parcurge colectia de grupuri
foreach(Group g in gc)
Console.WriteLine("Am gasit \'{0}\' la pozitia {1}", g.Value, g.Index);
//alternativ
//parcurge colectia de grupuri
foreach (Group g in gc){
//parcurge colecia de capturi
CaptureCollection cc = g.Captures;
foreach (Capture c in cc)
Console.WriteLine("Am gasit \'{0}\' la pozitia {1}", c.Value,
c.Index);
}
Console.ReadLine();
}
};
}
Regex.Replace este o metod ce poate fi utilizat pentru tergerea spaiilor,
desprirea n cuvinte, tergerea sau nlocuirea unor subiruri; de exemplu:
using System;
using System.Text.RegularExpressions;
namespace pnoro{
class Aplicatie{
public static void Main(){
string s = " spatii sterse";
Regex er1 = new Regex(@"^\s*");
Console.WriteLine(er1.Replace(s, ""));
Console.ReadLine();
}
}
}

Observaie:
Clase Regex pune la dispoziie i variantele statice ale metodelor Split, Replace i
Match; acestea pot fi folosite fr a iniializa obiecte Regex.

Exist i o versiune suprancarcat a constructorului clasei Regex care accept
un al doilea argument, de tipul RegexOptions; printre valorile acestui tip enumerare
se regsesc IgnoreCase i RightToLeft.

S-ar putea să vă placă și