abonnement Unibet Coolblue Bitvavo
  vrijdag 28 januari 2011 @ 15:11:18 #1
189216 netolk
maar dan andersom
pi_91990814

Nu mét gratis web-support!

Als je vragen hebt over C of C++, dan zit je hier goed met een (hopelijk later grote) kliek guru's.
Beperk je vragen niet tot "hij doet het niet" of "hij geeft een fout" - onze glazen bol is kapot en we willen graag van je weten wát er niet lukt en wélke foutmelding je precies krijgt. ;)

En onthoud: lieve modjes maken dit topic centraal! O+

Vorige delen:
[C(++)] voor dummies - Deel 1
[C(++)] voor dummies - Deel 2

:? FAQ :?

:? Ik wil beginnen met C/C++, wat voor IDE is het beste voor mij?
Dat ligt eraan. Als je alléén voor MS Windows wilt gaan developen, is Visual Studio de beste optie. Deze kun je bovendien als je student bent via Microsoft DreamSpark of MSDN Academic Alliance gratis downloaden. :)
Wil je echter cross-platform (dat wil zeggen: voor b.v. Windows én Linux, of Linux én Mac) gaan developen, dan zijn Dev-C++ en Code::Blocks de beste optie voor C++. Eclipse (ook voor C) en NetBeans zijn ook goede keuzes, alleen zijn deze meer op Java gericht. Een ander IDE, van Nokia's hand, is Qt Creator. Dit IDE maakt gebruik van het Qt-framework, een set van functies, types, variabelen etc. om programmeren makkelijker te maken. Dit framework is cross-platform. :)

:? Hoe gebruik ik x/wat houdt y in?
Stop! Voor vragen hoe je bepaalde ingebouwde functies, types of classes gebruikt kun je de C referentie of de C++ referentie gebruiken. Hier staat alles in wat je nodig hebt. :)

:? Wat is het verschil tussen C en C++?
C++ is, eenvoudig gezegd, een nieuwere versie van C (vandaar ook de naam, C++ wil zeggen: verhoog de waarde van C met 1). Het biedt onder andere betere klasse-ondersteuning en verschillende nieuwe types, zoals vectors en maps, om er maar een paar te noemen.
Als je wilt beginnen met leren, is C++ beter, want C wordt eigenlijk niet vaak meer gebruikt.

:? Wat is het Windows SDK?
Het Windows SDK is een set van functies, gemaakt door Microsoft, om het programmeren voor Windows te vereenvoudigen.
Als je ervoor kiest het Windows SDK te gebruiken, houd er dan rekening mee dat je applicatie Windows-only wordt!
Je kunt de laatste versie hier vinden ter download. :)

Handige links:

Referenties en tutorials:
Leer C en/of C++ (engels)
Leer programmeren met het Windows SDK (engels)
Info over het Windows SDK (engels)

Deze OP vind je hier.
Beware of the Raping Zebra's
  vrijdag 28 januari 2011 @ 15:32:36 #2
254493 Trollface.
gr rob fruithof, groningencity
pi_91991775
1
2
3
4
5
6
#include <cstdio>

int main() {
    printf("%c%c%c\n", 'T', 'V', 'P');
    return 0;
}
★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_91993326
Tvp* tvp = new Tvp();
  vrijdag 28 januari 2011 @ 18:10:44 #4
189216 netolk
maar dan andersom
pi_91999263
zou iemand kunnen uitleggen waarom het volgende niet werkt?

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
#include <iostream>
#include <vector>
class Master{
    protected:
        unsigned short i;
    public:
        Master():i(5){}
        virtual unsigned short get(){return 9;}
};
class Sub:public Master{
    public:
        Sub(){i=8;}
        unsigned short get(){return i;}
};

int main(){
    Master *M_ptr;
    
    Sub mySub;
    
    M_ptr = &mySub;
    
    Sub *S_ptr = dynamic_cast<Sub*>(M_ptr);
    if(S_ptr) // hier werkt het
        std::cout << "Works\n";
    else
        std::cerr << "FAIL\n";
    
    std::vector<Master> myVec;
    myVec.push_back(Sub());
    Master *vec_ptr = &myVec[0];
    Sub *S_ptr2 = dynamic_cast<Sub*>(vec_ptr);
    if(S_ptr2) // hier faalt het
        std::cout << "Works\n";
    else
        std::cout << "FAIL\n";
    
    return 0;
}

waarom werkt dynamic_cast niet als er een pointer naar een vecor wijst?
Beware of the Raping Zebra's
pi_92005650
Een van de problemen is dat een object van base class niet per se dezelfde geheugenruimte inneemt als een object van een derived class. Een dynamic cast werkt in principe alleen met pointers en references. Je definieert een vector van Masters, daar kun je niet zo een twee drie een Sub in stoppen want daar wordt dan gebruik gemaakt van slicing ipv polymorfisme: de Sub is niet echt een Sub maar wordt geconverteerd naar een Master. Met een vector<Master*> of een vector<Master&> gok ik dat je meer succes hebt.

Moraal van het verhaal: value-typed class objecten zijn gewoon zwaar kut. Een van de vele designfoutenblunders in C++ om zoiets toe te laten.
pi_92020859
Nog een probleem met je code is dat je de base class niet polymorf hebt gemaakt. Er moet tenminste 1 virtual methode in zitten; het is sowieso raadzaam om de destructor virtual te maken. Dat classes niet automatisch polymorf zijn is overigens ook een designflater.
  zaterdag 29 januari 2011 @ 12:18:41 #7
189216 netolk
maar dan andersom
pi_92034038
quote:
1s.gif Op zaterdag 29 januari 2011 00:15 schreef thabit het volgende:
Nog een probleem met je code is dat je de base class niet polymorf hebt gemaakt. Er moet tenminste 1 virtual methode in zitten; het is sowieso raadzaam om de destructor virtual te maken. Dat classes niet automatisch polymorf zijn is overigens ook een designflater.
um, die destructor klopt idd maar er is toch een virtual methode?

virtual unsigned short get(){return 9;}
Beware of the Raping Zebra's
pi_92034278
quote:
1s.gif Op zaterdag 29 januari 2011 12:18 schreef netolk het volgende:

[..]

um, die destructor klopt idd maar er is toch een virtual methode?

virtual unsigned short get(){return 9;}
O ja, overheen gelezen. Maar dan nog moet je geen polymorfisme toepassen op value-typed objecten.
  zaterdag 29 januari 2011 @ 17:41:29 #9
189216 netolk
maar dan andersom
pi_92046703
hmm... ik krijg behoorlijk wat compilatie fouten bij het declareren van std::vector<Master&> iets van
1mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/c++/3.4.5/ext/new_allocator.h:52: error: forming pointer to reference type `Master&'

en nog veel meer...

maar std::vector<Master*> werkt wel :)
Beware of the Raping Zebra's
pi_92047159
Pas wel een beetje op dat je geen pointers naar ongedefinieerde stukken geheugen laat wijzen.
  zaterdag 29 januari 2011 @ 18:01:56 #11
189216 netolk
maar dan andersom
pi_92047496
quote:
1s.gif Op zaterdag 29 januari 2011 17:52 schreef thabit het volgende:
Pas wel een beetje op dat je geen pointers naar ongedefinieerde stukken geheugen laat wijzen.
Ja, ik heb het zo bedacht:
[code]
Master *M_ptr = new Sub();
myVec.push_back(M_ptr);

en dan de destructor v.e class waar Master in zit:
~Class{
for(int i = 0; i < myVec.size(); i++){
delete myVec[i];
}
myVec.clear();
}

nog een vraagje, roept een vector bij destruction ook de destructor van het type aan? dus zegmaar std::vector<int> roept die dan ook ~int() aan?
Beware of the Raping Zebra's
pi_92048298
De destructor van de vector roept de destructors van de objecten aan die ruimte innemen in het stuk heap dat de vector zelf gealloceerd heeft. Dus niet als het pointers zijn. Dingen die je zelf met new aanmaakt moet je ook zelf deleten.

Een int heeft trouwens niet echt een destructor je kunt (denk ik) wel ~int() aanroepen, maar dat is puur om de syntax consistent de houden, de instructie doet helemaal niets.
pi_92050027
quote:
1s.gif Op zaterdag 29 januari 2011 18:01 schreef netolk het volgende:

nog een vraagje, roept een vector bij destruction ook de destructor van het type aan? dus zegmaar std::vector<int> roept die dan ook ~int() aan?
Ja, als er een destructor bestaat zal deze aangeroepen worden. Dit geldt echter alleen als je classes (of base-types) in de vector opslaat. Als je std::vector<X*> gebruikt, zal de X::~X() destructor niet automatisch aangeroepen worden. Daarom wordt het ook als niet netjes gezien om pointers in containers op te slaan.

Edit: Oh, ik had het bovenstaande antwoord gemist.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92050256
Niks mis met pointers in containers, mits je duidelijk aan elke new een delete koppelt.
pi_92050496
quote:
1s.gif Op zaterdag 29 januari 2011 19:19 schreef thabit het volgende:
Niks mis met pointers in containers, mits je duidelijk aan elke new een delete koppelt.
Gaat tegen het idee van de stl containers in, namelijk dat de container de eigenaar van de data is. Netter zou zijn de pointer in een class te wikkelen. Dit is echter erg afhankelijk van smaak en stijl, en iedereen weet dat daarover prima te twisten valt. :)
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92050860
Als je dat soort design patterns al moet gaan toepassen, dan kun je beter op een programmeertaal overstappen waar ze helemaal niet nodig zijn. :).
pi_92051592
1
2
long long troll[2]={7308604865845225588LL, 0};
printf("%s\n", (char *)troll);

*O*
  zaterdag 29 januari 2011 @ 20:38:45 #18
85514 ralfie
!Yvan eht nioj
pi_92053330
quote:
1s.gif Op zaterdag 29 januari 2011 19:25 schreef GS42 het volgende:

[..]

Gaat tegen het idee van de stl containers in, namelijk dat de container de eigenaar van de data is. Netter zou zijn de pointer in een class te wikkelen. Dit is echter erg afhankelijk van smaak en stijl, en iedereen weet dat daarover prima te twisten valt. :)
Mensen kiezen vaak voor c++ vanwege de snelheid, niet omdat de taal zo lekker netjes weg te tikken is... Daarvoor zijn veel geschiktere talen (met garbage collector etc)
  zaterdag 29 januari 2011 @ 21:05:17 #19
189216 netolk
maar dan andersom
pi_92054468
die ~int() was even een dummie voor de vraag, maar ik heb dus zo'n vector<Player> waar maar 1 player instaat en toch word de destructor 2x aangeroepen...
quote:
1s.gif Op zaterdag 29 januari 2011 19:14 schreef GS42 het volgende:

[..]

Ja, als er een destructor bestaat zal deze aangeroepen worden. Dit geldt echter alleen als je classes (of base-types) in de vector opslaat. Als je std::vector<X*> gebruikt, zal de X::~X() destructor niet automatisch aangeroepen worden. Daarom wordt het ook als niet netjes gezien om pointers in containers op te slaan.

Edit: Oh, ik had het bovenstaande antwoord gemist.
tja ik kan het ook in een matrix / array zetten maar dat is weer gekut als je er data aan toe wilt voegen, dan kan dat wel met classes die dan naar het volgende object wijzen maar waarom zou ik dat doen als ik ook gewoon vector<int*> kan gebruiken? en het dan via een destructor kan laten verwijderen
Beware of the Raping Zebra's
  zaterdag 29 januari 2011 @ 21:10:57 #20
189216 netolk
maar dan andersom
pi_92054675
code bij mijn vorige post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <vector>
class Temp{
    int i;
    public:
        Temp(){}
        ~Temp(){
            std::cout << "Destructor\n";
        }
};
int main(){
    std::vector<Temp> myvec;
    myvec.push_back(Temp());
    
    return 0;
}
output:
1
2
Destructor
Destructor

en als ik de push_back(Temp()) weglaat roept ie de destructor helemaal niet aan, maar waarom word de destructor 2x aangeroepen als er maar 1 object is?
Beware of the Raping Zebra's
pi_92054691


[ Bericht 100% gewijzigd door thabit op 29-01-2011 21:11:28 (was te snel) ]
  zaterdag 29 januari 2011 @ 21:11:40 #22
189216 netolk
maar dan andersom
pi_92054709
quote:
1s.gif Op zaterdag 29 januari 2011 21:11 schreef thabit het volgende:

:P

of ik te laat
Beware of the Raping Zebra's
pi_92054815
quote:
1s.gif Op zaterdag 29 januari 2011 21:05 schreef netolk het volgende:
die ~int() was even een dummie voor de vraag, maar ik heb dus zo'n vector<Player> waar maar 1 player instaat en toch word de destructor 2x aangeroepen...
Dat is mogelijk en niets om je zorgen over te maken. Bij het kopieren naar de vector is het mogelijk dat er een kopie gemaakt moet worden en dus voor het oude object een destructor aangeroepen wordt. (Sterker nog, aan de code van je kun je zien dat de compiler dit moet doen.) Ook moet een vector zichzelf vaak in geheugen verplaatsen waarbij het kopieen van objecten moet maken en de destructor kan gebruiken, evenals de copy constructor van de klasse (maar dit zou bij 1 object niet moeten gebeuren).

quote:
tja ik kan het ook in een matrix / array zetten maar dat is weer gekut als je er data aan toe wilt voegen, dan kan dat wel met classes die dan naar het volgende object wijzen maar waarom zou ik dat doen als ik ook gewoon vector<int*> kan gebruiken? en het dan via een destructor kan laten verwijderen
Bijvoorbeeld in het vorige voorbeeld. Als je de pointer in een klasse wikkelt die de geheugenafhandeling doet, hoef je er op dit moment niet meer aan te denken. Anders moet je voor elke klasse die een vector<int*> gebruikt, een destructor, copy constructor en eventueel een operator=() schrijven, terwijl een vector<IntPointer> dit zelf op zou kunnen lossen. Maar opnieuw: dit heeft veel met persoonlijke stijl te maken.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92054972
quote:
1s.gif Op zaterdag 29 januari 2011 21:10 schreef netolk het volgende:
code bij mijn vorige post

[ code verwijderd ]

output:

[ code verwijderd ]

en als ik de push_back(Temp()) weglaat roept ie de destructor helemaal niet aan, maar waarom word de destructor 2x aangeroepen als er maar 1 object is?
Omdat er 2 Temp-objecten zijn. ;). Zie je waarom?
  zaterdag 29 januari 2011 @ 21:19:14 #25
189216 netolk
maar dan andersom
pi_92055025
quote:
1s.gif Op zaterdag 29 januari 2011 21:17 schreef thabit het volgende:

[..]

Omdat er 2 Temp-objecten zijn. ;). Zie je waarom?
JA, ik zie het nu :) tenminste, omdat ie een copy maakt van de Temp() die ik declareer in de push_back() toch?
Beware of the Raping Zebra's
pi_92055059
Juist. Het zoveelste nadeel van value-typed objecten.
  zaterdag 29 januari 2011 @ 21:21:14 #27
189216 netolk
maar dan andersom
pi_92055095
quote:
14s.gif Op zaterdag 29 januari 2011 21:20 schreef thabit het volgende:
Juist. Het zoveelste nadeel van value-typed objecten.
Dit soort dingen zijn niet te voorkomen zeker?
Beware of the Raping Zebra's
pi_92055270
quote:
1s.gif Op zaterdag 29 januari 2011 21:21 schreef netolk het volgende:

[..]

Dit soort dingen zijn niet te voorkomen zeker?
Als je per se wilt dat je vector geen pointers bevat (ik lees net dat references niet mogen), dan vrees ik dat dat lastig gaat worden ja.
pi_92055388
quote:
1s.gif Op zaterdag 29 januari 2011 21:21 schreef netolk het volgende:

[..]

Dit soort dingen zijn niet te voorkomen zeker?
Als je een c++0x-compatible compiler gebruikt, dan moet je dit kunnen voorkomen door met std::move() een r-value-reference mee te geven aan de push_back. Dan wordt er geen kopie gemaakt. De std::vector hoort dit te ondersteunen.
"Slechts diegene mag slopen die iets beters kan bouwen."
  zaterdag 29 januari 2011 @ 21:34:20 #30
189216 netolk
maar dan andersom
pi_92055510
hmm, die pointers in een vector zijn ook verre van ideaal want ik heb een class waar zo'n vector<*int> in staat alleen staat die class zelf ook weer in een vector dus word ie gekopieerd wat er voor zorgt dat de destructor word aangeroepen zodat de pointer geen betekenis meer heeft...

dus ik ga het dan nu maar op de "nette" manier doen (GS42 ook weer blij :P)

PS. *int is nog steeds dummie
Beware of the Raping Zebra's
pi_92055680
In de destructor van die class kun je toch gewoon een delete over die vector heen lussen?
pi_92055856
quote:
1s.gif Op zaterdag 29 januari 2011 21:34 schreef netolk het volgende:

dus ik ga het dan nu maar op de "nette" manier doen (GS42 ook weer blij :P)

Dan moet je misschien ook even kijken naar de unique- en shared-pointer (c++0x): http://www.icce.rug.nl/documents/cplusplus/cplusplus18.html#l286
Of als je op een oudere compiler zit: http://www.cplusplus.com/reference/std/memory/auto_ptr/
(EDIT: Nu ik de stof nog eens nalees, zie ik dat je de auto_prt niet moet gebruiken in containers (zie eerste link).

Dat kan je weer een klasse schrijven schelen. :)

[ Bericht 6% gewijzigd door GS42 op 29-01-2011 22:18:07 ]
"Slechts diegene mag slopen die iets beters kan bouwen."
  zaterdag 29 januari 2011 @ 21:50:14 #33
189216 netolk
maar dan andersom
pi_92056036
hmm... ik had een simpele struct geschreven

1
2
3
4
5
struct T_sptr{
   Temp *_ptr
   T_sptr(Temp *pointer):_ptr(pointer){}
   ~T_sptr(){delete _ptr; _ptr=0;}
};

alleen hiermee geeft het nog eerder een runtime fout...
Beware of the Raping Zebra's
pi_92056866
quote:
1s.gif Op zaterdag 29 januari 2011 21:50 schreef netolk het volgende:
hmm... ik had een simpele struct geschreven

[ code verwijderd ]

alleen hiermee geeft het nog eerder een runtime fout...
Waar gaat wat dan precies fout?
pi_92056873
quote:
1s.gif Op zaterdag 29 januari 2011 21:50 schreef netolk het volgende:
hmm... ik had een simpele struct geschreven

alleen hiermee geeft het nog eerder een runtime fout...
Het is ook wat te kort door de bocht voor een pointer class. Als deze struct gekopierd wordt, wordt de _ptr by value gekopierd. Dan wordt het oude object vernietigd. Oftewel: het nieuwe object verwijst naar iets wat niet meer bestaat.
Als je een eigen pointer class wilt schrijven, moet je denken aan de copy constructor, destructor, operator= en eventueel de operator* en operator->. Daarom zijn de stl-pointers ook erg handig:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <vector>
#include <memory>

int main() {

    std::vector< std::unique_ptr<int> > pvect;
    
    for (size_t idx = 0; idx < 10; ++idx)
        pvect.push_back(std::unique_ptr<int>(new int(42)));
        
    std::cout << "Adding done." << std::endl;

    for (size_t idx = 0; idx < 10; ++idx)
        std::cout << *pvect[idx] << ' ';
}

Let wel dat je compileert met -std=c++0x.
"Slechts diegene mag slopen die iets beters kan bouwen."
  zaterdag 29 januari 2011 @ 22:16:20 #36
189216 netolk
maar dan andersom
pi_92057201
quote:
1s.gif Op zaterdag 29 januari 2011 22:08 schreef GS42 het volgende:

[..]

Het is ook wat te kort door de bocht voor een pointer class. Als deze struct gekopierd wordt, wordt de _ptr by value gekopierd. Dan wordt het oude object vernietigd. Oftewel: het nieuwe object verwijst naar iets wat niet meer bestaat.
Als je een eigen pointer class wilt schrijven, moet je denken aan de copy constructor, destructor, operator= en eventueel de operator* en operator->. Daarom zijn de stl-pointers ook erg handig:

[ code verwijderd ]

Let wel dat je compileert met -std=c++0x.
owja, dan hou ik het zelfde probleem natuurlijk |:(

en als ik nou eens in plaats van een vector een linked list maak?
of is dat moeilijk te realiseren? Ik heb nog nooit zo iets gemaakt namelijk

maar die unique pointer die maakt dan dus een nieuw opject aan als het gekopieerd word?
Beware of the Raping Zebra's
pi_92057232
quote:
1s.gif Op zaterdag 29 januari 2011 22:16 schreef netolk het volgende:

maar die unique pointer die maakt dan dus een nieuw opject aan als het gekopieerd word?
Sowieso wordt een nieuw object gemaakt, de unique_pointer is namelijk een object. Voor hetgene waar de ptr naar wijst hoeft dit echter niet te gelden. Als het mogelijk is, wordt de move constructor gebruikt waardoor dus geen deep copy nodig is. Dat is hier na te lezen.

Ik verwacht niet dat in een vector kopieen worden gemaakt. Het overzetten naar een linked list hoeft niet moeilijk te zijn, je pakt bijvoorbeeld een list<> container. Maar ik denk niet dat het nodig is in dit geval.

(Het lijkt ondertussen wel alsof ik reclame maak voor de C++ Annotations. ;))


[ Bericht 67% gewijzigd door GS42 op 29-01-2011 22:29:15 ]
"Slechts diegene mag slopen die iets beters kan bouwen."
  zaterdag 29 januari 2011 @ 22:37:56 #38
189216 netolk
maar dan andersom
pi_92058079
quote:
1s.gif Op zaterdag 29 januari 2011 22:16 schreef GS42 het volgende:

[..]

Sowieso wordt een nieuw object gemaakt, de unique_pointer is namelijk een object. Voor hetgene waar de ptr naar wijst hoeft dit echter niet te gelden. Als het mogelijk is, wordt de move constructor gebruikt waardoor dus geen deep copy nodig is. Dat is hier na te lezen.

Ik verwacht niet dat in een vector kopieen worden gemaakt. Het overzetten naar een linked list hoeft niet moeilijk te zijn, je pakt bijvoorbeeld een list<> container. Maar ik denk niet dat het nodig is in dit geval.

(Het lijkt ondertussen wel alsof ik reclame maak voor de C++ Annotations. ;))

ik gebruik de C++ compiler van mingw (32-bit) maar ik kan nergens vinden of het dat -std=c++0x ondersteund... of hoe ik het aan de compiler moet mee geven, heeft iemand hier ervaring mee?
Beware of the Raping Zebra's
pi_92058338
quote:
1s.gif Op zaterdag 29 januari 2011 22:37 schreef netolk het volgende:

ik gebruik de C++ compiler van mingw (32-bit) maar ik kan nergens vinden of het dat -std=c++0x ondersteund... of hoe ik het aan de compiler moet mee geven, heeft iemand hier ervaring mee?
Als je een nieuwe versie gebruikt van het MinGW pakket, dan wel. Je compiler-versie vind je zo: g++ -v
En de optie kan je uiteraard op dezelfde manier meegeven. Ik zit op hetzelfde systeem (GCC 4.5.0) en compileer zo: g++ -Wall -std=c++0x -o main -enable-auto-import -O3 main.cc
"Slechts diegene mag slopen die iets beters kan bouwen."
  zondag 30 januari 2011 @ 09:37:53 #40
189216 netolk
maar dan andersom
pi_92068292
quote:
1s.gif Op zaterdag 29 januari 2011 22:44 schreef GS42 het volgende:

[..]

Als je een nieuwe versie gebruikt van het MinGW pakket, dan wel. Je compiler-versie vind je zo: g++ -v
En de optie kan je uiteraard op dezelfde manier meegeven. Ik zit op hetzelfde systeem (GCC 4.5.0) en compileer zo: g++ -Wall -std=c++0x -o main -enable-auto-import -O3 main.cc
waarvoor is -wall en auto-import importeert dat alle files in de map waar main staat?

ow hehe ik moet mn compiler maar eens even gaan updaten XD

zit op versie 3.4.5 :'(

[ Bericht 5% gewijzigd door netolk op 30-01-2011 09:49:11 ]
Beware of the Raping Zebra's
  zondag 30 januari 2011 @ 10:10:21 #41
189216 netolk
maar dan andersom
pi_92068622
kut, nu mis ik libgmp-10.dll ... terwijl die wel gewoon op mn pc staat...
Beware of the Raping Zebra's
pi_92072000
quote:
1s.gif Op zondag 30 januari 2011 09:37 schreef netolk het volgende:

[..]

waarvoor is -wall en auto-import importeert dat alle files in de map waar main staat?
De -Wall is een redleijk veelvoorkomende optie die alle warnings (Warnings ALL: Wall) aanzet, waardoor je tijdens het compileren melding krijgt van legale maar mogelijk gevaarlijke dingen (zoals statements die niets doen of het vergelijken van signed met unsigned waarden).
De enable-auto-import heb ik eigenlijk alleen voor MinGW hoeven gebruiken (en dus niet onder Linux), maar zorgt ervoor dat een waarschuwing over het importeren van dll's niet in beeld komt. Volgens mij is dit Windows- (en misschien zelfs MinGW-) specifiek.

quote:
kut, nu mis ik libgmp-10.dll ... terwijl die wel gewoon op mn pc staat...
Ja, het installeren van MinGW gaat bij mij ook (schijnbaar) willekeurig goed of fout. Al het oude eerst verwijderen (of verplaatsen, ik heb c:/mingw en c:/mingw_old) en dan proberen de getting started te volgen. Toen het eenmaal goed gelukt was, heb ik de map 'mingw' gekopieerd zodat ik deze bij een nieuwe installatie gewoon op een computer kan plakken, zodat ik niet dat hele installatieproces door hoef te lopen. Als het je niet lukt, kan ik je misschien mijn installatie-map (~250mb) wel doorspelen.
"Slechts diegene mag slopen die iets beters kan bouwen."
pi_92082065
Goedemiddag,

Twee dagen geleden ben ik begonnen met het leren van C++. Heb verder eigenlijk geen programmeerervaring, maar het leek me wel interessant. Mijn eerste programma heb ik nu gemaakt en het is enigszins gelukt. Het programma vraagt eerst om hoeveel getallen je bij elkaar wilt optellen, vraagt daarna om de getallen, stopt ze in een array en geeft vervolgens het antwoord. Helaas zit er wel een grote, potentiële error in, en dat is dat wanneer je bij het invoeren van de getallen geen getal invoert. Hierdoor crash hij (natuurlijk), maar ik weet niet hoe ik dmv bijv. een if of do..while die eruit kan vissen. Weten jullie hoe dat moet?

Verder heb ik zojuist geprobeerd om de ingevoerde getallen doubles ipv integers te maken. Dat lukte wel, maar steeds geeft hij op het einde een error. Hij heeft dan al wel de laatste functie uitgevoerd. Ik heb hieronder eerst de add.cpp gepost, en daarna de main.cpp.

SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
Verder heb ik ervoor gekozen om zoveel kleine functies te gebruiken, omdat ik het dan makkelijker kan uitbreiden en het overzichtelijker blijft.
Als iemand tips heeft over hoe ik mijn programma op wat voor gebied dan ook kan verbeteren zou ik het graag horen.
pi_92083168
quote:
1s.gif Op zondag 30 januari 2011 16:14 schreef Jeroentk het volgende:
Goedemiddag,

Twee dagen geleden ben ik begonnen met het leren van C++. Heb verder eigenlijk geen programmeerervaring, maar het leek me wel interessant. Mijn eerste programma heb ik nu gemaakt en het is enigszins gelukt. Het programma vraagt eerst om hoeveel getallen je bij elkaar wilt optellen, vraagt daarna om de getallen, stopt ze in een array en geeft vervolgens het antwoord. Helaas zit er wel een grote, potentiële error in, en dat is dat wanneer je bij het invoeren van de getallen geen getal invoert. Hierdoor crash hij (natuurlijk), maar ik weet niet hoe ik dmv bijv. een if of do..while die eruit kan vissen. Weten jullie hoe dat moet?

Verder heb ik zojuist geprobeerd om de ingevoerde getallen doubles ipv integers te maken. Dat lukte wel, maar steeds geeft hij op het einde een error. Hij heeft dan al wel de laatste functie uitgevoerd. Ik heb hieronder eerst de add.cpp gepost, en daarna de main.cpp.

SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
Verder heb ik ervoor gekozen om zoveel kleine functies te gebruiken, omdat ik het dan makkelijker kan uitbreiden en het overzichtelijker blijft.
Als iemand tips heeft over hoe ik mijn programma op wat voor gebied dan ook kan verbeteren zou ik het graag horen.
Kun je iets specifieker zijn in de foutmeldingen etc?

Een std::vector kan handig zijn als je met arrays wilt werken van variabele lengte.

Verder kun je in plaats van met references als argumenten te werken, de berekende waarde ook als uitkomst meegeven dus, bijvoorbeeld, int AantalGetallen() ipv void AantalGetallen(int &nAantal).
pi_92084295
quote:
Als iemand tips heeft over hoe ik mijn programma op wat voor gebied dan ook kan verbeteren zou ik het graag horen.
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.)

Je 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:

1for (size_t idx = 0; idx < 10; ++idx)

Ik weet niet of het een typefout betreft, maar de declaratie

1void Vraag(double *&pnGetallen, int nAantal)

...is raar, omdat je een referentie naar een pointer doorgeeft. Ik kan me niet voorstellen dat dat de bedoeling was.

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.

Iets gevaarlijks wat je doet is het volgende:

1double *pnGetallen = new double;

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:

1
2
double d = 3.14;
double *d_ptr = &d;

Pas als je werkelijk geheugen dynamisch wilt alloceren, gebruik je de operator new.

Ik ken de headerfile "stdafx.h" ook niet: weet je zeker dat je die nodig hebt?

Voor invoercontrole kan je het uitlees-statement evalueren:

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

int main() {

    size_t input;
    std::cout << "Voer een (positief) getal in: ";
    if (std::cin >> input)
        std::cout << "Uw getal is " << input << '\n';
    else
        std::cout << "Verkeerde invoer.\n";
}

Hopelijk heb ik je niet afgeschrikt. :)

[ Bericht 0% gewijzigd door GS42 op 30-01-2011 17:04:15 ]
"Slechts diegene mag slopen die iets beters kan bouwen."
  zondag 30 januari 2011 @ 16:59:47 #46
189216 netolk
maar dan andersom
pi_92084343
quote:
1s.gif Op zondag 30 januari 2011 12:31 schreef GS42 het volgende:

[..]

De -Wall is een redleijk veelvoorkomende optie die alle warnings (Warnings ALL: Wall) aanzet, waardoor je tijdens het compileren melding krijgt van legale maar mogelijk gevaarlijke dingen (zoals statements die niets doen of het vergelijken van signed met unsigned waarden).
De enable-auto-import heb ik eigenlijk alleen voor MinGW hoeven gebruiken (en dus niet onder Linux), maar zorgt ervoor dat een waarschuwing over het importeren van dll's niet in beeld komt. Volgens mij is dit Windows- (en misschien zelfs MinGW-) specifiek.

[..]

Ja, het installeren van MinGW gaat bij mij ook (schijnbaar) willekeurig goed of fout. Al het oude eerst verwijderen (of verplaatsen, ik heb c:/mingw en c:/mingw_old) en dan proberen de getting started te volgen. Toen het eenmaal goed gelukt was, heb ik de map 'mingw' gekopieerd zodat ik deze bij een nieuwe installatie gewoon op een computer kan plakken, zodat ik niet dat hele installatieproces door hoef te lopen. Als het je niet lukt, kan ik je misschien mijn installatie-map (~250mb) wel doorspelen.
hmm die -wall deed ie hoe dan ook altijd al bij mij, maar krijg die mingw echt niet reïnstalleerd... :( eens even kijken hoe het met manual install gaat
Beware of the Raping Zebra's
pi_92084599
De error wanneer je geen getal invoert:
SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
De error die ik kreeg nadat ik van enkele ints doubles had gemaakt (zodat ik ook 0.66 + 0.33 kon doen etc.):
SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
Verder leek het me juist handig om voids te gebruiken, zodat ik geen hele functies in functies hoefde in te voeren? (zoals GeefResultaat(Vraag(AantalGetallen(), AantalGetallen(), Bereken(Vraag(AantalGetallen), AantalGetallen(), ... etc.
pi_92084956
De plaatjes doen het niet bij mij.
  zondag 30 januari 2011 @ 17:14:08 #49
189216 netolk
maar dan andersom
pi_92085005
quote:
1s.gif Op zondag 30 januari 2011 17:13 schreef thabit het volgende:
Plaatjes doen het niet bij mij.
bij mij ook niet...

@GS42, handmatig installeren is al helemaal niet te doen.. :( zou ik jou mingw mapje mogen hebben?
Beware of the Raping Zebra's
pi_92085094
quote:
1s.gif Op zondag 30 januari 2011 17:05 schreef Jeroentk het volgende:
De error wanneer je geen getal invoert:
SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
De error die ik kreeg nadat ik van enkele ints doubles had gemaakt (zodat ik ook 0.66 + 0.33 kon doen etc.):
SPOILER
Om spoilers te kunnen lezen moet je zijn ingelogd. Je moet je daarvoor eerst gratis Registreren. Ook kun je spoilers niet lezen als je een ban hebt.
Verder leek het me juist handig om voids te gebruiken, zodat ik geen hele functies in functies hoefde in te voeren? (zoals GeefResultaat(Vraag(AantalGetallen(), AantalGetallen(), Bereken(Vraag(AantalGetallen), AantalGetallen(), ... etc.
Je kan ook iets doen als n = AantalGetallen() ipv Aantalgetallen(n)
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
abonnement Unibet Coolblue Bitvavo
Forum Opties
Forumhop:
Hop naar:
(afkorting, bv 'KLB')