Referat Fortran
Mai jos puteti citi fragmente din
Referat Fortran si de asemenea puteti face
Download Referat FortranCiteste fragmente din Referat Fortran
-pastreaza cuvantul citit in memoria heap;
-realizeaza initializarile;
frecv = 1;
urm = 0.
*/
{
char t[255] ;
int sf;
cuvint = 0;
if (tnod : : ind = = false) {
while ( (sf = scanf ( “%sâ€Â,t)) ! = EOF ) {
char *p = t ;
int c ;
// salt peste caractere care nu sant litere
while ((c =*p)&&(c<‘A‘||C>‘Z‘&&
c<‘a’||c>‘z‘))
p++;
if ( c = = 0 ) //nu sant litere
continue;
//pastreaza inceputul cuvantului
char *q = p ;
//cauta inceputul cuvantului
while ((c=*p)&&(c>=‘A‘&&c<=‘z’ ||
c >= ‘a‘ &&c <=‘z‘ ))
p++ ;
*q = ‘ ’ ; //caracterul NUL la sfarsitul cuvantului
//rezerva zona pentru cuvantul in memoria heap
//se apeleaza operatorul new standard
printf ( “ tnod : : tnod %lu
†, coreleft () );
if ( ( cuvant = new char[strlen(q) +1] ) = = 0 ) {
printf ( “ memorie insuficienta
†) ;
exit (1) ;
}
printf( “ tnod : : tnod %lu
†, coreleft () ) ;
//se transfera cuvantul in zona rezervata
strcpy ( cuvant , q );
//initializari
frecv = 1 ;
urm = 0 ; //pointerul nul
break;
} //sfarsit while
if ) sf = = EOF ) //s-a intalnit EOF
tnod : : ind = true ;
}
} // sfarsit constructor
inline tnod : : ~ tnod ( )
{
//se apeleaza operatorul delete standard
printf (“
destructor tnod %lu
â€Â,coreleft ( ) );
delete cuvint ;
printf (“
destructor tnod %lu
â€Â,coreleft ( ) );
}
inline void tnod::afistnod() //afiseaza cuvantul si frecventa
{
printf (“cuvantul=%s are frecventa=%d
â€Â,cuvant,frecv) ;
{
tnod *p ;
//se aplica operatorul new standard
printf (“ operator new %lu
â€Â, coreleft ( ) ) ;
p=(tnod *) new char [lung] ;
printf (“ operator new %lu
â€Â, coreleft ( ) ) ;
return p ;
}
void tnod::operator delete(void*p) //supraincarcarea operatorului delete
{
//se aplica operatorul delete standard
printf (“ operator delete %lu
â€Â, coreleft ( ) ) ;
: : delete p ;
printf (“ operator delete %lu
â€Â, coreleft ) ) ;
}
void tnod : : operator ++ ( ) //incrementeaza frecv
{
frecv++ ;
}
Boolean tnod : : retind ( ) //returneaza valoarea ind
{
return tnod : : ind ;
}
Observatie
Functia coreleft returneaza dimensiunea,in octeti, a memoriei
libere in momentul apelului.Ea a fost apelata in mai multe functii
pentru a putea urmari momentele in care se dezaloca obiectele care sant
instantieri ale clasei tnod.
23.12 Sa se defineasca tipul abstract slist pentru implementarea listei
simplu inlantuite.
Listele simplu inlantuite au fost implementate in limbajul C in
capitolul 11.
Pentru gestiunea listelor simplu inlantuite s-au folosit doua variabile
prim si ultim care sant pointeri sper primul si respectiv ultimul nod al
listei.
Aceste valori se vor utiliza si in cazul de fata cu acelasi
scop.Ele sunt date membru protejate ale tipului abstract slist
Avantajul implementarii tipului abstract slist este acela ca ,
se pot defini simultan si simplu orice obiecte de tip lista.
Functiile membru ale tipului abstract slist sunt:
constructor implicit ;
deconstructor ;
adaugarea unui nou nod inaintea primului nod al listei ;
stergerea primului nod al listei ;
stergerea ultimului nod al listei ;
cautarea in lista a unui nod ;
afisarea datelor aflate in nodurile listei.
Nodurile listei sunt obiecte de tip tnod, tip definit in exercitiul
23.11
FISIERUL BXXIII12H
#ifndef __BXXIII11_H
#include “BXXIII1.CPPâ€Â
#define __ BXXIII1_H
class slist {
tnod *prim ;
tnod *ultim ;
public :
slist ( ) ; // constructor
~slist ( ) ; //destructor
tnod *adauga (tod*) ; //adauga un nod dupa cel spre care
//pointeaza ultim
tnod *insereaza (tnod *p); //insereaza un nod inaintea
//celui spre care pointeza prim
void sprim ( ) ; //sterge primul nod din lista
void sultim ( ) ; //sterge ultimul nod al listei
tnod *cauta (tnod *p) ;
/* - cauta nodul din lista pentru care p -> cuvant pointeaza
spre un sir identic cu cel care pointeaza cuvant din nod ;
-returneaza pointerul spre nodul respectiv sau zero daca nu
exista un astfel de nod */
void afislist ( ) ; //afiseaza datele din nodurile
listei
} ;
Functiile membru ale clasei slist se definesc in fisierul de
extensie CPP, de mai jos
FISIERUL BXXIII12
#idndef __BXXIII12_H
#include “BXXIII12.Hâ€Â
#define __BXIII12_H
#endif
inline slist : : slist ( ) //constructor
{
prim = ultim = 0 ;
}
slist : : ~slist ( ) //destructor ; distruge toate nodurile listei
{
tnod *p, *q ;
for (p = prim ; p ; p=q) {
q=p->urm ; //pointer spre nodul urmator
delete p ; //operatorul delete supraincarcat
}
prim = ultim = 0 ;
}
tnod *slist::adauga(tnod*p) //adauga un nod dupa ultimul nod al listei
{
if (prim == 0) //lista vida
prim = p ;
else ultim -> urm = p ;
ultim = p ;
return p ;
}
tnod *slist ; : insereaza (tnod *p)
//insereaza un nou nod inaintea celui spre care pointeaza prin
{
if ( prim = = 0 ) //lista vida
ultim = p ;
else p -> urm = prim ;
prim = p ;
return p ;
}
void slist : : sprim ( ) //sterge primul nod din lista
{
if (prim0 {
tnod *p = prim -> urm ;
delete prim ; //se aplica operatorul delete supraincarcat
prim = p ;
if (prim = = 0 ) ultim = 0 ; //lista a devenit
vida
} else
printf ( “lista vida
†) ;
}
void slist : : sultim ( ) //sterge ultimul nod al listei
{
if (prim) {
tnod 8p,*p1 ;
// p – pointeaza spre nodul curent
p = prim ;
//p1 – poinbteaza spre nodul precendet
p1 = 0 ;
while ( p != ultim ) { //parcurge lista
p1 = p ;
p = p -> urm ;
}
// p – pointeaza spre ultimul nod
//p1 – pointeaza spre nodul precedent
if (p1 = = 0 ) { //lista are un singur nod si devine vida
delete p ; //se aplica operatorul supraincarcat
prim = ultim = 0 ;
return ;
}
//nodul spre care pointeaza p1 devine ultimul nod al listei
p1 -> urm = 0 ;
ultim = p1 ;
//se sterge nodul spre care pointeaza p
delete p ; //se aplica operatorul supraincarcat
} else
printf ( “ lista vida
“ ) ;
}
tnod *slist : : cauta (tnod *p )
/* - cauta nodul pentru care cuvant pointeaza spre un sir identic cu cel
spre
care pointeaza p -> cuvant ;
- returneaza pointerul spre nodul respectiv sau 0 daca nu exista un
astfel
de nod. */
{
tnod *q ;
for (q=prim;q;q=q->urm)
if (stricmp (p -> cuvant,q -> cuvant = = 0 )
return q ;
return 0 ;
}
void slist : : afislist ( )
/* - afiseaza pentru fiecare nod:
-cuvant
si
-frecv.
*/
{
int nrlin = 1 ;
for (tnod *p = prim ; p ; p = p -> urm ) {
p -> afistnod ( ) ;
nrlin ++;
if (nrlin %23 = = 0) {
printf(“Actionati o tasta pentru a continua
†);
getch ( ) ;
}
}
}
23.13 Sa se scrie un program care citeste un text si afiseaza frecventa
de aparitie a fiecarui cuvant din tex.Nu se face distinctie intre
literele mari si mici
Aceasta problema a fost rezolvata in mai multe moduri in
capitolele precedente.
In particular,in capitolul 11 se da o rezolvare folosind listele
simplu inlantuite.
Programul de fata utilizeaza aceeasi metoda.
PROGRAMUL BXXIII13
#include
#ifndef __CONIO_H
#include
#define __CONIO_H
#endif
#include “BXIII12.CCPâ€Â
main ( )
/*citeste un text si afiseaza frecventa cuvintelor citite 8/
{
slist lista ;
tnod *nod, *p ;
printf ( “%lu
â€Â,coreleft ( ) );
while (tnod : : retind ( ) = = false )
//nu s-a ajuns la sfarsitul textului
{
nod = new tnod ; //se aplica operatorul new supraincarcat
//cauta nodul in lista
if (tnod : : retind ( ) = = false )
if (p = lista.cauta(nod) ) {
//cuvantul exista deja in lista
(*p)++; //incrementeaza frecv
delete nod ; //se aplica operatorul
delete supraincarcat
} else
lista.adauga (nod);
/*nodul spre care pointeazanod
contine un cuvant
negasit in lista; se adauga la
lista */
else delete nod ;
printf(“Pentru a continua actionati o tasta
â€Â);
getch ( ) ;
} //sfarsit while
//listeaza nodurile listei
lista.afislist ( ) ;
}
23.2 Supraincarcarea operatorului =
In limbajul C++ se pot face atribuiri de obiecte care sant
instantieri ale aceleeasi clase.
Exemplu
Fie instantierile:
numae_clasa obiect1,obiect2;
…
O atribuire de forma:
obiect2 = obiect1 ;
este acceptata de compilator.
La atribuirea de obiecte,in mod implicit,se atribuie datele membru
aleobiectului din dreapta operatorului = la datele membru
corespunzatoare ale obiectului din stanga aceluiasi operator.Astfel de
atribuiri se pot utiliza si in declaratii.
Exemplu:
class complex {
double real
double imag;
public :
complex (double x = 0, double y = 0 )
{
real = x ;
img = y ;
}
…
} ;
complex z (1,1) ; //z = 1+2I
complex z1 = z ; //z1 = 1 +2I
complex z2 ;
…
z2 = z1 ; //z2 = 1 +2I
Atat in cazul declaratiei lui z1 ,cat si in cazul instructiunii de
atribuire pentru z2 , se copiaza componentele date ale obiectului
complex din dreapta caracterului "“"â€Âin zona de memorie alocata
componentelor date ale obiectulu aflat in stanga aceluiasi caracter.
In cazul declaratiei lui z1 , caracterul “=†se utilizaeaza pentru
a realiza o initializare , iar in cazul instructiunii:
z2 = z1 ;
acelasi carater se utilizeaza pentru a realiza o atribuire.
Ambele operatii sant definite in mod implicit si se realizeaza asa cum
sa indicat mai sus,adica prin simpla copiere a datelor membru
B.Stroustrup numeste “bitwise copy†(copiere la nivel de biti)
copierile de acelasi fel.
In cazul obiectelor clasei complex, copierea din cadrul operatiei de
initializare este identica cu cea utilizata in cadrul operatiei de
atribuire.
In general,cele doua operatii nu sant identice.De asemenea,copierea
de tip “bitwise copy†nu este totdeauna suficienta.Acest fapt
rezulta imediat daca reluam exemplul pentru implementarea tipului
abstract string (vezi 22.90 sau sir (vezi exercitiul 22.12)
Consideram clasa sir,definita ca mai jos :
class sir {
char *psir ;
int lung ;
public :
sir (char *s ) ;
sir (int nrcar = 70 ) ;
int retlung ( ) ; //returneaza lungimea sirului
void afsir() ; // afiseaza sirul definit de psir
int citsir ( ) ; //citeste un sir de caractere
~sir ( ) {delete psir ; }
} ;
Functiile membru de mai sus ,sunt definte in exercitiul 22.12
Fie declaratia:
sir sir1 (“C++ este un C mai bun “);
La instantierea obiectului sir1 se apeleaza constructorul :
sir (char *s)
Acesta rezolva zona de memorie in memoria heap pentru textul:
C++ este un C mai bun
Si atribuie adresa de inceput a acestei zone pointerului:
sir1.psir
De asemene,se atribuie datei membru:
sir1.lung
valoarea 21 (numarul de caractere din compunearea textului de
initializare a obiectului sir1,fara a considera si caracterul NUL).
Sa consideram declaratia pentru instantierea obiectului sir2 cu
initializarea acestuia folosind obiectul sir1:
sir sir2 = sir1 ;
Utilizatorul foloseste o astfel de declaratie pentru a obtine
acelasi efect ca si cand ar utiliza declaratia:
(2) sir sir2 (“C++ este un C mai bunâ€Â) ;
In realitate ,cele doua declaratii nu realizeaza acelasi lucru.
In cazul declaratiei (10,la instantierea lui sir2 se apeleaza
constructorul:
sir (int nrcar = 70 )
care rezerva o zona de memorie de 70 de octeti in care se pastreaza
sirul vid.
Adresa de inceput a acestei zone se atribuie lui sir.psir ,apoi
se copiaza cu bit(bitwise copy) valorile componentelor obiectului sir1
(sir1.psir si sir.lung) in zonele de memorie alocate componentelor
corespunzatoare ale obiectului sir2.In felul acesta ,sir2.psir are
acceasi valoare ca si sir1.psir.Zona de memmorie de 70 de octeti alocata
in memmoria heap este pierduta si nu se mai poate face acces la ea.De
asemenea ,textul de initializare este pastrat intr-un singur
exemplar,situatie care,de obicei,va conduce la erori in prelucrarea
ulterioara a obiectelor sir1 si sir2.
De asemenea,la distrugerea obiectelor sir1 si sir2 ar urma ca
textul de initializare,pastrat intr-un singur exemplar,sa fie eliberat
din memmoria heap de doua ori.De accea,copierea implicita bit cu bit a
obiectelor nu este o solutie corecta pentru obiectele clasei sir.
Instantierea lui sir2 cu ajutorul decalaratiei (2) nu are nici o
legatura cu instantierea lui sir1 si se rezerva o zona de memorie in
memoria heap distincta fata de cea rezervata pentru acelasi text la
instantierea lui sir1.De accea,
sir1.psir
si
sir2.psir
au valori diferite.
Acelasi lucru este valabil si in cazul atriburilor.Fie de exemplu
instantierile:
sir1 sir1(“C++ este un C mai bun “);
sir sir2;
Ariburiea :
Sir2 = sir1 ;
realizeaza o copiere bit cu bit,deci sir1.psir si sir2.psir devin egale
si pointeaza spre acceasi zona de memorie heap care a fost rezervata la
instantierea lui sir1.Ca si in cazul declaratiei (2),zona de memorie din
memoria heap alocata la instantierea lui sir2 este pierduta in urma
atribuirii,deoarece ea devine inaccesibila.
Din cele de mai sus,rezulta ca pentru obiectele care sant
instantieri ale clasei sir nu este suficienta copierea implcita bit cu
bit.In astfel de cazuri este nevoie ca utilizatorul sa defineasca
copieri specifice,care sa tina seama de natura componentelor obiectelor.
In general,operatia de initializare prin copiere direfita de cea
de atribuire,deoarece initializarea este insotita de alocare.De
accea,sant necesare doua tipuri de copieri,una care sa se realizeze la
initializare prin copiere,adica declaratii de forma:
nume_clasa obiect2 = obiect1 ;
si una pentru atribuiri de obiecte:
obiect2 = obiect1
Initializarea prin copiere se realizeaza cu
ajutorulconstructorului de copiere care a fost definit in paragraful
22.8.
Un astfel de constructor are un prototip de forma:
nume_clasa ( const nume_clasa & obiect ) ;
Mentionam ca,un astefel de constructor se apeleaza automat la
instantierea unui obiect printr-o declaratie de forma (3).
Copierea bit cu bit se realizeaza numai dca clasa nu are un astfel
de constructor.
Clasa sir, definita in exercitiul 22.12 .,are un constructor de
copiere definit ca mai jos:
sir :: sir (sonst sir& s)
{
lung – s.lung ; //se copiaza ungimea sirului
//se aloca zona pentru sir
psir = new char [lung+1];
//se copiaza sirul in zonarezervata
strcpy (psir, s.psir);
}
Acest constructor se va apela automat la intalnirea declaratiei
(1) si rezultatul lui consta in accea ca declaratia (1) are acelasi
efect ca si declaratia (2).
Constructorul de copiere nu se apeleaza la atribuiri.
Pentru a solutiona in mod corect atribuirile de obiectede felul
celor de mai sus , este necesar sa supraincarcam in mod
corespunzatoroperatorul de atrbuire ( = ).
In principiu,constructorii de copiere si supraincarcarea
operatorului de atribuire sant necesari pentru clasele care au ca date
membru pointeri spre zone alocate in memoria heap (alocate dinamic)
Un alt caz in care se aloca obiecte temporare pe stiva se de accea
intervin operatii similare cu cele de la initializare.
Pentru ca aceste transferuri de obiecte sa se faca corect pentru
obiecte cu componente pointeri spre date din memoria heap ,este necesar
sa avem constructor de copiere in clasa respectiva.
Acesta se va apela automat atat la transferul prin parametri a
obiectelor precum si returnarea de obiecte,se realizeazaaplicand-se
copierea implicia,adica copierea bit cu bit.
Un exemplu in care se utilizeaza copierea bit cu bit, la
returnarea de obiecte,este clasa complex,implementat in exercitiul 22.1
In legatura cu supraincarcarea operatorului de atribuire este
neecsar sa amintim urmatoarele:
( supraincarcarea operatorului de atribuire se poate realizanumai
printr-o
functie membru care nu este statica ;
( obiectele operatorului se pot transfera prin valoare sau
referinta;
( obiectul din stanga operatorului de atribuire,dca are componente
pointeri
spre zone alocate in memoria heap trebuie eliberate inaite de
a se aloca
zone noi in vederea copierii elementelor corespunzatoare ale
obiectului
din dreapta operatorului respectiv;se obisnuieste sa se spuna
ca obiectul
din stanga operatorului de atribuire trebuie “curatatâ€Â
inainte de a se
atribui valorile obiectului din dreapta operatorului de
atribuire.
De obicei , functia pentru supraincarcarea operatorului de atribuire
are un parametru de tip referinta si returneaza o referinta la obiectul
curent.Aceasta deoarece transferul prin referinta este mai eficient
decat transferul obiectelor.
Avand in vedere acest fapt,se recomanda urmatorul antet pentru
supraincarcarea operatorului de atribuire :
nume_clasa& nume_clasa::operator = (const nume_clasa & operand_drept)
Obiectul curent este operandul stand al atribuirii
O astfel de functie se apeleza automat pentru reazlizarea atriburilor de
forma:
obiect2 = obiect1;
unde:
obiect1 si obiect2 – Sant instantieri ale clasei nume_clasa.
Atribuirile de forma:
obiect1 = obiect2 ;
Nu au nici un efect.De accea ,atrbuirile de acest fel se vor elimina.In
acest scop,in corpul functiei pentru supraincarcarea operatorului de
atrivuire se testeaza daca operatorul curent este diferit de cel referit
prin parametrul si numai in acest caz se executa corpul functiei.
Folosind antetul de mai sus,un astfel de test se poate realiza
astfel:
if(this != &operand_drept) {
//operanzi diferiti
…
}else //operanzi identici
return *this ;
Operatorul de atribuire are si o alta forma care se utilizeaza
pentru a face prescurtari.Este vorba de formatul:
op=
unde:
op -Este un operator binar aritmetic sau logic pe biti.
Aceste variante pot fi ele supraincarcate in mod
corespunzator.Mentionam ca,daca operatorii op si = sant
supraincarcati,nu decurge ca este supraincarcat si operatorul op=.Acesta
trebuie supraincarcat separat in mod corespunzator.
Operatorul op= se supraincarca folosind functii membru
nestatice care au un prototip similar cu functiile pentru
supraincarcarea operatorului de atribuire.
Exercitii:
23.14 Sa se implementeze tipul abstract sir pentru instantierea
sirurilor de caractere.
Tipul sir a fost definit in exercitiul 22.12.
In exercitiul de fata,se schimba functia membru atribsir a
clasei sir cu functia care supraincarca operatorulde atribuire.
In plus,se supraincarca operatorii + si += pentru
concatenarea sirurilor de caractere.
Expresia:
sir1 = sir2 = sir3
este legata pentru obiectele clasei sir si ea atribuie lui sir1,sirul
obtinut prin concatenarea lui sir3 la sfarsitul lui sir2.
Expresia
sir1 += sir2
este legata pentru obiectele clasei sir si ea are ca efect concatenarea
lui sir2 la sfarsitul lui sir1.
FISIERUL BXXIII14.H
class sir {
char *psir ;
int lung ;
public:
sir(chat s); /* constructor pentru initializarea obiectului cu
pointerul spre copia
in memoria heap a sirului spre
care pointeaza s */
sir (int nrcar = 70); /* constructor care rezerva zona de
memorie in memoria heap si pastreaza
in ea sirul vid */
sir (const sir&(; /*constructor de copiere*/
~sir () ; //destructor
int retlung(); //returneaza lungimea sirului
void afsir(); //afiseaza sirul
int citsir(); //citeste un sir de caractere
sir& operator = (const sir&); //supraincarca =
sir operator +(sir&); /* returneaza un obiect de tip sir obtinut
prin
concatenarea prametrului la sfarsitul
obiectului curent */
sir& operator += (sir&); /* concatenarea parametrului la
sfarsitul obiectuluicurent */
};
Fisierul de mai jos este extensie .cpp si el contine definitiile
functiilor membru.
FISIERUL BXXIII14
#ifndef __STDIO_H
#include
#define __STDIO_H
#endif
#ifndef __STRING_H
#include
#define __STRING_H
#endif
#idndef __SIR_H
#include “BXXIII14.Hâ€Â
#define __SIR_H
#endif
sir::sir (chat *s)
/* constructor utilizat la initializarea obiectului cu pointerul spre
copia in memoria heap a sirului spre care pointeaza s */
{
lung = strlen(s); //lungimea sirului
psir = new chat[lung+1]; //rezerva zona in memoria heap
strcpy(psir,s); //transfera sirul in memoria heap
}
sir:::sir (int dim)
/*-constructor utilizat pentru a rezolva in memoria heap o zona de dim+1
octeti;
-pastreaza sirul vid in zona respectiva.*/
{
lung = dim ; //pastreaza lungimea
psir = new chat [lung+1]; //rezerva zona
*psir = ‘ ’;
}
sir::sir(const sir& s) //constructor de copiere
{
lung = s.lung ; //pastreaza lungimea sirului
psir = new chat [lung+1] ; //rezerva zona
strcpy(psir,s.psir); //copiaza sirul
}
inline sir::~sir //destructor
{
delete psir;
}
inline int sir::retlung()
/*returneaza numarul de caractere din compunerea sirului fara caracterul
NUL */
{
return lung;
}
inline void sir::afsir() //afiseaza sirul spre care pointea psir
{
printf(psir);
printf(,,
â€Â);
}
int sir:citsir()
/* -citeste un sir de la intrarea standard si-l pasteaza in zona heap
rezervata pentru
obiectul curent;
-returneaza:
0  la sfarsit de fisier;
-1  la trunchiere;
1  altfel
*/
{
char temp [255];
if(gets(temp) = = 0) return 0 ; //s-a intalnit EOF
strncpy(psir,temp,lung); /* se copiaza sirul citit */
*(psir+lung) = ‘ ’;
if (strlen (temp) >lung return –a; //truchiere
else return 1;
}
sir& sir::operator = (const sir & operand_drept)
//supraincarca operatorul =
{
if (this != &operand_drept){
//operanzi diferiti
delete psir ; //curata obiectul curent
lung = operand_drept.lung ; //pastreaza lungimea
psir = new char [lung+1]; //rezerva zona
//transfera sirul in zona rezervata
strncpy (psir,operand_drept.psir,lung);
*(psir+lung) = ‘o’;
}
return *this ;
}
sir sir::operaot+ (sir& sir2)
/* returneaza un obiect care este rezultatul concatenarii
obiectuluireferit de sir2 la
obiectul curent */
{
sir rtemp;
delete rtemp.psir; //curata obiectul rtemp
rtemp.lung = lung; /* determina lungimea sirului rezultat */
//reserva memorie pentru sirul rezultat
rtemp.psir = new char [rtemp.lung+1];
strcpy(rtemp.psir,psir); //transfera sirul curent
/*concateneaza sirul referit de sir2 la starsitul sirului spre care
pointea rtemp.psir */
return rtemp;
}
sir& sir ::operator += (sir& operand_drept(
/*concatenarea obiectului operand_drept la obiectul curent */
{
/*pentru concatenare se utilizeaza operatorul + supraincarcat,iar
pentru atribuire
operatorul = supraincarcat */
*this = *this+operand_drept;
return *this:
}
23.15. Sa se scrie un program care citeste intregi din intervalul
[1,99] si afiseaza exprimarile lor prin cuvinte.
Programul construieste exprimarea in cuvinte a numerelor din intervalul
respectiv prin concatenarea compoentelor sale.
Exemple:
11 unsprezece
12 doisprezece
…
15 cincisprezece
16 saisprezece
17 saptesprezece
…
20 douazeci
21 douazeci si unu
22 douazeci si doi
…
29 douazeci si noua
30 treizeci
…
37 treizeci si sapte
…
40 patruzeci
…
45 patruzeci si cinci
…
60 saizeci
…
66 saizeci si sase
…
70 saptezeci
…
76 saptezeci si sase
…
99 nousazeci si noua
Se observa ca numerele peste 10,dar mai mici de 20 se termina in
sufizul sprezece.De asemenea,daca consideram numerele de la 1 la
9,observam ca exprimarea in cuvinte a acestora se urilizeaza drept
componentepentru exprimarea in cuvinte a numerelor maimari.Exista cateva
exceptii,ca de exemplu:
11,16,20-29 etc.
Tinand seama de aceste observatii,vom proceda camai jos.
Se defineste tabloul cu denumirile unitatilor:
char *unitate[] = {
“ “ ,
“unuâ€Â,
“doiâ€Â,
………
“nouaâ€Â
};
Pentru un numar n din intervalul [1,9] exprimarea este data de
elementul unitate[n].
Pentru un numar n din intervalul [12,19] diferit de 16,exprimarea
se obtine concatenand unitate[n/10] cu sprezece.
Pentru numerele n mai mari decat 20,exprimarile in cuvinte se
termina prin:
Douazeci pentru 20-29
Treizeci pentru 30-39
Patruzeci pentru 40-49
Cincizeci pentru 50-59
Saizeci pentru 60-69
Saptezeci pentru 70-79
Optzeci pentru 80-89
Nouazeci pentru 90-99
Aceste cuvinte su sufixul zeci ,iar prefixul este un element al
tabloului unitate,exceptand intervalele 20-29 si 60-69.Pentru primul
interval prefizul este doua,iar pentru al doilea interval prefixul este
sai.
Rezulta urmatorul procedeu:
daca n/10=2,atunci prefixul doua se concatenea cu zeci;
daca n/10=6,atunci prefixul sai se concateneaza cu zeci;
altfel unitate[n/10] se concateneaza cu zeci
PROGRAMUL BXXIII15
#include
#include “BXXIII14.CPP†//clasa sir
#include “BVIII2.CPP†//pcit_int
#include “BVIII3.CPP†//pcit_int_lim
main ()
/* -citeste intregi zecimali din intervalul [1,99[;
afiseaza exprimarile lor in cuvinte
*/
{
int n;
char *unit [] [ “ “ , “unu†, “doi†, “treiâ€Â
,â€Âpatruâ€Â,â€Âcinciâ€Â,â€Âsaseâ€Â,â€Âsapteâ€Â,â€Âoptâ€Â,â€Ânouaâ€Â};
sir zece (“zeceâ€Â);
sir spre (“spreâ€Â);
sir un (“unâ€Â);
sir sai (“saiâ€Â);
sir doua (“douaâ€Â);
sir zeci (“zeciâ€Â);
sir si (“siâ€Â);
sir rez;
int q,r;
for (;;) {
if (pcit_int_lim(“n = “,1,99,&n) = = 0)
exit(0);
q = n/10;
r = n%10;
switch (q) {
case 0 : { //[1,9]
sir rez0(unit [n]);
rez = rez0 ;
break ;
}
case 1: { //[10,19]
if ( n = = 10 ) rez = zece ;
else
if (n == 11) rez = un+spre+zece;
else
if (n = = 16) rez = sai+spre+zece;
else {
sir rez0(unit[r]);
rez = rez0+spre+zece;
}
break;
}
case 2 : { //[20-29]
rez = doua + zeci;
if (n = = 20) break;
rez += si;
sir rez0(unit[r]);
rez += rez0;
break;
}
case 6: { //[60-69]
rez =sai+zece;
if (n = = 60) break;
rez += rez- (unit[r]);
rez += rez0
break;
}
default : { //[30-39],[40-49],[50-59],[70-
79], [80-89],[90-99]
sir rez0 (unit [q]0;
if ( r = = 00 break;
rez += si;
sir rez1(unit[r]);
rez += rez1;
}
} //sfarsit switch
//afisare n si exprimare prin cuvinte
printf (“
n = %d â€Â,n);
rez.afsir();
}
}
Observatie :
Corpul functiri poate fi scris mai compact folosind
instructiuni if in locul instructiunii switch:
if (q = = 00 //[1,9]
sir rez0(unit[n]);
rez=rez0;
}
else
if (q = =1) { //[10,19]
if (n = = 10) rez = zece;
else {
if (n= = 11 0 rez = un ;
else
if (n = = 160 rez = sai;
else {
sir rez0 (unit[r]);
rez=rez0
}
rez += spre + zece;
}
} //sfarsit [10,19]
else {
if (q = = 2) //[20,29]
rez = doua;
else
if (q = = 6) //[60,69]
rez = sai;
else{
sir rez0(unit[q]0;
rez=rez0;
}
rez += zeci;
if (r) {
sir rez0 (unit[r])
rez += si + rez0;
}
}
23.3 Supraincarcarea operatorului [] (operatorul de indexare)
Operatorul [] predefinit se utilizeaza pentru a face acces la
elementele unui tablou.
De exemplu,daca tab este un tablou unidimensional de un tip
predefinit,atunci o expresie de forma:
tab [exp]
permite acces la elementul tabloului tab de indice exp,exp fiind o
expresie care furnizeaza o valoare de tip intreg.
Constructia (1) a fost numita ariabila cu indici.Ea este o
expresie formata din doi operanzi:
tab si exp
la care se aplica operatorul de indexare ( [] ).De obicei, expresia (1)
are si o interpretare unitara si anume se considera ca formand un
operand.Aceasta interpretare este posibila datorita faptului ca
parantezele sant operatori de prioritate maxima.
Interpretarea expresiei (1) ca operand se justifica datorita
faptului ca ea area utilizari similare cu numele unei variabile
simple;ambele permit acces la o data de un tip predefinit.
Constructia de mai sus este variabila si in cazuri mai
generale,cand primul operand este chiar o expresie de pointeri,care are
ca valoare un pointer.
Exemplu:
Int *p;
Int I,j;
Expresiile de mai jos sant legale:
p[1]
p[i]
p[i+2]
p[i-1]
(p+20[i*3+j]
(p-10)[i*3-2*j]
Utilizatorul poate supraincarca operatorul [] pentru a da sens
constructiilor de felul celor de mai sus si in cazul in care operanzii
sant obiecte.
Expresiile de forma (1) sunt expresii lvalue (se pot utiliza ca
parte stanga intr-o atribuire).De accea,la supraincarcarea operatorului
[] pentru tipuri abstracte,ca si la supraincarcarea operatorului = ,se
va utiliza o functie membru nestatica,functie care sa returneze o
referinta la elementul selectat prin functia respectiva.
In aceste conditii,functia pentru supraincarcarea operatorului []
are antetul general:
Tip & nume_clasa::operator[](tip_indice i)
Odata supraincarcat operatorul [] ca mai sus,sunt legate
expresiile de forma:
obiect [exprsie]
unde:
obiect -Este o instatiere a clasei nume_clasa
expresie -Este o expresie care are tipul tip_indice sau un tip
convertibil spre
acesta
Expresia (2) are ca rezultat o referinta la elementul definit prin
functia care supraincarca operatorul [].Ea este o lvalue si deci se
poate utiliza in ambele parti ale unei expresii de atribuire.De
asemenea,expresia (2) se poate interpreta ca fiind un operand,neglijand
faptul ca ea se compune din doi operanzi la care se aplica operatorul de
indexare.
Operandul de aceasta forma reprezinta un apel al functiei membru
operator[].
Astfel, operandul (2) de mai sus,se evalueaza prin apelul:
obiect.operator[] (expresie)
unde:
operator[] -Reprezinta numele functiei membru care supraincarca
operatorul [] si ea este apelata pentru obiectul obiect si indicele
expresie.
Interesul pentru formatul (2) fata de apelulexprimat prin (3)
rezulta din faptul ca reprezinta o exprimare clara si care este
incetatenita pentru tipurile predefinite de date.
PAGE 1
PAGE 27
ì¥Â@