Google Code University’s C++ tutorial Wordt gebruikt om deze code te hebben:
// Description: Illustrate the use of cin to get input
// and how to recover from errors.
#include <iostream>
using namespace std;
int main()
{
int input_var = 0;
// Enter the do while loop and stay there until either
// a non-numeric is entered, or -1 is entered. Note that
// cin will accept any integer, 4, 40, 400, etc.
do {
cout << "Enter a number (-1 = quit): ";
// The following line accepts input from the keyboard into
// variable input_var.
// cin returns false if an input operation fails, that is, if
// something other than an int (the type of input_var) is entered.
if (!(cin >> input_var)) {
cout << "Please enter numbers only." << endl;
cin.clear();
cin.ignore(10000,'\n');
}
if (input_var != -1) {
cout << "You entered " << input_var << endl;
}
}
while (input_var != -1);
cout << "All done." << endl;
return 0;
}
Wat is de betekenis van cin.clear()
EN cin.ignore()
? Waarom zijn de 10000
en \n
parameters die nodig zijn?
Antwoord 1, Autoriteit 100%
De cin.clear()
Wist de foutvlag op cin
(zodat toekomstige I / O-operaties correct werken), en dan cin.ignore(10000, '\n')
Springt naar de volgende nieuwe lijn (om iets anders op dezelfde lijn te negeren als het non-nummer, zodat het geen eenmalig ontleden mislukking veroorzaakt). Het zal alleen tot 10000 tekens overslaan, dus de code veronderstelt dat de gebruiker niet in een zeer lange, ongeldige lijn zal plaatsen.
Antwoord 2, Autoriteit 43%
u voert de
in
if (!(cin >> input_var))
Verklaring Als er een fout optreedt bij het nemen van de invoer van CIN. Als er een fout optreedt, wordt een foutvlag ingesteld en zullen toekomstige pogingen om inputs te krijgen. Dat is waarom je
nodig hebt
cin.clear();
Om de foutvlag af te komen. Ook, de input die mislukte zal zitten in wat ik aannemen, is een soort buffer. Wanneer u opnieuw probeert input te worden, zal deze dezelfde invoer in de buffer lezen en het zal opnieuw falen. Dat is waarom je
nodig hebt
cin.ignore(10000,'\n');
Het neemt 10000 tekens uit de buffer, maar stopt als het een nieuwlijn (\ N) tegenkomt. De 10000 is slechts een generieke grote waarde.
Antwoord 3, Autoriteit 26%
Waarom gebruiken we:
1) CIN.IGNORE
2) CIN.CLEAR
?
gewoon:
1) Om te negeren (extract en gooi) waarden die we niet willen op de stroom
2) om de interne stroomstaat te wissen. Na gebruik van Cin.Clear Interne State wordt opnieuw teruggezet naar Goodbit, wat betekent dat er geen ‘fouten’ zijn.
Lange versie:
Als iets op ‘Stream’ (CIN) wordt gezet, moet het vanaf daar worden genomen. Door ‘genomen’ bedoelen we ‘gebruikt’, ‘verwijderd’, ‘geëxtraheerd’ uit de stroom. Stream heeft een stroom. De gegevens stromen op CIN-achtige water op de stroom. U kunt eenvoudig de stroom van water niet stoppen;)
Kijk naar het voorbeeld:
string name; //line 1
cout << "Give me your name and surname:"<<endl;//line 2
cin >> name;//line 3
int age;//line 4
cout << "Give me your age:" <<endl;//line 5
cin >> age;//line 6
Wat gebeurt er als de gebruiker antwoordt: “Arkadiusz Wlodarczyk” voor de eerste vraag?
Voer het programma uit om voor uzelf te zien.
U ziet op console “arkadiusz” maar programma vraagt u niet om ‘leeftijd’. Het voltooit gewoon meteen direct na het afdrukken van “arkadiusz”.
en “WLODARCZYK” wordt niet weergegeven. Het lijkt erop dat het verdwenen was (?) *
Wat is er gebeurd? ; -)
Omdat er een ruimte is tussen “arkadiusz” en “wlodarczyk”.
“Space” -karakter tussen de naam en de achternaam is een bord voor de computer dat er twee variabelen wachten om te worden geëxtraheerd op ‘Input’-stream.
De computer denkt dat u aan het verzenden bent om meer dan één variabele in te voeren. Dat “spatie” -teken is een teken voor hem om het op die manier te interpreteren.
Dus de computer wijst “arkadiusz” toe aan ‘naam’ (2) en omdat u meer dan één stroming op stream (invoer) computer probeert, probeert de waarde “WLODARCZYK” aan variabele ‘Age’ (!) te wensen. De gebruiker heeft geen kans om iets op de ‘CIN’ in lijn 6 te plaatsen omdat die instructie al is uitgevoerd (!). Waarom? Omdat er nog iets over de stroom was. En zoals ik al zei dat eerdere stroom in een stroom is, zodat alles zo snel mogelijk van kan worden verwijderd. En de mogelijkheid kwam toen Computerzaag Instructie Cin & GT; & GT; Leeftijd;
De computer weet niet dat je een variabele hebt gemaakt die de leeftijd van iemand opslaat (regel 4). ‘leeftijd’ is slechts een label. Voor computer zou ‘leeftijd’ net zo goed ‘afsfasgfsagasggas’ kunnen worden genoemd en het zou hetzelfde zijn. Voor hem is het gewoon een variabele waaraan hij “Wlodarczyk” zal proberen toe te wijzen, omdat je de computer hebt besteld/geïnstrueerd om dit in regel (6) te doen.
Het is verkeerd om dit te doen, maar hey, jij hebt het gedaan! Het is jouw schuld! Nou ja, misschien gebruiker, maar toch…
Oké, oké. Maar hoe repareer je het?!
Laten we proberen wat met dat voorbeeld te spelen voordat we het goed repareren om nog een paar interessante dingen te leren 🙂
Ik geef er de voorkeur aan om een benadering te maken waarbij we dingen begrijpen. Iets repareren zonder te weten hoe we het hebben gedaan, geeft geen voldoening, vind je ook niet? 🙂
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate(); //new line is here :-)
Na het aanroepen van bovenstaande code zul je merken dat de status van je stream (cin) gelijk is aan 4 (regel 7). Wat betekent dat de interne staat niet langer gelijk is aan goodbit. Er is iets verpest. Het is vrij duidelijk, nietwaar? U hebt geprobeerd een tekenreekstypewaarde (“Wlodarczyk”) toe te wijzen aan de int-typevariabele ‘age’. Typen komen niet overeen. Het is tijd om te informeren dat er iets mis is. En de computer doet het door de interne streamstatus te veranderen. Het is als: “Fuck up man, fix me please. Ik informeer je ‘vriendelijk’ ;-)”
Je kunt ‘cin’ (stream) gewoon niet meer gebruiken. Het zit vast. Alsof je grote houtblokken op een waterstroom had gezet. U moet het repareren voordat u het kunt gebruiken. Gegevens (water) kunnen niet meer uit die stroom (cin) worden verkregen omdat houtblokken (interne staat) dit niet toelaten.
O, dus als er een obstakel is (houtblokken), kunnen we dit gewoon verwijderen met speciaal daarvoor gemaakt gereedschap?
Ja!
interne status van cin ingesteld op 4 is als een alarm dat huilt en geluid maakt.
cin.clear maakt de status weer normaal (goodbit). Het is alsof je was gekomen en het alarm had uitgezet. Je stelt het gewoon uit. Je weet dat er iets is gebeurd, dus je zegt: “Het is oké om te stoppen met lawaai maken, ik weet dat er al iets mis is, hou je mond (duidelijk)”.
Ok, laten we dat doen! Laten we cin.clear() gebruiken.
Roep onderstaande code op met “Arkadiusz Wlodarczyk” als eerste invoer:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;
cin.clear(); //new line is here :-)
cout << cin.rdstate()<< endl; //new line is here :-)
We kunnen na het uitvoeren van bovenstaande code zeker zien dat de status gelijk is aan goodbit.
Geweldig, dus het probleem is opgelost?
Roep onderstaande code op met “Arkadiusz Wlodarczyk” als eerste invoer:
string name;
cout << "Give me your name and surname:"<<endl;
cin >> name;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << cin.rdstate() << endl;;
cin.clear();
cout << cin.rdstate() << endl;
cin >> age;//new line is here :-)
Zelfs als de status is ingesteld op goodbit na regel 9, wordt de gebruiker niet om “leeftijd” gevraagd. Het programma stopt.
WAAROM?!
Oh man… Je hebt zojuist het alarm uitgesteld, hoe zit het met het houtblok in een water?* Ga terug naar de tekst waar we het hadden over “Wlodarczyk”, hoe het zogenaamd verdwenen was.
Je moet “Wlodarczyk” dat stuk hout uit de beek verwijderen. Het uitschakelen van alarmen lost het probleem helemaal niet op. Je hebt het net tot zwijgen gebracht en je denkt dat het probleem weg is? 😉
Het is dus tijd voor een andere tool:
cin.ignore kan worden vergeleken met een speciale vrachtwagen met touwen die komt en de houtblokken verwijdert die de stroom hebben laten vastlopen. Het lost het probleem op dat de gebruiker van uw programma heeft gemaakt.
Dus kunnen we het al gebruiken voordat het alarm afgaat?
Ja:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n'); //time to remove "Wlodarczyk" the wood log and make the stream flow
int age;
cout << "Give me your age:" << endl;
cin >> age;
De “Wlodarczyk” wordt verwijderd voordat het geluid in regel 7 wordt gemaakt.
Wat is 10000 en ‘\n’?
Er staat dat je 10000 tekens moet verwijderen (voor het geval dat) totdat aan ‘\n’ is voldaan (ENTER). BTW Het kan beter met numeric_limits, maar dit is niet het onderwerp van dit antwoord.
Dus de hoofdoorzaak van het probleem is verdwenen voordat er geluid werd gemaakt…
Waarom hebben we dan ‘clear’ nodig?
Wat als iemand had gevraagd om ‘geef me je leeftijd’-vraag in regel 6, bijvoorbeeld: ‘twintig jaar oud’ in plaats van 20 te schrijven?
Typen komen niet meer overeen. Computer probeert string toe te wijzen aan int. En het alarm gaat af. Je hebt niet eens de kans om op zo’n situatie te reageren. cin.ignore zal je in dat geval niet helpen.
Dus we moeten in dat geval clear gebruiken:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n'); //time to remove "Wlodarczyk" the wood log and make the stream flow
int age;
cout << "Give me your age:" << endl;
cin >> age;
cin.clear();
cin.ignore(10000, '\n'); //time to remove "Wlodarczyk" the wood log and make the stream flow
Maar moet je de status wissen ‘voor het geval dat’?
Natuurlijk niet.
Als er iets misgaat (cin >> age;) zal de instructie je hierover informeren door false te retourneren.
We kunnen dus een voorwaardelijke instructie gebruiken om te controleren of de gebruiker het verkeerde type in de stream heeft gezet
int age;
if (cin >> age) //it's gonna return false if types doesn't match
cout << "You put integer";
else
cout << "You bad boy! it was supposed to be int";
Ok, dan kunnen we ons aanvankelijke probleem als volgt oplossen:
string name;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin.ignore(10000, '\n'); //time to remove "Wlodarczyk" the wood log and make the stream flow
int age;
cout << "Give me your age:" << endl;
if (cin >> age)
cout << "Your age is equal to:" << endl;
else
{
cin.clear();
cin.ignore(10000, '\n'); //time to remove "Wlodarczyk" the wood log and make the stream flow
cout << "Give me your age name as string I dare you";
cin >> age;
}
Natuurlijk kan dit verbeterd worden door bijvoorbeeld te doen wat je in kwestie deed met loop while.
BONUS:
Je vraagt je misschien af. Hoe zit het als ik naam en achternaam in dezelfde regel van de gebruiker wil krijgen? Is het zelfs mogelijk om cin te gebruiken als cin elke waarde, gescheiden door “spatie” als verschillende variabele interpreteert?
Natuurlijk, je kunt het op twee manieren doen:
1)
string name, surname;
cout << "Give me your name and surname:"<< endl;
cin >> name;
cin >> surname;
cout << "Hello, " << name << " " << surname << endl;
2) of door de getline-functie te gebruiken.
getline(cin, nameOfStringVariable);
en zo doe je het:
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
De tweede optie kan een averechts effect hebben als je het gebruikt nadat je ‘cin’ voor de getline hebt gebruikt.
Laten we eens kijken:
a)
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
Als u “20” als leeftijd invoert, wordt u niet om nameAndSurname gevraagd.
Maar als je het zo doet:
b)
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cout << "Your age is" << age << endll
alles is in orde.
WAT?!
Elke keer dat je iets op invoer (stream) zet, laat je aan het einde een wit teken achter, dat is ENTER (‘\n’). Je moet op de een of andere manier waarden invoeren in de console. Het moet dus gebeuren als de gegevens van de gebruiker komen.
b) cin-kenmerken zijn dat het witruimte negeert, dus als u informatie uit cin inleest, maakt het nieuwe regelteken ‘\n’ niet uit. Het wordt genegeerd.
a) de getline-functie krijgt de hele regel tot aan het nieuwe-regelteken (‘\n’), en als het nieuwe-regelteken het eerste is, krijgt de getline-functie ‘\n’, en dat is alles. Je extraheert het teken van de nieuwe regel dat in de stream is achtergelaten door de gebruiker die “20” in de stream in regel 3 heeft gezet.
Dus om het te repareren moet je altijd cin.ignore(); elke keer dat je cin gebruikt om een waarde te krijgen als je ooit getline() in je programma gaat gebruiken.
Dus de juiste code zou zijn:
int age;
cout << "Give me your age:" <<endl;
cin >> age;
cin.ignore(); // it ignores just enter without arguments being sent. it's same as cin.ignore(1, '\n')
cout << "Your age is" << age << endl;
string nameAndSurname;
cout << "Give me your name and surname:"<< endl;
getline(cin, nameAndSurname);
cout << "Hello, " << nameAndSurname << endl;
Ik hoop dat streams duidelijker voor je zijn.
Hah leg me alsjeblieft het zwijgen op! 🙂
Antwoord 4
gebruik cin.ignore(1000,'\n')
om alle tekens van de vorige cin.get()
in de buffer te wissen en het zal ervoor kiezen om stop wanneer het ‘\n’ of 1000 chars
als eerste ontmoet.