Skrypt do Podstaw Programowania

Spis treści:

  1. Używanie dostępnego w laboratoriach narzędzia do programowania (Microsoft Visual C++).
  2. Budowa programu aplikacji konsolowej.
  3. Wyświetlanie na ekranie tekstu.
  4. Manipulowanie wyświetlanym tekstem.
  5. Pobieranie z klawiatury liczb i tekstu.
  6. Proste obliczenia matematyczne.
  7. Instrukcja warunku „if else”.
  8. Instrukcja wyboru „switch case”.
  9. Zmienne lokalne i globalne.
  10. Funkcje bezargumentowe.
  11. Pętla „for”.
  12. Pętla „while”.
  13. Pętla „do while”.
  14. Tworzenie tablicy.
  15. Zapis do tablicy.
  16. Odczyt z tablicy.
  17. Przestawianie elementów tablicy.
  18. Wskaźniki do zmiennych i tablic.
  19. Dostęp do zmiennych za pomocą wskaźników.
  20. Dostęp do tablic za pomocą wskaźników.
  21. Definiowanie i wykorzystanie własnych funkcji z argumentami.
  22. Przekazywanie parametrów przez wartość, referencję i adres.
  23. Przykładowe funkcje biblioteki string.h.
  24. Tworzenie własnych funkcji operujących na łańcuchach znaków.
  25. Dynamiczna alokacja pamięci na tablice jednowymiarowe i łańcuchy.


Używanie dostępnego w laboratoriach narzędzia do programowania (Microsoft Visual C++)

 

Uruchom program Microsoft Visual C++ i utwórz pusty plik o rozszerzeniu .cpp dokładnie w następujący sposób:

  1. Wybierz menu File, następnie New, a następnie Project….
  2. Otworzyło się okno „New Project„.
  3. W części Project types wybierz Win32.
  4. W części Templates wybierz Win32 Console Application.
  5. W polu Name wpisz dowolną nazwę twojego projektu.
  6. W polu Location wskaż folder, w którym będą umieszczane twoje projekty.
  7. Kliknij OK.
  8. Otworzyło się okno Win32 Application Wizard.
  9. Kliknij Next >.
  10. Zaznacz okienko Empty project i klinij Finish.
  11. W lewej części narzędzia pojawiły się foldery twojego projektu.
  12. Kliknij tam prawym klawiszem myszy na folderze Source Files i wybierz z menu, które się pojawi Add, a następnie New Item….
  13. Otworzyło się okno Add New Item.
  14. W części Categories wybierz Visual C++.
  15. W części Templates wybierz C++ File (.cpp).
  16. W polu Name wpisz dowolną nazwę pliku i kliknij Add.
  17. Utworzyłeś plik, w którym możesz napisać swój program.

Na wszystkich laboratoriach do każdego zadania trzeba będzie tworzyć osobny projekt z osobnym plikiem .cpp


Budowa programu aplikacji konsolowej

Program C++ składa się z kilku następujących po sobie części:

  • biblioteki
  • dodatkowe informacje
  • zmienne globalne
  • własne funkcje
  • funkcja main

Biblioteki

Biblioteka to zbiór funkcji, z których się korzysta w programie. Np. operacje pisania na ekranie i pobierania znaków z klawiatury zdefiniowane są m.in. w bibliotece iostream, co zapisuje się następująco:

#include <iostream>

Wszystkie używane biblioteki wpisuje się w ten sposób, jedna pod drugą.

Dodatkowe informacje

Gdy używa się biblioteki iostream itp., to jako dodatkową informację można podać:

using namespace std;

Zmienne globalne

Zmiennymi globalnymi i własnymi funkcjami zajmiemy się później.

Main

Funkcja main zawiera wszystko to, co ma zostać wykonane w programie. Może ona wyglądać nastepująco:

void main ()
{
cout << "witaj";
}

Powyższa funkcja nazywa się main. Przed jej nazwą podany jest typ danych wyjściowych tej funkcji (ponieważ funkcja ta niczego nie zwraca, to piszemy void). Między klamrami znajduje się tzw. ciało funkcji main, czyli wszystkie operacje, które wykonują się w niej (tutaj: wypisanie na ekranie napisu witaj)

Umieść w swoim pliku .cpp wszystkie powyższe fragmenty kodu w odpowiedniej kolejności, po czym naciśnij F7 aby m.in. sprawdzić, czy wszystko jest poprawnie zapisane (powinien wyświetlić się napis Build: 1 succeeded, 0 failed. Jeśli plik zawiera błędy, wyświetli się napis Build: 0 succeeded, 1 failed).  Następnie, aby uruchomić program, naciśnij kombinację klawiszy Ctrl i F5.


Wyświetlanie na ekranie tekstu

Aby wyświetlić na ekranie tekst, można użyć funkcji cout (z biblioteki iostream) lub operacji printf z biblioteki stdio.h.

Poniższe dwa przykłady wyświetlają na ekranie napis witaj i napis zegnaj pod nim.

#include <iostream>
using namespace std;
void main ()
{
  cout << "witaj" << endl << "zegnaj";
}

Powyższe polecenie cout poprzedza wszystko to, co chcemy wyświetlić na monitorze: napis witaj, przejście do nowej linii (polecenie endl) i napis zegnaj. Elementy te oddziela się znakiem <<.
Napisy podaje się w cudzysłowach.
Na końcu linii musi być średnik.

#include <stdio.h>
void main ()
{
  printf("witaj\nzegnaj");
}

Powyższe polecenie printf jest funkcją, w której nawiasach znajduje się wszystko to, co chcemy wyświetlić na monitorze: napis witaj, przejście do nowej linii (znaki \n) i napis zegnaj. Elementy te tworzą jeden ciąg znaków, który umieszcza się w cudzysłowach.
Na końcu linii musi być średnik.


Manipulowanie wyświetlanym tekstem

Gdy korzysta się z biblioteki iostream, można w pewnym stopniu formatować wyświetlany tekst, na co pozwala biblioteka iomanip, np. wyrównać wyrazy z kilku linii do prawej strony, co pokazuje poniższy kod:

#include <iostream>
#include <iomanip>
using namespace std;
void main ()
{
  // pierwsza linia tekstu:
  cout<<setw(7)<<"sss"<<setw(5)<<"zzzz"<<endl;
  // druga linia tekstu:
  cout<<setw(7)<<"sssss"<<setw(5)<<"zz"<<endl;
}

Powyższe polecenie setw(7), poprzedzające jakiś wyraz (umieszczony w cudzysłowach) powoduje, że wyraz ten zostanie wydrukowany w 7 znakach. Jeśli wyraz ten ma mniej niż siedem znaków, zostanie on poprzedzony tyloma spacjami, ilu znaków brakuje. W efekcie wyrazy sss i sssss zostaną wyrównane do prawej strony.

Na końcu każdej linii po znaku // można umieszczać dowolne komentarze.

Przepisz (przekopiuj) treść tego programu i zobacz jak działa.


Pobieranie z klawiatury liczb i tekstu

Aby pobrać z klawiatury liczbę, trzeba najpierw utworzyć dla niej zmienną. Można to zrobić wewnątrz ciała funkcji main (będzie to wówczas tzw. zmienna lokalna), np. dla liczby całkowitej – zmienna typu int, dla liczby rzeczywistej – zmienna typu float lub dla dużej liczby rzeczywistej – zmienna typu double. Oto definicja zmiennych: a, b, c, d.

int a; //zmienna a typu int
float b,c; //zmienne b i c typu float
double d; //zmienna d typu double

Aby pobrać z klawiatury tekst, trzeba najpierw utworzyć dla niego zmienną typu string (inne możliwe typy omówione zostaną w przyszłości) podobnie jak poprzednio utworzono zmienne dla liczb. Tym razem jednak dodatkowo stosuje się bibliotekę string. Oto definicja zmiennej tekstowej txt.

string txt; //zmienna txt typu string

Poniższy program pobiera z klawiatury (czyli wymaga wpisania) całkowitą liczbę do zmiennej a i tekst do zmiennej txt, po czym wyświetla je, korzystając z biblioteki iostream.

#include <iostream>
#include <string>
using namespace std;
void main ()
{
 int a;
 string txt;
 //pobranie z klawiatury liczby
 //i wpisanie jej do zmiennej a
 cout << "podaj liczbe:"; cin >> a;
 //pobranie z klawiatury slowa
 //i wpisanie go do zmiennej txt
 cout << "podaj slowo:"; cin >> txt;
 cout << "wpisano " << a << " i " << txt;
}

Polecenie cin >> z powoduje wczytanie ciągu znaków (tekstu) z klawiatury do zmiennej z. Zwróć uwagę na inny kierunek strzałek, niż stosuje się przy cout.

W celu pobrania z klawiatury dowolnego ciągu znaków, zawierającego także spacje i znaki przejścia do nowej linii (tzw. entery), należy skorzystać z innej funkcji, zamiast cin, mianowicie z getline, np. w poniższy sposób.

cin.sync();
getline(cin, txt, '$');

Powyższa funkcja getline spowoduje wczytanie z klawiatury (cin) ciągu znaków do zmiennej txt (typu string). Znaki wczytywane będą tak długo, aż zostanie naciśnięty znak $. Dodatkowo wcześniej warto wyczyścić ewentualne pozostałe znaki pobrane instrukcją cin za pomocą funkcji cin.sync().

Poniższy program, korzystając z biblioteki stdio.h, pobiera z klawiatury liczbę całkowitą, po czym wyświetla ją jako liczbę całkowitą i jako liczbę rzeczywistą.

#include <stdio.h>
void main ()
{
 int a;
 printf("podaj liczbe:");
 //pobranie liczby całkowitej do zmiennej a
 scanf("%d",&a);
 printf("wpisano %d (czyli %f)",a,(float)a);
}

Powyższa funkcja scanf, która pobiera z klawiatury ciąg znaków, posiada dwa argumenty: „%d” określający typ wprowadzanych danych (wprowadzany ciąg znaków ma być traktowany jako liczba typu int) i &a będący adresem (symbol &) zmiennej, do której zostanie wpisana wprowadzana liczba.

Powyższa funkcja printf jest tutaj dwuargumentowa. Pierwszym argumentem jest ciąg znaków do wyświetlenia na ekranie, przy czym zamiast znaków %d i %f wypisana zostanie zawartość zmiennej a jako: liczba całkowita (gdzie %d) i jako liczba rzeczywista (gdzie %f). Kolejnymi argumentami tej funkcji są zmienne, które mają być wydrukowane w miejsce symboli z procentami (w tej samej kolejności).

Zapis (float)a oznacza, że zmienna a zostanie w tym miejscu potraktowana nie jako liczba typu int, a jako liczba typu float.


Proste obliczenia matematyczne

Wiele przydatnych funkcji matematycznych znajduje się w bibliotece math.h, m.in. potęgowanie i pierwiastkowanie. Te i inne funkcje wymagają właściwych typów używanych zmiennych.

Oto przykładowe operacje matematyczne i zdefiniowane dla nich zmienne:

double a,b,c; //zmienne typu double
a = sqrt(b); //pierwiastek kwadratowy z liczby b
a = pow(b,c); //b do potęgi c

Instrukcja warunku „if else”

Najprostszą instrukcją warunkową jest instrukcja if, której przykład znajduje się poniżej. W funkcji tej, jeśli warunek a<b jest spełniony, wykonana zostanie operacja c = a+b:

int a,b,c;
 if(a<b)
 {
 c = a+b;
 }

Instrukcja if może definiować też operacje, które mają się wykonać, jeśli podany warunek nie jest spełniony. W poniższym przykładzie, jeśli warunek a<b nie zostanie spełniony, wykonana zostanie operacja c = a-b:

int a,b,c;
 if(a<b)
 {
  c = a+b;
 }
 else
 {
  c = a-b;
 }

Oczywiście między klamrami można umieścić więcej niż jedną operację, zależnie od tego, co ma zostać wykonane w ciele if i co w ciele else.

W ramach ciała else można umieścić kolejną instrukcję wyboru if. W poniższym programie, jeśli warunek a<b nie jest spełniony, to sprawdzany jest warunek a==b. Jeśli jest spełniony, wykonywana jest operacja c = a*b. Jeśli jednak i ten warunek nie jest spełniony, wykonywana jest operacja c = a-b:

int a,b,c;
 if(a<b)
 {
 c = a+b;
 }
 else if(a==b)
 {
 c = a*b;
 }
 else
 {
 c = a-b;
 }

Instrukcja wyboru „switch case”

Instrukcja wyboru switch pozwala na wykonanie odpowiednich operacji, zależnie od wartości podanej zmiennej.

W poniższym programie sprawdzana jest wartość zmiennej a, po czym po kolei sprawdzane są wszystkie warunki podane po słowach case. Np. jeśli a == 7, to wykonana zostanie operacja a++ (zwiększenie wartości a o 1). Jeśli natomiast a == 12, to wykonane zostaną operacje b = 2 i a += b (zwiększenie wartości a o wartość b, czyli o 2).

Słowo break zakazuje wykonywania operacji z kolejnych case‚ów, czyli kończy wykonanie instrukcji switch.

switch (a)
{
 case 7: //jeśli a == 7, zwiększ a o 1
  a++;
  break;
 case 12: //jeśli a == 12, dodaj 2 do a
  b = 2;
  a += b;
  break;
 case 13: //jeśli a == 13, wyzeruj a
  a = 0;
}

Przykład zastosowania instrukcji switch-case w konstrukcji menu programu.

W poniższym programie możliwe jest wykonanie trzech różnych funkcji, naciskając odpowiednio klawisz 1, 2 lub 3. Po wykonaniu wybranej funkcji ekran jest czyszczony i ponownie wyświetlane jest menu. Naciśnięcie klawisza 4 spowoduje zamknięcie programu.

int wybor = 0; //nr wybranej pozycji
//wyświetlenie menu:
while (wybor != 4) { //4 zakończy program
 system("CLS");  //wyczyszczenie ekranu
 cout << "MENU" << endl;
 cout << "1. funkcja pierwsza." << endl;
 cout << "2. funkcja druga." << endl;
 cout << "3. funkcja trzecia." << endl;
 cout << "7. koniec programu." << endl << endl;
 cout << "TWOJ WYBOR: ";  cin >> wybor;
 //wykonanie wybranej funkcji
 switch (wybor) {
  case 1:
   funkcja1();
   break;
  case 2:
   funkcja2();
   break;
  case 3:
   funkcja1();
   break;
   }
 }

Zmienne lokalne i globalne

Dotychczasowe programy posiadały tylko tzw. zmienne lokalne. Są to zmienne, które widoczne są tylko dla tej funkcji, w której ciele zostały zdefiniowane.

W odróżnieniu od nich, tzw. zmienne globalne widoczne są dla całego programu. Położenie zmiennych globalnych w ciele programu podano w punkcie 2.  poradnika.

Poniższy program pokazuje zdefiniowanie zmiennych lokalnych i globalnych.

#include <iostream>
using namespace std;
int a; //zmienna globalna a
int b; //zmienna globalna b
void main()
{
 int b; //zmienna lokalna b
 //Dla funkcji main globalna b nie istnieje,
 //a tylko lokalna b.
 int c; //zmienna lokalna c
 // tutaj można wstawić operacje programu
}

Funkcje bezargumentowe

Dowolny ciąg operacji można umieścić we własnoręcznie stworzonej funkcji, którą umieszcza się w ciele programu w części własnych funkcji (patrz pkt. 2 poradnika). Dzięki temu w ciele funkcji main można zamiast tego ciągu operacji wykonać tę funkcję. Łatwiej jest też powtórzyć dowolny ciąg operacji, powtarzając tylko wykonanie funkcji je zawierającej, zamiast wszystkich tych operacji w ciele funkcji main.

Każda własna funkcja, podobnie jak funkcja main, może korzystać z wszystkich zmiennych globalnych. Jeżeli tylko zmienne globalne są jej danymi wejściowymi, to taka funkcja nazywa się funkcją bezargumentową.

Oto dwa programy, z których pierwszy wylicza sumę a+b w ciele funkcji main, a drugi w osobnej funkcji suma. Poza tym oba programy działają identycznie.

#include <iostream>
using namespace std;
int a,b;  //globalne zmienne
void main()
{
 a = 1;
 b = 4;
 cout << a+b;
}
#include <iostream>
using namespace std;
int a,b;  //globalne zmienne
int suma()
{
 //zmienna lokalna funkcji suma (tu będzie wynik):
 int wynik;
 wynik = a+b; // wyliczenie wyniku
 return wynik; // zwrócenie wyniku
}
void main()
{
 a = 1;
 b = 4;
 cout << suma();
}

Powyższa funkcja suma ma przed nazwą typ int, gdyż funkcja ta zwraca liczbę typu int. Funkcja taka musi posiadać instrukcję return, po której podaje się wartość zwracaną przez tę funkcję (w tym przypadku zwracana jest suma a+b).


Pętla „for”

Aby program wykonywał daną operację, należy umieścić ją w pętli i określić liczbę wykonań pętli lub „czas” jej wykonania.

Jeśli znana jest liczba wykonań pętli, można zastosować instrukcję for. Poniżej znajduje się przykład pętli for, w której wykonywane są operacje cin i cout 8 razy.

float a;
int i;
for (i=1; i<=8; i++)
{
 cin >> a;
 cout << 2*a;
}

Powyższa instrukcja for wykonuje operacje zawarte w swoim ciele (między swoimi klamrami) tak długo, jak długo warunek i<=8 jest spełniony. Pierwotnie i ma wartość i=1. Po każdym wykonaniu ciała pętli zmienna i jest zwiększana o 1 (i++). Oczywiście można zamiast inkrementacji i++ wstawić inną operację, która będzie w inny sposób zmieniała wartość i.


Pętla „while”

Jeśli w trakcie programowania nie znamy jeszcze liczby wykonania pętli i nie będzie ona zadawana z klawiatury, można zastosować instrukcję while. Poniżej znajduje się przykład pętli while, która wykonuje się tak długo, jak długo zmienna z jest różna od litery q (zmienna z pobierana jest z klawiatury w każdym wykonaniu ciała pętli).

char z = ' ';
while (z != 'q')
{
 z = getch();
}

Powyższa instrukcja while wykonuje operacje zawarte w swoim ciele tak długo, jak długo warunek z != ‚q’ jest spełniony (z nie jest literą q), począwszy od pierwszego wykonania. Pętla wykona się przynajmniej 1 raz, gdyż na początku z jest spacją.


Pętla „do while”

Pewnym wariantem instrukcji while jest instrukcja dowhile.

char z;
do
{
 z = getch();
}
while (z != 'q');

Powyższa instrukcja do … while wykonuje to samo co przykład dla instrukcji while, z tym, że bez względu na pierwotną wartość znaku z ciało pętli wykona się przynajmniej jeden raz.
Inaczej mówiąc, tym razem sprawdzenie warunku dla pętli odbywa się nie przed wykonaniem jej ciała, ale po.


Tworzenie tablicy

Tablicę, czyli zbiór danych tego samego typu, tworzy się (deklaruje się), podobnie jak każdą zmienną, jako tablicę globalną (w części zmiennych globalnych) lub jako tablicę lokalną (w ciele dowolnej funkcji).

Poniższy przykład pokazuje utworzenie tablic: liczb całkowitych, liczb rzeczywistych i znaków.

int t1[7]; //tablica na 7 liczb całkowitych
float t2[12]; //tablica na 12 liczb rzeczywistych
char t3[10]; //tablica na 10 znaków

A oto tablica tablic, czyli macierz 4×6, mieszcząca 24 liczby całkowite:

int macierz[4][6]; //macierz 4x6 liczb całkowitych

Tablice te po utworzeniu są puste dopóki nie zostaną w nich umieszczone jakieś elementy.


Zapis do tablicy

Do tablicy można wstawiać dowolne zmienne, pod warunkiem, że:

  1. Każda wstawiana zmienna będzie tego samego typu, co typ tablicy (ewentualnie można rzutować inne typy).
  2. Zmienne wstawiane są do komórek tablicy o indeksach od 0 do n-1, gdzie n to rozmiar tablicy (liczba jej komórek).

Poniższy przykład pokazuje wstawienie liczby 123,45 do tablicy t2 do komórki nr 6 (licząc od zera). Następnie pokazuje wstawienie kolejnych liczb od 101 do 107 do tablicy t1, co wykonane jest automatycznie – w pętli.

//zapisanie konkretnej komórki tablicy:
t2[6] = 123.45;
int i;
//zamisanie każdej komórki tablicy:
for (i=0; i<7; i++)
{
 t1[i] = 100+i;
}

Odczyt z tablicy

Można odczytać zawartość każdej komórki tablicy, pod warunkiem, że:

  1. Odczytywana komórka zostanie przepisana do zmiennej tego samego typu, co typ tablicy (ewentualnie można rzutować inne typy).
  2. Zmienne odczytywane są z komórek tablicy o indeksach od 0 do n-1, gdzie n to rozmiar tablicy (liczba jej komórek).

Poniższy przykład pokazuje odczytanie liczby 123,45 z komórki nr 6 tablicy t2 do zmiennej z. Następnie pokazuje wyświetlenie wszystkich liczb wstawionych do tablicy t1, co wykonane jest automatycznie – w pętli.

//zapisanie liczby z konkretnej komórki tablicy
//w zmiennej z:
float z = t2[6];
int i;
//odczytanie każdej komórki tablicy:
for (i=0; i<7; i++)
{
 cout << t1[i];
}

Przestawianie elementów tablicy

Aby zamienić miejscami zawartość dwóch komórek tej samej tablicy, należy np. najpierw „wyjąć” zawartość jednej z tych komórek (i przechować ją w jakiejś tymczasowej zmiennej, by jej nie stracić), następnie „wyjąć” zawartość drugiej komórki i „włożyć” ją do pierwszej komórki. Na końcu z tymczasowej zmiennej „wyjąć jej zawartość i „włożyć” ją do drugiej komórki.

Chodzi o to, że gdy do danej komórki coś się wkłada, to traci się jej wcześniejszą zawartość. Z tego powodu należy wcześniej zachować jej kopię. Ilustruje to poniższy przykład.

//utworzenie tablicy na dwie liczby całkowite 12 i 21:
int tablica[2];
tablica[0] = 12;
tablica[1] = 13;
int tmp;  //zmienna tymczasowa
//przechowanie kopii zawartości komórki nr 0:
tmp = tablica[0];
//przepisanie zawartości komórki nr 1 do komórki nr 0:
tablica[0] = tablica[1];
//teraz obie komórki mają tę samą zawartość (13)
//przepisanie dawnej zawartości komórki nr 0
//do komórki nr 1:
tablica[1] = tmp;

Wskaźniki do zmiennych i tablic

Wskaźnik to zmienna zawierająca adres innej zmiennej (lub dowolnego obszaru pamięci).

Poniższy przykład pokazuje definicje wskaźników: liczby typu int, liczby typu float i tablicy liczb typu double.

int * a;
//a jest wskaźnikiem na liczbę typu int
//ale jeszcze na nią nie wskazuje
float * b;
//b jest wskaźnikiem na liczbę typu float
//ale jeszcze na nią nie wskazuje
double (*tab)[10];
//tab jest wskaźnikiem na 10-elementową tablicę
//liczb typu double ale jeszcze na nią nie wskazuje

Dostęp do zmiennych za pomocą wskaźników

Wskaźnik może przechowywać adres dowolnej zmiennej jego typu. Wówczas zawartość tej zmiennej dostępna jest także przez ten wskaźnik.

Poniższy przykład pokazuje różne operacje na zmiennych, z wykorzystaniem wskaźników.

int k = 23; //zmienna k zawiera liczbę 23
int f = 33; //zmienna f zawiera liczbę 33
int * w; //wskaźnik na jakąś liczbę typu int
w = &k; //w odtąd wskazuje na zmienną k
//(&k to akdres zmiennej k)
*w = 100; //od teraz zmienna k zawiera liczbę 100
//wyświetlenie sumy liczb ze zmiennych f i k
//(zamiast k podano *w):
cout << f+*w;
//wyświetlenie liczby ze zmiennej f
//(* i & wzajemnie się zmoszą)
cout << *&f;

Dostęp do tablic za pomocą wskaźników

Wskaźnik może przechowywać adres dowolnej tablicy zmiennych jego typu. Wówczas zawartość tej tablicy dostępna jest także przez ten wskaźnik.

Poniższy przykład pokazuje różne operacje na tablicy tab, z wykorzystaniem wskaźnika.

float tab[10]; //tablica 10 liczb typu float (pusta)
//podanie liczby dla każdej komórki tablicy tab:
for(int i = 0; i<10; i++)
{
 cin >> *(tab+i); // *(tab+i) to inaczej tab[i]
}
float * w; //wskażnik na jakąś liczbę typu float
w = tab;
//w wskazuje od teraz na pierwszą komórkę tablicy tab
//wyświetlenie zawartości ósmej komórki tablicy
//(czyli tab[7])
cout << *(w+7);
w++;
//w wskazuje teraz na drugą komórkę tablicy tab
//wyświetlenie zawartości dziewiątej komórki tablicy
//(czyli tab[8])
cout << *(w+7);

Definiowanie i wykorzystanie własnych funkcji z argumentami

W pkt. 10 poradnika przedstawione zostało zagadnienie bezargumentowych funkcji własnych, które można napisać, a potem wykorzystywać. Bezargumentowa funkcja jest wyodrębnionym fragmentem programu, który ilekroć wykonany, działa zawsze identycznie (o ile nie zmieniają się używane w niej zmienne globalne).

Funkcja z argumentami (inaczej: parametrami) wykorzystuje podane argumenty i działa na ich podstawie. Tak więc dla różnych wartości parametru – działa różnie.

Poniżej znajduje się program, który definiuje funkcję suma i wykorzystuje ją dla różnych parametrów – składników sumy.

#include <iostream>
using namespace std;
int suma(int a, int b)
//a i b to parametry przekazywane do funkcji,
//tutaj: składniki sumy
{
 int wynik; //zmienna lokalna funkcji suma
 //(tu będzie wynik)
 wynik = a+b; //wyliczenie wyniku
 return wynik; //zwrócenie wyniku
}
void main()
{
 //do funkcji suma przekazywane są liczby 5 i 7:
 cout << suma(5,7);
 int x = 5;
 int y = 7;
 //do funkcji suma przekazywane są wartości
 //zmiennych x i y:
 cout << suma(x,y);
}

Przekazywanie parametrów przez wartość, referencję i adres

Do funkcji argumentowej można przekazać parametry na kilka możliwych sposobów: przez wartość, przez referencję i przez adres.

Przekazanie argumentu przez wartość

Przekazanie argumentu przez wartość zostało omówione w poprzednim punkcie poradnika.

W poniższym programie zdefiniowano funkcję suma, która otrzymuje argumenty (składniki sumy) a i b przez wartość. Funkcja ta wywołana jest dla zmiennych x i y, ale nie pracuje na tych zmiennych, lecz na ich kopiach, którym przekazywane są tylko ich wartości.

int suma(int a, int b) //definicja funkcji
{
 return a + b; //a i b to zmienne inne niż x i y
 //ale wartość a to wartość x, wartość b to wartość y
}
int main()
{
 int x = 12;
 int y = 34;
 //wykonanie funkcji suma dla zmiennych x i y:
 int s = suma(x,y);
}

Przekazanie argumentu przez referencję

W poniższym programie zdefiniowano funkcję suma, która otrzymuje argumenty (składniki sumy) a i b przez referencję. Funkcja ta wywołana jest dla zmiennych x i y, i pracuje na tych zmiennych, ale pod innymi (referencyjnymi) nazwami.

int suma(int &a, int &b) //definicja funkcji
//a i b to referencyjne nazwy zmiennych x i y
{
 return a + b;
}
int main()
{
 int x = 12;
 int y = 34;
 //wykonanie funkcji suma dla zmiennych x i y:
 int s = suma(x,y);
}

Przekazanie argumentu przez adres

W poniższym programie zdefiniowano funkcję suma, która otrzymuje argumenty (składniki sumy) a i b przez adres. Funkcja ta wywołana jest dla zmiennych x i y, i pracuje na tych zmiennych, gdzyż otrzymuje ich adresy.

int suma(int *a, int *b) //definicja funkcji
{
 return *a + *b; //a i b to te same zmienne, co x i y
}
int main()
{
 int x = 12;
 int y = 34;
 //wykonanie funkcji suma dla zmiennych x i y
 //(podano ich adresy)
 int s = suma(&x,&y);
}

Przykładowe funkcje biblioteki string.h

Biblioteka string.h zawiera różne funkcje, które pozwalają w łatwy sposób operować na łańcuchach znaków, dzięki m.in. czemu można je traktować jak zwykłe zmienne (a nie tylko jak zmienne tablicowe).

Poniższy kod pokazuje definicję zmiennej łańcuchowej i jej wykorzystanie w kilku funkcjach z biblioteki string.h

//utworzenie łańcucha 100 znaków z zawartością:
char tekst[100] = "Tresc tekstu.";
//utworzenie łańcucha 100 znaków z zawartością:
char txt[100] = "Inny lancuch znakow.";
//po ostatnim znaku (kropce) łańcuch zawiera znak '\0',
//który jest znakiem końca łańcucha
//dlugosc otrzymuje liczbę znaków łańcucha tekst:
int dlugosc = strlen(tekst);
//małe litery łańcucha tekst zamieniane są na duże:
tekst = strupr(tekst);
//łańcuch tekst otrzymuje nową zawartość
//- zawartość łańcucha txt:
tekst = strcpy(tekst,txt)

Tworzenie własnych funkcji operujących na łańcuchach znaków

Ponieważ łańcuch znaków jest tablicą znaków, to można na nim pracować jak na tablicy, której każdy kolejny element jest kolejnym znakiem. Należy tylko pamiętać, by:

  • nie wyjść poza rozmiar tablicy (w przykładzie z poprzedniego pkt. poradnika obie tablice mają rozmiar 100),
  • po ostatnim znaku tekstu musi być znak końca (‚\0’).

Dynamiczna alokacja pamięci na tablice jednowymiarowe i łańcuchy

Tworzenie i usuwanie zmiennej

Poniższy program wykorzystuje bibliotekę alloc.h; za pomocą funkcji malloc przydziela pamięć na zmienną typu int (wskazywaną przez wskaźnik w), a następnie za pomocą funkcji free zwalnia tę pamięć:

int *w; //wskaźnik na zmienną typu int
w = (int*) malloc(sizeof(int)); //utworzenie zmiennej
//(int*) - rzutowanie na wskaźnik do int
//sizeof(int) - rozmiar przydzielanej pamięci
free(w); //usunięcie zmiennej

Poniższy program za pomocą operatora new przydziela pamięć na zmienną typu int (wskazywaną przez wskaźnik w), a następnie za pomocą operatora delete zwalnia tę pamięć:

int *w;
w = new int; //utworzenie zmiennej typu int
delete w; //usunięcie zmiennej

Tworzenie i usuwanie tablicy

Poniższy program wykorzystuje bibliotekę alloc.h; za pomocą funkcji calloc przydziela pamięć na tablicę liczb typu int (wskazywaną przez wskaźnik t), a następnie za pomocą funkcji free zwalnia tę pamięć:

int rozmiar; //rozmiar tablicy
//Rozmiar można podawać w trakcie działania programu.
cin >> rozmiar;
int *t; //wskaźnik na tablicę liczb typu int
//utworzenie tablicy:
t = (int*) calloc(rozmiar, sizeof(int));
free(t); //usunięcie tablicy

Poniższy program za pomocą operatora new przydziela pamięć na tablicę liczb typu int (wskazywaną przez wskaźnik t), a następnie za pomocą operatora delete zwalnia tę pamięć:

int rozmiar;
cin rozmiar;
int *t;
t = new int[rozmiar]; //utworzenie tablicy
delete []t; //usunięcie tablicy

Poniższy program tworzy tablicę tablic, a następnie ją usuwa:

int **t;
int rozmiar1, rozmiar2; //rozmiary tablicy
//utworzenie tablicy wskaźników na liczby typu int:
t = new int*[rozmiar1];
for (int i=0; i<rozmiar1; i++)
 //utworzenie tablicy liczb typu int:
 t[i] = new int[rozmiar2];

//usunięcie przydzielonej pamięci:
for (int i=0; i<rozmiar; i++)
 delete []t[i];
delete []t;

Zmiana rozmiaru tablicy

Poniższy przykład pokazuje zwiększenie tablicy liczb int o jedną nową liczbę, umieszczaną na końcu tablicy.

int rozmiar; //rozmiar tablicy
int liczba; //dodawana liczba
int *t;
t = new int[rozmiar]; //utworzenie tablicy
int *tt; //tymczasowy wskaźnik na nową tablicę
//utworzenie nowej tablicy o 1 większej:
tt = new int[rozmiar+1];
//przepisanie do nowej tablicy zawartości starej:
for (int i=0; i<rozmiar; i++)
 tt[i] = t[i];
//dopisanie nowej liczby na koniec:
tt[rozmiar] = liczba;
//usunięcie starej tablicy:
delete []t;
//podpięcie nowej tablicy pod wskaźnik starej:
t = tt;

Comments are closed.