Sunteți pe pagina 1din 6

Șiruri de caractere.

Aplicații (tokenize)

Separarea unităților lexicale dintr-un șir de caractere

Numim unitate lexicală o secvență de caractere din șir delimitată de separatori. Pentru extragerea
succesivă a unităților lexicale dintr-un șir de caractere (cel mai frecvent, extragerea cuvintelor dintr-
un text), vom folosi funcția strtok(), ce are următorul prototip:

char * strtok(char *s, const char * separatori);

Modul de apel al acestei funcții este mai special. Prima dată se apelează funcția sub forma

strtok(s, separatori);

După primul apel, funcția va returna adresa de început a primei unități lexicale din șirul s. După
acest prim apel, șirul s este modificat (primul separator de după prima unitate lexicală este înlocuit
de caracterul NULL). Pentru a extrage succesiv și celelalte unități lexicale din șirul s putem apela
din nou funcția strtok(), astfel:

strtok(NULL, separatori);

Acest apel returnează adresa de început a următoarei unități lexicale din șirul s (sau NULL, dacă în
șirul s nu mai există unități lexicale). După fiecare apel, primul separator de după unitatea lexicală
identificată este înlocuit de caracterul NULL.

Exemplu
char s[] = "A fost odata ca-n povesti, a fost ca niciodata.";
char sep[]=" .,?!";
char *p;

p = strtok(s,sep);
while (p) {
cout << p << '\n';
p = strtok(NULL, " .,?!");
}
// A
// fost
// odata
// ca-n
// povesti
// a
// fost
// ca
// niciodata

Observație
De la un apel la altul, șirul de separatori se poate modifica. De exemplu, să considerăm că în șirul s
este memorată o relație de forma <rezultat> = <operand_1> <operator> <operand_2>
unde operatorul poate fi un caracter din șirul "+-*/".
Pentru a extrage cele trei unități lexicale putem proceda astfel:
p=strtok(s,”=“);
cout<<”Rezultat:”<<p<<endl;
p=strtok(NULL,”+-*/“);
cout<<”Operand 1:”<<p<<endl;
p=strtok(NULL,”+-*/“);
cout<<”Operand 2:”<<p<<endl;

Resurse
 E. Cerchez, M. Serban - Programarea în limbajul C/C++. Volumul I. Editura Polirom
 https://www.pbinfo.ro/articole/19/siruri-de-caractere-in-cpp#intlink-15
 https://infogenius.ro/siruri-de-caractere-cpp/
 https://www.cplusplus.com/reference/cstring/strtok/

PROBLEME PROPUSE

1. SortareCuvinte
https://www.pbinfo.ro/probleme/101/sortarecuvinte

Cerinţa
Să se scrie un program care citește o propoziţie şi afişează cuvintele din propoziţie ordonate
alfabetic.
Date de intrare
Fișierul de intrare sortcuv.in conține pe prima linie o propoziție alcătuită din litere mici ale
alfabetului englez și spații.
Date de ieşire
Fișierul de ieșire sortcuv.out va conține cuvintele din propoziție, ordonate alfabetic, fiecare pe câte
o linie.
Restricţii şi precizări
 propoziția va conține cel mult 250 de caractere;
 fiecare cuvânt din propoziție are cel mult 20 litere

Exemplu
sortcuv.in
dreptunghiul este un paralelogram cu un unghi drept

sortcuv.out
cu
drept
dreptunghiul
este
paralelogram
un
un
unghi
Soluție
#include <fstream>
#include <cstring>
using namespace std;
ifstream fin("sortcuv.in");
ofstream fout("sortcuv.out");

int main()
{
char s[256],aux[256],*p,cuv[256][25];
int n=0;
bool ok;
fin.getline(s,256);
p=strtok(s," "); /// extragem primul cuvant din text
while(p)
{
strcpy(cuv[n],p); ///plasam cuvantul in matrice, pe linia n
n++;
p=strtok(NULL," "); /// extragem urmatorul cuvant din text
}
do ///bubble sort
{
ok=1;
for(int i=0; i<n-1; i++)
if(strcmp(cuv[i],cuv[i+1])>0)
{
strcpy(aux,cuv[i]);
strcpy(cuv[i],cuv[i+1]);
strcpy(cuv[i+1],aux);
///sau swap(cuv[i],cuv[i+1]);
ok=0;
}
}
while(!ok);
for(int i=0; i<n; i++)
fout<<cuv[i]<<'\n';
return 0;
}

2. Note
https://www.pbinfo.ro/probleme/2813/note

Cerința
Se consideră un text cu cel mult 100 de caractere, în care cuvintele sunt formate din litere mari ale
alfabetului englez și sunt separate prin câte un spațiu.
Scrieți un program care citește de la tastatură un text de tipul menționat mai sus și afișează pe ecran,
pe câte un rând, cuvintele care cuprind cel puțin o notă muzicală. Dacă nu există astfel de cuvinte,
se afișează pe ecran mesajul nu exista.
Date de intrare
Programul citește de la tastatură un text de tipul menționat.
Date de ieșire
Programul va afișa pe ecran, pe câte un rând, cuvintele care cuprind cel puțin o notă muzicală. Dacă
nu există astfel de cuvinte, se afișează pe ecran mesajul nu exista.
Restricții și precizări
 cuvintele vor fi afișate în ordinea din text
 notele muzicale sunt DO, RE, MI, FA, SOL, LA, SI.
Exemplu
Intrare
REMI DOMINO SI KHANHOO SUNT DENUMIRI DE JOCURI CE AU ASPECTE SIMILARE

Ieșire
REMI
DOMINO
SI
DENUMIRI
SIMILARE

3. NrAnagrame
https://www.pbinfo.ro/probleme/887/nranagrame
Cerinţa
Se dă un şir de caractere ce conţine cuvinte formate din litere mici ale alfabetului englez, separate
prin unul sau mai multe spații. Să se determine câte cuvinte din sir sunt anagrame ale ultimului
cuvânt, fără a fi identice cu acesta.
Date de intrare
Programul va citi de la tastatură şirul dat.
Date de ieşire
Programul va afişa pe ecran un număr C, reprezentând valoarea cerută.
Restricţii şi precizări
 șirul dat va conține cel mult 255 caractere, litere mici ale alfabetului englez și spații

Exemplu
Intrare
arc ingrat din granit car argint arc rating rac argint

Ieșire
3

4. Expresie9
https://www.pbinfo.ro/probleme/2185/expresie9

Soluție
#include <bits/stdc++.h>
using namespace std;
ifstream fin("expresie9.in");
ofstream fout("expresie9.out");
int s1[2000],s2[2000],n,t,a[1000],vmax[2000];
char c[1001],*p;
void scrie(int a[])///afiseaza numarul mare memorat in vectorul a
{
for(int i=a[0]; i>=1; i--)fout<<a[i];
fout<<endl;
}

void suma(int s[],int a[])///aduna in s numerele mari a si s

{
int i,t,nr;
nr=s[0];
if(a[0]>nr)nr=a[0];
for(i=1; i<=a[0]; i++)s[i]=s[i]+a[i];
t=0;
for(i=1; i<=nr; i++)
{
s[i]=s[i]+t;
t=s[i]/10;
s[i]=s[i]%10;
}
if(t>0)
{
nr++;
s[nr]=1;
}
s[0]=nr;
}
void zero( int y[])///seteaza vectorul y pe 0
{
for(int i=0; i<1000; i++)y[i]=0;
}
void transf(char *p)///transforma sirul de caractere p in numarul mare memorat in vectorul a
{
int i,lg,cod,u,v;
char aux;
lg=0;
for(i=0; i<strlen(p); i++)
{
cod=p[i]-'a'+1;
if(cod<=9)
{
lg++;
a[lg]=cod;
}
else
{
lg++;
a[lg]=cod/10;
lg++;
a[lg]=cod%10;
}
}
a[0]=lg;///plasam pe pozitia 0 numarul de cifre ale numarului astfel obtinut
u=1;
v=lg;
while(u<v)
{
aux=a[u];
a[u]=a[v];
a[v]=aux;
u++;
v--;
}
}

int compara(int x[],int y[]) /// compar numerele mari x si y si returnez 1, -1 sau 0

{
if(x[0]>y[0]) return 1;
if(x[0]<y[0])
return -1;
for(int i=x[0]; i>=1; i--)
{
if(x[i]>y[i])return 1;
if(x[i]<y[i])return -1;
}
return 0;
}
void copie(int vmax[],int a[])///copiez a in vmax
{
for(int i=0; i<=a[0]; i++) vmax[i]=a[i];
}
void cerinta1()///rezolvarea cerintei 1
{
int i,rez;
char sep[]="+<>";
vmax[0]=1;
for(i=1; i<=n; i++)
{
fin.getline(c,1001);///citesc expresia curenta
p=strtok(c,sep);
while(p!=NULL)
{
zero(a);///a=0
transf(p);/// compun a
rez=compara(a,vmax);
if(rez==1)copie(vmax,a);/// daca a>vmax, vmax=a
p=strtok(NULL,sep);
}
}
scrie(vmax);
}
void evaluare(char *d,int z[])///construiesc in z suma numerelor dintr-o expresie aritmetica
{
zero(z);
z[0]=1;
p=strtok(d,"+");
while(p!=NULL)
{
zero(a);///a=0
transf(p);/// compun a (numarul curent)
suma(z,a);
p=strtok(NULL,"+");
}
}
void cerinta2()
{
char *q,*r,aux;
int i,lg,j,rez,k;
for(k=1; k<=n; k++)
{
fin.getline(c,1000);
lg=strlen(c);

i=0;

while(c[i]!='<' &&c[i]!='>' && i<lg)


i++;

if(i==lg)///daca a fost doar o expresie aritmetica


{
evaluare(c,s1);
scrie(s1);
zero(s1);
zero(a);
}
else
{
aux=c[i];
j=i+1;
c[i]='\0';
evaluare(c,s1);///evaluez membrul stang
evaluare(c+j,s2);///evaluez membrul drept
rez=compara(s1,s2);
if(aux=='>')fout<< (rez==1)<<endl;
else fout<< (rez==-1)<<endl;
zero(s1);
zero(s2);
}
}
}
int main()
{
fin>>t>>n;
fin.get();
if(t==1)cerinta1();
else cerinta2();
return 0;
}

TEMĂ

1. SwapCuv
https://www.pbinfo.ro/probleme/2673/swapcuv
2. AfisSimetric
https://www.pbinfo.ro/probleme/2592/afissimetric
3. Cuvinte6
https://www.pbinfo.ro/probleme/1947/cuvinte6
4. Farma
https://www.pbinfo.ro/probleme/1705/farma

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