11. Meer data types

In dit hoofdstuk zullen we nog meer verschillende datatypes in C++ bespreken.

Long long int

Er is een maximum waarde dat je kan opslaan in een int. Als het getal te groot wordt om op slaan in een int dan gebruik je een long long int ipv van een int.

#include <iostream>
using namespace std;
 
int main()
{
  int getal1 = 100000; 
  int getal2 = 100000;
  int uitkomst = getal1 * getal2;
  cout << uitkomst << endl;
  return 0;
}

Opdracht 11.1 Probeer bovenstaande code uit en pas de code aan zodat deze correct werkt.

De grootte van de verschillende data types wordt uitgedrukt in bits. Meer bits betekent dat variabelen van dat type meer verschillende waardes kunnen opslaan. Een long long int is minimaal 64-bits. Een int is minimaal 16-bits maar kan ook 32-bits zijn afhankelijk van je compiler.

Auto

In C++ is het auto-datatype een manier om de compiler automatisch het type van een variabele te laten bepalen op basis van de initializer. Dit betekent dat je het type niet expliciet hoeft te specificeren wanneer je een variabele declareert, zolang er voldoende informatie is om het type af te leiden.

Dit kan handig zijn om complexe datatype te vereenvoudigen:

string zin = "Voorbeeld";

for (auto element : zin) {
    cout << element << endl;
}

Struct

Met een struct kun je meerdere variabelen groeperen. Een groenteboer wil bijvoorbeeld eigenschappen van fruit vastleggen. Zij wil dan vastleggen wat voor soort fruit het is en wat de prijs is en het aantal dat aanwezig is in de winkel. Hiervoor kunnen we een struct gebruiken.

#include <iostream>
#include <string>
using namespace std;

int main() {
  
  struct struct_fruit {
    string soort;
    float prijs;
    int aantal;
  };

  struct_fruit fruit;

  fruit.soort = "Appel";
  fruit.prijs = 1.70;
  fruit.aantal = 10;

  cout << "Soort = " << fruit.soort << endl;
  cout << "Prijs = " << fruit.prijs << endl;
  cout << "Aantal = " << fruit.aantal << endl;
}

In bovenstaande code kan je maar 1 fruitsoort opslaan. Je kan meerdere variabelen van het type struct_fruit aanmaken maar mooier is het om een array te declareren van het type struct_fruit.

struct_fruit fruit[10];

Op deze manier kan je meerdere fruitsoorten opslaan. De eerste fruitsoort wordt dan:

fruit[0].soort = "Appel";
fruit[0].prijs = 1.70;
fruit[0].aantal = 10;

Opdracht 11.2 Maak de opdracht: Programmeerwedstrijd. Gebruik een struct in je oplossing.

Je kan een struct ook gebruiken in een vector zoals bijvoorbeeld:

vector<StructFruit> fruitLijst

Als je de vector wil sorteren op bijvoorbeeld de prijs dan moet je een extra functie toevoegen om aan te geven op welk veld je wil sorteren:

bool vergelijkOpPrijs(const StructFruit &a, const StructFruit &b) {
    return a.prijs < b.prijs; 
}

Daarna kan je de sort functie gebruiken:

sort(fruitLijst.begin(), fruitLijst.end(), vergelijkOpPrijs);

Pair

Een pair houdt precies twee waarden bij elkaar. Je krijgt de eerste waarde met de functie first en de tweede waarde met de functie second. De datatypes van de twee waardes kunnen verschillen.

Voorbeeld:

#include <bits/stdc++.h>
using namespace std;

int main() {
    pair<string, int> persoon = {"Emma", 21};
    cout << "Naam: " << persoon.first << endl;
    cout << "Leeftijd: " << persoon.second << " jaar" << endl;
    return 0;
}

Voorbeeld met een vector en een pair:

vector<std::pair<std::string, int>> personen = {
    {"Emma", 21},
    {"Liam", 12},
    {"Olivia", 14}
};

for (auto [naam, leeftijd] : personen) {
    cout << "Naam: " << naam << ", Leeftijd: " << leeftijd << '\n';
}

Opdracht 11.3 Maak de opdracht: Film. Gebruik een pair in je oplossing.

int main() {  
  // PAIR -----------------------------------------------------------
    pair<int, int> p1 = {7, 5};
    pair<int, int> p2 = {4, 8};

    /*
        Nuttige functies voor een PAIR
        1) .first & .second
        2) auto-unpacking
        3) sort
    */

    cout << p1.first << " " << p1.second << '\n'; // output: 7 5

    auto [a, b] = p2; // je kan een pair opsplitsen in twee variablen met auto en []
    cout << a << '\n'; // output: 4
    cout << b << '\n'; // output: 8

    vector<pair<int, int>> v2 = {{4, 8}, {2, 7}, {4, 5}}; 

    // pair is gesorteerd op het EERSTE element en bij gelijke waardes ook op het tweede element
    sort(v2.begin(), v2.end());  

    for (auto p: v2) cout << p.first << " " << p.second << '\n';
    /* output: 
    2 7
    4 5
    4 8
    */ 
    
    // MAP ------------------------------------------------------
    map<string, int> m = {{"optie 1", 1}, {"optie 2", 3}, {"optie 5", 7}};

    cout << m.size() << '\n'; // output: 3
    m.insert({"optie 4", 13}); // m = {{"optie 1", 1}, {"optie 2", 3}, {"optie 4", 13}, {"optie 5", 7}}
    return 0;
}

Set

Een set is een lijst waarin alle elementen uniek zijn en automatisch in gesorteerde volgorde worden bewaard (standaard in oplopende volgorde).

#include <bits/stdc++.h>
using namespace std;

int main() {
    set<int> getallen;

    getallen.insert(5);
    getallen.insert(3);
    getallen.insert(9);
    getallen.insert(5);  // Dubbel, wordt genegeerd

    for (int getal : getallen) {
        cout << getal << " ";
    }

    return 0;
}

Opdracht 11.4 Maak de opdracht: Kluisjes. Gebruik een set in je oplossing.

int main() {    
    set<int> s{1, 3, 6, 7, 8}; // s = {1, 3, 6, 7, 8}

    /*
        Nuttige functies voor een SET
        1) .size()
        2) .insert()
        3) .find()
        4) .erase()
        5) .lower_bound() / .upper_bound()
    */

    cout << s.size() << '\n'; // output: 5

    s.insert(0); // s = {0, 1, 3, 6, 7, 8}

    // element vinden in een set
    auto it2 = s.find(3); // geeft een iterator die wijst naar 3
    // als het element niet in de set zit krijg je .end() iterator
    if (it2 != s.end()) cout << "3 gevonden!"; // output: 3 gevonden!

    s.erase(it2); // verwijder 3 van s, s = {1, 6, 7, 8}

    it2 = s.lower_bound(6); // geeft een iterator die wijst naar het eerste element GELIJK AAN of GROTER DAN 6 

    if (it2 == s.end()) "Niks >= 6 gevonden";
    else cout << *it2  << " gevonden!" << '\n'; // output: 6 gevonden!

    it2 = s.upper_bound(6); // geeft een iterator die wijst naar het eerste element dat GROTER DAN 6 is
    
    if (it2 == s.end()) "Niks > 6 gevonden";
    else cout << *it2 << " gevonden!" << '\n'; // output: 7 gevonden!
    
    return 0;    
}

Map

In C++ is een map een datastructuur die wordt gebruikt om sleutel-waardeparen op te slaan, vergelijkbaar met een woordenboek.

Een paar belangrijke eigenschappen:

  • Elke sleutel (key) in een map is uniek.

  • De sleutels zijn automatisch gesorteerd (standaard in oplopende volgorde).

  • De map hoort bij de Standard Template Library (STL) van C++.

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<string, int> leeftijd;

    leeftijd["Anna"] = 12;
    leeftijd["Sara"] = 16;

    for (auto pair : leeftijd) {
        cout << pair.first << ": " << pair.second << endl;
    }

    return 0;
}

Nog een tweede voorbeeld:

map<string, int> m = {{"optie 1", 1}, {"optie 2", 3}, {"optie 5", 7}};

cout << m.size() << '\n'; // output: 3
m.insert({"optie 4", 13}); // m = {{"optie 1", 1}, {"optie 2", 3}, {"optie 4", 13}, {"optie 5", 7}}

Opdracht 11.5 Maak de opdracht: Frequentie. Gebruik een map in je oplossing.

Queue/priority queue

Een queue lijkt op een array/vector maar dan met de eigenschap dat het eerste element dat wordt toegevoegd, ook het eerste element is dat eruit gaat. Dit is net zoals de rij bij de kassa.

De queue komt terug in het hoofdstuk Grafen. Hieronder al een voorbeeld van het datatype Queue.

int main() {    
    queue<int> q;
    q.push(1); // q = {1}
    q.push(4); // q = {1, 4}

    cout << q.front() << '\n'; // output: 1
    cout << q.back() << '\n'; // output: 4 
    cout << q.size() << '\n'; // output: 1

    q.pop(); // verwijdert het eerste element

    // priority_queue: een speciale queue die altijd gesorteerd is (in AFLOPENDE volgorde)
    priority_queue<int> pq;
    pq.push(0); // pq = {0}
    pq.push(5); // pq = {5, 0}
    cout << pq.top() << '\n'; // pak het eerste (=grootste) element; output: 5
    pq.pop(); // verwijdert het eerste (=grootste) element;
    cout << pq.size() << '\n'; // output: 1

    return 0;
}

Pointers

Pointers is een onderwerp dat lastiger is om te begrijpen. In dit hoofdstuk is een korte intro over pointers zodat jullie begrijpen wat een pointer is als je ze tegenkomt in een code. Een variabele is een naam die je geeft aan een plaats in het geheugen van je computer, zodat je daar gegevens op kunt slaan. De geheugenplaatsen hebben een adres, een uniek getal, om precies aan te geven waar in het geheugen de gegevens zich bevinden.

Je kunt zien wat het geheugenadres van een variabele is met de volgende code:

string dier = "Octopus"; // Een variabele met de naam dier krijgt de waarde Octupus
cout << dier;  // Deze code print de waarde van de variabele dus Octupus
cout << &dier; // Deze code print het geheugenadres van de variabele

Opdracht 11.6 Wat is het geheugenadres van de variabele dier?

Een pointer variabele bevat een geheugenadres. Door het adres op te geven, wijst een pointer naar een unieke plaats in het geheugen. Op die plaats staat de daadwerkelijke waarde.

Schematisch ziet dat er zo uit:

Een pointer declareer je door een * na het type van de variabele te zetten: string* dierPointer;

Dit kan je doen voor alle gegevenstypes, dus ook voor int , float etc. Als je een variabele hebt gedeclareerd dan heeft deze pointer nog geen waarde, ze wijzen dus nog nergens naar.

Een methode om een pointer variabele een waarde te geven is: dierPointer = &dier; nu wijst de pointer naar hetzelfde geheugenadres als de variabele dier, die de waarde Octopus heeft.

Opdracht 11.7 Wat is de uitvoer van onderstaand programma?

string dier = "Octopus";
string* dierPointer = &dier;
cout << dierPointer;

Bovenstaande code print het geheugenadres van de pointer, hier zijn we minder in geïnteresseerd. We willen graag weten wat de waarde is van de variabele waar de pointer naar toe wijst. Dit kan met de code *dierPointer.

Opdracht 11.8 Wat is de uitvoer van onderstaand programma?

string dier = "Octopus";
string* dierPointer = &dier;
cout << *dierPointer;

Je kan de waarde van de variabele waar de pointer naar wijst ook aanpassen met de code: *dierPointer = "Zeekoe";

Opdracht 11.9 Wat is de uitvoer van onderstaand programma?

string dier = "Octopus";
string* dierPointer = &dier;
*dierPointer = "Zeekoe";
cout << dier;

Last updated