$$ \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} \newcommand{\mod}{\,\mathrm{mod}\,} \renewcommand{\div}{\,\mathrm{div}\,} \newcommand{\metar}{\,\mathrm{m}} \newcommand{\cm}{\,\mathrm{cm}} \newcommand{\dm}{\,\mathrm{dm}} \newcommand{\litar}{\,\mathrm{l}} \newcommand{\km}{\,\mathrm{km}} \newcommand{\s}{\,\mathrm{s}} \newcommand{\h}{\,\mathrm{h}} \newcommand{\minut}{\,\mathrm{min}} \newcommand{\kmh}{\,\mathrm{\frac{km}{h}}} \newcommand{\ms}{\,\mathrm{\frac{m}{s}}} \newcommand{\mmin}{\,\mathrm{\frac{m}{min}}} \newcommand{\smin}{\,\mathrm{\frac{s}{min}}} $$
Priručnik za početnike (C++) / Traženje grešaka u programu

Traženje grešaka u programu

  • Dozvoljeno polaganje
  • Lekcije
  • Nema
  • Vugdelija
  • 7/29/2015

Često se dešava da naš program radi, ali ne uvek ono što smo očekivali. Ponekad čak i ne primetimo da se to dešava. Program uvek radi ono što smo mu rekli da radi, a ne ono što smo mislili. Zbog toga je važno da se program pažljivo i detaljno testira nakon što ga napišemo.

 

U ovoj lekciji ćeš videti kako možeš da potražiš grešku, nakon što otkriješ da za neke ulazne podatke tvoj program ne daje očekivani odgovor.

 

Primer:

Promenljiva sirinaOrmana sadrži širinu ormana, a promenljiva visinaOrmana visinu tog ormana. Pored ormana je nekoliko levih i desnih vrata. Sva leva vrata su iste širine i visine, koje se nalaze u promenljivim  sirinaLevihVrata, visinaLevihVrata, dok su širine i visine svih desnih vrata u promenljivama sirinaDesnihVrata, visinaDesnihVrata. Da bi orman mogao da se zatvori ovakvim vratima, potrebno je da:

  • Leva i desna vrata budu iste visine, koja se u visini ormana sadrži ceo broj puta;
  • Leva i desna vrata, kada se stave jedna pored drugih, zajedno tačno pokrivaju širinu ormana.

 

Proveriti da li orman može da se zatvori ovakvim vratima:

  1. ako se vrata ne uklapaju po širini, ispisati "Vrata nisu odgovarajuce sirine".
  2. ako se vrata uklapaju po širini, ali leva i desna vrata nisu iste visine, ispisati "Vrata nisu jednake visine".
  3. ako se vrata uklapaju po širini i jednake su visine, ali visina ormana ne može da se pokrije celim brojem (jednakih levih i desnih) vrata, ispisati "Vrata nisu odgovarajuce visine".
  4. ako orman može da se zatvori datim vratima, ispisati koliko parova vrata je potrebno za to.

 

Sledeća slika ilustruje slučajeve a, b, c, d (u slučaju d potrebno je 3 para vrata).


 

Recimo da smo ovaj program kao rešenje postavljenog zadatka:

 

#include <iostream>
int main()
{

    int sirinaOrmana, visinaOrmana;
    
int sirinaLevihVrata, visinaLevihVrata;
    
int sirinaDesnihVrata, visinaDesnihVrata;

    std::cout << "Unesite sirinu i visinu ormara: ";
    std::cin >> sirinaOrmana >> visinaOrmana;
    std::cout << 
"Unesite sirinu i visinu levih vrata: ";
    std::cin >> sirinaLevihVrata >> visinaLevihVrata;
    std::cout << 
"Unesite sirinu i visinu desnih vrta: ";
    std::cin >> sirinaDesnihVrata >> visinaDesnihVrata;
 
    
if(sirinaOrmana = sirinaLevihVrata + sirinaDesnihVrata)
    {
        
if (visinaLevihVrata = visinaDesnihVrata)
        {
            
if (visinaOrmana % visinaLevihVrata == 0)
            {
                std::cout << 
"Potrebno je "<< 

                    visinaOrmana / visinaLevihVrata <<

                    " parova vrata. ";
            }
            
else
            {
                std::cout << 
"Vrata nisu odgovarajuce visine.";
            }
        }
        
else
        {
            std::cout << 
"Vrata nisu jednake visine.";
        }
    }
    
else
    {
        std::cout << 
"Vrata nisu odgovarauce sirine. ";
    }
    
    std::cout << std::endl;
    
return 0;
}

Kada napišemo program, kao prvo proveravamo da li on može da se izvrši. Pokrenemo prevođenje programa i vidimo u prozoru ispod:

 

Uokvireni deo govori za koliko je projekata pripremanje za izvršavanje (prevođenje, kompajliranje) bilo redom uspešno (succeeded), neuspešno (failed), spremnih od ranije (up-to-date) i izostavljenih (skipped). U ovom konkretnom slučaju, mi imamo samo jedan projekat i on je uspešno preveden.

 

Normalno, sada želimo da vidimo kako naš program radi. Da bismo se koliko-toliko uverili da je program ispravan, trebalo bi da smislimo različite test-primere, tako da nateramo svaki deo (svaku granu) programa da se izvrši.

 

Pre pokretanja programa treba proveriti da je trenutna konfiguracija "debug" (vidi lekciju Postepeno izvršavanje programa).

                             

Isprobajmo program sa sledećim podacima:

Širina ormana: 90;

Visina ormana: 200;

Širina levih vrata: 45;

Visina levih vrata: 50;

Širina desnih vrata: 45;

Visina desnih vrata: 50;

Vidimo da se dobija tačan odgovor ("Potrebno je 4 parova vrata" je rezultat koji smo želeli da dobijemo, bez obzira na gramatičku neispravnost).

 

Probajmo sada sa ovim podacima:

Širina ormana: 90;

Visina ormana: 200;

Širina levih vrata: 45;

Visina levih vrata: 60;

Širina desnih vrata: 45;

Visina desnih vrata: 60;

Rezultat je ponovo dobar ("Vrata nisu odgovarajuce visine.")

 

Da li je ovo dovoljno proveravanja? Ne, rekli smo da treba da pokušamo da prođemo kroz svaku granu programa. Hajde da pokušamo da dobijemo odgovor "Vrata nisu jednake visine". Za to bi trebalo da nam posluži primer sa podacima

Širina ormana: 90;

Visina ormana: 200;

Širina levih vrata: 45;

Visina levih vrata: 60;

Širina desnih vrata: 45;

Visina desnih vrata: 50;

Izvršimo program i dobijemo: "Potrebno je 4 parova vrata". Zašto? Trebalo je da dobijemo "Vrata nisu jednake visine", zar ne?

 

Hajde da izvršavamo program naredbu po naredbu i pratimo šta se dešava.

 

Pri izvršavanju if naredbe sa sledeće slike, trebalo bi da odemo u else granu jer visine levih i desnih vrata nisu jednake (leva su 60 a desna 50).

 

 

 

Događa se međutim da ulazimo u granu, kojoj odgovara tačan uslov!

 

 

Ako pogledamo vrednosti promenljivih, vidimo da se vrednost visinaLevihVrata upravo promenila (crvena je) i sada je jednaka sa vrednošću visinaDesnihVrata: 

 

 

Kako je to moglo da se dogodi? Program se ponaša kao da je promenljivoj visinaLevihVrata upravo dodeljena vrednost visinaDesnihVrata. Pažljivijim gledanjem u if naredbu u liniji 16, uočavamo da tamo piše

visinaLevihVrata = visinaDesnihVrata umesto visinaLevihVrata == visinaDesnihVrata (sa dva znaka jednakosti, što označava poređenje).

Za one koji mogu da razumeju tekst na sledećoj slici, pomenimo da smo pri prevođenju programa dobili upozorenje da vršimo dodeljivanje vrednosti (assignment) u okviru uslova if naredbe, i to na dva mesta (u linijama 14 i 16).

 

Dodeljivanje vrednosti u if naredbi nije uobičajeno i veliki broj programera smatra da ovo ne treba raditi, ali je to ipak moguće.

 

Savet: Treba da obratiš pažnju na upozorenja koja dobijaš pri prevođenju programa, da pokušaš da ih razumeš i uzmeš u obzir. Nemoj da brineš ako ti neki put nisu jasna, ona mogu da budu vrlo nerazumljiva, a ponekad nisu ni bitna. Ipak, ako ih uočiš i rastumačiš, mogu da ti uštede mnogo kasnijeg truda u traženju grešaka.

 

Savet: Svako upozorenje ili greška koju dobijemo ima svoju oznaku, odnosno kod. Na primer, ovo upozorenje ima kod C4706. Ako ne razumeš poruku, koristeći pomenuti kod možeš da potražiš na internetu detaljnije objašnjenje, ili primer koji ilustruje kakav program dovodi to te poruke.

 

Nakon što ispravimo linije 14 i 16 i umesto "=" stavimo "==", nastavimo sa testiranjem dok se ne uverimo da u svim tipovima situacija program daje ispravan odgovor.

 

#include <iostream>
int main()
{

    int sirinaOrmana, visinaOrmana;
    
int sirinaLevihVrata, visinaLevihVrata;
    
int sirinaDesnihVrata, visinaDesnihVrata;

    std::cout << "Unesite sirinu i visinu ormara: ";
    std::cin >> sirinaOrmana >> visinaOrmana;
    std::cout << 
"Unesite sirinu i visinu levih vrata: ";
    std::cin >> sirinaLevihVrata >> visinaLevihVrata;
    std::cout << 
"Unesite sirinu i visinu desnih vrta: ";
    std::cin >> sirinaDesnihVrata >> visinaDesnihVrata;
 
    
if(sirinaOrmana == sirinaLevihVrata + sirinaDesnihVrata)
    {
        
if (visinaLevihVrata == visinaDesnihVrata)
        {
            
if (visinaOrmana % visinaLevihVrata == 0)
            {
                std::cout << 
"Potrebno je "<< 

                    visinaOrmana / visinaLevihVrata <<

                    " parova vrata. ";
            }
            
else
            {
                std::cout << 
"Vrata nisu odgovarajuce visine.";
            }
        }
        
else
        {
            std::cout << 
"Vrata nisu jednake visine.";
        }
    }
    
else
    {
        std::cout << 
"Vrata nisu odgovarauce sirine. ";
    }
    
    std::cout << std::endl;
    
return 0;
}

 

 

Možemo reći da smo u ovom primeru imali sreće što je greška takva da računar (program za prevođenje) daje upozorenje koje skreće pažnju na problem. Za neke greške koje napravimo, nećemo moći da dobijemo nikakvo upozorenje, jer ne radimo ništa neuobičajeno ili sumnjivo. Na primer, da smo umesto

    if(sirinaOrmana == sirinaLevihVrata + sirinaDesnihVrata)

omaškom napisali

    if(sirinaOrmana == sirinaLevihVrata - sirinaDesnihVrata)

ne bi bilo ni upozorenja. Programu za prevođenje je jednako logično da na datom mestu stoji minus kao i plus, jer on nema pojma o tome šta mi pokušavamo da izračunamo. Zato je i bitno da savladamo veštinu nalaženja grešaka onako kako je opisano u ovoj lekciji, a to se postiže vežbanjem. Osećaj zadovoljstva kada ti program proradi kako treba, pomoći će ti da u tom vežbanju istraješ i stekneš rutinu.