Sunteți pe pagina 1din 18

PCLP. Laborator 5: Declarații. Operatori.

Controlul execuției programelor


TIPURI DE DATE
Exista numai câteva tipuri de date de bază în C.
char un singur octet, capabil să memoreze un caracter din codul ASCII
int un întreg, mărimea depinde de implementare, 16 sau 32 de biti
float simplă-precizie virgulă mobilă
double dublă-precizie virgulă mobilă
În plus, există un număr de calificatori care pot fi aplicați acestor tipuri de bază. short şi long se
aplică întregilor:
short int sh;
long int counter;

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 int este [%d, %d].\n\n", INT_MIN, INT_MAX);


printf("Domeniul lui unsigned int este [%u, %u].\n\n", 0, UINT_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';

Există şi o variantă neinteractivă prin iniţializarea cu


constante şir la declarare, astfel:
char s1[20] = "primul sir", s2[20] = "al doilea sir";

Atenţie la afişarea ghilimelelor (\”) în printf.

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);

2. Operatorii logici şi relaţionali

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;

fără să utilizaţi operatorii logici && sau ||.

3. Conversii între tipurile de date

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 get_line(char line[], int maxline);


int atoi(char s[]);

int main(void)
{
int len;
char line[MAXLINE];

while ((len = get_line(line, MAXLINE)) > 0)


printf("%lu\n", atoi(line));

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>

#define MAXLINE 1000

int get_line(char line[], int maxline);


int lower(int c);

int main(void)
{
int len, i = 0;
char line[MAXLINE];

while ((len = get_line(line, MAXLINE)) > 0)


while(line[i])
printf("%c", lower(line[i++]));

printf("\n");
return 0;
}

3
int get_line(char s[], int lim)
{
int c, i, l;

for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i)


if (i < lim - 1)
s[l++] = c;
s[l] = '\0';

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>.

Funcția get_line() nu se modifică, funcția lower() dispare, în rest iată programul:


#include <stdio.h>
#include <ctype.h>

#define MAXLINE 1000

int get_line(char line[], int maxline);

int main(void)
{
int len, i = 0;
char line[MAXLINE];

while ((len = get_line(line, MAXLINE)) > 0)


while(line[i])
printf("%c", tolower(line[i++]));

printf("\n");
return 0;
}

4. Operatorul unar cast

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;

/* rand: return pseudo-random integer on 0..32767 */


int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
4
}

/* srand: set seed for rand() */


void srand(unsigned int seed)
{
next = seed;
}

5. Operatorii de incrementare/decrementare

Limbajul C furnizează doi operatori pentru incrementarea și decrementarea variabilelor. Operatorul de


incrementare ++ adună 1 la operandul căruia i se aplică și operatorul de decrementare -- scade 1.
Aspectul neobișnuit este că ++ şi –- pot fi utilizați fie ca operatori prefixați (înaintea variabilei, ca în ++n), sau
ca operatori postfixaţi (după variabilă: n++). În ambele cazuri efectul este incrementarea lui n.
Aplicație rezolvată 6. Folosind funcția squeeze(s,c) prezentată în Cursul 5, care îndepărtează toate aparițiile
caracterului c din șirul s, scrieți un program care citește un șir de caractere și un caracter, apoi afișează șirul de
caractere dat fără caracterul citit.
void squeeze(char s[], int c)
{
int i, j;

for (i = j = 0; s[i] != '\0'; i++)


if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
Iată programul:
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

int get_line(char line[], int maxline);


void squeeze(char s[], int c);

int main()
{
int c, len;
char line[MAXLINE];

printf("sirul de caractere : ");


get_line(line, MAXLINE);
printf("caracterul de eliminat : "); c = getchar();

squeeze(line, c);

printf("sirul ramas : %s\n", line);

return 0;
}

int get_line(char s[], int lim)


{
int c, i, l;

for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i)


if (i < lim - 1)
s[l++] = c;
s[l] = '\0';

return l;
}

/* squeeze: delete all c from s */


void squeeze(char s[], int c)
{
5
int i, j;

for (i = j = 0; s[i] != '\0'; i++)


if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}

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 get_line(char line[], int maxline);


void strcat(char s[], char t[]);

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);

printf("sirul s concatenat cu t : %s\n", s);

return 0;
}

int get_line(char s[], int lim)


{
int c, i, l;

for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i)


if (i < lim - 1)
s[l++] = c;
s[l] = '\0';

return l;
}

/* 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++;
6
while ((s[i++] = t[j++]) != '\0')
; /* copy t */
}

6. Operatori pe biţi

Limbajul C furnizează şase operatori pentru manipularea biţilor:


& operatorul ŞI logic pe biţi
| operatorul SAU (SAU-inclusiv) logic pe biţi
^ operatorul XOR (SAU-exclusiv) logic pe biţi
<< deplasare la stânga
>> deplasare la dreapta
~ complement faţă de unu (operator unar)
Tabele de adevăr: & 0 1 | 0 1 ^ 0 1
0 0 0 0 0 1 0 0 1
1 0 1 1 1 1 1 1 0
Operatorii de deplasare pe biţi << şi >> deplasează la stânga sau la dreapta biţii operandului din stânga
operatorului cu un număr de poziţii dat de operandul din dreapta.
Operatorul unar ~ (tilda) este operatorul pentru complement faţă de unu. El converteşte fiecare bit 1 la 0
şi invers. Ca o ilustrare a modului în care sunt folosiţi operatorii pe biţi, să considerăm funcţia getbits(x,p,n)
care returnează (aliniaţi la dreapta) o secvenţă de n biţi din x care încep la poziţia p. Vom presupune că cel mai
puţin semnificativ bit din x (cel mai din dreapta) este în poziţia 0 şi că n şi p sunt valori pozitive. De exemplu,
getbits(x,4,3) returnează cei trei biţi din poziţiile 4, 3 şi 2, aliniaţi la dreapta.

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>

unsigned getbits(unsigned x, int p, int n);

int main()
{
unsigned x = 170; /* 0252 in baza 8 sau 0000000010101010 in baza 2*/
int p1 = 7, p2 = 5;

printf("%d ", getbits(x, p1, p1 - p2 + 1) );/* se afiseaza 5 adica 101 */

return 0;
}

/* getbits: get n bits from position p */


unsigned getbits(unsigned x, int p, int n)

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.

Indicație. În main() funcția printf afișează getbits(x, p, 1).

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>

unsigned set0bit(unsigned n, int b);

int main()
{
unsigned n = 170; /* 0000000010101010 in baza 2*/
int b = 5;

printf("%d ", set0bit(n, b) ); /* 138 = 0000000010001010 */

return 0;
}

/* pune pe 0 bitul b din n */


unsigned set0bit(unsigned n, int b)
{
return (n & ~(1 << b));
}

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>

unsigned getbit(unsigned n, int b);

int main()
{
unsigned n = 170; /* 0252 in baza 8 sau 0000000010101010 in baza 2*/
int b = 5;

for( b = 15; b >=0; --b )


printf("%d ", getbit(n, b) );

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>

unsigned set1bit(unsigned n, int b);

int main()
{
unsigned n = 170; /* 0000000010101010 in baza 2*/
int b = 2;

8
printf("%d ", set1bit(n, b) ); /* 174 = 0000000010001110 */

return 0;
}

/* pune pe 1 bitul b din n */


unsigned set1bit(unsigned n, int b)
{
return (n | (1 << b));
}

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;

printf("%d ", getlast1(n, b) ); /* 15 = 1111 */


printf("%d ", getlast2(n, 6) ); /* 63 = 111111 */
return 0;
}
/* furnizeaza ultimii b biti din n */
unsigned getlast1(unsigned n, int b)
{
return n & ( (1 << b) - 1 );
}
/* furnizeaza ultimii b biti din n */
unsigned getlast2(unsigned n, int b)
{
return n % (1 << b); /* 1 << b: ridica pe 2 la b*/
}

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.

< ----- n ----- >


p
Poziţie 12 11 10 9 8 7 6 5 4 3 2 1 0
X 1 0 1 1 0 0 1 1 0 0 1 0 0 p = 6, n = 3 x = 5732
invert(x,6,3) 1 0 1 1 0 0 0 0 1 0 0 1 1 invert(x,6,3) = 5652

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 bitcount(unsigned x);

int main(void)
{
printf("%d\n", bitcount(01101101));
return 0;
}

/* bitcount: numara bitii 1 din x */


int bitcount(unsigned x)
{
int b;

for (b = 0; x != 0; x &= (x - 1))


b++;
return b;
}

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>

int strlen(char s[]);

main()
{
char s1[20], s2[20], c;
int i;

printf("\n Introduceti primul sir : ");


i = 0;
while ((c = getchar()) != '\n')
s1[i++] = c;
s1[i]='\0';

printf("\n Introduceti al 2-lea sir : ");


i = 0;
while ((c = getchar()) != '\n')
s2[i++] = c;
s2[i]='\0';

printf("\ns1 = \"%s\" are lungimea s1 = %d\n", s1, strlen(s1));


printf("\ns2 = \"%s\" are lungimea s2 = %d\n", s2, strlen(s2));

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>

int strlen(char s[]);


void citestesir(char s[]);

main()
{
char s1[20], s2[20];

printf("\n Introduceti primul sir : ");


citestesir(s1);

printf("\n Introduceti al 2-lea sir : ");


citestesir(s2);

printf("\ns1 = \"%s\" are lungimea s1 = %d\n", s1, strlen(s1));


printf("\ns2 = \"%s\" are lungimea s2 = %d\n", s2, strlen(s2));

return 0;
}

/* strlen: intoarce lungimea lui s */


int strlen(char s[])
{
int i;

i = 0;
while (s[i] != '\0')
++i;
return i;
}

/* citestesir: citeste un sir de caractere */


void citestesir(char s[])
{
int i = 0;
char c;

while ((c = getchar()) != '\n')


s[i++] = c;
s[i]='\0';
}

Aplicaţie propusă 1. Varianta ne-interactivă


#include <stdio.h>

int strlen(char s[]);

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;
}

/* strlen: return length of s */


int strlen(char s[])
{
int i;

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;

fără să utilizați operatorii logici && sau ||.

#include <stdio.h>

#define MAXLINE 1000

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>

#define MAXLINE 1000

int get_line(char line[], int maxline);


unsigned long htoi(char s[]);

int main(void)
{
int len;
char line[MAXLINE];

while ((len = get_line(line, MAXLINE)) > 0)


printf("%lu\n", htoi(line));

13
return 0;
}

int get_line(char s[], int lim)


{
int c, i, l;

for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i)


if (i < lim - 1)
s[l++] = c;
s[l] = '\0';

return l;
}

unsigned long htoi(char s[])


{
unsigned long n = 0;
int i = 0;

if ( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' ) )


i = 2;
for (; s[i]; ++i) {
if ( isdigit(s[i]) ){
n *= 16;
n += s[i] - '0';
}
else if (s[i] >= 'a' && s[i] <= 'f') {
n *= 16;
n += s[i] - 'a' + 10;
}
else if (s[i] >= 'A' && s[i] <= 'F') {
n *= 16;
n += s[i] - 'A' + 10;
}
}
return n;
}

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);

unsigned long int next = 1;

int main()
{
int r, i;

for ( i = 1; i < 10; ++i ){


srand(i);
printf("samanta = %d, nr aleator = %d\n", i, rand() );
}

return 0;
}

int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}

14
void srand(unsigned int seed)
{
next = seed;
}

Aplicație propusă 6. Integrați codul funcției getbits() furnizate într-un program.


#include <stdio.h>

unsigned getbits(unsigned x, int p, int n);

int main()
{
unsigned x = 077; /* 63 in baza 10*/;
int p = 4, n = 3;

printf("%d ", getbits(x, p, n));

return 0;
}

/* getbits: get n bits from position p */


unsigned getbits(unsigned x, int p, int n)
{
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.
#include <stdio.h>

unsigned getbits(unsigned x, int p, int n);

int main()
{
unsigned x = 170; /* 0252 in baza 8 sau 0000000010101010 in baza 2 */;
int p = 5;

printf("%d ", getbits(x, p, 1) );

return 0;
}

/* getbits: get n bits from position p */


unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p + 1 - n)) & ~(~0 << n);
}

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>

unsigned invert(unsigned x, int p, int n);

int main(void)
{
printf("%u\n", invert(5732, 6, 3));
return 0;
}

unsigned invert(unsigned x, int p, int n)


{
// 000001111100000
15
unsigned mask = ~(~0U << n) << (p + 1 - n);

// 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 lower(int c);

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 binsearch(int x, int v[], int n);

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;
}

/* 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;

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>

#define MAXLINE 1000

int getchars(char line[], int maxline);


void escape(char s[], char t[]);
void unescape(char s[], char t[]);

int main(void)
{
char t[MAXLINE];
char s1[MAXLINE];
char s2[MAXLINE];

printf("Introduceti caractere cu tab si Enter , finalizare Ctrl+Z:\n");


while (getchars(t, MAXLINE) == 0)
;

escape(s1, t);
printf("\nconversie escape:\n%s\n", s1);

unescape(s2, s1);
printf("conversie inversa:\n%s\n", s2);

return 0;
}

int getchars(char s[], int lim)


{
int c, i, l;

for (i = 0, l = 0; (c = getchar()) != EOF; ++i)


if (i < lim - 1)
s[l++] = c;
s[l] = '\0';

return l;
}

void escape(char s[], char t[])


{
int i, j;

for (i = 0, j = 0; t[i] != '\0'; ++i) {


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;
}
17
}
s[j] = '\0';
}

void unescape(char s[], char t[])


{
int i, j;

for (i = 0, j = 0; t[i] != '\0'; ++i) {


if (t[i] == '\\') {
switch (t[++i]) {
case 'n':
s[j++] = '\n';
break;
case 't':
s[j++] = '\t';
break;
case '\0':
default:
s[j++] = '\\';
--i;
break;
}
} else {
s[j++] = t[i];
}
}
s[j] = '\0';
}

18

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