Języki Programowania – Zajęcia 1

Wprowadzenie do C++: VS Code, kompilator, pierwszy program

Cel zajęć

Na poprzednich zajęciach programowaliście w Pythonie w środowisku Google Colab. Teraz zaczynamy pracę z C++. Najważniejszą zmianą nie jest sama składnia języka, ale sposób pracy: będziemy tworzyć pliki źródłowe, kompilować je przy użyciu kompilatora i uruchamiać otrzymane programy.

1. C++ a Python – co się zmienia?

W Pythonie większość technicznych szczegółów związanych z uruchamianiem programu była przed Wami ukryta. W Colabie wpisywaliście kod do komórki i naciskaliście przycisk uruchomienia. Środowisko zajmowało się resztą.

W C++ zobaczymy wyraźnie kolejne etapy:

kod źródłowy (.cpp)
        |
        v
    kompilator
        |
        v
program wykonywalny
        |
        v
    uruchomienie

Kod C++ zapisujemy w pliku, najczęściej z rozszerzeniem .cpp. Kompilator tłumaczy kod źródłowy na postać wykonywalną przez komputer. W naszych zajęciach będziemy korzystać z kompilatora g++.

W praktyce oznacza to, że po zmianie kodu źródłowego trzeba ponownie wykonać kompilację, jeżeli chcemy, aby zmiana znalazła się w uruchamianym programie.

Ważne: plik .cpp i program wykonywalny to dwa różne obiekty. Plik .cpp zawiera kod, który napisaliście. Plik wykonywalny jest wynikiem kompilacji tego kodu.

2. VS Code – nasze środowisko pracy

Do pisania programów będziemy używać Visual Studio Code (VS Code). Jest to edytor kodu z funkcjami środowiska programistycznego (IDE): pozwala między innymi otwierać pliki projektu, edytować kod, korzystać z terminala i uruchamiać narzędzia programistyczne.

Po lewej stronie okna VS Code, pod niebieską ikoną programu, znajduje się pionowy pasek z podstawowymi ikonami nawigacyjnymi. Na początku szczególnie interesują nas trzy z nich:

Podstawowe ikonki nawigacyjne VS Code
Rys. 1. Podstawowe ikonki nawigacyjne VS Code.

2.1. Instalacja rozszerzenia C/C++

Sam VS Code nie zawiera pełnego wsparcia dla języka C++. Potrzebujemy więc dodatku (extension), który ułatwia pracę z tym językiem.

Najpierw sprawdźcie, czy rozszerzenie jest już zainstalowane. Na komputerach laboratoryjnych może być ono zainstalowane, ale może też być konieczne wykonanie poniższych kroków.

  1. Kliknijcie ikonę Extensions na pasku po lewej stronie.
  2. W polu wyszukiwania wpiszcie C/C++.
  3. Znajdźcie rozszerzenie C/C++ firmy Microsoft.
  4. Jeżeli rozszerzenie nie jest zainstalowane, kliknijcie Install.
  5. Jeżeli zamiast przycisku Install widzicie informację Installed, rozszerzenie jest już dostępne i nie trzeba go instalować ponownie.
Rozszerzenie C/C++ firmy Microsoft w VS Code
Rys. 2. Rozszerzenie C/C++ firmy Microsoft.
Uwaga: instalujemy rozszerzenie C/C++ firmy Microsoft. Nie jest ono tym samym co kompilator g++. Rozszerzenie zapewnia wsparcie dla C++ w edytorze VS Code, natomiast g++ jest programem, który faktycznie kompiluje nasz kod.

2.2. Katalog projektu

Na każde zajęcia warto utworzyć osobny katalog. Przykładowo możemy utworzyć katalog cpp/lab_1.

Aby tak pracować, najlepiej wejść w terminal:
cd ~      # wchodzimy do katalogu domowego (jeśli już w nim nie jesteśmy)
mkdir cpp #tworzymy globalny katalog na nasze zajęcia/projekty
cd cpp    #wchodzimy tam
mkdir lab_1 #tworzymy katalog na nasz pierwszy projekt
cd lab_1  #wchodzimy do niego
code .    #odpalamy code

2.3. Terminal i sprawdzenie kompilatora

Do kompilowania programów nie będziemy na razie używać przycisku Run. Chcemy najpierw zobaczyć, jak wygląda proces kompilacji i uruchamiania programu, dlatego będziemy korzystać bezpośrednio z terminala.

Otwórzcie terminal w VS Code, wybierając Terminal → New Terminal.

Najpierw sprawdźmy, czy kompilator g++ jest dostępny. W terminalu wpiszcie:

g++ --version

Jeżeli kompilator jest zainstalowany, terminal wyświetli informację o jego wersji.

Jeżeli polecenie g++ --version nie działa, zgłoście to prowadzącemu. Nie instalujcie samodzielnie kompilatora na komputerze laboratoryjnym bez uzgodnienia z prowadzącym — sposób instalacji zależy od systemu operacyjnego i konfiguracji pracowni.

Rozszerzenie C/C++ i kompilator g++ to dwie różne rzeczy.
Rozszerzenie daje VS Code wsparcie w pisaniu kodu C++, natomiast g++ tłumaczy kod źródłowy na program wykonywalny. Do napisania i skompilowania programu potrzebujemy obu elementów.

Uwaga: podkreślenie fragmentu kodu przez VS Code nie zawsze oznacza błąd samego programu. Edytor musi również wiedzieć, którego kompilatora i których plików nagłówkowych używamy. Ostatecznym testem poprawności programu jest kompilacja.

3. Pierwszy plik C++

W Explorerze utwórzcie nowy plik o nazwie:

main.cpp

Do pliku wpiszcie:

#include <iostream>

using namespace std;

int main()
{
    cout << "Hello World" << endl;

    return 0;
}

Na razie nie próbujcie zapamiętać wszystkich elementów tego programu. Najpierw zobaczymy, jak go skompilować i uruchomić.

4. Kompilacja programu

Otwórzcie terminal w VS Code: Terminal → New Terminal.

Jeżeli terminal znajduje się w katalogu zawierającym main.cpp, wykonajcie:

g++ main.cpp -o main

Polecenie składa się z kilku części:

Jeżeli kompilacja zakończyła się poprawnie, w terminalu zwykle nie zobaczymy żadnego komunikatu o sukcesie. Pojawi się natomiast plik wykonywalny main (na systemach Linux/macOS; na Windowsie może pojawić się main.exe).

4.1. Uruchomienie programu

Na Linuxie lub macOS wykonujemy:

./main

Powinniście zobaczyć:

Hello World

Na Windowsie, zależnie od konfiguracji środowiska, program może być uruchamiany jako:

.\main.exe
Zapamiętajcie:
g++ main.cpp -o main
kompiluje program, natomiast
./main
uruchamia program wynikowy.

5. Eksperyment: co się stanie, jeśli nie skompilujemy ponownie?

Zmieńcie w main.cpp tekst:

cout << "Hello World" << endl;

na przykład na:

cout << "Witaj w C++!" << endl;

Teraz nie wykonujcie kompilacji. Od razu uruchomcie:

./main

Jeżeli wcześniej program został poprawnie skompilowany, zobaczycie starą wersję komunikatu. Dopiero po wykonaniu:

g++ main.cpp -o main

i ponownym:

./main

zobaczycie nowy tekst.

To proste doświadczenie jest bardzo ważne: zmiana pliku źródłowego nie zmienia automatycznie programu wykonywalnego.

6. Co właściwie znajduje się w programie?

Przyjrzyjmy się jeszcze raz:

#include <iostream>

using namespace std;

int main()
{
    cout << "Hello World" << endl;

    return 0;
}

#include <iostream>

Dołączamy bibliotekę nagłówkową iostream. Jest ona potrzebna między innymi do obsługi standardowego wejścia i wyjścia, czyli mechanizmów, z których korzystamy poprzez cin i cout.

Można to na tym etapie traktować jako coś podobnego do importowania funkcjonalności w Pythonie.

using namespace std;

Informujemy kompilator, że będziemy korzystać z elementów standardowej przestrzeni nazw (std) bez konieczności ciągłego wpisywania przedrostka std::. Dzięki tej linijce możemy pisać po prostu cout, cin, endl czy string zamiast std::cout, std::cin, std::endl i std::string.

int main()

main to funkcja, od której rozpoczyna się wykonywanie programu C++. Każdy samodzielny program C++ musi mieć funkcję main.

int oznacza typ wartości zwracanej przez funkcję. W przypadku main wartość 0 oznacza poprawne zakończenie programu.

Klamry { }

Klamry wyznaczają blok programu. W Pythonie znaczenie bloków określały wcięcia. W C++ wcięcia są bardzo ważne dla czytelności kodu, ale o strukturze bloku decydują przede wszystkim klamry.

cout

cout służy do wypisywania danych na standardowe wyjście, zwykle na ekran.

Można na tym etapie myśleć o nim jako o odpowiedniku Pythonowego print().

<<

Operator << pozwala przekazywać dane do strumienia wyjściowego, np. na ekran. Na tym etapie wystarczy zapamiętać jego podstawowe zastosowanie.

endl

endl kończy linię. W dalszej części kursu będziemy również korzystać z zapisu '\n'.

return 0;

Kończymy funkcję main, zwracając wartość 0. Współczesny C++ pozwala pominąć return 0; na końcu main, ale na tym etapie będziemy go jawnie zapisywać, ponieważ dobrze pokazuje ideę wartości zwracanej przez funkcję.

Nie wszystkie szczegóły składni C++ muszą być jasne po pierwszym kontakcie. Na tym etapie najważniejsze jest rozumienie ogólnego schematu programu i umiejętność jego skompilowania i uruchomienia.

7. Zmienne – pierwsza duża różnica względem Pythona

W Pythonie można było napisać:

x = 3
x = "trzy"

W C++ przed użyciem zmiennej określamy jej typ:

int x = 3;

Zmiennej x typu int nie możemy później przypisać napisu:

int x = 3;
x = "trzy";       // błąd

Jeżeli chcemy przechowywać tekst, potrzebujemy zmiennej odpowiedniego typu, na przykład:

#include <string>

string text = "trzy";

Jest to jedna z podstawowych różnic pomiędzy Pythonem a C++: typ zmiennej jest w C++ jawnie określony.

Python C++
x = 10 int x = 10;
x = 3.14 double x = 3.14;
x = "tekst" string x = "tekst";
True / False true / false

8. Podstawowe typy danych

Na początek wystarczy znać kilka podstawowych typów:

Typ Przykład Zastosowanie
int int n = 10; liczby całkowite
double double x = 3.14; liczby zmiennoprzecinkowe
char char c = 'A'; pojedynczy znak
bool bool ok = true; wartość logiczna
string string name = "Ala"; tekst

Zwróćcie uwagę na różnicę między char a std::string:

char letter = 'A';
string word = "Ala";

Pojedynczy znak zapisujemy w apostrofach, a napis w cudzysłowie.

9. Wypisywanie wartości

Za pomocą cout możemy wypisywać nie tylko tekst, ale również wartości zmiennych:

#include <iostream>

using namespace std;

int main()
{
    int age = 20;
    double temperature = 21.5;

    cout << "Wiek: " << age << endl;
    cout << "Temperatura: " << temperature << endl;

    return 0;
}

Możemy również połączyć kilka elementów w jednym poleceniu:

cout << "Wiek: " << age
     << ", temperatura: " << temperature
     << endl;

W Pythonie napisalibyśmy na przykład:

print("Wiek:", age, "temperatura:", temperature)

10. Operacje arytmetyczne

Podstawowe operatory arytmetyczne wyglądają podobnie jak w Pythonie:

Operator Znaczenie
+dodawanie
-odejmowanie
*mnożenie
/dzielenie
%reszta z dzielenia

Przykład:

#include <iostream>

using namespace std;

int main()
{
    int a = 17;
    int b = 5;

    cout << a + b << endl;
    cout << a - b << endl;
    cout << a * b << endl;
    cout << a / b << endl;
    cout << a % b << endl;

    return 0;
}
Uwaga na dzielenie całkowite. Jeżeli obie liczby są typu int, wynik dzielenia jest również całkowity:
int a = 17;
int b = 5;

cout << a / b << endl;      // 3
Jeżeli potrzebujemy wyniku zmiennoprzecinkowego, używamy np. double:
double a = 17;
double b = 5;

cout << a / b << endl;      // 3.4

11. Wczytywanie danych z klawiatury

Do wczytywania danych ze standardowego wejścia służy cin. Najprostszy przykład:

#include <iostream>

using namespace std;

int main()
{
    int x;

    cout << "Podaj liczbe: ";
    cin >> x;

    cout << "Podana liczba to: " << x << endl;

    return 0;
}

Operator >> przekazuje dane z wejścia do zmiennej. Na tym etapie można traktować:

cin >> x;

jako podstawowy odpowiednik Pythonowego:

x = input()

z tą istotną różnicą, że w C++ typ zmiennej jest już określony. Jeżeli x jest typu int, oczekujemy liczby całkowitej.

11.1. Wczytanie dwóch liczb

#include <iostream>

using namespace std;

int main()
{
    double a;
    double b;

    cout << "Podaj pierwsza liczbe: ";
    cin >> a;

    cout << "Podaj druga liczbe: ";
    cin >> b;

    cout << "Suma = " << a + b << endl;

    return 0;
}

Można również wczytać kilka wartości jednym poleceniem:

cin >> a >> b;

Jeżeli użytkownik wpisze wartości rozdzielone spacją, zostaną one przypisane kolejno do zmiennych.

12. Pierwszy kompletny program

Połączmy teraz poznane elementy. Napiszemy program obliczający pole prostokąta.

#include <iostream>

using namespace std;

int main()
{
    double a;
    double b;

    cout << "Podaj dlugosc prostokata: ";
    cin >> a;

    cout << "Podaj szerokosc prostokata: ";
    cin >> b;

    double area = a * b;

    cout << "Pole prostokata = " << area << endl;

    return 0;
}

Zapiszcie program jako prostokat.cpp. Następnie w terminalu wykonajcie:

g++ prostokat.cpp -o prostokat
./prostokat

Program powinien poprosić o dwie liczby i wyświetlić obliczone pole.

13. Ćwiczenie 1 – zmiana programu

Ćwiczenie 1: prostokąt

Zmodyfikujcie program z poprzedniego punktu tak, aby oprócz pola obliczał również obwód prostokąta.

Program powinien:

Wykorzystajcie wzory:

P = a * b
O = 2 * (a + b)

Program zapiszcie w osobnym pliku, np. prostokat2.cpp, a następnie samodzielnie skompilujcie i uruchomcie.

14. Ćwiczenie 2 – przeliczanie temperatury

Ćwiczenie 2: stopnie Celsjusza i Fahrenheita

Napiszcie program, który pobiera od użytkownika temperaturę w stopniach Celsjusza i przelicza ją na stopnie Fahrenheita.

Skorzystajcie ze wzoru:

F = C * 9 / 5 + 32

Program powinien jasno informować użytkownika, co ma wpisać, a wynik powinien być opisany, np.:

Podaj temperature w stopniach Celsjusza: 20
Temperatura w Fahrenheitach: 68
W tym zadaniu użyjcie typu double. Zastanówcie się również, dlaczego użycie typu int może prowadzić do niepożądanego wyniku.

15. Ćwiczenie 3 – średnia trzech liczb

Ćwiczenie 3: średnia

Napiszcie program, który wczyta trzy liczby rzeczywiste i obliczy ich średnią arytmetyczną.

Program powinien:

Przetestujcie program dla kilku zestawów danych, np. 1, 2, 3 oraz 1.5, 2.5, 10.

Zwróćcie uwagę na typ zmiennych oraz na sposób wykonania dzielenia.

16. Co zrobić, gdy kompilator zgłosi błąd?

Na pierwszych zajęciach bardzo często zobaczycie komunikaty błędów. Jest to normalna część programowania. Kompilator nie uruchomi programu, jeżeli kod zawiera błąd uniemożliwiający jego skompilowanie.

Spróbujcie na przykład celowo usunąć średnik:

int x = 10
cout << x << endl;

Następnie spróbujcie skompilować program. Kompilator wypisze komunikat zawierający informację o miejscu, w którym wykrył problem.

Nie należy zakładać, że pierwsza linia wskazana przez kompilator jest zawsze dokładnie miejscem popełnienia błędu. Błąd składniowy może spowodować, że kompilator zgłosi problem dopiero przy kolejnym elemencie kodu.

17. Najważniejsze rzeczy z dzisiejszych zajęć

18. Schemat pracy, który będziemy stosować

1. Utwórz / otwórz katalog projektu
              |
              v
2. Utwórz plik .cpp
              |
              v
3. Napisz / zmodyfikuj kod
              |
              v
4. Skompiluj:
   g++ program.cpp -o program
              |
              v
5. Jeżeli kompilacja się udała:
   uruchom program
              |
              v
6. Sprawdź działanie
              |
              v
7. Wprowadź poprawki i wróć do punktu 4
Na kolejnych zajęciach będziemy rozwijać ten schemat. Dojdą między innymi instrukcje warunkowe, pętle, funkcje oraz kolejne elementy języka C++. Z czasem większość pracy będzie odbywała się już bez potrzeby szczegółowego zastanawiania się nad samą procedurą kompilacji. Na pierwszych zajęciach zależy nam jednak na tym, żebyście dokładnie zobaczyli, co dzieje się pomiędzy napisaniem kodu a jego wykonaniem.