>> Inapoi <<

========
Capitolul 1
========

=========================
Cum se scrie un program (in C) ?
=========================

Programele sunt scrise pentru a instrui masinile sa lucreze cu taskuri 
specifice sau sa rezolve probleme specifice. O procedura (descrisa pas cu pas)
asociata unui task se numeste algoritm. Programarea este activitatea de 
comunicare (codificare) a algoritmilor in calculatoare. Procesul de programare
are (in general) patru pasi:

  1. Specificarea task-ului;
  2. Descoperirea unui algoritm pentru solutia sa;
  3. Codificarea algoritmului in C;
  4. Testarea codului.
  
Un calculator este o masina electronica digitala compusa din trei componente: 
  1. procesor (central processing unit sau CPU);
  2. memorie;
  3. dispozitive de intrare/iesire.
Procesorul lucreaza cu instructiuni care sunt inregistrate in memorie. Pe langa 
aceste instructiuni, in memorie sunt pastrate si date. Dispozitivele de intrare
/iesire iau informatii de la agenti externi catre masina si produc informatii 
pentru acesti agenti. Dispozitivele de intrare sunt (de obicei):
  1. tastatura;
  2. discheta;
  3. banda;
  4. CD-ROM.
Dispozitivele de iesire sunt (de obicei):
  1. ecranul terminalului;
  2. imprimanta;
  3. discheta;
  4. banda;
  5. CD-ROM.

Sistemul de operare consta intr-o colectie de programe speciale si are doua 
scopuri principale:
  1. coordoneaza resursele (memoria, procesorul, imprimanta) masinii. De 
     exemplu, daca un fisier este creat pe disc sistemul de operare are grija 
     de detaliile localizarii acestuia si  memoreaza numele, lungimea si data 
     creearii;
  2. produce instrumente necesare utilizatorilor, multe dintre ele sunt 
     folositoare utilizatorilor C. De exemplu, doua dintre acestea sunt un 
     editor de texte si un compilator de C.

Un cod C se numeste cod sursa, iar un fisier ce contine un cod sursa se numeste 
fisier sursa. Dupa ce a fost creat un fisier sursa, atunci se invoca un 
compilator de C. De exemplu, pentru sistemele MS-DOS se poate da comanda:
                        bc ex1.c   sau tcc ex1.c
iar pentru unele sisteme UNIX:
                        cc ex1.c
Daca nu sunt erori in ex1.c, atunci aceasta comanda produce fisierul executabil 
asociat (ex1.exe). Acum acesta poate fi rulat (executat) cu numele sau (ex1 
sau ex1.exe). 

In continuare, vom preciza trei dintre trasaturile procesului de compilare 
(mentionam ca asupra acestor notiuni, vom reveni cu detalii interesante intr-un
capitol viitor):
  1. invocarea preprocesorului; 
  2. invocarea compilatorului;
  3. invocarea incarcatorului.
Preprocesorul modifica o copie a codului sursa prin includerea altor fisiere si 
facand alte schimbari. Compilatorul traduce aceasta in cod obiect folosit de 
incarcator pentru producerea fisierului executabil final. Fisierul care contine 
codul obiect se numeste fisier obiect. Fisierele obiect, spre deosebire de 
fisierele sursa, nu se pot intelege asa usor. Cand spunem deci compilare, de 
fapt invocam preprocesorul, compilatorul si apoi incarcatorul.

Dupa ce scriem un program, acesta trebuie compilat si testat. Daca sunt 
necesare modificari, atunci codul sursa trebuie editat din nou. Asadar, 
partea proceselor de programare consta din ciclul:

             editare ---> compilare ---> executie
                ^^                    |                     |
                | |__________ |                     |
                |___________________________|


-----------------------
Un prim program
-----------------------
O sa incepem cu un exemplu de program C necesar pentru tiparirea unui sir pe 
ecran.

#include 

main()
 {
  printf("azi am inceput laboratoarele de C\n");
 }

Folosind un editor de texte, presupunem ca am scris si salvat acest fisier numit 
"ex1.c". Cand programul este compilat si rulat atunci va apare pe ecran sirul:

     azi am inceput laboratoarele de C

-------------      
Explicatii:
-------------
1. #include 

Liniile care incep cu "#" se numesc directive de preprocesare (precompilare). 
Acestea comunica cu preprocesorul. Aceasta directiva "#include" determina 
preprocesorul sa includa o copie a fisierului header "stdio.h" in acest punct 
al codului. Parantezele unghiulare din "" indica ca acest fisier se 
gaseste in biblioteca C (pentru compilatorul Borland 3.1 pentru MS-DOS, acesta 
se gaseste in subdirectorul BC31/INCLUDE). Am inclus acest fisier deoarece 
acesta contine informatii despre functia "printf()".

2. main()

Fiecare program are o functie numita "main", care se executa intai. Parantezele 
ce urmeaza dupa "main" indica compilatorului ca aceasta este o functie.

3. {

Acolada stanga incepe corpul fiecarei functii. O acolada dreapta corespunzatoare 
trebuie sa fie la sfarsitul functiei. 

4. printf()

Sistemul C contine o biblioteca standard de functii care poate fi utilizata in 
programe. "printf()" este o functie din biblioteca care tipareste pe ecran. 
Aceasta este o functie descrisa in biblioteca "stdio.h" (care se numeste 
prototipul functiei "printf()").

5. "azi am inceput laboratoarele de C\n"

Un sir constant in C consta dintr-un numar de caractere incadrate intre 
ghilimele. Acest sir este un argument al functiei "printf()". Caracterele \n 
de la sfarsitul sirului (se citesc "backslash n") reprezinta, de fapt, un 
singur caracter numit "newline". 

O forma echivalenta a programului de mai sus:

#include 

main()
 {
  printf("azi am inceput ");
  printf("laboratoarele de C\n");
 }

--------------
Observatii:
--------------
1. Primul "printf" contine la sfarsit un spatiu.

--------------------------------------
Variabile, expresii si asignari
--------------------------------------
In urmatorul exemplu vom ilustra folosirea variabilelor pentru manipularea 
valorilor intregi. Variabilele sunt folosite sa memoreze valori. Din moment ce
diferite tipuri de variabile sunt folosite sa memoreze diferite tipuri de date, 
tipul fiecarei variabile trebuie specificat. 

Pentru a ilustra aceasta idee vom calcula cate ore si minute contin un anumit 
numar de zile. Algoritmul ar fi:

  1. asigneaza un numar de zile unei variabile;
  2. calculeaza numarul de ore si memoreaza-l intr-o variabila;
  3. calculeaza numarul de minute si memoreaza-l intr-o variabila;
  4. afiseaza numarul de zile, ore si minute pe ecran.
  
Urmatorul program scris in C reprezinta implementarea algoritmului precedent: 

#include 

main()
 {
  int zile, ore, minute;
  
  zile=7;
  ore=24*zile;
  minute=60*ore;
  printf("O saptamana are %d ore, %d minute.\n",ore, minute);
 }
 
Cand compilam si rulam acest program, pe ecran va apare mesajul:

        O saptamana are 168 ore, 10080 minute.

-------------
Explicatii:
-------------
1. Linia

       int zile, ore, minute; 

reprezinta o declaratie de variabile. Variabilele zile, ore, minute sunt 
declarate de tip "int", unul dintre cele mai importante tipuri din C. O 
variabila de tip "int" poate lua o valoare intreaga intre -32678 si 32677. 
Toate variabilele dintr-un program trebuie declarate inainte de a fi utilizate.
Declaratiile, la fel ca si instructiunile, au la sfarsit ";".

2. Linia 

             zile=7;

reprezinta o instructiune de atribuire (sau asignare). Semnul "=" este 
operatorul de asignare de baza in C. Valoarea expresiei din partea dreapta a 
simbolului "=" este atribuita variabilei din partea stanga. 

3. Instructiunea

     printf("O saptamana are %d ore, %d minute.\n",ore, minute);
     
este similara celei prezentate in exemplul precedent, dar are trei argumente. 
Primul argument, intotdeauna un sir de caractere, se numeste sir de control. 
Aici, intalnim specificarea de conversie (care se mai numeste format) "%d". 
Formatele "%d" determina tiparirea valorilor expresiilor corespunzatoare (al
doilea si al treilea argument) in formatul intregilor zecimali. Asadar, primul 
format "%d" corespunde cu valoarea variabilei "ore", iar cel de-al doilea 
format "%d" cu valoarea variabilei "minute".


In C, toate variabilele trebuie declarate inainte de a fi utilizate in expresii
si instructiuni. Forma generala a unui program simplu este: 

directive de precompilare

main()
 {
  declaratii
  instructiuni
 }
 
Un nume de variabila, numit si identificator, consta dintr-o secventa de litere
cifre si "underscore", dar fara a incepe cu cifra. Cuvintele cheie, numite si 
cuvinte rezervate, nu pot fi utilizate ca nume de variabile. Exemple de cuvinte 
cheie: char, int, float.

Operatorii binari

                +  -  *  /  %

sunt folositi pentru adunare, scadere, inmultire, impartire sau modul.

Exemple: 5 % 2 = 1 si 7 % 4 = 3.

Evident, in expresia a % b, b nu trebuie sa fie zero, din moment ce nu se 
poate face impartirea cu zero. 


----------------------------------------------------------------
Un exemplu de utilizare a variabilelor de tip float
----------------------------------------------------------------
#include 

main()
 {
  float x, y;
  
  x = 1.0;
  y = 2.0;
  printf("Suma dintre x si y este %f.\n", x+y);
 }
 
Pe ecran se va afisa

         Suma dintre x si y este 3.000000.
         
--------------
Observatii:         
--------------
1. Linia 
                
                float x, y;
                
semnifica declararea variabilelor x si y de tip "float" (deci de tip real). In 
realitate sunt numere rationale din intervalul

           [-10^{308},-10^{-308}] U [10^{-308},10^{308}]
           
2. Linia           

          printf("Suma dintre x si y este %f.\n", x+y);
          
are doua argumente si reprezinta o tiparire la ecran. De remarcat, ca spre 
deosebire de exemplele precedente (unde foloseam formatul %d), aici folosim 
formatul pentru numere reale, care este "%f".

3. Precizarea tipului variabilelor este esential. De exemplu, daca, sa zicem,
ca x=7.0 si y=2.0, sunt declarati ca fiind de tip float, atunci x/y se 
evalueaza la 3.5. Daca, insa x=7 si y=2, sunt declarati ca fiind de tip int, 
atunci x/y se evalueaza la 3 (ramane doar partea intreaga).


----------------
Initializarea
----------------
Initializarea variabilelor se poate face si cand se declara acestea. De exemplu, 
 putem scrie: 

    char c='A';
    int i=1;
    
Putem astfel modifica programul precedent, inlocuind liniile 

    int zile, ore, minute;
    
    zile=7;
    
cu 
 
    int zile=7, ore, minute;
    

--------------
Observatii:
--------------
1. De obicei, pentru initializarea unei variabile se folosesc constante sau 
expresii constante. Se pot insa folosi si variabile care au deja valoarea 
precizata. De exemplu, urmatoarea secventa de program este corecta:

    int zile=7, ore=zile * 24, minute=ore * 60;
    

------------------------------------
Folosirea directivei #define
------------------------------------
Reamintim ca in procesul de compilare a programelor C, intai este invocat 
preprocesorul. De exemplu, pot fi incluse fisiere, sau anumite siruri de 
caractere specificate pot fi modificate in alte siruri. Directivele de 
preprocesare incep cu caracterul # (in C traditional, acesta trebuie pus pe 
prima coloana, pe cand in ANSI C poate fi precedat de spatii). Se recomanda 
scrierea # pe prima coloana, iar a directivelor de precompilare la inceputul 
programului. Iata cateva exemple de folosire a directivei "#define":

    #define LIMIT 100
    #define PI    3.14159
    
--------------
Observatii:    
--------------
1. Daca aceste directive de preprocesare apar la inceputul fisierului, atunci 
in momentul compilarii preprocesorul schimba toate aparitiile identificatorului
LIMIT la 100 si a lui PI cu 3.14159. Singurele care raman neschimbate sunt 
sirurile constante. De exemplu, preprocesorul va schimba

    printf("PI = %f\n", PI);   in   printf("PI = %f\n", 3.14159);
    
Deoarece identificatorul PI se va inlocui peste tot (cu exceptia sirurilor 
constante) in 3.14159, atunci acesta se va numi constanta simbolica. 

2. Directiva #define poate aparea oriunde in program, dar ea afecteaza numai 
liniile care urmeaza acesteia. 

3. Prin conventie, identificatorii care trebuie schimbati de preprocesor se 
scriu cu majuscule.


--------------------------------------------------
Avantaje ale folosirii directivei #define
--------------------------------------------------
1. Lizibilitate marita. Se refera la citirea si intelegerea rapida a fisierului
sursa (PI stim ce inseamna si ne amintim ca este 3.ceva, deci nu trebuie sa 
scriem de fiecare data valoarea sa);

2. Schimbarile ulterioare ale unor valori constante se face foarte usor. De 
exemplu, vrem sa modificam valoarea lui LIMIT la 10000. In locul liniei

                #define LIMIT  100
                
scriem 

                #define LIMIT  10000

Daca nu am fi folosit acest mod de definire a constantei LIMIT, atunci ar fi 
trebuit sa modificam peste tot in program 100 cu 10000.


-----------------------------------------------
Folosirea functiilor printf() si scanf()
-----------------------------------------------
 Functiile de tiparire, respectiv de citire, "printf()" si "scanf()" au 
urmatoarele argumente:

    sir_de_control   si   celelalte_argumente
    
unde sir_de_control este un sir care poate contine specificatii de conversie, 
sau formate. O specificare de conversie incepe cu caracterul % si se termina cu
caracterul de conversie. De exemplu, in formatul %d, litera "d" este caracterul 
de conversie.

---------------------------
Folosirea lui printf()
---------------------------
Reamintim ca formatul %d este folosit pentru scrierea valorii unei expresii ca 
un intreg zecimal. In mod similar:

  -  %c este folosit pentru tiparirea unei expresii ca un caracter
  -  %f este folosit pentru tiparirea unei expresii reale 
  -  %s este folosit pentru tiparirea unui sir de caractere
  
-----------
Exemplu: Fie instructiunea:
-----------
 printf("Multime de argumente: %s %d %f %c%c\n","one",2,2.33,'G','O');
 
Argumentele lui "printf()" sunt separate de virgula, deci avem sase argumente. 
Primul argument este sirul de control. Obtinem corespondenta:
    %s <---> "one"
    %d <---> 2
    %f <---> 2.33
    %c <---> 'G'
    %c <---> 'O'
    
Cand se executa programul ce contine aceasta instructiune, obtinem:

    Multime de argumente: one 2 2.330000 GO
    
--------------
Observatii:
--------------
1. Daca instructiunea "printf()" contine prea multe caractere, atunci se poate
 scrie aceasta pe mai multe linii, separate prin virgula. De exemplu, putem 
 scrie:

    printf("%s%s\n",
           "Aceasta instructiune se va scrie ",
           "pe o linie de text foarte lunga.\n");

Tabelul de mai jos descrie cum caracterele de conversie afecteaza argumentele 
corespunzatoare.

      printf()
 |-------------------------------------------------------------------------|
 |  Caracter  |                                                            |
 |     de     |  Cum este tiparit argumentul corespunzator ?               |
 |  conversie |                                                            |
 |-------------------------------------------------------------------------|
 |     c      |     ca un caracter                                         |
 |     d      |     ca un intreg zecimal                                   |
 |     e      |     ca un numar in virgula flotanta in notatia stiintifica |
 |     f      |     ca un numar in virgula flotanta                        |
 |     g      |     in format e sau f (alegand cel mai scurt dintre ele)   |
 |     s      |     ca un sir                                              |
 |-------------------------------------------------------------------------|

Cand un argument este tiparit, locul unde este tiparit se numeste campul sau,
iar numarul de caractere ale acestui camp se numeste lungimea campului. Aceasta
lungime poate fi specificata intr-un format ca un intreg plasat intre 
caracterul % si caracterul de conversie. De exemplu, instructiunea

                printf("%c%3c%7c\n", 'A', 'B', 'C');
                
va tipari
                A  B      C
                
Pentru numerele in virgula flotanta, putem controla precizia (numarul de cifre 
zecimale), la fel ca lungimea campului. Forma generala a formatului este 
                        %m.nf
si semnifica ca m este lungimea campului, iar n precizia. Formatul %mf 
specifica doar lungimea campului, iar formatul %.nf numai precizia. De exemplu,
instructiunile:

        printf("Numere1: %.1f %.2f %.3f\n", 1.0, 2.0, 3.0);
        printf("Numere2: %7.1f %7.2f %7.3f\n", 4.0, 5.0, 6.0);

vor avea ca efect afisarea:

        Numere1: 1.0 2.00 3.000
        Numere2:    4.0   5.00  6.000

--------------------------
Folosirea lui scanf()
--------------------------
Functia "scanf()" este asemanatoare cu "printf()", dar este folosita pentru 
intrari in loc de iesiri. Primul sau argument este un sir de control care are 
formatele corespunzatoare cu variatele moduri de interpretare a sirurilor de 
intrare. Dupa sirul de control urmeaza adresele variabilelor. Adresa unei
variabile este locul din memorie unde este memorata variabila (vom reveni in 
capitolele viitoare). Simbolul "&" reprezinta operatorul de adresa. De exemplu,

        scanf("%d", &x);
        
formatul %d implica interpretarea caracterelor tiparite la intrare ca un intreg 
zecimal, si apoi memorarea valorii variabilei la adresa lui x.        

Tabelul de mai jos descrie efectele caracterelor de conversie din formate folosite 
de functia scanf().

      scanf()
 |-------------------------------------------------------------------------|
 |  Caracter  |                                                            |
 |     de     |     La ce caractere se face convertirea ?                  |
 |  conversie |                                                            |
 |-------------------------------------------------------------------------|
 |     c      |     la un caracter                                         |
 |     d      |     la un intreg zecimal                                   |
 |     f      |     la un numar in virgula flotanta (float)                |
 |     lf     |     la un numar in virgula flotanta (double)               |
 |     Lf     |     la un numar in virgula flotanta (long double)          |
 |     s      |     la un sir                                              |
 |-------------------------------------------------------------------------|

-----------
Atentie ! Functia "prinf()" foloseste formatul %f pentru tiparirea numerelor
-----------   float si double, pe cand "scanf()" foloseste formatul %f pentru
                citirea unui float si %lf pentru citirea unui double.
          
------------
Exemplu: Aria unui cerc.
------------          
#include 

#define PI 3.141592653589793

main()
 {
  double raza;
  
  printf("\n%s\n\n%s",
         "Acest program calculeaza aria cercului",
         "Dati raza:");
  scanf("%lf", &raza);
  printf("\n%s\n%s%.2f%s%.2f%s%.2f\n%s%.5f\n\n",
         "Aria = PI * raza * raza",
         "     = ", PI, " * ", raza, " * ", raza,
         "     = ", PI * raza * raza);
 }
 
Presupunem ca la executia programului introducem raza egala cu 2.333. Atunci 
vor apare pe ecran:

  Acest program calculeaza aria cercului
  
  Dati raza: 2.333
  
  Aria = PI * raza * raza
       = 3.14 * 2.33 * 2.33
       = 17.09934
       
Daca am calcula separat (pe hartie), am obtine Aria = 3.14 * 2.33 * 2.33 
= 17.046746, numar care nu coincide cu cel furnizat de calculator. Justificarea
este aceea ca PI si raza sunt tiparite doar cu doua zecimale, pe cand valorile 
lor sunt pastrate in memorie cu precizie mai mare.


-----------------------------
Instructiunea "while"
-----------------------------
Instructiunea while face parte din categoria actiunilor repetitive. Pentru a 
intelege aceasta instructiune, vom face un exemplu de adunare a numerelor de la
1 la 10.

-------------
Exemplu:
-------------
#include 

main()
 {
  int i=1, suma=0;

  while (i<=10) 
   {
    suma = suma + i;
    i = i + 1;
   }
  printf("Suma primelor 10 numere este %d\n",suma);
 }

-------------
Explicatii:
-------------
1. La linia 

           int i=1, suma=0;

se declara variabilele i si sum de tip int si sunt initializate cu 1 si 0, 
respectiv.

2. Constructia 

  while (i<=10)
   {
    suma = suma + i;
    i = i + 1;
   }

reprezinta o instructiune while (sau iteratie while). Mai intai, se evalueaza 
expresia i<=10. Cum valoarea initiala a lui i este egala cu 1, rezulta ca se 
vor executa instructiunile dintre acolade. Astfel, variabila suma va fi 
asignata cu vechea valoare a lui suma la care se adauga valoarea lui i. Deci, 
suma se evalueaza la 1. Apoi, variabila I se evalueaza la suma dintre vechea 
valoare a lui i (i=1) si 1, deci este egala cu 2. In acest moment, executia 
revine la inceput adica evaluam expresia i<=10. Cum valoarea lui i este 2, 
rezulta ca se va executa iar corpul lui while. La sfarsitul acestei iteratii,
suma este evaluata la 1+2, iar i la 3. Se observa usor ca i<=10 este tot 
adevarata, deci se va executa din nou corpul lui while. La sfarsitul celei de-a
treia iteratii, sum este evaluata la 1+2+3, iar i la 4. Procesul continua pana
cand valoarea lui i este 11, care implica falsitatea expresiei i<=10. Astfel se
ese din bucla while.

3. Instructiunea

    printf("Suma primelor 10 numere este %d\n", suma);

va afisa mesajul Suma primelor 10 numere este 55.

4. Formatul general al instructiunii while este

    while (expresie)
      instructiune

unde instructiune poate fi o singura instructiune sau un grup de instructiuni 
delimitate prin { si } (care se mai numeste si instructiune compusa).

-----------------------------------------------
Generalizarea problemei precedente
-----------------------------------------------
Dorim sa citim mai multe numere (fara a sti aprioric numarul lor si care sunt 
acestea) si dorim sa afisam suma lor.

Consideram urmatorul algoritm cu patru pasi:

1. Initializarea a doua variabile contor si suma;
2. Afisarea unor mesaje utile citirii numerelor;
3. Citirea repetata a numerelor, incrementarea variabilei contor si
   adunarea numarului citit la suma;
4. Afisarea celor doua valori ale variabilelor.

Instructiunea while este una din cele trei constructii existente in C menite 
sa descrie actiuni repetitive. In solutia noastra, utilizam valoarea returnata
de functia "scanf()" pentru a controla instructiunea while. Consideram 
urmatorul cod C:

#include 

main()
 {
  int contor = 0;
  float suma = 0.0, x;

  printf("Suma urmatoarelor numere va fi calculata\n");
  printf("Dati numerele:\n"); 
  while (scanf("%f", &x)==1)
   {
    contor = contor +1;
    suma = suma +x;
   } 
  printf("\n%s%5d\n%s%12f\n\n",
         "Numarul de numere: ", contor,
         "Suma lor: ", suma);
 }

--------------
Explicatii:
--------------
1. scanf("%f", &x)==1

Simbolul == reprezinta operatorul de egalitate. Expresia a==b intoarce true 
daca valoarea lui a este egala cu valoarea lui b. De exemplu, 1==1 intoarce 
true, 2==3 intoarce false. Functia "scanf()" are rolul de a citi caractere 
scrise de utilizator, sa le converteasca la float, si sa plaseze aceasta 
valoare la adresa lui x. Daca totul se desfasoara cu succes, atunci scanf() 
intoarce valoarea 1, adica true. Daca din anumite motive, procesul de conversie
esueaza, atunci se intoarce valoarea 0 (deci false). Daca nu mai introducem 
nici o data (Control^z in MD-DOS, CR urmat de Control^d in UNIX), atunci 
scanf() va intoarce valoarea -1 (deci tot false).

2. while (scanf("%f", &x)==1)
   {
    contor = contor +1;
    suma = suma +x;
   }

Dupa cum am vazut mai sus, bucla while se executa atata timp cat scanf("%f", 
&x)==1 se evalueaza la true. Iteratia se incheie cand tastam Control^z sau ceva
ce nu se poate converti la float, de exemplu 'a' sau CR. La fiecare executie a
buclei se incrementeza variabila contor, iar valoarea variabilei suma creste cu
valoarea lui x (citita de la tastatura).

3. printf("\n%s%5d\n%s%12f\n\n",
         "Numarul de numere: ", contor,
         "Suma lor: ", suma);

Presupunem ca executam acest program pentru numerele

  1.1 2.02 3.003 4.0004 5.00005
  
Pe ecran va apare rezultatul:

       Numarul de numere: 5
       Suma lor: 15.123449
    
---------------
Observatii:
---------------
1. Daca numaram spatiile, observam ca valoarea lui contor a fost tiparita pe un
camp de 5 caractere, iar suma pe 12 caractere. Aceasta este cauzata de 
formatele "%5d" si "%12f". Retineti ca tiparirea zecimalelor pentru suma este 
gresita de la a treia zecimala.


---------------------------------------------
Stilul de redactare al programelor
---------------------------------------------
Un stil bun de scriere a codului este esential pentru arta programarii. 
Aceasta faciliteaza citirea, scrierea si intretinerea programelor. Un stil bun
foloseste:

1. spatii goale si comentarii, astfel incat codul este usor de citit si de 
inteles;

2. utilizarea indentarii este cruciala, care indica cu precizie structurile de 
control. De exemplu, in constructia:

    while (expresie)
      instructiune
      
indentarea instructiunii indica ca executia acesteia este sub controlul 
iteratiei while;

3. alegerea de nume sugestive pentru variabile;

4. corespondenta dintre acolade. De exemplu, urmatorul program este scris in 
   stilul "Bell Labs industrial programming style" (#,{,},m pe prima coloana).

#include 
#include 

#define GO "Start"

main()
{

}

---------------
Observatii: 
---------------
1. Programatorii incepatori uneori cred ca vor "sparge" piata cu stilul lor propriu de redactare a programelor. Atentie ! Utilizati 
strategia care este deja in uz.


-----------------------------------------
Erori de programare frecvente
-----------------------------------------
Mai ales la inceputul invatarii programarii pe calculator, se fac multe erori 
simple, cum ar fi:

1. neinchiderea sirului cu ghilimele drepte. Cand compilatorul intalneste 
ghilimeaua stanga, atunci incepe sa colecteze toate caracterele care urmeaza 
spre a forma un sir de caractere, pana intalneste ghilimeaua dreapta. Daca 
aceasta nu exista, atunci compilatorul da mesajul de eroare, de tipul:

    Unterminated string or character constant
    
2. scrierea gresita a numelui variabilelor;

3. nedeclararea lor.

In general, compilatorul da un mesaj de eroare potrivit, alteori din cauza 
interpretarii separate, nu. De exemplu, scriem gresit "prinf()" in loc de 
"printf()". Atunci compilatorul va da un mesaj prin care ne informeaza ca nu 
gaseste functia "prinf()". Deci, el nu isi da seama de omiterea unei litere, 
ci o interpreteaza in mod diferit.

4. daca dorim sa citim o variabila de tip double, atunci in functia "scanf()" 
trebuie sa specificam formatul "%lf";

5. faptul ca uneori uitam ca in formatul "%m.nf" pentru afisarea cu virgula 
mobila, m semnifica lungimea campului. De exemplu, pentru a specifica doua 
zecimale la dreapta si trei la stanga, nu trebuie sa scriem %2.3f, ci %6.3f 
deoarece se numara si punctul zecimal;

6. poate cea mai frecventa greseala cand se foloseste scanf() este uitarea 
operatorului de adresa. Daca, de exemplu, scriem

    scanf("%d%d", a, b) in loc de scanf("%d%d", &a, &b)
    
atunci compilatorul nu se va "prinde" de eroare. Bineinteles, ca vom obtine 
rezultate eronate (run-time error) care sunt ceva mai greu de corectat. 


---------------------------------------
Redirectarea intrarii si iesirii
---------------------------------------
Putem citi valorile variabilelor dintr-un fisier, nu neaparat de la tastatura. 
De exemplu, fisierul nostru executabil se numeste "ex1.exe". Pentru a extrage 
datele din fisierul de intrare "in.dat", dam comanda

                ex1.exe < in.dat
                
Putem, de asemenea, sa scriem valorile unor variabile intr-un fisier extern, 
sa zicem "out.dat". Astfel dam comanda

                ex1.exe > out.dat
                
Evident, daca se doreste atat citirea unor variabile din fisier, cat si 
scrierea rezultatelor in alt fisier, atunci se va da comanda

                ex1.exe < in.dat > out.dat

-------------
Exemplu:
-------------
#include 

main()
 {
  char ch;
  
  while (scanf("%c", &ch) ==1)
    {
     printf("%c", ch);
     printf("%c", ch);
    }
 }


-----------------------------------------------
Exercitii propuse spre implementare
-----------------------------------------------
1. Presupunem ca dispunem de rezultatele din anul curent relative la cursul de 
schimb valutar dintre leu, dolar, marca si franc. Sa se scrie un program C care
deseneaza (cu caractere ASCII) graficul evolutiei raportului leu/valuta, unde 
valuta={dolar, marca, franc}. Apoi, desenati graficul raportului dolar/marca si
marca/franc.

2. Scrieti un program C care primeste la intrare un numar de secunde, si 
intoarce numar maxim de ore, de minute, de secunde care este echivalent ca timp
. De exemplu, 7384 secunde este echivalent cu 2 ore, 3 minute si 4 secunde.

3. Folosind o bucla while, scrieti un program C care calculeaza al n-lea termen 
din sirul din Fibonacci. Reamintim ca sirul lui Fibonacci este dat de recurenta
liniara de ordin 2: 

    a_1=a_2=1;
    a_{n+2}=a_{n+1}+a_n, n>=1