Jazyk C/C++

NSWI170, 2026, 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
    • 5 + 1 Unforgivable curses

Pravidlo #0 - konzistence

  • Kód by měl být co nejčitelnější
    • Jeden jazyk - Angličtina
    • Konzistentní casing - camelCase, PascalCase, snake_case, ...
    • Jednotné formátování
  • Jasné a srozumitelné názvy proměnných a funkcí
    • Bez zbytečných zkratek
    • Pozor na ustálené pojmy (např. getter)

Pravidlo #1 - dekompozice

  • Funkce 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

// Please do NOT do this:
void appendMeasurement(ofstream& file, string sensor, float temperature) {
    if (sensor.empty())
        throw invalid_argument("Sensor cannot be empty");

    while (sensor.find('"') != string::npos)
        sensor.replace(sensor.find('"'), 1, "\"\"");
    if (sensor.find(',') != string::npos)
        sensor = "\"" + sensor + "\"";

    if (!file.good())
        throw runtime_error("Output file is invalid");

    file << sensor << "," << fixed << setprecision(2) << temperature << "\n";
}
    

Pravidlo #1 - dekompozice

  • Č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 - nemají side effecty

Rekapitulace C++

  • C/C++ jsou staticky silně typované jazyky
    • Typy proměnných se určují za překladu

int a = 1;
    
  • Syntax 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 (stejného 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 (dynamicky)

  • 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á počítá klouzavý průměr hodnot pole
    • 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