Documente Academic
Documente Profesional
Documente Cultură
Cuvantul int poate fi omis în astfel de declarații şi de obicei chiar este omis. Calificatorul signed sau
unsigned poate fi aplicat la char sau la orice întreg. Numerele unsigned sunt totdeauna pozitive sau zero.
De exemplu, daca char ocupa 8 biți, variabilele unsigned char iau valori între 0 şi 255, în timp ce
variabilele signed char iau valori între -128 şi 127 (in cod complement fata de doi). Caracterele tipăribile
sunt totdeauna pozitive. Tipul long double specifica numere reale în virgulă mobilă cu precizie extinsă.
Ca şi la tipurile întregi dimensiunile tipurilor virgulă mobilă depind de implementare; float, double şi long
double pot avea una, doua sau trei dimensiuni distincte. Headerele standard <limits.h> şi <float.h>
conțin constante simbolice pentru toate aceste dimensiuni împreună cu alte proprietăţi ale mașinii şi
compilatorului.
Aplicaţie rezolvată 1. Scrieți un program care să determine domeniile de variație ale variabilelor de tipurile
char, short, int şi long, precum şi pentru signed şi unsigned, afișând valorile corespunzătoare din
headerele standard şi prin calcul direct.
Reţineţi numele constantelor simbolice care precizează cel mai mic şi cel mai mare număr al unui tip de dată.
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("Domeniul lui signed char este [%d, %d].\n\n", SCHAR_MIN, SCHAR_MAX);
printf("Domeniul lui unsigned char este [%u, %u].\n\n", 0, UCHAR_MAX);
printf("Domeniul lui char este [%d, %d].\n\n", CHAR_MIN, CHAR_MAX);
printf("Domeniul lui signed short int este [%hd, %hd].\n\n", SHRT_MIN, SHRT_MAX);
printf("Domeniul lui unsigned short int este [%hu, %hu].\n\n", 0, USHRT_MAX);
printf("Domeniul lui signed long int este [%ld, %ld].\n\n", LONG_MIN, LONG_MAX);
printf("Domeniul lui unsigned long int este [%lu, %lu].\n\n", 0, ULONG_MAX);
return 0;
}
CONSTANTE ŞIR
Aplicaţie propusă 1. Folosind funcţia strlen de mai jos, scrieţi un program care să afişeze lungimile unor
şiruri de caractere.
/* strlen: return length of s */
int strlen(char s[])
{
int i;
i = 0;
1
while (s[i] != '\0')
++i;
return i;
}
Ieşirea programului va arăta ca în imaginea alăturată. Pentru citire interactivă a celor două şiruri se poate folosi
o construcţie de forma:
i = 0;
while ((c = getchar()) != '\n')
s[i++] = c;
s[i]='\0';
OPERATORI
1. Operatori aritmetici
Aplicație propusă 2. Scrieţi o aplicaţie care spună dacă un an este bisect sau nu, folosind codul de mai jos
pentru testul cerut.
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
printf("%d is a leap year\n", year);
else
printf("%d is not a leap year\n", year);
Aplicație propusă 3. Scrieţi un ciclu echivalent pentru ciclul for de mai jos
for ( i = 0; i < lim - 1 && ( c = getchar() ) != '\n' && c != EOF; ++i ) s[i] = c;
Aplicație rezolvată 2. Folosind funcția atoi(s) prezentată în Cursul 5, scrieți un program care convertește un
șir de cifre - reprezentând un număr natural - la echivalentul său numeric.
#include <stdio.h>
#define MAXLINE 1000
int main(void)
{
int len;
char line[MAXLINE];
return 0;
}
int get_line(char s[], int lim)
{
int c, i, l;
2
for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i)
if (i < lim - 1)
s[l++] = c;
s[l] = '\0';
return l;
}
int atoi(char s[])
{
int i, n;
n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
n = 10 * n + (s[i] - '0');
return n;
}
Aplicație rezolvată 3. Modificați funcţia atoi(s) prezentată mai sus, înlocuind testul s[i] >= '0' && s[i]
<= '9' cu apelul funcției isdigit(s[i]), funcție care are prototipul în headerul <ctype.h>. Integrați funcția
într-un program ca cel de mai sus.
#include <stdio.h>
#include <ctype.h>
.......
int atoi(char s[])
{
int i, n;
n = 0;
for (i = 0; isdigit(s[i]); ++i)
n = 10 * n + (s[i] - '0');
return n;
}
Aplicație propusă 4*. Folosind una din variantele funcției atoi(s) prezentată mai sus, scrieți un program care
conţine o funcţie htoi(s), care converteşte un şir de cifre hexazecimale (şirul putând include opţional un 0x
sau 0X) în valoarea întreagă echivalentă. Cifrele permise sunt: 0 până la 9, a până la f şi A până la F.
Indicaţie. Se citeşte linia de text (cu funcţia getline) care conţine numărul hexa, se memorează într-un şir de
caractere şi asupra acestui şir se aplică htoi(s).
Aplicație rezolvată 4. Folosind funcția lower() prezentată în Cursul 5, care convertește un caracter din codul
ASCII la minusculă, iar dacă caracterul nu este o literă mare lower() îl returnează nemodificat, scrieți un
program care citește un cuvânt cu litere minuscule și majuscule și convertește majusculele la minuscule, lăsând
minusculele și alte caractere nemodificate.
#include <stdio.h>
int main(void)
{
int len, i = 0;
char line[MAXLINE];
printf("\n");
return 0;
}
3
int get_line(char s[], int lim)
{
int c, i, l;
return l;
}
int lower(int c)
{
if (c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
else
return c;
}
Aplicație rezolvată 5. În programul anterior înlocuiți funcția lower() cu funcția tolower() din headerul
<ctype.h>.
int main(void)
{
int len, i = 0;
char line[MAXLINE];
printf("\n");
return 0;
}
Putem forța conversiile explicite de tip în orice expresie cu operatorul unar numit cast. În construcția
(nume-tip) expresie
expresie este convertită la tipul precizat. Operatorului cast acționează ca și cum expresie este atribuită unei
variabile de tipul nume-tip, variabilă care apoi este utilizată în locul întregii construcții (nume-tip)
expresie.
Aplicație propusă 5. Folosind codul de mai jos (prezentat la Cursul 5) al unei implementări portabile a unui
generator de numere pseudo-aleatoare (rand) și al funcției pentru inițializarea sămânţei (srand) incluse în
biblioteca standard, scrieți un program care, pentru valori ale sămânței
de la 1 la 10, generează numere pseudo-aleatoare între 0 și 32767.
unsigned long int next = 1;
5. Operatorii de incrementare/decrementare
int main()
{
int c, len;
char line[MAXLINE];
squeeze(line, c);
return 0;
}
return l;
}
Aplicație rezolvată 7. Folosind funcția strcat(s, t) prezentată în Cursul 5, care concatenează șirul t la
finalul șirului s, scrieți un program care citește două șiruri de caractere s și t, concatenează șirul t la finalul
șirului s și apoi afișează șirul final s.
/* strcat: concatenate t to end of s; s must be big enough */
void strcat(char s[], char t[])
{
int i, j;
i = j = 0;
while (s[i] != '\0‘) /* find end of s */
i++;
while ((s[i++] = t[j++]) != '\0‘)
; /* copy t */
}
Iată programul:
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */
int main()
{
int c, len;
char s[MAXLINE], t[MAXLINE];
printf("sirul s: ");
get_line(s, MAXLINE);
printf("sirul t: ");
get_line(t, MAXLINE);
strcat(s, t);
return 0;
}
return l;
}
i = j = 0;
while (s[i] != '\0') /* find end of s */
i++;
6
while ((s[i++] = t[j++]) != '\0')
; /* copy t */
}
6. Operatori pe biţi
Poziţie 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Biţi 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 x = 077 = 63(10)
Biţi 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 = getbits(x,4,3) = 7
/* getbits: get n bits from position p */
unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p + 1 - n)) & ~(~0 << n);
}
Expresia x >> (p + 1 - n) mută secvența dorită la marginea din dreapta a cuvântului. ~0 este format
numai din biţi egali cu 1; deplasându-l la stânga cu n poziţii, cu expresia ~0<<n, se pun numai zerouri în cei
mai din dreapta n biţi; complementând acest rezultat cu ~ se creează o mască numai cu 1 în cei mai din dreapta
n biți.
Aplicație propusă 6. Integrați codul funcției getbits() de mai sus într-un program.
Aplicație rezolvată 8. Folosind funcția getbits() de mai sus afișați biții aflați între pozițiile p1 și p2 dintr-un
număr x natural dat. p1 și p2 se dau.
#include <stdio.h>
int main()
{
unsigned x = 170; /* 0252 in baza 8 sau 0000000010101010 in baza 2*/
int p1 = 7, p2 = 5;
return 0;
}
7
{
return (x >> (p + 1 - n)) & ~(~0 << n);
}
Aplicație propusă 7. Folosind funcția getbits() de mai sus afișați bitul aflat într-o anumită poziție p dată
într-un număr natural x dat.
Aplicaţie rezolvată 9. Scrieţi o funcţie set0bit(n,b) care setează bitul b din numărul întreg n la 0.
#include <stdio.h>
int main()
{
unsigned n = 170; /* 0000000010101010 in baza 2*/
int b = 5;
return 0;
}
Aplicaţie rezolvată 10. Fie n și b două numere întregi. Scrieți o funcție care determină valoarea bitului b din
numărul întreg fără semn n.
#include <stdio.h>
int main()
{
unsigned n = 170; /* 0252 in baza 8 sau 0000000010101010 in baza 2*/
int b = 5;
return 0;
}
/* preia bitul b din n */
unsigned getbit(unsigned n, int b)
{
if( n & ( 1 << b ) )
return 1;
else
return 0;
}
Aplicaţie rezolvată 11. Scrieţi o funcţie set1bit(n,b) care setează bitul b din numărul întreg n la 1.
#include <stdio.h>
int main()
{
unsigned n = 170; /* 0000000010101010 in baza 2*/
int b = 2;
8
printf("%d ", set1bit(n, b) ); /* 174 = 0000000010001110 */
return 0;
}
Aplicație rezolvată 11. Scrieți două funcții getlast1(n, b) și getlast2(n, b)pentru găsirea valorii
ultimilor b biți din reprezentarea internă a unui număr întreg n folosind pentru prima funcție restul împărțirii lui
n la 2b, iar pentru a doua funcție expresia: n & ((1 << b) – 1).
#include <stdio.h>
unsigned getlast1(unsigned n, int b);
unsigned getlast2(unsigned n, int b);
int main()
{
unsigned n = 127; /* 0000000001111111 in baza 2*/
int b = 4;
Aplicaţie propusă 8*. Scrieţi o funcţie invert(x,p,n) care returnează pe x cu cei n biţi care încep la
poziţia p inversaţi (i.e. 1 schimbat în 0 şi 0 în 1), lăsând ceilalţi biţi nemodificaţi.
7. Operatori de atribuire
Operatorii binari au un operator de atribuire corespunzător op=, unde op este unul dintre operatorii:
+ - * / % << >> & ^ |
Funcţia bitcount de mai jos contorizează numărul de biţi 1 din întregul furnizat ca argument.
/* bitcount: count 1 bits in x */
int bitcount(unsigned x)
{
int b;
for (b = 0; x != 0; x >>= 1)
if (x & 01)
9
b++;
return b;
}
Aplicație rezolvată 12*. În sistemul de codificare a numerelor în complement față de 2, x &= (x-1) șterge
cel mai din dreapta bit 1 din x. Explicaţi de ce. Utilizați această observație pentru a scrie o versiune mai rapidă
pentru funcţia bitcount.
#include <stdio.h>
int main(void)
{
printf("%d\n", bitcount(01101101));
return 0;
}
8. Operatorul condiţional ?:
În expresia
expr1 ? expr2 : expr3
expresia expr1 este evaluată prima. Dacă ea este nenulă, este evaluată expr2 şi aceasta este valoarea expresiei
condiţionale. Altfel, este evaluată expr3 şi aceasta este valoarea expresiei condiţionale.
Aplicaţie propusă 9. Rescrieţi funcţia lower (vezi în continuare), care converteşte literele majuscule la litere
minuscule, folosind o expresie condiţională în locul lui if-else.
/* lower: convert c to lower case; ASCII only */
int lower(int c)
{
if (c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
else
return c;
}
FUNCŢIA DE CĂUTARE BINARĂ decide dacă o valoare particulară x apare în tabloul sortat crescător v.
/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */
int binsearch(int x, int v[], int n)
{
int low, high, mid;
low = 0;
high = n - 1;
while (low <= high) {
mid = (low+high)/2;
if (x < v[mid])
high = mid - 1;
else if (x > v[mid])
low = mid + 1;
else /* found match */
return mid;
10
}
return -1; /* no match */
}
Decizia (triplă) fundamentală este dacă x este mai mic decât, mai mare decât sau egal cu elementul din mijloc
v[mid] la fiecare pas al ciclului while.
Aplicaţie propusă 10. Scrieți un program care să apeleze funcția de căutare binară: binsearch.
Apoi observați că funcția prezentată mai sus realizează două teste în interiorul ciclului while deşi unul ar fi
suficient (cu preţul mai multor teste în afara ciclului). Încercați să scrieți și o versiune care să aibă doar un test
în interiorul ciclului (cu preţul că timpul de rulare creşte).
Aplicație propusă 11*. Scrieţi o funcţie escape(s,t) care converteşte caractere precum newline şi tab în
secvențe escape vizibile precum \n şi \t ca şi cum aţi copia şirul t în s. Utilizaţi o instrucţiune switch.
Apoi adăugaţi programului o funcţie care face operaţia inversă convertind secvenţele escape în caractere reale.
Indicație: Programul va citi cu o funcție getline liniile intrării până se dă un Ctrl+Z. Apoi șirul de caractere
citit va fi convertit. Instrucțiunea switch care converteşte un caracter din şirul de caractere t[] plasându-l în
şirul de caractere s[], substituind caracterele newline şi tab prin \n şi \t poate arăta ca mai jos:
switch (t[i]) {
case '\n':
s[j++] = '\\';
s[j++] = 'n';
break;
case '\t':
s[j++] = '\\';
s[j++] = 't';
break;
default:
s[j++] = t[i];
break;
}
REZOLVĂRI
Aplicaţie propusă 1. Folosind funcţia strlen furnizată, scrieţi un program care să afişeze lungimile unor şiruri
de caractere.
Varianta interactivă
#include <stdio.h>
main()
{
char s1[20], s2[20], c;
int i;
return 0;
}
11
/* strlen: return length of s */
int strlen(char s[])
{
int i;
i = 0;
while (s[i] != '\0')
++i;
return i;
}
Observație: Citirea celor două șiruri se face cu o secvență de cod similară, de aceea putem transforma această
secvență într-o funcție citestesir() pe care să o apelăm la nevoie:
#include <stdio.h>
main()
{
char s1[20], s2[20];
return 0;
}
i = 0;
while (s[i] != '\0')
++i;
return i;
}
main()
{
char s1[20] = "primul sir", s2[20] = "al doilea sir";
12
printf("\ns1 = \"%s\" are lungimea = %d\n", s1, strlen(s1));
printf("\ns2 = \"%s\" are lungimea = %d\n", s2, strlen(s2));
return 0;
}
i = 0;
while (s[i] != '\0')
++i;
return i;
}
Aplicație propusă 3. Scrieți un ciclu echivalent pentru ciclul for de mai jos
for (i=0; i < lim - 1 && (c = getchar()) != '\n' && c != EOF; ++i) s[i] = c;
#include <stdio.h>
int main(void)
{
char s[MAXLINE];
int c, i, j = 0, lim;
lim = MAXLINE;
for ( i = 0; i < lim - 1; ++j, ++i ) {
c = getchar();
if (c == '\n')
i = lim;
if (c == EOF)
i = lim;
s[j] = c;
}
s[++j] = '\0';
printf("%s\n", s);
return 0;
}
Aplicaţie propusă 4. Folosind modelul de la funcţia atoi(s) furnizată, scrieţi un program care conţine o
funcţie htoi(s), care converteşte un şir de cifre hexazecimale (şirul putând include opţional un 0x sau 0X) în
valoarea întreagă echivalentă. Cifrele permise sunt: 0 până la 9, a până la f şi A până la F.
#include <stdio.h>
int main(void)
{
int len;
char line[MAXLINE];
13
return 0;
}
return l;
}
Aplicație propusă 5. Folosind codul furnizat al unei implementări portabile a unui generator de numere
pseudo-aleatoare (rand) și al funcției pentru inițializarea sămânţei (srand) incluse în biblioteca standard, scrieți
un program care, pentru valori ale sămânței de la 1 la 10, generează numere pseudo-aleatoare între 0 și 32767.
#include <stdio.h>
int rand(void);
void srand(unsigned int seed);
int main()
{
int r, i;
return 0;
}
int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
14
void srand(unsigned int seed)
{
next = seed;
}
int main()
{
unsigned x = 077; /* 63 in baza 10*/;
int p = 4, n = 3;
return 0;
}
Aplicație propusă 7. Folosind funcția getbits() de mai sus afișați bitul aflat într-o anumită poziție p dată
într-un număr natural x dat.
#include <stdio.h>
int main()
{
unsigned x = 170; /* 0252 in baza 8 sau 0000000010101010 in baza 2 */;
int p = 5;
return 0;
}
Aplicaţie propusă 8. Scrieţi o funcţie invert(x,p,n) care returnează pe x cu cei n biţi care încep la poziţia
p inversaţi (i.e. 1 schimbat în 0 şi 0 în 1), lăsând ceilalţi biţi nemodificaţi.
#include <stdio.h>
int main(void)
{
printf("%u\n", invert(5732, 6, 3));
return 0;
}
// xxxxx^^^^^xxxxx
return x ^ mask;
}
Aplicație propusă 9. Rescrieţi funcţia lower furnizată, care converteşte literele majuscule la litere minuscule,
folosind o expresie condiţională în locul lui if-else.
#include <stdio.h>
int main(void)
{
char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i;
i = 0;
while (s[i] != '\0') {
printf("%c -> %c\n", s[i], lower(s[i]));
i++;
}
return 0;
}
int lower(int c)
{
return (c >= 'A' && c<= 'Z') ? c + 'a' - 'A' : c;
}
Aplicaţie propusă 10. Scrieți un program care să apeleze funcția de căutare binară: binsearch (furnizată).
Apoi observați că funcția furnizată realizează două teste în interiorul ciclului while deşi unul ar fi suficient (cu
preţul mai multor teste în afara ciclului). Încercați să scrieți și o versiune care să aibă doar un test în interiorul
ciclului (cu preţul că timpul de rulare creşte).
#include <stdio.h>
int main(void)
{
int i, x = 12, n = 10;
int v[10] = {2, 3, 7, 10, 11, 12, 15, 18, 20, 21};
printf("v = ");
for(i = 0; i< n; ++i)
printf(" %d ", v[i]);
printf("\n\n");
printf("pozitia in care se afla %d in v = %d\n", x, binsearch(x, v, n));
return 0;
}
low = 0;
high = n - 1;
while (low < high) {
mid = (low + high) / 2;
if (x <= v[mid])
high = mid;
16
else
low = mid + 1;
}
return (x == v[low]) ? low : -1;
}
Aplicaţie propusă 11. Scrieţi o funcţie escape(s,t) care converteşte caractere precum newline şi tab în
secvențe escape vizibile precum \n şi \t ca şi cum aţi copia şirul t în s. Utilizaţi o instrucţiune switch.
Apoi adăugaţi programului o funcţie care face operaţia inversă convertind secvenţele escape în caractere reale.
#include <stdio.h>
int main(void)
{
char t[MAXLINE];
char s1[MAXLINE];
char s2[MAXLINE];
escape(s1, t);
printf("\nconversie escape:\n%s\n", s1);
unescape(s2, s1);
printf("conversie inversa:\n%s\n", s2);
return 0;
}
return l;
}
18