abonnement Unibet Coolblue Bitvavo
pi_92085388
quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:

[..]

Oeh, een excuus om ongegeneerd te gaan muggenziften. :)

Je gebruikt voor elk getal een int. Opzich niets mis mee, maar een int kan ook negatief zijn. In veel getallen is een negatieve waarde geen valide waarde, bijvoorbeeld als je vraagt hoeveel getallen ingelezen moeten worden of als de index van een for-loop. In dit geval kun je beter het 'type' size_t gebruiken, dat in C(++) gebruikt wordt voor een 'size', oftewel een aantal of grootte dat niet negatief kan zijn. ('Type' staat hier tussen aanhalingstekens omdat het een typedef is voor een unsigned int en geen basistype.)
Ah, uiteraard. Zou hier niet bijvoorbeeld ook een simpele unsigned int toepasbaar zijn? Size(_t) ken ik niet, maar zoals u (jij?) het beschrijft lijkt het me dezelfde eigenschappen hebben als een unsigned int.

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
e gebruikt een postfix increment in de for-loops: idx++. Wederom opzich niets mis mee, behalve dat idx++ een extra operatie uitvoert vergeleken met ++idx. (Lees het verschil maar eens ergens.) Een nette for-loop is dus als volgt:

[ code verwijderd ]
kan het niet allebei? Dus ofwel dat je doet:
1for (size_t iii = 0; iii < 10; ++iii)
ofwel dit, en dat het dezelfde uitkomst heeft?
1for (size_t iii = 0; iii <= 10; iii++)

Overigens dacht ik dat bij ++iii je nooit iii = 0 krijgt?

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
Ik weet niet of het een typefout betreft, maar de declaratie

[ code verwijderd ]

...is raar, omdat je een referentie naar een pointer doorgeeft. Ik kan me niet voorstellen dat dat de bedoeling was.
Ik heb deze *&pnGetallen gedaan, zodat ik de Array pnGetallen kon bewerken in de void? Moet dat anders/doe ik het niet goed?

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
De main() functie van C++ hoeft geen return-waarde te hebben; als deze er niet is, wordt '0' teruggegeven. Je laatste statement in de main is dus nutteloos.
Oke, bedankt voor de informatie, dat wist ik niet. :)

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
Iets gevaarlijks wat je doet is het volgende:

[ code verwijderd ]

De operator new() alloceert geheugen buiten de stack en alles wat met new aangemaakt wordt, moet ook met delete verwijderd worden. Als je een pointer naar een double mee wilt geven, gebruik je daarvoor de &-operator:

[ code verwijderd ]

Pas als je werkelijk geheugen dynamisch wilt alloceren, gebruik je de operator new.
Ik wil ook dynamisch alloceren, omdat de grootte van de array nog niet bepaald is, toch? Ik moet volgens mij wel sowieso nadat ik met new een array heb gemaakt, even delete[] pnArray doen, toch? Of gaat dat vanzelf wanneer het programma afsluit?

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
Ik ken de headerfile "stdafx.h" ook niet: weet je zeker dat je die nodig hebt?
Die is volgens mij nodig voor de compiler die ik gebruik (Microsoft Visual C++ 2010 Express)

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
Voor invoercontrole kan je het uitlees-statement evalueren:

[ code verwijderd ]
Oke, hierbij is dus input per definitie bijv. een int, en als de invoer geen int is geeft hij een error/kan je er iets mee doen? Bedankt. :)

quote:
1s.gif Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
Hopelijk heb ik je niet afgeschrikt. :)
Zeker niet, altijd goed om verbeterpunten te zien. Bedankt. :)
pi_92085603
Het verschil tussen ++i en i++ is als volgt. Beide expressies verhogen i met 1, maar het zijn ook expressies met een waarde. ++i heeft als waarde i na de verhoging, en i++ heeft als waarde i voor de verhoging. Omdat je de expressie alleen maar als statement gebruikt, zal de compiler de waarde volkomen negeren, i++ en ++i zijn in dit geval precies hetzelfde. Maar als i een of ander class-object is waarvoor beide operatoren gedefinieerd zijn, dan zal i++ net iets meer tijd kosten om uit te voeren omdat-ie de oude waarde moet returnen ipv de nieuwe.
  zondag 30 januari 2011 @ 17:29:21 #53
189216 netolk
maar dan andersom
pi_92085733
quote:
1s.gif Op zondag 30 januari 2011 17:22 schreef Jeroentk het volgende:

Ah, uiteraard. Zou hier niet bijvoorbeeld ook een simpele unsigned int toepasbaar zijn? Size(_t) ken ik niet, maar zoals u (jij?) het beschrijft lijkt het me dezelfde eigenschappen hebben als een unsigned int.

kan het niet allebei? Dus ofwel dat je doet:
dat klopt idd je kan beide methode gebruiken...
Alleen weetje met size_t zeker dat je getal altijd groot genoeg kan worden

quote:
Overigens dacht ik dat bij ++iii je nooit iii = 0 krijgt?
Dit kan je zelf heel eenvoudig checken hè...
1
2
3
4
#include <iostream>
for(int i = 0; i < 10; ++i){
  std::cout << i << std::endl;
}
quote:
Ik wil ook dynamisch alloceren, omdat de grootte van de array nog niet bepaald is, toch? Ik moet volgens mij wel sowieso nadat ik met new een array heb gemaakt, even delete[] pnArray doen, toch? Of gaat dat vanzelf wanneer het programma afsluit?
Je moet delete altijd aanroepen anders kan je geheugenleaks krijgen

quote:
Die is volgens mij nodig voor de compiler die ik gebruik (Microsoft Visual C++ 2010 Express)

compiled die niet ook gewoon zonder die include?
Beware of the Raping Zebra's
pi_92086240
quote:
1s.gif Op zondag 30 januari 2011 17:27 schreef thabit het volgende:
Het verschil tussen ++i en i++ is als volgt. Beide expressies verhogen i met 1, maar het zijn ook expressies met een waarde. ++i heeft als waarde i na de verhoging, en i++ heeft als waarde i voor de verhoging. Omdat je de expressie alleen maar als statement gebruikt, zal de compiler de waarde volkomen negeren, i++ en ++i zijn in dit geval precies hetzelfde. Maar als i een of ander class-object is waarvoor beide operatoren gedefinieerd zijn, dan zal i++ net iets meer tijd kosten om uit te voeren omdat-ie de oude waarde moet returnen ipv de nieuwe.
Oke, ik zal dus wanneer ik ze nodig heb in statements ++i gebruiken. Bedankt. :)

quote:
1s.gif Op zondag 30 januari 2011 17:29 schreef netolk het volgende:

[..]

dat klopt idd je kan beide methode gebruiken...
Alleen weetje met size_t zeker dat je getal altijd groot genoeg kan worden
Size_t past zich dan ook aan aan de invoer? Want waarom zou je dan überhaupt nog ooit int gebruiken?

quote:
1s.gif Op zondag 30 januari 2011 17:29 schreef netolk het volgende:

Je moet delete altijd aanroepen anders kan je geheugenleaks krijgen
Oke, bedankt. Gedaan. :)

quote:
1s.gif Op zondag 30 januari 2011 17:29 schreef netolk het volgende:
compiled die niet ook gewoon zonder die include?
Nee, ik heb het geprobeerd, maar ik krijg dan de volgende error:
1>c:\*\add.cpp(1): warning C4627: '#include <iostream>': skipped when looking for precompiled header use

Links naar de afbeeldingen:
http://img412.imageshack.us/f/errorc2.jpg/
Error wanneer ik 'A' invul.
http://img821.imageshack.us/i/errorc3.jpg/
Error nadat ik gewone getallen heb ingevuld..
pi_92086535
Dat zijn bufferoverflows. Je hebt geen geheugenruimte gereserveerd voor de arrays waarin je schrijft.
pi_92087310
Oh, bedankt, dat is een vrij opzichtige fout. Wel erg makkelijk te herstellen.. simpelweg door te schrijven:

1
2
3
4
size_t nAantal;
AantalGetallen(nAantal);
    
double *pnGetallen = new double[nAantal];
  zondag 30 januari 2011 @ 18:13:25 #57
189216 netolk
maar dan andersom
pi_92087711
quote:
1s.gif Op zondag 30 januari 2011 18:03 schreef Jeroentk het volgende:
Oh, bedankt, dat is een vrij opzichtige fout. Wel erg makkelijk te herstellen.. simpelweg door te schrijven:

[ code verwijderd ]

ja, idd maar waarom maak je je AantalGetallen functie niet gewoon zo?

1
2
3
4
5
6
7
size_t AantalGetallen(){
    size_t nAantal=0;
    cout << "Hoeveel getallen wilt u bij elkaar optellen?" << endl;
    cin >> nAantal;
    cout << endl;
    return nAantal;
}

dan kan je het gewoon zo schrijven:
1double *pnGetallen = new double[AantalGetallen()];
Beware of the Raping Zebra's
  zondag 30 januari 2011 @ 18:15:54 #58
11839 DemonRage
[ Eindhoven ]
pi_92087844
quote:
1s.gif Op zondag 30 januari 2011 17:27 schreef thabit het volgende:
Het verschil tussen ++i en i++ is als volgt. Beide expressies verhogen i met 1, maar het zijn ook expressies met een waarde. ++i heeft als waarde i na de verhoging, en i++ heeft als waarde i voor de verhoging. Omdat je de expressie alleen maar als statement gebruikt, zal de compiler de waarde volkomen negeren, i++ en ++i zijn in dit geval precies hetzelfde. Maar als i een of ander class-object is waarvoor beide operatoren gedefinieerd zijn, dan zal i++ net iets meer tijd kosten om uit te voeren omdat-ie de oude waarde moet returnen ipv de nieuwe.
Sterker nog:
_asm { inc i }

is sneller dan:
++i;
wat zich vertaalt naar:
mov eax, dword ptr [i]
add eax, 1
move dword ptr [i], eax


Maar het eerste is wel minder platform onafhankelijk en het werkt alleen op primitieve typen. :+
pi_92088026
Het lijkt me toch dat een compiler dat nog wel moet kunnen optimaliseren. :?
  zondag 30 januari 2011 @ 18:31:09 #60
11839 DemonRage
[ Eindhoven ]
pi_92088598
quote:
1s.gif Op zondag 30 januari 2011 18:19 schreef thabit het volgende:
Het lijkt me toch dat een compiler dat nog wel moet kunnen optimaliseren. :?
Als je 'm laat optimaliseren voor snelheid dan waarschijnlijk wel. Bij mij wordt add eax, 1 wel veranderd in inc eax. De reden dat-ie nog wel eerst mov eax, dword ptr [i] doet is omdat eax wordt gebruikt als parameter bij het aanroepen van printf. eax wordt dus eerst gepusht op de stack en dan opgeslagen in het geheugen met mov dword ptr [i], eax, voordat de call naar printf plaats vindt.

[ Bericht 1% gewijzigd door DemonRage op 30-01-2011 18:42:45 ]
pi_92089268
quote:
Je moet delete altijd aanroepen anders kan je geheugenleaks krijgen
Wat nette code betreft, klopt dit, maar als antwoord op de vraag: als je programma termineert wordt gealloceerd geheugen wel teruggeven aan het OS, dus je verliest nooit geheugenruimte. (Wel kan het zijn dat destrcutors niet aangeroepen worden waarin je iets belangrijks doet (port sluiten, bestand schrijven), dus altijd delete-en, maar het geheugen zelf wordt teruggegeven.)

quote:
Ik wil ook dynamisch alloceren, omdat de grootte van de array nog niet bepaald is, toch? Ik moet volgens mij wel sowieso nadat ik met new een array heb gemaakt, even delete[] pnArray doen, toch? Of gaat dat vanzelf wanneer het programma afsluit?
Hier ligt waarschijnlijk ook je buffer overflow probleem: je alloceert geen array, je alloceert een (1) double. Arrays alloceer je met operator new[], die ook een lengte verwacht. Als je alleen new gebruikt, alloceer je slechts ruimte voor 1 double. Details zijn bijvoorbeeld hier te vinden.

Edit: Oh, ik zie dat je dat al had gevonden. Naja. :)

[ Bericht 5% gewijzigd door GS42 op 30-01-2011 19:03:54 ]
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92089700
quote:
1s.gif Op zondag 30 januari 2011 18:31 schreef DemonRage het volgende:

[..]

Als je 'm laat optimaliseren voor snelheid dan waarschijnlijk wel. Bij mij wordt add eax, 1 wel veranderd in inc eax. De reden dat-ie nog wel eerst mov eax, dword ptr [i] doet is omdat eax wordt gebruikt als parameter bij het aanroepen van printf. eax wordt dus eerst gepusht op de stack en dan opgeslagen in het geheugen met mov dword ptr [i], eax, voordat de call naar printf plaats vindt.
Zal wel komen doordat printf een int als returnwaarde heeft en die worden doorgaans in eax doorgegeven.
  zondag 30 januari 2011 @ 18:56:45 #63
11839 DemonRage
[ Eindhoven ]
pi_92089850
quote:
1s.gif Op zondag 30 januari 2011 18:53 schreef thabit het volgende:

[..]

Zal wel komen doordat printf een int als returnwaarde heeft en die worden doorgaans in eax doorgegeven.
Nee, het is sneller om eax meteen te gebruiken dan om de waarde van i na de optelling uit het geheugen te plukken, want in eax zit dan toch al het resultaat van de optelling. :) (het gaat nog steeds om code die vóór de aanroep van printf uitgevoerd wordt)
pi_92090614
quote:
1s.gif Op zondag 30 januari 2011 18:13 schreef netolk het volgende:

[..]

ja, idd maar waarom maak je je AantalGetallen functie niet gewoon zo?

[ code verwijderd ]

dan kan je het gewoon zo schrijven:

[ code verwijderd ]

Zoiets zou ik ook kunnen doen, ja, maar mij lijkt dat minder praktisch. Dit omdat ik meerdere keren AantalGetallen() zou moeten gebruiken en hij hem dus ook meerdere keren activeert. Om dit te voorkomen zou ik er een variabele aan toe kunnen schrijven, maar dan heb je uiteindelijk meer code. Maar misschien zit ik fout, en is die andere manier toch sneller. Wel zou ik dan graag weten hoe ik kan voorkomen dat AantalGetallen() steeds opnieuw uitgevoerd wordt, zonder er een variabele aan toe te schrijven.. Tenzij een variabele eraan toeschrijven uiteindelijk toch nog sneller is dan de manier die ik al heb beschreven. :)
  zondag 30 januari 2011 @ 19:36:22 #65
189216 netolk
maar dan andersom
pi_92091749
quote:
1s.gif Op zondag 30 januari 2011 19:12 schreef Jeroentk het volgende:

[..]

Zoiets zou ik ook kunnen doen, ja, maar mij lijkt dat minder praktisch. Dit omdat ik meerdere keren AantalGetallen() zou moeten gebruiken en hij hem dus ook meerdere keren activeert. Om dit te voorkomen zou ik er een variabele aan toe kunnen schrijven, maar dan heb je uiteindelijk meer code. Maar misschien zit ik fout, en is die andere manier toch sneller. Wel zou ik dan graag weten hoe ik kan voorkomen dat AantalGetallen() steeds opnieuw uitgevoerd wordt, zonder er een variabele aan toe te schrijven.. Tenzij een variabele eraan toeschrijven uiteindelijk toch nog sneller is dan de manier die ik al heb beschreven. :)
en wat is het probleem dat je een functie vaker gebruikt?
Alles in een functie word opnieuw "aangemaakt" als je de functie aanroept, dus je variabele word gewoon opnieuw gemaakt.

ik volg even niet helemaal wat je bedoelt met voorkomen dat ie steeds opnieuw uitgevoerd word...
Als je die functie maar 1 x aanroept word ie ook maar 1x uitgevoerd (tenzij je een loop maakt)

maar als je 1x een getal wilt invullen en dan met dat getal allemaal dingen wilt doen kun je beter 1 variabele maken en daar je ingevulde getal in opslaan...

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
int main(){
   size_t getal;
   std::cout << "Vul een getal in.\t"
   std::cin >> getal;
   std::cout << std::endl;
   
   // hier dingen doen met dat getal
  
  return 0;
}
Beware of the Raping Zebra's
pi_92092099
Ja, dat is inderdaad wat ik wil. Maar ik wil dat niet in de main() doen, dus heb ik 2 opties: of ik voer de functie uit en schrijf iets van:
1size_t AantalGetallen = AantalGetallen()
of ik gebruik degene die ik al heb laten zien, waarin ik eerst een variabele maak, die meegeef aan een void die hem vervolgens verandert. Ik weet niet welke sneller is?
  zondag 30 januari 2011 @ 19:49:20 #67
189216 netolk
maar dan andersom
pi_92092318
quote:
1s.gif Op zondag 30 januari 2011 19:44 schreef Jeroentk het volgende:
Ja, dat is inderdaad wat ik wil. Maar ik wil dat niet in de main() doen, dus heb ik 2 opties: of ik voer de functie uit en schrijf iets van:

[ code verwijderd ]

of ik gebruik degene die ik al heb laten zien, waarin ik eerst een variabele maak, die meegeef aan een void die hem vervolgens verandert. Ik weet niet welke sneller is?
qua snelheid maakt het denk ik niet merkbaar wat uit, als je via referenties (&) iets aan een functie door geeft kost dat volgens mij wel minder geheugen (verbeter me als dit niet klopt)

maar waarom wil je dit niet in de main doen dan? want dit is niet zo'n groot programma dus blijft het wel overzichtelijk... (tenzij je dit als oefening doet dan heb ik niks gezegd)
Beware of the Raping Zebra's
pi_92092495
Jep, ik doe dit allemaal als een oefening. ;) Ik ben nog niet zo lang bezig (2 dagen :') ) en ik had dit programma vooral geschreven om te proberen de pointers en referenties toe te passen met arrays ed. Toch bedankt. :)
  zondag 30 januari 2011 @ 21:46:36 #69
189216 netolk
maar dan andersom
pi_92100554
quote:
1s.gif Op zondag 30 januari 2011 19:52 schreef Jeroentk het volgende:
Jep, ik doe dit allemaal als een oefening. ;) Ik ben nog niet zo lang bezig (2 dagen :') ) en ik had dit programma vooral geschreven om te proberen de pointers en referenties toe te passen met arrays ed. Toch bedankt. :)
ahh, ik snap :)

Het zijn hele handige dingen maar je moet zorgen dat je voor elke new ook een delete uitvoert vanwege de geheugen leaks... en dat is soms nog best lastig...
Beware of the Raping Zebra's
pi_92108389
quote:
Ik heb deze *&pnGetallen gedaan, zodat ik de Array pnGetallen kon bewerken in de void? Moet dat anders/doe ik het niet goed?
In C(++) is een array in principe een (const) pointer. Als je een int[5] aan een functie doorgeeft, kan je die opvangen als int*. Hierbij weet de functie de lengte van de array niet, dus wordt deze vaak als extra argument meegegeven. (De main functie, int main(int argc, char **argv) {} is hier een voorbeeld van.) Je kunt in jouw code de reference (&) dus gewoon weglaten: een reference naar een pointer is nooit nodig - ik kan ten minste geen nut verzinnen.

quote:
Size_t past zich dan ook aan aan de invoer? Want waarom zou je dan überhaupt nog ooit int gebruiken?
In vrijwel elke implementatie is 'size_t' identiek aan 'unsigned int' en heeft dus geen speciale eigenschappen, het is een typedef voor een basistype en past zich niet aan aan de invoer. Je kunt er echter niet vanuit gaan dat size_t gelijk is aan unsigned int, omdat dit niet in de standaard staat. Veel stl-functies geven size_t's terug (std::string::length() en std::string::find(), bijvoorbeeld). Om deze op te vangen is het beter een size_t te gebruiken omdat je dan gegarandeerd het goede type hebt: als je deze immers in een unsigned int opvangt, hoop je maar dat dit hetzelfde is.

Je wordt dus min of meer gedwongen om size_t voor afstandsmaten te gebruiken: zo garandeer je maximale portability van je code. En waarom ook niet? Het is minder typewerk en heeft geen overhead...

En natuurlijk wil je soms wel een int gebruiken, bijvoorbeeld als negatieve waarden ook mogelijk zijn. Je wilt nooit de buitentemperatuur in een size_t zetten, maar een array-index wel. Als negatieve waarden geen (valide) betekenis in je variabele hebben, gebruik je size_t.

quote:
qua snelheid maakt het denk ik niet merkbaar wat uit, als je via referenties (&) iets aan een functie door geeft kost dat volgens mij wel minder geheugen (verbeter me als dit niet klopt)
Ik denk niet dat het in dit geval iets uitmaakt. Een return-by-argument heeft de overhead van het maken en dereferencen van een pointer. Een standaard return moet in principe een kopie maken van het object dat hij teruggeeft. (Dit gebeurt in de praktijk zelden, elke hedendaagse compiler past indien mogelijk copy elision toe, waardoor er geen kopie gemaakt wordt.) Dus ook qua geheugengebruik verwacht ik geen merkbaar verschil.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92108584
Op 64-bitssystemen is een size_t een 64-bits unsigned integer en een int 32-bits. Voor indexering van arrays e.d. is het altijd het handigst een size_t te gebruiken.
pi_92111800
quote:
1s.gif Op maandag 31 januari 2011 00:05 schreef GS42 het volgende:

[..]

In C(++) is een array in principe een (const) pointer. Als je een int[5] aan een functie doorgeeft, kan je die opvangen als int*. Hierbij weet de functie de lengte van de array niet, dus wordt deze vaak als extra argument meegegeven. (De main functie, int main(int argc, char **argv) {} is hier een voorbeeld van.) Je kunt in jouw code de reference (&) dus gewoon weglaten: een reference naar een pointer is nooit nodig - ik kan ten minste geen nut verzinnen.

[..]
Oke, ik had hier gelezen dat je ze wel kunt gebruiken om de waarden van pointers te veranderen binnen functies, maar ik heb inderdaad eens geprobeerd om de reference weg te laten en het werkte. Bedankt. :) Wel vraag ik me af of je nu altijd dat kunt weglaten, of dat dat alleen bij een array zo is? Of is het hier zo van array = pointer.

quote:
1s.gif Op maandag 31 januari 2011 00:05 schreef GS42 het volgende:In vrijwel elke implementatie is 'size_t' identiek aan 'unsigned int' en heeft dus geen speciale eigenschappen, het is een typedef voor een basistype en past zich niet aan aan de invoer. Je kunt er echter niet vanuit gaan dat size_t gelijk is aan unsigned int, omdat dit niet in de standaard staat. Veel stl-functies geven size_t's terug (std::string::length() en std::string::find(), bijvoorbeeld). Om deze op te vangen is het beter een size_t te gebruiken omdat je dan gegarandeerd het goede type hebt: als je deze immers in een unsigned int opvangt, hoop je maar dat dit hetzelfde is.

Je wordt dus min of meer gedwongen om size_t voor afstandsmaten te gebruiken: zo garandeer je maximale portability van je code. En waarom ook niet? Het is minder typewerk en heeft geen overhead...
Maar een size_t 'reserveert' dus eigenlijk dubbel zoveel ruimte als een int? Of is dat alleen omdat het niet negatief kan gaan?

Verder had ik nog een vraag: met betreft het eruit filteren van tekst in plaats van getallen heb ik geprobeerd een beroep te doen op de isnan() functie. Ik had gehoord dat die in de <math.h> stond, maar wanneer ik dit heb zegt hij nog steeds dat isnan een undefined identifier is..
1
2
#include <math.h>
if (isnan('test'));
Hoe kan ik hem wel werkende krijgen?
pi_92112743
quote:
Wel vraag ik me af of je nu altijd dat kunt weglaten, of dat dat alleen bij een array zo is? Of is het hier zo van array = pointer.
Bij arrays is een reference niet nodig, bij basic types en classes is deze (of een pointer) wel nodig als je de waarde van de variabele in de functie wilt veranderen. Het geldt niet helemaal dat array == pointer, maar nadat de array opgevangen is door een functie wel (binnen de functie). Het verschil tussen een array en een pointer is dat je een pointer een nieuwe waarde kunt geven en een array-naam niet. Dus:

1
2
3
4
int arr[3] = {1, 2, 3}; // Maak array van 3 elementen
int *ptr = arr; // Maak pointer die naar begin van array wijst
++ptr; // Zet pointer op tweede element van array
++arr; // ILLEGAAL! Waarde van 'arr' ligt vast en kan niet veranderd worden

quote:
Maar een size_t 'reserveert' dus eigenlijk dubbel zoveel ruimte als een int?
Daar is dus niets over te zeggen: dat is implementatieafhankelijk. Natuurlijk kan een unsigned int een hogere waarde bevatten dan een signed int, maar dat is omdat het bereik anders gebruikt wordt.

quote:
Verder had ik nog een vraag: met betreft het eruit filteren van tekst in plaats van getallen heb ik geprobeerd een beroep te doen op de isnan() functie
Niet gebruiken. Dit is een twijfelachtige functie (of soms erger: macro) die niet in de standaard zit. Misschien werkt 'ie wel, misschien werkt 'ie anders dan je verwacht, misschien is 'ie niet aanwezig. Je kan input controleren met de evaluatie waar we het over gehad hebben, en een divide-by-zero (die 'inf' op zou moeten leveren ipv. 'nan') moet je zelf afvangen door te controleren of de noemer nul is.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92135866
quote:
1s.gif Op maandag 31 januari 2011 07:05 schreef Jeroentk het volgende:

[ code verwijderd ]

Hoe kan ik hem wel werkende krijgen?
Google is je vriend...

http://en.wikipedia.org/wiki/Math.h
Zoals blijkt bestaat de functie 'isnan' helemaal niet... enkel 'nan' bestaat.

Verder zou ik eens kijken naar:
http://en.wikibooks.org/wiki/Subject:C_programming_language

en
http://en.wikibooks.org/wiki/Subject:C%2B%2B_programming_language
  maandag 31 januari 2011 @ 21:17:43 #75
189216 netolk
maar dan andersom
pi_92143843
quote:
1s.gif Op maandag 31 januari 2011 07:05 schreef Jeroentk het volgende:

Verder had ik nog een vraag: met betreft het eruit filteren van tekst in plaats van getallen heb ik geprobeerd een beroep te doen op de isnan() functie. Ik had gehoord dat die in de <math.h> stond, maar wanneer ik dit heb zegt hij nog steeds dat isnan een undefined identifier is..
Je kan beter std::isalpha gebruiken om te kijken of het een teken is deze functie staat gedeclareerd in de <cctype> header
Beware of the Raping Zebra's
pi_92231384
Hoe kan ik ervoor zorgen dat wanneer de gebruiker een verkeerd/geen getal invoert, hij automatisch "Voer een getal tussen x en x in" schrijft en dan opnieuw vraagt om een getal, zonder zichzelf aan te roepen? (bij een functie)
pi_92233153
Iets als het volgende is mogelijk:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int input;
for (;;) {
    std::cout << "Voer een getal tussen -10 en 10 in: ";
    if ( (std::cin >> input) ) {
        if (input >= -10 && input <= 10)
            break;
    }
    else {
        std::cin.clear(); // clear error state
        char dump[255];
        std::cin.getline(dump, 255); // Discard cin buffer
    }
}
std::cout << "Het getal is " << input << ".\n";

De truc is dat als lezen uit std::cin faalt, er een error flag in het object wordt geset, en je deze dus eerst moet resetten en de tekens (die blijkbaar geen cijfers zijn) uit moet lezen. Met cin.clear() reset je alle error flags en met een cin.getline() (bijvoorbeeld, er zijn andere mogelijkheden) kan je willekeurige tekens uitlezen en weggooien.

Alleen als je de juiste invoer hebt, laat je de gebruiker uit de loop komen.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92236475
Oke, bedankt, ik begrijp het. Wel vraag ik me nu af hoe je gewoon een x aantal characters kunt aflezen en weggooien en dat je dus niet afhankelijk bent van of de gebruiker meer of minder dan 255 karakters intypt.. Doe je dit door 'dump' dynamisch te maken?
pi_92265188
quote:
Wel vraag ik me nu af hoe je gewoon een x aantal characters kunt aflezen en weggooien en dat je dus niet afhankelijk bent van of de gebruiker meer of minder dan 255 karakters intypt.
Op deze manier lees je maximaal 255 characters uit de istream. Als je maximaal x characters wilt, kan je dat doen met char dump[x]. Als je x wilt laten bepalen door de gebruiker, dan kan je inderdaad dynamisch alloceren of x/n keer n chars uitlezen en deze in een string opslaan.

Wat je je echter moet realiseren, is dat je niet weet hoeveel characters er in een istream buffer staan en je dus niet van tevoren dynamisch kunt alloceren op basis daarvan. Daarnaast wordt input alleen naar std::cin gestuurd na een enter, dus je kunt geen individuele characters uitlezen op het moment dat ze getypt worden (normaal gesproken dan; er zijn os-specifieke oplossingen die het wel kunnen, zoals curses).

Voor het negeren van een deel van het buffer bestaat ook nog istream::ignore, misschien dat je daar wat aan hebt. Deze kan je een te negeren lengte meegeven en een stop-byte.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92380674
Hoe kan ik het beste omgaan met namespaces? Stel ik heb twee namespaces, en ik wil in de ene namespace iets van de andere namespace pakken, dan kan ik :: voor de naam zetten, het werkt echter ook zonder.

Ik zie eigenlijk nooit code waar bijvoorbeeld dingen uit de std namespace zo benadert worden, met andere namespaces zie ik dat weer wel.
One cannot make an omelette without
breaking eggs -- but it is amazing how
many eggs one can break without making
a decent omelette.
  zaterdag 5 februari 2011 @ 20:22:06 #81
85514 ralfie
!Yvan eht nioj
pi_92382579
quote:
5s.gif Op zaterdag 5 februari 2011 19:35 schreef nightsleeper het volgende:
Hoe kan ik het beste omgaan met namespaces? Stel ik heb twee namespaces, en ik wil in de ene namespace iets van de andere namespace pakken, dan kan ik :: voor de naam zetten, het werkt echter ook zonder.

Ik zie eigenlijk nooit code waar bijvoorbeeld dingen uit de std namespace zo benadert worden, met andere namespaces zie ik dat weer wel.
Wat is je vraag precies?
pi_92386564
quote:
Hoe kan ik het beste omgaan met namespaces? Stel ik heb twee namespaces, en ik wil in de ene namespace iets van de andere namespace pakken, dan kan ik :: voor de naam zetten, het werkt echter ook zonder.
Je kunt niet zomaar iets uit een namespace pakken zonder óf de scope resolution operator (::) te gebruiken óf een using-directive (using namespace std) te op te geven. Je kunt dus niet zomaar vanuit de ene namespace iets uit een andere gebruiken.

Wél kun je in een namespace dingen gebruiken die in de global scope gedefinieerd zijn:

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <cmath>

namespace X {
    double y = cos(0);
};

int main() {
    std::cout << X::y << '\n';
}

Je ziet hier dat in de namespace X de globale functie cos() aangeroepen kan worden. Dit kan op deze manier, of met ::cos() omdat de lege scope resultion operator verwijst naar de globale namespace. Als je echter een conflicterende functie in je namespace hebt, kan de :: nodig zijn voor de juiste aanroep:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <cmath>

namespace X {
    double cos(double in) { return 42; };

    double y = cos(0);
    double z = ::cos(0);
};

int main() {
    std::cout << X::y << ", " << X::z << '\n';
}

Hier krijg je de uitvoer: 42, 1
Soms gebeurt het dat je in je namespace een conflict hebt met een globale functie, waardoor je de scope resolution nodig hebt. Ik hoop dat dit je vraag beantwoordt; zoniet zal je deze moeten verduidelijken.

[ Bericht 0% gewijzigd door GS42 op 05-02-2011 21:52:56 ]
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92401396
quote:
5s.gif Op zaterdag 5 februari 2011 20:22 schreef ralfie het volgende:

[..]

Wat is je vraag precies?
Stel, ik heb namespace a en namespace b. In namespace a wil ik de variabele blabla van namespace b gebruiken, dan kan ik ::b::blabla doen, maar b::blabla werkt ook.

Ik zie mensen vanuit namespaces ook nooit ::std::iets doen, maar bij andere namespaces wordt dat weer wel gedaan.
One cannot make an omelette without
breaking eggs -- but it is amazing how
many eggs one can break without making
a decent omelette.
pi_92402039
quote:
Ik zie mensen vanuit namespaces ook nooit ::std::iets doen, maar bij andere namespaces wordt dat weer wel gedaan.
Gegeven wat ik hierboven schrijf, kan dat - denk ik - twee redenen hebben. Ten eerste is het gebruik van de lege scope resolution operator alleen in geval van ambiguiteit noodzakelijk, en niemand zal zelf een namespace std maken. Daarnaast wordt de lege operator ook wel gebruikt om duidelijk aan te geven dat iets uit de globale namespace komt, dus niet omdat het programmeertechnisch nodig is maar om te verduidelijken waar een object vandaan komt. Dit is niet nodig bij de std-namespace omdat iedereen weet waat deze zich bevindt.
"Slechts diegene mag slopen die iets beters kan bouwen."
  donderdag 3 maart 2011 @ 16:28:07 #85
189216 netolk
maar dan andersom
pi_93596279
is hier iemand bekent met sockets??? ik snap niet goed hoe ik een server meerdere connecties kan laten hebben. Ik heb deze tut gevonden maar die heeft dus geen meerdere connecties. Iemand enig idee hoe ik dit zou kunnen maken?
Beware of the Raping Zebra's
pi_93601254
Je zou met threads kunnen werken, maar dat is in C++ een crime.
  donderdag 3 maart 2011 @ 20:24:04 #87
67978 HenryHill
Fake it 'till you make it
pi_93607039
quote:
1s.gif Op donderdag 3 maart 2011 18:31 schreef thabit het volgende:
Je zou met threads kunnen werken, maar dat is in C++ een crime.
De taal C(++) biedt zelf geen threading functionaliteit, maar Win32 biedt hier bijvoorbeeld wel een API voor. En inderdaad, vergeleken met bijv. .NET is Win32 threading niet grappig.

Zie bijvoorbeeld hier en hier voor uitleg.
So this is how liberty dies... with thunderous applause.
Truth? What's so great about the truth? Try lying for a change, it's the currency of the world
  donderdag 3 maart 2011 @ 22:32:43 #88
189216 netolk
maar dan andersom
pi_93616801
hmm, ja threads... is dat de enige (handige) oplossing?
Beware of the Raping Zebra's
pi_93617116
Interrupts kan ook nog (denk ik).
  vrijdag 4 maart 2011 @ 01:11:50 #90
189216 netolk
maar dan andersom
pi_93624293
hmm, oke ik had gehoopt dat het wat makkelijker was...

maar het komt er dus op neer dat een nieuwe aanvraag word doorverwezen naar een nieuwe threat en een andere poort?
Beware of the Raping Zebra's
pi_93628960
quote:
1s.gif Op donderdag 3 maart 2011 16:28 schreef netolk het volgende:
is hier iemand bekent met sockets??? ik snap niet goed hoe ik een server meerdere connecties kan laten hebben. [...] Iemand enig idee hoe ik dit zou kunnen maken?
Het is mogelijk om het niet multi-threaded te doen maar alles gewoon in 1 thread af te handelen. Hiertoe zet je alle sockets op non-blocking en sla je alle connecties op in een std::vector<Client>.

Algemene aanpak: eerst loop je door alle clients heen en lees je alle gestuurde gegevens. En hierna kijk je of er toevallig nieuwe clients zijn die een connectie willen.

Alle clients afhandelen kan het beste door gebruik te maken van een fd_set i.c.m een select() aanroep. Hiermee kan je in 1 keer controleren of er clients zijn die data hebben gestuurd en áls die er zijn, welke clients data hebben gestuurd. Hierdoor hoef je niet elke client met een timeout uit te lezen. Als er data is, loop je alle clients langs en controleer je via de df_set of een client data heeft gestuurd. Als dat zo is, kan je gewoon read()'en.

Nieuwe clients accepteren gaat zoals je gewend bent met accept(); omdat deze op non-blocking staat faalt deze direct (met EAGAIN) als er geen clients zijn, waardoor je direct door kan gaan. Als er wel een client is, accepteer je deze, zet je de verbinding op non-blocking en voeg je de client toe aan je vector.

Als je op fd_set zoekt, vind je vast wel voorbeelden.
"Slechts diegene mag slopen die iets beters kan bouwen."
  vrijdag 4 maart 2011 @ 11:11:09 #92
254493 Trollface.
gr rob fruithof, groningencity
pi_93632549
Ik kan niet wachten op C++0x, dan heeft het eindelijk native threads.

Ik zou trouwens boost::thread gebruiken, veel makkelijker ook.
★5731U★ Death from above '79★You're a woman, i'm a machinielsie ★ ✠ ★ Telkens weer een beetje sterven★ I was born in a winterstorm, i live there still★
pi_93632877
Tja, je weet hopelijk waar "0x" voor staat?
  maandag 7 maart 2011 @ 21:16:42 #94
189216 netolk
maar dan andersom
pi_93788644
quote:
1s.gif Op vrijdag 4 maart 2011 09:40 schreef GS42 het volgende:

[..]

Het is mogelijk om het niet multi-threaded te doen maar alles gewoon in 1 thread af te handelen. Hiertoe zet je alle sockets op non-blocking en sla je alle connecties op in een std::vector<Client>.

Algemene aanpak: eerst loop je door alle clients heen en lees je alle gestuurde gegevens. En hierna kijk je of er toevallig nieuwe clients zijn die een connectie willen.

Alle clients afhandelen kan het beste door gebruik te maken van een fd_set i.c.m een select() aanroep. Hiermee kan je in 1 keer controleren of er clients zijn die data hebben gestuurd en áls die er zijn, welke clients data hebben gestuurd. Hierdoor hoef je niet elke client met een timeout uit te lezen. Als er data is, loop je alle clients langs en controleer je via de df_set of een client data heeft gestuurd. Als dat zo is, kan je gewoon read()'en.

Nieuwe clients accepteren gaat zoals je gewend bent met accept(); omdat deze op non-blocking staat faalt deze direct (met EAGAIN) als er geen clients zijn, waardoor je direct door kan gaan. Als er wel een client is, accepteer je deze, zet je de verbinding op non-blocking en voeg je de client toe aan je vector.

Als je op fd_set zoekt, vind je vast wel voorbeelden.
kijk dit klinkt beter :)
Beware of the Raping Zebra's
  dinsdag 8 maart 2011 @ 16:58:19 #95
189216 netolk
maar dan andersom
pi_93820216
ik ben nu een beetje aan het klooien met threads, die kunnen zeker niet cross-platform geschreven worden?

ik heb nu dit simpele progje gemaakt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <windows.h>

unsigned long WINAPI Threader(void *Data){
    int i = 0;
    while(true){
        std::cout << "Threader:\t" << i++ << '\n';
        Sleep(500);
    }
}
int main(){
    std::cout << "Start of program\n";
    
    HANDLE Thread = CreateThread(0,0,Threader,0,0,0);
    Sleep(5000);
    std::cout << "Main:\tMiddel in the run\n";
    getchar();
    CloseHandle(Thread);
    return 0;
}

Ik vroeg me af wat WINAPI doet, als ik het weg laat dan kan ie Dword (*)(void*) niet converteren naar Dword (*)(void*)... weet iemand wat het precies doet?
Beware of the Raping Zebra's
pi_93823367
quote:
1s.gif Op dinsdag 8 maart 2011 16:58 schreef netolk het volgende:
ik ben nu een beetje aan het klooien met threads, die kunnen zeker niet cross-platform geschreven worden?

ik heb nu dit simpele progje gemaakt

[ code verwijderd ]

Ik vroeg me af wat WINAPI doet, als ik het weg laat dan kan ie Dword (*)(void*) niet converteren naar Dword (*)(void*)... weet iemand wat het precies doet?
WINAPI vertelt de compiler hoe de functie argumenten krijgt en returnt en hoe de functie gelinkt moet worden en dergelijke, voor systeemfuncties zoals threads is dat anders dan hoe het standaard in C++ functioneert.
  dinsdag 8 maart 2011 @ 20:07:20 #97
67978 HenryHill
Fake it 'till you make it
pi_93829226
quote:
1s.gif Op dinsdag 8 maart 2011 16:58 schreef netolk het volgende:
Ik vroeg me af wat WINAPI doet, als ik het weg laat dan kan ie Dword (*)(void*) niet converteren naar Dword (*)(void*)... weet iemand wat het precies doet?
In grote lijnen - wat thabit zegt.

Hier stelt iemand precies dezelfde vraag, en die krijgt het volgende antwoord
"Someone has defined the WINAPI word in WinDef.h file like this: #define WINAPI __stdcall; you can find this file and definition on your computer. Therefore, WINAPI means just __stdcall, and now you have to look for this word in documentation. It provides certain features to your MyThreadFunction function, like: the function will clean the stack of arguments, and the arguments will be passed from right to left."

De verschillende calling conventions worden hier uitgelegd; de twee die in dit geval van belang zijn, zijn "cdecl" (de standaard C(++) conventie), en "stdcall" (de conventie die door de Windows API wordt gehanteerd).
Zoals je kunt lezen wordt bij "cdecl" verwacht dat de stack* opgeruimd wordt door de code die de functie aanroept, terwijl "stdcall" functies zelf de stack opruimen voordat ze retourneren. Je kunt je voorstellen dat je duidelijk moet afspreken welke conventie je aanhoudt, anders wordt de stack twee keer (of juist nooit) opgeruimd en heb je een groot probleem.

* De stack is een stuk geheugen dat zich letterlijk gedraagd als een stapel: je kunt er waardes bovenop stapelen en waardes van de bovenkant afhalen, maar niet ertussenuit. Een stack wordt voornamelijk gebruikt om, vlak voor een functieaanroep het returnadres (=de volgende opdracht na het uitvoeren van die functie) op te zetten, zodat de processor weet waar 'ie verder moet gaan als hij een return statement tegenkomt.
Echter, omdat een processor slechts een beperkt aantal registers (="variabelen") heeft, wordt de stack ook gebruikt om functie parameters op te zetten die dan door de functie zelf weer uitgelezen worden. In wezen worden dus returnadressen en functie parameters door elkaar heen op de stack opgeslagen - en dit werkt alleen zolang iedereen ervoor zorgt dat de stack altijd precies genoeg wordt opgeruimd.

Vandaar dat de compiler je een stdcall functie echt niet laat herdefineren als een cdecl functie. ;)
So this is how liberty dies... with thunderous applause.
Truth? What's so great about the truth? Try lying for a change, it's the currency of the world
  dinsdag 8 maart 2011 @ 21:01:27 #98
189216 netolk
maar dan andersom
pi_93832634
quote:
1s.gif Op dinsdag 8 maart 2011 20:07 schreef HenryHill het volgende:

[..]

In grote lijnen - wat thabit zegt.

Hier stelt iemand precies dezelfde vraag, en die krijgt het volgende antwoord
"Someone has defined the WINAPI word in WinDef.h file like this: #define WINAPI __stdcall; you can find this file and definition on your computer. Therefore, WINAPI means just __stdcall, and now you have to look for this word in documentation. It provides certain features to your MyThreadFunction function, like: the function will clean the stack of arguments, and the arguments will be passed from right to left."

De verschillende calling conventions worden hier uitgelegd; de twee die in dit geval van belang zijn, zijn "cdecl" (de standaard C(++) conventie), en "stdcall" (de conventie die door de Windows API wordt gehanteerd).
Zoals je kunt lezen wordt bij "cdecl" verwacht dat de stack* opgeruimd wordt door de code die de functie aanroept, terwijl "stdcall" functies zelf de stack opruimen voordat ze retourneren. Je kunt je voorstellen dat je duidelijk moet afspreken welke conventie je aanhoudt, anders wordt de stack twee keer (of juist nooit) opgeruimd en heb je een groot probleem.

* De stack is een stuk geheugen dat zich letterlijk gedraagd als een stapel: je kunt er waardes bovenop stapelen en waardes van de bovenkant afhalen, maar niet ertussenuit. Een stack wordt voornamelijk gebruikt om, vlak voor een functieaanroep het returnadres (=de volgende opdracht na het uitvoeren van die functie) op te zetten, zodat de processor weet waar 'ie verder moet gaan als hij een return statement tegenkomt.
Echter, omdat een processor slechts een beperkt aantal registers (="variabelen") heeft, wordt de stack ook gebruikt om functie parameters op te zetten die dan door de functie zelf weer uitgelezen worden. In wezen worden dus returnadressen en functie parameters door elkaar heen op de stack opgeslagen - en dit werkt alleen zolang iedereen ervoor zorgt dat de stack altijd precies genoeg wordt opgeruimd.

Vandaar dat de compiler je een stdcall functie echt niet laat herdefineren als een cdecl functie. ;)
ahh, ik snap :)
Beware of the Raping Zebra's
  donderdag 10 maart 2011 @ 16:28:55 #99
189216 netolk
maar dan andersom
pi_93910472
EDIT, al opgelost
Beware of the Raping Zebra's
  donderdag 10 maart 2011 @ 18:01:24 #100
189216 netolk
maar dan andersom
pi_93914667
vraagje hoe kan je parameters meegeven bij het creëren van treads?

ik heb dit stukje code (ik weet dat het niet werkt)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
unsigned long WINAPI Threader(void *Data){
    std::cout << "Threader\n";
    SOCKET Client = *(SOCKET*)(&Data);
    char Buffer[2] = {'1','2'};
    if((send(Client,Buffer,2,0)) == SOCKET_ERROR)
        throw Error("Socket error while sending!");
    
    if(Client != INVALID_SOCKET)
        closesocket(Client);
}

int main(){
     SOCKET hClient;

     // socket code
     HANDLE Thread = CreateThread(0,0,Threader,0,0,0);
     Sleep(5000);
     CloseHandle(Thread);
}
ik zou hClient nu graag willen mee geven aan de nieuwe thread zodat ik voor elke connectie een nieuwe thread heb...

ow enne de HANDLE moet open blijven tot de thread klaar is toch?
Beware of the Raping Zebra's
abonnement Unibet Coolblue Bitvavo
Forum Opties
Forumhop:
Hop naar:
(afkorting, bv 'KLB')