Plugins en C++

Hoe krijg je je code hier geplaatst? Dat lukt mij al een tijdje niet meer. Bij mij wordt het geweigerd. :(
 
Hoe krijg je je code hier geplaatst? Dat lukt mij al een tijdje niet meer. Bij mij wordt het geweigerd. :(
Ik plaats het in een blok omgeven met [ CODE ] en [ /CODE ] maar dan zonder de spaties tussen de brackets en CODE

Code:
 // like this

Of via:

1787050504882.png
 
Dat deed ik ook. Nog eens proberen:

Code:
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>
#include <iostream>

Nu werkt het weer wel, of misschien zag mijn eerdere code er te gevaarijk uit?
 
Je threading doet niet echt iets. Wat je typisch wilt doen is workload verdelen over threads. Ik heb hier een klein programmaatje dat priemgetallen berekent door het werk uit te besteden aan meerdere threads. Iedere thread krijgt zijn eigen struct met de beschrijving van het werk en waar de thread de gevonden priemgetallen kan opslaan. De main thread gaat vervolgens voortgang rapportage doen over de threads. Er is dus communicatie tussen de threads en het hoofdprogramma. In de struct zie je een atomic 'percent' (init op 0) dat gezet wordt door de thread en gelezen wordt door de main thread (programma). De atomicity zorgt ervoor dat schrijven en lezen van deze locatie gesynchroniseerd is. Een lees operatie wordt gedaan als een schrijf actie klaar is of een schrijf operatie wordt gedaan als een lees actie klaar is.

Als alle threads klaar zijn dan kan het hoofdprogramma veilig alle data lezen uit de individuele structs die ooit aan threads toebedeeld zijn.

C++:
// primes2.cpp - the smallest version: no command line, options are constants.
//
// NUM_THREADS threads search the numbers 1..RANGE for primes. Each thread
// gets its own PrimeRange object (its part of the range + a counter).
// While working, every thread stores its progress (0..100 %) in its object
// and the main program keeps drawing one progress bar per thread on screen.
//
// Compile:  g++ -std=c++17 -Wall -Wextra -O2 -pthread primes2.cpp -o primes2
// Run:      ./primes2

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>

const int  NUM_THREADS = 10;          // how many threads
const int  RANGE       = 1000000000;  // inspect the numbers 1..RANGE
const bool SHOW_PRIMES = false;       // true: store and print the primes too
const int  BAR_WIDTH   = 50;          // progress bar columns (1 column = 2 %)

struct PrimeRange {
    int low, high;               // the part this thread checks (inclusive)
    long long count = 0;         // primes found
    std::vector<int> primes;     // the primes themselves (only if SHOW_PRIMES)
    std::atomic<int> percent{0}; // progress 0..100; the thread writes it, main
                                 // reads it -> atomic makes that safe
};

bool isPrime(int n)
{
    if (n < 2) return false;
    for (int d = 2; d * d <= n; ++d)
        if (n % d == 0) return false;
    return true;
}

void findPrimes(PrimeRange* r)   // this is what every thread runs
{
    long long size = r->high - r->low + 1;
    for (int n = r->low; n <= r->high; ++n) {
        if (isPrime(n)) {
            ++r->count;
            if (SHOW_PRIMES) r->primes.push_back(n);
        }
        int done = (long long)(n - r->low + 1) * 100 / size;
        if (done != r->percent) r->percent = done;   // report progress
    }
    r->percent = 100;            // also for an empty range
}

// Draw one bar: a full block per 2 %, a half block for an odd 1 %.
void drawBar(int threadNo, int percent)
{
    std::cout << "Thread " << (threadNo < 10 ? " " : "") << threadNo << " [";
    for (int col = 0; col < BAR_WIDTH; ++col) {
        int p = percent - col * 2;   // how much of this column is filled: 0, 1 or 2+
        std::cout << (p >= 2 ? "█" : p == 1 ? "▌" : " ");
    }
    std::cout << "] " << (percent < 100 ? " " : "") << (percent < 10 ? " " : "")
              << percent << " %\n";
}

int main()
{
    // Divide 1..RANGE over the threads; thread 1 gets the leftovers.
    std::vector<PrimeRange> ranges(NUM_THREADS);
    int next = 1;
    for (int i = 0; i < NUM_THREADS; ++i) {
        int size = RANGE / NUM_THREADS + (i == 0 ? RANGE % NUM_THREADS : 0);
        ranges[i].low  = next;
        ranges[i].high = next + size - 1;
        next = ranges[i].high + 1;
    }

    // Start the threads, each with a pointer to its own object.
    auto start = std::chrono::steady_clock::now();
    std::vector<std::thread> threads;
    for (int i = 0; i < NUM_THREADS; ++i)
        threads.push_back(std::thread(findPrimes, &ranges[i]));

    // Show the progress bars until every thread reports 100 %.
    // "\033[<n>A" is the terminal code for "move the cursor n lines up", so
    // the bars stay in place and are overwritten instead of scrolling.
    // "\033[?25l" hides the cursor (no flickering), "\033[?25h" shows it again.
    std::cout << "\033[?25l";
    while (true) {
        bool allDone = true;
        for (int i = 0; i < NUM_THREADS; ++i) {
            int p = ranges[i].percent;
            drawBar(i + 1, p);
            if (p < 100) allDone = false;
        }
        std::cout << std::flush;
        if (allDone) break;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::cout << "\033[" << NUM_THREADS << "A";
    }
    std::cout << "\033[?25h";

    // Wait for the threads (they are done, this just cleans up).
    for (std::thread& t : threads)
        t.join();
    auto stop = std::chrono::steady_clock::now();

    // Report.
    long long total = 0;
    for (int i = 0; i < NUM_THREADS; ++i) {
        if (SHOW_PRIMES)
            for (int p : ranges[i].primes) std::cout << p << "\n";
        std::cout << "Thread " << i + 1 << ": " << ranges[i].low << " .. "
                  << ranges[i].high << " -> " << ranges[i].count << " primes\n";
        total += ranges[i].count;
    }
    std::cout << "\nRange 1 .. " << RANGE << " -> " << total << " primes in total\n"
              << "Time: " << std::chrono::duration<double, std::milli>(stop - start).count()
              << " ms\n";
}

Mooi programma - ik begrijp er ongeveer de helft van. Ik zal bekijken wat ik op internet kan vinden, en dan later hier vragen waar ik niet uit kom.

Zelf kom ik met de koppeling van MIDI aan audio nu niet verder. Ook met hulp van AI loop ik steeds vast op dingen die niet werken...
 
Hier wordt het lastig:

Code:
void findPrimes(PrimeRange* r)   // this is what every thread runs
{
    long long size = r->high - r->low + 1;
    for (int n = r->low; n <= r->high; ++n) {
        if (isPrime(n)) {
            ++r->count;
            if (SHOW_PRIMES) r->primes.push_back(n);
        }
        int done = (long long)(n - r->low + 1) * 100 / size;
        if (done != r->percent) r->percent = done;   // report progress
    }
    r->percent = 100;            // also for an empty range
}

Kennelijk is "findPrimes" een functie zonder functiewaarde maar met een argument "PrimeRange* r". Maar wat is "PrimeRange* r" precies voor iets?
 
Het idee is dat je iedere thread zijn "eigen ding" geeft zodat het niet in conflict komt met andere threads. Dus voor iedere thread maak in een struct PrimeRange en die geef ik mee aan de thread (als pointer). Ik heb dus een arraytje met n-aantal PrimeRanges (waarbij n het aantal threads is).
Code:
struct PrimeRange {
    int low, high;               // the part this thread checks (inclusive)
    long long count = 0;         // primes found
    std::vector<int> primes;     // the primes themselves (only if SHOW_PRIMES)
    std::atomic<int> percent{0}; // progress 0..100; the thread writes it, main
                                 // reads it -> atomic makes that safe
};
 
Het idee van een struct begrijp ik, maar ik begrijp niet wat "PrimeRange* r" voor iets is. Of is dat de geheugenlocatie waar PrimeRange is opgeslagen?
 
Ja, het is een pointer, dus het adres in het geheugen waar de struct is opgeslagen. Pointers / references is een onderwerp dat je goed moet begrijpen in C en C++ want het is een veelvuldig gebruikt iets.

Code:
#include <iostream>

int main( void )
{

    int a = 10;
    int b = 20;

    int *p = &a;  // pointer p wijst naar het geheugen waar a leeft

    std::cout << "a: " << a << "  b:" << b << "  *p:" << *p << "  p:" << p <<'\n';

    *p = 12; // de inhoud van het geheugen waar pointer p naar wijst wordt 12
    std::cout << "a: " << a << "  b:" << b << "  *p:" << *p << "  p:" << p <<'\n';

    p = &b;  // pointer p wijst nu naar het geheugen waar b leeft
    std::cout << "a: " << a << "  b:" << b << "  *p:" << *p << "  p:" << p <<'\n';

    *p = *p + a; // de inhoud van het geheugen waar pointer p naar wijst wordt zichzelf + a
    std::cout << "a: " << a << "  b:" << b << "  *p:" << *p << "  p:" << p <<'\n';
}
 
je kunt dan

r->count

b.v.

ook schrijven

als

(*r).count

hee snap eens iets, sorry dat ik ff tussendoor kom, pointers zijn cruciaal in C en blijkbaar ook in C++, ik zat nog wat syntax te bestuderen, een tijdje terug, en zag dat pointers, en die arrow schrijfwijze, nog veelvuldig voorkomen.

ik kan me nog goed herinneren, dat ik dat eens goed doorhad, en trots was! 17 jaar!....

vanwege dat ik nu geen compiler, etc. heb, of oefen, ontglipt het je snel....

nou dat was ik weer ff..... blijft leuk....

@3ddie de code die je hebt gedeeld, moet ik nog goed bestuderen. ik weet gelukkig, voor een tijd, de basis en meer, beter.... dus.... maar het blijft een opgave....
 
Ik vind die notatie nog steeds verwarrend:

Code:
#include <iostream>

int main( void )
{
    int a = 10;
    int *p = &a;  // pointer p wijst naar het geheugen waar a leeft

    std::cout << "a: " << a << std::endl;
    std::cout << "&a: " << &a << std::endl;
    std::cout << "*p:" << *p << std::endl;
    std::cout << "p:" << p << std::endl;
    std::cout << std::endl;
    std::cout << "Dus geldt niet dat:*p = &a ." << std::endl;
}

resultaat.png
 
Ik programmeer beroepsmatig, en ik haak ook enigszins af bij dat soort zaken. Ik heb het liefst code die als een romannetje leest. Ik heb programma's met multithreading gemaakt, maar daar was het wat minder abstract dan deze C++ code. En in de Arduino C++ gebruik ik pointers nooit (tenminste, onder de motorkap wel in de libraries en bv de pinnamen die je gebruikt zijn op zich al referenties naar andere variabelen, maar ik bedoel zelf expliciet).
 
Ik vind die notatie nog steeds verwarrend:

Code:
#include <iostream>

int main( void )
{
    int a = 10;
    int *p = &a;  // pointer p wijst naar het geheugen waar a leeft

    std::cout << "a: " << a << std::endl;
    std::cout << "&a: " << &a << std::endl;
    std::cout << "*p:" << *p << std::endl;
    std::cout << "p:" << p << std::endl;
    std::cout << std::endl;
    std::cout << "Dus geldt niet dat:*p = &a ." << std::endl;
}

Bekijk bijlage 3875769

zover ik het nu kan begrijpen is:

int *p = &a;

een declaratie, en *p geeft aan dat p een pointer is.

daarna werkt p natuurlijk vanzelfsprekend als een pointer......

*p is de waarde, niet het adres dan. (dereferencing.... ik doe eens stoer)

dus in de rest van het programma, moet je niet *p gebruiken voor het adres, maar p.

dus uiteindelijk p == &a

en *p == a.....
 
Ik programmeer beroepsmatig, en ik haak ook enigszins af bij dat soort zaken. Ik heb het liefst code die als een romannetje leest. Ik heb programma's met multithreading gemaakt, maar daar was het wat minder abstract dan deze C++ code. En in de Arduino C++ gebruik ik pointers nooit (tenminste, onder de motorkap wel in de libraries en bv de pinnamen die je gebruikt zijn op zich al referenties naar andere variabelen, maar ik bedoel zelf expliciet).
Ja pointers, references, dereferencing is meer iets voor datastructuren. Zolang je programmatuur dat niet nodig heeft kun je gelukkig zonder.
 
Het is toch automatisch al zo dat p een pointer moet zijn als p = &a? Waarvoor is dat sterretje dan nog nodig?
 
@ProgHead ik weet dat heel veel boeken en C++ cursussen heel graag std::endl gebruiken ipv '\n'. Weet dat std::endl niet alleen een newline is maar ook de stream flushed. Normaal gesproken wordt output en input gebufferd en pas als er genoeg data is wordt de data geschreven. Dit is om zoveel mogelijk bloksgewijs met input/output om te gaan. Dit maakt verwerking een stuk efficiënter. Een std::endl leegt de buffer meteen. Ook als er maar een paar karakters inzitten. In kleine programma's die we hier schrijven maakt dat niet zoveel uit. Als je echter serieus data gaat processen kun je beter '\n' gebruiken als je een newline naar de output wilt schrijven. Laat het OS lekker de buffering doen. Als een stream gesloten wordt dan wordt sowieso de laatste output nog geschreven.
 
Laatst gewijzigd:
Het is toch automatisch al zo dat p een pointer moet zijn als p = &a? Waarvoor is dat sterretje dan nog nodig?

hoe moet de compiler weten dat het een pointer is?

dmv van een declaratie.

de syntax van die declaratie is dan in dit voorbeeld;

int *p = &a;

het is inderdaad verwarrend; want in 'body' geeft

*p

de waarde, en niet het adres.

dus *p != *p

de eerste is declaratie p, de tweede in de body (dat is geen echte, en goede term...).
 
Het is toch automatisch al zo dat p een pointer moet zijn als p = &a? Waarvoor is dat sterretje dan nog nodig?
Vanwege typering. We hebben in dit voorbeeld 'int' gebruikt als type maar het kan een pointer zijn naar van alles en nog wat. Zoals in mijn priem proggeltje: daar hebben we een pointer naar een struct gebruikt. Je compiler moet weten naar WAT de pointer wijst. Het is niet voldoende om te weten dat het een pointer (geheugenadres) is. Je moet dus expliciet aangeven welk type pointer het is.

Code:
char *p;   // pointer naar een enkel karakter
PrimeRange *x;   // pointer naar een struct

En zoals @vink al terecht opmerkte kun je de pointer op twee manieren gebruiken:

Code:
PrimeRange *p = &ranges[1];

*p.count += 1;
p->count += 1;

Waarbij de tweede variant met -> vaak de voorkeur verdient.
 
Back
Top