ABC... C
Napisy w C
Napisy w C tworzą tak zwane łańcuchy znakowe. Idea jest bardzo podobna do tej, z jaką mogłeś spotkać się w przypadku BASCOM-a: w pamięci umieszczany jest ciąg kodów ASCII, które kończą się bajtem zerowym. Ten specjalny kod jest zarezerwowany do oznaczenia końca napisu.
W naszym pierwszym programie w celu przesyłania kolejnych znaków wykorzystaliśmy litery ujęte w apostrofy. Litera umieszczona w apostrofach zostanie zamieniona przez kompilator w kod jednego znaku. Tak należy taki zapis traktować: jako pojedynczy znak kodu ASCII. Inaczej ma się sprawa, jeśli litera zostanie umieszczona między znakami cudzysłowu. W takim przypadku mamy do czynienia z łańcuchem kończącym się znakiem zerowym. Tylko między znakami cudzysłowu możemy umieścić cały napis, Między apostrofami wolno nam umieścić tylko jedną literę.
Znaki cudzysłowu zwracają adres, pod jakim w pamięci umieszczony Jest początek napisu! Apostrofy zwracają kod znaku!
W C brak specjalnej zmiennej do obsługi łańcuchów znakowych. Służą do tego zwykłe tablice zbudowane ze zmiennych char (character ang. znak). Trzeba pamiętać, żeby tworzona tablica była o I bajt większa zc względu na konieczność oznaczenia końca napisu. W praktyce, jeśli inicjujemy tablicę jakąś wartością, możemy pozwolić, aby kompilator automatycznie określił jej rozmiar. Uzyskamy to, pozostawiając puste nawiasy kwadratowe przy definicji. Zwykle podajemy jawnie rozmiar tablicy, jeśli konieczne jest dodatkowe miejsce w napisie lub też zmienna nie jest inicjowana: char napis[] = “witaj!”; char napis[32] = “wiecej miejsca’ char napis[16]; // Brak inicjacji
W poprzednich częściach pisałem, że posługując się nazwą tablicy, posługujemy się tak naprawdę wskaźnikiem na pierwszą komórkę pamięci, gdzie zaczynają się dane. Aby mieć możliwość przekazania takiej danej do fitnkcji, musimy posłużyć się wskaźnikiem na char (więcej o wskaźnikach już w tym numerze): void LCDstr(char* 3tr)
{
Rzadziej stosowany, ale również poprawny i działający identycznie jest zapis: void LCDstr(char str[])
Co bardzo ważne, mając taką funkcję, nie musimy zajmować się oddzielnie tworzeniem tablicy znaków oraz jej inicjacją. Funkcję taką można równic dobrze wywołać, podając jej bezpośrednio tekst do przesłania: LCDstr("Napis");
Kompilator sam zajmie się stworzeniem odpowiedniej zmiennej lokalnej, jej inicjacją oraz przesłaniem jej adresu do funkcji.
Przydatną właściwością definiowanych stałych tekstowych jest ich łączność. Znaczy to, że zapis taki jak niżej:
LCDstrCNa" “pis”);
jest równoważny z poprzednim. Jest to przydatne, między innymi, przy dzieleniu długich napisów:
LCDstr(“Dlugi napis”
“dzielony na linie”);
Przydaje się także przy próbie łączenia napisu z innym tekstem, który mógł być wcześniej zdefiniowany:
#define ver "1.0” LCDstr("Program ver.: “ver);
W każdym z powyższych przypadków, jeśli napisy dzidą tylko białe znaki (jak spacja, tabulator oraz znak końca linii), napisy zostaną połączone, a na ich końcu umieszczony będzie znak zerowy.
Istnieją znaki, których nie możemy wpisać bezpośrednio w prosty sposób. Ich uzyskanie jest możliwe za pomocą sekwencji wykorzystującej ukośnik. Odpowiednie możliwości przedstawia tabela pod koniec ramki. Pozycje oznaczone na szaro mają zastosowanie głównie do sterowanie drukarki i podczas naszej przygody z C nie będziemy (raczej) z nich korzystać. W systemie Windows każda linia kończy się znakiem końca linii oraz powrotu karetki („\n\r”).
\n \t |
Nowa linia Tabulator |
Tabulacja pionowa | |
\b |
Backspace |
\r |
Powrót karetki |
\a |
Alarm |
W |
Ukośnik |
V |
Apostrof |
V |
Cudzysłów |
\ooo |
Kod znaku zapisany ósemkowo |
\xhh |
Kod znaku zapisany szesnastkowo Uwaga: w aktualnej wersji GCC nie działa prawidłowo |
Listing 27 LCD: pierwsze 1nt main (wid)
// Inicjacja - uwaga: uproszczona, może wymagać // zmian przy zmianie przyporządkowania portów
ddr(lcd_dport) - l«i,cr_r | 1«łcd_rs | OxOF«LCD D4 j
LCDdaraO H' )J LCOdata('E') ; LCDdata(* L’); LCDdatsCl'); LCDdata<‘0’); LCDdaia(‘ ‘); ŁCDdata(‘:LCDdattaC'-’); -CDdataf')'); return 0;
Posiadamy już wszystkie funkcje konieczne do włączenia i skonfigurowania wyświetlacza. Możemy wysyłać do niego także dane. Listing 27 przedstawia ostatnią potrzebną nam funkcję - funkcję main. Przy inicjacji portu wykorzystujemy fakt, że port danych oraz wyprowadzenia sterujące zostały podłączone do tego samego portu mikrokontrolera. Oszczędza nam to nadmiarowych strukcji, jednak może okazać się, że jeśli zmieni się połączenie wyświetlacza, poza zmianą definicji wyprowadzeń będziemy musieli zmienić także tę linię.
Po przeprowadzonych próbach dodane zostało dodatkowe czyszczenie wyświetlacza. Jest zasadzie przydatne tylko, jeśli korzystamy z zerowania układu z poziomu pro- } gramatora. W innym przy- L_
padku wyświetlacz jest prawidłowo czyszczony podczas inicjacji. Programator niestety w przypadku zerowania powodował czasami wpisanie dodatkowych śmieci na wyświetlaczu.
Program powinien pozwolić się teraz skompilować i po wysianiu do procesora, wyświetlić piękne przywitanie :).
Pierwszy program miał na celu zaspokojenie naszej ciekawości oraz uzyskanie czegokolwiek na wyświetlaczu. Jak się zapewne domyślasz, takie wyświetlanie po jednej literce jest zarówno niewygodne, jak i nieekonomiczne. Oczywiste jest, że w C, tak jak w każdym sensownym języku programowania, istnieje możliwość obsługiwania łańcuchów znakowych jako większej całości. W artykule znajdziesz ramkę opisującą obsługę napisów w C. Podane w niej informacje natychmiast poprzemy przykładem.
Ciąg dalszy na stronie 45.
Listing 28 Proste wypi |
ywanie tekstu. |
void ucostrfchar |
str) |
i nt n—0; | |
while(0 I- st | |
{ | |
LCDd,t.C» |
r[n)); |
} |
40 Październik 2005 Elektronika dla Wszystkich