Zaczynamy!

Oto pierwszy etap kursu OKI - programowanie specyficznie pod Olimpiadę. Nauczymy się tu konceptów takich jak zmienne, wymiana danych z użytkownikiem, struktury danych, funkcje i więcej - rzeczy potrzebne w każdym języku i w każdym typie programowania. Na tym jednak się zatrzymamy i później przejdziemy do algorytmiki. Nie będziemy zagłębiać się w interfejs użytkownika i inne zagadnienia praktyczne, ponieważ OIJ/OI skupia się na tzw. teoretycznej informatyce.


Dołącz do konkursu i wysyłaj zadania: https://szkopul.edu.pl/c/oki-programowanie-od-podstaw
Pierwszy program w C++. Wypisujemy tekst i rysujemy znakami specjalnymi w konsoli.
To najpewniej Twoja pierwsza lekcja z tym kursem, więc rekomendujemy taką kolejność:
1) Obejrzeć nagranie - możesz przyspieszyć, pomijać i zakończyć kiedy uważasz to za stosowne;
2) Rozwinąć i przejrzeć kategorię "Materiały" poniżej;
3) Zrobić kilka zadań - przeczytać treść, zastanowić się, spróbować napisać i wysłać. Jak nie idzie - zajrzeć do rozwiązania.
4) Jeśli nadal mało - skorzystać z źródeł zewnętrznych:
Artykuł z Kursu OI new tab Szczegółowy poradnik z kanału Pasja Informatyki new tab
Na początku, zamiast instalować środowisko programistyczne i kompilator na swoim komputerze, możesz skożystać z któregoś z tych darmowych kompilatów C++ online:

W późniejszym etapie jednak warto zainteresować się lokalnym środowiskiem. Tylko takie jest dostępne na olimpiadzie i nie tylko tam. Najpopularniejszy wybór to VS Code z rozszerzeniem do C++. Ja polecam też Zed lub Sublime Text z kompilatorem g++.

    // Tutaj załączamy podstawową bibliotekę C++ do wypisywania tekstu na ekran.
// W zadanich możesz używać też biblioteki <bits/stdc++.h> z wszystkimi funkcjami.
#include <iostream>

// Ustawiamy std jako domyślną przestrzeń nazw. Dzięki temu nie musimy za każdym razem powtarzać std:: za każdym razem,
// np dla std::cout << "blablabla" lub std::string a = "blabla".
using namespace std;

// Tu deklarujemy, co dzieje się w funkcji main(), czyli głównej części naszego programu.
int main(){

    // Rysujemy obrazek z zadania znakami ASCII
    cout << " .-." << endl;
    cout << "(o o)" << endl;
    cout << " '-'" << endl;

    // Wychodzimy z programu bez błędu (domyślnie kod 0 = brak błędu; inne = coś poszło nie tak!)
    return 0;
}

  
Wskazówka
#include <bits/stdc++.h> dołącza całą bibliotekę standardową naraz. Na zawodach to standard, bo nie trzeba pamiętać, skąd jaka funkcja pochodzi.
Zadania na rozgrzewkę. Pozwolą zapoznać Ci się konceptem i przygotują cię do kolejnych zadań.

Dodatkowe: Auto

Wyślij
Programowanie 1
Zmienna to nazwane pudełko na wartość. Deklarujemy ją, podając typ i nazwę, a wypełniamy m.in. przez cin - czyli wczytanie wartości z konsoli. Zadania zawsze zaczynają się od wczytania danych.
Omówienie i przykłady na algorytm.edu.pl new tab Inny poradnik z strefakodera.pl new tab
Przykłady - wczytaj i wypisz:
    int a, b; // deklarujemy dwie zmienne (int - od integer, czyli liczba całkowita)
cin >> a >> b; // dwie liczby, oddzielone spacją lub enterem
cout << "Suma: " << a + b << "\n";
cout << "Iloczyn: " << a * b;
  
Uwaga!
Na Szkopule dane wejściowe są w pliku, nie na klawiaturze. Nie wypisuj więc zachęt typu "Podaj liczbę:", bo popsują wynik.

Inny przykład, zamiana zmiennych miejscami (bez użycia funkcji):

    int a = 3, b = 7;
int c = a;
a = b;
b = c;
cout << a << " " << b; // 7 3

  
Zamiast tworzyć nową zmienną możesz użyć wbudowanej funkcji swap(a, b);. Więcej o wbudowanych funkcjach później.
Zadania na rozgrzewkę. Pozwolą zapoznać Ci się konceptem i przygotują cię do kolejnych zadań.
Zadaj pytanie
Programowanie 1
Zadaj pytanie
Programowanie 1
Zadaj pytanie
Zadania wymagające, czasami wręcz ostentacyjnie nietrywialnej, ilości pomyślunku, której skala pozostaje niewspółmierna do liczby linijek kodu prowadzących do rozwiązania.
Zadania z materiału do tego tematu włącznie. Niekoniecznie muszą zawierać materiały z tego tematu, ale zalecamy zrobienie wszystkich dla powtórzenia i treningu!
Instrukcja warunkowa wykonuje kod tylko wtedy, gdy warunek jest prawdziwy. Wiem, 🤯 prawda? ify są jednym z najczęściej używanych struktur, więc polecam sobie poeksperymentować i sprawdzić przykłady poniżej!
Scope'y, zakres kodu wewnątrz IF new tab
Porównania ==, !=, <, >, <=, >= dają prawdę lub fałsz, a łączymy je przez && (i), || (lub), ! (nie). Na przykład:
    int a = 5, b = 10;
cout << (a == b); // false
cout << (a != b); // true
cout << (a < b); // true
cout << (a > b); // false
cout << (2 * a <= b); // true
cout << !(a >= b + a); // true
cout << !(a == b) && (a == a); // true
cout << (a == b) || (a == a); // true

// Uwaga - jeśli faktycznie spróbujesz uruchomić ten kod, to na ekranie pojawią się zera i jedynki reprezentujące true i false.
// Możesz to zmienić przez 'wypisywanie' cout << boolalpha; przed tekstem
  
true / false to wartości zmiennej typu bool. Np.:
    int a = 1, b = 1;
bool czy_dodawanie_dziala = (a + b == 2);
cout << czy_dodawanie_dziala; // true
czy_dodawanie_dziala = !czy_dodawanie_dziala; // false, bo odwracamy wartość
  
Wykorzystując narzędzia z poprzedniego boxa:
    #include <bits/stdc++.h>
using namespace std;

int main() {
  int x;
  cin >> x;

  cout << x << " jest ";
  if (x >= 1 && x <= 100) cout << "w zakresie\n";
  if (x < 0 || x > 100) cout << "poza zakresem\n";
  if (!(x % 2 == 0)) cout << "nieparzysta\n";

  // lub
  bool decyzja1 = true, decyzja 2 = false;
  if (decyzja1 && decyzja2) cout << "tak"; // nie wyświetli się
  if (decyzja1 || decyzja2) cout << "tak"; // wyświetli się
}
  
    if((rok % 4 == 0 && rok % 100 != 0) || rok % 400 == 0)
  cout << "przestepny";
  
Wskazówka
w if (a && b) jeśli a jest fałszem, b nie jest sprawdzane. Dzięki temu if (i < n && a[i] == x) nigdy nie wyjdzie poza tablicę.
Zadania na rozgrzewkę. Pozwolą zapoznać Ci się konceptem i przygotują cię do kolejnych zadań.
Zadaj pytanie
Programowanie 1
Zadaj pytanie
Zadania wymagające, czasami wręcz ostentacyjnie nietrywialnej, ilości pomyślunku, której skala pozostaje niewspółmierna do liczby linijek kodu prowadzących do rozwiązania.
Zadaj pytanie
Pętla for ma trzy części: start, warunek trwania i krok. Używamy jej, gdy z góry wiadomo, ile iteracji (powtórzeń) wykonamy.
    for (int i = 0; i < n; i++) cout << i << " "; // 0 .. n-1
for (int i = 1; i <= n; i++) cout << i << " "; // 1 .. n
for (int i = n; i >= 1; i--) cout << i << " "; // od tyłu
for (int i = 0; i < n; i += 2) cout << i << " "; // co drugi
  
Zadania na rozgrzewkę. Pozwolą zapoznać Ci się konceptem i przygotują cię do kolejnych zadań.
Programowanie 1
Programowanie 1
Zadaj pytanie
Zadania wymagające, czasami wręcz ostentacyjnie nietrywialnej, ilości pomyślunku, której skala pozostaje niewspółmierna do liczby linijek kodu prowadzących do rozwiązania.
Zadania z materiału do tego tematu włącznie. Niekoniecznie muszą zawierać materiały z tego tematu, ale zalecamy zrobienie wszystkich dla powtórzenia i treningu!
Zadaj pytanie
Różne typy danych w C++ służą do przechowywania informacji o różnym charakterze. Każdy typ określa, jaki rodzaj wartości może być zapisany w zmiennej oraz ile pamięci zostanie na nią przeznaczone. Poznaliśmy już int (liczby całkowite) i string (ciągi znaków). Poniżej znajduje się tabelka z innymi ważnymi typami. Nie musisz jej zapamiętywać od razu. Wróć tutaj, jeśli będziesz potrzebował jakiegoś typu, np. dla liczb większych niż $2 \cdot 10^9$ lub liczb niecałkowitych.
typ opis rozmiar w pamięci
bool Wartość logiczna - true albo false 1 B
char Pojedynczy znak ASCII 1 B
short Krótka liczba całkowita w zakresie [-32'768, 32'767] 2 B
int Liczba całkowita w zakresie [-2'147'483'648, 2'147'483'647] 4 B
long Długa liczba całkowita (najczęściej taki sam zakres jak int na Windows) 4 lub 8 B
long long Bardzo duża liczba całkowita w zakresie około $\pm$9×1018 8 B
float Liczba zmiennoprzecinkowa pojedynczej precyzji (~7 cyfr znaczących) 4 B
double Liczba zmiennoprzecinkowa podwójnej precyzji (~15 cyfr znaczących) 8 B
long double Liczba zmiennoprzecinkowa rozszerzonej precyzji (~18–21 cyfr znaczących, zależy od architektury) 8–16 B
std::string Łańcuch znaków o dowolnej długości długość tekstu

Tip: możesz sprawdzić rozmiar typu w bajtach przy użyciu sizeof:
    cout << "rozmiar inta: " << sizeof(int);
  
while działa cały czas, dopóki warunek jest prawdziwy. Używamy jej, gdy nie wiadomo z góry, ile obiegów będziemy potrzebować. Wariant do while wykonuje kod co najmniej raz.
    // ile cyfr ma liczba?
int x, ile = 0;
cin >> x;
while (x > 0) {
  x /= 10;
  ile++;
}

cout << x << " ma " << ile << " cyfr." 
  
    // jeśli w zadaniu mamy t przypadków testowych
int t; cin >> t;
while (t--) {
    int a, b; cin >> a >> b;
    cout << a + b << "\n";
} 
  

Uwaga!
Nieskończona pętla może być przyczyną przekroczenia limitu czasu. Upewnij się, że coś w środku faktycznie zmienia warunek.

Możesz szybciej zakończyć pętle - break przerywa całą pętlę, continue przeskakuje do następnego obiegu. Działa też w forze!
Zadania na rozgrzewkę. Pozwolą zapoznać Ci się konceptem i przygotują cię do kolejnych zadań.
poziom olimpiad międzynarodowych
vector to tablica, która trzyma wiele wartości (mających coś ze sobą wspólnego) pod jedną nazwą. Do każdej sięgamy po indeksie, licząc od zera: $a[0], a[1],$ ... Rozmiar podajemy w trakcie działania programu, więc najpierw wczytujemy $n$, a potem tworzymy vector na $n$ liczb (lub .resizeujemy.
Dostęp do elementu i dopisanie na koniec (push_back) działają w $\mathcal{O}(1)$. Najczęstszy błąd to wyjście poza zakres - odwołanie do $a[n]$. Indeksy kończą się na $n-1$!
    #include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n; // ile liczb bedziemy wczytywac

    vector<int> a(n); // n zer, indeksy 0 .. n-1
    for(int i = 0; i < n; i++)
        cin >> a[i];

    long long suma = 0; // suma może nie zmieścić się w int!
    for(int i = 0; i < n; i++)
        suma += a[i];

    cout << suma << "\n";
    for(int i = n - 1; i >= 0; i--) // wypisujemy od końca
        cout << a[i] << " ";
    return 0;
}
  
Zadania na rozgrzewkę. Pozwolą zapoznać Ci się konceptem i przygotują cię do kolejnych zadań.
Programowanie 2
Zadaj pytanie