Bine ati venit pe ItAssistant. Aceasta noua serie de tutoriale isi propune sa va familiarizeze cu limbajul de programare C si conceptele Programarii Structurata.
Introducere
C este un limbaj de programare structurată menit să simplifice scrierea programelor apropiate de masină. A fost creat de către Dennis Ritchie în perioada 1968-1973 și a fost dezvoltat în strânsă legatură cu sistemul de operare Unix, care a fost rescris în întregime în C. Utilizarea limbajului s-a extins cu trecerea timpului de la sisteme de operare și aplicaţii de sistem la aplicaţii generale.
Deşi în prezent, pentru dezvoltarea aplicaţiilor complexe au fost create limbaje de nivel mai înalt (Java, C#, Python), C este în continuare foarte folosit la scrierea sistemelor de operare şi a aplicațiilor de performanţă mare sau dimensiune mică (în lumea dispozitivelor embedded). Nucleele sistemelor Windows şi Linux sunt scrise în C.
Compilatorul GCC
GCC este unul dintre primele pachete software dezvoltate în cadrul Proiectului GNU (GNU’s Not Unix) de către Free Software Foundation. Deși GCC se traducea iniţial prin GNU C Compiler, acesta a devenit între timp un compilator multifrontend, multi-backend, având suport pentru o serie largă de limbaje, ca C, C++, Objective-C, Ada, Java, etc, astfel că denumirea curentă a devenit GNU Compiler Collection.
Compilatorul GCC rulează pe o gamă largă de echipamente hardware (procesoare din familia: i386, alpha, vax, m68k, sparc, HPPA, arm, MIPS, PowerPC, etc.) și de sisteme de operare (GNU/Linux, DOS, Windows 9x/NT/2000, Solaris, Tru64, VMS, Ultrix, Aix ), fiind la ora actuală cel mai portat compilator.
Compilatorul GCC se apelează din linia de comandă, folosind diferite opțiuni, în funcție de rezultatul care se dorește (specificarea de căi suplimentare de căutare a bibliotecilor/fișierelor antet, link-area unor biblioteci specifice, opțiuni de optimizare, controlul stagiilor de compilare, al avertisementelor, etc.).
Pentru exemplificare vom considera următorul program foarte simplu:
/*hello.c*/ #include <stdio.h> int main() { printf("Hello from your first program!"); return 0; }
Pentru compilarea programului se va lansa comanda (în linia de comandă):
gcc hello.cpresupunând că fișierul sursă se numește hello.c (este esențial ca extensia să fie c și nu C (C mare – așa cum este cazul fișierelor produse de Borland C++ 3.1), deoarece aceasta din urmă este interpretată de către compilator ca fiind extenesie de fișier C++).
În funcţie de sistemul de operare folosit, pentru executarea programului astfel obținut se va lansa fie comanda
pentru Linux
a
pentru Windows, fie comanda
./a.outPrima comandă are ca efect compilarea și link-editarea (rezolvarea apelurilor de funcții) fișierului sursă hello.c, generându-se un fișier executabil, al cărui nume implicit este a.out în cazul sistemelor Linux și a.exe în cazul sistemelor Windows. Pentru un control mai fin al comportării compilatorului, sunt prezentate în tabelul următor cele mai folosite opţiuni (pentru lista completă studiaţi pagina de manual pentru GCC – man gcc):
| Opțiune | Efect |
|---|---|
| -o nume_fișier | Numele fișierului de ieşire va fi nume_fişier. În cazul în care această opțiune nu este setată, se va folosi numele implicit (pentru fișiere executabile: a.out – pentru Linux și a.exe – pentru Windows) |
| -I cale_catre_fisiere_antet | Caută fișiere antet și în calea specificată |
| -L cale_catre_biblioteci | Caută fișiere bibliotecă și în calea specificată |
| -l nume_biblioteca | Link-editează librăria nume_biblioteca. Atenție!!! nume_bibliotecă nu este întotdeauna același cu numele fișierului antet prin care se include această bibliotecă. Spre exemplu, pentru includerea bibliotecii de funcții matematice, fișierul antet este math.h, iar biblioteca este m |
| -W tip_warning | Afișează tipurile de avertismente specificate (Pentru mai multe detalii man gcc sau gcc --help). Cel mai folosit tip este all. Este indicat ca la compilarea cu -Wall să nu apară nici un fel de avertismente |
| -c | Compilează și asamblează, dar nu link-editează. Rezultă fișiere obiect, cu extensia .o |
| -S | Se opreste după faza de compilare, fară să asambleze. Rezultă cod assembler in fișiere cu extensia .s |
Spre exemplu:
gcc -o exemplu exemplu.c -lm -Wall
are ca efect compilarea și link-editarea fişierului exemplu.c, cu includerea bibliotecii matematice, afişând toate avertismentele. Fişierul de ieşire se va numi exemplu.exe (extensia e determinată de sistemul de operare, dar şi de conţinutul fişierului sursă).
Utilitarul Make
Utilitarul make determină automat care sunt părțile unui proiect care trebuie recompilate ca urmare a operării unor modificări și declanşează comenzile necesare pentru recompilarea lor. Pentru a putea utiliza make, este necesar un fișier de tip makefile numit de obicei Makefile (sau makefile) care descrie relațiile de dependenţă între diferitele fișiere din care se compune programul şi care specifică regulile de actualizare pentru fiecare fişier în parte.
În mod normal, într-un program, fişierul executabil este actualizat (recompilat) pe baza fișierelor-obiect, care la rândul lor sunt obținute prin compilarea fișierelor sursă. Totuși, acest utilitar poate fi folosit pentru orice proiect care conţine dependenţe şi cu orice compilator/utilitar care poate rula în linia de comandă. Odată creat fișierul makefile, de fiecare dată când apare vreo modificare în fișierele sursă, este suficient să rulăm utilitarul make pentru ca toate recompilările necesare să fie efectuate. Programul make utilizează fișierul Makefile ca bază de date şi pe baza timpilor ultimei modificări a fișierelor din Makefile decide care sunt fișierele care trebuie actualizate. Pentru fiecare din aceste fișiere, sunt executate comenzile precizate in Makefile.
În continuare prezentăm un exemplu simplu de makefile.
# Declarațiile de variabile CC = gcc CCFLAGS = -Wall -lm SRC = radical.c PROGRAM = radical # Regulă de compilare all: $(CC) -o $(PROGRAM) $(SRC) $(CCFLAGS) # Regulile de "curațenie" (se folosesc pentru ștergerea fișierelor intermediare si/sau rezultate) .PHONY : clean clean : rm -f $(PROGRAM) core *~
Pachetul MinGW
Compilatorul GCC este disponibil pentru Windows în pachetul MinGW. Pentru instalare folosiţi fişierul .exe. Antenţie! Installer-ul are nevoie de acces la Internet pentru a putea descărca diversele componente.
Tot de la această adresă se poate descărca si pachetul MSYS care conține variante portate ale utilitarului make și ale programelor folosite cel mai frecvent în makefile-uri (rm, cd, cat, etc.).
Instalarea este simplă, folosind un setup intuitiv. Pentru funcționarea corectă a pachetului MinGW/MSYS, este însă necesară adăugarea directorului unde se află binarele instalate la variabila de mediu PATH (în mediul Windows). Pentru GCC, aceasta este de obicei C:MinGWbin. Pentru sistemele Windows 2000 și mai recente setarea variabilei de mediu PATH se realizează astfel:
- click dreapta pe My Computer > Properties
- din tabul Advanced se selectează Environment Variables
- aici dublu click pe elementul Path din System Variable
- adaugați la sfarșitul șirului de la Variable value calea către directorul care conține binarele compilatorului GCC (vezi imaginea).
Pentru Ubuntu puteti folosi urmatoarea comanda pentru a instalat make
apt-get install build-essential
Editoare
Pentru editarea surselor se poate folosi orice editor de text. Astfel, putem menționa:
- Linux: vi(m), pico, joe, nano, emacs, mcedit – cu interfața în mod text si Kate, KWrite, GEdit, Scribes – cu interfață grafică.
- Windows: Crimson Editor, Notepad++, Textpad, etc.
Java: jEdit
Deși lista nu este completă, editoarele specificate au pe langă facilitățile standard (Cut/Copy, wordwrap) si suport pentru syntax highlight, auto-indent, etc. ceea ce le face să fie mai prietenoase și să ajute în scrierea codului.
Interacțiunea program-utilizator
Majoritatea algoritmilor presupun introducerea unor date de intrare și calcularea unor rezultate. În cazul programelor de consolă, datele sunt introduse de la tastatură și afișate pe ecran (alte variante sunt folosirea fișierelor sau preluarea datelor de la un hardware periferic).
Programul dat ca exemplu mai sus folosește funcția de afișare printf. Această funcție realizează transferul și conversia de reprezentare a valorii întregi / reale in șir de caractere sub controlul unui format (specificat ca un șir de caractere):
printf("format", expr_1, expr_2, ..., expr_n);
unde expr_i este o expresie care se evaluează la unul din tipurile fundamentale ale limbajului. Este necesar ca pentru fiecare expresie să existe un specificator de format, şi viceversa.
În caz contrar, compilatorul va returna o eroare (în afara cazului în care formatul este obtinut la rulare). Sintaxa unui descriptor de format este:
% [ - ] [ Lung ] [ .frac ] [ h|l|L ] descriptor
Semnificația câmpurilor din descriptor este descrisă în tabelul următor:
| Câmp | Descriere |
|---|---|
| - | Indică o aliniere la stânga în câmpul de lungime Lung (implicit alinierea se face la dreapta). |
| Lung | Dacă expresia conține mai puțin de Lung caractere, ea este precedată de spații sau zerouri, dacă Lung începe printr-un zero. Dacă expresia conține mai mult de Lung caractere, câmpul de afișare este extins. În absența lui Lung, expresia va fi afișată cu atâtea caractere câte conține. |
| frac | Indică numărul de cifre după virgulă (precizia) cu care se face afișarea. |
| l | Marchează un long int, în timp ce pentru reali l determină afișarea unei valori double. |
| h | Marchează un short int |
| L | Precede unul din descriptorii f,e,E,g,G pentru afișarea unei valori de tip long double. |
Tabelul următor prezintă descriptorii și conversiile care au loc:
| Descriptor | Descriere |
|---|---|
| d | Întreg cu semn în baza 10 |
| u | Întreg fără semn în baza 10 |
| o | Întreg fără semn în baza 8 |
| x sau X | Întreg fără semn în baza 16. Se folosesc literele a, b, c, d, e, f mici, respectiv mari |
| c | Caracter |
| s | Șir de caractere |
| f | Real zecimal de forma [-]xxx.yyyyyy (implicit 6 cifre după virgulă) |
| e sau E | Real zecimal în notație exponențială. Se folosește e mic, respectiv E mare |
| g | La fel ca și e, E și f dar afișarea se face cu număr minim de cifre zecimale |
Citirea cu format se realizează cu ajutorul funcției scanf() astfel:
scanf("format", &var_1, &var_2, ..., &var_n)
care citește valorile de la intrarea standard în formatul precizat și le depune în variabilele var_i, returnând numarul de valori citite.
Atenție! Funcția scanf primește adresele variabilelor în care are loc citirea. Pentru tipuri fundamentale și/sau structuri, aceasta se obține folosind operatorul de adresă – &.
Sintaxa descriptorului de format în acest caz este:
% [*] [ Lung ] [ l ] descriptor
Semnificația campurilor din descriptor este descrisă în tabelul următor:
| Câmp | Descriere |
|---|---|
| * | Indică faptul că valoarea citită nu se atribuie unei variabile. (valoarea citită poate fi folosită pentru specificarea lungimii câmpului) |
| Lung | Indică lungimea câmpului din care se face citirea. În cazul în care e nespecificat, citirea are loc până la primul caracter care nu face parte din număr, sau până la ‘n’ (linie nouă/enter) |
| d | Întreg în baza 10 |
| o | Întreg în baza 8 |
| x | Întreg în baza 16 |
| f | Real |
| c | Caracter |
| s | Șir de caractere |
| L | Indică un întreg long sau un real double |
| h | Indică un întreg short |
Pentru scrierea și citirea unui singur caracter, biblioteca stdio.h mai definește și funcțiile getchar() și putchar():
- getchar() are ca efect citirea cu ecou a unui caracter de la terminalul standard. Caracterele introduse de la tastatură sunt puse într-o zonă tampon, până la acționarea tastei ENTER, moment în care în zona tampon se introduce caracterul rând nou. Fiecare apel getchar() preia următorul caracter din zona tampon.
- putchar() afișează caracterul având codul ASCII egal cu valoarea expresiei parametru.
Nota: getchar() și putchar() nu sunt de fapt funcții, ci niște macroinstrucțiuni definite în stdio.h
Pentru citirea și scrierea unei linii biblioteca stdio.h definește funcțiile gets() și puts():
- gets(zona) - introduce de la terminalul standard un șir de caractere terminat prin acționarea tastei ENTER. Funcția are ca parametru adresa zonei de memorie în care se introduc caracterele citite. Funcția returnează adresa de început a zonei de memorie; la întalnirea sfarșitului de fișier (CTRL+Z) funcția returnează NULL.
- puts(zona) – afișează la terminalul standard șirul de caractere din zona dată ca parametru, până la caracterul null ( ), care va fi înlocuit prin caracterul linie nouă. Funcția returnează codul ultimului caracter din șirul de caractere afișate sau -1 în caz de eroare.
Sursa tutorialului: http://cursuri.cs.pub.ro/~programare/w/index.php/Pagina_principal%C4%83
Related posts:
- Invata Limbajul de Programare C – Partea 12
- Invata Limbajul de Programare C – Partea 2
- Invata Limbajul de Programare C – Partea 11
- Invata Limbajul de Programare C – Partea 9
- Invata Limbajul de Programare C – Partea 7



