Programowanie w Visual C++ 2010

Spis treści

Błędy w kodzie cz. 1 – błędy syntaktyczne

Trochę zmęczenia, roztargnienia czy nieuwagi sprawiają, że czasami program działa nie tak, jak powinien, lub w ogóle nie może się skompilować. W niniejszym samouczku przyjrzymy się najczęściej popełnianym błędom syntaktycznym i nauczymy się je poprawiać.

Na wstępie...

Każdy programista, w szczególności ten początkujący, jest bohaterem takiej (lub podobnej) historii:

Nareszcie skończyłam pisać program! Ale się nad nim napracowałam... Trzeba teraz sprawdzić, czy wszystko dobrze działa... Zatem, skompiluję go i... Hola, hola! A cóż to? Czemu się nie chce skompilować?! Przecież kod napisałam poprawnie... Ach, zabrakło średnika w 134 linii! Zaraz to poprawię i ponownie skompiluję... Uff, tym razem się udało bez problemów.

Zauważmy, programistka miała do czynienia z pewnym rodzajem błędu. To tzw. błąd syntaktyczny (składniowy, ang. syntax error), który uniemożliwia kompilację programu – jest wykrywany na podstawie analizy kodu. Języki programowania mają ściśle określone reguły tworzenia programów. Podobnie jest przecież w językach, którymi posługują się ludzie w codziennej komunikacji – każdy z nich ma sprecyzowaną gramatykę. Na przykład zdania "Gegessen zu viel Ich habe.", "Eaten too much I have.", "Dużo za zjadłem ja." nie są poprawne syntaktycznie.

Podczas próby kompilacji kodu z błędami syntaktycznymi, ujrzymy taki komunikat: Komunikat przy błędach kompilacji

UWAGA! Wczytajmy się uważnie w treść komunikatu! Oznacza on: Wystąpiły błędy przy kompilacji. Czy chcesz kontynuować i uruchomić ostatnią działającą wersję programu?

Widząc ten komunikat, zawsze klikamy No.

Może wystąpić taka sytuacja, że popełniliśmy jeden błąd syntaktyczny, a mimo to w panelu Output pojawiają się informacje o kolejnych. Korygowanie błędów zaczynamy zawsze od pierwszego na liście! Niestety, kompilator nie jest stworzeniem grzeszącym inteligencją; często drugi zgłoszony "błąd" mogą być konsekwencją pierwszego; po poprawieniu pierwszego może się okazać, że jednak wszystko jest dalej w porządku.

Rodzaje błędów syntaktycznych

Średniki, średniki i jeszcze raz średniki; a właściwie ich brak

Brak średnika na końcu instrukcji jest chyba najczęściej występującym błędem składniowym niestety kompilator bardzo źle reaguje na tego typu pomyłki i odmawia współpracy powoduje to niemałą frustrację dobrze że poprawienie tego nie jest bardzo trudne inaczej to by dopiero było

Trudno zrozumieć powyższy tekst? Brakuje w nim w szczególności kropek na końcu zdań, nieprawdaż? Do którego zdania przynależy słowo "niestety"? Powinno być "(...) jest chyba najpopularniejszym błędem, niestety." czy "Niestety, kompilator bardzo źle reaguje (...)"? Trudno jest nam więc odczytać dokładne znaczenie wypowiedzi, w której brakuje znaków interpunkcyjnych. Podobnie "czuje się" kompilator, kiedy nie widzi średników na końcu instrukcji, ponieważ nie ma pojęcia, co jest jednym, a co innym rozkazem.

Zatem zapamiętajmy: instrukcja = zdanie, a średnik = kropka.

Średniki są też używane w innych sytuacjach, a mianowicie — stawia się je po definicji struktury czy klasy.

struct osoba
{
	char imie[15];
	char nazwisko[20];
	int wiek;
}; //o, tutaj jest średnik!

O strukturach i klasach dowiemy się dopiero za jakiś czas, więc na razie nie zawracajmy sobie nimi głowy.

Literówki, złe nazewnictwo zmiennych, ...

Niestty, przy pisaniu tekstów na komputerze niemal każdy z nas boryka się z literówkaim czy nawet błendami ortografjicznymi. Nasze programy również są na to narażone – zdrza się nam czasem wprwadzić fr zamiast for, wywołać funkcję sex(), mimo że chodziło nam o exp() itp. Na szczęście, Visual Studio jest dość pomocny w usuwaniu tego typu błędów.

Pamiętajmy, że istnieją specjalne reguły nazywania zmiennych, o których początkujący programiści potrafią zapomnieć:

  • nazwa zmiennej musi zaczynać się od litery lub znaku podkreślenia, np. ala12, _ala34, Ala,
  • nie można stosować słów kluczowych do nazywania zmiennych.
Jeszcze "ciemniejszym" scenariuszem jest sytuacja, gdy mamy w programie dwie zmienne o podobnych nazwach (np. Licznik i licznik – kompilator rozróżnia wielkość liter w nazwach zmiennych), a my pomylimy się w ich rozróżnieniu... Wtedy mamy do czynienia z błędem semantycznym, który może być dosyć trudny do zdiagnozowania. Więcej na ten temat dowiemy się m.in. w tym samouczku.
W języku C++ separatorem dziesiętnym liczb jest nie przecinek, lecz kropka. Pamiętajmy o tym, jeżeli będziemy przypisywać wartości zmiennym typu float lub double.

Czy wesiz, że cołzeiwk bez pmrbelou pniwoein ozatydcć ten tkset? Wytszsko dękzii tmeu, że ldkzui mzóg pzatry na waryz jkao oarbz — nie cytza go lerita po letzire. Zracwa ugawę na peiwzrsą i ottsinaą lertię, a rzestę po posrtu "dopjasowue".

Szkoda, że kompilator tak nie potrafi... :-(

Niewłaściwa liczba nawiasów

Często zachodzi potrzeba zapisania np. wyrażeń matematycznych zawierających dużą liczbę nawiasów. Kompilator zgłosi błąd, kiedy zorientuje się, że liczba nawiasów otwierających i zamykających się nie zgadza.

Starajmy się bardzo uważnie pisać wyrażenia z nawiasami. Najlepiej będzie, jeżeli po napisaniu nawiasu otwierającego ( od razu dopiszemy nawias domykający ). Dodatkowe spacje, zwiększające czytelność, również nie zaszkodzą. Można też próbować "rozbijać" jedną długą instrukcję na kilka mniejszych.

Podobnie jest z klamrami { }, które służą do wydzielenia bloków kodu – czyli grupowania wielu instrukcji.

Istnieje dodatek do VS o nazwie Productivity Power Tools, który potrafi m.in. automatycznie domykać nawiasy i cudzysłowy.

Aby go zainstalować, należy wejść w menu Tools | Extension Manager , wybrać Online Gallery i tam wyszukać oraz zainstalować wspomniany wyżej dodatek. Najpierw trzeba jednak włączyć opcję korzystania z Visual Studio Gallery. Klikamy Tools | Options, a tam w sekcji Environment szukamy pozycji Extension Manager i zaznaczamy ptaszkiem Enable access to (...)

Brak odpowiednich dyrektyw

Utwórzmy nowy projekt i wprowadźmy taki o to program:

int main()
{
	cout << "A code without any bugs!" << endl;
	return 0;
}

Skompilujmy go. W panelu Output zapewne pojawi się informacja typu: c:\users\kasia\documents\visual studio 2010\projects\exercises\tutorial\tutorial\main.cpp(3): error C2065: 'cout' : undeclared identifier

Napis undeclared identifier oznacza, że to słowo nie zostało uprzednio zadeklarowane. Taki komunikat pojawia się zazwyczaj przy literówkach, ale także wtedy, kiedy zapomnieliśmy po prostu załączyć jakiejś biblioteki. W tym przypadku należy oczywiście na początku pliku źródłowego dopisać:

#include <iostream>
using namespace std;

Zagadnienie to jest już nam dobrze znane z tego samouczka. Cóż, teoria teorią, a praktyka – praktyką.

Czasami zdarza się, że pamiętamy nazwę funkcji, lecz nie wiemy, w której bibliotece została zdefiniowana. W nielicznych przypadkach możemy wtedy liczyć na Kolegów lub Prowadzących zajęcia, jednak najlepiej samemu poszukać nazwy biblioteki w dokumentacjach. Wtedy łatwiej zapamiętać te informacje. ;-)

Przydadzą nam się do tego dwie strony (w języku angielskim):

  • C++ Reference (w polu Search wystarczy wpisać nazwę funkcji — zazwyczaj pierwszy link prowadzi do odpowiedzi),
  • Microsoft Developer Network Library (w polu wyszukiwania najlepiej wpisać nazwę funkcji z dopiskiem c++, np. cout c++ — odpowiedź zazwyczaj znajduje się w linku z tytułem Standard C++ Library, gdzie w sekcji Requirements jest podana nazwa biblioteki).

Brak funkcji main()

Brak funkcji main() to – w teorii – bardzo rzadki błąd. Cóż... jednak się zdarza. Po prostu, powinniśmy zapamiętać, że każdy program w C++ musi posiadać funkcję main(). Jeżeli jej nie napiszemy, po nieudanej kompilacji w panelu Output zobaczymy bardzo dziwny komunikat .

Jak pokazuje praktyka, powyższy komunikat może się niestety pojawić (na szczęście bardzo rzadko) nawet w przypadku, gdy funkcja main() jest umieszczona w naszym programie. Nie wiemy, dlaczego tak się dzieje (jest to ewidentny błąd kompilatora dołączonego do VS). W takim przypadku należy projekt utworzyć od nowa i dołączyć do niego "problematyczny" plik źródłowy. Nagle wszystko zacznie działać poprawnie...

Jak VS pomaga odnaleźć błędy?

IntelliSense

IntelliSense jest zaawansowanym narzędziem do analizy kodu, które działa już w trakcie pisania programu. Dzięki niemu trudniej popełnić błędy syntaktyczne.

Przykładowo: zdefiniowaliśmy funkcję fun, która przyjmuje jeden argument typu int i jeden argument typu float. Chcemy teraz wykorzystać tę funkcję. Gdy napiszemy jej nazwę i otworzymy nawias, ujrzymy szary dymek (ang. tool-tip), który podpowie nam, jak wyglądać powinna lista argumentów: Podpowiadaczka w IntelliSense

Wciskamy teraz CTRL+SPACJA, żeby pojawiła się ładna lista funkcji i zmiennych: Inna podpowiadaczka w IntelliSense

Napiszmy coś jeszcze: Podkreślenie w IntelliSense

Kiedy wskażemy kursorem na czerwone podkreślenie, pojawi się szary dymek, który w tym przypadku informuje nas o brakującym średniku. Spoglądamy linijkę wyżej – rzeczywiście, po wywołaniu funkcji fun() zapomnieliśmy średnika.

Najczęściej będziemy korzystać właśnie ze wskazówek tego podkreślenia. Wyłapuje ono m.in. brakujące średniki, problemy z nawiasami czy cudzysłowami, a także niektóre literówki.

Jednakże, nie ufajmy ślepo temu narzędziu! Analiza kodu działa stosunkowo szybko, przez co czasami podkreślenie może pojawić się nawet wtedy, gdy nie skończyliśmy pisać danej instrukcji.

Panel Output i Error List

Są to dwa ważne panele przy diagnozowaniu błędów w kodzie.

Jeżeli skompilujemy program, który zawiera błędy, w panelu Output pojawiają się rozbudowane informacje nt. problemów .

Opis błędu jest podany wg następującego schematu:

  • Najpierw pokazana jest ścieżka do pliku, w którym znajduje się błąd.
  • Po nazwie pliku, w nawiasach okrągłych, pokazany jest numer linii z występującą nieprawidłowością.
  • Dalej wyświetlana jest informacja, czy to jest błąd (ang. error) czy tylko ostrzeżenie (ang. warning).
  • Następnie znajduje się kod nieprawidłowości (wpisując ten kod w wyszukiwarce, możemy natrafić na rozwiązanie problemu na stronie MSDN, zob. np. opis błędu C2146).
  • Na końcu dana jest dokładniejsza informacja o błędzie.
Dwukrotnie klikając na opis błędu, VS przeniesie kursor do linii, w której występuje nieprawidłowość.

Panel Error List zbiera informacje z panelu Output oraz komunikaty IntelliSense i przedstawia je w czytelniejszej formie. Panel Error List

Dwukrotne kliknięcie na konkretną pozycję również przeniesie kursor do odpowiedniej linii w kodzie.

Warto włączyć sobie numerowanie linii. Klikamy Tools | Options, tam szukamy Text Editor, następnie wybieramy C/C++. W sekcji Display zaznaczamy ptaszkiem opcję Line numbers.
Raz jeszcze przypominamy, by poprawianie błędów zaczynać od pierwszego na liście. Po każdej poprawce należy spróbować skompilować program ponownie!

Przydatne sztuczki

Komentarze

Gdy coś nam nie działa prawidłowo, nie ma sensu od razu tego usuwać. Czasami bowiem okazuje się, że w danej linijce jest drobny błąd, którego my mogliśmy za pierwszym razem nie zauważyć. W takim przypadku można skorzystać z komentarzy i zakomentować "podejrzany" kawałek kodu. Z biegiem czasu sami zauważymy, że jest to dobre narzędzie przy poprawianiu kodu. Jest to też dobre rozwiązanie w przypadku, gdy pisany program składa się z dobrze określonych i rozdzielonych "etapów".

Nie opłaca się zwlekać z kompilacją do momentu skończenia pisania kodu programu. W miarę możliwości, sprawdzajmy jego działanie w trakcie programowania, posuwając się do przodu fragment po fragmencie. Wtedy łatwiej odnaleźć ewentualne błędy. Unikniemy dzięki temu niepotrzebnego stresu podczas punktowanych laboratoriów.

Przećwiczmy usuwanie błędów

Pora przekonać się, jak w praktyce wygląda usuwanie błędów syntaktycznych. Utwórzmy zatem nowy projekt o nazwie bledy1 oraz plik źródłowy bledy_syntaktyczne.cpp. Poniżej znajduje się kilka kodów, które spróbujemy poprawić.

Przykład I

Skopiujmy do naszego projektu poniższy listing:

#include <iostream>

int main()
{
	int a=1, b=2, c=3;
	cout << a << " " << b << " " << c << endl;
	c=5
	cout << c << endl;
	return 0;
}

Skompilujmy projekt i sprawdźmy, jakie opisy błędów pojawiły się w panelach Output oraz Error List

Panel Output: Błędy w panelu Output Panel Error List: Błędy w panelu Error List

Jak już nam wiadomo, napis undeclared identifier oznacza, że dany identyfikator nie został wcześniej zdefiniowany. Racja, brakuje tu dyrektywy:

using namespace std;

Przekopiujmy ją zatem do kodu (pamiętasz, w które miejsce?) i ponownie skompilujmy projekt.

Tym razem ukazał się tylko jeden błąd. Dotyczy on średnika w #7 linijce (zauważmy, że VS odwołuje nas do linijki #8, gdyż to bezpośrednio przed nią występuje problem). Również poprawmy to przeoczenie. Teraz program kompiluje się bez żadnych problemów. :-)

Przykład II

Teraz przyjrzymy się bliżej "skomplikowanemu" przykładowi z błędami. Skopiujmy do naszego projektu poniższy kod:

#include <iostream>
using namespace std;

int main()
{
	int a,b=4,c=3;
	cout << "Czesc!" << endl
	a=5
	cout << a << endl;
	a=7+((5-c)*b-(a+c))):
	cout << a << endl;
	return 0;
}

Na ekranie najprawdopodobniej ujrzymy takie działanie IntelliSense: Uwaga na IntelliSense!

Jeśli przyjrzymy się bliżej programowi, to zauważymy, że chyba nie wszystko zostało podkreślone (np. cout w linijce #9). Widzimy, że nie wolno bezmyślnie ufać temu narzędziu.

Po kompilacji projektu w panelu Error List ujrzymy więcej informacji o błędach od kompilatora niż od samego IntelliSense. Informacje panelu Error List

Powtórzmy kolejny raz, należy poprawiać błędy począwszy od pierwszego zgłoszonego przez kompilator! (Założę się, że po przeczytaniu tego samouczka i tak wiele osób będzie robić inaczej.) :-(

Zgodnie z zaleceniem, poprawmy błąd z linijki #7 – dostawmy średnik. Teraz powinno pojawić się podkreślenie cout w linijce #9. Zatem, dopiszmy średnik również w poprzednim wierszu.

Przejdziemy teraz do najtrudniejszego fragmentu (przedtem ponownie kompilując projekt). Jak widać, w wierszu #10 kompilator zwraca uwagę na problem z nawiasami oraz brakującym średnikiem. Tym razem, gdy dwukrotnie klikniemy na opis błędu dot. brakującego średnika, kursor zostanie przeniesiony dokładnie do linijki z błędem. Dzieje się tak dlatego, że nie zgadza się liczba nawiasów, przez co "):" są traktowane jako oddzielna instrukcja. Na szczęście, wystarczy jedynie usunąć ostatni nawias, a w miejsce dwukropka wstawić średnik. Uff, kolejny program gotowy!

Podsumowanie

W niniejszym samouczku poznaliśmy rodzaje błędów, ich opisy oraz wskazówki, jak sobie radzić z problemami w trakcie programowania. Już od początku przygody z programowaniem starajmy się o umiejętność samodzielnego znajdywania i poprawiania błędów w kodzie. Starajmy się postępować zgodnie z zasadą: najpierw spróbuj sam, a dopiero potem proś innych o pomoc.

CC By 3.0
Copyright © 2011-2016 by Katarzyna Fokow [Last update: 2017-02-01 17:17:03]
This work is licensed under a Creative Commons Attribution 3.0 Unported License