Differences

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

Link to this comparison view

programare:laboratoare:lab10 [2016/12/11 19:39]
george.muraru [Noţiuni teoretice]
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:​**  +
-  * [[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>​
  
-Exemple:+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 genera, cel 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 student ​+#include <​stdio.h>​ 
-  char nume[40]; +#include <​string.h>​ 
-  int an+ 
-  float medie+#define N 30 
-};+  
 +int main () 
 +   ​char str[N], c
 +   ​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>​
  
-Variabilele declarate in interiorul structurii ​se numesc "​campurile"​ structurii: +

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. 
-  *nume; + 
-  *an; +  * ''​gets(zona)''​ -– citeşte de la terminalul standard un şir de caractere terminat cu linie noua (enter). 
-  *medie.+      * 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 contrarParametrii 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() ==
  
 <code c> <code c>
-struct complex { /pentru memorarea unui număr complex cu dublă precizie */ +size_t strlen(const char *str);
-  double re; +
-  double im; +
-};+
 </​code>​ </​code>​
  
-Declararea ​şi iniţializarea unor variabile ​de tip structură se poate face astfel:+Returneaza lungimea unui şir dat ca parametru. (numarul ​de caractere până la întalnirea terminatorului de şir: \0) 
 + 
 +**Exemplu:** 
 <code c> <code c>
-struct student s1 = {"Popescu Ionel", 3, 9.25}+#include <​stdio.h>​ 
-struct complex c1c2+#include <​string.h>​ 
-struct complex v[10];+ 
 +#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>​
  
-Pentru simplificarea declaraţiilor,​ putem asocia unei structuri ​un nume de tip de date:+**Iesire:​** 
 + 
 +<​code>​ 
 +Introduceti ​un textjust testing 
 +Textul are 12 caractere. 
 +</​code>​ 
 + 
 +== memset() == 
 <code c> <code c>
-typedef struct student Student; +void* memset(void *ptrint valsize_t num);
-... +
-Student s1s2s3;+
 </​code>​ </​code>​
  
-Accesul ​la membrii unei structuri se face prin operatorul ".":+În zona de memorie dată de pointerul ptr, sunt setate primii num octeți ​la valoarea dată de valPentru ș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>
-s1.nume = "Ionescu Raluca";+#include <stdio.h> 
 +#include <​string.h>​ 
 +  
 +int main () { 
 +  char str[] = "nu prea vreau vacanta!"; 
 +  memset(str, '​-',​ 7); 
 +  puts(str);​ 
 +  return 0; 
 +}
 </​code>​ </​code>​
  
-În cazul pointerilor la structuriaccesul la membri se poate face astfel:+**Iesire:​** 
 + 
 +<​code>​ 
 +------- vreau vacanta! 
 +</​code>​ 
 + 
 +<note important>​ 
 +Ca programatoriveți întâlni adesea situații în care ''​memset''​ este folosit pentru inițializarea de vectori de diverse tipuri. 
 + 
 +Atunci când scrieți 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>
-Student *stud = (Student *)malloc(sizeof(Student)); +#include <​stdio.h>​ 
-(*stud).medie ​9.31+#include <​string.h>​ 
-/* altă modalitate mai simplă şmai des folosită: */ + 
-stud->​medie ​9.31;+#define SIZE 2 
 + 
 +int main(void) 
 +
 +    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 0i < 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() ==
  
-Atribuirile de structuri se pot face astfel: 
 <code c> <code c>
-struct complex n1n2; +void* memmove(void *destinationconst void *source, size_t num);
-... +
-n2 = n1;+
 </​code>​ </​code>​
  
-Prin această atribuire ​se realizează o copiere bit cu bit elementelor lui n1 în n2.+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 ​evita depăsirea trebuie ca dimensiunea sursei sa fie mai mare ca num. Funcţia returnează destinaţia. 
 + 
 +**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+++int main () 
 +  ​char str[] = "​memmove can be very useful......"​
 +  ​memmove(str + 20, str + 15, 11)
 +  ​puts(str); 
 +  return 0; 
 +
 +</code>
  
-struct S2 { +**Iesire:**
-  int data; +
-  int text; +
-}; // este un typedef pentru S2, functional numai in C+++
  
-struct { +<​code>​ 
-  int data; +memmove can be very very useful. 
-  int text; +</code>
-} S3; +
-// este o declaratie a lui S3, variabila de tip struct nu defineste un tip +
-/spune compilatorului sa aloce memorie pentru variablia S3+
  
-int main() { +== memcpy() == 
-  // ce se intampla la declarare variabile de tip S1,S2,S3 + 
-  S1 mine1; // este un typedef si va merge +<code c> 
-  ​S2 mine2// este un typedef si va merge +void* memcpy(void *destinationconst void *sourcesize_t num); 
-  ​S3 mine3// nu va merge pt ca S3 nu este un typedef. +</code> 
-  ​// ce se intampla la utilizare variabile S1,S2,s3 + 
-  ​S1.data = 5; // da eroare deoarece S1 este numai un typedef. +Copiază ​un număr de num caractere din şirul sursă in şirul destinaţie. Funcţia returnează şirul destinaţie. 
-  ​S2.data = 5; // da eroare deoarece S2 este numai un typedef. + 
-  ​S3.data = 5// merge doarece S3 e o variabila+**Exemplu:​** 
 + 
 +<code c> 
 +#include <​stdio.h>​ 
 +#include <​string.h>​ 
 + 
 +#define N 40 
 + 
 +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;   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ţi să alocaţşi câmpurile structuriicare sunt pointeriînainte ​de utilizaredacă este cazulDe asemenea fiţi atenţi ​şi la modul de accesare al câmpurilor.+**Iesire:​** 
 + 
 +<code> 
 +str1: Exemplu 
 +str2: Exemplu 
 +str3: un sir 
 +</​code>​ 
 + 
 +== strcpy() == 
 + 
 +<code c> 
 +char* strcpy(char *destination,​ const char *source); 
 +</​code>​ 
 + 
 +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. 
 + 
 +== strncpy() == 
 + 
 +<code c> 
 +char* strncpy(char *destinationconst char *sourcesize_t num); 
 +</​code>​ 
 + 
 +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; 
 +
 +</​code>​ 
 + 
 +**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ţieFuncţ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 *str, const char *delimitators);​ 
-Address of temp 165496feels_like ​165500 +</​code>​ 
-Wind_Chill ​165500Heat_Index16550+ 
 +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ă. 
 + 
 +La primul apel, parametrul //str// trebuie sa fie un şir de caractere, ce urmează a fi împartit. Apelurile urmatoare, vor avea în loc de //str//, ''​NULL''​ conţinuând împarţirea aceluiaşi şir. 
 + 
 +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''​. 
 + 
 +<note important>​ 
 +Implementarea curentă din ''<​string.h>''​ nu permite folosirea ''​strtok()''​ în paralel pe mai mult de un şir. 
 +</​note>​ 
 + 
 +**Exemplu:​** 
 + 
 +<code c> 
 +#include <​stdio.h>​ 
 +#include <​string.h>​ 
 +  
 +int main () { 
 +  char str[] "- Uiteasta 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>​ 
 + 
 +**Iesire:​** 
 + 
 +<​code>​ 
 +Uite 
 +asta 
 +
 +un 
 +sir
 </​code>​ </​code>​
  
 ===== Exercitii laborator CB/CD ===== ===== Exercitii laborator CB/CD =====
  
-Codul sursa se gaseste [[http://​swarm.cs.pub.ro/​~gmuraru/​PC/​lab10.c|aici]] +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. 
-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.+ 
 +<code c ex.c> 
 +#include <​stdio.h> ​                                                                                                                                                                                                   
 +#include <​string.h> ​                                                                                                                                                                                                  
 +#include <​ctype.h>​ 
 +#include <​stdlib.h> ​                                                                                                                                                                                                   
 +                                                                                                                                                                                                                      
 +#define SEPARATORS " ,​." ​                                                                                                                                                                                             
 +                                                                                                                                                                                                                      
 +int count_lowercases_words(char *str)                                                                                                                                                                                      
 +{                                                                                                                                                                                                                     
 +        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: Cerinte:
-  *Sa se afiseze ​cate persoane s-au nascut in acelasi an +  *Sa se numere ​cate cuvinte ​au cel putin un caracter din sirul “api”. 
-  *Sa se sorteze persoanele dupa nume+  *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.** **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>​ <​hidden>​
-Link direct către lista completă de probleme: [[https://​docs.google.com/​document/​d/​10K_4WKI-66ikvtzq2NNCMJZPPZ3YsDQv-sv4-r1DGRU/​edit|aici]]+Link direct către lista completă de probleme: [[https://​docs.google.com/​document/​d/​10TkUC2MEXGmayvim563MP27SxvIvrB97Lk1cX492c1k/​edit|aici]]
 </​hidden>​ </​hidden>​
  
 +==== Exercitii de laborator ====
  
-==== Exerciţii 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.
  
-  ​- [2pO matrice rară (cu circa 90% din elemente 0) este păstrată economic sub forma unei structuri, care conţine următoarele câmpuri: +=== Bonus === 
-      * int L,C - numărul de linii/​coloane al matricei rare +  ​- [3pSe dă N de la tastatură. Citiţpentru ​fiecare N numele, prenumele ​şi vârsta elevului respectiv, alocând întreaga memorie în mod dinamic pentru fiecare elev nou (lungimea numelui şi prenumelui se consideră 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.
-      * int - 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 ​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 coeficientilorSă se definească ​funcţii pentru: +
-      * [1p] citirea unui polinom +
-      * [1p] afişarea unui polinom +
-      * [2p] adunarea/scăderea a două polinoame +
- +
-==== Bonus ==== +
-  - [3p] Considerand reprezentarea unui polinom conform structurii de mai sussă se definească o funcţie ​pentru înmulţirea a două polinoame+
  
 ==== 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.1481477986.txt.gz · Last modified: 2016/12/11 19:39 by george.muraru
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