Jazyk C/C++

NSWI170, 2025, Labs 01

Jáchym Bártík

Úvod

  • Podmínky zápočtu na webu
  • Cílem cvičení je především naučit se obecné zásady programování
    • Detaily jazyka C/C++ budou pouze na přednášce
  • Coding guidelines
    • Five Unforgivable curses

Kletba #1 - dekompozice

  • Umožňují znovupoužití dříve napsaného kódu
  • Dělí kód na menší logické celky, které je snazší pochopit
    • Pojmenovávají kus kódu - self-documentation
    • Umožňují opakovat jména proměnných
  • Oddělují různé úrovně abstrakce
  • Čemu se vyhnout:
    • Kód je po rozdělení výrazně delší, než před tím
    • Je potřeba předávat příliš mnoho argumentů
    • Nemáte představu, jak novou funkci pojmenovat
  • Ideální funkce dělá právě jednu věc (kterou má v názvu)
    • Pure funkce - pracují pouze s argumenty

Rekapitulace

  • C/C++ jsou staticky silně typované jazyky
    • Typy proměnných se určují za překladu
int a = 1;
  • Syntaxe je na první pohled podobná Pythonu, ale v mnoha detailech se liší
if (someExpression)         // Parentheses, no colon
    doSomething();          // Mandatory semicolon
else {                      // Again, no colon
    doSomethingElse();
    doMoreElse();           // Braces are used to create a block
}                           // of code (instead of indentation)

for (int i = 0; i < 10; i++) {      // For-loop is entirely different
    doSomething();
}

Cvičení #1

  • Vypište Hello World!
#include <iostream>

using namespace std;

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

    return 0;
}
  • Kompilace:
g++ helloWorld.cpp -o helloWorld
./helloWorld

Cvičení #2

  • Vytvořte funkci, která dostane číslo a vypíše tolik * na jednom řádku
void printStars(int amount) {
    ...
}

int main() {
    printStars(5);
    
    return 0;
}

/*

*****

*/

Cvičení #3

  • Vytvořte funkci, která dostane číslo a vypíše tak dlouhý trojúhelník z *
void printTriangle(int levels) { ... }

printTriangle(4);

/*

*
**
***
****

*/

Cvičení #4

  • Vytvořte funkci, která dostane číslo a vypíše tak dlouhý strom z *
    • Bonus: Umožněte přeskočit zadaný počet řádků
void printTree(int levels, int skipped = 0) { ... }

printTree(3);

/*

  *
 ***
*****

*/

printTree(3, 1);

/*

 ***
*****

*/

Cvičení #5 (bonus)

  • Vytvořte funkci, která dostane tři parametry:
    • Počet segmentů - kolik segmentů má vypsat
    • Výšku segmentu - kolik řádků má každý segment
    • Ozdoby - po kolika řádcích mají následovat ozdoby
  • Segment s indexem i (číslováno od nuly) začíná řádkem s (2i + 1) znaky *
void printChristmasTree(int segments, int segmentHeight, int ornaments) { ... }

printChristmasTree(5, 3, 4);

/*

      *
     ***
    *****
    @***@
    *****
   *******
    *****
  @*******@
  *********
   *******
  *********
@***********@
  *********
 ***********
*************

*/

Pole

  • Sekvence hodnot (jednoho typu)
    • K hodnotám přistupujeme indexem (od nuly)
  • Statická alokace:
int a[32];                      // Array with 32 elements (from a[0] to a[31])
int b[] = { 1, 2, 3, 4, 5 };    // Array with 5 elements

int c[3][4];                        // Matrix of 3 times 4 elements
int d[][2] = { { 1, 0 }, { 0, 1 } };   // Unit matrix 2 times 2
  • Pole si nepamatuje svoji velikost
    • Musíme ji zjistit a předat zvlášť
int b[] = { 1, 2, 3, 4, 5 };
int bSize = sizeof(b) / sizeof(b[0]);       // bSize = 5

void foo(int array[], int size) {
    int computedSize = sizeof(array) ...    // Does not work!
}

Cvičení #6

  • Vytvořte funkci, která zobrazí graf
    • Hodnoty dostanete v poli
    • Každou hodnotu zobrazíte jako odpovídající počet znaků *
void printChart(int values[], int count) { ... }

int values[] = { 3, 4, 4, 5, 6, 8, 11, 10, 5, 2, 0 };
printChart(values, count);

/*
| ***
| ****
| ****
| *****
| ******
| ********
| ***********
| **********
| *****
| **
| 
*/

Pole

  • Když velikost pole neznáme za překladu, musíme použít dynamickou alokaci
    • Paměť si ale managujeme sami, takže ji musíme co nejdřív vrátit (dealokovat)
  • Pole lze také chápat jako ukazatel na první hodnotu v poli
    • Výsledkem dynamické alokace je právě takový ukazatel
int size = rand() % 100;    // Random size from 0 to 99

int* array = new int[size]; // Dynamic allocation

...                         // Some computations

delete [] array;            // Deallocation

Cvičení #7

  • Vytvořte funkci, která spočítá klouzavý průměr hodnot v poli
    • Velikost okna dostane jako parametr
    • Výsledky vypíše do nového pole, které vrátí
      • To bude mít stejnou délku, jako to původní
    • Nakonec použijte funkci z předchozího cvičení k jejich vykreslení
int* computeMovingAverage(int values[], int count, int windowSize) { ... }

int values[] = { 3, 4, 4, 5, 6, 8, 11, 11, 10, 5, 2, 0 };
computeMovingAverage(values, 12, 3);

/*

initial: [ 3, 4, 4, 5, 6,  8, 11, 11, 10, 5, 2, 0 ]
output:  [ 4, 4, 5, 6, 8, 10, 10,  8,  5, 2, 0, 0 ]

*/

Domácí úkol #1

  • Zobrazte graf (podobně jako v úloze #6) s následujícími úpravami:
    • Hodnoty mohou být záporné
    • Na místě nuly vypíšete znak |
    • Některé hodnoty mohou chybět (tzn. rovnají se konstantě no_value)
      • Místo nich jen zopakujete předchozí hodnotu (na začátku předpokládáte nulu)
    • Vstupní pole temperatures a konstanta no_value  jsou poskytnuty v souboru temps.h
int temperatures[] = { 4, 2, no_value, 0, -1, -3 };

/*

   |****
   |**
   |**
   |
  *|
***|

*/

Závěr

  • Vyřešte úlohu v ReCodExu
    • První deadline je za týden
    • Deadline na opravy je za čtyři týdny
  • Nesplnění druhého deadlinu libovolné úlohy znamená opakování předmětu
    • Výjimky je nutné řešit dostatečně dopředu
  • Sežeňte si Arduino (ideálně ze školní knihovny)
    • Pokud si plánujete nosit vlastní počítač, nainstalujte si Arduino IDE