abonnement Unibet Coolblue Bitvavo
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')