C ++ Tutorial: Meer informatie over invoer en uitvoer

01

van 08

Een nieuwe manier van output

Programmacode
traffic_analyzer / Getty Images

C ++ behoudt een zeer hoge achterwaartse compatibiliteit met C, dus kan worden opgenomen om u toegang te geven tot de printf () functie voor uitvoer. De I / O van C ++ is echter aanzienlijk krachtiger en, nog belangrijker, veilig voor typen. U kunt ook nog steeds gebruiken scanf () voor invoer, maar het type veiligheidsfuncties dat C ++ biedt, betekent dat uw toepassingen robuuster zijn als u C ++ gebruikt.

In de vorige les werd dit aangestipt met een voorbeeld dat cout gebruikte. Hier zullen we wat dieper ingaan, te beginnen met uitvoer, omdat deze eerder wordt gebruikt dan invoer.

De klasse iostream biedt toegang tot de objecten en methoden die u nodig hebt voor zowel uitvoer als invoer. Denk aan i / o in termen van streams van bytes - ofwel van uw applicatie naar een bestand, het scherm of een printer - dat is output, of van het toetsenbord - dat is input.

Uitvoer met Cout

Als je C kent, weet je dat misschien << wordt gebruikt om bits naar links te verplaatsen. Bijv. 3 << 3 is 24. Bijv. Shift links verdubbelt de waarde, dus 3 shifts links vermenigvuldigt het met 8.

instagram viewer

In C ++, << is geweest overbelast in de ostream-klasse dus int, vlotteren tekenreeksen (en hun varianten, bijvoorbeeld dubbel) worden allemaal ondersteund. Dit is hoe je tekstuitvoer uitvoert door meerdere items samen te voegen tussen <<.>


cout << "Some Text" << intvalue << floatdouble << endl; 

Deze bijzondere syntaxis is mogelijk omdat elk van de << is eigenlijk een functieaanroep die a retourneert referentie naar een ostream voorwerp. Dus een lijn zoals hierboven is eigenlijk zo


cout. << ("enige tekst"). cout. << (waarde) .cout. << (floatdouble) .cout. << (endl); 

De C functieprintf was in staat om output te formatteren met Format Specifiers zoals% d. In C ++ kan cout ook uitvoer opmaken, maar gebruikt het op een andere manier.

02

van 08

Cout gebruiken om uitvoer te formatteren

Het object cout is lid van de iostream bibliotheek. Vergeet niet dat dit moet worden opgenomen met een


# opnemen 

Deze bibliotheek iostream is afgeleid van stroomafwaarts (voor uitvoer) en istream voor invoer.

Formatteren van tekstuitvoer wordt gedaan door manipulators in de uitvoerstroom in te voegen.

Wat is een manipulator?

Het is een functie die de kenmerken van de uitvoer (en invoer) stroom kan wijzigen. Op de vorige pagina zagen we dat << was een overbelaste functie die een verwijzing terugbracht naar het aanroepende object, b.v. cout voor output of cin voor input. Alle manipulators doen dit zodat u ze in de uitvoer kunt opnemen << of invoer >>. We zullen kijken naar input en >> later in deze les.


tel << endl; 

endl is een manipulator die de regel beëindigt (en een nieuwe begint). Het is een functie die ook op deze manier kan worden opgeroepen.


endl (cout); 

Hoewel je dat in de praktijk niet zou doen. Je gebruikt het zo.


cout << "Some Text" << endl << endl; // Twee lege regels. 

Bestanden zijn gewoon streams

Iets om in gedachten te houden dat met veel ontwikkeling tegenwoordig wordt gedaan GUI toepassingen, waarom zou u tekst-I / O-functies nodig hebben? Is dat niet alleen voor troosten toepassingen? Nou, je zult waarschijnlijk bestands-I / O doen en je kunt ze daar ook gebruiken, maar ook wat naar het scherm wordt uitgevoerd, moet meestal ook worden geformatteerd. Stromen zijn een zeer flexibele manier om invoer en uitvoer te verwerken en kunnen ermee werken

  • Tekst I / O. Zoals in consoletoepassingen.
  • Snaren. Handig voor het formatteren.
  • Bestand I / O.

Opnieuw manipulatoren

Hoewel we de stroomafwaarts klasse, het is een afgeleide klasse van de ios klasse die is afgeleid van de ios_base. Deze voorouderklasse definieert het publiek functies die manipulators zijn.

03

van 08

Lijst van Cout-manipulatoren

Manipulators kunnen worden gedefinieerd in invoer- of uitvoerstromen. Dit zijn objecten die een verwijzing naar het object retourneren en worden geplaatst tussen paren van <<. De meeste manipulators worden binnen verklaard, maar endl, loopt af en blozen Komt van . Verschillende manipulatoren nemen één parameter en deze komen van .

Hier is een meer gedetailleerde lijst.

Van

  • endl - beëindigt de lijn en roept flush aan.
  • eindigt - Voegt '\ 0' in ( NUL) in de stream.
  • flush - Forceer dat de buffer onmiddellijk wordt uitgevoerd.

Van . De meeste zijn aangegeven in de voorouder van . Ik heb ze gegroepeerd op functie in plaats van alfabetisch.

  • boolalpha - Bool-objecten invoegen of extraheren als "waar" of "onwaar".
  • noboolalpha - Bool-objecten invoegen of extraheren als numerieke waarden.
  • vast: voeg waarden met drijvende komma in een vast formaat in.
  • wetenschappelijk - Drijvende-kommawaarden invoegen in wetenschappelijk formaat.
  • internal - Internal-justify.
  • links - links-rechtvaardigen.
  • rechts - Rechtvaardig.
  • dec - Invoegen of extraheren van gehele getallen in decimaal formaat.
  • hex - Voeg gehele waarden in of extraheer deze in hexadecimaal (basis 16) formaat.
  • oct - waarden invoegen of extraheren in het octale (basis 8) formaat.
  • noshowbase - Voorvoegsel geen waarde met de basis.
  • showbase - Voorvoegselwaarde met basis.
  • noshowpoint - Toon geen decimale punt indien niet noodzakelijk.
  • showpoint - Toon altijd decimale punten bij het invoegen van waarden met drijvende komma.
  • noshowpos - Geen plusteken (+) invoegen als nummer> = 0.
  • showpos - Voer plusteken (+) in als nummer> = 0.
  • noskipws - Sla de initiële witruimte niet over bij het extraheren.
  • skipws - Sla de initiële witruimte over bij het extraheren.
  • hoofdletters - Vervang kleine letters niet door hoofdletters.
  • hoofdletters - Vervang kleine letters door hoofdletters.
  • unitbuf - Spoel buffer na een insert.
  • nounitbuf - Spoel de buffer niet na elke invoeging.

04

van 08

Voorbeelden met behulp van Cout

// ex2_2cpp. # include "stdafx.h" # opnemennamespace std; gebruiken; int main (int argc, char * argv []) { cout.width (10); cout << rechts << "Test" << endl; cout << links << "Test 2" << endl; cout << intern << "Test 3" << endl; cout << endl; cout.precision (2); cout << 45.678 << endl; cout << hoofdletters << "David" << endl; cout.precision (8); cout << wetenschappelijke << endl; cout << 450678762345.123 << endl; cout << vast << endl; cout << 450678762345.123 << endl; cout << showbase << endl; cout << showpos << endl; cout << hex << endl; cout << 1234 << endl; cout << okt << endl; cout << 1234 << endl; cout << dec << endl; cout << 1234 << endl; cout << noshowbase << endl; cout << noshowpos << endl; cout.unsetf (ios:: hoofdletters); cout << hex << endl; cout << 1234 << endl; cout << okt << endl; cout << 1234 << endl; cout << dec << endl; cout << 1234 << endl; terugkeer 0; }

De uitvoer hiervan is hieronder, met een of twee extra regelruimtes verwijderd voor de duidelijkheid.

 Test. Test 2. Test 3. 46. David. 4.50678762E + 011. 450678762345.12299000. 0X4D2. 02322. +1234. 4d2. 2322. 1234. 

Notitie: Ondanks de hoofdletters wordt David afgedrukt als David en niet DAVID. Dit komt omdat hoofdletters alleen van invloed zijn op gegenereerde uitvoer, b.v. nummers afgedrukt in hexadecimaal. Dus de hexuitgang 4d2 is 4D2 wanneer de hoofdletter in werking is.

Ook zetten de meeste van deze manipulators eigenlijk een beetje in een vlag en het is mogelijk om dit direct in te stellen met

 cout.setf () 

en wis het met

 cout.unsetf () 

05

van 08

Setf en Unsetf gebruiken om I / O-opmaak te manipuleren

De functie setf heeft twee overbelast hieronder weergegeven versies. Terwijl unsetf wist gewoon de opgegeven bits.

 setf (vlagwaarden); setf (vlagwaarden, maskerwaarden); unsetf (vlagwaarden); 

De variabele vlaggen worden afgeleid door ORing samen alle bits die u wilt met |. Dus als je wilt wetenschappelijk, hoofdletters en boolalpha gebruik dit dan. Alleen de bits zijn doorgegeven als de parameter spelen zich af. De andere bits blijven ongewijzigd.

 cout.setf (ios_base:: science | ios_base:: uppercase | ios_base:: boolalpha); cout << hex << endl; cout << 1234 << endl; cout << dec << endl; cout << 123400003744.98765 << endl; bool value = true; cout << waarde << endl; cout.unsetf (ios_base:: boolalpha); cout << waarde << endl; 

Produceert

 4D2. 1.234000E + 011. waar. 1. 

Maskerende bits

De twee parameter versie van setf gebruikt een masker. Als het bit is ingesteld in zowel de eerste als de tweede parameter, wordt het ingesteld. Als het bit zich alleen in de tweede parameter bevindt, wordt het gewist. De waarden adjustfield, basisveld en drijfveld (hieronder weergegeven) zijn samengestelde vlaggen, dat wil zeggen meerdere vlaggen Of zou samen. Voor basisveld met de waarden 0x0e00 is hetzelfde als dec | okt | hex. Zo

 setf (ios_base:: hex, ios_basefield); 

wist alle drie vlaggen en stelt vervolgens in hex. Op dezelfde manier veld aanpassen is links | rechts | intern en drijfveld is wetenschappelijk | gemaakt.

Lijst met bits

Deze lijst met enums is afkomstig uit Microsoft Visual C ++ 6.0. De werkelijk gebruikte waarden zijn willekeurig - een andere compiler kan andere waarden gebruiken.

 skipws = 0x0001. unitbuf = 0x0002. hoofdletter = 0x0004. showbase = 0x0008. showpoint = 0x0010. showpos = 0x0020. links = 0x0040. rechts = 0x0080. intern = 0x0100. dec = 0x0200. oct = 0x0400. hex = 0x0800. wetenschappelijk = 0x1000. vast = 0x2000. boolalpha = 0x4000. adjustfield = 0x01c0. basisveld = 0x0e00, drijfveld = 0x3000. _Fmtmask = 0x7fff, _Fmtzero = 0. 

06

van 08

Over Clog en Cerr

Leuk vinden Cout, verstoppen en cerr zijn vooraf gedefinieerde objecten gedefinieerd in ostream. De klasse iostream neemt van beide over stroomafwaarts en istream dus dat is waarom de Cout voorbeelden kunnen gebruiken iostream.

Gebufferd en niet gebufferd

  • Gebufferd - Alle uitvoer wordt tijdelijk opgeslagen in een buffer en vervolgens in één keer op het scherm gedumpt. Zowel cout als klomp worden gebufferd.
  • Niet gebufferd - Alle uitvoer gaat onmiddellijk naar het uitvoerapparaat. Een voorbeeld van een ongebufferd object is cerr.

Het onderstaande voorbeeld laat zien dat cerr op dezelfde manier wordt gebruikt als cout.


# opnemen namespace std; gebruiken; int _tmain (int argc, _TCHAR * argv []) {cerr.breedte (15); cerr.right; cerr << "Fout" << endl; terugkeer 0; }

Het grootste probleem met bufferen is of de programma crasht dan gaat de bufferinhoud verloren en is het moeilijker te zien waarom het is gecrasht. Niet-gebufferde uitvoer is onmiddellijk, dus een paar regels zoals deze door de code sprenkelen kan handig zijn.

 cerr << "Gevaarlijke functie invoeren zappit" << endl; 

Het registratieprobleem

Het bouwen van een logboek van programma-evenementen kan een nuttige manier zijn om moeilijke bugs op te sporen, het type dat alleen af ​​en toe voorkomt. Als die gebeurtenis echter een crash is, hebt u het probleem: spoelt u het logboek na elke oproep naar schijf zodat u gebeurtenissen kunt zien tot aan de crash of bewaar deze in een buffer en spoel de buffer regelmatig door en hoop dat je niet te veel verliest tijdens de crash komt voor?

07

van 08

Cin gebruiken voor invoer: geformatteerde invoer

Er zijn twee soorten invoer.

  • Geformatteerd. Invoer lezen als getallen of van een bepaald type.
  • Niet opgemaakt. Bytes lezen of snaren. Dit geeft veel meer controle over de invoerstroom.

Hier is een eenvoudig voorbeeld van opgemaakte invoer.

 // excin_1.cpp: definieert het toegangspunt voor de consoletoepassing. #inclusief "stdafx.h" // alleen Microsoft. # opnemen namespace std; gebruiken; int main (int argc, char * argv []) { int a = 0; vlotter b = 0,0; int c = 0; cout << "Voer een int, een float en int gescheiden door spaties in" <> a >> b >> c; cout << "U heeft" << a << "" << b << "" << c << endl; terugkeer 0; }

Dit gebruikt cin om drie cijfers te lezen (int, vlotter, int) gescheiden door spaties. U moet op Enter drukken nadat u het nummer hebt ingevoerd.

3 7.2 3 geeft "U heeft 3 7.2 3" ingevoerd.

Opgemaakte invoer heeft beperkingen!

Als u 3,76 5 8 invoert, krijgt u "U heeft 3 0,76 5 ingevoerd", alle andere waarden op die regel gaan verloren. Dat gedraagt ​​zich correct, zoals de. maakt geen deel uit van de int en markeert dus het begin van de float.

Fout bij trapping

Het cin-object stelt een fail-bit in als de invoer niet succesvol is geconverteerd. Dit bit is onderdeel van ios en kan worden gelezen met behulp van de falen () functioneren op beide cin en Cout soortgelijk.

 if (cin.fail ()) // doe iets. 

Niet verrassend, cout.fail () is zelden ingesteld, althans op de schermuitvoer. In een latere les over bestands-I / O zullen we zien hoe cout.fail () kan waar worden. Er is ook een mooi zo() functie voor cin, Cout enz.