Probleme de antrenament (Utilizarea si programarea calculatoarelor, sem. I) Șiruri și calcule simple: Se citesc de la intrare notele obținute de un grup de studenți, sub forma unui șir de numere naturale cu valori între 1 și 10, încheiat de numărul 0 (care nu se consideră a face parte din șir). Să se afișeze: - pentru fiecare notă, câți studenți au obținut acea notă - ce procentaj de studenți a obținut notă de trecere (>= 5) - care este media aritmetică a tuturor notelor (cu două zecimale exacte) - care este nota (sau notele) obținută de cei mai mulți studenți Se citește de la intrare un șir de numere întregi de 5 cifre, reprezentând codurile poștale de pe o serie de scrisori. Citirea se oprește când se întâlnește numărul 0. Primele 3 cifre din fiecare cod reprezintă zona, iar ultimele două cifre localitatea sau cartierul din zona respectivă. Să se afișeze câte zone sunt reprezentate în adresele din scrisori, și câte scrisori trebuiesc trimise în fiecare zonă. Numere în format extern și intern, în diverse baze: Se citesc de la intrare trei șiruri de câte cel mult 9 cifre zecimale, fiecare pe câte o linie. Ele reprezintă trei numere, dar nu se știe în ce bază. Să se determine dacă există vreo bază în care suma primelor două numere să fie egală cu al treilea. Exemple: 1024 + 321 = 1345 în orice bază >= 6 1442 + 26 = 1501 în baza 7. Tablouri și pointeri: Să se completeze o matrice NxN cu numerele de la 1 la N^2 în spirală pornind din colțul din stânga sus, în sens invers trigonometric. Rezolvați problema întâi pentru N fix, cu alocare statică, și apoi pentru N citit de la intrare, cu alocare dinamică. Se citește de la intrare o matrice NxN, conținând numerele de la 0 la N^2-1. Elementele se dau câte N pe linie. Locul indicat cu 0 se consideră gol, iar celălalte ocupate de piese care se pot mișca în planul matricii (ca într-o cunoscută jucărie cu numere de la 1 la 15). Se mai citește de la intrare o linie formată din caracterele u (sus), j (jos), s (stânga) și d (dreapta), fiecare reprezentând o comandă prin care o piesă adiacentă cu spațiul gol, se mută în locul acestuia, în direcția dată. Să se afișeze matricea rezultantă, sau mesaj de eroare pentru un șir de comenzi invalid. Rezolvați problema întâi pentru N fix, cu alocare statică, și apoi pentru N citit de la intrare, cu alocare dinamică. Modificați citirea datelor dacă spațiul liber din matrice nu e reprezentat la intrare prin 0, ci prin caracterul *. Citire formatată de la intrare: Să se scrie secvențe de cod care să accepte de la intrare următoarele: ("spațiu" se referă la caracterele definite conform cu isspace() ) - o linie de maxim 80 de caractere arbitrare - o linie de lungime arbitrară - un cuvânt de maxim 80 de caractere, fără spații, ignorând spațiile dinainte - un cuvânt de maxim 80 de caractere, fără spații, fără spații la început - un identificator, de maxim 32 de caractere - o atribuire de forma identificator = identificator cu spații arbitrare, și identificatori de cel mult 32 de caractere - ca mai sus, identificator=identificator , dar fără spații - un număr întreg, dacă e urmat de spații - un număr întreg, dacă e urmat de orice în afară de punct sau _ sau litere - un șir de N numere întregi, toate pe o linie, despărțite prin spații - un șir de N numere întregi, toate pe o linie, despărțite prin câte o virgulă, și eventual spații - un număr întreg, verificând dacă se produce depășire (nr. prea mare) În toate aceste cazuri, utilizatorul poate introduce orice și oricât de multe caractere. Codul trebuie să accepte *doar* cazurile specificate, și să dea un mesaj de eroare în caz contrar. Șiruri: Să se implementeze funcția char *strstr(const char *where, const char *substr) care returnează un pointer la prima apariție a șirului substr în șirul where (dacă există), sau NULL în caz contrar. Să se implementeze funcția char *strdup(const char *s) care returnează o copie alocată dinamic a șirului str sau NULL în caz de memorie insuficientă. Să se implementeze funcția void *memmove(void *dest, const void *src, size_t n); care copiază n octeți din zona de memorie src în zona de memorie dest, care pot avea o porțiune comună Lucru pe biți: Să se genereze în ordine toate numerele de la 0 la 255, folosind operatori pe biți pentru a implementa incrementarea cu 1. Scrieti o functie checksum care calculeaza o suma de control pentru un bloc de memorie. Functia are doi parametri: adresa de memorie a blocului (de tip nespecificat), si un intreg nenegativ, reprezentand lungimea blocului in octeti. Functia returneaza un rezultat pe 8 biti, calculat dupa cum urmeaza: bitul k (0 <= k <= 7) al rezultatului este egal cu paritatea sumei octetilor de pe pozitiile egale cu k modulo 8 din bloc (k, k+8, k+16, etc). Enumerări, structuri și uniuni: Să se implementeze o funcție care citeșțe după caz unul sau mai multe caractere de la intrare, și returnează câte o valoare distinctă pentru: - număr întreg - număr real - caracter între ' ' - șir de caractere între " " - semnele +, -, =, == - eroare (pentru orice altceva) Pe lângă valoarea returnată, funcția va completa într-o variabilă de tip uniune a cărei adresă e transmisă ca parametru, valorile în caz că elementul citit de la intrare este întreg, real, caracter sau șir Fisiere: Pentru toate programele de mai jos, dacă nu se specifică parametri pe linia de comandă, se face citirea din fișierul standard de intrare, până la sfârșit de fișier. Să se implementeze programul wc care numără caracterele, cuvintele (considerate ca fiind despărțite prin spații), si linii dintr-un fișier. Programul ia ca argument pe linia de comandă numele fișierului și tipărește cele 3 numere, fiecare pe 7 poziții (cu spații la stânga), cu câte un spațiu între ele. Suplimentar: dacă se specifică mai multe fișiere pe linia de comandă se afișează pe câte o linie rezultatele de mai sus, urmate de un spațiu și numele fișierului. La sfârșit se afișează o linie cu totalurile pe cele 3 coloane, apoi un spațiu și cuvântul "total". Să se implementeze programul grep care tipărește liniile dintr-un fișier care conțin un cuvânt dat. Programul ia ca argument pe linia de comandă cuvântul de căutat, urmat de numele fișierului. Suplimentar: dacă se specifică mai multe fișiere pe linia de comandă, se caută în fiecare din fișiere, și se prefixează liniile afișate cu numele fișierului și : Dacă în linia de comandă (înainte de cuvânt) se specifică opțiunea -n se afișează fiecare linie precedată de numărul liniei în fișier și : (totul precedat dacă e cazul de numele fișierului, ca mai sus). Să se implementeze programul sort care sortează alfabetic liniile din fișierul specificat pe linia de comandă și le scrie la ieșire. Suplimentar: dacă se specifică mai multe fișiere pe linia de comandă, se sortează împreună liniile din toate fișierele. Să se implementeze programul 'uniq' care citește fișierul specificat pe linia de comandă, și îl scrie la ieșire eliminând eventualele copii identice consecutive ale unei linii (și păstrând doar una). Recursivitate: Să se genereze toate permutările numerelor de la 1 la n. Să se genereze toate șirurile de n caractere 0 sau 1. (recursiv, și apoi nerecursiv). Sortare: Să se scrie un program care ia două șiruri de valori sortate, și le combină într-un unic șir, și el sortat. Scrieți programul pentru variantele: - șirurile sunt de numere întregi în tablouri de dimensiuni date, și se scriu într-un tablou dat (sau alocat dinamic) - șirurile sunt de numere reale, câte unul pe linie, în două fișiere date pe linia de comandă. Se scrie în fișierul standard de ieșire - la fel ca mai sus, dar fișierele conțin linii de text sortate alfabetic.