| 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"; |
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.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.
Wat is je vraag precies?quote: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.
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.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.
| 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'; } |
| 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'; } |
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.quote:
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.quote:Ik zie mensen vanuit namespaces ook nooit ::std::iets doen, maar bij andere namespaces wordt dat weer wel gedaan.
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.quote:Op donderdag 3 maart 2011 18:31 schreef thabit het volgende:
Je zou met threads kunnen werken, maar dat is in C++ een crime.
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>.quote: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?
kijk dit klinkt beterquote: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.
| 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; } |
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.quote: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?
In grote lijnen - wat thabit zegt.quote: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?
ahh, ik snapquote: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.
| 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); } |
| Forum Opties | |
|---|---|
| Forumhop: | |
| Hop naar: | |