Witam i witam ponownie. Teraz, gdy rozumiemy nieco więcej wskaźników,
chcę porozmawiać o wskaźnikach znaków, głównie o
tym, jak można używać wskaźników znaków do reprezentowania ciągów.
Łańcuchy to tablice znaków, wiele znaków, słowa.
Więc teraz wiemy, jak tablice odnoszą się do wskaźników w koncepcji arytmetyki wskaźników.
Bardzo, bardzo przydatna koncepcja.
Pojęcia te mogą być bardzo przydatne, gdy stosuje się
je do łańcuchów tablic znaków, ponieważ teraz możemy łatwo przechodzić przez ciąg znak po znaku.
Jednym z najczęstszych zastosowań wskaźnika do tablicy jest użycie
wskaźnika do ciągu znaków.
Powody to wygoda notacji i skuteczność.
Tak więc użycie zmiennej typu wskaźnik do znaku w celu
odniesienia do łańcucha daje dużą elastyczność.
Będziesz więc próbował używać wskaźników
znakowych tak często, jak tylko możesz,
na tablicach znaków, w szczególności używając wskaźników znakowych do przekazywania danych do funkcji.
Takie fajne rzeczy.
Spójrzmy więc na przykład, który używa tablicy do skopiowania ciągu.
W tym przykładzie naszym parametrem tablicy będzie tablica znaków.
Zobaczysz to w deklaracji funkcji.
Chcę to porównać z funkcją, która pobiera wskaźnik znaku i
pokazuje, w jaki sposób funkcja wskaźnika znakowego jest o wiele bardziej wydajna.
W tym przykładzie mamy dwie funkcje,
jedną pobierającą tablicę i drugą
pobierającą wskaźniki.
W pierwszej funkcji copy string
możemy przejść przez całą tablicę, używając pętli for I równa się zero
od sub I i przechodzimy całą drogę, aż zobaczymy ciąg znaków
zerowych, a następnie zwiększamy naszą zmienną sterującą pętli.
A potem wszystko, co musisz zrobić, to powiedzieć, że 2 sub I równa się sub I. Robimy tam bezpośrednie
zadanie.
A na samym końcu, po przejściu przez całą drogę, aż zobaczymy
znak null, dodajemy znak null na końcu naszej
tablicy to, całkiem podstawowy. Zobaczmy teraz, jak to robimy, gdy używamy wskaźników.
Najpierw deklarujemy wskaźniki jako deklarację funkcji w ciągu kopiującym, mówiąc po
prostu znak star, od którego znak zaczyna się.
W naszej pętli for nie musimy w rzeczywistości deklarować
żadnych zmiennych, ponieważ mamy wskaźniki i chcemy
po prostu iterować, aż from trafi na terminator zerowy.
Następnie możemy zwiększyć zarówno wskaźniki od, jak i do.
Ponieważ tutaj zajmujemy się arytmetyką punktową.
Po prostu dodajemy jeden do wskaźnika, który zwiększa jego adres o jeden, co oznacza,
że otrzymuje następny znak.
A do następnej linii pętli for po prostu
odwołujemy się zarówno do, jak i od,
ponieważ chcemy przypisać rzeczywistą wartość, na którą wskazuje wskaźnik,
rzeczywisty znak do wskaźnika do.
A następnie na samym końcu dodajemy
znak null do miejsca, w którym wskazuje wskaźnik
to, czyli na końcu ostatniego adresu ciągu od, ale teraz
wskazuje na adres do.
Nie wygląda to źle. Mam na myśli pętlę for.
Zasadniczo masz taką samą liczbę wierszy kodu.
Ale widzisz różnicę w składni.
Nie używasz indeksów dolnych i używasz wskaźników, użyj gwiazdki.
Znowu, naprawdę kwestia wygody notacji.
Nie widzisz tutaj dużej przewagi.
Ale w rzeczywistości możesz to bardziej zoptymalizować,
aby nawet zredukować kod, gdy używasz wskaźników.
Więc jeśli masz tablicę
znaków jako wskaźnik, jeśli masz tablicę znaków zwaną tekstem, możesz podobnie
zdefiniować wskaźnik do niej i użyć elementów w tekście.
Więc tutaj możemy powiedzieć, że wskaźnik
tekstu gwiazdy char, tak definiuje się wskaźnik znaku.
Jeśli wskaźnik tekstu jest ustawiony na początek tablicy znaków zwanej
tekstem, możesz po prostu zwiększyć
go o jeden, używając tych operatorów przed i po implementacji oraz dekrementacji.
Więc to powyżej, ten plus plus wskaźnik tekstu ustawi wskaźnik tekstu wskazujący
na następny znak w tekście, który jest tekstem pod 1.
Więc jeśli chcemy spojrzeć na następny promień, tak jak w przypadku
liczb całkowitych, wszystko, co musimy zrobić, to dodać 1 2 i możemy uzyskać następny znak.
Jest to o wiele bardziej przydatne
w tablicach znaków, ponieważ można łatwo manipulować znakami jeden po drugim.
Jeśli wykonasz znak minus minus tekst, który jest operatorem dekrementacji,
to ustawi wskaźnik na poprzedni znak w tekście,
zakładając, że wskaźnik tekstu nie wskazywał początku tekstu.
Bo gdyby tak było, będziesz miał te błędy „under bounds”.
Jeśli robił plus plus na końcu łańcucha, wystąpiłby błąd poza zakresem.
Zawsze musisz być ostrożny, tak jak arytmetyka liczb całkowitych, aby nie przekroczyć granic tablicy.
Ale bardzo proste, wiąże się bardzo ściśle z arytmetyką
wskaźników całkowitych.
Arytmetyka wskaźnika znaków to to samo.
Jest to jeszcze bardziej przydatne, ponieważ teraz możesz faktycznie przeglądać poszczególne znaki bez używania indeksu dolnego.
Jeśli więc spojrzymy na poprzedni przykład
i możemy go nieco bardziej zoptymalizować za pomocą wskaźników, aby uzyskać
jeszcze mniej wierszy kodu.
Więc teraz w naszym ciągu kopiującym, robimy, że deklaracja funkcji jest taka sama jak
poprzednio, tworzymy kilka wskaźników za pomocą gwiazdki.
Ale nie używamy już pętli for, ponieważ użycie pętli
for w poprzednim przykładzie było trochę
bezcelowe, ponieważ tak naprawdę nie musieliśmy inicjować zmiennej sterującej pętli.
Wszystko, co musieliśmy zrobić, to wyjść z
pętli pod warunkiem, a następnie faktycznie używamy operatorów inkrementacji i dekrementacji
w pętli for, ale nawet nie musimy tego robić.
W rzeczywistości staje się to jeszcze prostsze, ponieważ jeśli użyjemy pętli while,
wszystko, co musimy zrobić, to spojrzeć na pętlę while i
wyskoczy, jeśli wskazuje na znak null, ponieważ znak null jest w
rzeczywistości równy zero.
A pętla while pamięta, że wartości logiczne w
c są reprezentowane przez liczby całkowite, jeden jest prawdą, a następnie
zero jest fałszem lub naprawdę zero jest fałszem, a wszystko inne jest prawdą.
W tym przypadku znak zerowy 0, który jest fałszywy, wyskoczy.
Więc wszystko, co musisz zrobić, aby spełnić warunek wyjścia w pętli while, to wstawić gwiazdkę from.
Co to za dereferencja, aby zobaczyć, jaka jest wartość tego znaku.
Kiedy więc zbliżamy się do końca łańcucha, z którego chcemy skopiować, wyskakujemy.
W przeciwnym razie po prostu umieścimy tam
naszą modyfikację naszych wskaźników, dwa plus plus z plus plus.
Teraz jest to operator postinkrementacji.
Oznacza to, że plus plus znajduje się po prawej stronie zmiennej.
A kiedy to zrobisz, oznacza to, że
nie dodasz go do tego, dopóki instrukcja nie zostanie wykonana.
Więc co to zrobi, to znaczy, że gwiazda 2 równa się zaczynając od.
A potem po wykonaniu tej instrukcji doda do 2 1 i doda do 1.
Gdybyś miał plus plus przed nazwą zmiennej,
dodałaby ona do tej zmiennej przed wykonaniem tej instrukcji i
byłby to problem, ponieważ zasadniczo przegapilibyśmy pierwszy kopiowany element
w ciągu.
Ale nie potrzebujemy więcej wierszy kodu. Wykonujemy rzeczywistą arytmetykę wskaźnika inkrementacji
i przypisanie w tej samej instrukcji, więc
zmniejszamy kod o jeden.
Ponownie notacja jest bardzo prosta.
Bardzo łatwo wykonujemy zadania arytmetyczne na liczbach całkowitych.
A na końcu, po zakończeniu kopiowania wszystkich ciągów,
po prostu dodajemy na końcu znak
null do wskaźnika, z którego odwołujemy się, ponieważ te dwa są w rzeczywistości
powodem, dla którego przechodzi przez pętlę, która będzie wskazywać na ostatnią postać.
Więc tutaj jest trochę posprzątane.
Pokazuje moc wskaźników i jak można
używać wskaźników i arytmetyki w tych samych wierszach, a dzięki
tym operatorom inkrementacji i dekrementacji, plus plus minus minus, jest to
jeszcze szybsze i łatwiejsze, więc jest również bardziej wydajne.
Gdybyśmy chcieli użyć tych funkcji kopiowania ciągów, moglibyśmy po prostu utworzyć dwie tablice znaków.
Możemy przekazać tablice znaków bezpośrednio do ciągu kopiującego, ponieważ tablice znaków 0
są wskaźnikami.
Są wskazówkami, więc nie musimy ich usuwać, dodawać
adresów ani nic takiego. Możemy po prostu powiedzieć string2, string1.
Więc to, co to zrobi, to skopiowanie ciągu
do skopiowania do tablicy znaków string2, a następnie wydrukowanie
go za pomocą printf.
Chciałem przejść przez przykład, w jaki sposób można używać
wskaźników znaków zamiast tablic znaków i dlaczego czasami są one preferowane.
Wspomnieliśmy, że czasami jest to preferencja programisty, w której jeśli
programowałeś w poprzednich językach, takich jak Fortran,
możesz być przyzwyczajony do podniesienia. Ale jeśli go masz,
zobaczysz korzyści płynące z używania wskaźników.
Mam nadzieję, że to było pomocne. Dziękuję Ci.