Programarea Calculatoarelor: Laborator 7
Tablouri. Șiruri de caractere
Exercițiu pregătitor
Implementați câteva funcții simple pentru lucru cu șiruri de caractere:
- funcția standard strlen care returnează lungimea unui șir:
size_t strlen(const char *s)
Reamintim că size_t e un tip întreg fără semn folosit pentru dimensiuni (e tipul returnat de operatorul sizeof), iar specificatorul const precizează că obiectul respectiv (șirul s) nu e modificat.
Scrieți un ciclu care parcurge șirul cu un indice până când întâlnește caracterul '\0' (fanionul de sfârșit de șir) și returnează valoarea indicelui (care numără caracterele parcurse).
- Scrieți o funcție int strindex(const char *s, char c) care returnează valoarea primului indice la care se găsește caracterul c în șirul s, sau valoarea -1 în cazul cănd caracterul nu e găsit.
Ciclul de parcurgere a șirului va avea în acest caz două condiții de ieșire, corespunzătoare celor două cazuri. O variantă simplă e să scriem ciclul cu una din condiții, iar pe cealaltă s-o verificăm în interiorul ciclului, și să ieșim din ciclu returnând direct
valoarea funcției.
- funcția char *strchr(const char *s, int c) care la fel cu cea de mai sus caută un caracter (reprezentat de întregul c) într-un șir, dar returnează adresa caracterului găsit, sau NULL dacă acesta nu există în șir
- variantele strrindex și strrchr ale funcțiilor de mai sus, care găsesc ultima apariție a caracterului în șir
Exercițiul 1 Scrieți o funcție care ia ca parametru un șir de caractere și returnează valoarea numărului aflat în porțiunea inițială a șirului.
Funcția acceptă ca șirul să conțină un număr arbitrar de spații albe inițiale, opțional semnul (+ sau -), și apoi cifre în baza 10. Conversia se oprește la întâlnirea primului caracter necorespunzător. Dacă până în acel punct nu s-a întâlnit un număr valid, funcția returnează zero.
Observație: O astfel de funcție standard există: int atoi(const char *s) și e declarată în stdlib.h.
Funcția va construi numărul similar cu cele de citire de numere întregi (readnat, readint) scrise anterior, cu deosebirea că numărul e conținut în șir. Funcția nu va citi pe rând caractere de la intrare, ci va avansa cu indicele în șir.
Variantă: scrieți o funcție care se comportă similar, dar acceptă un șir reprezentând un număr într-o bază arbitrară (între 2 și 36), dată ca al doilea parametru. Cifrele cu valori începând de la 10 sunt reprezentate prin litere mari sau mici.
Exercițiul 2
Scrieți un program care calculează toate numerele prime până la o limită dată (1000) folosind ciurul lui Eratostene. Declarați un tablou cu indici până la limita dată, care la sfârșit va conține 1 pe o poziție dacă numărul e compus, și 0 dacă e prim. Inițial, tabloul conține peste tot 0, apoi se pune 1 pe toate pozițiile care nu sunt numere prime (multiplii de 2, 3, 5, etc.)
Exercițiul 3
Completați o matrice N x N în spirală cu numerele de la 1 la N*N pornind de la colțul din stânga sus, în sensul acelor de ceasornic. Afișați matricea.
Exercițiul 4
Completați o matrice cu reprezentarea unui fractal de formă pătrată, folosind valori diferite (de exemplu 1 și 0) pentru căsuțele (elementele) tipărite (ocupate) și libere. Tipăriți matricea, folosind caracterele * și spațiu. Ca exemple, folosiți fractalul cu cruciulițe sau covorul lui Haferman.
Pentru a rezolva problema:
- stabiliți ca și constantă ordinul fractalului (numărul de pași de transformare) și declarați o matrice pătrată de dimensiune corespunzătoare.
- definiți o funcție recursivă care completează matricea pentru o figură (pătrat) de ordin dat, și se autoapelează pentru a construi figurile (pătratele) de ordin mai mic din care e compusă. Funcția va primi ca parametru coordonatele pătratului (de exemplu un colț, sau centrul său)
- pentru cazul al doilea (covorul), scrieți fie două funcții, câte una pentru cele două pătrate care sunt transformate după reguli diferite (plin și gol), fie folosiți un parametru suplimentar (valoare: 1 sau 0) pentru a identifica tipul de pătrat care trebuie completat.
Exercițiul 5 Scrieți o funcție care normalizează (simplifică) un șir de caractere care conține un nume de fișier. Șirul conține opțional mai multe componente de nume de catalog (directory), separate de caracterul / și în final numele propriu-zis de fisier. Funcția va efectua următoarele prelucrări:
-
O componentă de nume .. înseamnă catalogul părinte (trecerea cu un nivel mai sus în ierarhia de fisiere). Dacă e precedată de o altă componentă (care nu e ..) are ca efect eliminarea componentei anterioare din nume. De exemplu, numele users/doru/../dragos revine din catalogul doru un până la users și apoi din nou un nivel în jos în catalogul dragoș. Deci numele poate fi simplificat la users/dragos.
O componentă de catalog .. aflată la începutul unui nume: ../lib/libc.so nu poate fi simplificată, deoarece nu știm numele catalogului care se află cu un nivel mai sus.
Catalogul părinte al catalogului rădăcină (/ aflat la începutul numelui) este tot rădăcina, deci /../ la începutul unui nume poate fi înlocuit cu /
-
O componentă de catalog cu numele . (catalogul curent) nu are nici un efect (nu schimbă catalogul), deci poate fi eliminată. De exemplu, ./fisier.txt devine fisier.txt
-
Dublarea separatorului / nu are nici un efect, // poate fi înlocuit cu /.
Scrieți o funcție care ia ca parametru un șir de caractere reprezentând un nume de fișier și îl transformă simplificând-ul după regulile date. (Fiecare regulă poate doar să reducă dimensiunea șirului, deci rezultatul va încape în locul alocat șirului inițial).
Marius Minea
Last modified: Sat Apr 5 17:38:25 EET 2008