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: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.)
kan het niet allebei? Dus ofwel dat je doet:quote: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 ]
| 1 | for (size_t iii = 0; iii < 10; ++iii) |
| 1 | for (size_t iii = 0; iii <= 10; iii++) |
Ik heb deze *&pnGetallen gedaan, zodat ik de Array pnGetallen kon bewerken in de void? Moet dat anders/doe ik het niet goed?quote: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.
Oke, bedankt voor de informatie, dat wist ik niet.quote: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.
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: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.
Die is volgens mij nodig voor de compiler die ik gebruik (Microsoft Visual C++ 2010 Express)quote: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?
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:Op zondag 30 januari 2011 16:58 schreef GS42 het volgende:
Voor invoercontrole kan je het uitlees-statement evalueren:
[ code verwijderd ]
Zeker niet, altijd goed om verbeterpunten te zien. Bedankt.quote:
dat klopt idd je kan beide methode gebruiken...quote: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:
Dit kan je zelf heel eenvoudig checken hè...quote:Overigens dacht ik dat bij ++iii je nooit iii = 0 krijgt?
| 1 2 3 4 | #include <iostream> for(int i = 0; i < 10; ++i){ std::cout << i << std::endl; } |
Je moet delete altijd aanroepen anders kan je geheugenleaks krijgenquote: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?
compiled die niet ook gewoon zonder die include?quote:Die is volgens mij nodig voor de compiler die ik gebruik (Microsoft Visual C++ 2010 Express)
Oke, ik zal dus wanneer ik ze nodig heb in statements ++i gebruiken. Bedankt.quote: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.
Size_t past zich dan ook aan aan de invoer? Want waarom zou je dan überhaupt nog ooit int gebruiken?quote: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
Oke, bedankt. Gedaan.quote:Op zondag 30 januari 2011 17:29 schreef netolk het volgende:
Je moet delete altijd aanroepen anders kan je geheugenleaks krijgen
Nee, ik heb het geprobeerd, maar ik krijg dan de volgende error:quote:Op zondag 30 januari 2011 17:29 schreef netolk het volgende:
compiled die niet ook gewoon zonder die include?
| 1 2 3 4 | size_t nAantal; AantalGetallen(nAantal); double *pnGetallen = new double[nAantal]; |
ja, idd maar waarom maak je je AantalGetallen functie niet gewoon zo?quote: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 ]
| 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; } |
| 1 | double *pnGetallen = new double[AantalGetallen()]; |
Sterker nog:quote: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.
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.quote:Op zondag 30 januari 2011 18:19 schreef thabit het volgende:
Het lijkt me toch dat een compiler dat nog wel moet kunnen optimaliseren.
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:Je moet delete altijd aanroepen anders kan je geheugenleaks krijgen
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.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?
Zal wel komen doordat printf een int als returnwaarde heeft en die worden doorgaans in eax doorgegeven.quote: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.
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.quote: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.
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.quote: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 ]
en wat is het probleem dat je een functie vaker gebruikt?quote: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.
| 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; } |
| 1 | size_t AantalGetallen = AantalGetallen() |
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)quote: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?
ahh, ik snapquote: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.
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:Ik heb deze *&pnGetallen gedaan, zodat ik de Array pnGetallen kon bewerken in de void? Moet dat anders/doe ik het niet goed?
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.quote:Size_t past zich dan ook aan aan de invoer? Want waarom zou je dan überhaupt nog ooit int gebruiken?
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.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)
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.quote: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.
[..]
Maar een size_t 'reserveert' dus eigenlijk dubbel zoveel ruimte als een int? Of is dat alleen omdat het niet negatief kan gaan?quote: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...
| 1 2 | #include <math.h> if (isnan('test')); |
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: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.
| 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 |
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:Maar een size_t 'reserveert' dus eigenlijk dubbel zoveel ruimte als een int?
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.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
Google is je vriend...quote:Op maandag 31 januari 2011 07:05 schreef Jeroentk het volgende:
[ code verwijderd ]
Hoe kan ik hem wel werkende krijgen?
Je kan beter std::isalpha gebruiken om te kijken of het een teken is deze functie staat gedeclareerd in de <cctype> headerquote: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..
| Forum Opties | |
|---|---|
| Forumhop: | |
| Hop naar: | |