Witam i witam ponownie.
W tym wykładzie chcę omówić kilka typowych błędów, które popełnisz podczas
programowania w języku c.
Niektóre z nich możesz znać z poprzednich
wyzwań i faktycznie napotkałeś już te błędy, ale
są to najczęstsze typy błędów.
Pierwsza jest bardzo, bardzo oczywista. Brak średnika.
Pamiętaj, że wszystkie instrukcje w c kończą się średnikiem.
Jeśli go tam nie masz, kompilator będzie narzekał.
Więc albo niewłaściwe umieszczenie średnika, albo całkowite pominięcie średnika
jest naprawdę częstym błędem. W tym przypadku błędnie umieszczamy średnik.
Mamy oświadczenie if. Na końcu instrukcji umieszczamy średnik.
A to faktycznie powoduje, że zachowanie programu jest zupełnie inne.
To faktycznie się skompiluje.
Jeśli pominiesz średnik i nawet go nie włączysz, nie zostanie on skompilowany.
Ale w tym przypadku wartość j zawsze będzie ustawiona na
zero, ponieważ w instrukcji if został umieszczony średnik.
Tak więc średnik jest całkowicie prawidłowy, jeśli ma go po instrukcji if.
W rzeczywistości reprezentuje instrukcję zerową.
Dlatego nie masz błędu kompilatora, ale
spowoduje to problem, ponieważ j nigdy nie zostanie ustawione na zero.
Tego typu błąd może być również powszechny w przypadku pętli.
Kiedy masz pętlę i umieszczasz średnik
na końcu pętli for, możesz mieć nawias, w którym nie
masz nawiasu, ponieważ będziesz mieć błąd, jeśli masz nawias, bardzo często.
Innym jest mylenie operatora równości z operatorem równa się równa się.
W szczególności wspomniano, że operator równa się równa
się nie porównuje ciągów. Więc jeśli używasz równa się równa się
podczas porównywania łańcuchów, to nie jest poprawne. Po prostu porówna odniesienia.
Ale jeśli naprawdę chcesz przypisać wartość do zmiennej i zamiast
tego użyć równa się równa się, będziesz mieć kompilator.
Teraz, jeśli spróbujesz porównać dwa elementy, takie jak dwie
liczby całkowite wewnątrz instrukcji if, i zamiast tego użyjesz operatora
przypisania, w rzeczywistości nie wystąpi błąd kompilatora,
ale to wyrażenie zawsze będzie miało wartość true.
Więc kiedy używasz równa się i nie używasz równa się
równa się, zwykle jest to wykonywane w instrukcji if while do, wewnątrz wyrażenia boolowskiego.
I jest to ważne, z wyjątkiem
tego, że skutkuje przypisaniem do czegoś, a nie wykonaniem czegoś.
Więc w tym
przykładzie, jeśli a jest równe 2, przypisujemy 2 do a.
Zawsze ma wartość true, ponieważ jest to prawdziwe stwierdzenie, ponieważ nigdy
nie zawiedziesz, gdy wykonuje zadanie. I tak printf zawsze będzie działać.
To, co naprawdę chciałeś tutaj zrobić, to powiedzieć, czy a równa się.
Dlatego bardzo często używa się równości, a nie równa się równa
się, a następnie nie powoduje błędu kompilatora.
Jeśli użyjesz równa się równa się
w niewłaściwej sytuacji,
możesz również mieć nieoczekiwane zachowanie, ale
wystąpi błąd kompilatora, jeśli używasz go do przypisania nieprawidłowo.
Ale uważaj na to z równymi, a nie równymi sobie.
Pomijanie deklaracji prototypów.
Wspomniałem, że bardzo ważne jest, aby zawsze deklarować swoje
funkcje na początku pliku, zanim ich użyjesz.
Jednak nie zawsze tak się dzieje i jest to bardzo częsty błąd.
Zwykle w kompilatorze pojawi się niejawny błąd
deklaracji.
W tym przykładzie, jeśli pierwiastek kwadratowy został zdefiniowany później
w programie niż w miejscu, w którym go wywołujesz, lub
w innym pliku i
nie zadeklarowałeś go jawnie, pojawią się ostrzeżenia.
Kompilator przyjmie, że funkcja zwraca int.
Zawsze najbezpieczniej jest umieścić tę deklarację prototypu u
góry dla wszystkich wywoływanych
funkcji, jawnie
lub niejawnie, przez dołączenie odpowiedniego pliku nagłówkowego do programu.
Ale jeśli tego nie uwzględnisz, te deklaracje prototypów mogą
mieć błędy.
Brak dołączenia pliku nagłówkowego, który zawiera definicję funkcji
biblioteki programowania C używanej w programie.
W tym przypadku chcesz ponownie użyć kodu. Być może masz funkcję
printf, którą chcesz wyświetlić, ale nie dołączasz standardowego pliku nagłówkowego lib.
To pomyłka. I to zwykle powie Ci kompilator.
Będzie problem z łączeniem z
tą funkcją.
W tym przypadku mamy podwójną odpowiedź równą pierwiastkowi kwadratowemu wartość 1.
Jeśli ten program nie zawiera matematyki. nagłówka, spowoduje
to błąd, że pierwiastek kwadratowy jest niezdefiniowany.
Spróbuje połączyć pliki obiektowe. To nie będzie miało matematyki. o.
I powie, hej, nazywasz pierwiastek kwadratowy, ale nie ma dla niego implementacji.
Dlatego upewnij się, że dołączasz poprawne
nagłówki do wszystkich wywołań funkcji, zwłaszcza z biblioteki standardowej.
Mylenie stałej znakowej w ciągu znaków.
Więc tutaj, jeśli mamy tekst równy wewnętrznemu cudzysłowowi, to jest
to pojedynczy znak, który jest przypisany do tekstu.
Jeśli mamy zmienną o nazwie text i przypisujemy ją w
cudzysłowie, jest to wskaźnik do ciągu znaków.
Nie dotyczy to pojedynczego
znaku.
W rzeczywistości rozmawialiśmy o stałych
łańcuchowych i przypisywaniu ich do tablic znaków.
I jak nie możesz tego zrobić z równymi sobie i
musisz to zrobić z kopią gwiazdy.
W tym przypadku, kiedy mówimy, że tekst równa się a, przypisuje on wskaźnik
i to również nie jest poprawne
i zobacz, co musiałbyś zrobić, to zrobić tekst gwiazdy równy
a lub kopię gwiazdy, jeśli tego nie zrobisz nie chcę go przypisać
bezpośrednio w ten sposób.
Ale rozumiesz.
Używanie a wewnątrz pojedynczych cudzysłowów w porównaniu ze znakiem w
podwójnych cudzysłowach jest zupełnie inne, znak kontra ciąg.
W pierwszym przypadku tekst jest zwykle deklarowany jako zmienna typu char.
W drugim przypadku należy zadeklarować, że jest to wskaźnik typu do znaku.
A jeśli chcesz przypisać temu wskaźnikowi wartość inną
niż sam wskaźnik, musisz usunąć odniesienie do niego.
W rzeczywistości jest to niepoprawne, ponieważ jeśli
jest to wskaźnik zamiast przypisywać adres, przypisujesz mu ciąg znaków, więc to
nie ma sensu.
Używanie niewłaściwych granic dla tablicy, wyjątek tablicy poza granicami.
Tutaj deklarujemy tablicę liczb całkowitych o rozmiarze 100, a następnie kilka
zmiennych I i sumę, przy czym tylko niektóre są inicjalizowane.
I przechodzimy przez naszą pętlę, mówimy, że I równa się 1 I jest mniejsze niż równe 100.
Jest to niepoprawne, ponieważ rozmiar stu oznacza, że w tablicy
jest sto elementów. Ale tablice są oparte na zerach.
Więc pierwszy element to zero. Maksymalny indeks, który możesz przypisać
do tablicy lub uzyskać do niego dostęp, to 99.
To będzie mniej niż równe.
Więc będziesz miał tutaj pomyłkę poza granicami.
To nie jest prawidłowy
indeks dolny, ponieważ ta pętla przejdzie do 100.
Prawdopodobnie jest to również niepoprawne, ponieważ zaczynasz od 1.
Jeśli naprawdę chciałbyś mieć pierwszy element tej tablicy, zacząłbyś od 0.
Zapomnienie o zarezerwowaniu dodatkowej lokalizacji w tablicy
dla kończącego znaku null łańcucha jest
również częstym problemem.
Deklarując tablice znaków, muszą one być wystarczająco duże, aby zawierać sam znak kończący.
Dlatego sugerowałbym, abyś nie umieszczał
rozmiaru w tablicy podczas jej tworzenia, jeśli ją inicjalizujesz.
Wpisujesz tam rozmiar tylko wtedy, gdy go nie inicjalizujesz.
Jeśli tworzysz inicjalizację w tej samej linii, pozwól c wykonać
pracę za Ciebie, automatycznie ustawi właściwy rozmiar i będzie zawierać ten terminator zerowy.
Na przykład, jeśli masz ciąg znaków o nazwie hello, jest
to więcej niż pięć lokalizacji pamięci, jest ich sześć z powodu tego zerowego terminatora na końcu.
Nie zapomnij o rozmiarze swoich tablic.
Jest to częsty problem ze wskaźnikami, o których nie rozmawialiśmy zbyt wiele,
ale chciałem tylko wspomnieć, ponieważ jest bardzo powszechny.
W przypadku wskaźników, jeśli chcesz uzyskać dostęp lub nawet poinstruować,
jeśli chcesz uzyskać dostęp
do czegoś za pomocą wskaźnika, musisz użyć myślnika większego niż symbol.
Jest używany, gdy uzyskujesz dostęp do elementu wskaźnika.
Więc jeśli masz wskaźnik, który wskazuje na strukturę, w ten sposób uzyskujesz do niej dostęp.
Jeśli masz strukturę, nie jest
to wskaźnik, wtedy uzyskujesz do niej dostęp za pomocą operatora kropki.
Wiele razy ten operator kropki i ten myślnik są większe niż
jest używane nieprawidłowo.
Kropka dla nie-wskaźników, wskaźniki kreskowe większe niż, stanie się to jasne
w większej liczbie naszych przykładów.
Pomijanie ampersand przed zmiennymi niebędącymi wskaźnikami w wywołaniu scanf.
Pamiętaj więc, że nasze wywołanie scanf oczekuje wskaźnika jako drugiego argumentu,
a to oznacza adres.
Kiedy deklarujemy typ danych jako zmienną typu int, nie jest
to wskaźnik.
Aby więc umożliwić scanf przechowywanie tych danych w naszej zmiennej int, musimy przekazać mu znak
ampersand, aby powiedzieć, że jest to adres.
Więc to jest
niepoprawne, brak znaku ampersand przed liczbą i skanowanie f
jako drugiego argumentu jest niepoprawne. Jedyny przypadek, w którym nie masz znaku ampersand, to użycie
wskaźnika, takiego jak tablica znaków.
Wszystkie argumenty występujące po ciągu formatu i scanf muszą być wskaźnikami.
Używanie zmiennej wskaźnikowej przed jej zainicjowaniem.
Oto przykład tworzenia wskaźnika, a następnie próby przypisania do niego.
I to jest prawidłowe przypisanie, w którym przypisujesz wartość, do której usuwasz odniesienie.
Ale to, czego tutaj nie zrobiliśmy, to zainicjowanie wskaźnika, aby faktycznie mieć przydzieloną
jakąkolwiek pamięć i nie można
tego zrobić w c.
Możesz zastosować tylko operator pośredni,
którym jest gwiazdka przed
punktem lub zmienną, po ustawieniu zmiennej wskazującej gdzieś.
Musi więc gdzieś wskazywać, w tej chwili jest pusty, nigdzie nie wskazuje, ponieważ nie
przydzieliłeś żadnej pamięci.
Tak więc wskaźnik znaku nigdy nie jest ustawiony tak, aby wskazywał na cokolwiek, więc przypisanie nie ma znaczenia.
W rzeczywistości spowodowałoby to błąd segmentacji.
Innym częstym błędem jest pomijanie instrukcji break na końcu przypadku w instrukcji switch.
Jeśli przerwa nie jest zawarta na końcu sprawy, wykonanie jest kontynuowane do następnej sprawy.
Więc to jest to, o czym wspomniałem, gdzie masz sprawę, zostanie ona oceniona.
A jeśli nie masz tam tej przerwy, przechodzi od
razu do następnej sprawy i wykona kod wewnątrz następnej sprawy.
Dlatego zawsze chcesz mieć przerwy w opisach przypadków.
Są chwile, kiedy chcesz przejść przez przypadek do innej sprawy
i robią dokładnie to samo, w
takim przypadku nie miałbyś nic w instrukcji case.
Wstawienie średnika na końcu definicji preprocesora.
Definicje preprocesorów pamiętają, że zaczynają się od
liczby, symbolu funta. Preprocesor jest zwykle uruchamiany przed kompilatorem
w celu optymalizacji.
Prawidłowa składnia definicji preprocesorów nie może zawierać średnika.
Jednak w c ty nabądź zwyczaju umieszczania po wszystkim średnika.
Ale musisz pamiętać, że jeśli zdefiniujesz jakieś stałe dane, że
nie potrzebujesz średnika, jest to niepoprawne.
Doprowadzi to do błędu składniowego, jeśli
zostanie użyte takie wyrażenie.
tak. Więc jeśli faktycznie spróbujesz użyć
tego do stwierdzenia, że będzie dobrze mieć ten średnik na końcu.
Ale kiedy preprocesor działa, wstawi dokładnie to, co jest zdefiniowane.
Więc to będzie służyć do okrężnicy końca danych 999.
To właśnie zobaczy kompilator i faktycznie spowoduje błąd, który
byłby błędem składniowym.
Pomijanie zamykającego nawiasu lub zamykającego cudzysłowu w jakimkolwiek
stwierdzeniu, bardzo często. Więc jest to również bezpośrednio związane
z nawiasami klamrowymi, mając początkowy nawias klamrowy, a następnie nie kończący nawiasów klamrowych,
to samo z nawiasami. W tym przypadku
mamy dwa początkowe lewe nawiasy lub trzy, ale mamy
tylko dwa końcowe nawiasy. Brakuje kończącego prawego nawiasu.
Byłby to błąd składniowy, który znalazłby kompilator.
Więc kiedy używasz osadzania w nawiasach, aby rozdzielić każdą część równania, tworzy
to bardziej czytelną linię kodu.
Chcesz użyć nawiasów.
Jednak chcesz się upewnić, że wszystkie
pasują do nawiasu, musisz mieć końcowy nawias zamykający, tak samo jak w nawiasach klamrowych.
Zaczynasz klamrę kręconą, musi mieć ona końcową klamrę kręconą.
Więc albo masz za dużo, albo za
mało, ale kompilator będzie narzekał, a to jest bardzo, bardzo częste.
Więc w drugiej linii brakuje również cudzysłowu zamykającego, ta instrukcja print.
Nie mamy końcowego cytatu.
Kompilator będzie na to narzekał.
Oba spowodują błąd kompilacji.
Czasami jednak kompilator jest bardzo mylący, ponieważ tak naprawdę
nie wie, gdzie wystąpił błąd. Uważa, że błąd mógł wystąpić w kolejnym wierszu.
Więc wiersz, w którym informuje o błędzie, może wprowadzać w błąd.
Zatem w zależności od tego,
czy kompilator użyje nawiasu, czy cudzysłowu w kolejnym
wierszu, w rzeczywistości zakończy to wyrażenie.
Więc przeniesie błąd do innej linii.
I właśnie to będzie narzekać i powie, że tam jest błąd. Ale rzeczywisty błąd
jest wyżej, powyżej miejsca, w którym zamierzałeś go umieścić.
Oto kilka typowych błędów, które często popełniają programiści
C.
Łatwo je naprawić. A jeśli je zrozumiesz i
przestudiujesz to, będziesz
wiedział, jak ich nie tworzyć. W porządku jest
uczynić ich początkującymi, ale kiedy coraz więcej kodujesz
i zdobywasz więcej praktyki, zdasz sobie sprawę, hej,
zapomniałem nawiasu, zapomniałem nawiasu, nie użyłem równych i równych równa się
poprawnie , Nieprawidłowo używam wskaźników, nie przydzieliłem żadnej pamięci.
Wszystkie te rzeczy staną się bardziej drugą naturą. Dziękuję Ci.