Tablice znaków służą do przechowywania ciągów znaków, czyli tekstu. Przy deklaracji musimy pamiętać, żeby podać o jedną komórkę więcej niż potrzebujemy, ponieważ ciąg znaków musi być zakończony specjalnym znakiem '\0' (kod ASCII = 0). Dzięki temu "zakończeniu", między innymi program wie kiedy zakończyć wypisywanie tekstu.
Poniżej przedstawiony jest schemat przechowywania tekstu "Ala ma kota". W tym przypadku potrzebujemy co najmniej dwunastu komórek tablicy (pamiętajmy, że numerowanie zaczynamy od zera):
$$\overset{\underline{'A'}}{0}\ \overset{\underline{'l'}}{1}\ \overset{\underline{'a'}}{2}\ \overset{\underline{'\ '}}{3}\ \overset{\underline{'m'}}{4}\ \overset{\underline{'a'}}{5}\ \overset{\underline{'\ '}}{6}\ \overset{\underline{'k'}}{7}\ \overset{\underline{'o'}}{8}\ \overset{\underline{'t'}}{9}\ \overset{\underline{'a'}}{10}\ \overset{\underline{'\backslash 0'}}{11}$$
Wypełnianie tablicy znakami
Tablicę można wypełnić przy deklaracji (podobnie jak inne obiekty), pamiętając o tym szczególnym znaku na końca tablicy:
#include <iostream> #include <cstdlib> using namespace std; int main() { //pierwszy sposób char tab[5] = {'a','b','\0'}; //tworzymy tablicę 5-elementową, która może //przechować do 4 znaków cout<< tab<< endl; //program wypisze ab //drugi sposób - nie podając wielkości tablicy - program sam dopasuje jej wielkość char tab2[] = {'a','b','\0'}; //tym razem tworzymy tablicę 3-elementową cout<< tab2<< endl; //trzeci sposób - podajemy ciąg znaków pamiętając o podwójnym cudzysłowie char tab3[] = "Ala ma kota :)"; cout<< tab3<< endl; system("pause"); return 0; } |
Wypełnianie tablicy poprzez przypisanie do danych komórek odbywa się tak samo jak na innych typach.
Zauważmy, że przy wyświetlaniu tablicy znaków podajemy tylko nazwę tablicy. |
Wprowadzanie ciągów znaków
Podobnie jak przy wypisywaniu tekstu, do wprowadzania posługujemy się tylko nazwą tablicy. W tym miejscu należy zwrócić uwagę na działanie obiektu "cin". Dane zostaną wczytane do napotkania pierwszej spacji lub znaku końca linii. Oznacza to, że tym sposobem możemy wczytać tylko jeden wyraz.
#include<iostream> #include<cstdlib> using namespace std; int main() { char tablica[100]; cout<<"Podaj imie i nazwisko: "; cin>>tablica; cout<<"Twoje dane osobowe: "<<tablica<<endl; //dane zostaną zredukowane //do imienia system("pause"); return 0; } |
Zrzut:
Metoda getline().
Drugim sposobem, jaki można tu zastosować jest wykorzystanie metody getline() obiektu cin. Funkcja ta jest ukierunkowana na wczytywanie całych wierszy i odrzuceniem znaku końca linii. Konstrukcja wygląda następująco:
cin.getline(tab, bufor); |
gdzie tab to tablica znaków, a bufor to wielkość tej tablicy (tablica może przechować bufor - 1 znaków + znak końca tablicy).
Przeanalizujmy jeszcze raz nasz program:
#include<iostream> #include<cstdlib> using namespace std; int main() { char tablica[100]; cout<<"Podaj imie i nazwisko: "; cin.getline(tablica,100); //wykorzystanie metody getline() cout<<"Twoje dane osobowe: "<<tablica<<endl; system("pause"); return 0; } |
Zrzut:
Następną dostępną metodą jest funkcja o nazwie get() występująca w kilku wariantach. Metoda ta może działać podobnie jak getline, z tą różnicą, że znak nowego wiersza nie jest odrzucany (jak w przypadku getline()), tylko pozostaje w kolejce wejściowej. Oznacza to, że ponowne użycie get() nie pobierze ciągu znaków, ponieważ zakłada, że nastąpił już koniec wiersza. Aby zaradzić temu problemowi można użyć innej postaci get, a mianowicie metody get() bez argumentów. Pobiera ona następny znak, a wiec znak końca linii zostanie usunięty i można ponownie wczytywać dane:
#include<iostream> #include<cstdlib> using namespace std; int main() { char tablica[100]; cout<<"Podaj imie i nazwisko: "; //wykorzystanie metody getline() cin.get(tablica,100); //pobranie wiersza danych cout<<"Twoje dane osobowe: "<<tablica<<endl; cin.get(); //usunięcie znaku końca linii cout<<"Ponownie podaj imię i nazwisko: "; cin.get(tablica,100); //pobranie następnego wiersza danych cout<<"Twoje dane osobowe: "<<tablica<<endl; system("pause"); return 0; } |
Dokładnie ten sam efekt można osiągnąć wywołując na przemian metodę get z argumentami i bez argumentów:
#include<iostream> #include<iostream> #include<cstdlib> using namespace std; int main() { char tablica[100]; cout<<"Podaj imie i nazwisko: "; //wykorzystanie metody getline() cin.get(tablica,100).get(); //pobranie wiersza danych cout<<"Twoje dane osobowe: "<<tablica<<endl; cout<<"Ponownie podaj imię i nazwisko: "; cin.get(tablica,100).get(); //pobranie następnego wiersza danych cout<<"Twoje dane osobowe: "<<tablica<<endl; system("pause"); return 0; } |
Zadanie. Napisz program, który pobierze ze standardowego wejścia trzy zdania oraz wyświetli je w odwrotnej kolejności, zamieniając wszystkie male litery (tylko angielskie) na duże.
Rozwiązanie. Warto zauważyć, że numery ASCII małych liter mieszczą się w przedziale [97; 122]. Różnica między małymi i dużymi literami wynosi 32. Będziemy sprawdzać każdy znak, czy jest to mała litera. Gdy będzie spełniony warunek przesuniemy ją o 32 numery w dół aby przeskoczyć na dużą literę. Do przechowania zdań użyjemy tablicy dwuwymiarowej.
#include<iostream> #include<cstdlib> using namespace std; int main() { char zdanie[3][100]; cout<<"Podaj pierwsze zdanie: "; cin.getline(zdanie[0],100); cout<<"Podaj drugie zdanie: "; cin.getline(zdanie[1],100); cout<<"Podaj trzecie zdanie: "; cin.getline(zdanie[2],100); for(int i=2;i>=0;i--) //pętla odpowiedzialna { //za wypisanie w odwrotnej kolejności int k = 0; //ustawienie na czytanie pierwszegj komórki tablicy while(zdanie[i][k]) //dopóki nie napotkamy znak końca linii, { //pętla będzie sie wykonywać if(zdanie[i][k]>=97&&zdanie[i][k]<=122) //sprawdzenie czy //znak jest małą literą cout<<char(zdanie[i][k]-32); //jeśli tak to przesuwamy //ją do dużej litery else cout<<(char)zdanie[i][k]; ++k; //przeskoczenie do następnej komórki tablicy } cout<<endl; } system("pause"); return 0; } |