PROGRAMOWANIE I ALGORYTMY

Tablice znaków


powrót

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>
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; 
;
	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:

tablice znaków

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>
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;
	
	return 0;
}

Zrzut:

getlilne

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>
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; 
	
	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>
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; 

	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>
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;
	}
	
	return 0;
}