This shows you the differences between two versions of the page.
programare:laboratoare:lab13 [2017/12/15 16:49] darius.neatu [Exemplu 1] |
programare:laboratoare:lab13 [2020/10/05 00:39] (current) darius.neatu [Parametrii liniei de comandă. Preprocesorul. Funcţii cu număr variabil de parametri.] |
||
---|---|---|---|
Line 1: | Line 1: | ||
===== Parametrii liniei de comandă. Preprocesorul. Funcţii cu număr variabil de parametri. ===== | ===== Parametrii liniei de comandă. Preprocesorul. Funcţii cu număr variabil de parametri. ===== | ||
- | **Responsabil:** | + | **Resposabili:****Responsabili:** |
- | * [[neatudarius@gmail.com|Darius Neațu (2016, 2017)]] | + | * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip (CA 2016-2020)]] |
+ | * [[neatudarius@gmail.com|Darius Neațu (CA 2016-2020)]] | ||
* [[mihaela.vasile@gmail.com|Mihaela Vasile (2015)]] | * [[mihaela.vasile@gmail.com|Mihaela Vasile (2015)]] | ||
+ | |||
+ | **Ultima modificare:** **09.12.2018** | ||
==== Obiective ==== | ==== Obiective ==== | ||
Line 51: | Line 54: | ||
- | ==== Exemplu 1 ==== | + | <spoiler Exemplu1 > |
Fie urmatorul cod sursa care afiseaza numarul de argumente primite, apoi afiseaza numele extras al executabilului din calea primitita ca argument. | Fie urmatorul cod sursa care afiseaza numarul de argumente primite, apoi afiseaza numele extras al executabilului din calea primitita ca argument. | ||
<code c> | <code c> | ||
Line 93: | Line 96: | ||
</code> | </code> | ||
+ | </spoiler> | ||
==== Preprocesorul ==== | ==== Preprocesorul ==== | ||
Line 154: | Line 157: | ||
în cazul în care nu se mai doreşte prezenţa simbolului de preprocesor ulterior definirii sale. | în cazul în care nu se mai doreşte prezenţa simbolului de preprocesor ulterior definirii sale. | ||
- | ==== Exemplu 2 (studiu de caz) ==== | + | <spoiler Exemplu2 (studiu de caz)> |
Codul urmator defineste cateva simboluri. Simbolul CHANGE este definit la compilare. Definirea acestuia determina modificarea simbolului GIGEL. | Codul urmator defineste cateva simboluri. Simbolul CHANGE este definit la compilare. Definirea acestuia determina modificarea simbolului GIGEL. | ||
Line 185: | Line 189: | ||
GIGEL = 1 | GIGEL = 1 | ||
</code> | </code> | ||
- | + | </spoiler> | |
=== Definirea de macro-uri === | === Definirea de macro-uri === | ||
Instrucţiunile de preprocesare mai pot fi folosite şi pentru definirea de constante simbolice şi macroinstrucţiuni. De exemplu | Instrucţiunile de preprocesare mai pot fi folosite şi pentru definirea de constante simbolice şi macroinstrucţiuni. De exemplu | ||
<code c> | <code c> | ||
- | #define CONSTANTA valoare | + | #define IDENTIFICATOR valoare |
+ | </code> | ||
+ | va duce la înlocuirea peste tot în cadrul codului sursă a şirului **IDENTIFICATOR** cu şirul **valoare**. Înlocuirea nu se face totuşi în interiorul şirurilor de caractere. | ||
+ | |||
+ | Un exemplu foarte bun este definirea unor macro-uri pentru dimensiunile tablourilor alocate static. | ||
+ | <code c> | ||
+ | #define NMAX 100 | ||
+ | #define MMAX 10 | ||
+ | #define LMAX 10000 | ||
+ | |||
+ | ... | ||
+ | int a[NMAX][MMAX]; | ||
+ | ... | ||
+ | int v[LMAX]; | ||
+ | ... | ||
</code> | </code> | ||
- | va duce la înlocuirea peste tot în cadrul codului sursă a şirului **CONSTANTA** cu şirul **valoare**. Înlocuirea nu se face totuşi în interiorul şirurilor de caractere. | ||
O macroinstrucţiune este similară unei constante simbolice, ca definire, dar acceptă parametrii. Este folosită în program în mod asemănător unei funcţii, dar la compilare, ea este înlocuită în mod textual cu corpul ei. În plus, nu se face nici un fel de verificare a tipurilor. Spre exemplu: | O macroinstrucţiune este similară unei constante simbolice, ca definire, dar acceptă parametrii. Este folosită în program în mod asemănător unei funcţii, dar la compilare, ea este înlocuită în mod textual cu corpul ei. În plus, nu se face nici un fel de verificare a tipurilor. Spre exemplu: | ||
Line 208: | Line 226: | ||
</note> | </note> | ||
- | Astfel, la un apel de forma: | + | Astfel, la o folosire de forma: |
<code c> | <code c> | ||
DUBLU(a + 3) | DUBLU(a + 3) | ||
Line 218: | Line 236: | ||
care bineînţeles că nu realizează funcţia dorită. | care bineînţeles că nu realizează funcţia dorită. | ||
- | Pentru a evita astfel de probleme, este bine ca întotdeauna în corpul unui macro, numele „parametrilor” să fie închise între paranteze (ca de exemplu:) | + | Pentru a evita astfel de probleme, este bine ca întotdeauna în corpul unui macro, numele „parametrilor” să fie închise între paranteze: |
<code c> | <code c> | ||
#define SQUARE(a) (a)*(a) | #define SQUARE(a) (a)*(a) | ||
</code> | </code> | ||
- | ==== Exemplu 3 (studiu de caz) ==== | + | <spoiler Exemplu3 (studiu de caz)> |
Fie simbolul SQUARE, care inlocuieste o expresie cu expresia ridicata la patrat. Acesta poate fi definit astfel. | Fie simbolul SQUARE, care inlocuieste o expresie cu expresia ridicata la patrat. Acesta poate fi definit astfel. | ||
<code c> | <code c> | ||
Line 280: | Line 299: | ||
-5 // ceea ce se doreste | -5 // ceea ce se doreste | ||
</code> | </code> | ||
+ | </spoiler> | ||
- | ==== Exemplu 4 (studiu de caz) ==== | + | <spoiler Exemplu4 (studiu de caz)> |
+ | |||
Sa incercam sa definim un simbol corect pentru aflarea maximului intre 2 expresii numerice. | Sa incercam sa definim un simbol corect pentru aflarea maximului intre 2 expresii numerice. | ||
Line 326: | Line 347: | ||
max = 1048576 | max = 1048576 | ||
</code> | </code> | ||
+ | </spoiler> | ||
+ | |||
+ | |||
+ | <spoiler Exemplu5 (studiu de caz)> | ||
- | ==== Exemplu 5 (studiu de caz) ==== | ||
Sa se defineasca un simbol SWAP care sa interschimbe doua variabile de acelasi tip, tipul fiind precizat. | Sa se defineasca un simbol SWAP care sa interschimbe doua variabile de acelasi tip, tipul fiind precizat. | ||
Line 467: | Line 491: | ||
Inspectati codul dupa etapa de preprocesare. Compilati si rulati codul. | Inspectati codul dupa etapa de preprocesare. Compilati si rulati codul. | ||
+ | </spoiler> | ||
<note warning> | <note warning> | ||
* ATENTIE! O variabila este vizibila in scopul ([[https://en.wikipedia.org/wiki/Scope_(computer_science)#Levels_of_scope | scope]]) in care a fost declarata. La iesirea din scop, zona de memorie corespunzatoare este eliberata([[https://blog.feabhas.com/2010/09/scope-and-lifetime-of-variables-in-c/ | Scope and Lifetime of Variables in C]]). | * ATENTIE! O variabila este vizibila in scopul ([[https://en.wikipedia.org/wiki/Scope_(computer_science)#Levels_of_scope | scope]]) in care a fost declarata. La iesirea din scop, zona de memorie corespunzatoare este eliberata([[https://blog.feabhas.com/2010/09/scope-and-lifetime-of-variables-in-c/ | Scope and Lifetime of Variables in C]]). | ||
Line 510: | Line 535: | ||
care testează dacă simbolul SIMBOL este definit, respectiv nu este definit. | care testează dacă simbolul SIMBOL este definit, respectiv nu este definit. | ||
- | ==== Exemplu 6 (studiu de caz) ==== | + | <spoiler Exemplu 6 (studiu de caz)> |
Directivele de preprocesor ar putea fi utile pentru a scrie cod portabil. De exemplu, putem identifica tipul sistemului de operare sau arhitectura procesorului. In exemplul urmator, se doreste folosirea unei functii ''f'' care sa aiba implementare de dependenta de sistemul de operare. | Directivele de preprocesor ar putea fi utile pentru a scrie cod portabil. De exemplu, putem identifica tipul sistemului de operare sau arhitectura procesorului. In exemplul urmator, se doreste folosirea unei functii ''f'' care sa aiba implementare de dependenta de sistemul de operare. | ||
<code c> | <code c> | ||
Line 568: | Line 594: | ||
La rularea executabilului, se va afisa pe ecran stringul corespunzator sistemului de operare pe care a fost compilat executabilul. | La rularea executabilului, se va afisa pe ecran stringul corespunzator sistemului de operare pe care a fost compilat executabilul. | ||
+ | </spoiler> | ||
=== Includere multipla === | === Includere multipla === | ||
Line 582: | Line 609: | ||
Astfel, la prima includere a fişierului antet, simbolul **_NUME_FISIER_ANTET_** nu este definit. Preprocesorul execută ramura **#ifndef** în care este definit simbolul **_NUME_FISIER_ANTET_** şi care conţine şi corpul - conţinutul util - al fişierului antet. La următoarele includeri ale fişierului antet simbolul **_NUME_FISIER_ANTET_** va fi definit iar preprocesorul va sări direct la sfârşitul fişierului antet, după **#endif**. | Astfel, la prima includere a fişierului antet, simbolul **_NUME_FISIER_ANTET_** nu este definit. Preprocesorul execută ramura **#ifndef** în care este definit simbolul **_NUME_FISIER_ANTET_** şi care conţine şi corpul - conţinutul util - al fişierului antet. La următoarele includeri ale fişierului antet simbolul **_NUME_FISIER_ANTET_** va fi definit iar preprocesorul va sări direct la sfârşitul fişierului antet, după **#endif**. | ||
- | ==== Exemplu 7 (studiu de caz) ==== | + | <spoiler Exemplu7(studiu de caz) > |
Vom face o ierarhie de fisiere pentru a vedea utilizarea ** garzilor ** ([[ https://en.wikipedia.org/wiki/Include_guard | include guard]]). | Vom face o ierarhie de fisiere pentru a vedea utilizarea ** garzilor ** ([[ https://en.wikipedia.org/wiki/Include_guard | include guard]]). | ||
Line 745: | Line 773: | ||
run | run | ||
</code> | </code> | ||
+ | </spoiler> | ||
+ | |||
=== Alte instrucţiuni === | === Alte instrucţiuni === | ||
Line 811: | Line 841: | ||
* Eliberarea memoriei folosite de lista de parametri se realizează prin intermediul macro-definiţiei **va_end(arg_list)**, unde **arg_list** are aceeaşi semnificaţie ca mai sus. | * Eliberarea memoriei folosite de lista de parametri se realizează prin intermediul macro-definiţiei **va_end(arg_list)**, unde **arg_list** are aceeaşi semnificaţie ca mai sus. | ||
- | ==== Exemplu 8 ==== | + | <spoiler Exemplu8 > |
+ | |||
Fie o functie care afiseaza un număr variabil de numere naturale primite ca parametru. Lista este terminată cu un număr negativ. | Fie o functie care afiseaza un număr variabil de numere naturale primite ca parametru. Lista este terminată cu un număr negativ. | ||
<code c> | <code c> | ||
Line 877: | Line 908: | ||
These are the numbers (excluding terminator): 1 2 3 | These are the numbers (excluding terminator): 1 2 3 | ||
</code> | </code> | ||
+ | </spoiler> | ||
+ | <spoiler Exemplu 9 (studiu de caz)> | ||
- | ==== Exemplu 9 (studiu de caz) ==== | ||
In exemplul anterior am considerat toate argumentele primite erau intregi. In general, acestea pot avea tipuri diferite. | In exemplul anterior am considerat toate argumentele primite erau intregi. In general, acestea pot avea tipuri diferite. | ||
Line 1007: | Line 1039: | ||
* Codul a compilat, desi nu am implementat separat float si double. La pasarea parametrilor, unele tipuri de date sunt promovotate: float la double, char/short la int ([[http://stackoverflow.com/questions/11270588/variadic-function-va-arg-doesnt-work-with-float | stackoverflow ]]). | * Codul a compilat, desi nu am implementat separat float si double. La pasarea parametrilor, unele tipuri de date sunt promovotate: float la double, char/short la int ([[http://stackoverflow.com/questions/11270588/variadic-function-va-arg-doesnt-work-with-float | stackoverflow ]]). | ||
</note> | </note> | ||
+ | |||
+ | </spoiler> | ||
==== Exerciții de laborator CB/CD ==== | ==== Exerciții de laborator CB/CD ==== | ||
Line 1020: | Line 1054: | ||
Primul exercitiu presupune modificarea/adaugarea de instructiuni unui cod existent pentru a realiza anumite lucruri. In momentul actual programul populeaza vectorul cu valorile parametrilor primiti de functie (atat timp cat valoarea parametrului este > 0). Daca nu s-a populat tot vectorul, se adauga 0 pe pozitiile ramase goale. | Primul exercitiu presupune modificarea/adaugarea de instructiuni unui cod existent pentru a realiza anumite lucruri. In momentul actual programul populeaza vectorul cu valorile parametrilor primiti de functie (atat timp cat valoarea parametrului este > 0). Daca nu s-a populat tot vectorul, se adauga 0 pe pozitiile ramase goale. | ||
+ | <spoiler ex1.c> | ||
<code c ex1.c> | <code c ex1.c> | ||
Line 1062: | Line 1097: | ||
} | } | ||
</code> | </code> | ||
+ | </spoiler> | ||
Cerinte: | Cerinte: | ||
* Sa se modifice functia astfel incat sa se poata popula si un vector cu elemente de tip char. Functia va fi declarata astfel: | * Sa se modifice functia astfel incat sa se poata popula si un vector cu elemente de tip char. Functia va fi declarata astfel: | ||
* **void insert_elemenets(void *v, int n, char type, …)** - unde type va specifica tipul (‘d’ pentru int si ‘c’ pentru char). | * **void insert_elemenets(void *v, int n, char type, …)** - unde type va specifica tipul (‘d’ pentru int si ‘c’ pentru char). | ||
- | * Daca nu se umple tot vectoru cu valori, vor trebui puse niste valori default (cum este si in codul deja existent): pentru int va ramane valoarea 0, iar pentru char va fi ‘a’. | + | * Daca nu se umple tot vectorul cu valori, vor trebui puse niste valori default (cum este si in codul deja existent): pentru int va ramane valoarea 0, iar pentru char va fi ‘a’. |
* In functie de simbolul NUMBERS, programul va popula fie un vector de numere, fie un vector de caractere si il va afisa (se pot lasa valori specifice trimise la functia de populare) | * In functie de simbolul NUMBERS, programul va popula fie un vector de numere, fie un vector de caractere si il va afisa (se pot lasa valori specifice trimise la functia de populare) | ||
* Simbolul nu trebuie definit in cadrul fisierului sursa | * Simbolul nu trebuie definit in cadrul fisierului sursa | ||
Line 1075: | Line 1110: | ||
</hidden> | </hidden> | ||
==== Exerciţii de Laborator ==== | ==== Exerciţii de Laborator ==== | ||
- | - [1p] Completati formularul de **FEEDBACK** pentru [[ http://cs.curs.pub.ro/2016/course/view.php?id=16 | Programarea calculatoarelor (CA)]]. | + | Exercițiile următoare fac referire la anumite exemple (ex. **Exemplu1**). Aceste exemple se găsesc în laborator (CTRL + F pentru **Exemplu1**). |
- | - [1p] Să se realizeze un program care să afișeze toți parametrii liniei de comandă primiți. Hint:[[http://ocw.cs.pub.ro/courses/programare/laboratoare/lab12#exemplu_1 | Exemplu 1]]. | + | |
+ | - [1p] Completati formularul de **FEEDBACK** pentru [[https://acs.curs.pub.ro/2018/course/view.php?id=127 | Programarea calculatoarelor (CA)]]. Vă rugăm să îl completați cu atenție și răbdare. Apreciem orice feedback **NEGATIV CONSTRUCTIV **. Vă rugăm nu spuneți ** DOAR ** lucruri precum "tema X a fost grea", "nu am reușit să fac tot la parțial", "Gigel apare de prea multe ori prin laboratoare". Încercați să argumentați de ce credeți că s-a ajuns în acea situație și (eventual) cum credeți voi că am putea remedia asta pentru anul viitor. Mulțumim! | ||
+ | - [1p] Să se realizeze un program care să afișeze toți parametrii liniei de comandă primiți. Hint: ** Exemplu1**. | ||
- [2p] Scrieti un program C care primeste argumente in linia de comanda. Acesta trebuie sa respecte urmatoarele reguli. | - [2p] Scrieti un program C care primeste argumente in linia de comanda. Acesta trebuie sa respecte urmatoarele reguli. | ||
* Numele executabilului va fi ''gigel''. | * Numele executabilului va fi ''gigel''. | ||
Line 1082: | Line 1119: | ||
* Lista de argumente reprezinta un sir de numere naturale (''unsigned int''). Se cere sortarea listei folosind functia ''[[http://www.cplusplus.com/reference/cstdlib/qsort/?kw=qsort | qsort ]]''. | * Lista de argumente reprezinta un sir de numere naturale (''unsigned int''). Se cere sortarea listei folosind functia ''[[http://www.cplusplus.com/reference/cstdlib/qsort/?kw=qsort | qsort ]]''. | ||
* Daca lista de argumente contine stringuri care nu reprezinta numere intregi fara semn, se va afisa la stderr mesajul ''Gigele, da-mi numere naturale!''. In acest caz, programul va iesi cu valoarea ''[[http://www.cplusplus.com/reference/climits/ | INT_MIN]]''. | * Daca lista de argumente contine stringuri care nu reprezinta numere intregi fara semn, se va afisa la stderr mesajul ''Gigele, da-mi numere naturale!''. In acest caz, programul va iesi cu valoarea ''[[http://www.cplusplus.com/reference/climits/ | INT_MIN]]''. | ||
- | - [2p] Realizați un macro SWAP(x, y). Hint: Puteti folosi ''sizeof'' pentru a determina cata memorie este necesara pentru variabila de interschimbare. De asemenea, puteti consulta si [[ http://ocw.cs.pub.ro/courses/programare/laboratoare/lab12#exemplu_5_studiu_de_caz | Exemplu 5]]. | + | - [2p] Realizați un macro SWAP(x, y). Hint: Puteti folosi ''sizeof'' pentru a determina cata memorie este necesara pentru variabila de interschimbare. De asemenea, puteti consulta si **Exemplu 5**. |
- | - [4p] Realizați implementarea funcției cu ''număr variabil de parametri'' numită ''gcd'', care să permită aflarea celui mai mare divizor comun (''[[https://en.wikipedia.org/wiki/Greatest_common_divisor | gcd]]'') al parametrilor dați (''cel puțin'' două elemente care sunt numere naturale). Puteti presupune ca lista se termina cu un numar negativ. Hint: [[http://ocw.cs.pub.ro/courses/programare/laboratoare/lab12#exemplu_8 | Exemplu 8]]. | + | - [4p] Realizați implementarea funcției cu ''număr variabil de parametri'' numită ''gcd'', care să permită aflarea celui mai mare divizor comun (''[[https://en.wikipedia.org/wiki/Greatest_common_divisor | gcd]]'') al parametrilor dați (''cel puțin'' două elemente care sunt numere naturale). Puteti presupune ca lista se termina cu un numar negativ. Hint: ** Exemplu8**. |
Line 1139: | Line 1176: | ||
</hidden> | </hidden> | ||
+ | [[https://docs.google.com/document/d/1lwQBmJ4YuaBmpUOb5uUIs27TwLvWu-6jTL3aQ9TAwIA/edit?usp=sharing|Probleme laborator 14:00 - 16:00]] |