Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

C++ Programmeren Beginnersvraag(en)

Pagina: 1
Acties:

Vraag


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Hallo,

Als hobby pas (weer) begonnen met C++ en maak daarvoor gebruik van visual studio 2017 en deze website waarvan onderstaande link meteen opgave 3 toont waar mijn vraag over gaat :

http://www.ronkes.nl/oldprogrammeren/oefeningen8.html

Ik probeer het zo kort mogelijk te houden met hierna mijn broncode.

Ik begrijp namelijk niet goed waarom de parameter int ivUitkomst in de functie Machtsverheffen niet verandert, ondanks de for-lus eronder die deze parameter wijzigt.
Als de functie zn bewerking heeft gedaan en terugspringt naar main() krijg ik namelijk niet de gewijzigde waarde van ivUitkomst maar de beginwaarde ervan, dus van voordat de functie werd aangeroepen.

Lastig dit onder woorden te brengen maar heb mn best gedaan.
Hopelijk maakt de broncode duidelijker :


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
3. Schrijf een functie die een grondtal en een exponent(beide gehele getallen) als parameters meekrijgt 
en hiermee een machtsverheffing uitvoert.
Gebruik voor de berekening van het antwoord een for - lus.

Schrijf de onderstaande unit test voor de functie :
- een specifiek geval(bijvoorbeeld 3^5 = 243)
*/

#include<iostream>
using namespace std;

int ivGrondtal;
int ivExponent;
int ivUitkomst;

// functie machtsverheffen
int Machtsverheffen( int ivGrondtal,  int ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
        cout << ivUitkomst << endl;
    }

    cout << endl << endl << "ivUitkomst vlak voor return = " << ivUitkomst << endl;
    
    return ivUitkomst;
}

int main()
{
    cout << "voer een willekeurig grondtal in, maar gebruik voor deze test een 3   \n";
    cin >> ivGrondtal;

    cout << "voer een willekeurige exponent in, maar gebruik voor deze test een 5     \n";
    cin >> ivExponent;

    // nodig om kwadraat te berekenen :
    ivUitkomst = ivGrondtal;
    
    // zet alvast de eerste twee getallen van de machtsverheffings-reeks neer van x^0 en x^1
    cout << endl << "1" << endl;
    cout << ivGrondtal << endl;

    //roep functie aan
    Machtsverheffen(ivGrondtal, ivUitkomst);

    cout << "dit krijg ik dan terug als return van de functie :" << endl << endl;
    cout << endl << "ivUitkomst is niet gelijk meer aan de return in de functie Uitkomst ??????"  << endl << endl;
    cout << "ivUitkomst is namelijk teruggesprongen naar zijn beginwaarde vlak voor het aanroepen van de functie" << endl << endl;
    cout << "ivUitkomst is weer " << ivUitkomst << " geworden terwijl ik 243 had verwacht en daarom mislukt de Test." << endl << endl;

    //unit test
        if (ivGrondtal == 3 && ivExponent == 5 && ivUitkomst == 243)
        {
            cout << "Test gelukt !!" << endl;
            cout << endl;
            system("pause");
        }
        else
        {
            cout << "Test mislukt !!" << endl;
            cout << endl;
            system("pause");
        }
}



ik heb op iedere regel breakpoints gezet en integer variabele ivUitkomst veranderde prima mee totdat die terugkwam in main waarna die weer zn beginwaarde aannam. Mijn vraag is nu , waar gebeurt dat dan precies en waarom behoudt ivUitkomst niet zn laatste waarde na de berekening in de for-lus ?


Overigens heb ik het inmiddels zelf goed gekregen, maar dat verklaart (mij) nog niet waarom bovenstaande niet werkt.

Vrijwel zelfde code maar dan iets anders :


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
3. Schrijf een functie die een grondtal en een exponent(beide gehele getallen) als parameters meekrijgt
en hiermee een machtsverheffing uitvoert.
Gebruik voor de berekening van het antwoord een for - lus.

Schrijf de onderstaande unit test voor de functie :
- een specifiek geval(bijvoorbeeld 3^5 = 243)
*/

#include<iostream>
using namespace std;

int ivGrondtal;
int ivExponent;
int ivUitkomst;
int ivResultaat;

// functie machtsverheffen
int Machtsverheffen(int ivGrondtal, int ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
        cout << ivUitkomst << endl;
    }

    ivResultaat = ivUitkomst;
    return ivResultaat;
}

int main()
{
    cout << "voer een willekeurig grondtal in, maar gebruik voor deze test een 3   \n";
    cin >> ivGrondtal;

    cout << "voer een willekeurige exponent in, maar gebruik voor deze test een 5     \n";
    cin >> ivExponent;

    // nodig om kwadraat te berekenen :
    ivUitkomst = ivGrondtal;

    // zet alvast de eerste twee getallen van de machtsverheffings-reeks neer van x^0 en x^1
    cout << endl << "1" << endl;
    cout << ivGrondtal << endl;

    //roep functie aan
    Machtsverheffen(ivGrondtal, ivUitkomst);

    cout << endl << "dit krijg ik terug als return van de functie :" << ivResultaat << endl << endl;

    //unit test
    if (ivGrondtal == 3 && ivExponent == 5 && ivResultaat == 243)
    {
        cout << "Test gelukt !!" << endl;
        cout << endl;
        system("pause");
    }
    else
    {
        cout << "Test mislukt !!" << endl;
        cout << endl;
        system("pause");
    }
}



Alvast bedankt voor een antwoord :)

Aangaande dit topic, van mij mogen anderen die ook C++ beginnersvragen hebben dit topic gebruiken om hun eigen vraag/opmerking te stellen.

Alle reacties


  • Marber
  • Registratie: juni 2014
  • Nu online
Je geeft de uitkomst mee aan de functie, dus zal je zien dat als een cout doet van je functieaanroep hij wel het goede resultaat geeft.

Andere oplossing is werken met pointers, maar daar zou ik nog even mee wachten

  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Marber schreef op maandag 7 januari 2019 @ 18:07:
Je geeft de uitkomst mee aan de functie, dus zal je zien dat als een cout doet van je functieaanroep hij wel het goede resultaat geeft.

Andere oplossing is werken met pointers, maar daar zou ik nog even mee wachten
Bedankt voor je antwoord

maar ik begrijp je niet helemaal.
ik dacht namelijk niet dat ik de uitkomst meegeef aan de functie Machtsverheffen.
Ik gaf wel een beginwaarde mee voor ivUitkomst en dat was in dit geval 3 (regel 40) na invoer op regel 33.
de functie gaat vervolgens verder rekenen met deze beginwaarde van ivUitkomst en print deze netjes uit in de for-lus van regel 20 t/m 24.
als de for lus klaar is blijkt ivUitkomst nog steeds 243 te zijn, zie cout regel 26.
daarna komt echter de return op regel 28 naar regel 48 in main en dan blijkt ivUitkomst ineens weer 3 te zijn ?

Zelf dacht ik aan het volgende :
dit is de functie op regel 18

int Machtsverheffen(int ivGrondtal, int ivUitkomst)

volgens de website uit de OP worden de int ivGrondtal, int ivUitkomst de parameters genoemd van de functie.
omdat deze in de functie staan opgenomen kun je er blijkbaar wel mee rekenen of bewerken, maar niet in gewijzigde vorm, dwz de stand volgens de laatste bewerking, als return terugsturen.

daarom heb ik in de tweede code de extra int ivResultaat opgenomen waarna de unit test wel goed werkte (in visual studio zie je ook kleurverschil tussen de parameters en een 'gewone variabele') , maar ik begrijp niet goed waarom ik niet de bewerkte parameter als return krijg in de eerste code.

overigens staat er in regel 50 een klein foutje maar is niet van invloed op het geheel

50 cout << endl << "ivUitkomst is niet gelijk meer aan de return in de functie Uitkomst ??????" << endl << endl;

dit moet zijn :

50 cout << endl << "ivUitkomst is niet gelijk meer aan de return in de functie Machtsverheffen ??????" << endl << endl;

Op het laatste moment heb ik de naam van de functie gewijzigd maar ben die regel vergeten mee te wijzigen.

Beide codes zijn getest op visual en heb op meerdere plaatsen cout geplaatst , ook via breakpoints de waardes blijven volgen, maar punt is, code 1 geeft een mislukte test bij grondtal 3 en exponent 5 en code 2 met diezelfde getallen slaagt wel.
Mijn conclusie is dus dat een bewerkte parameter, zoals in dit geval ivUitkomst, niet als return kan worden meegegeven. (?)

  • Kneddah
  • Registratie: april 2014
  • Laatst online: 14:32
ivResultaat = Machtsverheffen(ivGrondtal, ivExponent), hierdoor wordt de return value van de functie machtsverheffen toegewezen aan de variable ivResultaat.

In het tweede deel wijs je ivResultaat in de functie machtverheffen al toe, daardoor werkt deze wel ;)

Daarnaast: de variabelen in de functie machtsverheffen (lokale variabelen) anders benoemen dan de globale gedeclareerde variabelen, deze kunnen met elkaar in conflict komen. Gaat nu wel goed, omdat het dezelfde waardes heeft volgens mij..

  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Bedankt, ben al stuk verder geholpen.
Pointers, lokale en globale conflict variabelen was ik in die lessen serie nog niet tegengekomen.
Zal morgen proberen een nog kortere versie van een code te schrijven waaruit waarschijnlijk zal blijken dat de return-waarde van een parameter in een functie ook na bewerking zn begin-waarde vasthoudt.
Maar waarom dat zo is, (als dat zo is en dat lijkt er wel op na de run van code 1), is me nog steeds niet helemaal duidelijk.

  • Daos
  • Registratie: oktober 2004
  • Niet online
kitao schreef op maandag 7 januari 2019 @ 20:33:
Maar waarom dat zo is, (als dat zo is en dat lijkt er wel op na de run van code 1), is me nog steeds niet helemaal duidelijk.
Dat hoort gewoon zo (in C++ en vele andere talen). De waardes worden gekopieerd bij het aanroepen van een functie. Dit noemt men "call by value". Als je de originele variabelen wilt wijzigen in een functie dan kan je pointers (* C-manier) of references (& C++-manier) gebruiken.

In jouw geval kan je, zoals anderen al hebben aangegeven, ook de return value gebruiken. Dat doe je door een variabele en een = voor de functie-aanroep te zetten. De uitkomst die je meegeeft aan return wordt dan in die variabele gestopt. Bv:

C++:
1
2
3
4
5
int functie (int a, int b) {
    return a + b;
}

uitkomst = functie(a, b);


  • Omega Supreme
  • Registratie: augustus 2002
  • Laatst online: 18-01 22:03

Omega Supreme

The God of Death

Is er een reden dat letterlijk niemand de oplossing geeft voor het probleem dat zijn uitvoer variabele niet verandert? Het is voor dit probleem uiteraard niet de ideale oplossing, maar wel het antwoord op zijn vraag. @Daos is de enige die het in passing noemt: pass by reference.

Hij programmeert in c++ een minuscule wijziging in zijn code lost het probleem op

C++:
1
2
3
4
5
6
7
void Machtsverheffen(int ivGrondtal, int &ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
    }
}



Wel redelijk dubbel op om de waarde dan ook nog eens als return value mee te geven dus dat heb ik er ook maar uit gehaald.:/

Aanroep van de functie blijft exact gelijk.

Ik zat wel even te kijken wat deze bij exponent 0 doet.

De loop wordt dan niet doorlopen en uitkomst houdt de innitiele waarde zijnde het grondgetal. Deze functiie rekent dus fout als iemand voor exponent 0 invoert!

0 tot de macht 0 is wiskundig niet gedefinieerd, vandaar dat de opgave zegt dat je die mag negeren. In de praktijk heb je twee gangbare oplossingen: 1 of een exception.

De opdracht geeft ook aan dat het exponent een functieparameter moet zijn, dat heeft TS niet gedaan. TS gebruikt globale variabelen in een functie, iets om meteen af te leren.


C++:
1
2
3
4
5
6
7
8
9
int Machtsverheffen(int ivGrondtal, int ivExponent)
{
    int resultaat = 1;
    for (int i = 0; i < ivExponent; i++)
    {
        resultaat = resultaat * ivGrondtal;
    }
   return resultaat;
}


Is denk ik waar de website naar streeft.

Omega Supreme wijzigde deze reactie 07-01-2019 21:29 (39%)

"You know you're hanging out with physics geeks when neutronium counts as a "mundane" form of matter."


  • ThomasG
  • Registratie: juni 2006
  • Laatst online: 12-01 22:39
Omega Supreme schreef op maandag 7 januari 2019 @ 21:02:
Is er een reden dat letterlijk niemand de oplossing geeft voor het probleem dat zijn uitvoer variabele niet veranderd? Het is voor dit probleem uiteraard niet de ideale oplossing, maar wel het antwoord op zijn vraag. @Daos is de enige die het in passing noemt: pass by reference.

Hij programmeert in c++ een minuscule wijziging in zijn code lost het probleem op

C++:
1
2
3
4
5
6
7
void Machtsverheffen(int ivGrondtal, int &ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
    }
}



Wel redelijk dubbel op om de waarde dan ook nog eens als return value mee te geven dus dat heb ik er ook maar uit gehaald.:/

Aanroep van de functie blijft exact gelijk.
Dit is een oplossing maar of dat in dit geval een goede oplossing is, is natuurlijk een ander verhaal. Aangezien hij globale variabelen gebruikt was in dit geval het hernoemen van de functie argumenten, of ze geheel weglaten, een "betere" optie dan ad-hoc gebruik maken van references.

In dit geval zijn dat beide echter slechte oplossingen. Als we het probleem even versimpelen komt het neer op het volgende: we hebben gehele getallen als invoer, en krijgen een geheel getal als uitvoer. In dit geval kunnen we dus de meest basis oplossing gebruiken: de functie aanpassen naar twee invoer argumenten, en een return waarde. We veranderen het tweede argument van uitvoer naar exponent, omdat uitvoer hier onnodig is als we ook de eerste stap ivUitvoer = ivGrondgetal verplaatsen naar binnen de functie.

C++:
1
2
3
4
5
6
7
8
9
10
int Machtsverheffen(int grondgetal, int exponent) {
    int uitkomst = grondgetal;
    for (int i = 1; i < exponent; ++) {
        uitkomst = uitkomst * grondgetal;
    }
    return uitkomst;
}

//
ivUitkomst = Machtsverheffen(ivGrondgetal, ivExponent);


  • Omega Supreme
  • Registratie: augustus 2002
  • Laatst online: 18-01 22:03

Omega Supreme

The God of Death

ThomasG schreef op maandag 7 januari 2019 @ 21:14:
[...]
Dit is een oplossing maar of dat in dit geval een goede oplossing is, is natuurlijk een ander verhaal. Aangezien hij globale variabelen gebruikt was in dit geval het hernoemen van de functie argumenten, of ze geheel weglaten, een "betere" optie dan ad-hoc gebruik maken van references.
Helemaal mee eens. Maar TS vroeg niet zo zeer naar de oplossing, maar waarom ivUitkomst niet wijzigde.

Overigens heb je een foutje in jouw uitwerking: uitkomst = uitkomst * uitkomst gaat je niet de juiste waarde opleveren. 'e'en van de twee variabelen aan de rechterzijde moet grondgetal zijn.

En het gaat mis bij exponent = 0! Dat laatste is simpel op te lossen door de innitiele waarde van uitkomst op 1 te zetten en de loop bij i=0 aan te vangen.

p.s. misschien kom ik wat kort door de bocht over, is niet mijn bedoeling. Zat een OpenCL kernel in c te schrijven toen ik deze welkome afleiding zag. Daar wordt je vanzelf een mierenneuker van anders werken die niet ;)

Omega Supreme wijzigde deze reactie 07-01-2019 21:24 (18%)

"You know you're hanging out with physics geeks when neutronium counts as a "mundane" form of matter."


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Iedereen hartelijk dank allemaal, heb jullie reacties eens goed doorgelezen en er al veel van opgestoken :)

Mijn vraag was inderdaad waarom kan je een parameter wel bewerken in een functie maar deze niet als bewerkt zijnde een return geven , dwz je kan hem wel returnen maar dan springt hij terug naar zn beginwaarde.
Hieronder heb ik de code korter gemaakt met een plaatje erbij.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*De return van een functie parameter*/

#include <iostream>
using namespace std;

int Parameter1 = 17;
int Parameter2 = 2;

int Functie(int Parameter1, int Parameter2)
{
    Parameter1 = Parameter1 * Parameter2;
    cout << "Regel 12 : Parameter1 binnen de functie en na bewerking binnen de functie is gelijk aan : " << Parameter1 << endl << endl;

    return Parameter1;
}

int main()
{
    cout << "Regel 19 : Print Parameter1 voordat de functie wordt aangeroepen, dan heeft deze de volgende waarde : " << Parameter1 << endl << endl;

    // roep de functie aan
    Functie(Parameter1, Parameter2);

    // de functie returnt met de volgende waarde :
    cout << "Regel 25 : Print Parameter1 nadat de functie werd aangeroepen, dan heeft deze de volgende Return-waarde : " << Parameter1 << endl << endl;
    
    system("pause");
}






Mijn vraag leek misschien van de orde van waarom is water nat maar laat ik het zo zeggen, ik had het niet verwacht dat de return niet de bewerkte versie van Parameter1 meegeeft.
Ik had ongeveer datzelfde in les 6.

http://www.ronkes.nl/oldprogrammeren/les6.html


code:
1
2
3
4
5
6
7
8
int Oppervlakte(int hoogte, int breedte)
{
    // bereken oppervlakte
    int myOppervlakte = hoogte * breedte;

    // geef oppervlakte terug
    return myOppervlakte;
}



waarom niet gewoon :


code:
1
2
3
4
5
6
7
8
int Oppervlakte(int hoogte, int breedte)
{
    // bereken oppervlakte
    Oppervlakte = hoogte * breedte;

    // geef oppervlakte terug
    return Oppervlakte;
}



Dat werkt dus niet.
Maar ja, de dingen zijn zoals ze zijn en is verder geen ramp maar was wel even zoeken om het te 'omzeilen'.
Knap daarom dat Daos dit vrijwel direkt bij naam weet te noemen.
Ik was de website al eerder tegengekomen https://www.tutorialspoint.com/cplusplus/index.htm , en zat nog te verzinnen welke ik als studie vervolg zou kiezen.
Deze krijgt nu extra punten.

Ps/
De website met lessen geeft van sommige ook de antwoorden.
Les 8 , waar dit topic mee ontstond, staat daar ook bij

http://www.ronkes.nl/oldprogrammeren/antwoorden.html

Mapje Machtsverheffen geeft dan de uitwerking van de UnitTest
Om de hoofdfunctie te starten heb ik er wel een stukje bij moeten schrijven :

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
    // voer unit tests uit
    UnitTest();

    int grondtal, exponent;

    // wacht op enter
    cout << endl << endl;
    cout << "Wat is het grondtal ? ";
    cin >>  grondtal ;
    cout << endl << "Wat is de exponent ? ";
    cin >>  exponent;
    cout << endl << "De uitkomst van deze machtsverheffing = " << Macht( grondtal,  exponent) << endl << endl;
    system("pause");

    return 0;
}

kitao wijzigde deze reactie 08-01-2019 09:20 (14%)


  • Rotterdammertje
  • Registratie: juni 2002
  • Laatst online: 18-01 14:21
kitao schreef op dinsdag 8 januari 2019 @ 06:36:


code:
1
2
3
4
5
6
7
8
int Oppervlakte(int hoogte, int breedte)
{
    // bereken oppervlakte
    int myOppervlakte = hoogte * breedte;

    // geef oppervlakte terug
    return myOppervlakte;
}



waarom niet gewoon :


code:
1
2
3
4
5
6
7
8
int Oppervlakte(int hoogte, int breedte)
{
    // bereken oppervlakte
    Oppervlakte = hoogte * breedte;

    // geef oppervlakte terug
    return Oppervlakte;
}

Waar je denk ik mee worstelt is het concept van input en output van een functie. Een functie heeft input parameters, en geeft op basis van die input parameters een waarde terug. In de functie declaratie:


code:
1
int Oppervlakte(int hoogte, int breedte)



is Oppervlakte de naam van je functie, hoogte en breedte zijn de input parameters, en de eerste int is het type van de output waarde. De code in de functie bepaalt hoe de output waarde wordt berekend; het "return" statement geeft aan wat de output waarde van de functie uiteindelijk is.

In de code waar je de functie aanroept, geef je de input waarden mee. Deze input waarden worden gekopieerd en aan de functie meegegeven (dit is niet helemaal waar, maar voorlopig waar genoeg). De functie doet dan zijn dingetje, en geeft de berekende waarde terug. Deze berekende waarde wordt niet als een parameter terug gegeven! De parameters zijn puur input voor de functie (ook weer niet helemaal waar, maar voorlopig waar genoeg). C++ doet net alsof de functie zelf de berekende waarde krijgt. In je aanroepende code moet je dan nog wel wat met die waarde doen!


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
int Oppervlakte(int hoogte, int breedte)
{
    // bereken oppervlakte
    int myOppervlakte = hoogte * breedte;

    // geef oppervlakte terug
    return myOppervlakte;
}

void DoeIets()
{
    int berekendeOppervlakte = Oppervlakte(25, 30);
}



In "DoeIets" wordt de functie Oppervlakte aangeroepen met parameters 25 en 30. Deze functie berekent de waarde 750. Deze waarde wordt daarna terug gegeven als het resultaat van de functie. In DoeIets wordt die waarde daarna opgeslagen in de variabele "berekendeOppervlakte".
waarom niet gewoon :


code:
1
2
3
4
5
6
7
8
int Oppervlakte(int hoogte, int breedte)
{
    // bereken oppervlakte
    Oppervlakte = hoogte * breedte;

    // geef oppervlakte terug
    return Oppervlakte;
}

Dit werkt niet, omdat "Oppervlakte" een functie is, en geen variabele. In C++ is het statement


code:
1
    Oppervlakte = hoogte * breedte;



ongeldig. Je kan geen waarde toekennen aan een functie. Een functie kan alleen een waarde teruggeven.

De reden dat je eerste programma niet werkte, is iets subtieler:


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int ivGrondtal;
int ivExponent;
int ivUitkomst;

// functie machtsverheffen
int Machtsverheffen( int ivGrondtal,  int ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
     }
    
    return ivUitkomst;
}



Hier definieer je eerst drie globale variabelen (ivGrondtal, ivExponent, en ivUitkomst). Deze variabelen zijn beschikbaar in je hele programma. Maar daarna definieer je in de functie Machtsverheffen ook twee parameters: ivGrondtal en ivUitkomst. Hoewel deze parameters dezelfde naam hebben als de globale variabelen, zijn het volkomen aparte dingen, met hun eigen geheugenlocatie. Als je in de functie Machtsverheffen de waarde van ivUitkomst wijzigt, dan wijzig je de waarde van de parameter ivUitkomst, niet de waarde van de globale variabele ivUitkomst. Dit wordt "shadowing" genoemd. De parameter ivUitkomst heeft als scope de functie Machtsverheffen, en is daardoor meer specifiek dan de globale variabele.

Vervolgens geef je de waarde van ivUitkomst wel terug als functie resultaat, maar in je aanroepende code negeer je het resultaat van de functie:


code:
1
2
    //roep functie aan
    Machtsverheffen(ivGrondtal, ivUitkomst);



Had je hiervan gemaakt:


code:
1
2
    //roep functie aan
    int ivNieuweUitkomst = Machtsverheffen(ivGrondtal, ivUitkomst);



dan had ivNieuweUitkomst de berekende waarde toegekend gekregen.

main = putStr (q ++ show q); q = "main = putStr (q ++ show q); q = "


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Rotterdammertje schreef op dinsdag 8 januari 2019 @ 09:19:
[...]


Waar je denk ik mee worstelt is het concept van input en output van een functie. Een functie heeft input parameters, en geeft op basis van die input parameters een waarde terug. In de functie declaratie:

[...]

Had je hiervan gemaakt:


code:
1
2
    //roep functie aan
    int ivNieuweUitkomst = Machtsverheffen(ivGrondtal, ivUitkomst);



dan had ivNieuweUitkomst de berekende waarde toegekend gekregen.
Heel duidelijk, tof d:)b

Bij dat gedeelte van Oppervlakte besefte ik ergens wel dat een computer, of mss beter gezegd de cpu, dat ieder adres slechts één waarde kan hebben. Dus als adres Functie Oppervlakte gebruikt wordt om die functie te definiëren dat die dan niet meer tegelijkertijd als opslagadres voor het eindresultaat kan dienen.
Maar wat ik vreemd vond is dat de parameter van de machtsverheffing functie wel te bewerken valt binnen die functie maar geen bewerkte waarde meekreeg in zn return.

Door jouw heldere uitleg en die van anderen snap ik nu een stuk beter hoe dat komt.
Bedankt daarvoor en in principe is mijn vraag hiermee opgelost :)

Ik heb nog wel een ander vraagje maar moet bekennen dat ik het nog niet zelf heb opgezocht.
Kan je in Visual Studio in één keer op alle coderegels Breakpoints zetten of gaat dit enkel door op één regel tegelijk te klikken ?

  • Radiant
  • Registratie: juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

kitao schreef op dinsdag 8 januari 2019 @ 09:49:
[...]

Ik heb nog wel een ander vraagje maar moet bekennen dat ik het nog niet zelf heb opgezocht.
Kan je in Visual Studio in één keer op alle coderegels Breakpoints zetten of gaat dit enkel door op één regel tegelijk te klikken ?
Je kan dan beter één breakpoint zetten op het punt waar je wil beginnen of op pauze klikken en daarna step into/step over gebruiken.

  • Rmg
  • Registratie: november 2003
  • Laatst online: 19:16
Sowieso moet je functie aanroep niet

int Machtsverheffen( int ivGrondtal, int ivExponent) zijn


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
// functie machtsverheffen
int Machtsverheffen( int ivGrondtal,  int ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
        cout << ivUitkomst << endl;
    }

    cout << endl << endl << "ivUitkomst vlak voor return = " << ivUitkomst << endl;
    
    return ivUitkomst;
}


  • BoAC
  • Registratie: februari 2003
  • Laatst online: 18:39

BoAC

Memento mori

Daarnaast wil je nooit aan je input variabelen sleuten:


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// functie machtsverheffen
int Machtsverheffen( const int &ivGrondtal,  const int &ivExponent)
{
    int ivUitkomst = ivGrondtal;
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
        cout << ivUitkomst << endl;
    }

    cout << endl << endl << "ivUitkomst vlak voor return = " << ivUitkomst << endl;
    
    return ivUitkomst;
}


De compiler levert in dit geval performance winst op, omdat er geen 'kopie' behoeft gedaan te worden :)
https://www.learncpp.com/...g-arguments-by-reference/
In dit voorbeeld zijn globale variabelen niet nodig :)

  • Omega Supreme
  • Registratie: augustus 2002
  • Laatst online: 18-01 22:03

Omega Supreme

The God of Death

@BoAC Uiteraard is passing by const reference de beste optie. Alleen dan denk ik dat het wel goed is om dat even uit te leggen, de voorbeelden die TS volgt gaan daar geheel niet op in.

Op zich wel verassend dat referencing, pointers, noch templates en unique_ptr/shared_ptr behandeld wordt. Om echt iets nuttigs te maken zal hij na het doorwerken van deze voorbeelden dus op zoek moeten naar een wat uitgebreidere tutorial.

"You know you're hanging out with physics geeks when neutronium counts as a "mundane" form of matter."


  • ThomasG
  • Registratie: juni 2006
  • Laatst online: 12-01 22:39
BoAC schreef op dinsdag 8 januari 2019 @ 10:49:
*knip*
De compiler levert in dit geval performance winst op, omdat er geen 'kopie' behoeft gedaan te worden :)
https://www.learncpp.com/...g-arguments-by-reference/
In dit voorbeeld zijn globale variabelen niet nodig :)
Nee. Als je pass-by-reference gebruikt heb je te maken met het doorgeven van een pointer (wat een reference is), en het de-referencen van de pointer binnen de functie. Dit doet de compiler voor je. Aangezien een integer op een 64 platform kleiner is dan een cpu-register (en dus kleiner dan een pointer), heb je er weinig tot geen voordeel van. Aangezien moderne compilers zorgen dat primites via pass-by-value worden geoptimaliseerd via cpu-registers, is pass-by-reference op integers eigenlijk gewoon langzamer.

Het gebruik van int & is te verdedigen, omdat je de waarde kunt aanpassen. int const & heeft geen enkel praktisch nut, en is zeker niet sneller.

  • Omega Supreme
  • Registratie: augustus 2002
  • Laatst online: 18-01 22:03

Omega Supreme

The God of Death

ThomasG schreef op dinsdag 8 januari 2019 @ 11:03:
[...]
Nee. Als je pass-by-reference gebruikt heb je te maken met het doorgeven van een pointer (wat een reference is), en het de-referencen van de pointer binnen de functie. Dit doet de compiler voor je. Aangezien een integer op een 64 platform kleiner is dan een cpu-register (en dus kleiner dan een pointer), heb je er weinig tot geen voordeel van. Aangezien moderne compilers zorgen dat primites via pass-by-value worden geoptimaliseerd via cpu-registers, is pass-by-reference op integers eigenlijk gewoon langzamer.

Het gebruik van int & is te verdedigen, omdat je de waarde kunt aanpassen. int const & heeft geen enkel praktisch nut, en is zeker niet sneller.
Goed punt, had ik nog niet eens over gedacht. Voor objecten op de heap is het echter wel degelijk een winst tov pass by value en veiliger dan pointers gebruiken.

"You know you're hanging out with physics geeks when neutronium counts as a "mundane" form of matter."


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Rmg schreef op dinsdag 8 januari 2019 @ 10:20:
Sowieso moet je functie aanroep niet

int Machtsverheffen( int ivGrondtal, int ivExponent) zijn


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
// functie machtsverheffen
int Machtsverheffen( int ivGrondtal,  int ivUitkomst)
{
    for (int i = 1; i < ivExponent; i++)
    {
        ivUitkomst = ivUitkomst * ivGrondtal;
        cout << ivUitkomst << endl;
    }

    cout << endl << endl << "ivUitkomst vlak voor return = " << ivUitkomst << endl;
    
    return ivUitkomst;
}

ok, tnx
maar de functie werd in regel 46,47 aangeroepen, zie OP codes :

46 //roep functie aan
47 Machtsverheffen(ivGrondtal, ivUitkomst);
Radiant schreef op dinsdag 8 januari 2019 @ 09:53:
[...]

Je kan dan beter één breakpoint zetten op het punt waar je wil beginnen of op pauze klikken en daarna step into/step over gebruiken.
Prima tip, meteen getest en werkt goed.
Omega Supreme schreef op dinsdag 8 januari 2019 @ 11:02:
@BoAC Uiteraard is passing by const reference de beste optie. Alleen dan denk ik dat het wel goed is om dat even uit te leggen, de voorbeelden die TS volgt gaan daar geheel niet op in.

Op zich wel verassend dat referencing, pointers, noch templates en unique_ptr/shared_ptr behandeld wordt. Om echt iets nuttigs te maken zal hij na het doorwerken van deze voorbeelden dus op zoek moeten naar een wat uitgebreidere tutorial.
ja, helemaal met je eens, zoals ik al schreef ik zat al te verzinnen voor een volgend reeks oefeningen.
Daos gaf al een goeie website maar die van BoAC ziet er zelfs nog iets beter uit. Die kon ik trouwens nog niet.
Ongeveer 5 jaar geleden wel deze proberen te volgen :

http://www.cplusplus.com/doc/tutorial/

maar werd me iets te moeilijk, bij Classes meen ik dat het schip strandde, en ging andere dingen doen.
Sindsdien niets meer aan gedaan tot een paar weken geleden. Dit wordt poging twee zeg maar.
.

  • MSalters
  • Registratie: juni 2001
  • Laatst online: 13:15
BoAC schreef op dinsdag 8 januari 2019 @ 10:49:

code:
1
2
// functie machtsverheffen
int Machtsverheffen( const int &ivGrondtal,  const int &ivExponent)


De compiler levert in dit geval performance winst op, omdat er geen 'kopie' behoeft gedaan te worden :)
Dat is wel heel erg 2010 stijl. Even afgezien van de eerdere opmerking over de grootte van integers versus adressen op 64 bits platformen, voor grote types is dit ook niet vanzelfsprekend optimaal. C++11 compilers maken geen kopie, als ze een "move" kunnen doen. Pass-by-value is expliciet een situatie waarin moves mogelijk zijn, mits het type uiteraard gemoved kan worden (Integers moven is zinloos, een kopie maken is net zo complex)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Omega Supreme
  • Registratie: augustus 2002
  • Laatst online: 18-01 22:03

Omega Supreme

The God of Death

MSalters schreef op dinsdag 8 januari 2019 @ 12:45:
[...]

Dat is wel heel erg 2010 stijl. Even afgezien van de eerdere opmerking over de grootte van integers versus adressen op 64 bits platformen, voor grote types is dit ook niet vanzelfsprekend optimaal. C++11 compilers maken geen kopie, als ze een "move" kunnen doen. Pass-by-value is expliciet een situatie waarin moves mogelijk zijn, mits het type uiteraard gemoved kan worden (Integers moven is zinloos, een kopie maken is net zo complex)
Als iemand die lang geleden c++ (lees c met classes) heeft gebruikt en redelijk recent pas met moderne c++ geconfronteerd is vindt ik dit nog redelijk verwarrend.

Ik heb wat presentaties over modern c++ van het internet gehaald en de concensus is dat pass by const ref gebruikt moet worden als een move te duur is. Wat ik echter niet kan vinden is in welke gevallen een move duur is, laat staan wanneer het te duur is. Met unique_ptr is het simpel
C++:
1
uitkomst = functie(std::move(uniquePointer));

omdat je dan geen andere optie hebt. Dat is alleen wel een bijzondre situatie omdat je na het uitvoeren van de functie de input 'kwijt bent' tenzij het op enige wijze onderdeel is van de return waarde.

Omega Supreme wijzigde deze reactie 08-01-2019 13:19 (6%)

"You know you're hanging out with physics geeks when neutronium counts as a "mundane" form of matter."


  • MSalters
  • Registratie: juni 2001
  • Laatst online: 13:15
Je kunt inderdaad niet op internet vinden welke classes een dure move hebben. Net zoals de copy constructor is de move constructor van een class potentieel user-defined, met een member-wise move als default. En voor de primitieve types is een move gelijk aan een copy.

(Na een C++ move is de toestand van het bron-object doorgaans ongespecificeerd; daarom is er geen verschil tussen copy en move voor primitieve types. "Ongewijzigd" valt ook binnen "ongespecificeerd. )

En inderdaad, een move-in van een unique_ptr betekent dat de resource geconsumeerd wordt. Dat hoef je dus niet in commentaar te beschrijven, C++11 maakt dat gedrag expliciet in de functie signature.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • ThomasG
  • Registratie: juni 2006
  • Laatst online: 12-01 22:39
Wellicht is het handig om F.call: Parameter passing uit de C++ Core Guidelines eens door te lezen.

  • EddoH
  • Registratie: maart 2009
  • Niet online

EddoH

Backpfeifengesicht

MSalters schreef op dinsdag 8 januari 2019 @ 12:45:
[...]

Dat is wel heel erg 2010 stijl.
Een move is toch geen vervanging van const reference?
Als je een functie schrijft waar je een argument mee wilt geven die je niet gaat aanpassen of kopiëren, en het niet altijd een rvalue is, is een const reference nog altijd het meest efficiënt?

  • Alain
  • Registratie: oktober 2002
  • Niet online
De code van mijn voorganger ziet er als volgt uit:


C++:
1
int getValue(double *value) { ... }



Waarbij de functie een error (negatief), ok (0) of busy (positief) terug geeft.

Ik had dit eigenlijk nooit gezien. Iemand enig idee waarom je het zo zou doen en niet gewoon de waarde teruggeven en eventueel een status als pointer?

You don't have to be crazy to do this job, but it helps ....


  • DroogKloot
  • Registratie: februari 2001
  • Niet online

DroogKloot

depenisvanjezus

Het "return status, schrijf waarde naar pointer" patroon is vrij standaard. Je kunt de signature natuurlijk ook zo schrijven:


C:
1
double getValue(int* status)



... maar nu heb je het probleem dat de caller apart naar de waarde van status moet kijken om te bepalen of de double iets zinnigs bevat, en in de niet-zinnige situaties de callee alsnog een waarde moet bedenken die dan mogelijk verkeerd geinterpreteerd wordt. Bovendien kan value een of ander custom type zijn dat duur is om te kopiëren en/of initialiseren, wat in deze variant altijd* gebeurt.

* wanneer je het zonder move semantics moet stellen althans, zoals in plain C of C++ <= 03

  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Volgende vraag alweer en heb me voorgenomen niet te snel van Tweakers gebruik te maken maar hier ben ik al paar uurtjes mee bezig en zie nog geen uitweg, behalve misschien een heel andere opzet toepassen, waarover later meer.

Uit les 9 : Bewerkingen op strings


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;

void main()
{
    string myString = "Een string vol tekens.";
    cout << myString.find("X") << endl;

    if (myString.find("X", 0))
    {
        cout << "Gevonden.";
    }
    cout << endl << endl;
    system("pause");
}



Dit is dan het resultaat :




De if lus wordt gewoon uitgevoerd (??)
sterker nog, maakt niet uit wat ik tot nu toe heb ingevuld, of ik 0 verander tot 5 of X verander tot n, alles wordt gevonden.
Enige uitzondering die ik daarbij tegenkwam was met if (myString.find("E", 0)).
Dan wordt niet de if-lus uitgevoerd.

De andere opzet waar ik het over had staat hier als example :

http://www.cplusplus.com/reference/string/string/find/

Die moet ik eigenlijk eerst nog goed doornemen maar omdat het een andere methode is weet ik dan nog niet waar het mis gaat.

Alvast bedankt.

  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

Alain schreef op dinsdag 8 januari 2019 @ 23:05:
Ik had dit eigenlijk nooit gezien. Iemand enig idee waarom je het zo zou doen en niet gewoon de waarde teruggeven en eventueel een status als pointer?
Of je gebruikt gewoon een struct, std::optional of std::variant (of straks de beste optie: std::expected) als je meer wil returnen dan in een enkele primitive past. Een andere optie is het gebruik van exceptions.



@kitao
Je antwoord wordt redelijk duidelijk als je gewoon de documenatie van find() leest. Het returnt geen bool. Wat returnt het wel?

.oisyn wijzigde deze reactie 09-01-2019 17:57 (20%)

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • ThomasG
  • Registratie: juni 2006
  • Laatst online: 12-01 22:39
find returned geen boolean, maar unsigned integer dat een positie voorstelt. Als het stukje tekst niet gevonden wordt, returned het string::npos, wat gelijk is aan 2^32-1, ofwel 4294967295. Als het wel gevonden is, returned het de positie, waarbij de eerste positie 0 is.

If-statements, of eigenlijk: condities, werken natuurlijk met true of false en niet met integers. Maar van oudsher kun je er in C++ een integer in stoppen, het getal 0 staat gelijk aan false, en vanaf 1 en hoger als true.

In jouw voorbeeld wordt X niet gevonden in de string, en returned daarom string::npos. E word wel gevonden, maar omdat het in dit geval het eerste character is (ofwel, de 0e positie), returned het 0.

Op de pagina die jij gelinkt hebt (http://www.cplusplus.com/reference/string/string/find/) staat nota bene een voorbeeld hoe je find correct gebruikt (maar helaas geen uitleg waarom).

ThomasG wijzigde deze reactie 09-01-2019 18:00 (0%)
Reden: typfout


  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

ThomasG schreef op woensdag 9 januari 2019 @ 17:57:
het getal 0 staat gelijk aan true, en vanaf 1 en hoger als true.
Gevaarlijke definitie (en dan neem ik gewoon even aan dat je bij de eerste "true" eigenlijk "false" bedoelt ;)). Wat dan bij negatieve getallen?

Voor alle primitieven geldt: 0/nullptr convert naar false, de rest naar true.

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
ThomasG schreef op woensdag 9 januari 2019 @ 17:57:
find returned geen boolean, maar unsigned integer dat een positie voorstelt. Als het stukje tekst niet gevonden wordt, returned het string::npos, wat gelijk is aan 2^32-1, ofwel 4294967295. Als het wel gevonden is, returned het de positie, waarbij de eerste positie 0 is.

[...]

Op de pagina die jij gelinkt hebt (http://www.cplusplus.com/reference/string/string/find/) staat nota bene een voorbeeld hoe je find correct gebruikt (maar helaas geen uitleg waarom).
Helemaal bedankt voor je antwoord. Ik ga met dat voorbeeld verder want ik maak hier engzins uit op dat find in genoemde les 9 niet correct wordt gebruikt, wat ik natuurlijk niet verwacht had.
Morgen als ik het cplusplus voorbeeld heb doorgenomen zal ik ook proberen de hint van .oisyn te beantwoorden, alhoewel in jouw reactie daar ook al op in wordt gegaan. Dat is dan alvast mooi meegenomen. Tnx. :)

kitao wijzigde deze reactie 09-01-2019 18:12 (17%)


  • ThomasG
  • Registratie: juni 2006
  • Laatst online: 12-01 22:39
.oisyn schreef op woensdag 9 januari 2019 @ 17:59:
[...]

Gevaarlijke definitie (en dan neem ik gewoon even aan dat je bij de eerste "true" eigenlijk "false" bedoelt ;)). Wat dan bij negatieve getallen?

Voor alle primitieven geldt: 0/nullptr convert naar false, de rest naar true.
Dat was een typefout 8)7 Maar inderdaad, wat er werkelijk gebeurd als je een primitive in een conditie stopt is kijken of het niet gelijk is aan 0.

C++:
1
2
3
4
int foo = 42;
if (foo) {
// is eigenlijk:
if (foo != 0) {



Dus:

C++:
1
2
3
4
5
if (myString.find("X")) {
// is eigenlijk:
if (myString.find("X") != 0) {
// tenzij je er het volgende van maakt:
if (myString.find("X") != std::string::npos) {


  • SuperJoker
  • Registratie: januari 2019
  • Laatst online: 11-01 11:15
Leer jezelf aan om het gewoon uit te schrijven. En als je het puristisch juist wil doen, doe je het andersom.

Dus niet:

C++:
1
if (foo != 0)



maar:


C++:
1
if (0 != foo)



Functioneel maakt het geen moer uit, het is meer een anti-bug ding.

Je zou de eerste niet zijn die per ongeluk bij een vergelijking '=' typt ipv '==' of '==='. Het voordeel van de conditie omdraaien, is dat je dan een compiler error krijgt. Dat kan je later vele uren debuggen schelen, omdat het ook typisch iets is waar je heel snel overheen kijkt.

Het best te consumeren met 1kg JOZO.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
ThomasG schreef op woensdag 9 januari 2019 @ 18:12:
[...]
Dat was een typefout 8)7 Maar inderdaad, wat er werkelijk gebeurd als je een primitive in een conditie stopt is kijken of het niet gelijk is aan 0.

C++:
1
2
3
4
int foo = 42;
if (foo) {
// is eigenlijk:
if (foo != 0) {



Dus:

C++:
1
2
3
4
5
if (myString.find("X")) {
// is eigenlijk:
if (myString.find("X") != 0) {
// tenzij je er het volgende van maakt:
if (myString.find("X") != std::string::npos) {

Prima hoor. Heb het inmiddels aangepast en werkt nu.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>
using namespace std;

void main()
{
    string myString = "Een string vol tekens.";
    cout << myString.find("x") << endl;

    if (myString.find("x", 0) != string::npos)
    {
        cout << endl <<"Gevonden.";
    }
    else
    {
        cout << endl << "Niet Gevonden.";
    }
    cout << endl << endl;
    system("pause");
}



Maar dat het werkt is niet het belangrijkste, ik begrijp door alle uitleg nu ook wat er gebeurt, mede dankzij dit :
[het getal 0 staat gelijk aan false, en vanaf 1 en hoger als true.

dat wist ik nog niet.

@.oisyn
Bedankt voor de referentie link, ben ze inmiddels aan het verzamelen in mapje.

@SuperJoker
Heb meteen ook geprobeerd om een = weg te laten en dan zonder de conditie om te draaien maar kreeg hier wel een foutmelding. (?)


  • SuperJoker
  • Registratie: januari 2019
  • Laatst online: 11-01 11:15
Kijk meteen de voordelen van wat ik zei.

Dat je een foutmelding krijgt is totaal terecht. Immers je probeert iets toe te kennen aan een functie. Dat kan niet.

Hier zie je gelijk het voordeel van deze notatiewijze. Je krijgt gelijk een foutmelding om je oren.

Je ziet ook 'left operand must be l-value'. Je hebt l values en r values, l values kunnen links van de operator staan, r values niet, die kunnen alleen rechts staan.

SuperJoker wijzigde deze reactie 09-01-2019 23:28 (14%)

Het best te consumeren met 1kg JOZO.


  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

SuperJoker schreef op woensdag 9 januari 2019 @ 23:27:
Dat je een foutmelding krijgt is totaal terecht. Immers je probeert iets toe te kennen aan een functie. Dat kan niet.
find is een functie, find(...) is een functie-aanroep, met een bepaald resultaat. Je kunt best iets assignen aan het resultaat van een functie-aanroep, vermits dat resultaat een lvalue is, of een object van class-type.

Vooral dat laatste is een beetje raar, maar dit compilet:


C++:
1
2
3
4
5
6
7
8
struct S { };
S foo();

void bar()
{
    S s;
    foo() = s;
}



foo() returnt een temporary object wat in principe gewoon assignable is.
kitao schreef op woensdag 9 januari 2019 @ 20:24:
@.oisyn
Bedankt voor de referentie link, ben ze inmiddels aan het verzamelen in mapje.
cppreference.com is echt de go-to site om details op te zoeken :). Enorm gedetailleerd en wordt actief up to date gehouden met alle nieuwe ontwikkelingen (je kunt er ook al veel dingen over C++20 lezen), en er staat precies bij vanaf welke versie van C++ iets geldt.

Om gewoon met dingen te spelen heb je de compiler explorer van Matt Godbolt: godbolt.org. Ondersteunt tal van verschillende compilers en laat de gegenereerde assembly zien. Voor standard compliance kun je het beste de x64 trunc versie van GCC of Clang pakken (Clang produceert over het algemeen betere errormeldingen), maar wel zorgen dat je -std=c++17 opgeeft als argument voor de compiler (en -O2 of -O3 voor optimalisaties als je geïnteresseerd bent in de gegenereerde assembly)

.oisyn wijzigde deze reactie 10-01-2019 08:55 (44%)

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • SuperJoker
  • Registratie: januari 2019
  • Laatst online: 11-01 11:15
Geheel waar, en in dit geval is er sprake van een constante dus is het omdraaien van de waardes niet nodig en zelfs ongewenst, maar ik dacht, laat ik het verder even niet uitwerken. Het ging mij even om het principe.

Het best te consumeren met 1kg JOZO.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
.oisyn schreef op woensdag 9 januari 2019 @ 23:52:
[...]
cppreference.com is echt de go-to site om details op te zoeken :). Enorm gedetailleerd en wordt actief up to date gehouden met alle nieuwe ontwikkelingen (je kunt er ook al veel dingen over C++20 lezen), en er staat precies bij vanaf welke versie van C++ iets geldt.

Om gewoon met dingen te spelen heb je de compiler explorer van Matt Godbolt: godbolt.org. Ondersteunt tal van verschillende compilers en laat de gegenereerde assembly zien. Voor standard compliance kun je het beste de x64 trunc versie van GCC of Clang pakken
[...]
Dat laatste gedeelte zegt me niet zo veel maar heb wel de comp.expl. bekeken en stukje getest.
Kan inderdaad later goed van pas komen, bedankt. :)

Ben nu al diverse uren bezig om een string te returnen vanuit een functie maar mijn basis is nog te weinig om het goed op te bouwen. Natuurlijk wel gezocht maar kom veel uitleg tegen met dingen die ik nog niet gehad heb. Het is niet mijn bedoeling om hele ingewikkelde vragen te stellen met veel uitgebreide uitleg die ik toch niet snap maar mss wel leuk om even oppervlakkig naar te kijken.

Ik heb dit programma geschreven (les 9 , link in code) :


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
2. Schrijf een functie die een string als invoer krijgt en als uitvoer 
het omgekeerde van die string geeft.
Oefening komt uit :
http://www.ronkes.nl/oldprogrammeren/oefeningen9.html
*/
#include <iostream>
#include <string>
using namespace std;

string str1;
string str2;
string str3;
int Positie = 0;

int Functie(string stri1)
{
    if (str1 == "")
    {
        cout << endl << "Je hebt een lege string ingevoerd" << endl;
    }

    Positie = str1.length();
    Positie--;

    for (int i = Positie; i >= 0; i--)
    {
        str2 = str1.at(Positie);
        str3 += str2;
        Positie--;
    }
    cout << endl << "Dit is str3 in Functie :   " << str3 << endl;

    return 0;
}

int main()
{
    cout << "Geef om te draaien woord ?   ";
    getline(cin, str1);

    Functie(str1);

    cout << endl << "Dit is de str3 vanuit main, " << endl;
    cout << "na terugkeer uit Functie : " << str3 << endl << endl;
    system("pause");
}



Daar komt dan dit uit :




Op zich ben ik daar best tevreden mee maar heb eigenlijk geen return 0; nodig maar een return string.
(dit ivm unit testen uit die opgave die niet in de code staat opgenomen)


verander ik regel 34 van
return 0;
naar
return str3;

en regel 45 van
cout << endl << "Dit is str3 in Functie : " << str3 << endl;
naar
cout << endl << "Dit is str3 in Functie : " << Functie(str1) << endl;

dan komt deze foutmelding :

Error C2440 'return': cannot convert from 'std::string' to 'int' Line 34


Return string zoeken op internet gaf wel verschillende resultaten maar zoals gezegd, kan ze nog niet allemaal bevatten, zoals deze http://www.cplusplus.com/forum/beginner/91991/.

Uiteindelijk komt het er dan op neer om van de verschillende uitlegversies er eentje te gaan proberen en dat heb ik bij deze gedaan, is in 5 minuten video vorm , zie link onder /* code.


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
Uitleg video op
https://www.youtube.com/watch?v=V9uWJJ6owMQ
*/

#include <iostream>
#include <string>
using namespace std;
string & ReturnString(string & n);

int main(void)
{
    string myname = "kitao";
    cout << "Mijn originele naam is :  " << myname << endl;
    cout << "De naam is veranderd tot : " << ReturnString(myname) << endl;
    system("pause");

    return 0;
}

string & ReturnString(string & n);
{
    n.clear();
    n = "piet";
    return n;
}



Dat geeft dan weer deze foutmelding :

Error C2447 '{': missing function header (old-style formal list?) Line 23

Raar, want de video is niet oud, uit feb 2016 en gebruikt ook visual studio zo te zien.
Er staan weinig reacties onder maar geen met de opmerking dat het niet werkt.

Paar keer nagekeken maar weet vrijwel 99,9% zeker dat mijn gemaakte kopie van zijn programma identiek is. Maar loopt dus toch vast. Overigens weet ik dan eigenlijk nog niet wat er precies gebeurt maar voor nu zoek ik een simpele manier om een string te returnen.
Had niet gedacht dat het returnen van een string nogal behoorlijk ingewikkeld zou blijken.
Les 9 lijkt wel een uitgewerkt antwoord te hebben maar die bekijk ik pas op het allerlaatste moment.

http://www.ronkes.nl/oldprogrammeren/antwoorden.html

  • EddoH
  • Registratie: maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Kijk eens goed naar je functie definitie. kuch, iets met puntkomma, kuch

Het returnen van dezelfde reference die je als functieargument meegeeft is overigens weinig nuttig.

EddoH wijzigde deze reactie 10-01-2019 21:19 (69%)


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
EddoH schreef op donderdag 10 januari 2019 @ 21:16:
Kijk eens goed naar je functie definitie. kuch, iets met puntkomma, kuch

Het returnen van dezelfde reference die je als functieargument meegeeft is overigens weinig nuttig.
regel 21 :$

Mijn 99,9% was dus eigenlijk 0,09% :$

Heb het getest en gaat nu goed.

Kan excuusje opvoeren, bij het invoeren van regel 9 kreeg ik al een groen golf lijntje onder string & ReturnString(string & n);
Dacht dat het, gezien de foutmelding old style uit de library van <string> was verdwenen.
Zo noemen ze dat geloof ik, <string> is een library , meen ik nog uit mn arduino tijd te herinneren, ook 5 jaar geleden.
In ieder geval, hartstikke bedankt, kan nu morgen met frisse blik en werkende string return weer verder. :)
Aangaande functieargument en reference, zover ben ik nog niet om daarover in discussie te gaan maar vind het natuurlijk niet erg als anderen daar wel op in gaan.

ps/
zie nog een foutje in de 1e code van het woord omkeer programma in mijn vorige post.

16 int Functie(string stri1)
moet zijn
int Functie(string str1)

maar blijkt voor de uitvoering geen verschil te maken. (?)

kitao wijzigde deze reactie 11-01-2019 00:58 (12%)


  • farlane
  • Registratie: maart 2000
  • Laatst online: 15:45
EddoH schreef op donderdag 10 januari 2019 @ 21:16:
Het returnen van dezelfde reference die je als functieargument meegeeft is overigens weinig nuttig.
Method chaining?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • EddoH
  • Registratie: maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Zit wat in, alleen ik denk niet dat dat de intentie was ;)
Misschien had ik 'in deze context' er bij moeten zetten.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 15:45
EddoH schreef op vrijdag 11 januari 2019 @ 15:43:
[...]
Zit wat in, alleen ik denk niet dat dat de intentie was ;)
Misschien had ik 'in deze context' er bij moeten zetten.
Ik heb zitten twijfelen of ik wel zo bijdehand zou moeten zijn. Ik vond van wel. :P

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

Omega Supreme schreef op dinsdag 8 januari 2019 @ 11:09:
[...]

Voor objecten op de heap is het echter wel degelijk een winst tov pass by value en veiliger dan pointers gebruiken.
Dit wil ik toch nog even nuanceren. Het is een ontzettend gevaarlijke uitspraak. Ja, het kopiëren van een object kan mogelijk duur zijn, maar dat is maar 1 kant van het verhaal. Het probleem met references is dat de onderliggende waarde zomaar kan wijzigen, bijvoorbeeld door een write naar een andere reference (aliasing), of na het aanroepen van een functie waarvan de compiler de inhoud niet weet.

Hierdoor zijn er tal van optimalisaties ineens niet meer mogelijk, en zit er voor de compiler niets anders op dan de betreffende waarde steeds opnieuw uit te lezen nadat hij mogelijk veranderd is. Bij het hebben van een eigen kopie binnen de scope van de functie kan ontzettend veel voordeel gehaald worden, wat misschien wel meer oplevert dan wat de kopie zelf kost.

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Was net in dit topic even aan het terugkijken voor een eerder geplaatste link.
Maar nu ik hier toch ben, het programma Visual Studio 2017 begint bijdehand te doen.

string.lenght() pakt die ene keer wel, andere keer niet :?

vergelijk regel 23, 34 , 35 , 36




Heb daarna regel 35 gekopie-plakt op regel 34 , ge-edit tot hetzelfde als wat er nu in de afbeelding op regel 34 staat en het rode error lijntje, waardoor die ook niet compileert trouwens, is dan weer weg.
Zit dan ergens hikje in het programma volgens mij.

Zou ook handig zijn als bij doorlopen van het programma met step into de prompt kan worden vastgepind ?

  • Omega Supreme
  • Registratie: augustus 2002
  • Laatst online: 18-01 22:03

Omega Supreme

The God of Death

.oisyn schreef op vrijdag 11 januari 2019 @ 17:34:
[...]

Dit wil ik toch nog even nuanceren. Het is een ontzettend gevaarlijke uitspraak. Ja, het kopiëren van een object kan mogelijk duur zijn, maar dat is maar 1 kant van het verhaal. Het probleem met references is dat de onderliggende waarde zomaar kan wijzigen, bijvoorbeeld door een write naar een andere reference (aliasing), of na het aanroepen van een functie waarvan de compiler de inhoud niet weet.

Hierdoor zijn er tal van optimalisaties ineens niet meer mogelijk, en zit er voor de compiler niets anders op dan de betreffende waarde steeds opnieuw uit te lezen nadat hij mogelijk veranderd is. Bij het hebben van een eigen kopie binnen de scope van de functie kan ontzettend veel voordeel gehaald worden, wat misschien wel meer oplevert dan wat de kopie zelf kost.
Goed punt, zo diep zit ik helaas (gelukkig?) niet in de materie. Ik doe tegenwoordig veel meer met C# en c++ lag jaren in het verleden. Alleen ben ik nu druk met OpenCL op Linux en heb ik voor de host code teruggegrepen op c++. Ophalen en voorbereiden van de iinput data voor het doorrekenen, data structures van 1GB+ zijn niet ongewoon, dan wil je echt geen onnodige kopiën hebben.

Overigens is die data omvang ook een reden voor c++, werkt in C# niet echt lekker, je ziet letterlijk wanneer de garbage collector aan de slag gaat, de berekeningen komen bijna tot stilstand.

"You know you're hanging out with physics geeks when neutronium counts as a "mundane" form of matter."


  • EddoH
  • Registratie: maart 2009
  • Niet online

EddoH

Backpfeifengesicht

kitao schreef op vrijdag 11 januari 2019 @ 17:44:
Was net in dit topic even aan het terugkijken voor een eerder geplaatste link.
Maar nu ik hier toch ben, het programma Visual Studio 2017 begint bijdehand te doen.

string.lenght() pakt die ene keer wel, andere keer niet :?

vergelijk regel 23, 34 , 35 , 36

[Afbeelding]


Heb daarna regel 35 gekopie-plakt op regel 34 , ge-edit tot hetzelfde als wat er nu in de afbeelding op regel 34 staat en het rode error lijntje, waardoor die ook niet compileert trouwens, is dan weer weg.
Zit dan ergens hikje in het programma volgens mij.
Ga je nu Visual Studio de schuld geven van je eigen spelfouten? ;)

Dit is overigens waarom code completion gebruiken/instellen in je IDE een goed idee is.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 15:45
SuperJoker schreef op woensdag 9 januari 2019 @ 18:16:
Leer jezelf aan om het gewoon uit te schrijven. En als je het puristisch juist wil doen, doe je het andersom.

Dus niet:

C++:
1
if (foo != 0)



maar:


C++:
1
if (0 != foo)

Het mag dan de kans op een bepaald type bug verkleinen, de mental capacity die het mij kost wanneer ik het lees maakt dat ik er slecht tegen kan. Nu is == en != nog te doen, maar < en > dan maakt het voor mij net negatieve logica. Kills my brain }:|

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

Maar bij < en > (en <= en >=) hoeft het natuurlijk ook niet hè ;). Maar ik ben ook geen fan. Ik kan me de laatste keer niet heugen dat ik deze fout heb gemaakt, dus dan vind ik leesbaarheid een belangrijker punt.

.oisyn wijzigde deze reactie 11-01-2019 21:41 (53%)

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • Matis
  • Registratie: januari 2007
  • Nu online

Matis

Rubber Rocket

Daarbij komt nog dat tegenwoordig een beetje compiler of SCA tool dit gewoon oppikt en je er (minstens) en warning op geeft.

If money talks then I'm a mime
If time is money then I'm out of time


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
*heel verhaal over length() verwijderd door kitao*
ik heb echt een brilletje nodig hoewel het er op lijkt dat het erger is als dat, namelijk blinde vlekken die me zelfs na minuten kijken blijkbaar niet opvallen. Geen goed begin om mee te gaan leren programmeren.

EddoH bedankt, ik zal meer vd auto complete gebruik maken, dankzij jouw post waarna ik deze video tegenkwam met daarin een paar sneltoetsen zoals ctrl+spacebar, heb er dus toch nuttige dingen van opgestoken.

YouTube: Visual Studio tutorial: Using IntelliSense effectively | lynda.com


Zal zelf eens verder zoeken hoe ik het prompt scherm in beeld kan blijven houden als ik step into gebruik.
Deze verdwijnt namelijk bij iedere klik naar de taskbar.

kitao wijzigde deze reactie 12-01-2019 09:30 (200%)


  • Mijzelf
  • Registratie: september 2004
  • Niet online
kitao schreef op zaterdag 12 januari 2019 @ 08:40:
Zal zelf eens verder zoeken hoe ik het prompt scherm in beeld kan blijven houden als ik step into gebruik.
Deze verdwijnt namelijk bij iedere klik naar de taskbar.
Het makkelijkst is een dual monitor setup.

  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

Matis schreef op zaterdag 12 januari 2019 @ 06:57:
Daarbij komt nog dat tegenwoordig een beetje compiler of SCA tool dit gewoon oppikt en je er (minstens) en warning op geeft.
Het is niet een warning die snel gegeven wordt ivm legitiem gebruik. Je moet wel moeite doen om 'm aan te zetten.

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Mijzelf schreef op zaterdag 12 januari 2019 @ 11:25:
[...]

Het makkelijkst is een dual monitor setup.
Bedankt, dat is een goeie tip, het blijft staan en ik kan tijdens het 'steppen' mee blijven kijken.
Had ik eigenlijk zelf al moeten opkomen om te proberen want is niet voor het eerst dat ik twee programma's naast elkaar zet.




Nadeel is enigzins dat alles stuk kleiner wordt, ik zocht eigenlijk een manier om de output window vast te pinnen terwijl het visual studio scherm maximaal blijft.
Kwam dan o.a. hier uit
https://visualstudio.user...o-stay-open-on-off-settin
Toegepast en cons.window blijft na einde dan wel open maar met 'steppen' helaas niet en een makkelijke oplossing hiervoor heb ik niet gevonden.


Zoals op deze manier blijft het namelijk niet staan :




Bij klik op step into verdwijnt de window naar taskbar.

Desondanks prima verbetering met duo-monitor, tnx.

Op zich had deze vraag niet veel met programmeren te maken maar wou je toch even laten weten wat het resultaat is geworden. :)

Kan wel een programmeer vraagje verzinnen maar het is niet zo dat ik er door 'vast loop'.

Ik zie voorbeelden waar geen using namespace std; wordt gebruikt en dan in plaats van bijvoorbeeld gewoon cout is het nodig om std::cout te gaan schrijven.
Dus vroeg me af waarom niet iedereen using namespace std gebruikt.

  • Mijzelf
  • Registratie: september 2004
  • Niet online
kitao schreef op zaterdag 12 januari 2019 @ 15:38:
Nadeel is enigzins dat alles stuk kleiner wordt, ik zocht eigenlijk een manier om de output window vast te pinnen terwijl het visual studio scherm maximaal blijft.
Ik bedoelde eigenlijk letterlijk 2 monitors.
Ik zie voorbeelden waar geen using namespace std; wordt gebruikt en dan in plaats van bijvoorbeeld gewoon cout is het nodig om std::cout te gaan schrijven.
Dus vroeg me af waarom niet iedereen using namespace std gebruikt.
Namespaces hebben een functie, namelijk om collisions in naamgeving te voorkomen. Met 'using namespace std' mag je zelf geen 'cout' meer aanmaken. Nou is dat niet zo'n probleem, maar wat als een van jouw globale functies/variabelen in een latere versie van de standard libraries ook in std zit? Dan heb je een conflict en compileert het niet meer.

  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Mijzelf schreef op zaterdag 12 januari 2019 @ 18:30:
[...]

Ik bedoelde eigenlijk letterlijk 2 monitors.
Ja dat dacht ik al maar mijn financiële situatie is bedroevend. Maar jouw tip werkte prima, tnx. :)
Om die reden ben ik ook met een gratis internet cursus bezig die af en toe wat stappen overslaat.
Omdat ik nog niet naar de antwoorden had gekeken onstond eerder in dit topic mijn aanname dat het returnen van een string nogal ingewikkeld is (uren mee zoet geweest)
Heb inmiddels mijn uitwerkingen van les 9 nagekeken en blijkt het heel simpel te wezen.
Het 'voorvoegsel' int Functie() veranderen naar string Functie() en return myString; gaat ineens zonder problemen.
Hier is de les 9 te vinden voor wie het interesseert.
http://www.ronkes.nl/oldprogrammeren/antwoorden.html
Namespaces hebben een functie, namelijk om collisions in naamgeving te voorkomen. Met 'using namespace std' mag je zelf geen 'cout' meer aanmaken. Nou is dat niet zo'n probleem, maar wat als een van jouw globale functies/variabelen in een latere versie van de standard libraries ook in std zit? Dan heb je een conflict en compileert het niet meer.
Had die vraag erbij verzonnen en nog niet zelf opgezocht, trefwoord 'using namespace disadvantage' levert o.a. dit op : https://www.geeksforgeeks...-considered-bad-practice/
Dat is de lange versie van jouw antwoord zeg maar.
Toch was het niet enkel luiheid om die vraag te stellen, ik zat namelijk te tobben met waarom std::cout wel vervangen kan worden door cout mits 'using' wordt gebruikt , terwijl string::npos niet vervangen kan worden door string npos hoewel #include<string> toch boven main() staat.
Of logischer een andere variant die ik probeerde:
std::cout kan met 'using' wel cout worden
maar
string::npos kan met #include<string> geen npos worden.

En opvallend is dat in het antwoord van les 9 (mapje Aeneas) maar liefst drie keer dit voorkomt :
if (myIndex != string.npos)
Hetgeen bij mij dus een error oplevert.
Heb inmiddels gevonden dat dit wel gaat :
string string = "Hallo";
if (myIndex != string.npos)
Maar zo heeft de cursus auteur het m.i. niet bedoeld aangezien hij geen string met de naam string heeft geïni-tialiseerd en 3x dezelfde schrijffout lijkt me ook onwaarschijnlijk.
Ik vermoed hier een verouderde schrijfwijze ?
Deze vraag is lastig te vinden, zoeken op string.npos levert maar één resultaat, de rest is allemaal string::npos.
Lijkt triviaal maar met zulk soort dingetjes kan ik me een tijd mee bezighouden.

kitao wijzigde deze reactie 13-01-2019 16:55 (3%)
Reden: spelfouten


  • EddoH
  • Registratie: maart 2009
  • Niet online

EddoH

Backpfeifengesicht

Een include is iets anders dan using. Zie documentatie.
Verder is string::npos een static member, geen namespace.

Zie voor gebruik:
http://www.cplusplus.com/reference/string/string/npos/
http://www.cplusplus.com/forum/beginner/233668/

  • Mijzelf
  • Registratie: september 2004
  • Niet online
mijn financiële situatie is bedroevend.
Bij een kringloop winkel zie je vaak 'oude' 3:4 LCD monitoren voor 1 of 2 tientjes.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 15:45
.oisyn schreef op vrijdag 11 januari 2019 @ 21:33:
Maar bij < en > (en <= en >=) hoeft het natuurlijk ook niet hè ;). Maar ik ben ook geen fan. Ik kan me de laatste keer niet heugen dat ik deze fout heb gemaakt, dus dan vind ik leesbaarheid een belangrijker punt.
Nee klopt, maar het ligt voor de hand (en is mijn ervaring) dat alle relational operators dan op die manier geschreven gaan worden.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Mijzelf schreef op zondag 13 januari 2019 @ 20:34:
Bij een kringloop winkel zie je vaak 'oude' 3:4 LCD monitoren voor 1 of 2 tientjes.
Dat valt zeker te overwegen, bedankt. :)
EddoH schreef op zondag 13 januari 2019 @ 19:19:
Een include is iets anders dan using. Zie documentatie.
Verder is string::npos een static member, geen namespace.

Zie voor gebruik:
http://www.cplusplus.com/reference/string/string/npos/
http://www.cplusplus.com/forum/beginner/233668/
Ja bedankt, die twee begrippen moet ik inderdaad nog uitzoeken, had inmiddels wel de verschillen in schrijfwijze gezien van het aanroepen van #include en namespace.
Eigenlijk stond er ook geen string::npos maar std::string::npos in het example.
Maar vind het verder nog steeds een raadsel waarom de cursus auteur if (myIndex != string.npos) heeft toegepast want dat compileert bij mij niet.

Ben inmiddels bij les 10 met titel Verzamelingen: http://www.ronkes.nl/oldprogrammeren/les10.html
Deze oefening zit erbij :
2. Maak een vector met daarin een vector, zodat je een tabel krijgt.
Schrijf de tabel naar het scherm.
Hieronder zie je hoe je zo'n twee-dimensionale vector moet declareren.
vector<vector<int> > myTable;

Bovenstaande hint bleek iets te summier, eerst geprobeerd met enkel die info de oefening te maken maar dat lukte niet. Dus ben elders gaan spieken. Het principe heb ik geloof ik redelijk door nu, maar nog niet dat ik het zonder naslag zo op kan schrijven. Er is wel iets dat ik enigzins teleurstellend vind.
Dit programma levert als resultaat een rijtje van 6 getallen op :




code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>Vector;
    int N = 0;
    cout << "Voer 6 getallen in   \n\n";
        for (int i = 0; i < 6; i++) {
        cin >> N;
        Vector.push_back(N);
    }
    cout << "\n\nDit is de getallen Verzameling :\n\n";
        for (int i = 0; i < 6; i++) {
        cout << Vector.at(i) << "\t";
    }
    cout << "\n\n";
    system("pause");
}


Onderstaand programma levert als resultaat een tabel op met twee rijen en drie kolommen :




code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//https://www.quora.com/How-do-I-create-a-2D-vector-array-using-std-vector
// http://www-h.eng.cam.ac.uk/help/tpl/languages/C++/vectormemory.html
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<vector<int> > VectorVector;
    int k;
    cout << "Voer 6 getallen in   \n\n";
    for (int i = 0; i < 2; i++) {
        VectorVector.push_back(vector<int>());
        for (int j = 0; j < 3; j++)     {
            cin >> k;
            VectorVector[i].push_back(k);
        }
    }
    cout << "\n\nDit is de getallen Verzameling :\n\n";
    for (int i = 0; i < 2; i++)     {
        for (int j = 0; j < 3; j++)
        {
            cout << VectorVector[i][j] << "\t";
        }
        cout << endl;
    }
    cout << endl << endl;
    system("pause");
}


Maar dat resultaat staat of valt met het wel of niet aanwezig zijn van regel 23, cout << endl;
Haal ik die namelijk weg dan is het resultaat van prog2 identiek aan prog1.
Toen ik dat voor het eerst merkte had ik het gevoel van valsspelen.
Ik zie wel het nut in van cout << VectorVector[i][j] , zo kan je bepaalde gedeeltes uit de verzameling opvragen en printen. Maar had ergens verwacht dat er een soort van allesomvattende cout << VectorVector; zou zijn waardoor de verzameling in zn geheel meteen in tabelvorm zou worden geprint.
Die is er waarschijnlijk niet ?

  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
Dit wordt meer een algemene vraag, apart van de vorige anders wordt die te lang.
Zelf heb ik geen programmeurs in mijn kennissenkring en als hobbyist ook geen scholing voor gedaan.
Merk nu wel dat ik aan het kopie/plak blokkendoos programmeren ben en eigenlijk puur afgaand van wat er op het output schermpje verschijnt.
Kopie/plak uit voorbeelden die zo weinig mogelijk voor mij nieuwe dingen bevatten en het vinden daarvan kan soms enige tijd duren.
En veel geschuif binnen het programma als het resultaat afwijkt van hetgeen er moet komen.

Met daarbij soms verrassende dingen, zo verwachtte ik dat Vector.at(0) de eerste letter zou geven maar in plaats daarvan werd het eerste woord geprint.
Voorbeeld van bij elkaar geblokt programmaatje uit drie verschillende websites :

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
4. Schrijf een programma dat een zin vraagt aan de gebruiker, 
alle woorden in de zin stuk-voor-stuk in een vector zet 
en daarna de woorden genummerd onder elkaar op het scherm zet.
*/
#include<iostream>
#include<string>
#include<vector>
#include <sstream>
using namespace std;

string zin;
int y;
vector<string>Vector;

int main()
{
    cout << "schrijf een zin \n\n";
    getline(cin, zin);  
    cout << endl << endl;
    system("pause");
    cout << endl;

    istringstream ss(zin);      // gevonden op http://www.cplusplus.com/faq/sequences/strings/split/
    while (!ss.eof())           // blijf splitten tot einde string
    {
        string x;               // here's a nice, empty string
        getline(ss, x, ' ');    // splits de string op de spaties
    //  cout << x << endl;      // print it out, EVEN IF WE ALREADY HIT EOF
        
        Vector.push_back(x);    // zet iedere aparte split in vector
                                // gevonden op http://www.ronkes.nl/oldprogrammeren/les10.html
        y += 1;                 // y wordt gebruikt als display nummertje voor de woorden

        for (int i = 0; i < Vector.size(); i++) // doorloop vector
                                                // ieder woord krijgt blijkbaar eigen positie in de Vector
        {
            cout << y << " " << Vector.at(i) << endl;   // print het woord op positie i 
            Vector.erase(Vector.begin());               // maak de Vector leeg voor het volgende woord
                                                        // gevonden op http://www.cplusplus.com/reference/vector/vector/erase/
        }
    }
    cout << endl;
    system("pause");
}



met deze output :



Ik vraag me nu af of anderen op deze manier ook programmeren hebben geleerd en of de kopie/plak methode gangbaar gebruik is ?
Zou misschien beter zijn een basis setje 'steentjes' te hebben en dan eerst daarmee wat gaan schuiven voordat er een nieuw setje bij komt ?
Probleem is dat bij deze korte en gratis online cursus er m.i. te weinig steentjes zijn om de oefening mee te voltooien. Iemand die uit ervaring een meer gestructureerde, goedkope (en legale) cursusboek of online tutorial weet , dan hoor ik dat graag. :)

kitao wijzigde deze reactie 15-01-2019 15:04 (1%)
Reden: code iets overzichtelijker gemaakt


  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

Ik vind je code maar raar. Elke iteratie van de buitenste while ga je een woord toevoegen aan de vector, vervolgens loop je binnen die iteratie over de elementen van de vector en verwijder je de elementen. Je vector bevat dus altijd hooguit maar 1 element.

Die for-lus is ook raar. Je verwijdert steeds het eerste element bij elke iteratie (waardoor het element op plek 1 natuurlijk op plek 0 terecht komt), maar je gebruikt wel steeds i om de vector te indexeren. Dan ga je natuurlijk elementen missen als er daadwerkelijk meerdere elementen in staan.

En waarom verwacht je dat Vector.at(i) het i'de teken teruggeeft? Het is toch een vector van woorden?

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
.oisyn schreef op dinsdag 15 januari 2019 @ 14:04:

Ik vind je code maar raar.

Elke iteratie van de buitenste while ga je een woord toevoegen aan de vector, vervolgens loop je binnen die iteratie over de elementen van de vector en verwijder je de elementen. Je vector bevat dus altijd hooguit maar 1 element.
Ja, dat vond ik ook.

Maar kan niet alles reproduceren wat ik daarvoor heb geprobeerd.
Kijkend op de output window zag ik dat zonder leegmaken bij iedere while loop er een woord bijkwam.
dus bij while loop 0 werd er 1 Goede geprint
en bij while loop 1 werd er 2 Goede middag geprint etc.
Heb bovendien moeite met het begrip iteratie.
Die for-lus is ook raar. Je verwijdert steeds het eerste element bij elke iteratie (waardoor het element op plek 1 natuurlijk op plek 0 terecht komt), maar je gebruikt wel steeds i om de vector te indexeren. Dan ga je natuurlijk elementen missen als er daadwerkelijk meerdere elementen in staan.
Dat bedoelde ik dus met puur op output window afgaan.
Heb willekeurig ergens een lange zin geplukt, die als invoer geplakt maar toch werd ieder apart woord op nummervolgorde geprint. Had niet het idee dat er iets gemist werd ? Of bedoel je iets anders ?

Moet er wel bij zeggen dat ik mijn uitwerking nog niet met het antwoord heb vergeleken.
http://www.ronkes.nl/oldprogrammeren/antwoorden.html
Maar ja, de volgende twee en laatste lessen hebben geen antwoorden en mede daarom was mijn vraag of iemand nog een goede tutorial kan aanraden.
En waarom verwacht je dat Vector.at(i) het i'de teken teruggeeft? Het is toch een vector van woorden?
niet bij declaratie vector<int>Vector; meen ik ?
heb er zelf als vermoeden maar vector<string>Vector; van gemaakt zonder eigenlijk te weten wat er dan gebeurt.

  • .oisyn
  • Registratie: september 2000
  • Laatst online: 16:44

.oisyn

Moderator Devschuur® / Cryptocurrencies

Demotivational Speaker

kitao schreef op dinsdag 15 januari 2019 @ 15:24:
[...]


Ja, dat vond ik ook.

Maar kan niet alles reproduceren wat ik daarvoor heb geprobeerd.
Kijkend op de output window zag ik dat zonder leegmaken bij iedere while loop er een woord bijkwam.
dus bij while loop 0 werd er 1 Goede geprint
en bij while loop 1 werd er 2 Goede middag geprint etc.
Heb bovendien moeite met het begrip iteratie.
Omdat je bij ieder woord over de hele vector heenloopt. Waarom loop je niet gewoon pas over de vector heen als je alle woorden hebt verzameld, dus buiten de while loop?
niet bij declaratie vector<int>Vector; meen ik ?
Een vector<int> is een vector van ints. Nu gebruik je een vector van strings. En wat je eraan toevoegt met push_back() is ook een string, namelijk het woord dat je toevoegt.
heb er zelf als vermoeden maar vector<string>Vector; van gemaakt zonder eigenlijk te weten wat er dan gebeurt.
Misschien moet je eerst proberen de code te begrijpen ipv gewoon maar wat bij elkaar copy-pasten :)

If we can hit that bullseye, the rest of the dominoes will fall like a house of cards. Checkmate.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
.oisyn schreef op dinsdag 15 januari 2019 @ 15:32:

Misschien moet je eerst proberen de code te begrijpen ipv gewoon maar wat bij elkaar copy-pasten :)
ja, dat idee had ik ook al
beetje erop los knippen en plakken totdat het output schermpje de gewenste vorm aanneemt is dus niet de juiste methode.
"Snap het dan" helpt daarentegen ook niet veel.
Maar bedankt voor je tips .oisyn ,zal ze morgen nog eens goed doorlezen.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 15:45
kitao schreef op dinsdag 15 januari 2019 @ 05:58:
[...]
Maar vind het verder nog steeds een raadsel waarom de cursus auteur if (myIndex != string.npos) heeft toegepast want dat compileert bij mij niet.
Weet niet of het kwartje inmiddels gevallen was, maar std::string::npos is een static member van de class string (die in de std namespace leeft).

Static members kunnen met <classname>::<membername> worden aangesproken ( hier dus string::npos ) wat wat mij betreft de cleanste manier is, maar ook via een object van dat type (my_string.npos) wat jij dus doet als je je std::string object 'string' gaat noemen.

Je voelt aan je water dat dat laatste geen goed idee is neem ik aan? ;)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
farlane schreef op dinsdag 15 januari 2019 @ 22:33:
Weet niet of het kwartje inmiddels gevallen was, maar std::string::npos is een static member van de class string (die in de std namespace leeft).
Static members kunnen met <classname>::<membername> worden aangesproken ( hier dus string::npos ) wat wat mij betreft de cleanste manier is, maar ook via een object van dat type (my_string.npos) wat jij dus doet als je je std::string object 'string' gaat noemen.
Je voelt aan je water dat dat laatste geen goed idee is neem ik aan? ;)
Dat was om te testen farlane, de auteur gaf namelijk dit in zn antwoord : if (myIndex != string.npos).
maar dat draait bij mij niet, dus was er (tijdelijk) over verbaasd.
.oisyn schreef op dinsdag 15 januari 2019 @ 15:32:
Omdat je bij ieder woord over de hele vector heenloopt. Waarom loop je niet gewoon pas over de vector heen als je alle woorden hebt verzameld, dus buiten de while loop?
Op deze manier bedoel je ?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<string>
#include<vector>
using namespace std;
string Zin, Zin2;
vector<string>Vec;
int main(){
    cout << "geef zin " << endl;
    getline(cin, Zin);  getline(cin, Zin2);
    Vec.push_back(Zin); Vec.push_back(Zin2); // laad eerst de vector op
    // doe er pas na het opladen bewerkingen mee, zoals bijvoorbeeld ..
    for (int i = 0 ; i < Vec.size() ; ++i)  {
        cout << Vec[i] << endl; }
    system("pause");}


Nog even terugkomend op mijn opmerking dat ik mijn code ook maar vreemd vond, dat was meer in de zin van dat het vast niet de bedoeling was om in het antwoord allerlei dingen erbij te plukken die nog niet behandeld waren in die lessen serie. Voor mij zijn de meeste codes nog hiërogliefen waarvan lastig te zien is of zo'n code elegant of geforceerd is. Heb inmiddels wel het antwoord van de auteur bekeken en deze gecompacteerd

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// les 10 oef 4 http://www.ronkes.nl/oldprogrammeren/oefeningen10.html
// les 10 antw 4 http://www.ronkes.nl/oldprogrammeren/antwoorden.html
#pragma warning ( disable : 4786 )  // schakel waarschuwing 4786 uit
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
    string myZin;       // vraag om invoer
    cout << "Voer een zin in: ";
    getline(cin, myZin);
    vector<string> myWoorden;   // doorloop zin letter voor letter
    int myBegin = 0;
    for (int i = 0; i < myZin.length(); i++)
    {
        if (myZin.at(i) == ' ')     // is dit een spatie?
        {
            string myWoord = myZin.substr(myBegin, i - myBegin);    // ja, haal woord uit zin
            myWoorden.push_back(myWoord);           // sla woord op in vector
            myBegin = i + 1;            // onthoud begin van volgende woord
        }
    }
    myWoorden.push_back(myZin.substr(myBegin, myZin.length() - myBegin));   // voeg laatste woord toe aan vector
    for (int j = 0; j < myWoorden.size(); j++)  // doorloop vector
    {
        cout << j + 1 << ". " << myWoorden.at(j) << endl;       // schrijf woord naar scherm
    }
    cout << endl;   // wacht op enter
    system("pause");
    return 0;
}
#pragma warning ( default: 4786 )   // schakel waarschuwing 4786 weer in


Bij deze heb ik dan vanwege regel 24 e.v. (laatste woord opvegen) wel het gevoel van gekunsteld maar heb nog niet zelf geprobeerd om met de beschikbare 'steentjes' het beter te doen, als dat al mogelijk is, want wil tegelijkertijd ook graag verder met het volgende hoofdstuk.
Dit komt eruit :


Vanwege dubbele spatie een lege lijn op 3. Maar dat gebeurt ook met mijn programmaatje.
Ik merk trouwens op (zonder bijdehand te willen doen) dat de vector in regel 20 ook binnen 2 loops wordt gevuld ?
En nog hartelijk bedankt trouwens voor de moeite die jij en anderen nemen en/of genomen hebben om dit even door te nemen. :)

O ja nog iets
de #pragma regels (?) op 3 en 33, die kunnen weg, had bij mij tenminste geen invloed.

  • farlane
  • Registratie: maart 2000
  • Laatst online: 15:45
kitao schreef op woensdag 16 januari 2019 @ 14:23:
[...]
Dat was om te testen farlane, de auteur gaf namelijk dit in zn antwoord : if (myIndex != string.npos).
maar dat draait bij mij niet, dus was er (tijdelijk) over verbaasd.
Dat was me duidelijk, maar de test die je deed gaf (impliciet) aan dat je niet de betekenis ken(t/de) van een static member.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • kitao
  • Registratie: juli 2012
  • Laatst online: 17:51
farlane schreef op woensdag 16 januari 2019 @ 18:55:
Dat was me duidelijk, maar de test die je deed gaf (impliciet) aan dat je niet de betekenis ken(t/de) van een static member.
Dat klopt, en ik beheers dat begrip nog steeds niet goed. Static Members of a C++ Class doorgelezen maar op dit moment wacht ik nog even met classes, na wat meer basis komt dat vast nog voorbij neem ik aan. :)

Kwam vandaag while (cin.good()); tegen en is op zich best te bevatten totdat ik probeerde die op de watchlist te krijgen. Dat lukte maar er kan daarvan geen waarde in beeld worden gebracht ?
Heb twee pagina's doorgelezen, hfdst 1.11 en 1.11a van https://www.learncpp.com/ en hier en daar wat rondgekeken maar ben er op dit punt niet verder mee gekomen.

Visual Studio snip



code:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
void main()
{
    int myInput;
    do  
    {
        cin >> myInput;
    } 
    while (cin.good());
    // cin.good() geeft false als de invoer ongeldig is.
    system("pause");
}


Ps/
Liep vervolgens tegen een geskipte cin aan, heeft me drie uur gekost :|
Fragmentje met oplossing, via http://www.cs.technion.ac...q/istream-and-ignore.html

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    cout << "toets b om opnieuw te beginnen \n";
    cin >> d;    // cin doet het hier prima !!!!!!
    if (d == "a")   
    {
        cout << "toets een niet-getal om naar het menu te gaan \n";
        do      
        {
            cout << "geef getal   ";
            cin >> Input; // Input is een Int.
            Som += Input;
            cout << "De som =  " << Som << endl;
        } while (cin.good());   
    }
    cout << "geef je nieuwe keuze : a of b ? \n";
    //  cin >> d;      wordt geskipt ?????????????????

    // Oplossing :
    // How can I get cin to skip invalid input characters?
    // http://www.cs.technion.ac.il/users/yechiel/c++-faq/istream-and-ignore.html
    // #include <limits> moet vermeld staan boven main

    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cin >> d;



Hier stond nog een suggestie maar die deed het niet :

You can only input one word into a cin. Instead, use getline(cin, string name); If it still doesn't work, add a cin.ignore(); before your getline(cin, string name);, like this:
string country;
cout << "Now please enter the country you are in at the moment:\n\n";
cin.ignore();
getline(cin, country);
This will now definitely work.


Waarom dat laatste niet lukt weet ik echter niet.

Ps2/
Mijn vraag over een passende cursus is inmiddels gevonden. Ik had wel iets duidelijker kunnen zijn, ik bedoelde eentje met oefeningen én antwoorden.
Voorlopig kan ik met deze drie verder :

Cursus
http://liacs.leidenuniv.nl/~kosterswa/lst/lst.pdf
http://liacs.leidenuniv.nl/~kosterswa/lst/
antwoorden
http://liacs.leidenuniv.nl/~kosterswa/lst/uitw.txt

Video Cursus
https://github.com/TPayne...ee/master/LLCPP_Solutions
Let's Learn C++ ~ Basics: 1 of 14
YouTube: Let's Learn C++ ~ Basics: 1 of 14 ~ Visual Studio Setup + My First ...

Vampire Studios (snelcursus, zonder oef en antw)
http://members.chello.nl/~s.pampiermole/index.html

en
http://www.ronkes.nl/oldprogrammeren/index.html

kitao wijzigde deze reactie 18-01-2019 02:26 (53%)

Pagina: 1


Apple iPhone XS Red Dead Redemption 2 LG W7 Google Pixel 3 XL OnePlus 6T (6GB ram) FIFA 19 Samsung Galaxy S10 Google Pixel 3

Tweakers vormt samen met Tweakers Elect, Hardware.Info, Autotrack, Nationale Vacaturebank, Intermediair en Independer de Persgroep Online Services B.V.
Alle rechten voorbehouden © 1998 - 2019 Hosting door True