PCLP Laborator 6 PDF

Descărcați ca pdf sau txt
Descărcați ca pdf sau txt
Sunteți pe pagina 1din 21

PCLP. Laborator 6: Controlul execuției programelor.

Proiecte în code blocks


Aplicație rezolvată 1. Scrieți o funcție atoi() pentru conversia unui șir de caractere la echivalentul său
numeric. Funcția se va aplica și la șiruri prefixate de spații albe, sau care prezintă semnul + sau -. Integrați
funcția într-un program.
#include <stdio.h>
/* atoi: convert s to integer */
#include <ctype.h>
int atoi(char s[])
{
int atoi(char s[]);
int i, n, sign;
int main()
for (i = 0; isspace(s[i]); i++)
{
; /* skip white space */
printf("%d\n", atoi(" -23"));
sign = (s[i] == '-') ? -1 : 1;
printf("%d\n", atoi(" +145"));
if (s[i] == '+' || s[i] == '-')
i++; /* skip sign */
return 0;
for (n = 0; isdigit(s[i]); i++)
}
n = 10 * n + (s[i] - '0');

return sign * n;
}

Aplicație rezolvată 2. Scrieți o funcție itoa() care convertește un număr întreg la un șir de caractere. Integrați
funcția într-un program.
Indicații: Cea mai ușoară metodă de a genera cifre nu le generează în ordinea corectă, ci inversată pentru că
folosește operațiile %10 pentru extragerea ultimei cifre și /10 pentru eliminarea ultimei cifre din număr.
Funcția construiește șirul inversat extrăgând cifrele numărului de la cea mai puțin semnificativă la cea mai
semnificativă și apoi inversează șirul.
/* itoa: convert n to characters in s */ /* reverse: reverse string s in place */
void itoa(int n, char s[]) void reverse(char s[])
{ {
int i, sign; int c, i = 0, j = strlen(s)-1;

if ((sign = n) < 0) /* record sign */ for (; i < j; i++, j--)


n = -n; /* make n positive */ c = s[i], s[i] = s[j], s[j] = c;
}
i = 0;
#include <stdio.h>
do { /* generate digits in reverse order */ #include <string.h>
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */ void itoa(int n, char s[]);
void reverse(char s[]);
if (sign < 0)
s[i++] = '-'; int main()
{
s[i] = '\0'; char s[10];

reverse(s); itoa(-23,s); printf("%s\n", s);


} itoa(+145,s); printf("%s\n", s);

return 0;
}

Aplicație rezolvată 3. Scrieți o funcție trim() care șterge blank-urile, tab-urile şi newline-urile de la
sfârșitul unui șir de caractere. Integrați funcția într-un program.
/* trim: remove trailing blanks, tabs, newlines */
int trim(char s[])
{
int n;

for (n = strlen(s)-1; n >= 0; n--)


if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')
break;
s[n + 1] = '\0';
return n + 1;
1
}

#include <stdio.h>
#include <string.h>

int trim(char s[]);

int main()
{
char s[10] = "abc\n\t ";
int n;

n = strlen(s);
printf("sirul initial = %s are lungimea = %d \n", s, n);
n = trim(s);
printf("sirul dupa eliminarea spatiilor albe = %s are lungimea = %d \n", s, n);

return 0;
}

Aplicație rezolvată 4. Scrieți o funcție trim1() care șterge blank-urile, tab-urile şi newline-urile de la
începutul unui șir de caractere. Integrați funcția într-un program.
Inversăm șirul, folosim funcția trim() anterioară și apoi inversăm din nou șirul.
/* trim1: remove blanks, tabs, newlines */
/* reverse: reverse string s in
int trim1(char s[])
place */
{
void reverse(char s[])
int n;
{
int c, i = 0, j = strlen(s)-1;
reverse(s);
for (; i < j; i++, j--){
for (n = strlen(s)-1; n >= 0; n--)
c = s[i];
if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')
s[i] = s[j];
break;
s[j] = c;
s[n + 1] = '\0';
}
reverse(s);
}
return n + 1;
}

#include <stdio.h>
#include <string.h>

int trim1(char s[]);


void reverse(char s[]);

int main()
{
char s[10] = "\n\t abc";
int n;

n = strlen(s);
printf("sirul initial = %s are lungimea = %d \n", s, n);
n = trim1(s);
printf("sirul dupa eliminarea spatiilor albe = %s are lungimea = %d \n", s, n);

return 0;
}

Aplicație rezolvată 5. Scrieți un program care determină dacă două tablouri unidimensionale a[] şi b[] au un
element în comun.
# include <stdio.h>

int main()
{

2
int found = 0, i, j, n = 5, m = 5, a[10] = {1, -2, 5, 8, 7}, b[7] = {2, 9, -1, 4, 8};

for (i = 0; i < n && !found; i++)


for (j = 0; j < m && !found; j++)
if (a[i] == b[j])
found = 1;
if (found)
printf("Am gasit a[%d] = %d == b[%d] = %d\n", i-1, a[i-1], j-1, b[j-1]);
else
printf("Nu am gasit niciun element comun\n");

return 0;
}

Aplicație rezolvată 6. Scrieți un program care determină dacă două tablouri unidimensionale a[] şi b[] au un
element în comun folosind o funcție care returnează poziția din tabloul a[] unde a fost găsit primul element
comun sau -1 (valoare care nu poate fi indexul niciunui element din tablou) dacă tablourile nu au niciun
element comun.
#include <stdio.h>

int findequal(int a[], int na, int b[], int nb);

int main()
{
int i, na = 5, nb = 5, a[10] = {1, -2, 5, 8, 7}, b[7] = {2, 9, -1, 4, 8};

i = findequal(a, na, b, nb);


if ( i == -1 )
printf("Nu am gasit niciun element comun\n");
else
printf("Am gasit comun elementul a[%d] cu valoarea %d\n", i, a[i]);

return 0;
}

/* return i such that a[i] == b[j] for some j, or -1 if none */


int findequal(int a[], int na, int b[], int nb)
{
int i, j;
for(i = 0; i < na; i++)
for(j = 0; j < nb; j++)
if(a[i] == b[j])
return i;
return -1;
}

Aplicație rezolvată 7. Având corect scrisă şi declarată funcţia atof() care convertește un șir de caractere la
numărul real corespunzător, putem scrie pe baza ei o funcţie atoi() care converteşte un şir de caractere la
numărul întreg corespunzător, astfel:
#include <ctype.h> /* atoi:convert string s to integer using atof */
int atoi(char s[])
/* atof: convert string s to double */ {
double atof(char s[]) double atof(char s[]);
{
double val, power; return (int) atof(s);
int i, sign; }
for (i = 0; isspace(s[i]); i++)
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
3
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
power *= 10;
}
return sign * val / power;
}

Scrieți un program care folosește funcția atoi().


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

int atoi(char s[]);


double atof(char s[]);

int main()
{
printf("%d\n", atoi(" -123"));
return 0;
}

Aplicație propusă 1*. Scrieţi o funcţie expand(s1,s2) care expandează notaţiile prescurtate cum ar fi a-z
din şirul de caractere s1 într-o listă echivalentă completă abc...xyz memorată în şirul de caractere s2.
Funcţia va lucra cu majuscule, minuscule şi cifre şi va trebui să gestioneze şi cazuri de forma a-b-c, a-z0-9 şi
-a-z. Un semn – aflat la începutul şirului sau la finalul acestuia va fi interpretat ca un caracter simplu, nu ca un
substituent pentru „de la … până la …” (vezi şi figura).

Indicaţii: În main() se va citi un şir de caractere


reprezentând notaţii prescurtate apelând o funcţie
care citeşte o linie de caractere de pe intrare, apoi se
va apela o funcţie expand() care va primi pe intrare
un şir de caractere reprezentând notaţii prescurtate şi
va returna un şir de caractere care va conţine
expandarea şirului primit pe intrare. Funcţia
expand() poate arăta ca mai jos:
void expand(char s1[], char s2[])
{
int i, j, k;
int c;

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


if (s1[i+1] == '-' && (c = s1[i+2]) != '\0' &&
(('a' <= s1[i] && s1[i] <= 'z' && s1[i] <= c && c <= 'z') ||
('A' <= s1[i] && s1[i] <= 'Z' && s1[i] <= c && c <= 'Z') ||
('0' <= s1[i] && s1[i] <= '9' && s1[i] <= c && c <= '9'))) {
k = 0;
while (k <= c - s1[i])
s2[j++] = s1[i] + k++;
i += 2;
} else {
s2[j++] = s1[i];
}
}
s2[j] = '\0';
}

Aplicaţie propusă 2*. Scrieţi funcţia itob(n,s,b) care converteşte întregul n într-o bază b reprezentându-l
sub forma unui şir de caractere s. În particular, itob(n,s,16) îl scrie pe n ca un număr întreg hexazecimal în
şirul de caractere s.
Indicaţii: În main() se va apela funcţia itob() care la rândul său apelează funcţia reverse() (vezi Cursul 6)
pentru inversarea unui şir. Iată mai jos aceste funcţii:
void itob(int n, char s[], int b)

4
{
int i, sign, rest;
char baze[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

if (b < 2 || b > 36)


return;

sign = n;
i = 0;
do {
rest = n % b;
s[i++] = ((sign < 0) ? baze[-rest] : baze[rest]);
} while (n /= b);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}

void reverse(char s[])


{
int i, j;
int tmp;

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


;
--j;

for (i = 0; i < j; ++i, --j) {


tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

Aplicație propusă 3*. Scrieţi o versiune a funcţiei itoa (care converteşte un număr la un şir de caractere, vezi
Cursul 6) care acceptă trei argumente în loc de două. Al treilea argument este mărimea minimă a câmpului de
reprezentare a numărului; numărul convertit la şir de caractere trebuie să fie completat cu blank-uri la stânga
dacă este necesar pentru a-l face suficient de mare pentru a încăpea în mărimea minimă a câmpului de
reprezentare (vezi figura).
Indicaţii: În main() se va apela
funcţia itoa() care la rândul său
apelează funcţia reverse() pentru
inversarea unui şir. Iată mai jos
funcţia itoa():
void itoa(int n, char s[], int w)
{
int i, sign, rest, k, j;

sign = n;
i = 0;
do {
rest = n % 10;
s[i++] = ((sign < 0) ? -rest : rest) + '0';
} while (n /= 10);
if (sign < 0)
s[i++] = '-';

while (i < w) /* completarea cu spatii in fata numarului convertit la sir */


s[i++] = ' ';

s[i] = '\0';
reverse(s);
}

5
Aplicație rezolvată 8. Programul următor afișează fiecare linie de pe intrare care conține un model (pattern)
particular reprezentat de un şir de caractere (”to”).
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int max);


int strindex(char source[], char searchfor[]);

char pattern[] = "to"; /* pattern to search for */

/* find all lines matching pattern */


int main()
{
char line[MAXLINE];
int found = 0;

while (getline(line, MAXLINE) > 0)


if (strindex(line, pattern) >= 0) {
printf("%s", line);
found++;
}

return found;
}

/* getline: get line into s, return length */


int getline(char s[], int lim)
{
int c, i;

i = 0;
while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';

return i;
}

/* strindex: return index of t in s, -1 if none */


int strindex(char s[], char t[])
{
int i, j, k;

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


for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++)
;
if (k > 0 && t[k] == '\0')
return i;
}

return -1;
}

Aplicație propusă 4. Rescrieți funcția strrindex(s,t) care să returneze poziția celei mai din dreapta apariții a
șirului de caractere t în șirul de caractere s, sau -1 dacă șirul t nu apare deloc în șirul s. Vezi imaginea.

6
PROIECTE ÎN code blocks
Mecanismul prin care se compilează și se încarcă un program care rezidă în mai multe fișiere sursă variază de
la un sistem la altul.
Aplicație propusă 5. Conform indicaţiilor următoare va trebui să construim o aplicație cu programul sursă
format din trei fișiere numite main.c, getline.c şi strindex.c în care vom plasa cele trei funcții. Vom construi un
proiect cu cele trei fișiere.
În Code blocks procedăm astfel:

Pasul 1: Alegem File-> New -> Project

Pasul 2: Apare o fereastră de dialog din care


selectăm Console Application şi apoi click pe
butonul Go

Pasul 3: Click pe butonul Next, apoi alegem limbajul C şi click pe


Next

Pasul 4: Completăm titlul proiectului şi selectăm folderul unde dorim


să fie salvat, apoi dăm Next.

Pasul 5: Apare o nouă fereastră de dialog. Click pe butonul Finish.

Pasul 6: Alegem File -> New -> Empty File şi apare o casetă de dialog.
Facem click pe butonul Yes.

Pasul 7: Apare o casetă de dialog în care ni se cere să dăm numele primului fişier sursă, alegem main.c şi
salvăm

7
Pasul 8: Apare o casetă de dialog (Multiple selection), dăm click pe butonul
OK.

Pasul 9: Scriem codul funcţiei main, apoi salvăm.

Pasul 10: Repetăm procedeul


şi pentru celelalte două funcţii
getline (adăugând linia
#include <stdio.h> pentru
a recunoaşte constanta EOF) şi
strindex.

Pasul 11: Apoi compilăm şi rulăm proiectul (click pe butoanele Buid şi Run).

Aplicație propusă 6. Scrieți un proiect care citește un număr pe linie, precedat opțional de un semn și-l adună
la toate numerele anterioare, tipărind suma după fiecare intrare folosind trei fișiere sursă:
1. getline.c pe baza funcției getline()definită mai sus
2. main.c şi atof.c pe baza funcțiilor definite în continuare:
#include <stdio.h>
#define MAXLINE 100

/* rudimentary calculator */
int main()
{
double sum, atof(char []);
char line[MAXLINE];
int getline(char line[], int max);

sum = 0;
while (getline(line, MAXLINE) > 0)
printf("\t%g\n", sum += atof(line));
return 0;
}

#include <ctype.h>
/* atof: convert string s to double */
double atof(char s[])
{
double val, power;
int i, sign;

for (i = 0; isspace(s[i]); i++) /* skip white space */


8
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
power *= 10;
}
return sign * val / power;
}

Aplicaţie rezolvată 9*. Extindeţi funcţia atof astfel încât ea să recunoască şi să convertească şi notaţia
ştiinţifică de forma:
123.45e-6 (reprezentând numărul 123.45*10-6)

în care un număr real virgulă mobilă poate fi urmat de e sau E şi de un exponent cu semn. Apoi scrieţi
programul complet care primind pe intrare un şir de caractere reprezentând un număr real virgulă mobilă fie în
notaţie ştiinţifică, fie cu punct zecimal îl converteşte în număr real în reprezentarea cu parte întreagă, punct
zecimal şi parte fracţionară.
#include <stdio.h>
#include <ctype.h>

#define MAXLINE 1000

int getchars(char s[], int max);


double atof(char s[]);
int main(void)
{
char s[MAXLINE];
printf("Dati nr real cu punct zecimal sau in notatie stiintifica, apoi Enter:\n");
while (getchars(s, MAXLINE) == 0)
;

printf("Numarul este: %lf\n", atof(s));


return 0;
}

int getchars(char s[], int max)


{
int c, i, l;

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


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

/* atof: converteste un sir s la double */


double atof(char s[])
{
double val, power, base, epower;
int i, sign, exponent;

for (i = 0; isspace(s[i]); i++) /* sare spatiile albe */


;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
9
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
power *= 10;
}
epower = 1;
if (s[i] == 'e' || s[i] == 'E') {
i++;
base = s[i] == '-' ? 0.1 : 10.0;
if (s[i] == '-' || s[i] == '+')
i++;
for (exponent = 0; isdigit(s[i]); i++) {
exponent = 10 * exponent + (s[i] - '0');
}
while (exponent-- > 0)
epower *= base;
}
return sign * val / power * epower;
}

Aplicație rezolvată 10*. Extindeți programul calculator prezentat la Cursul 6,


adăugând operatorul modulo (%) - pentru calcularea restului împărțirii a două numere
întregi - și posibilitatea de a lucra cu numere negative.
#include <stdio.h>
#include <stdlib.h> /* pentru atof() */
#include <math.h>

#define MAXLINE 1000


#define MAXOP 100 /* dimensiunea maxima a unui operand sau a unui operator */
#define NUMBER '0' /* semnal ca a fost gasit un numar */

int getop(char []);


void push(double);
double pop(void);

int main(void)
{
int type;
double op2;
char s[MAXOP];

while ((type = getop(s)) != EOF) {


switch (type) {
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("eroare: impartire la zero\n");
break;
case '%':
op2 = pop();
if (op2 != 0.0)
push(fmod(pop(), op2));
10
else
printf("eroare: impartire la zero\n");
break;
case '\n':
printf("= %g\n", pop());
break;
default:
printf("eroare: comanda necunoscuta %s\n", s);
break;
}
}
return 0;
}

#define MAXVAL 100 /* adancimea maxima a stivei */

int sp = 0; /* urmatoarea pozitie libera in stiva */


double val[MAXVAL]; /* stiva cu valori */

/* push: pune f pe stiva cu valori */


void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("eroare: stiva plina, push imposibil%g\n", f);
}

/* pop: scoate si returneaza valoare din varful stivei */


double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("eroare: stiva vida\n");
return 0.0;
}
}

#include <ctype.h>
int getch(void);
void ungetch(int);
/* getop: preia urmatorul caracter sau un operand numeric */
int getop(char s[])
{
int i, c, c2;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.' && c != '-')
return c; /* nu este numar */
i = 0;
if (c == '-') {
c2 = getch();
if (c2 != EOF)
ungetch(c2);
if (!isdigit(c2) && c2 != '.')
return c;
}
if (isdigit(c) || c == '-') /* colecteaza partea intreaga */
while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /* colecteaza partea fractionara */
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';

11
if (c != EOF)
ungetch(c);
return NUMBER;
}
#define BUFSIZE 100

char buf[BUFSIZE]; /* bufer pentru ungetch */


int bufp = 0; /* urmatoarea pozitie libera in buf */
int getch(void) /* preia un posibil caracter pus inapoi */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) /* pune caracterul inapoi in intrare */


{
if (bufp >= BUFSIZE)
printf("ungetch: prea multe caractere\n");
else
buf[bufp++] = c;
}

Aplicație rezolvată 11*. Adăugați programului


calculator comenzi pentru:
 afișarea elementelor din vârful stivei fără a apela
funcția pop,
 duplicarea elementului din vârful stivei,
 interschimbarea cele două elemente din vârful stivei și
 golirea stivei (vezi imaginea).
#include <stdio.h>
#include <stdlib.h> /* pentru atof() */
#include <math.h>

#define MAXLINE 1000


#define MAXOP 100 /* dimensiunea maxima a unui
operand sau a unui operator */
#define NUMBER '0' /* semnal ca a fost gasit
un numar */

int getop(char []);


void push(double);
double pop(void);
void printtop(void);
void printstiva(void);
void duplicate(void);
void swap(void);
void clear(void);

int main(void)
{
printf("pun -3.981 in stiva\n");
push(-3.981);
printf("\n stiva=\n");
printstiva();
printf("\n pun 44.152 in stiva\n");
push(44.152);
printf("\n stiva=\n");
printstiva();
printf("\n interschimb cele 2 elemente din varful stivei\n");
swap();
printf("\n stiva=\n");
printstiva();
printf("\n duplic elementul din varful stivei\n");
duplicate();
printf("\n stiva=\n");
printstiva();
12
printf("\n elementul din varful stivei=\n" );printtop();
printf("\n golesc stiva\n" );
clear();
printf("\n elementul din varful stivei=\n" );printtop();
printf("\n stiva=\n");
printstiva();
return 0;
}
#define MAXVAL 100 /* adancimea maxima a stivei */
int sp = 0; /* urmatoarea pozitie libera in stiva */
double val[MAXVAL]; /* stiva cu valori */
/* push: pune f pe stiva cu valori */
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}

/* pop: scoate si returneaza valoare din varful stivei */


double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}

/* printtop: afiseaza elementul din varful stivei */


void printtop(void)
{
if (sp > 0)
printf("%g\n", val[sp - 1]);
else
printf("eroare: stiva vida\n");
}
/* printstiva: afiseaza stivei */
void printstiva(void)
{
int i;
if (sp > 0)
for (i = sp - 1; i >= 0; --i)
printf("%g\n", val[i]);
else
printf("eroare: stiva vida\n");
}
/* duplicate: duplica elementul din varful stivei */
void duplicate(void)
{
double top = pop();
push(top);
push(top);
}

/* swap: interschimba cele doua elemente din varful stivei */


void swap(void)
{
double top1 = pop();
double top2 = pop();
push(top1);
push(top2);
}

13
/* clear: curata stiva */
void clear(void)
{
sp = 0;
}

Aplicație propusă 7*. Adăugați la programul calculator posibilitatea calculării unor funcții precum sinus,
exponențială şi putere pe baza accesului la funcțiile de bibliotecă sin, exp şi pow (pentru ele utilizați
<math.h>).

Indicații: Singurele funcţii care se modifică sunt main şi getop. În plus, apare o constantă MATHLIB pentru a
semnaliza apariția uneia din funcțiile de bibliotecă sin, exp şi pow.
#include <math.h>
#include <string.h>
#define MATHLIB '1' /* semnal ca se apeleaza o functie din biblioteca math.h */

int getop(char []);


void push(double);
double pop(void);

int main(void)
{
int type;
double op2;
char s[MAXOP];

while ((type = getop(s)) != EOF) {


switch (type) {
case NUMBER:
push(atof(s));
break;
case MATHLIB:
if (strcmp(s, "sin") == 0)
push(sin(pop()));
else if (strcmp(s, "cos") == 0)
push(cos(pop()));
else if (strcmp(s, "pow") == 0) {
op2 = pop();
push(pow(pop(), op2));
} else
printf("eroare: comanda necunoscuta %s\n", s);
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("eroare: impartire la zero\n");
break;
case '%':
op2 = pop();
if (op2 != 0.0)
push(fmod(pop(), op2));
else
printf("eroare: impartire la zero \n");
break;
case '\n':
14
printf("= %g\n", pop());
break;
default:
printf("eroare: comanda necunoscuta %s\n", s);
break;
}
}

return 0;
}
#include <ctype.h>

int getch(void);
void ungetch(int);

int getop(char s[])


{
int i, c, c2;

while ((s[0] = c = getch()) == ' ' || c == '\t')


;
s[1] = '\0';

i = 0;
if (isalpha(c)) {
while (isalpha(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return MATHLIB;
}

if (!isdigit(c) && c != '.' && c != '-')


return c;
if (c == '-') {
c2 = getch();
if (c2 != EOF)
ungetch(c2);
if (!isdigit(c2) && c2 != '.')
return c;
}
if (isdigit(c) || c == '-')
while (isdigit(s[++i] = c = getch()))
;
if (c == '.')
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}

REZOLVĂRI
Aplicaţie propusă 1. Scrieţi o funcţie expand(s1,s2) care expandează notaţiile prescurtate cum ar fi a-z din
şirul de caractere s1 într-o listă echivalentă completă abc...xyz memorată în şirul de caractere s2. Funcția va
lucra cu majuscule, minuscule şi cifre şi va trebui să gestioneze şi cazuri de forma a-b-c, a-z0-9 şi -a-z. Un
semn – aflat la începutul şirului sau la finalul acestuia va fi interpretat ca un caracter simplu, nu ca un
substituent pentru „de la … până la …”
#include <stdio.h>

#define MAXLINE 1000

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


15
void expand(char s1[], char s2[]);

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

printf("Introduceti intervale de caractere(litere cifre):\n");


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

expand(s1, s2);
printf("\nRezultatul expandarii:\n%s\n", s2);

return 0;
}

int getchars(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;
}

void expand(char s1[], char s2[])


{
int i, j, k;
int c;

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


if (s1[i+1] == '-' && (c = s1[i+2]) != '\0' &&
(('a' <= s1[i] && s1[i] <= 'z' && s1[i] <= c && c <= 'z') ||
('A' <= s1[i] && s1[i] <= 'Z' && s1[i] <= c && c <= 'Z') ||
('0' <= s1[i] && s1[i] <= '9' && s1[i] <= c && c <= '9'))) {
k = 0;
while (k <= c - s1[i])
s2[j++] = s1[i] + k++;
i += 2;
} else {
s2[j++] = s1[i];
}
}
s2[j] = '\0';
}

Aplicație propusă 2. Scrieți funcția itob(n,s,b) care convertește întregul n într-o bază b reprezentându-l sub
forma unui șir de caractere s. În particular, itob(n,s,16) îl scrie pe n ca un număr întreg hexazecimal în șirul
de caractere s.
#include <stdio.h>
#include <limits.h>

#define MAXLINE 1000

void itob(int n, char s[], int b);


void reverse(char s[]);

int main(void)
{
char s[MAXLINE];

itob(1487, s, 16);
printf("%d in baza %d este %s.\n", 1487, 16, s);
16
itob(-2093, s, 16);
printf("%d in baza %d este %s.\n", -2093, 16, s);

return 0;
}

void itob(int n, char s[], int b)


{
int i, sign, rest;
char baze[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

if (b < 2 || b > 36)


return;

sign = n;
i = 0;
do {
rest = n % b;
s[i++] = ((sign < 0) ? baze[-rest] : baze[rest]);
} while (n /= b);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}

void reverse(char s[])


{
int i, j;
int tmp;

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


;
--j;

for (i = 0; i < j; ++i, --j) {


tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

Aplicație propusă 3. Scrieți o versiune a funcției itoa (care convertește un număr la un șir de caractere) care
acceptă trei argumente în loc de două. Al treilea argument este mărimea minimă a câmpului de reprezentare a
numărului; numărul convertit la șir de caractere trebuie să fie completat cu blank-uri la stânga dacă este necesar
pentru a-l face suficient de mare pentru a încăpea în mărimea minimă a câmpului de reprezentare.
#include <stdio.h>
#include <limits.h>

#define MAXLINE 1000

void itoa(int n, char s[], int w);


void reverse(char s[]);

int main(void)
{
char s[MAXLINE];
int width;

width = 11;
itoa(INT_MIN, s, width);
printf("campul are %9d caractere: %s.\n", width, "12345678901");
printf("%12d este convertit la. %s.\n", INT_MIN, s);
itoa(826, s, width);
printf("%12d este convertit la. %s.\n", 826, s);
itoa(-2093, s, width);
printf("%12d este convertit la. %s.\n", -2093, s);
17
return 0;
}

void itoa(int n, char s[], int w)


{
int i, sign, rest, k, j;

sign = n;
i = 0;
do {
rest = n % 10;
s[i++] = ((sign < 0) ? -rest : rest) + '0';
} while (n /= 10);
if (sign < 0)
s[i++] = '-';

while (i < w)
s[i++] = ' ';

s[i] = '\0';
reverse(s);
}

void reverse(char s[])


{
int i, j;
int tmp;

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


;
--j;

for (i = 0; i < j; ++i, --j) {


tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}

Aplicaţie propusă 4. Rescrieți funcția strrindex(s,t) care să returneze poziția celei mai din dreapta apariții a
șirului de caractere t în șirul de caractere s, sau -1 dacă șirul t nu apare deloc în șirul s.
#include <stdio.h>
#include <string.h>

#define MAXLINE 1000

int getchars(char s[], int max);


int strindex(char source[], char searchfor[]);

int main(void)
{
char source[MAXLINE];
char pattern[MAXLINE];

printf("Introduceti sirul in care se cauta, finalizare Enter:\n");


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

printf("Introduceti sirul care se cauta, finalizare Enter:\n");


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

printf("Pozitia este: %d\n", strindex(source, pattern));

return 0;
}
18
int getchars(char s[], int max)
{
int c, i, l;

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


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

return l;
}

int strindex(char s[], char t[])


{
int sl, tl;
int i, j, k;
int c;

sl = strlen(s);
tl = strlen(t);
i = sl - tl;
while (i >= 0) {
for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; ++j, ++k)
;
if (k > 0 && t[k] == '\0')
return i;
--i;
}
return -1;
}

Aplicație propusă 7. Adăugați la programul calculator posibilitatea calculării unor funcții precum sinus,
exponențială și putere pe baza accesului la funcțiile de bibliotecă sin, exp şi pow.
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <math.h>
#include <string.h>

#define MAXLINE 1000


#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
#define MATHLIB '1' /* signal that a library function in math.h was found */

int getop(char []);


void push(double);
double pop(void);

int main(void)
{
int type;
double op2;
char s[MAXOP];

while ((type = getop(s)) != EOF) {


switch (type) {
case NUMBER:
push(atof(s));
break;
case MATHLIB:
if (strcmp(s, "sin") == 0)
push(sin(pop()));
else if (strcmp(s, "cos") == 0)
push(cos(pop()));
else if (strcmp(s, "pow") == 0) {
op2 = pop();
push(pow(pop(), op2));

19
} else
printf("error: unknown command %s\n", s);
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
op2 = pop();
if (op2 != 0.0)
push(fmod(pop(), op2));
else
printf("error: zero divisor\n");
break;
case '\n':
printf("= %g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}

return 0;
}

#define MAXVAL 100 /* maximum depth of val stack */

int sp = 0; /* next free stack position */


double val[MAXVAL]; /* value stack */

/* push: push f onto value stack */


void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}

/* pop: pop and return top value from stack */


double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}

#include <ctype.h>

int getch(void);
void ungetch(int);

20
/* getop: get next character or numeric operand */
int getop(char s[])
{
int i, c, c2;

while ((s[0] = c = getch()) == ' ' || c == '\t')


;
s[1] = '\0';

i = 0;
if (isalpha(c)) {
while (isalpha(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return MATHLIB;
}

if (!isdigit(c) && c != '.' && c != '-')


return c; /* not a number */

if (c == '-') {
c2 = getch();
if (c2 != EOF)
ungetch(c2);
if (!isdigit(c2) && c2 != '.')
return c;
}

if (isdigit(c) || c == '-') /* collect integer part */


while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /* collect fraction part */
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE]; /* buffer for ungetch */


int bufp = 0; /* next free position in buf */

int getch(void) /* get a (possibly pushed-back) character */


{
return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) /* push character back on input */


{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}

21

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