Sunteți pe pagina 1din 20

9/5/2018

Programarea Calculatoarelor si CUPRINS


Limbaje de Programare • TRATAREA ERORILOR - stderr şi exit

CURS 11 • CITIREA ŞI SCRIEREA LINIILOR


• FUNCŢII DIVERSE
 Operaţii cu şiruri de caractere
- suport de curs -  Testarea tipului şi conversia caracterelor
 ungetc
 Executarea comenzilor
 Funcţii matematice
Tratarea erorilor. Citirea şi scrierea  Generarea unui număr aleatoriu
liniilor. Funcţii diverse • HEADERELE stdlib.h, assert.h, time.h
• Revizuiri ale C-ului standard
21:38 PCLP CURS 11 2

Tratarea erorilor - stderr şi exit


• Tratarea erorilor în programul cat nu este una
ideală.
• Problema este că dacă unul dintre fişiere nu poate fi
accesat dintr-un anumit motiv,
 diagnosticul este tipărit concatenat la sfârşitul
fişierului de ieşire.
TRATAREA ERORILOR - stderr ŞI • Acest lucru ar putea fi acceptabil dacă datele de ieşire
exit ar fi trimise către un ecran, pentru că nu le vedem și deci
nu știm că a fost o eroare
 dar nu şi dacă acestea sunt transferate unui fişier
 sau unui alt program printr-un canal de transfer.
21:38 PCLP CURS 11 4

Tratarea erorilor - stderr şi exit Tratarea erorilor - stderr şi exit


• Pentru a oferi o soluţie mai bună la această • Să modificăm programul cat
situaţie,  astfel încât să scrie mesajele de eroare la ieşirea
 un al doilea flux de ieşire, numit stderr, standard pentru erori.
 este ataşat unui program #include <stdio.h>
 în acelaşi mod în care sunt ataşate şi stdin şi /* cat: concateneaza fisiere, versiunea 2 */
stdout. main(int argc, char *argv[]){
FILE *pf;
• Datele de ieşire scrise în stderr apar în mod
void copiazafisier(FILE *, FILE*)
normal pe ecran char *prog : argv[0]; /* numele programului
 chiar dacă ieşirea standard este redirecţionată. pentru cazul cand apar erori*/
21:38 PCLP CURS 11 5 21:38 PCLP CURS 11 6

PCLP Curs 11 1
9/5/2018

if (argc == 1 ) /* fara argumente; copiaza intrarea standard */ • Programul semnalează erorile în două moduri.
copiazafisier(stdin, stdout);
else
while (--argc > 0)
1. În primul rând, diagnosticul produs de funcţia
if ((pf = fopen(*++argv, ”r")) == NULL){ fprintf este trimis către stderr,
fprintf(stderr, "%s: nu se poate deschide %s\n",prog, *argv);  deci îşi găseşte drumul către ecran
exit(l);
}else {  în loc de a dispărea
copiazafisier(pf, stdout);  în lungul unui canal de transfer
fclose(pf);  sau într-un fişier de ieşire.
}
if (ferror(stdout)){ • Am inclus numele programului, din argv[0], în mesaj
fprintf(stderr, "%s: eroare la scrierea in stdout\n", prog);
exit(2);  astfel încât dacă acest program este folosit împreună cu
} altele,
exit(0);
}  să se poată identifica sursa unei eventuale erori.
21:38 PCLP CURS 11 7 21:38 PCLP CURS 11 8

2. În al doilea rând, programul foloseşte funcţia • În mod convenţional, o valoare returnată


exit din biblioteca standard,
 egală cu zero semnalează că
 care încheie execuţia unui program atunci când  totul este bine;
este apelată.
 valorile diferite de zero semnalează de obicei
• Argumentul funcţiei exit este disponibil  situaţii anormale.
oricărui proces care l-a apelat pe cel curent,
 astfel încât succesul sau eşecul programului • Funcţia exit apelează funcţia fclose pentru
fiecare fişier de ieşire deschis,
 să poată fi testat de un alt program
 cu scopul de a goli bufferele de orice date de
 care îl foloseşte pe cel curent ca pe un subproces.
ieşire.
21:38 PCLP CURS 11 9 21:38 PCLP CURS 11 10

• În interiorul funcţiei main, • Deşi erorile la scriere sunt rare, acestea apar totuşi
return expr  de exemplu, când un disc este plin,
 este echivalent cu  în consecinţă un program demonstrativ ar trebui să
exit(expr) verifice şi acest lucru.

• exit prezintă avantajul că poate fi apelată din alte • Funcţia


funcţii şi feof (FILE *)
 acele apeluri către ea pot fi găsite cu un program de
 este asemănătoare funcţiei ferror;
căutare a şablonului cum sunt cele din Cursul 6.
 returnează o valoare diferită de zero
• Funcţia ferror returnează o valoare diferită de  dacă a fost întâlnit sfârşitul fişierului respectiv.
zero dacă a apărut o eroare în fluxul pf
int ferror(FILE *pf) int feof(FILE *pf)
21:38 PCLP CURS 11 11 21:38 PCLP CURS 11 12

PCLP Curs 11 2
9/5/2018

• În general nu ne-am preocupat de starea de la


ieşirea din micile noastre programe
demonstrative,
 dar orice program riguros ar trebui să aibă grijă să
returneze valori de stare logice, utile.

CITIREA ŞI SCRIEREA LINIILOR

21:38 PCLP CURS 11 13

Citirea şi scrierea liniilor Citirea şi scrierea liniilor


• Biblioteca standard furnizează o rutină de citire fgets • Linia rezultată se termină cu '\0 '
 care este asemănătoare funcţiei getline pe care am • De obicei fgets returnează linie
folosit-o în cursurile anterioare:  în cazul în care se ajunge la sfârşitul fişierului
char *fgets(char *linie, int maxlinie, FILE *pf)  sau dacă are loc o eroare,
 returnează NULL.
• fgets citeşte următoarea linie de intrare
• Funcţia noastră getline returnează lungimea liniei
 inclusiv caracterul linie nouă
 aceasta fiind o valoare mai utilă
 din fişierul fp în tabloul de caractere linie  zero se interpretează prin faptul că s-a ajuns la
 vor fi citite cel mult maxlinie - 1 caractere. sfârşitul fişierului
21:38 PCLP CURS 11 15 21:38 PCLP CURS 11 16

Citirea şi scrierea liniilor Citirea şi scrierea liniilor


• În ceea ce priveşte ieşirea, funcţia fputs scrie un • Funcţiile de bibliotecă gets şi puts
şir  sunt similare funcţiilor fgets şi fputs,
 care nu trebuie să conţină un caracter linie nouă  dar lucrează cu stdin şi stdout.
 într-un fişier:
int fputs(char *line, FILE *fp) • Funcţia gets şterge caracterul terminal '\n'

• fputs returnează • Funcţia puts introduce caracterul terminal '\n’


 EOF dacă apare o eroare şi
 zero în caz contrar.
21:38 PCLP CURS 11 17 21:38 PCLP CURS 11 18

PCLP Curs 11 3
9/5/2018

Citirea şi scrierea liniilor


• Este uşor să implementăm funcţia noastră getline
 cu ajutorul funcţiei fgets:

/* preialinie: citeste o linie, returneaza lungimea */


int getline(char *linie, int max)
{
if (fgets(linie, max, stdin) == NULL)
return 0; FUNCŢII DIVERSE
else
return strlen(linie);
}
21:38 PCLP CURS 11 19

Funcţii diverse
• Biblioteca standard pune la dispoziţie o gamă
largă şi variată de funcţii.

• Această secţiune este o trecere în revistă a celor


mai utile.

OPERAŢII CU ŞIRURI DE CARACTERE

21:38 PCLP CURS 11 21

Operaţii cu şiruri de caractere Operaţii cu şiruri de caractere


strcat(s,t) concatenează t la sfârşitul lui s
• Am menţionat deja funcţiile pentru lucrul cu şiruri
de caractere: strncat(s,t,n) concatenează n caractere ale
lui t la sfârşitul lui s
 strlen, strcpy, strcat şi strcmp,
 care se găsesc în <string.h>. strcmp(s,t) returnează o valoare negativă,
zero sau pozitivă pentru s<t,
s==t, respectiv s>t
• În funcţiile care urmează,
 variabilele s şi t sunt de tipul char * strncmp(s,t,n) la fel ca şi la strcmp, dar
numai pentru primele n
 variabilele c şi n aparţin tipului int
caractere din t
21:38 PCLP CURS 11 23 21:38 PCLP CURS 11 24

PCLP Curs 11 4
9/5/2018

Operaţii cu şiruri de caractere Operaţii cu şiruri de caractere


strcpy(s,t) copiază t în s strrchr(s,c) returnează pointer spre
ultima apariţie a lui c in s,
strncpy(s,t,n) copiază cel mult n caractere sau NULL dacă nu apare
din t în s

strlen(s) returnează lungimea lui s

strchr(s,c) returnează un pointer spre


prima apariţie a lui c în s, sau
NULL dacă nu apare
21:38 PCLP CURS 11 25 21:38 PCLP CURS 11 26

Testarea tipului şi conversia caracterelor


• Mai multe funcţii din <ctype.h> efectuează
asupra caracterelor
 teste şi
 conversii

• În cele ce urmează, c este un int


 care poate fi reprezentat ca
TESTAREA TIPULUI ŞI CONVERSIA  un unsigned char
CARACTERELOR  sau ca EOF.

• Funcţiile returnează valori de tipul int.


21:38 PCLP CURS 11 28

Testarea tipului şi conversia caracterelor Testarea tipului şi conversia caracterelor


isalpha(c) valoare diferită de zero dacă c este
literă, 0 în caz contrar isalnum(c) valoare diferită de zero dacă se
îndeplineşte isalpha(c) sau
isupper(c) valoare diferită de zero dacă c este isdigit(c), 0 în caz contrar
majusculă, 0 în caz contrar

islower(c) valoare diferită de zero dacă c este isspace(c) valoare diferită de zero dacă c este
literă mică, 0 în caz contrar spaţiu, tab, rând nou, retur de car,
salt la pagină nouă la imprimantă,
isdigit(c) valoare diferită de zero dacă c este tab vertical
cifră, 0 în caz contrar
21:38 PCLP CURS 11 29 21:38 PCLP CURS 11 30

PCLP Curs 11 5
9/5/2018

Testarea tipului şi conversia caracterelor

toupper(c) returnează c convertit în majusculă

tolower(c) returnează c convertit în minusculă

ungetc

21:38 PCLP CURS 11 31

ungetc ungetc
• Biblioteca standard furnizează o versiune mai • Nu se garantează decât
restrânsă a funcţiei ungetch  reintroducerea unui singur caracter în fiecare
 decât cea pe care am scris-o noi în Cursul 6 fişier.
 aceasta se numeşte ungetc
• Funcţia ungetc poate fi folosită cu oricare dintre
int ungetc(int c, FILE *pf) funcţiile de citire:
 scanf
 reintroduce caracterul c în fişierul pf şi returnează
 getc
 fie caracterul c,
 getchar
 fie EOF în caz de eroare.
21:38 PCLP CURS 11 33 21:38 PCLP CURS 11 34

Executarea comenzilor
• Funcţia
int system(const char *s)
 execută comanda conţinută în şirul de caractere s,
 după care reia execuţia programului curent din
punctul în care fusese oprită.
EXECUTAREA COMENZILOR
• Conţinutul şirului s depinde foarte mult de
sistemul de operare de pe calculator.

21:38 PCLP CURS 11 36

PCLP Curs 11 6
9/5/2018

Executarea comenzilor #include <stdio.h>


int main()
{
system(“date“);
int i = 12;
 are ca efect executarea comenzii date;
 acesta afişează data calendaristică la ieşirea printf("testare system %d \n\n", i);
standard şi system("date");
 cere introducerea unei noi date calendaristice. printf("\n testare system %d\n", i);

return 0;
}
21:38 PCLP CURS 11 37 21:38 PCLP CURS 11 38

Executarea comenzilor #include <stdio.h>


#include <stdlib.h>
int main(){
• Funcţia system returnează o valoare de stare int i = 12;
întreagă în urma comenzii executate, printf("testare system %d \n\n", i);
printf("Este procesorul de comenzi disponibil?\n\n");
 valoare care este dependentă de sistem. if (system(NULL)){
printf("Procesorul de comenzi este disponibil!\n\n");
}else{
printf("Procesorul de comenzi NU este disponibil!\n\n");
exit(1);
}
i = system("date");
printf("\n Valoarea returnata de functia system = %d\n", i);
return 0;
}
21:38 PCLP CURS 11 39 21:38 PCLP CURS 11 40

FUNCŢII MATEMATICE

21:38 PCLP CURS 11 41

PCLP Curs 11 7
9/5/2018

Funcţii matematice Funcţii matematice

• Există peste douăzeci de funcţii matematice sin(x) sinus de x, x în radiani


declarate în <math.h>
cos(x) cosinus de x, x în radiani
• Le prezentăm aici pe cele mai frecvent utilizate.
atan2(y,x) arctangentă de y/x, în radiani
• Fiecare dintre acestea
 primeşte unul sau două argumente de tip exp(x) funcţia exponenţială ex
double şi
log(x) logaritm natural (în baza e) din x
 returnează o valoare de tip double.
(x>0)
21:38 PCLP CURS 11 43 21:38 PCLP CURS 11 44

Funcţii matematice
log10(x) logaritm zecimal (în baza 10)
din x (x>0)

pow(x,y) xy

sqrt(x) radical de ordinul doi din x (x≥0)


ALTE FUNCȚII DIN stdlib.h
fabs(x) valoarea absolută a lui x

21:38 PCLP CURS 11 45 21:38

void abort(void) void exit(int status)


• Generează terminarea anormală a programului: • Generează terminarea normală a programului. Valoarea
abort(); 0 a argumentului specifică terminarea complet normală a
Poate apare oriunde în program. programului.
#include <stdio.h>
#include <stdlib.h>

#include <stdio.h> main (){


#include <stdlib.h> char c;
main (){
char c; printf("Dati un numar nenul (0 : iesire cu exit) ");
scanf("%i", &c);
printf("Dati un numar nenul (0 : iesire anormala) ");
if(c){
scanf("%i", &c);
printf("Ati introdus = %i \n", c);
if(c){
printf("Terminare program cu return 0\n");
printf("Ati introdus = %i \n", c);
} else {
printf("Terminare normala program!\n");
printf("Ati introdus = %i \n", c);
}else {
printf("Terminare program cu exit(0) !\n"); exit(0);
printf("Terminare anormala program!\n"); abort();
}
}
return 0;
return 0;
}
}
21:38 PCLP CURS 11 47 21:38 PCLP CURS 11 48

PCLP Curs 11 8
9/5/2018

int atexit(void (*f)(void)) #include <stdio.h>


#include <stdlib.h>
void adio(void);
void pa(void);
• atexit() înregistrează funcția f pentru a fi apelată int main (){

atunci când programul se termină normal. int status;


printf("Inceput program\n\n.....\n\n");

• Funcțiile atexit() se pot înregistra oriunde în status = atexit(adio); /* inregistrez a 2-a functie (adio) apelata la o
iesire normala */

program, printf("status atexit(adio) = %d\n", status);


atexit(pa); /* inregistrez prima functie (pa) apelata la o iesire normala */
 dar la finalul programului se apelează în ordinea inversă a printf("Final program. \nAcum se apeleaza pa() si adio()\n\n");
return 0;
înregistrării lor. }

• atexit() returnează 0 atunci când înregistrarea void adio(void){


printf("\nSuntem in functia adio()!\nADIO!\n");
funcției f se realizează cu succes și }
void pa(void){
 o valoare nenulă atunci când funcția f nu poate fi printf("\nSuntem in functia pa()!\nLa revedere!\n");
}
înregistrată .
21:38 PCLP CURS 11 49 21:38 PCLP CURS 11 50

void assert(int expresie)


• Macroul assert este folosit la diagnosticarea
programelor
 cu scrierea mesajelor în stderr, fluxul standard de
ieșire pentru erori.

• Dacă expresie are valoarea 0, în momentul


FIȘIERUL ANTET assert.h apelului macroului assert(expresie) se va
tipări la stderr un mesaj de eroare.
 Apoi se apelează abort() pentru a termina anormal
execuția programului.
21:38 21:38 PCLP CURS 11 52

#include <assert.h>
Dacă odată cu includerea antetului
#include <stdio.h> #include <stdio.h> <assert.h> este definită
int main(){ #define NDEBUG constanta NDEBUG, macroul
int nota; #include <assert.h> assert(expresie) este ignorat.
int main(){
printf("Introduceti nota studentului (1..10) : ");
int nota;
scanf("%d", &nota);
assert(nota <=10 && nota >= 1); printf("Introduceti nota studentului (1..10) : ");
printf("Nota introdusa %d\n", nota); scanf("%d", &nota);
assert(nota <=10 && nota >= 1);
return 0;
printf("Nota introdusa %d\n", nota);
}
return 0;
}

21:38 PCLP CURS 11 53 21:38 PCLP CURS 11 54

PCLP Curs 11 9
9/5/2018

Pentru a invalida blocarea acțiunii


#include <stdio.h> macroului assert() se poate
#undef NDEBUG elimina definirea constantei
#include <assert.h> NDEBUG, prin #undef NDEBUG.
int main(){ Astfel pe sistemele care implicit au
invalidat macroul assert(),
int nota;
acesta poate fi activat.
printf("Introduceti nota studentului (1..10) : ");
scanf("%d", &nota);
assert(nota <=10 && nota >= 1);
printf("Nota introdusa %d\n", nota);

return 0; FIȘIERUL ANTET PENTRU DATĂ ȘI


}
ORĂ time.h

21:38 PCLP CURS 11 55 21:38

Macrouri Tipuri declarate


• NULL: acest macro este valoarea unui pointer • size_t: tipul întreg fără semn furnizat de rezultatul
constant nul. aplicării operatorului sizeof
• clock_t: tip de dată aritmetic, destinat memorării
• CLOCKS_PER_SEC: reprezintă numărul de bătăi bătăilor ceasului procesorului,
de ceas pe secundă ale procesorului.  tipul valorilor returnate de funcția clock().
 Are tipul de dată clock_t (vezi în continuare).
• time_t: tip de dată aritmetic pentru memorarea
unor momente de timp calendaristic
 ce presupun atât data din calendar, cât și ora, minutul
și secunda.
21:38 PCLP CURS 11 57 21:38 PCLP CURS 11 58

clock_t clock(void) Aplicație 1


• Folosind funcția clock și macroul CLOCKS_PER_SEC,
• Funcția returnează numărul de bătăi de ceas ale scrieți un program care:
procesorului scurse de la lansarea în execuție a  afișează numărul de bătăi ale procesorului memorate într-o
programului curent. variabilă (start) la un moment de timp foarte aproape de
începutul programului, apoi
• Pentru a afla numărul de secunde scurse de la  apelează o funcție întarziere care simulează prelucrări ale
programului care durează 10 secunde, apoi
lansarea în execuție a programului,  memorează într-o variabilă (stop) numărul de bătăi ale
 trebuie să împărțim valoarea furnizată de funcția procesorului foarte aproape de finalul programului.
clock() la CLOCKS_PER_SEC  Se afișează numărul de bătăi ale procesorului între aceste
momente de timp (start, stop) și
 numărul de secunde scurse între cele două momente de timp
(start, stop)
21:38 PCLP CURS 11 59 21:38 PCLP CURS 11 60

PCLP Curs 11 10
9/5/2018

#include <stdio.h>
#include <time.h>
struct tm timp descompus
void intarziere(unsigned int);
main(){ • Structură (numită broken-down time) care memorează
clock_t start, stop, total;
o dată și un timp, descompuse în componentele lor:
start = clock(); printf("Pornire program = %ld\n", start);
struct tm {
intarziere(10000); /* intarziere 10 de secunde */
stop = clock(); printf("Final program = %ld\n", stop); int tm_sec; /* secunde dupa minut, 0..60 */
total = stop - start; int tm_min; /* minute dupa ora, 0..59 */
printf("Timp total procesor = %ld batai\n", total); int tm_hour; /* ore de la miezul noptii, 0..23 */
printf("CLOCKS_PER_SEC = %ld\n", CLOCKS_PER_SEC); int tm_mday; /* ziua din luna, 1..31 */
printf("timpul scurs = %ld\n", total/CLOCKS_PER_SEC); int tm_mon; /* luna incepand de la ianuarie, 0..11 */
return 0; int tm_year; /* numarul de ani de la 1900 */
} int tm_wday; /* ziua din saptamana de la duminica, 0..6 */
void intarziere(unsigned int milisecunde){ int tm_yday; /* ziua din an de la 1 ianuarie, 0..365 */
clock_t stop = milisecunde + clock(); int tm_isdst; /* ora de vara, >0 daca e activa, 0 daca nu e
while ( stop > clock() ); si <0 daca nicio informatie nu e disponibila*/
} };
21:38 PCLP CURS 11 61 21:38 PCLP CURS 11 62

time_t time(time_t *timer) Aplicație 2


• Folosind funcția time afișați câți ani au trecut din 1
• Funcția returnează ora și data curente codificate în ianuarie 1970,
formatul tipului time_t  împărțind numărul de secunde care au trecut din acel
 adică numărul de secunde scurse de la 1 ianuarie 1970, moment de timp (pe care îl furnizează funcția time) la
ora 0, minutul 0, secunda 0 (UTC/GMT).  numărul de secunde dintr-un minut * numărul de
minute dintr-o oră * numărul de ore dintr-o zi * numărul
• Dacă ora și data nu sunt disponibile se returnează de zile dintr-un an.
valoarea (time_t)(-1).
• Observație: se obține un număr exact de ani datorită
• Dacă timer nu este pointerul nul, valoarea returnată proprietăților operatorului / care în cazul a doi
este asignată și obiectului indicat de pointer: *timer. operanzi întregi afișează câtul împărțirii lor.
21:38 PCLP CURS 11 63 21:38 PCLP CURS 11 64

time_t mktime(struct tm
*timeptr)
#include <stdio.h>
#include <time.h>
• Convertește un timp descompus (broken-down time)
main () exprimat prin pointerul la structura tm: timeptr,
{
 într-o valoare temporală codificată la fel ca valorile
time_t secunde;
returnate de funcția time().
secunde = time(NULL);
printf("Din 1 ianuarie 1970 au trecut %ld de ani.\n", • Valorile originale ale membrilor structurii tm:
secunde/(60*60*24*365)); tm_wday și tm_yday sunt ignorate,
 iar valorile originale ale celorlalți membrii nu sunt
return 0;
} restricționate la intervalele precizate anterior în
comentariile din dreptul lor.
21:38 PCLP CURS 11 65 21:38 PCLP CURS 11 66

PCLP Curs 11 11
9/5/2018

time_t mktime(struct tm time_t mktime(struct tm


*timeptr) *timeptr)
• La finalizarea cu succes, valorile membrilor tm_wday
• Astfel, o valoare pozitivă (sau zero) pentru
și tm_yday sunt poziționate adecvat,
tm_isdst
 iar valorile celorlalți membrii sunt poziționate să
 determină ca funcția mktime() să presupună că ora
reprezinte timpul specificat,
de vară este (sau nu este) activă.
 dar cu valorile lor forțate la intervalele specificate
• O valoare negativă determină funcția să încerce să anterior.
determine • Valoarea finală a membrului tm_mday nu este
 dacă ora de vară era activă la momentul de timp poziționată
specificat.
 până când nu sunt determinate tm_mon și tm_year.
21:38 PCLP CURS 11 67 21:38 PCLP CURS 11 68

Aplicație 3 #include <stdio.h>


#include <time.h>
main(){
• Folosind funcția mktime afișați numele zilei din static const char *const zi_din_saptamana[] = {"duminica",
săptămână (luni, marti, ..., duminica) în care cade o "luni", "marti", "miercuri", "joi", "vineri", "sambata", "zi necunoscuta"};
struct tm timp; int an, luna, zi;
anumită dată furnizată prin: printf("Anul (e.g. 2016) = "); scanf("%d", &an);
printf("Luna (1:ian..12:dec) = "); scanf("%d", &luna);
 an (pe 4 cifre), printf("Ziua din luna (1..31) = "); scanf("%d", &zi);
 lună (număr între 1 și 12) și timp.tm_year = an – 1900; timp.tm_mon = luna - 1;
timp.tm_mday = zi; timp.tm_isdst = -1;
 zi (număr între 1 și 31). timp.tm_hour = timp.tm_min = timp.tm_sec = 0;
if (mktime(&timp) == (time_t)(-1)) /* in caz de eroare */
• Programul detectează eroare în cazul unei date pe timp.tm_wday = 7; /* ziua din saptamana este
pozitionata la o valoare care nu exista:7 */
care nu o recunoaște. printf("Ziua din saptamana in care cade %d/%d/%d =
%s\n", zi, luna, an, zi_din_saptamana[timp.tm_wday]);
return 0;
}
21:38 PCLP CURS 11 69 21:38 PCLP CURS 11 70

Temă struct tm *localtime(const


time_t *timer)
• Asemănător calculați a câta zi din anul curent a
căzut o anumită dată introdusă.
• Funcția convertește data și ora indicate de
Indicație: se afișează timp.tm_yday pointerul timer într-un timp descompus (broken
down time) care exprimă o dată și oră locală.

• Valoarea returnată este un pointer la un timp


descompus, sau pointerul nul, dacă data și ora
furnizate pe intrare nu pot fi convertite în dată și
oră locală.
21:38 PCLP CURS 11 71 21:38 PCLP CURS 11 72

PCLP Curs 11 12
9/5/2018

struct tm *gmtime(const char *asctime(const struct


time_t *timer) tm *timeptr)

• Funcția convertește data și ora spre care indică • Funcția convertește timpul descompus (broken-
pointerul timer într-un timp descompus (broken down time) din structura spre care indică
down time) care exprimă ora și data UTC/GMT. timeptr într-un șir de forma:
• Valoarea returnată este un pointer la un timp Tue Nov 29 09:56:04 2016\n\0
descompus, sau pointerul nul, dacă data și ora
furnizate pe intrare nu pot fi convertite în dată și • Utilizând un algoritm echivalent cu următorul:
oră UTC/GMT.

21:38 PCLP CURS 11 73 21:38 PCLP CURS 11 74

char *asctime(const struct tm *timeptr){


Aplicație 4
static const char zi_sapt[7][3] = {"Sun", "Mon", "Tue",
"Wed", "Thu", "Fri", "Sat"};
• Notând cu a funcția asctime din slide-ul anterior
static const char luna[12][3] = {"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; (pentru a nu fi confundată cu funcția asctime din
static char timp[26]; <time.h>), scrieți un program care afișează
sprintf(timp, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",  data și ora locală (furnizată de apelul funcției
zi_sapt[timeptr->tm_wday], localtime) și
luna[timeptr->tm_mon],
timeptr->tm_mday,  data și ora UTC/GMT (furnizată de apelul funcției
timeptr->tm_hour, gmtime) în formatul:
timeptr->tm_min,
timeptr->tm_sec, Mar Noi 29 09:56:04 2016
1900 + timeptr->tm_year);
return timp; • Apelând de fiecare dată, pentru cele două afișări,
} funcția a.
21:38 PCLP CURS 11 75 21:38 PCLP CURS 11 76

#include <stdio.h>
#include <time.h> Aplicație 5
char *a(const struct tm *timeptr);
main(){ • Folosind funcția asctime din headerul
time_t timp = time(NULL);
<time.h>, scrieți un program care afișează
printf("Data si ora UTC/GMT: %s", a(gmtime(&timp)));
printf("Data si ora locala : %s", a(localtime(&timp)));  data și ora UTC/GMT (furnizată de apelul funcției
}
return 0; gmtime) și
char *a(const struct tm *timeptr){
 data și ora locală (furnizată de apelul funcției
static const char zi_sapt[7][3] = {"Dum", "Lun", "Mar", "Mie", "Joi",
"Vin", "Sam"}; localtime) în formatul:
static const char luna[12][3] = {"Ian", "Feb", "Mar", "Apr", "Mai",
"Iun", "Iul", "Aug", "Sep", "Oct", "Noi", "Dec"};
static char timp[26];
Tue Nov 29 09:56:04 2016
sprintf(timp, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", zi_sapt[timeptr-
>tm_wday], luna[timeptr->tm_mon], timeptr->tm_mday,timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec, 1900 + timeptr->tm_year);
• Apelând de fiecare dată, pentru cele două afișări,
return timp;
}
funcția asctime.
21:38 PCLP CURS 11 77 21:38 PCLP CURS 11 78

PCLP Curs 11 13
9/5/2018

char *ctime(const time_t


*timer)
#include <stdio.h>
#include <time.h>
• Funcția convertește data și ora furnizate prin
main()
pointerul timer la o dată și oră locale în forma unui
{ șir de caractere.
time_t timp = time(NULL);
• Este echivalentă cu:
printf("Data ora UTC/GMT: %s“, asctime(gmtime(&timp)));
asctime(localtime(timer))
printf("Data ora locala : %s",
asctime(localtime(&timp)));
• Funcția întoarce un pointer la un șir de caractere - ca
return 0; și asctime - cu același format:
} Tue Nov 29 09:56:04 2016\n\0
21:38 PCLP CURS 11 79 21:38 PCLP CURS 11 80

Aplicație 6 #include <stdio.h>


#include <time.h>

main()
• Rescrieți aplicația anterioară (Aplicație 5)pentru {
afișarea time_t timp = time(NULL);

 datei și orei locale (furnizată de data aceasta doar printf("Data ora UTC/GMT: %s", asctime(gmtime(&timp)));
de apelul funcției ctime) și a printf("Data ora locala : %s", ctime(&timp));

 datei și orei UTC/GMT (furnizată de apelul /* ctime(&timp)


este echivalent cu
funcțiilor asctime și gmtime) în formatul: asctime(localtime(&timp) */

Tue Nov 29 09:56:04 2016 return 0;


}

21:38 PCLP CURS 11 81 21:38 PCLP CURS 11 82

double difftime(time_t t1, Aplicație 7


time_t t2)
• Aplicația următoare afișează câte secunde s-au
scurs din ora curentă,
• Calculează diferența dintre două momente de
timp t1 și t2 (i.e. t2-t1) în secunde.  folosind funcția diff pentru
 a scădea din ora, minutul și secunda curente
• Rezultatul este negativ dacă t2 referă un moment (acum),
de timp anterior momentului indicat de t1.  o variabilă inițializată cu acum (ora_curenta)
 la care poziționăm membrii corespunzători secundei
și minutului pe zero.

21:38 PCLP CURS 11 83 21:38 PCLP CURS 11 84

PCLP Curs 11 14
9/5/2018

#include <stdio.h>
#include <time.h>
size_t strftime(char *s,
Data și ora curente preluate
main(void){
time_t acum = time(NULL);
de pe ecranul calculatorului
size_t maxsize, const char *format,
struct tm ora_curenta;
/* memoram membrii variabilei temporale acum in membrii
const struct tm *timeptr)
variabilei temporale ora_curenta */
ora_curenta = *localtime(&acum);
/* variabila ora_curenta va avea toti membrii identici cu
• Funcția formatează informații de despre dată și oră
variabila acum mai putin minutul si secunda care le facem 0 */  indicate de timeptr
ora_curenta.tm_min = ora_curenta.tm_sec = 0;
 plasându-le într-un șir de caractere indicat de pointerul s
/* cu functia difftime() scadem cele doua momente de timp si
aflam cate secunde s-au scurs de la inceputul orei curente */  și controlat de șirul indicat de pointerul format (analog
double secunde = difftime(acum, mktime(&ora_curenta));
formatelor din printf).
printf("Din ora curenta au trecut %.f secunde\n", secunde);
printf("Din ora curenta au trecut %.f minute\n", secunde/60);
• Funcția întoarce numărul de caractere din șirul indicat
}
return 0;
de s.
21:38 PCLP CURS 11 85 21:38 PCLP CURS 11 86

• În șirul s sunt copiate maxim maxsize caractere. %a e înlocuit de prescurtarea locală a numelui zilei din
• timeptr indică o structură de tip timp descompus. săptămână [tm_wday]
• Șirul de caractere indicat de pointerul format constă %A e înlocuit de numele local al zilei din săptămână
din zero sau mai mulți specificatori de conversie și alte [tm_wday]
caractere dorite de utilizator.
%b e înlocuit de prescurtarea locală a numelui lunii [tm_mon]
• Toate caracterele dorite de utilizator sunt copiate
neschimbate în șirul s. %B e înlocuit de numele local al lunii [tm_mon]
• Un specificator de conversie constă din caracterul % %c e înlocuit de o reprezentare locală adecvată a datei și orei
urmat de specificatorul de conversie.
%d e înlocuit de ziua din lună ca număr (01−31) [tm_mday]
• Fiecare specificator de conversie este înlocuit de
%H e înlocuit de oră ca număr (00−23) [tm_hour]
caractere corespunzătoare așa cum va fi descris în lista
următoare: %I e înlocuit de oră ca număr (01−12) [tm_hour]
21:38 PCLP CURS 11 87 21:38 PCLP CURS 11 88

%j e înlocuit de ziua din an ca număr (001−366) [tm_yday] %W e înlocuit de numărul din an al săptămânii (prima luni este
prima zi a săptămânii unu) ca număr (00−53) [tm_year,
%m e înlocuit de lună ca număr (01−12) [tm_mon]
tm_wday, tm_yday]
%M e înlocuit de minut ca număr (00−59) [tm_min]
%x e înlocuit de o reprezentare locală adecvată a datei
%p e înlocuit de echivalentul local al notației AM/PM asociat %X e înlocuit de o reprezentare locală adecvată a orei
un ceas cu 12 ore [tm_hour]
%y e înlocuit de ul mele 2 cifre ale anului (00−99) [tm_year]
%S e înlocuit de secundă ca număr (00−60) [tm_sec]
%Y e înlocuit de an (e.g. 2016) [tm_year]
%U e înlocuit de numărul din an al săptămânii (prima duminică
este prima zi a săptămânii unu) ca număr (00−53) %Z e înlocuit de fusul orar sau abrevierea lui (e.g. pentru
[tm_year, tm_wday, tm_yday] România se afișează: GTB Standard Time ceea ce este tot
una cu Ora Europei de Est (EET): GMT/UTC+2)
%w e înlocuit de ziua din săptămână ca număr (0−6), unde
duminică este 0 [tm_wday] %% e înlocuit de %.
21:38 PCLP CURS 11 89 21:38 PCLP CURS 11 90

PCLP Curs 11 15
9/5/2018

Aplicație 8 #include <stdio.h>


#include <time.h> %a prescurtare locală nume zi săptămână
#define MAX_LUNG 40 %A nume local zi din săptămână
main(){ %b prescurtare locală nume lună
• Exemplificați cei 22 de specificatori de conversie, time_t timp = time( NULL );
enumerați anterior, ai funcției strftime. struct tm *ptr_timp_local, *ptr_timp_gmt;
char sir_timp[ MAX_LUNG ];
ptr_timp_local = localtime( &timp );
• Observație: Doar primul program va fi prezentat strftime(sir_timp, MAX_LUNG, "(%a) (%A) (%b)“,ptr_timp_local);
complet, la programele următoare nu va fi printf( "local %%a(zi abrev.) %%A(zi) %%b(luna abrev.):
%s\n", sir_timp );
prezentată decât zona de program care presupune ptr_timp_gmt = gmtime( &timp );
modificări datorită schimbării specificatorilor de strftime( sir_timp, MAX_LUNG, "(%a) (%A) (%b)", ptr_timp_gmt);
conversie. printf( "gmt %%a(zi abrev.) %%A(zi) %%b(luna abrev.):
%s\n", sir_timp );
return 0;
}

21:38 PCLP CURS 11 91 21:38 PCLP CURS 11 92

%B nume local lună


%H ora număr 00−23
%c reprezentare locală dată și oră
%d ziua din lună ca număr (01−31) . . . . . . . . . %I ora număr 01−12
. . . . . . . . . . . . . .
ptr_timp_local = localtime( &timp );
ptr_timp_local = localtime( &timp );
strftime( sir_timp, MAX_LUNG, "(%B) (%c) (%d)", strftime( sir_timp, MAX_LUNG, "(%H) (%I)",
ptr_timp_local ); ptr_timp_local );

printf( "local %%B(luna) %%c(data ora locala) %%d(zi din printf( "local %%H(ora 00..23) %%I(ora 00..12) :
luna):\n %s\n\n", sir_timp ); %s\n\n", sir_timp );

ptr_timp_gmt = gmtime( &timp ); ptr_timp_gmt = gmtime( &timp );


strftime( sir_timp, MAX_LUNG, "(%B) (%c) (%d)", strftime( sir_timp, MAX_LUNG, "(%H) (%I)",
ptr_timp_gmt); ptr_timp_gmt);
printf( "gmt %%B(luna) %%c(data ora) %%d(zi din printf( "gmt %%H(ora 00..23) %%I(ora 00..12) : %s\n",
luna):\n %s\n", sir_timp ); sir_timp );
. . . . . . . . . . . . . . . . . . . . . . .

21:38 PCLP CURS 11 93 21:38 PCLP CURS 11 94

%j ziua din an, număr 001−366 %p echivalentul local al notației


AM/PM asociat un ceas cu 12 ore
%m luna număr 01−12
. . . . . . . . . %S secunda număr 00−60
. . . . . . . . . %M minut număr 00−59
ptr_timp_local = localtime( &timp );
ptr_timp_local = localtime( &timp );
strftime( sir_timp, MAX_LUNG, "(%p) (%S)",
strftime( sir_timp, MAX_LUNG, "(%j) (%m) (%M)", ptr_timp_local );
ptr_timp_local );
printf( "local %%p(AM/PM) %%S(secunda 00..60) : %s\n\n",
printf( "local %%j(zi 001..366) %%m(luna 01..12) sir_timp );
%%M(minut 00..59): %s\n\n", sir_timp );
ptr_timp_gmt = gmtime( &timp );
ptr_timp_gmt = gmtime( &timp );
strftime( sir_timp, MAX_LUNG, "(%p) (%S)",
strftime( sir_timp, MAX_LUNG, "(%j) (%m) (%M)", ptr_timp_gmt);
ptr_timp_gmt);
printf( "gmt %%p(AM/PM) %%S(secunda 00..60) : %s\n",
printf( "gmt %%j(zi 001..366) %%m(luna 01..12) sir_timp );
%%M(minut 00..59): %s\n", sir_timp ); . . . . . . . . .
. . . . . . . . .

21:38 PCLP CURS 11 95 21:38 PCLP CURS 11 96

PCLP Curs 11 16
9/5/2018

%U numărul din an al săptămânii (prima duminică %W numărul din an al săptămânii (prima luni
este prima zi a săptămânii unu) număr 00−53 e prima zi a săptămânii unu) număr 00−53
%w ziua din săptămână număr 0−6, 0 = duminică %x reprezentare locală adecvată a datei
. . . . . . . . . . . . . . . . . .
ptr_timp_local = localtime( &timp ); ptr_timp_local = localtime( &timp );
strftime( sir_timp, MAX_LUNG, "(%U) (%w)", strftime( sir_timp, MAX_LUNG, "(%W) (%x)",
ptr_timp_local ); ptr_timp_local );
printf( "local %%U(nr saptamana 00-53) %%w(zi saptamana printf( "local %%W(nr saptamana 00-53) %%x(reprezentare
0..6) : %s\n\n", sir_timp ); locala data) : %s\n\n", sir_timp );

ptr_timp_gmt = gmtime( &timp ); ptr_timp_gmt = gmtime( &timp );


strftime( sir_timp, MAX_LUNG, "(%U) (%w)", strftime( sir_timp, MAX_LUNG, "(%W) (%x)",
ptr_timp_gmt); ptr_timp_gmt);
printf( "gmt %%U(nr saptamana 00-53) %%w(zi saptamana printf( "gmt %%W(nr saptamana 00-53) %%x(reprezentare
0..6) : %s\n", sir_timp ); locala data) : %s\n", sir_timp );
. . . . . . . . . . . . . . . . . .

21:38 PCLP CURS 11 97 21:38 PCLP CURS 11 98

%X reprezentare locală adecvată a orei %Y an (e.g. 2016)


. . . . . . . . . %y ul mele 2 cifre ale anului 00−99 %Z fusul orar sau abrevierea lui (pt
ptr_timp_local = localtime( &timp ); România: GTB Standard Time )
. . . . . . . . .
strftime( sir_timp, MAX_LUNG, "(%X) (%y)", ptr_timp_local = localtime( &timp );
ptr_timp_local ); strftime( sir_timp, MAX_LUNG, "(%Y) (%Z)",
printf( "local %%X(reprezentare locala ora) %%y(an 2 ptr_timp_local );
cifre) : %s\n\n", sir_timp ); printf( "local %%Y(an) %%Z(fus orar) : %s\n\n", sir_timp );

ptr_timp_gmt = gmtime( &timp ); ptr_timp_gmt = gmtime( &timp );


strftime( sir_timp, MAX_LUNG, "(%X) (%y)", strftime( sir_timp, MAX_LUNG, "(%Y) (%Z)",
ptr_timp_gmt); ptr_timp_gmt);
printf( "gmt %%X(reprezentare ora) %%y(an 2 cifre) : printf( "gmt %%Y(an) %%Z(fus orar) : %s\n", sir_timp );
%s\n", sir_timp );
. . . . . . . . .
. . . . . . . . .

21:38 PCLP CURS 11 99 21:38 PCLP CURS 11 100

C99 (1999) și C11 (2011)

• Sunt ultimele standarde pentru limbajul C.


• Ele rafinează și extind puterea limbajului C
standard.
• C99 introduce o colecția mai mare de schimbări
REVIZUIRI ALE C-ULUI STANDARD. decât C11.
STANDARDELE C99 și C11 • Nu toate compilatoarele implementează toate
caracteristicile C99 și C11.
21:38 21:38 PCLP CURS 11 102

PCLP Curs 11 17
9/5/2018

Alegerea Headere noi în C99


standardului
<complex.h> conține prototipuri de macrouri și
C99 / C11 în funcții pentru numere complexe
CodeBlocks
<fenv.h> furnizează informații despre
așa sau așa
implementarea în C a mediului
virgulă mobilă
<inttypes.h> definește câteva noi tipuri întregi
portabile și furnizează specificatori de
format pentru tipurile definite.
”-std=c99” sau ”-std=c11”
21:38 PCLP CURS 11 103 21:38 PCLP CURS 11 104

Headere noi în C99 Headere noi în C99 multibyte și wide character: tipuri
de date caracter pe mai mult de 8 biți
(16/32) pentru a permite utilizarea
unui set de caractere extins.
<iso646.h> definește 11 macrouri care reprezintă <tgmath.h> furnizează macrouri cu tip generic care permit
operatori de egalitate, relaționali și la ca funcții pentru operații matematice din
nivel de bit [C95] <math.h> și <complex.h> (incluse în el)
să fie utilizate cu argumente de diferite tipuri
<stdbool.h> definește macrourile bool, true și
false, utilizate pentru variabile <wchar.h> împreună cu <wctype.h>, furnizează suport
booleene pentru intrările și ieșirile multibyte character
și wide character [C95]
<stdint.h> definește tipuri întregi și macrouri
<wctype.h> împreună cu <wchar.h>, furnizează o
corespunzătoare bibliotecă pentru wide character [C95]
21:38 PCLP CURS 11 105 21:38 PCLP CURS 11 106

Combinarea declarațiilor cu #include <stdio.h>


main(){
codul executabil int a = 3; // declara variabla la inceputul blocului
printf( “7 + a = %d\n", 7 + a );
int b = 8; //declara variabila in mijlocul codului executabil
• Înainte de C99 toate variabilele care aveau printf( “2 * b = %d\n", 2 * b );
domeniul de existență într-un bloc trebuiau return 0;
definite la începutul blocului. }
• Deși combinarea declarațiilor cu codul poate spori
• C99 permite combinarea declarațiilor cu codul lizibilitatea și reduce posibilitatea unor referințe
neintenționate,
executabil.
 anumiți programatori preferă gruparea declarațiilor
• O variabilă poate fi definită oriunde într-un bloc variabilelor la începutul blocurilor.
înainte de utilizarea ei. • O variabilă nu poate fi declarată după liniile de cod în care
acea variabilă este utilizată.
21:38 PCLP CURS 11 107 21:38 PCLP CURS 11 108

PCLP Curs 11 18
9/5/2018

Declararea variabilelor în antetul for


#include <stdio.h>
int main(){
float i = 10.25;
printf( "Primele 10 numere naturale:\n" );
C99 permite
for ( int i = 0; i <= 9; ++i ){ includerea
printf( i < 9 ? "%d " : "%d\n\n", i );
} /* acoladele pot lipsi */
declarațiilor în
expresia de
printf("i vechi = %g\n", i );
inițializare a
return 0; instrucțiunii for.
}
• În loc să utilizăm o variabilă deja existentă cu rol de contor, Compilatorul utilizează standardul C11

 putem crea o nouă variabilă contor (int i = 0) în antetul


instrucțiunii for al cărei domeniu de existență este limitat
la instrucțiunea for.
21:38 PCLP CURS 11 109 21:38 PCLP CURS 11 110

Inițializări la tipuri compuse de date


Declararea variabilelor în antetul for
• În standardele anterioare lui C99, inițializarea
elementelor unui tablou unidimensional se putea realiza
• Orice variabilă declarată într-o instrucțiune for cu un cod ca mai jos:
(int i = 0) are ca domeniu de existență doar #include <stdio.h>

instrucțiunea for. int main(){


int i, v[8];
v[0] = 5; v[7] = 3;
• Variabila nu există în afara instrucțiunii for și for( i = 1; i < 7; ++i )
v[i] = 0;
 încercarea de a referi o astfel de variabilă după printf( "afisare tablou \n" );
for( i = 0; i < 8; ++i )
corpul ciclului for generează eroare de compilare. printf( "%d ", v[i] );
return 0;
}
21:38 PCLP CURS 11 111 21:38 PCLP CURS 11 112

Inițializări la tipuri compuse de date Inițializări la tipuri compuse de date


• În C99 se poate face o inițializare doar pentru elementele • Se poate inițializa un tablou, struct sau union
care sunt nenule, elementele neinițializate explicit sunt fără nume.
implicit inițializate cu valoarea 0 a tipului tabloului.
#include <stdio.h> • De exemplu, dacă dorim să transmitem unei funcții
int main(){ f() un tablou (ca tabloul v[] din exemplele
int i, v[ 8 ] = { [ 0 ] = 5, [ 7 ] = 3 }; anterioare)
printf( "afisare tablou\n" );  fără a fi declarat anterior tabloul,
for( i = 0; i < 8; ++i )
printf( "%d ", v[i] );
 se poate scrie în program un apel de forma:
return 0; f( ( int [ 8 ] ) { [ 0 ] = 5, [ 7 ] = 3 } );
}
21:38 PCLP CURS 11 113 21:38 PCLP CURS 11 114

PCLP Curs 11 19
9/5/2018

#include <stdio.h>
#include <stdio.h> Asemănător se petrec
struct cvartet{ lucrurile și pentru struct
void f(int [8]); int x, y, z, w;
};
(vezi exemplul) sau union.
int main(){
void f(struct cvartet);
printf( " afisare tablou \n" );
int main(){
f( ( int [ 8 ] ) { [ 0 ] = 5, [ 7 ] = 3 } ); printf( "Afisare structura \n" );
return 0; f( ( struct cvartet ) { .x = 5, .w = 3 } );
return 0;
}
}
void f(int a[8]) void f(struct cvartet p){
{ printf( "membrul x = %d \n", p.x );
for( int i = 0; i < 8; ++i ) printf( "membrul y = %d \n", p.y );
printf("%d ", a[i]); printf( "membrul z = %d \n", p.z );
printf( "membrul w = %d \n", p.w );
}
}

21:38 PCLP CURS 11 115 21:38 PCLP CURS 11 116

#include <stdio.h>
BIBLIOGRAFIE
struct punct_in_spatiu{
float x, y, z;
}; [1] Kernighan, B., Ritchie, D., The C Programming
int main(){ Language, 2nd ed., Ed. Prentice Hall, 1988.
struct punct_in_spatiu a[8] = {
[ 0 ] = { .x = 1.12, .y = -2.04, .z = 3.25 },
[ 7 ] = { .x = 15.31, .z = -12.14 } [2] Deitel, P., Deitel, H., C - How to program, 8th ed.,
};
Inițializarea Pearson Publisher, 2016.
printf( "Afisare tablou de struct \n" ); unui tablou
printf( " x y z\n" );
de struct.
for ( int i = 0; i < 8; ++i ) [3] ***, N1570, Standardul C11 - ISO/IEC 9899:2011,
printf( "%7.2f %7.2f %7.2f\n", a[ i ].x, a[ i ].y, http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
a[ i ].z );
return 0;
}

21:38 PCLP CURS 11 117 21:38 PCLP CURS 11 118

PCLP Curs 11 20

S-ar putea să vă placă și