Differences

This shows you the differences between two versions of the page.

Link to this comparison view

programare:laboratoare:lab10 [2017/09/29 02:49]
darius.neatu removed
programare:laboratoare:lab10 [2020/10/05 00:38] (current)
darius.neatu [Prelucrarea şirurilor de caractere. Funcţii. Aplicaţii.]
Line 1: Line 1:
-===== StructuriUniuni. Aplicaţie: Matrice rare ===== +===== Prelucrarea şirurilor de caractereFuncţii. Aplicaţii. =====
- +
-**Responsabil:​** +
-  * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip]] (2016) +
-  * [[mihaela.vasile@gmail.com|Mihaela Vasile]]+
  
 +**Resposabili:​****Responsabili:​**
 +  * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip (CA 2016-2020)]]
 +  * [[neatudarius@gmail.com|Darius Neațu (CA 2019-2020)]]
 +  * [[emil.racec@gmail.com|Emil Racec (2012)]]
 +  * [[alina.g.simion@gmail.com|Alina Simion (2008)]]
 +  * [[stefan.bucur@gmail.com|Ştefan Bucur (2006)]]
 ==== Obiective ==== ==== Obiective ====
  
-În urma parcurgerii acestui laborator studentul va fi capabil ​+În urma parcurgerii acestui laborator studentul va fi capabil: 
-  * organizeze datele din rezolvarea unei probleme complexe în structuri ​şi uniuni; + 
-  * optimizeze scrierea funcţiilor prin minimizarea numărului de parametri ​şi prin utilizarea structurilor ca parametri returnaţi ​de funcţie; +  * să declare ​şi să folosească şiruri de caractere 
-  * distingă diferenţa dintre o structură ​şi o uniune; +  * să folosească funcţiile de manipulare ​a şirurilor de caractere din libraria string.h
-  * evite utilizarea greşită a structurilor.+
  
 ==== Noţiuni teoretice ==== ==== Noţiuni teoretice ====
  
-=== Structuri ​=== + 
-Structurile sunt tipuri ​de date în care putem grupa mai multe variabile eventual ​de tipuri diferite ​(spre deosebire ​de vectori, care conţin numai date de acelasi tip). O structură se poate defini astfel:+ 
 +=== Şiruri de caractere ​=== 
 + 
 +Un **caracter** se declară în C de forma: ''​char a=%%'​a'​%%'';​ Pentru inițializarea lui, se observă că am pus un caracter între apostroafe. 
 + 
 +Un **şir de caractere** presupune practic un vector de caractere, terminat prin caracterul ''​\0''​.  
 + 
 +Compilatorul folosește ​în mod implicit această reprezentare,​ astfel încât cea mai simplă declarație este ''​char c[]="​cuvant"'';​ Observăm aici folosirea ghilimelelor în locul apostroafelor. Acecastă instrucțiune va aloca un spațiu ​de ''​7''​ octeți pe care va reprezenta șirul de caractere '​cuvant' ​(care are ''​6''​ caractere).  
 + 
 +Dacă dorim să alocăm un spațiu ​de memorie mai mare (pentru a putea folosi variabila pentru a stoca șiruri de caractere mai lungi)putem folosi o declarație de tipul ''​char c[10] = "​cuvant";''​. Astfel am alocat spațiu suficient pentru un șir de ''​9''​ caractere. 
 + 
 +<note important>​ 
 +Deși o inițializare de tipul ''​char c[6] = "​cuvant"'',​ în care spațiul alocat este egal cu numărul de caractere, nu va determina compilatorul să genereze un warning/o eroare, acest lucru poate avea rezultate neașteptate dacă în memorie - la finalul șirului - nu se află (întâmplător) valoarea 0 binar.  
 +</​note>​ 
 + 
 +Cum s-a prezentat anterior, o variabilă vector ​conţine adresa ​de început a vectorului(adresa primei componente a vectorului), şi de aceea este echivalentă cu un pointer la tipul elementelor din vector. Deci declaraţiile de mai jos vor declara fiecare cate un şir de caractere:
  
 <code c> <code c>
-struct nume_structura { +char a[5]; 
-  ​declaratii_de_variabile +char *b="​unsir";​ 
-};+char *c;
 </​code>​ </​code>​
  
-Definiția unei structuri poate fi urmată imediat ​de declararea ​de variabile ​de acel tipforma cea mai generală fiind:+Diferenţa majoră dintre între ele este însa că primele două declaraţii vor aloca 5 pozitii în memorie, pe când ultima nu va aloca nici o zona de memorie, necesitând sa fie ulterior alocată, folosind funcţiile de alocare dinamică (''​malloc(),​ calloc(), realloc()''​),​ prezentate în laboratorul anterior. 
 + 
 +Între prima și a 2-a declarație,​ diferența este mai subtilă și constră în faptul că declarația ''​char *b="​unsir"''​ va determina compilatorul să plaseze șirul respectiv într-o zonă de memorie asupra căreia nu avem drepturi ​de scriere, deci orice încercare ​de a modifica ​acel șir - pe Linux - va generacel mai probabil, o eroare de tipul ''​segmentation fault''​. 
 + 
 +Un mic exemplu de citire a unui şir, caracter cu caracter pana la întâlnirea caracterului ''​-''​: 
 <code c> <code c>
-struct [structure tag] {+#include <​stdio.h>​ 
 +#include <​string.h>​
  
-   ​member definition; +#define N 30 
-   member definition+  
-   ... +int main () { 
-   member definition+   char str[N], c
-} [one or more structure variables]; +   int n = 0; 
 +  
 +   do { 
 +     ​scanf("​%c",​ &c)
 +     if (c == '​-'​) { 
 +       ​break;​ 
 +     } 
 +     str[n++= c; 
 +   } while(1); 
 +    
 +   ​str[n] = '​\0';​ // setam terminatorul de șir 
 +   ​printf("​%s",​ str); 
 +    
 +   ​return 0; 
 +}
 </​code>​ </​code>​
  
-Unde între ​''​[]''​ se află câmpurile opționale.+

Pentru citirea si afisarea unui şir de caractere se poate folosi flagul ​'**s**' ​la citirea cu ''​scanf''​ sau afişarea cu ''​printf''​. De asemenea biblioteca ''​stdio.h''​ defineşte funcţiile ''​gets()''​ şi ''​puts()''​ pentru lucrul cu şiruri de caractere. 
 + 
 +  * ''​gets(zona)''​ -– citeşte de la terminalul standard un şir de caractere terminat cu linie noua (enter). 
 +      * Funcţia are ca parametru adresa zonei de memorie în care se introduc caracterele citite. 
 +      * Funcţia returneaza adresa de început a zonei de memorie. 
 +  * ''​puts(zona)''​ -- afişeaza la terminalul standard şirul de caractere din zona data ca parametru, până la caracterul terminator de şir (\0), în locul căruia va afișa caracterul sfârșit de linie. 
 +      * Funcţia are ca parametru adresa zonei de memorie de unde începe afişarea caracterelor. 
 +      * Funcţia returneaza codul ultimului caracter (diferit de \0) din şirul de caractere afişat şi -1 dacă a aparut o eroare. 
 + 
 +<note important>​ 
 +Funcţia ''​gets()''​ va citi de la tastatura câte caractere sunt introduse, chiar daca şirul declarat are o lungime mai mică. Presupunem un şir declarat: ''​char a[]=”unsir”'' ​, care va avea deci 5 caractere. Citind un şir de lungime mai mare ca 5 de la tastatura, în şirul a, la afişare vom vedea ca s-a reţinut tot sirul (nu doar primele 5 caractere)! . Nimic deosebit până acum. Dar dacă luăm în considerare că citirea caracterelor auxiliare ​se face în continuare în zona de memorie, ne punem problema ce se va suprascrie?​! 
 +Raspunsul este: nu se ştie... poate nimic important pentru programul nostru, poate ceva ce il va bloca sau duce la obţinerea de date eronate. 
 +</​note>​ 
 + 
 +Pentru a evita aceasta se recomandă utilizarea ''​fgets()''​. 
 + 
 +  * ''​fgets(zona,​ lung_zona, stdin)''​ -– citeşte de la ''​stdin''​ un şir de caractere terminat printr-o linie nouă dacă lungimea lui este mai mică decat ''​lung_zona''​ sau primele ''​lung_zona - 1''​ caractere în caz contrar. Parametrii sunt: zona de memorie, lungimea maxima admisă a şirului, şi terminalul standard de intrare. În cazul în care şirul dorit are lungime mai mică decât cea maximă, înaintea terminatorului de şir (\0), în zona de memorie va fi reţinut şi enter-ul dat(\n). 
 + 
 +=== Funcţii din <​string.h>​ === 
 + 
 +Pentru manipularea şirurilor de caractere în limbajul C se folosesc funcţii declarate în fişierul <​string.h>​. Vom încerca să le detaliem putin pe cele mai des folosite: 
 + 
 +== strlen() ==
  
-Exemple: 
 <code c> <code c>
-struct student { +size_t strlen(const ​char *str);
-  ​char nume[40]; +
-  int an; +
-  float medie; +
-};+
 </​code>​ </​code>​
  
-Variabilele declarate in interiorul structurii se numesc "​campurile"​ structurii+Returneaza lungimea unui şir dat ca parametru. (numarul de caractere până la întalnirea terminatorului de şir\0) 
-  ​*nume;​ + 
-  *an; +**Exemplu:**
-  ​*medie.+
  
 <code c> <code c>
-struct complex ​/* pentru memorarea unui număr complex cu dublă precizie */ +#include <​stdio.h>​ 
-  ​double re+#include <​string.h>​ 
-  ​double im+ 
-};+#define N 256 
 +  
 +int main () 
 +  ​char text[N]
 +  ​printf("​Introduceti un text: ")
 +  ​gets(text); 
 +  printf("​Textul are %u caractere.\n",​ strlen(text));​ 
 +  return 0; 
 +}
 </​code>​ </​code>​
  
-Declararea şi iniţializarea unor variabile de tip structură se poate face astfel:+**Iesire:** 
 + 
 +<​code>​ 
 +Introduceti un text: just testing 
 +Textul are 12 caractere. 
 +</​code>​ 
 + 
 +== memset() == 
 <code c> <code c>
-struct student s1 = {"​Popescu Ionel"39.25}; +void* memset(void *ptrint valsize_t num);
-struct complex c1, c2; +
-struct complex v[10];+
 </​code>​ </​code>​
  
-Pentru simplificarea declaraţiilorputem asocia unei structuri un nume de tip de date:+În zona de memorie dată de pointerul ptrsunt setate primii num octeți la valoarea dată de val. Pentru șiruri ​de caractere - în care fiecare element ocupă 1 octet - aceasta are ca rezultat înlocuirea primelor '​num'​ valori cu cea dată ca argument.  
 + 
 +Funcţia returnează şirul ptr. 
 + 
 +**Exemplu:** 
 <code c> <code c>
-typedef struct student Student; +#include <​stdio.h>​ 
-... +#include <string.h> 
-Student s1s2s3;+  
 +int main () { 
 +  char str[] = "nu prea vreau vacanta!";​ 
 +  memset(str'​-'​7); 
 +  puts(str);​ 
 +  return 0; 
 +}
 </​code>​ </​code>​
  
-Redenumirea de tip de mai sus poate fi inclusă șîn definirea structurii, caz în care putem folosi - din prima - atât ''​struct Student'' ​cât știpul de date rezultat din typedef:+**Iesire:​** 
 + 
 +<​code>​ 
 +------- vreau vacanta! 
 +</​code>​ 
 + 
 +<note important>​ 
 +Ca programatori,​ vețîntâlni adesea situații ​în care ''​memset'' ​este folosit pentru inițializarea de vectori de diverse tipuri. 
 + 
 +Atunci când scriețsau evaluați cod care face acest lucru trebuie să aveți în vedere că memset face scrierea valorii primite pe fiecare **octet** (fără a ține cont de dimensiunea reperezentării tipului ​de date). Următorul cod arată cum putem folosi memset pentru a inițializa un vector de int la 0 folosind memset, respectiv care ar fi rezultatul dacă am încerca să inițializăm vectorul cu o altă valoare:
  
 <code c> <code c>
-typedef struct student { +#include <​stdio.h>​ 
-  char nume[40]; +#include <​string.h>​
-  int an; +
-  float medie; +
-} Student;+
  
-int main() { +#define SIZE 2 
-   /Ambele declaratii de mai jos sunt valide ​*/ + 
-   struct student s1+int main(void) 
-   Student s2;+
 +    int a[SIZE], b[SIZE], i; 
 +    memset(a, 0, SIZE sizeof(int));​ 
 +    memset(b, 5, SIZE sizeof(int));​ 
 + 
 +    for(i = 0i < SIZE; i++) 
 +        printf("​%d ", a[i]); 
 + 
 +    printf("​\n"​);​ 
 + 
 +    for(i = 0; i < SIZE; i++) 
 +        printf("​%d ", b[i]); 
 + 
 +    ​return 0;
 } }
 </​code>​ </​code>​
 +Rezultatul este...
 +<​code>​
 +0 0 
 +84215045 84215045
 +</​code>​
 +rezultatul neașteptat de pe a 2-a linie provenind din faptul că fiecare octet al int-urilor a fost setat la 5, și nu valoarea întregii structuri.
  
 +Este de menționat faptul că utilizarea ''​memset''​ în astfel de situații **nu** este recomandată.
 +
 +</​note>​
 +
 +== memmove() ==
  
-Accesul la membrii unei structuri se face prin operatorul "​.":​ 
 <code c> <code c>
-s1.nume = "​Ionescu Raluca"​;+void* memmove(void *destination,​ const void *source, size_t num);
 </​code>​ </​code>​
  
-În cazul pointerilor ​la structuriaccesul ​la membri ​se poate face astfel:+Copiază un număr de num caractere de la sursă, la zona de memorie indicată de destinaţie. Copierea are loc ca şi cum ar exista un buffer intermediar,​ deci sursa si destinatia ​se pot suprapune. Funcţia nu verifică terminatorul de şir la sursă, copiază mereu num bytes, deci pentru a evita depăsirea trebuie ca dimensiunea sursei sa fie mai mare ca num. Funcţia returnează destinaţia. 
 + 
 +**Exemplu:** 
 <code c> <code c>
-Student *stud = (Student *)malloc(sizeof(Student)); +#include <​stdio.h>​ 
-(*stud).medie = 9.31+#include <​string.h>​ 
-/* altă modalitate mai simplă şi mai des folosită: */ +  
-stud->​medie = 9.31;+int main () 
 +  char str[] = "​memmove can be very useful......";​ 
 +  memmove(str + 20, str + 15, 11); 
 +  puts(str); 
 +  ​return 0; 
 +}
 </​code>​ </​code>​
  
-Atribuirile de structuri se pot face astfel:+**Iesire:** 
 + 
 +<​code>​ 
 +memmove can be very very useful. 
 +</​code>​ 
 + 
 +== memcpy() == 
 <code c> <code c>
-struct complex n1n2; +void* memcpy(void *destinationconst void *source, size_t num);
-... +
-n2 = n1;+
 </​code>​ </​code>​
  
-Prin această atribuire se realizează o copiere bit cu bit a elementelor lui n1 în n2.+Copiază un număr de num caractere din şirul sursă in şirul destinaţie. Funcţia returnează şirul destinaţie. 
 + 
 +**Exemplu:​**
  
-Alt exemplu de utilizare: După cum se vede mai jos trebuie facută diferenta când definim un tip şi cand declaram o variabila de tip struct sau typedef struct. 
 <code c> <code c>
-typedef struct { +#include <​stdio.h>​ 
-  int data; +#include <​string.h>​
-  int text; +
-} S1; // este un typedef pentru S1, functional in C si C+++
  
-struct S2 { +#define N 40
-  int data; +
-  int text; +
-}; // este un typedef pentru struct S2+
  
 +int main () {
 +  char str1[] = "​Exemplu";​
 +  char str2[N];
 +  char str3[N];
 +  memcpy(str2,​ str1, strlen(str1) + 1); // + 1 este necesar pentru a copia și terminatorul de șir
 +  memcpy(str3,​ "un sir", 7);
 +  printf("​str1:​ %s\nstr2: %s\nstr3: %s\n", str1, str2, str3);
 +  return 0;
 +}
 +</​code>​
  
-struct { +**Iesire:**
-  int data; +
-  int text; +
-} S3; +
-// este o declaratie a lui S3, variabila de tip struct nu defineste un tip +
-// spune compilatorului sa aloce memorie pentru variablia S3+
  
-typedef struct S4 { +<​code>​ 
-  int data; +str1: Exemplu 
-  int text; +str2: Exemplu 
-} S4; // este un typedef atât pentru struct S4, cât și pentru S4+str3: un sir 
 +</​code>​
  
 +== strcpy() ==
  
-int main() { +<code c> 
-  // ce se intampla la declarare variabile ​de tip S1,S2,S3 +char* strcpy(char *destination,​ const char *source); 
-  S1 mine1// este un typedef si va merge +</code> 
-  ​struct S2 mine2; ​// este un typedef si va merge + 
-  S2 mine22; ​// S2 NU este un typedef si NU va merge +Copiază şirul sursă in şirul destinaţie. Şirul destinaţie va fi suprascris. Funcţia asigură plasarea terminatorului ​de şir în şirul destinaţie după copiere. Funcţia returneaza şirul destinaţie. 
-  S3 mine3; ​// nu va merge pt ca S3 nu este un typedef+ 
-  ​struct S4 mine4// este un typedef și va merge +== strncpy() == 
-  ​S4 mine4// este un typedef și va merge + 
-   +<code c> 
-  ​// ce se intampla la utilizarea ca variabile a S1,S2,S3 +char* strncpy(char *destinationconst char *sourcesize_t num)
-  ​S1.data = 5// da eroare deoarece S1 este numai un typedef. +</code> 
-  ​struct S2.data ​5// da eroare deoarece S2 este numai un typedef. + 
-  ​S3.data = 5// merge doarece S3 e o variabila+Asemeni cu ''​strcpy()'',​ dar in loc de a fi copiată toata sursa sunt copiate doar primele ​//num// caractere. 
 + 
 +**Exemplu:​** 
 + 
 +<code c> 
 +#include <​stdio.h>​ 
 +#include <​string.h>​ 
 + 
 +#define N 40 
 + 
 +int main () { 
 +  ​char str1[] = "​Exemplu"​
 +  ​char str2[N]
 +  ​char str3[N]; 
 +  ​strcpy(str2str1); 
 +  ​strncpy(str3,​ "un sir", 2)
 +  ​str3[2] ​'​\0'​
 +  ​printf("​str1:​ %s\nstr2: %s\nstr3: %s\n", str1, str2, str3);
   return 0;   return 0;
 } }
 </​code>​ </​code>​
  
-<note>Dacă declaraţi pointeri ​la structuri, nu uitaţi să alocaţi memorie pentru aceştia înainte de a accesa câmpurile structurii. Nu uitaţsă alocaţi şi câmpurile structurii, care sunt pointeri, înainte de utilizare, dacă este cazul. De asemenea fiţi atenţi şi la modul de accesare al câmpurilor.+**Iesire:​** 
 + 
 +<code> 
 +str1: Exemplu 
 +str2: Exemplu 
 +str3: un 
 +</​code>​ 
 + 
 +== strcat() == 
 + 
 +<code c> 
 +char* strcat(char *destination,​ const char *source); 
 +</​code>​ 
 + 
 +Concatenenaza şirul sursă la şirul destinaţie. Funcţia returnează ​şirul destinaţie. 
 + 
 +<note critical>​ 
 +Șirul destinație trebuie ​să aibă suficientă memorie alocată pentru a a acomoda șirul rezultat.
 </​note>​ </​note>​
  
-=== Diferenţa dintre copierea structurilor şi copierea pointerilor ===+== strncat() ​==
  
-Pentru exemplificarea diferenţei dintre copierea structurilor şi copierea pointerilor să considerăm urmatorul exemplu: 
 <code c> <code c>
-struct exemplu ​+char* strncat(char *destination,​ const char *source, size_t num); 
-  ​int n+</​code>​ 
-  ​char *s;+ 
 +Asemeni cu ''​strcat()'',​ dar în loc de a fi concatenată toată sursa sunt concatenate **cel mult** primele //num// caractere din șirul sursa (aceasta putând fii și mai scurt). 
 + 
 +**Exemplu:​** 
 + 
 +<code c> 
 +#include <​stdio.h>​ 
 +#include <​string.h>​ 
 + 
 +#define N 80 
 + 
 +int main () 
 +  ​char str[N]
 +  ​strcpy(str, "ana "); 
 +  strcat(str, "are "); 
 +  strcat(str, "mere "); 
 +  puts(str);​ 
 +  strncat(str,​ "si pere si prune",​ 7); 
 +  puts(str);​ 
 +  return 0;
 } }
-struct exemplu s1, s2; 
-char *litere = "​abcdef";​ 
-s1.n = 5; 
-s1.s = strdup(litere);​ 
-s2 = s1; 
-s2.s[1]='​x';​ 
 </​code>​ </​code>​
  
-După atribuirea s2 = s1;, s2.s va avea o valoare identică cu s1.s. Deoarece s este un pointer (o adresă de memorie), s2.s va indica aceeaşi adresa de memorie ca şi s1.s. Deci, după modificarea celui de-al doilea caracter din s2.s, atat s2.s cât si s1.s vor fi axcdef. De obicei acest efect nu este dorit şi nu se recomandă atribuirea de structuri atunci cand acestea contin pointeri.+**Iesire:**
  
-Totuşi, putem atribui ulterior lui s2.s o altă valoare ​(o altă adresă), iar ca urmare a acestei operaţii, stringurile vor fi distincte din nou.+<​code>​ 
 +ana are mere 
 +ana are mere si pere 
 +</​code>​ 
 + 
 +== strcmp() ==
  
-Un alt caz (diferit de cel expus anterior) este cel al atribuirii aceleiaşi structuri către două variabile pointer diferite: 
 <code c> <code c>
-struct exemplu ​+int strcmp(const char *str1, const char *str2); 
-  ​int n+</​code>​ 
-  char * s;+ 
 +Compară şirul //str1// cu şirul //str2//, verificându-le caracter cu caracter. Valoarea returnată este 0 daca cele şiruri sunt identice, mai mare ca 0 daca str1 este "mai mare"​(alfabetic) şi mai mic ca 0 altfel. 
 + 
 +**Exemplu:​** 
 + 
 +<code c> 
 +#include <​stdio.h>​ 
 +#include <​string.h>​ 
 +  
 +#define N 80 
 + 
 +int main () 
 +  ​char cuv[] = "​rosu"​
 +  char cuv_citit[N];​ 
 +  do { 
 +    printf ("​Ghiceste culoarea..."​);​ 
 +    gets(cuv_citit);​ 
 +  } while (strcmp(cuv,​cuv_citit) != 0); 
 +   
 +  puts("​OK"​);​ 
 +   
 +  return 0;
 } }
-struct exemplu s1; 
-struct exemplu *p1; 
-struct exemplu *p2; 
-p1 = &s1; 
-p2 = &s2; 
 </​code>​ </​code>​
  
-În acest caz observăm că din nou p1->s şp2->s indică către acelaşşir de caractere, dar aici adresa către şirul de caractere apare memorată o singura dată; spre deosebire de cazul anteriordacă modificăm adresa din p2->s, ea se va modifica automat şi în p1->s.+În situația în care șirurile au lungimi diferite, ultima comparație se face între \0 șcaracterul de pe aceașpoziție din șirul mai lung
  
-=== Uniuni ​=== +== strchr() ​==
-Uniunile sunt asemănătoare structurilor,​ dar lor li se rezervă o zonă de memorie ce poate conţine, la momente de timp diferite, variabile de tipuri diferite. Sunt utilizate pentru a economisi memoria (se refoloseşte aceeaşi zonă de memorie pentru a stoca mai multe variabile).+
  
-Uniunile se pot declara astfel: 
 <code c> <code c>
-union numere { +char* strchr(const char *str, int character)
-  ​int i+</code>
-  float f; +
-  double v; +
-};              /* se poate utiliza si typedef... */+
  
-union numere u1u2;+Caută caracterul //​character//​ în şirul //str// şi returnează un pointer la //prima// sa apariţie sau ''​NULL''​ dacă acesta nu a fost găsit.. 
 + 
 +== strrchr()== 
 + 
 +<code c> 
 +char* strrchr(const char *strint character);
 </​code>​ </​code>​
  
-Când scriem ceva într-o uniune (de exemplu când facem o atribuire de genul u1.f = 7.4), ceea ce citim apoi trebuie să fie de acelaşi tip, altfel vom obţine rezultate eronate (adică trebuie să utilizam u1.f, nu u1.v sau u1.i). Programatorul trebuie să ţină evidenţa tipului variabilei care este memorată în uniune în momentul curent pentru a evita astfel de greşeli. Operaţiile care se pot face cu structuri se pot face şi cu uniuni; o structura poate conţine uniuni şi o uniune poate conţine structuri.+Caută caracterul //​character//​ în şirul //​str// ​şi returnează un pointer la //ultima// sa apariţie sau ''​NULL''​ dacă acesta ​nu există în șir. 
 + 
 +== strstr() ==
  
-Exemplu: 
 <code c> <code c>
-#include <​stdio.h>​ +char* strstr(const char *str1, const char *str2); 
-#​include ​<stdlib.h>+</code>
  
-typedef union { +Caută şirul //str2// în şirul //str1// şi //​returnează un pointer la prima sa apariţie//,​ sau //''​NULL''//​ dacă nu a fost găsit.
-  int Wind_Chill;​ +
-  char Heat_Index;​ +
-} Condition;+
  
-typedef struct { +== strdup() ==
-  float temp; +
-  Condition feels_like;​ +
-} Temperature;​+
  
-int main() {+<code c> 
 +char* strdup(const char *str)
 +</​code>​
  
-  Temperature *tmp; +Realizează un duplicat al şirului //str//pe care îl şi returneazăSpațiul de memorie necesar copiei este alocată dinamicfiind responsabilitatea noastră să o dealocăm ​(așa cum am s-a prezentat laboratorul anterior).
-  tmp = (Temperature *)malloc(sizeof(Temperature));​ +
-     +
-  printf("​\nAddress of Temperature = %u"tmp); +
-  printf("​\nAddress of temp = %u, feels_like = %u",  +
-                 &​(*tmp).temp,&(*tmp).feels_like);​ +
-  printf("​\nWind_Chill = %u, Heat_Index= %u\n",  +
-                 &​((*tmp).feels_like).Wind_Chill,​ +
-                 &​((*tmp).feels_like).Heat_Index);​+
  
 +**Exemplu:​**
 +
 +<code c>
 +#include <​stdio.h>​
 +#include <​string.h>​
 +
 +#define N 80
 + 
 +int main () {
 +  char str[N] = "​salut",​ *d;
 + 
 +  d = strdup(str);​
 +  if(d == NULL) {
 +      printf("​Eroare!\n"​);​
 +      return -1;
 +  }
 +  ​
 +  puts(d);
 +  free(d);
 +  ​
   return 0;   return 0;
 } }
 </​code>​ </​code>​
  
-La rulare ​va afişa:+<​note>​ 
 +''​strdup(..)'' ​va aloca întotdeuna ''​strlen() + 1''​ octeți pentru destinație,​ indiferent de dimensiunea memoriei alocate pentru sursă. 
 +</​note>​ 
 + 
 +== strtok() == 
 <code c> <code c>
-Address of Temperature = 165496 +char* strtok(char *strconst char *delimitators);​
-Address of temp = 165496feels_like = 165500 +
-Wind_Chill = 165500, Heat_Index= 16550+
 </​code>​ </​code>​
  
-===== Exercitii laborator CB/CD =====+Funcţia are rolul de a împarţi şirul ​//str// în tokens(subşiruri separate de orice caracter aflat în lista de delimitatori),​ prin apelarea ei succesivă.
  
-Codul sursa se gaseste [[http://swarm.cs.pub.ro/~gmuraru/PC/lab10.c|aici]] +La primul apel, parametrul ​//str// trebuie sa fie un şir de caractere, ce urmează a fi împartitApelurile urmatoare, vor avea în loc de //str//, ''​NULL''​ conţinuând împarţirea aceluiaşi şir.
-Primul exercitiu presupune modificarea/adaugarea de instructiuni unui cod existent pentru a realiza anumite lucruri. In momentul actual programul numara cate persoane au acelasi prenume.+
  
-Cerinte: +Funcţia va returna la fiecare apel un token(un subsir), ignorând caracterele cu rol de separator aflate în şirul de delimitatori. O dată terminat şirul, funcţia va returna ''​NULL''​.
-  *Sa se afiseze cate persoane s-au nascut in acelasi an +
-  *Sa se sorteze persoanele dupa nume+
  
-**Următoarele două probleme vă vor fi date de asistent în cadrul laboratorului.** +<note important
-<hidden+Implementarea curentă din ''<​string.h>''​ nu permite folosirea ''​strtok()''​ în paralel pe mai mult de un şir
-Link direct către lista completă de probleme: [[https://​docs.google.com/​document/​d/​10K_4WKI-66ikvtzq2NNCMJZPPZ3YsDQv-sv4-r1DGRU/​edit|aici]] +</note>
-</hidden>+
  
 +**Exemplu:​**
  
-==== Exerciţii de laborator ====+<code c> 
 +#include <​stdio.h>​ 
 +#include <​string.h>​ 
 +  
 +int main () { 
 +  char str[] "- Uite, asta e un sir.";​ 
 +  char *p;   
 +  p strtok(str, " ,​.-"​);​ 
 +  /* separa sirul in "​tokeni"​ si afiseaza-i pe linii separate. */ 
 +  while (p !NULL) { 
 +    printf("​%s\n",​ p); 
 +    p strtok(NULL,​ " ,​.-"​);​ 
 +  } 
 +   
 +  return 0; 
 +
 +</​code>​
  
-  - [2p] O matrice rară (cu circa 90% din elemente 0) este păstrată economic sub forma unei structuri, care conţine următoarele câmpuri: +**Iesire:**
-      ​int L,C - numărul de linii/​coloane al matricei rare +
-      ​int N - numărul de elemente nenule +
-      * int LIN[] - vectorul ce păstrează liniile în care se află elemente nenule +
-      * int COL[] - vectorul ce păstrează coloanele în care se află elemente nenule +
-      * float X[] - vectorul ce păstrează elementele nenule +
-  - Să se definească funcţii pentru: +
-      * [1p] citirea unei matrice rare +
-      * [1p] afişarea unei matrice rare (ca o matrice, cu tot cu zerouri) +
-      * [2p] adunarea a două matrice rare.  +
-      * **Observatii** :  +
-      * Vectorii LIN, COL, X vor avea fiecare cate N elemente. +
-      * Elementul nenul cu valoare X[index] se afla pe linia LIN[index] si coloana COL[index]. +
-      * Elementele vor fi citite in ordinea crescatoare a liniilor, iar elementele de pe aceeasi linie in ordinea crescatoare a coloanelor. +
-  - Un polinom este reprezentat printr-o structură care conţine gradul polinomului şi tabloul coeficientilor. Să se definească funcţii pentru: +
-      * [1p] citirea unui polinom +
-      ​[1p] afişarea unui polinom +
-      ​[2p] adunarea/​scăderea a două polinoame+
  
-==== Bonus ==== +<​code>​ 
-1. [3p] În registrul ''​Uni-Struct'',​ fiecărui elev îi corespunde o înregistrare care reține: +Uite 
-  * numele acestuia (maxim 50 de caractere), +asta 
-  * clasa în care acesta se află (o valoare de tipul ''​unsigned int''​),​ +e 
-  * rezultatul obținut la materia cea mai apropaiata (ca semnificație) de programare. +un 
-   +sir 
-Tipul rezultatului diferă în funcție de clasa în care elevul se află, astfel: +</​code>​
-    * elevii din clasele primare (1-4), primesc ​un calificativ (FB, B, S, I) reprezentat ca un șir maxim 9 caractere; +
-    * elevii din toate celelalte clase primesc note, care vor fi reținute cu ajutorul unui câmp de tip ''​float''​. +
-  +
-Scrieți un program care citește de la tastatură astfel de înregistrări,​ până la inserarea șirului de caractere ''"​stop"''​ în locul numelui unuia dintre elevi, apoi afișează toți studenții din registru, alături de toate informațiile despre ei, în ordinea lexicografică a numelor cu care sunt înregistrați.+
  
-Folosiți un vector de structuri pentru a stoca toate informațiile despre elevi. Faceți eficient reținerea unei singure valori pentru rezultatul parcurgerii materiei în cadrul structurii.+===== Exercitii laborator CB/CD =====
  
-<​file ​bonus.in> +Primul exercitiu presupune modificarea/​adaugarea de instructiuni unui cod existent pentru a realiza anumite lucruri. In momentul actual programul numara cate cuvinte doar cu litere mici se gasesc intr-un sir de caractere.
-Ionut Popescu +
-10 +
-7.4 +
-Maria Almasan +
-+
-FB +
-Alex Grigorescu +
-12 +
-10 +
-stop +
-</​file>​+
  
-<file - bonus.out+<code c ex.c
-Alex Grigorescu +#include <​stdio.h> ​                                                                                                                                                                                                   
-12 +#include <​string.h> ​                                                                                                                                                                                                 ​ 
-10 +#include <​ctype.h>​ 
-Ionut Popescu +#include <​stdlib.h> ​                                                                                                                                                                                                   
-10 +                                                                                                                                                                                                                     ​ 
-7.4 +#define SEPARATORS " ,." ​                                                                                                                                                                                             
-Maria Almasan +                                                                                                                                                                                                                      
-3 +int count_lowercases_words(char *str)                                                                                                                                                                                      
-FB +{                                                                                                                                                                                                                     
-</file>+        char *tmp_str = strdup(str); ​                                                                                                                                                                                 
 +        unsigned int count = 0;                                                                                                                                                                                       
 +                                                                                                                                                                                                                      
 +        if (tmp_str == NULL) {                                                                                                                                                                                        
 +                printf("​Eroare la alocare\n"​); ​                                                                                                                                                                       
 +                return -1;                                                                                                                                                                                            
 +        }                                                                                                                                                                                                             
 +                                                                                                                                                                                                                      
 +        char *word = strtok(tmp_str,​ SEPARATORS); ​                                                                                                                                                                    
 +        while (word) {                                                                                                                                                                                                
 +            unsigned int i;                                                                                                                                                                                           
 +                                                                                                                                                                                                                      
 +            for (i = 0; i < strlen(word);​ i++) {                                                                                                                                                                      
 +                    if (isupper(word[i])) {                                                                                                                                                                           
 +                            break; ​                                                                                                                                                                                   
 +                    }                                                                                                                                                                                                 
 +            }                                                                                                                                                                                                         
 +                                                                                                                                                                                                                      
 +            if (i == strlen(word)) {                                                                                                                                                                                  
 +                count++; ​                                                                                                                                                                                             
 +            }        
 +                                                                                                                                                                                                                                                                                                                                                                                                            
 +            word = strtok(NULL,​ SEPARATORS); ​                                                                                                                                                                         
 +        }                                                                                                                                                                                                             
 +         
 +        free(tmp_str); ​                                                                                                                                                                                                             
 +        return count; ​                                                                                                                                                                                                
 +}                                                                                                                                                                                                                     
 +                                                                                                                                                                                                                      
 +int main(void) ​                                                                                                                                                                                                       
 +{        
 +        char sentence[] = "Ana are mere, pere si gutui. Gigel nu are nimic."; ​                                                                                                                                        
 +                                                                                                                                                                                                                      
 +        printf("​%d\n",​ count_lowercases_words(sentence)); ​                                                                                                                                                                                       
 +                                                                                                                                                                                                                     ​ 
 +        ​return 0;                                                                                                                                                                                                    ​ 
 +} 
 +</code>
  
 +Cerinte:
 +  *Sa se numere cate cuvinte au cel putin un caracter din sirul “api”.
 +  *Sa se realizeze o functie care intoarce un sir de caractere compus din cuvintele care incep cu litera mare.
  
  
 +**Următoarele două probleme vă vor fi date de asistent în cadrul laboratorului.**
  
 +[[https://​drive.google.com/​drive/​folders/​1qB6EZLGVubKbuTXMtMue06egH_8fo25M|Checker laborator 10]]
 +
 +[[ https://​ocw.cs.pub.ro/​courses/​programare/​checker | Tutorial folosire checker laborator ]]
 +
 +<​hidden>​
 +Link direct către lista completă de probleme: [[https://​docs.google.com/​document/​d/​10TkUC2MEXGmayvim563MP27SxvIvrB97Lk1cX492c1k/​edit|aici]]
 +</​hidden>​
 +
 +==== Exercitii de laborator ====
 +
 +  - [2p] Să se citească o succesiune de cuvinte. Să se creeze o funcţie: ''​void ordCresc(char *vectorschar[],​ int n);''​ care să ordoneze cuvintele crescător
 +      * după lungimea acestora.
 +      * alfabetic
 +  - [2p] Să se determine dacă o propozitie este palindromă. O propozitie este palindromă daca citită de la prima literă pană la ultima are aceeasi succesiune ca citită de la ultima literă până la prima. Nu conteaza dacă sunt litere mici sau mari.\\ ​ //​Exemplu//:​ ele fac cafele
 +  - [1p] Folosind funcţia strtok, citiţi un şir de caractere şi afişaţi pe ecran cuvintele sale constituente.
 +  - [2p] Folosind funcţia strtok, citiţi un şir de caractere, apoi un cuvânt şi afişaţi pe ecran numărul de apariţii al cuvântului în şir.
 +  - [3p] Folosind funcţiile din ''<​string.h>''​ înlocuiţi într-un text dat o secventă de caractere cu altă secvenţă de caractere, date la intrare.
 +
 +=== Bonus ===
 +  - [3p] Se dă N de la tastatură. Citiţi pentru fiecare N numele, prenumele şi vârsta elevului respectiv, alocând întreaga memorie în mod dinamic pentru fiecare elev nou (lungimea numelui şi a prenumelui se consideră a fi 20 de caractere, iar vârsta se consideră între 0 şi 100). Afişaţi pe ecran, în funcţie de opţiunea selectata, lista citită de la tastatură, ordonată în funcţie de nume, prenume, respectiv vârsta.
  
 ==== Referinţe ==== ==== Referinţe ====
-  * [[http://​crasseux.com/​books/​ctutorial//​Data-structures.html#​Data%20structures|The GNU Programming Tools - Data structure]] 
-  * [[http://​publications.gbdirect.co.uk/​c_book/​chapter6/​unions.html|The C Book - Unions]] 
  
 +  * [[http://​en.wikipedia.org/​wiki/​String_(computer_science)|Wikipedia - String(Computer science)]]
 +  * [[http://​en.wikipedia.org/​wiki/​String.h|Wikipedia - C string handling]]
 +
 +
 +[[https://​drive.google.com/​open?​id=1n-X0kssdqDXF9i73VfMxAb7GZP7CzhT3|Probleme laborator 14-16]]
programare/laboratoare/lab10.1506642574.txt.gz · Last modified: 2017/09/29 02:49 by darius.neatu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0