Podstawy programowania C++

Wybrane podstawowe zagadnienia ze strukturalnego programowania w języku C\C++.

  1. Budowa programu - pobieranie danych z klawiatury - wyświetlanie na ekranie .
  2. Wybrane biblioteki i ich funkcje.
  3. Funkcja główna -> main.
  4. Typy danych.
  5. Struktury.
  6. Instrukcja warunku „if”.
  7. Instrukcja wyboru „switch”.
  8. Pętle: for, while, do..while.
  9. Tablica statyczna.
  10. Wskaźnik.
  11. Funkcje.
  12. Tablica dynamiczna jedno i dwuwymiarowa.

Zadania

Budowa programu

Kolejne części typowego programu:

  • biblioteki – definicje funkcji użytych w programie,

  • dodatkowe polecenia,

  • dane globalne – zmienne i stałe dostępne w całym programie,

  • funkcje – definicje funkcji napisanych i użytych w programie,

  • funkcja główna main.

Dopuszczalna jest również kolejność:

  • biblioteki,

  • dodatkowe polecenia,

  • dane globalne,

  • nagłówki funkcji – „pierwsze linie” definicji funkcji napisanych i użytych w programie,

  • funkcja główna main.

  • funkcje – definicje funkcji napisanych i użytych w programie.

Komentarz do kodu

Komentarz to fragment programu, który nie jest kodem – jest pomijany przez kompilatora. Między znakami /* i */ umieszcza się komentarz, który może zajmować dowolną liczbę linii programu. Po znakach // umieszcza się komentarz, który kończy się z końcem tej samej linii programu.

Biblioteka

Biblioteka to zbiór funkcji, z których korzysta się w programie, ale nie napisanych w nim.

Każdą potrzebną bibliotekę dołącza się poleceniem #include, np.:

#include<iostream> // dołączenie biblioteki iostream

Dodatkowe polecenia

Polecenie using namespace sdt ustawia klawiaturę jako domyślne źródło pobierania danych, a ekran jako domyślne źródło zwracania danych, jeśli używa się operatorów cin i cout z biblioteki iostream:

using namespace std;

Przykład użycia cin i cout:

#include <iostream> 
int main() { 
int a; 
float b; 
std::cout << "Podaj liczbe calkowita: "; 
std::cin >> a; std::cout << "Podaj liczbe rzeczywista: "; 
std::cin >> b; std::cout << "Liczba a = " << a << std::endl; 
std::cout << "Liczba b = " << b << std::endl; 
return 0; 
}

Przykład użycia scanf:

int a; 
float b; 
double c; 
char d; 
scanf("%d", &a); // pobranie liczby całkowitej do a 
scanf("%f %lf %c", &b, &c, &d); // pobranie liczb rzeczywistych do b i c oraz znaku do d 
// (wprowadzane dane są oddzielane spacjami) 
scanf("%f,%lf,%c", &b, &c, &d); // pobranie jak wyżej 
// (wprowadzane dane są oddzielane przecinkami)

gdzie:

  • %d – liczba całkowita (do zmiennej typu int),
  • %f – liczba rzeczywista (do zmiennej typu float),
  • %lf – liczba rzeczywista (do zmiennej typu double),
  • %c – znak (do zmiennej typu char),
  • %s – łańcuch znaków (do zmiennej typu string lub tablicy typu char).

Argumenty funkcji scanf to formatowanie wprowadzanych danych (w cudzysłowie) i adresy zmiennych, do których są wprowadzane. Adres zmiennej to jej nazwa poprzedzona znakiem &. Argumenty oddzielane są przecinkami.

Format danej wprowadzanej do zmiennej opisuje znak % i identyfikator typu zmiennej, opcjonalnie poprzedzony rozmiarem danej.

Przykłąd użycia scanf:

Przy pomocy funkcji printf (z biblioteki stdio.h) można wyświetlić dane bezpośrednio lub do jednej lub więcej zmiennych, np.:

int a = 15; 
float b = 7.45; 
char c = 'k'; 
printf("qwerty"); // wyświetlenie napisu qwerty 
printf("%d", a); // wyświetlenie zawartości a 
printf("b=%f", a); // wyświetlenie napisu b= i zawartości b 
printf("%.1f", a); // wyświetlenie zawartości b 
// z 1 cyfrą części ułamkowej 
printf("%c %d", c, c); // wyświetlenie zawartości c jako znaku, // spacji i zawartości z jako kodu ASCII

gdzie:

  • %d – liczba całkowita (ze zmiennej typu int),
  • %f – liczba rzeczywista (ze zmiennej typu float lub typu double),
  • %c – znak (ze zmiennej typu char),
  • %s – łańcuch znaków (ze zmiennej typu string lub tablicy typu char).

Wybrane biblioteki i ich funkcje

    • alloc.h – operacje na pamięci programu:
      • calloc – przydzielenie pamięci na dynamiczną tablicę,
      • free – zwolnienie pamięci przydzielonej wcześniej na dynamiczną tablicę,
    • cstdlib – operacje systemowe, w tym na terminalu”
      • system – funkcja wykonująca polecenie systemowe.
    • iostream – operacje wejścia/wyjścia, w tym pobieranie danych z klawiatury i wyświetlanie ich na ekranie:
      • cin – operator pobrania danych,
      • cout – operator zwrócenia danych.
    • math.h – operacje matematyczne:
      • pow – potęga liczby o zadanym wykładniku,
      • sqrt – kwadratowy pierwiastek z liczby.
    • stdio.h – operacje wejścia/wyjścia, w tym pobieranie danych z klawiatury i wyświetlanie ich na ekranie:
      • fgets – funkcja pobierająca ciąg znaków do tablicy znaków,
      • printf – funkcja zwrócenia danych,
      • scanf – funkcja pobrania danych.
    • string.h – operacje na łańcuchach znaków:
      • strlen – funkcja zwracająca długość łańcucha.

Funkcja główna -> main

Funkcja main to główna funkcja programu, której ciało definiuje to, co program ma wykonać.

Standardowo funkcja main zwraca liczbę całkowitą (0, jeśli wykonała się poprawnie), więc jej nagłówek zawiera typ int, np.:

int main() { 
std::cout << "Hello World!\n"; 
}

Typy danych

Wybrane typy danych:

  • bool – wartość logiczna: true lub 1 (prawda), false lub 0 (fałsz),
  • char – znak: litera, cyfra itp.,
  • int – liczba całkowita (-2147483648 .. 2147483647),
  • float – liczba rzeczywista (8 cyfrowa),
  • double – liczba rzeczywista (15-cyfrowa),
  • string – łańcuch znaków (wymaga biblioteki string.h).

Zapisywanie danych w kodzie:

  1. liczbie rzeczywistej - część ułamkową oddziela się od całkowitej kropką, np. 2.25,
  2. znak umieszcza się w apostrofach, np 'a',
  3. łańcuch znaków umieszcza się w cudzysłowie, np. "qwerty""a" (łańcuch jednoznakowy), "" (łańcuch pusty).

Zmienną tworzy (deklaruje) się, podając jej typ, nazwę i ewentualnie początkową wartość, np:

bool czy_tak = true; // zmienna czy_tak typu bool zawierająca true 
float liczba; // zmienna liczba typu float 
double liczba_1,liczba_2; // zmienne liczba_1 i liczba_ typu double

Stałą tworzy się, podając słowo const, jej typ, nazwę i wartość, np:

const int stala = 12; // stała stala typu int zawierająca 12

Struktury

Utworzę przykładową strukturę reprezentującą osobę. Dzięki utworzeniu takiej struktury, będzie można przechowywać informacje takie jak imię, nazwisko i wiek w jednym pojemniku.

struct osoba { 
string imie; 
string nazwisko; 
int wiek; 
};

Wczytywanie danych do struktury:

#include <iostream> 
#include <string.h> 

using namespace std; // deklaracja struktury 

struct osoba { 
string imie; 
string nazwisko; 
int wiek; 
}; 

int main() { 

osoba Pawel; // tworzenie obiektu struktury o nazwie Pawel 
Pawel.imie = "Pawel"; 
Pawel.nazwisko = "Janas"; 
Pawel.wiek = 55; 
cout << "Twoje imie to: " << Pawel.imie << endl; 

return 0; 

}

Tablica struktur:

#include <iostream> 
#include <string.h> 
#include <cstdlib> 

using namespace std; 
// deklaracja struktury 
struct osoba { 
string imie; 
string nazwisko; 
int wiek; 
}; 

int main() { 
osoba student[3]; // tablica ze struktury 
for (int i = 0; i<3; i++) { // pobieramy dane 
cout << "Podaj imie studenta numer " << i+1 << endl; 
cin >> student[i].imie; 
} 
for (int i = 0; i<3; i++) { // wyświetlamy tablicę 
cout << student[i].imie << endl; 
} 
system("pause >nul"); 
return 0; 
}

Instrukcja warunku „if”

Instrukcja warunku if służy do wyboru operacji do wykonania, zależnie od prawdziwości podanego warunku. Warunek podaje się w nawiasach; musi mieć wartość logiczną, np.:

if( wyrazenieLogiczne == true )... //powyższy zapis jest równoważny poniższemu: 
if( wyrazenieLogiczne )...
//lub 
if( wiek > 100 || wiek < 2 )...

Przykład użycie bloku instrukcji:

#include <iostream> 

int main() { 
 int wiek; 
 std::cin >> wiek; 
if( wiek >= 18 ) { 

   std::cout << "Czy jesteś osobą pełnoletnią?." << std::endl; 
   std::cout << "Tak, możesz głosować :)" << std::endl; 
 } 
   std::cout << "Koniec" << std::endl; 
 return 0; 
}

Zagnieżdżanie warunków przykład:

#include <iostream>
int main()
{
    int liczba;
    std::cin >> liczba;
    if( liczba >= 10 )
    {
        std::cout << "Liczba jest >= 10" << std::endl;
        if( liczba >= 50 )
        {
            std::cout << "Liczba jest >= 50" << std::endl;
            if( liczba <= 100 )
                 std::cout << "Liczba jest <= 100" << std::endl;
           
        }
    }
    std::cout << "Koniec" << std::endl;
    return 0;
}

Słowo kluczowe else:

Słowo kluczowe else oznacza "w przeciwnym wypadku", czyli jeśli warunek nie zostanie spełniony, wykonaj inny kod.

#include <iostream>
int main()
{
    int wiek;
    std::cin >> wiek;
    if( wiek >= 18 )
         std::cout << "Jestes pelnoletni." << std::endl;
    else
         std::cout << "Nie jestes pelnoletni." << std::endl;
   
    std::cout << "Koniec" << std::endl;
    return 0;
}

Instrukcja wyboru „switch”

Instrukcja warunku switch służy do wyboru operacji do wykonania, zależnie od wartości podanej zmiennej kontrolnej. Dla każdej wartości definiuje się osobny przypadek wyrażeniem case, np.:

switch( zmienna )
{
case wartosc_1:
    //jakiś kod
    break;
   
case wartosc_2:
    //jakiś kod
    break;
   
    //...
case wartosc_n:
    //jakiś kod
    break;
   
default:
    //jakiś kod
    break;
}

Polecenie break kończy/przerywa wykonywanie wyrażenia switch.

Wyrażenie default jest opcjonalne; odpowiada wszystkim innym przypadkom, niż te zdefiniowane wyrażeniami case.

Pętle: for, while, do..while

Pętla for:

Instrukcja pętli for służy do wielokrotnego wykonania jej kodu, zwykle zależnie od wartości zmiennej sterującej pętlą i/lub spełnienia danego warunku.

Budowa pętli for jak łatwo można zauważyć jest podzielona na cztery części:

  • nadawanie początkowych wartości zmiennym (instrukcja_1);
  • warunek kończący pętlę for (instrukcja_2);
  • zwiększenie (zmniejszenie) licznika pętli (instrukcja_3).
for( instrukcja_1; instrukcja_2; instrukcja_3 ) {
 //blok instrukcji 
}

Przykład:

for( int i = 1; i <= 10; i++ ) { 
//Powtarzany blok instrukcji 
}

Pętla while:

Instrukcja pętli while służy do wielokrotnego wykonania jej kodu, zależnie od spełnienia podanego warunku. Wykonanie pętli następuje po sprawdzeniu, że warunek jest prawdziwy; w przeciwnym razie pętla się kończy. Czyli  pętla wykonywana jest dopóki warunek jest prawdziwy.:

while (warunekKoncowy){ 
lista_instrukcji 
}

Przykład:

#include <iostream>

using namespace std;

int main()
{  
  int ile=3;

  while (ile<10)
  {
     cout <<"Pierwsza instrukcja"<<endl;  
     cout <<"Druga instrukcja"<<endl;
     ++ile;
  }

  cout <<endl<<"Nacisnij ENTER aby zakonczyc"<<endl;
  getchar();
  return 0;  
}

Pętla do .. while:

Instrukcja pętli do .. while służy do wielokrotnego wykonania jej kodu, zależnie od spełnienia podanego warunku. Drugie i każde kolejne wykonanie pętli następuje po sprawdzeniu, że warunek jest prawdziwy; w przeciwnym razie pętla się kończy. Czyli pętla taka wykona się zawsze przynajmniej raz.

do { 
lista_instrukcji 
} while (warunekKoncowy);

Przykład:

#include <iostream>
int main()
{
    int liczba;
    do
    {
        std::cout << "Podaj liczbe 123 aby zakonczyc petle" << std::endl;
        std::cin >> liczba;
        std::cout << "Podales liczbe " << liczba << std::endl;
    } while( liczba != 123 );
   
    std::cout << "Koniec" << std::endl;
    return 0;
}

Tablica statyczna

Tablica jest uporządkowaną strukturą danych tego samego typu.

Statyczna tablica ma stały rozmiar i tworzona jest podobnie do zmiennej – lokalnie lub globalnie; z zawartością lub bez. Rozmiar tablicy (liczbę jej komórek) podaje się w nawiasach [], np.: 

Przykład tworzenia tablicy jednowymiarowej:

char znaki[4]; // utworzenie tablice znaki jako tablicę 4 znaków 
char znaki[4] = {'x','y','z','r'}; // utworzenie tablice znaki i wypełnij elementami 
char c[] = {'x','y','z'}; // bez podania rozmiaru tablicy int tablica[4] 

// utworzenie tablicy int 
int tablica[4] = {1,2,3,4}; 
int tablica[] = {1,2,3,4}; 

Przykład tworzenia tablicy dwuwymiarowej:

int tab[3][4]; // utworzenie tablicy 3×4 liczb całkowitych 
int tab[3][4] = { // utworzenie takie samej tablicy z liczbami 
{1,2,3,4}, // wiersz 1 
{5,6,7,8}, // wiersz 2 
{9,10,11,12}}; // wiersz 3

Zapis i odczyt z tablicy:

//zapis do tablicy int tablica[7]; 
int tab[10] 
tablica[3] = 5; // wstawienie liczby 5 do komórki nr 3 
// wstawienie do każdej komórki jej numeru: 
for (int i = 0; i < 10; i++) // zmienna kontrolna zaczyna się od 0 
{ 
tab[i] = i; //dla każdego elementu tablicy 
} //odczyt z tablicy 
int element = tab[4]; // skopiowanie tab[4] do zmiennej element 
// wyświetlenie każdej komórki: 
for(i=0; i<7; i++) // zmienna kontrolna zaczyna się od 0 
{ 
cout << a[i]; 
} 

Wskaźnik

Wskaźnik (ang. pointer) – typ zmiennej odpowiedzialnej za przechowywanie adresu do innej zmiennej (innego miejsca w pamięci) w obrębie naszej aplikacji.

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Podstawowe operatory niezbędne do operowania wskaźnikami:

– operator wyłuskania wartości zmiennej, na którą wskazuje wskaźnik (wyciąga wartość ze wskaźnika)
& – operator pobrania adresu danej zmiennej, tablicy, struktury itp (pobiera adres zmiennej)

Przykład:

int telefon = 12345; //zmienna liczbowa 
int *wsk = &telefon; //przypisanie wskaźnikowi adresu zmiennej telefon 
cout << *wsk << endl; //wyświetlenie wyłuskanej wartości wskaźnika (12345) 
cout << wsk << endl; //wyświetlenie adresu zmiennej telefon 
cout << &wsk << endl; //wyświetlenie adresu wskaźnika 
cout << &telefon << endl; //wyświetlenie adresu zmiennej telefon 

Wskaźnik jako argumentem funkcji:

#include <iostream>

using namespace std;

// funkcja przyjmuje jako argument wskaźnik
void zwieksz_liczbe (int *liczba)
{
    *liczba+= 5;
}

int main()
{
    int numerek = 5;
    int *wsk = &numerek;

    zwieksz_liczbe(wsk); //przekazujemy wskaźnik (bez operatorów)

    cout << numerek << endl;

    zwieksz_liczbe(&numerek); //przekazujemy bezpośrednio adres zmiennej (operator &)

    cout << numerek << endl;

    return 0;
}

Funkcje

Budowa funkcji:

typ_zwracanej_wartosci nazwa( typ_1 nazwa_1 ,typ_2 nazwa_2, ..., typ_n _n ) { 
return zwracana_wartosc; 
}

Funkcja bezargumentowa nie otrzymuje żadnych danych wejściowych jako argumentów, czyli nawiasy () umieszczone po jej nazwie są puste. Przykład:

// definicja funkcji zwroc_liczbe: 
int zwroc_liczbe() { 
int a = 5; 
return a; // ta funkcja zwraca liczbę 5 
} // wykonanie funkcji zwroc_liczbe w funkcji main: 
int main() { 
cout << zwroc_liczbe(); // wyświetlenie liczby 5 
return 0; 
}

Funkcja z argumentami przekazywanymi przez wartość otrzymuje wartości (liczby, znaki itp.) jako dane wejściowe, które wpisuje do zmiennych podanych w nawiasach () w nagłówku definicji funkcji jako argumenty; te zmienne są lokalnymi zmiennymi tej funkcji. Przykłąd:

// definicja funkcji suma int 
suma(int a, int b) { 
return a + b; // funkcja zwraca sumę argumentów a i b 
} // wykonanie funkcji suma w funkcji main: 
// przekazanie przez zmienne 
int main() { 
int c = 2; 
int d = 3; 
cout << suma(d, c); // wyświetlenie sumy liczb 2 i 3 
return 0; 
} 
//lub 
int main() { 
cout << suma(2, 3); // wyświetlenie sumy liczb 2 i 3 
return 0; 
}

 

Tablica dynamiczna jedno i dwuwymiarowa

Operatory new i delete:

int * tablica = new int[3]; //wskaźnik tego samego typu co elementy tablicy 
tablica[0] = 11; 
tablica[1] = 12; 
tablica[2] = 13; 
delete [] tablica; // zawsze usuwamy 

Generowanie tablicy dwuwymiarowej dynamicznej odbywa podobnie jak jednowymiarowej. Zamiast tworzyć wskaźnik do jednego wymiaru, tworzymy tablicę wskaźników wskazujących na wymiary. W uproszczeniu tworzymy tablicę z tablic. Przykład

int ** tablica = new int * [3]; 
tablica[0] = new int [3]; // wskaźnik tablica[0] wskazuje na nową tablicę 
tablica[1] = new int [3]; // wskaźnik tablica[1] wskazuje na nową tablicę 
tablica[2] = new int [3]; // wskaźnik tablica[2] wskazuje na nową tablicę 
tablica[2][2] = 123; 
cout << tablica[2][2]; // zwalniamy pamiec 
delete [] tablica[0]; 
delete [] tablica[1]; 
delete [] tablica[2]; 
delete [] tablica;