Programul memoreaza identificatorii si valorile asociate lor într-o evidenta, pe care o foloseste conform functionalitatii cerute. Evidenta este realizata printr-o lista simplu înlantuita ordonata. Fiecare nod al listei contine un câmp pentru pastrarea identificatorului, care este indicat de char *id, un câmp pentru memorarea valorii asociate identificatorului, câmpul int valoare, si un câmp pentru a crea înlantuirea cu nodul urmator din lista, câmpul struct elem *urm. Lista este ordonata crescator functie de câmpurile id ale nodurilor.
Functia main apeleaza functia meniu. Aceasta
afiseaza în mod repetat, datorita instructiunii while(1)
de pe linia /* meniu 1 */, optiunile pe care le ofera
programul. În continuare, meniu citeste de la tastatura
optiunea dorita (linia /* meniu 2 */) si caracterul
Return
. În functie de optiunea aleasa (linia /*
meniu 3 */) se selecteaza rutina ce implementeaza
functionalitatea dorita.
Rutina comanda_a citeste un identificator si valoarea asociata lui, dupa care îl introduce în evidenta. Citirea se face apelând functia citesc_linie. În cazul în care lungimea identificatorului citit este 0, se afiseaza un mesaj de eroare. În caz contrar, identificatorul si valoarea asociata lui sunt introduse în lista ordonata prin apelarea rutinei introducere.
comanda_t citeste un identificator folosind citesc_linie. Daca lungimea identificatorului este 0, atunci se afiseaza mesajul ca linia este incorecta. Daca însa lungimea este diferita de 0, atunci identificatorul este cautat în lista (apelând functia caut). Daca identificatorul apare în lista, atunci se afiseaza valoarea asociata lui, în caz contrar se tipareste un mesaj de eroare adecvat.
Functia comanda_s citeste o linie ce contine un identificator (folosind citesc_linie). Daca linia citita este corecta (adica lungimea identificatorului este nenula), atunci identificatorul este eliminat din evidenta prin apelarea lui sterg.
comanda_oper citeste doi identificatori (liniile /* comanda_oper 1 */ si /* comanda_oper 2 */) si efectueaza o operatie aritmetica cu acesti operanzi. Felul operatiei dorite este transmis prin parametrul char c al rutinei comanda_oper. Daca identificatorii sunt corecti (au lungimile diferite de 0), atunci ei sunt cautati în evidenta (linia /* comanda_oper 3*/). Daca ambii apar, atunci, functie de c, se efectueaza operatia dorita, iar rezultatul este afisat.
Citirea unei linii de la tastatura se face prin rutina
citesc_linie. Linia /* citesc_linie 1 */ citeste în
variabila locala temp o linie de la tastatura. Ciclul while
de pe linia /* citesc_linie 2 */ parcurge tabloul
temp. Daca gaseste o litera (linia /*
citesc_linie 3 */), atunci înseamna ca a descoperit începutul
unui identificator. Ciclul while de pe linia /* citesc_linie 4
*/ preia întregul identificator si îl memoreaza în tabloul al
carui început este indicat de parametrul char *s. Linia
/*citesc_linie 5 */ memoreaza caracterul ''0'' ce
indica sfârsitul identificatorului. Daca la parcurgerea lui
temp este întâlnita o cifra (linia /* citesc_linie
6 */), atunci a fost descoperit începutul numarului care apare
în linia de text. Acest numar este preluat prin ciclul while de pe
linia /* citesc_linie 7 */, calculându-se simultan si
valoarea numerica asociata lui. Linia /* citesc_linie 8 */
face conversia, din sirul de caractere asociat numarului întreg,
în valoarea lui. Calcularea valorii numerice se face folosind
variabila întreaga a carei adresa este transmisa prin parametrul
int *val. Linia /* citesc_linie 9 */ "sare" peste
acele caractere care nu fac parte din identificator sau numar.
caut parcurge lista al carei început este transmis prin
parametrul nod *lista, cautând nodul al carui
identificator este egal cu sirul indicat de parametrul char
*s. Daca un astfel de nod este gasit, atunci caut
returneaza pointerul catre el. În caz contrar, returneaza NULL.
Parcurgerea listei se face prin ciclul for de pe linia /* caut
1 */. Variabila q1 este initializata astfel încât sa
indice începutul listei. La sfârsitul fiecarei iteratii,
q1 este mutat catre urmatorul nod. Conditia de reluare a
ciclului este ca lista sa nu fi fost parcursa în întregime
(conditia q1 != NULL de pe linia /* caut 1 */) si
identificatorul sa nu fi fost gasit. Deoarece lista este ordonata
crescator este suficient sa testam ca strcmp(q1-id,s)
0 (linia /* caut 1 */). Linia /* caut 2 */
verifica daca identificatorul a fost gasit. Pentru aceasta este
necesar ca q1 != NULL (altfel s-ar fi parcurs toata lista)
si sirul memorat în nodul curent sa fie egal cu cel indicat de
s.
Rutina listez parcurge toate nodurile din lista si, pentru fiecare, afiseaza identificatorul retinut si valoarea atasata lui.
Rutina sterg elimina, din lista referita prin parametrul
nod *lista, nodul al carui identificator este egal cu sirul
indicat de parametrul char *s. sterg returneaza
pointerul catre începutul listei modificate. Dupa eliminare, lista
ramâne ordonata. Pentru eliminarea unui nod sunt folositi doi
pointeri care parcurg lista. q1 indica nodul curent, în
timp ce q2 pe cel anterior lui. Acest lucru este necesar
deoarece la eliminarea nodului indicat de q1, înlantuirea
urm a nodului anterior (care este indicat de q2) se
modifica spre nodul urmator lui q1. Ciclul for de pe linia
/* sterg 1 */ parcurge lista. Pointerii q1 si
q2 sunt initializati sa indice spre începutul listei din
care se face stergerea. La fiecare reluare a ciclului, q2 ia
vechea valoare a lui q1, în timp ce q1 se muta
spre nodul urmator. Conditia de reluare a ciclului for este ca lista
sa nu fi fost parcursa în întregime (q1 != NULL) si
nodul sa nu fi fost gasit (strcmp(q1-id, s)
0).
Daca nodul a fost gasit (linia /* sterg 2 */), atunci se
verifica daca el este sau nu primul nod al listei. Daca nodul nu
este chiar începutul listei (linia /* sterg 3 */), atunci
înlantuirea urm a nodului anterior celui indicat de
q1 se modifica spre nodul urmator celui indicat de
q1. Daca însa nodul indicat de q1 este primul din
lista, atunci variabila lista este schimbata spre al doilea
nod. Memoria ocupata de nodul eliminat este eliberata. Daca însa
nu exista un nod care sa aiba identificatorul egal cu sirul
indicat de s, atunci sterg tipareste un mesaj de
eroare.
introduc creeaza un nod nou care contine sirul indicat de parametrul char *s, iar câmpul lui de valoare este egal cu parametrul int v. Nodul este inserat în lista indicata de parametrul nod *lista, astfel încât dupa introducere, lista ramâne ordonata. introduc returneaza începutul listei modificate. Linia /* introduc 1 */ aloca memorie pentru noul nod. Daca alocarea nu este posibila, se afiseaza un mesaj de eroare si executia programului este încheiata. În caz contrar, câmpurile id si valoare sunt initializate corespunzator. Linia /* introduc 2 */ parcurge lista cautând pozitia în care noul nod trebuie introdus. Pentru introducerea unui nod într-o lista ordonata sunt necesari doi pointeri; unul indica nodul în fata caruia se face inserarea, iar al doilea pe cel anterior lui. Daca noul nod nu este inserat ca primul nod în lista (linia /* introduc 4 */), atunci înlantuirea de la nodul anterior (indicat de q2) se schimba catre nodul nou, iar înlantuirea noului nod se schimba spre nodul indicat de q1. Daca nodul devine primul în lista (linia /* introduc 5 */) atunci înlantuirea lui urm este modificata spre nodul indicat de q1. În acest caz valoarea returnata de introduc (care este începutul listei modificate) este tocmai pointerul spre nodul recent introdus. Daca în lista apare deja un nod al carui identificator este egal cu cel care se doreste a fi introdus (linia /* introduc 3 */), atunci se afiseaza un mesaj de eroare si se pastreaza lista nemodificata.