Setul 7

Problema 1 - Topul Melodiilor

Să se scrie un program pentru realizarea unui top al unor melodii. Persoanele care participă la alcătuirea topului se împart în 4 categorii, după sex şi vârstă (mai tineri de 20 de ani şi peste 20 de ani). Fiecare persoană nominalizează, în ordine, 5 melodii preferate, fiecare identificată prin titlu. Datele pentru o persoană vor fi de forma:

    • nume

    • sex (m sau f)

    • vârstă

    • melodie1

    • melodie2

    • melodie3

    • melodie4

    • melodie5

Datele privind persoanele participante la realizarea topului se citesc dintr-un fișier text în care apar în ordine datele pentru mai multe persoane. Numărul de persoane nu este specificat la începutul fișierului.

Să se afişeze:

    1. Lista melodiilor în ordinea popularităţii lor.

    2. Lista câştigătorilor (cei care au ghicit melodiile câştigătoare) pentru fiecare categorie, şi anume: 4 liste separate cuprinzând numele persoanelor care au menţionat pe prima poziţie a preferinţelor lor una din cele mai populare 3 melodii.

Un exemplu de fișier de intrare este dat în continuare.

Vasile m 19 Kobi Peretz - Some Love Madcon feat Ameerah - Freaky like me Shakira - Loca Sak Noel - Loca People Toni Tone - Forever alive Elena f 18 Guess Who - Manifest Shakira - Loca Toni Tone - Forever alive Sak Noel - Loca People Akcent - My passion Ion m 24 Sak Noel - Loca People Akcent - My passion ROA - Ne place Guess Who - Manifest Rihanna feat Drake - What's my name Maria f 19 Black Eyed Peas - The Time Amna - Tell me why Jessie J - Price tag Adrian Sana feat Beverlei Brown - I cant live without you Tinie Tempah Feat. Kelly Rowland - Invincible Tudor m 23 Natalia Kills - Mirrors Taio Cruz feat Kylie Minogue - Higher Radio Killer - Lonely heart Alex Velea - One Shot Morandi - Midnight Train Ioana f 22 Toni Tone - Forever alive Guess Who - Manifest Akcent - My passion ROA - Ne place Mahomby - Bumpy ride Mihai m 18 Sak Noel - Loca People Akcent - My passion Kobi Peretz - Some Love Amna - Tell me why Jessie J - Price tag Adriana f 23 Puya feat Connect'r - Americandrim Shakira - Loca Guess Who - Manifest Natalia Kills - Mirrors Morandi - Midnight Train

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<ctype.h>

#define MASCULIN 'm'

#define FEMININ 'f'

#define PRAG_VARSTA 20

#define NR_MELODII 5

#define LINE_LEN 256

struct melodie {

char *titlu;

int punctaj;

};

struct persoana {

char *nume;

char sex;

int varsta;

int mel[NR_MELODII];

};

struct melodie *m = NULL;

int nr_mel;

struct persoana *p;

int nr_pers;

void afisare_date(void)

{

int i, j;

printf("%d melodii\n", nr_mel);

for (i=0;i<nr_mel;i++)

printf("%s (%d puncte)\n", m[i].titlu,m[i].punctaj);

printf("\n%d persoane\n", nr_pers);

for(i=0;i<nr_pers;i++)

{

printf("%s (%c, %d)\n", p[i].nume, p[i].sex,

p[i].varsta);

for (j = 0; j < NR_MELODII; j++)

printf("\t%s\n", m[p[i].mel[j]].titlu);

}

}

int adauga_melodie(char *titlu)

{

int i;

for(i=0;i<nr_mel;i++)

{

if (!strcmp(m[i].titlu, titlu))

return i;

}

m=(struct melodie*)realloc(m,(nr_mel+1)*sizeof(struct melodie));

if(!m)

{

printf("Eroare alocare melodie.\n");

exit(EXIT_FAILURE);

}

m[nr_mel].titlu = strdup(titlu);

m[nr_mel].punctaj = 0;

nr_mel++;

return nr_mel - 1;

}

int citeste_persoana(FILE * f)

{

char nume[LINE_LEN], linie[LINE_LEN];

int empty, i;

if (NULL == fgets(nume, LINE_LEN, f))

return 1;

empty = 1;

for (i = 0; i < strlen(nume); i++)

{

if (!isspace(nume[i]))

{

empty = 0;

break;

}

}

if(empty)

return 1;

p=(struct persoana*)realloc(p,(nr_pers + 1)*sizeof(struct persoana));

if(!p)

{

printf("Eroare alocare memorie pentru persoana.\n");

exit(EXIT_FAILURE);

}

nume[strlen(nume) - 1] = 0;

p[nr_pers].nume = strdup(nume);

fgets(linie, LINE_LEN, f);

p[nr_pers].sex = linie[0];

fgets(linie, LINE_LEN, f);

sscanf(linie,"%d",&p[nr_pers].varsta);

for (i = 0; i < NR_MELODII; i++)

{

fgets(linie, LINE_LEN, f);

linie[strlen(linie) - 1] = 0;

p[nr_pers].mel[i] = adauga_melodie(linie);

}

nr_pers++;

return 0;

}

void citire(void)

{

int gata = 0;

FILE *f = fopen("bac.txt", "r");

if(!f)

{

perror("Eroare deschidere fisier");

exit(EXIT_FAILURE);

}

while (!gata)

gata = citeste_persoana(f);

fclose(f);

}

void calcul_top()

{

int i,j;

for(i=0;i<nr_pers;i++)

for(j=0;j<NR_MELODII;j++)

m[p[i].mel[j]].punctaj++;

}

void ordonare_top()

{

int i,j,aux;

char string_aux[LINE_LEN];

for(i=0;i<nr_mel-1;i++)

for(j=i+1;j<nr_mel;j++)

if(m[i].punctaj<m[j].punctaj)

{

aux=m[i].punctaj;

m[i].punctaj=m[j].punctaj;

m[j].punctaj=aux;

strcpy(string_aux,m[i].titlu);

m[i].titlu=strdup(m[j].titlu);

m[j].titlu=strdup(string_aux);

}

}

void afisare_top()

{

int i,j;

ordonare_top();

for (i = 0; i < nr_mel; i++)

printf("%s (%d puncte)\n",m[i].titlu,m[i].punctaj);

}

void print_winner(char c, int age)

{

int i;

if(age==1)

for(i=0;i<nr_pers;i++)

if((p[i].sex==c)&&(p[i].varsta<=20))

if(!strcmp(m[p[i].mel[1]].titlu, m[1].titlu) || !strcmp(m[p[i].mel[1]].titlu, m[2].titlu) || !strcmp(m[p[i].mel[1]].titlu, m[3].titlu))

printf("%s\n",p[i].nume);

if(age==0)

for(i=0;i<nr_pers;i++)

if((p[i].sex==c)&&(p[i].varsta>20))

if(!strcmp(m[p[i].mel[1]].titlu, m[1].titlu) || !strcmp(m[p[i].mel[1]].titlu, m[2].titlu) || !strcmp(m[p[i].mel[1]].titlu, m[3].titlu))

printf("%s\n",p[i].nume);

}

void afisare_castigatori()

{

int i,j;

printf("Castigatori sub 20 de ani: \n");

print_winner('m',1);

printf("Castigatori peste 20 de ani: \n");

print_winner('m',0);

printf("Castigatoare sub 20 de ani: \n");

print_winner('f',1);

printf("Castigatoare peste 20 de ani: \n");

print_winner('f',0);

}

int main(void)

{

citire();

calcul_top();

afisare_top();

afisare_castigatori();

free(m);

free(p);

return 0;

}

Problema 2 - Macrosimbol cu 2 parametrii

Definiţi un macrosimbol C care să poată fi folosit la depanarea programelor. Macrosimbolul trebuie să primească doi parametri. Primul parametru este un specificator de format, similar cu cei folosiţi la funcţia printf. Al doilea parametru este o variabilă definită în program. Macrosimbolul trebuie să afişeze pe ecran fişierul în care ne aflăm, linia de la care a fost apelat, numele variabilei trimisă ca parametru şi valoarea variabilei.

Macrosimbolul se va numi DBG_PRINT, şi el trebuie să poată fi utilizat în secvenţe de cod de genul:

int main(void) { int a = 10; float f = 20.4; DBG_PRINT("%d", a); DBG_PRINT("%f", f); return 0; }

Afişarea se va face într-un format asemănător cu:

[fisier p2.c, linia 11] a=10 [fisier p2.c, linia 12] f=20.400000

#include <stdio.h>

#include <stdlib.h>

#define dbg_print(a,b)\

printf("[fisier %s, linia %d]",__FILE__,__LINE__);\

printf(" %s=",(#b));\

printf(a,b);\

printf("\n")

int main()

{

printf("Hello world!\n");

int a=10;

float f=20.4;

dbg_print("%d",a);

dbg_print("%f",f);

return 0;

}

Problema 3 - X și 0

Scrieţi un program C care să implementeze binecunoscutul joc “X si Zero”. Programul trebuie să permită ca doi jucători umani să joace unul împotriva celuilalt.

Tabla de joc va arăta în felul următor (va fi desenată în mod text):

+-------+-------+-------+ | | | | | \ / | /---\ | | | x | | | | | | / \ | \---/ | | | | | | +-------+-------+-------+ | | | | | | | | | | | | | | | | | | | | +-------+-------+-------+ | | | | | | | | | | | | | | | | | | | | +-------+-------+-------+

La pornirea programului se va afişa tabla fară nici o piesă pe ea.

Primul jucător care mută este întotdeauna jucătorul “X”. Programul va citi de la tastatură linia şi coloana unde doreşte să mute jucătorul care este la rând. În caz că valorile introduse nu sunt corecte (fie sunt în afara tablei, fie căsuța respectivă este deja ocupată) se va afişa un mesaj de eroare şi se va repeta citirea pentru acelaşi jucător.

Dacă valorile sunt corecte, se va pune o piesă la poziţia indicată şi se va trece la celălalt jucător. În momentul în care unul din jucători a câstigat sau este remiză, programul va anunţa acest lucru printr-un mesaj pe ecran.

În timpul rulării, programul trebuie să lase o impresie plăcută, tabla de joc trebuie să apară mereu în aceeași poziție pe ecran, eventualele mesaje de eroare să nu rămană vizibile de la o mutare la alta, etc.

Se recomandă abordarea programului în următorii pași:

Pasul 1. Functia main, cu o buclă în care se fac citiri repetate de la tastatură ale mutărilor celor doi jucători; programul să știe oricând care jucător urmează să mute.

Pasul 2. Definirea structurii de date pentru tabla de joc; extinderea programului astfel încât să se poată juca un joc, dar cu o afișare foarte simplistă a tablei (o codificare simplă: 1 pentru ‘x’, 0 pentru ‘o’, -1 pentru căsuță goală).

Pasul 3. Extinderea programului astfel încât tabla să fie desenată conform specificațiilor din enunț.

Aspectul vizual al tablei nu este important. Nu începeți programul cu funcția de desenare a tablei. Desenarea se va implementa ultima, după ce funcționează algoritmul de joc.

Pentru a șterge ecranul în terminalul Linux puteți folosi următoarea funcție:

void clrscr(void) { printf("\x1B[2J\x1B[1;1H"); }

#include <stdio.h>

#include <stdlib.h>

void clrscr(void)

{

printf("\x1B[2J\x1B[1;1H");

}

int castig(int tabla[4][4])

{

int i;

for(i=1;i<=3;i++)

{

if(tabla[i][1]==tabla[i][2]&&tabla[i][2]==tabla[i][3]&&tabla[i][1]!=-1)

return 1;

if(tabla[1][i]==tabla[2][i]&&tabla[2][i]==tabla[3][i]&&tabla[1][i]!=-1)

return 1;

}

if((tabla[1][1]==tabla[2][2]&&tabla[2][2]==tabla[3][3]&&tabla[1][1]!=-1)||(tabla[3][1]==tabla[2][2]&&tabla[2][2]==tabla[1][3]&&tabla[1][3]!=-1))

return 1;

return 0;

}

void afisare(int tabla[4][4])

{

int i,j;

printf("+---+---+---+\n");

for(i=1;i<=3;i++)

{

printf("|");

for(j=1;j<=3;j++)

if(tabla[i][j]==-1)

printf(" |");

else

if(tabla[i][j]==1)

printf(" x |");

else

printf(" o |");

printf("\n+---+---+---+\n");

}

}

int verific(int l,int c,int tabla[4][4])

{

if(l<1||l>3||c<1||c>3||tabla[l][c]!=-1)

return 0;

return 1;

}

void init(int tabla[4][4])

{

int i,j;

for(i=1;i<=3;i++)

for(j=1;j<=3;j++)

tabla[i][j]=-1;

}

int main()

{

printf("Hello world!\n");

int l,c,tabla[4][4],casute=0,castigator=1;

init(tabla);

afisare(tabla);

do

{

printf("\nJucatorul X:\n");

do{

scanf("%d%d",&l,&c);

if(verific(l,c,tabla)==0)

printf("Mutare nevalida\n");

}while(verific(l,c,tabla)==0);

clrscr();

casute++;

tabla[l][c]=1;

afisare(tabla);

if(castig(tabla))

{

castigator=0;

printf("\nJucatorul X a castigat\n");

}

else

{

if(casute<9)

{

printf("\nJucatorul 0:\n");

do{

scanf("%d%d",&l,&c);

if(!verific(l,c,tabla))

printf("Mutare nevalida");

}while(!verific(l,c,tabla));

clrscr();

casute++;

tabla[l][c]=0;

afisare(tabla);

if(castig(tabla))

{

castigator=0;

printf("\nJucatorul 0 a castigat\n");

}

}

else

printf("Remiza\n");

}

}while(castigator!=0&&casute<9);

return 0;

}