Hoe een reeks getallen te lezen met behulp van scanf De functies printf() en scanf() leren en gebruiken

De functies printf() en scanf() geven ons de mogelijkheid om met het programma te communiceren. We noemen ze I/O-functies. Dit zijn niet de enige functies die we kunnen gebruiken om gegevens in en uit te voeren met behulp van C-programma's, maar ze zijn wel de meest veelzijdige. Deze functies zijn opgenomen in de beschrijving van de C-taal en worden gegeven in de stdio.h-bibliotheek. Normaal gesproken werken de functies printf() en scanf() op vrijwel dezelfde manier: elk gebruikt een controletekenreeks en een lijst met argumenten. Eerst zullen we bekijken hoe de functie printf() werkt, en daarna scanf().

Formaat

Type informatie dat wordt weergegeven

decimaal geheel getal

één karakter

tekenreeks

exponentiële notatie

drijvende-kommagetal, decimale notatie

gebruikt in plaats van %f of %e

niet-ondertekend decimaal geheel getal

octaal geheel getal zonder teken

hexadecimaal geheel getal zonder teken

De instructies die aan de functie printf() worden doorgegeven wanneer we een variabele willen afdrukken, zijn afhankelijk van het type variabele. Als u bijvoorbeeld een geheel getal afdrukt, is het formaat %d, en als u een teken afdrukt, is het formaat %c. De formaten staan ​​vermeld in de tabel.

Laten we nu kijken hoe deze formulieren worden gebruikt:

/* zegel */

#erbij betrekken

#define PI 3.14159

int-nummer = 2003;

printf("De Internet Universiteit voor Informatietechnologie werd geopend in het %d jaar \n", getal);

printf("De waarde van pi is %f.\n", PI);

Het formaat dat is opgegeven bij het aanroepen van de printf()-functie is als volgt:

printf(Controletekenreeks, argument1, argument2,_);

argument 1, argument 2, enz. zijn afdrukbare parameters die variabelen, constanten of zelfs kunnen zijn uitdrukkingen, berekend vóór het afdrukken.

De controleregel is een reeks tekens die aangeeft hoe de parameters moeten worden afgedrukt. Bijvoorbeeld, binnen exploitant

printf("%d studenten kregen een cijfer van %f.\n",

de controlereeks is een zin tussen aanhalingstekens, en getal en z zijn argumenten of in in dit geval waarden van twee variabelen.

We zien dat de controleregel twee verschillende soorten informatie bevat:

    Tekens tekstueel afgedrukt.

    Gegevensidentificatoren, ook wel genoemd conversie specificaties .

Elk argument uit de lijst na de controletekenreeks moet met één argument overeenkomen conversie specificatie. Als u een zin wilt afdrukken, hoeft u deze niet te gebruiken conversie specificatie; als u de gegevens alleen hoeft af te drukken, kunt u dit doen zonder commentaar te gebruiken. Daarom elk van exploitanten hieronder zijn zeer acceptabel:

printf("Dit boek is niet erg duur!\n");

printf("%c%d\n","$",kosten);

Als u het %-symbool zelf moet afdrukken, beschouwt de compiler dit als een fout conversie specificatie. De uitweg uit deze situatie is een vrij eenvoudige oplossing: schrijf twee% tekens achter elkaar.

Bijvoorbeeld:

printf("Slechts %d%% van de bevolking kan zelfstandig leren!\n",i);

Het resultaat van het programma ziet er als volgt uit:

Slechts 5% van de bevolking kan zelfstandig studeren!

We kunnen de basisdefinitie uitbreiden conversie specificaties, waarbij modificatoren tussen het %-teken en het symbool worden geplaatst dat het type conversie specificeert. Wanneer meerdere modifiers tegelijkertijd worden gebruikt, moeten deze worden opgegeven in de volgorde waarin ze in de tabel worden vermeld.

Modificatoren

Betekenis

Het argument wordt afgedrukt vanuit de linkerveldpositie gegeven breedte. Normaal gesproken eindigt de argumentafdruk op de meest rechtse veldpositie. Voorbeeld: %-10

reeks cijfers

Stelt de minimale veldbreedte in. Het grotere veld wordt gebruikt als het nummer of de tekenreeks die wordt afgedrukt niet in het oorspronkelijke veld past. Voorbeeld: %4d

reeks cijfers

Bepaalt de nauwkeurigheid: voor gegevenstypen met drijvende komma: het aantal cijfers dat rechts van de komma moet worden afgedrukt; voor tekenreeksen - Maximaal nummer afdrukbare tekens Voorbeeld:

%4.2f(twee decimale cijfers voor een veld van vier tekens breed)

Het corresponderende data-element is van het type long, niet int. Voorbeeld: %ld

printf("/%d/\n",135);

printf("/%2d/\n",135);

printf("/%10d/\n",135);

printf("/%-10d/\n",135);

Eerst conversie specificatie%d bevat geen modificatoren. Dit is de zogenaamde standaardkeuze, d.w.z. het resultaat van de actie van de compiler als u hem geen aanvullende instructies heeft gegeven. Seconde conversie specificatie- %2d. Er wordt aangegeven dat de veldbreedte 2 moet zijn, maar omdat het getal uit drie cijfers bestaat, wordt het veld automatisch uitgebreid tot de gewenste grootte. Volgende specificatie%10d geeft aan dat de veldbreedte 10 is. Laatste specificatie%-10d specificeert ook een veldbreedte van 10, en het teken - zorgt ervoor dat het gehele getal naar links wordt verschoven.

In dit artikel wordt de functie scanf() besproken algemeen beeld zonder verwijzing naar een specifieke standaard, daarom zijn hier gegevens van alle standaarden C99, C11, C++11, C++14 opgenomen. Het is mogelijk dat in sommige standaarden de functie anders werkt dan het materiaal dat in het artikel wordt gepresenteerd.

scanf C-functie - beschrijving

scanf() is een functie die zich bevindt in het headerbestand van stdio.h(C) en cstdio(C++). Het wordt ook wel geformatteerde invoer voor het programma genoemd. scanf leest tekens uit standaard stroom input (stdin) en converteert ze volgens het formaat, en schrijft ze vervolgens naar de opgegeven variabelen. Formaat betekent dat de gegevens bij ontvangst worden teruggebracht tot een bepaalde vorm. Zo wordt de scanf C-functie beschreven:

scanf("%format", &variabele1[, &variabele2,[…]]),

waar variabelen als adressen worden doorgegeven. De reden om op deze manier variabelen aan een functie door te geven ligt voor de hand: als gevolg van de werking ervan retourneert het een waarde die de aanwezigheid van fouten aangeeft, dus de enige manier om de waarden van variabelen te wijzigen is door het adres door te geven. Dankzij deze methode kan de functie ook gegevens van elk type verwerken.

Sommige programmeurs roepen functies zoals scanf() of printf() procedures aan vanwege analogieën met andere talen.

Met Scanf kunt u alles invoeren basistypen talen: char, int, float, string, etc. In het geval van variabelen type tekenreeks Het is niet nodig om het adresteken - “&” op te geven, aangezien een variabele van het type string een array is en de naam het adres is van het eerste element van de array in het computergeheugen.

Gegevensinvoerformaat of controletekenreeks

Laten we beginnen met een voorbeeld van het gebruik van de scanf C-functie uit de beschrijving.

#erbij betrekken int main() ( int x; while (scanf("%d", &x) == 1) printf("%d\n", x); return 0; //vereiste voor Linux-systemen )

Het invoerformaat bestaat uit de volgende vier parameters: %[*][width][modifiers] type. In dit geval zijn het teken “%” en het type vereiste parameters. Dat wil zeggen, het minimale formaat ziet er als volgt uit: “%s”, “%d” enzovoort.

IN algemeen geval De tekens waaruit de opmaaktekenreeks bestaat, zijn onderverdeeld in:

  • formaatspecificaties - alles dat begint met het%-symbool;
  • verdelen of witruimte tekens- ze worden beschouwd als spatie, tab (\t), nieuwe regel (\n);
  • andere tekens dan witruimte.

De functie is mogelijk onveilig.

Gebruik scanf_s() in plaats van scanf().

(bericht van Visuele studio)

Type- of formaatspecificaties, of conversietekens, of controletekens

De beschrijving van scanf C moet minimaal een formaatspecificatie bevatten, die wordt aangegeven aan het einde van expressies die beginnen met het "%" -teken. Het vertelt het programma welk type gegevens het kan verwachten bij invoer, meestal vanaf het toetsenbord. Een lijst met alle formaatspecificaties vindt u in de onderstaande tabel.

Betekenis

Het programma wacht tot er een teken wordt ingevoerd. De te schrijven variabele moet van het tekentype char zijn.

Het programma wacht op invoer decimaal getal een hele soort. De variabele moet van het type int zijn.

Het programma verwacht een getal met drijvende komma in exponentiële vorm. De variabele moet van het type float zijn.

Het programma verwacht dat er een getal met drijvende komma wordt ingevoerd. De variabele moet van het type float zijn.

7

Het programma verwacht dat er een getal met drijvende komma wordt ingevoerd. De variabele moet van het type float zijn.

Het programma wacht op invoer octaal getal. De variabele moet van het type int zijn.

Het programma verwacht dat er een string wordt ingevoerd. Een string wordt beschouwd als een verzameling van willekeurige tekens, tot aan het eerste scheidingsteken dat wordt aangetroffen. De variabele moet van het type string zijn.

Het programma wacht op invoer hexadecimaal getal. De variabele moet van het type int zijn.

De variabele verwacht een pointerinvoer. De variabele moet van het pointertype zijn.

Schrijft een geheel getal dat gelijk is aan het aantal leesbewerkingen naar een variabele. huidige moment tekens met behulp van de scanf-functie.

Het programma leest een geheel getal zonder teken. Het variabeletype moet een geheel getal zonder teken zijn.

Het programma wacht op invoer binair getal. De variabele moet van het type int zijn.

Een set scanbare karakters. Het programma wacht op invoer van tekens uit een beperkte pool die is opgegeven tussen scanf en zal werken zolang er tekens uit de opgegeven set in de invoerstroom aanwezig zijn.

Tekens in de notatiereeks

Sterretje (*)

Het sterretje (*) is een vlag die aangeeft dat de toewijzingsbewerking moet worden onderdrukt. Direct na het “%”-teken wordt een asterisk geplaatst. Bijvoorbeeld,

Scanf("%d%*c%d", &x, &y); // negeer het teken tussen twee gehele getallen. scanf("%s%*d%s", str, str2); // negeer het gehele getal tussen twee strings.

Dat wil zeggen, als u de regel "45-20" in de console invoert, zal het programma het volgende doen:

  1. De variabele "x" krijgt de waarde 45.
  2. De variabele "y" krijgt de waarde 20.
  3. En het minteken (streepje) “-” wordt genegeerd dankzij “%*c”.

Breedte (of veldbreedte)

Dit is een geheel getal tussen het teken "%" en de formaatspecificatie die dit specificeert maximaal aantal tekens die moeten worden gelezen voor de huidige leesbewerking.

Er zijn een paar dingen waarmee u rekening moet houden belangrijke punten:

  1. scanf stopt met werken als het een scheidingsteken tegenkomt, zelfs als het nog geen 20 tekens heeft geteld.
  2. Als de invoer meer dan 20 tekens bevat, worden alleen de eerste 20 tekens naar de str-variabele geschreven.

Typemodificatoren (of precisie)

Dit zijn speciale vlaggen die het type gegevens wijzigen dat voor invoer wordt verwacht. De vlag wordt links van de typeaanduiding opgegeven:

  • L of l (kleine L) Wanneer "l" wordt gebruikt met de specificaties d, i, o, u, x, vertelt de vlag het programma dat invoer wordt verwacht lange soort int. Wanneer u "l" gebruikt met de e- of f-specificatie, vertelt de vlag het programma dat het moet wachten totdat een waarde is ingevoerd typ dubbel. Het gebruik van "L" vertelt het programma dat een waarde van het type long double wordt verwacht. Door "l" te gebruiken met de specificaties "c" en "s" vertelt het programma dat dubbelbytetekens van het type wchar_t worden verwacht. Bijvoorbeeld "%lc", "%ls", "%l".
  • h is een vlag die het type kortsluiting aangeeft.
  • hh - geeft aan dat de variabele een verwijzing is naar een waarde van het type ondertekende char of Ongetekend char. De vlag kan worden gebruikt met de specificaties d, i, o, u, x, n.
  • ll (twee kleine L) - geeft aan dat de variabele een verwijzing is naar een waarde van het type Signed Int of Unsigned Long Long Int. De vlag wordt gebruikt met de specificaties: d, i, o, u, x, n.
  • j - geeft aan dat de variabele een pointer is om intmax_t of uintmax_t uit het headerbestand stdint.h te typen. Gebruikt met specificaties: d, i, o, u, x, n.
  • z - geeft aan dat de variabele een verwijzing is naar het type size_t, waarvan de definitie in stddef.h staat. Gebruikt met specificaties: d, i, o, u, x, n.
  • t - geeft aan dat de variabele een pointer is naar het type ptrdiff_t. De definitie voor dit type staat in stddef.h. Gebruikt met specificaties: d, i, o, u, x, n.

De afbeelding met modifiers kan duidelijker worden gepresenteerd in de vorm van een tabel. Dit scanf-beschrijving C zal duidelijker zijn voor programmeurs.

Andere karakters

Alle tekens die u in het formaat tegenkomt, worden verwijderd. Het is vermeldenswaard dat de aanwezigheid van witruimte of scheidingstekens (nieuwe regel, spatie, tab) in de controleregel kan leiden tot ander gedrag functies. In de ene versie leest scanf() zonder een aantal scheidingstekens op te slaan totdat het een ander teken tegenkomt dan het scheidingsteken, en in een andere versie doen spaties (alleen zij) er niet toe en is de uitdrukking "%d + %d" gelijkwaardig naar "% d+%d".

Voorbeelden

Laten we een aantal voorbeelden bekijken om u te helpen nadenken over en beter begrijpen hoe de functie werkt.

Scanf("%3s", str); //als u de regel “1d2s3d1;3” in de console invoert, wordt alleen “1d2” naar str scanf("%dminus%d", &x, &y) geschreven; //mintekens tussen twee cijfers worden verwijderd scanf("%5", str); //tekens worden in str ingevoerd totdat er 5 zijn en de tekens bestaan ​​uit cijfers van 0 tot en met 9. scanf("%lf", &d); //verwachte invoer van het type double scanf("%hd", &x); //verwacht een aantal van het type short scanf("%hu", &y); //verwacht een aantal van het type unsigned short scanf("lx", &z); //verwacht aantal type lange int

Uit de bovenstaande voorbeelden kunt u zien hoe het verwachte aantal verandert met behulp van verschillende karakters.

scanf C - beschrijving voor beginners

Deze sectie zal nuttig zijn voor beginners. Vaak moet je niet zo veel bij de hand hebben Volledige beschrijving scanf C, hoeveel details over hoe de functie werkt.

  • De functie is enigszins verouderd. Er zijn meerdere verschillende implementaties in bibliotheken verschillende versies. Bijvoorbeeld de verbeterde scanf SC-functie, waarvan een beschrijving te vinden is op de website van Microsoft.
  • Het aantal specificaties in het formaat moet overeenkomen met het aantal argumenten dat aan de functie wordt doorgegeven.
  • Elementen van de invoerstroom mogen alleen worden gescheiden door tekens te scheiden: spatie, tab, nieuwe regel. Komma, puntkomma, punt, enz. - deze tekens zijn geen scheidingstekens voor de functie scanf().
  • Als scanf een scheidingsteken tegenkomt, wordt de invoer gestopt. Als er meer dan één variabele te lezen is, gaat scanf verder met het lezen van de volgende variabele.
  • De kleinste discrepantie in het formaat van de invoergegevens leidt tot onvoorspelbare resultaten van het programma. Het is goed als het programma gewoon eindigt met een fout. Maar vaak blijft het programma werken en doet het het verkeerd.
  • scanf("%20s...", ...); Als de invoerstroom langer is dan 20 tekens, leest scanf de eerste 20 tekens en beëindigt of gaat verder met het lezen van de volgende variabele, indien opgegeven. De volgende scanf-oproep gaat verder met het lezen van de invoerstroom vanaf het punt waar de vorige scanf-oproep was gebleven. Als er een scheidingsteken wordt aangetroffen tijdens het lezen van de eerste 20 tekens, stopt scanf met uitvoeren of gaat door met het lezen van de volgende variabele, zelfs als er geen 20 tekens voor de eerste variabele zijn gelezen. In dit geval worden alle niet-getelde tekens aan de volgende variabele gekoppeld.
  • Als de set tekens die moet worden gescand begint met het teken "^", dan leest scanf de gegevens totdat het een scheidingsteken of een teken uit de set tegenkomt. Met "%[^A-E1-5]" worden bijvoorbeeld gegevens uit de stream gelezen totdat een van de Engelse hoofdletters A tot en met E of een van de cijfers 1 tot en met 5 wordt aangetroffen.
  • De functie scanf C retourneert, zoals beschreven, een getal dat gelijk is aan het succesvolle aantal vermeldingen in variabelen. Als scanf 3 variabelen schrijft, is het resultaat: succesvol werk De functie retourneert het getal 3. Als scanf geen variabelen kan schrijven, is het resultaat 0. En ten slotte, als scanf om de een of andere reden helemaal niet kan werken, is het resultaat EOF.
  • Als de functie scanf() zijn werk niet correct heeft voltooid. Scanf("%d", &x) bijvoorbeeld: er werd een getal verwacht, maar er werden symbolen ontvangen als invoer. De volgende scanf()-aanroep begint vanaf het punt in de invoerstroom waar de vorige functie-aanroep eindigde. Om dit probleem te overwinnen, moet je de problematische karakters verwijderen. Dit kan bijvoorbeeld worden gedaan door scanf("%*s") aan te roepen. Dat wil zeggen dat de functie een reeks tekens leest en weggooit. Op deze slimme manier kunt u doorgaan met het invoeren van de benodigde gegevens.
  • Bij sommige implementaties van scanf() is het gebruik van "-" in de tekenset niet toegestaan.
  • De specificatie “%c” leest elk teken uit de stream. Dat wil zeggen dat het ook het scheidingsteken leest. Om het scheidingsteken over te slaan en door te gaan met het lezen van het gewenste teken, kunt u “%1s” gebruiken.
  • Bij gebruik van de “c” specificatie is het acceptabel om de breedte “%10c” te gebruiken, maar dan in de vorm variabele functie scanf moet je een array van char-type elementen doorgeven.
  • “%” betekent “alle kleine letters van het Engelse alfabet”, en “%” betekent eenvoudigweg 3 tekens: ‘z’, ‘a’, ‘-’. Met andere woorden: het teken "-" betekent alleen een bereik als het tussen twee tekens staat die in de juiste volgorde staan. Als "-" aan het einde van een uitdrukking staat, aan het begin, of in de verkeerde volgorde van tekens aan weerszijden ervan, vertegenwoordigt het eenvoudigweg een koppelteken en geen bereik.

Conclusie

Hiermee is de beschrijving van scanf C afgesloten. Het is een goede, handige functie om in te werken kleine programma's en bij gebruik van de procedurele programmeermethode. Het belangrijkste nadeel is echter het aantal onvoorspelbare fouten dat kan optreden bij het gebruik van scanf. Daarom is het het beste om tijdens het programmeren de beschrijving van scanf C voor ogen te houden. In grote professionele projecten worden iostreams gebruikt vanwege het feit dat ze over hogere capaciteiten beschikken, beter in staat zijn fouten op te vangen en te verwerken, en ook met aanzienlijke hoeveelheden informatie werken. Er moet ook worden opgemerkt dat een beschrijving van scanf C in het Russisch beschikbaar is op veel online bronnen, evenals voorbeelden van het gebruik ervan, vanwege de ouderdom van de functie. Daarom kunt u, indien nodig, het antwoord altijd vinden op thematische forums.

#erbij betrekken
int scannenf(const char *formaat, ...);

Functie scanf() vertegenwoordigt een invoerprocedure algemeen doel, die de stream leest stdin en slaat de informatie op in de variabelen die in de argumentenlijst worden vermeld. Het kan alle ingebouwde gegevenstypen lezen en deze automatisch converteren naar het juiste interne formaat.

In versie C99 naar parameter formaat kwalificatie toegepast beperken.

Controlereeks gespecificeerd door parameter formaat, bestaat uit symbolen van drie categorieën:

  • formaatspecificaties;
  • witruimtetekens;
  • andere tekens dan witruimte.

  • Formaatspecificaties beginnen met % en rapportfuncties scanf() het type gegevens dat wordt gelezen. Volgens de specificatie bijvoorbeeld %S de regel wordt gelezen, en volgens de specificatie %D- integere waarde. De formaatreeks wordt van links naar rechts gelezen en de formaatspecificaties worden gekoppeld aan de argumenten in de volgorde waarin ze in de argumentenlijst verschijnen.

    Functie Formaatspecificaties scanf():
    %A Leest een drijvende-kommawaarde (alleen C99)
    %A Hetzelfde als code %A(alleen C99)
    %Met Leest één karakter
    %D Leest een decimaal geheel getal
    %i Leest een geheel getal in elk formaat (decimaal, octaal of hexadecimaal)
    %e
    % E Hetzelfde als code %e
    %F Leest een getal met drijvende komma
    %F Hetzelfde als code %F(alleen C99)
    %G Leest een getal met drijvende komma
    %G Hetzelfde als code %G
    %O Leest een octaal getal
    %S Leest een regel
    %X Leest hexadecimaal getal
    %X Hetzelfde als code %X
    %R Leest de wijzer
    %N Neemt een geheel getal dat gelijk is aan het aantal tot nu toe gelezen tekens
    %u Leest een decimaal geheel getal zonder teken
    % Bekijkt een reeks karakters
    %% Leest het procentteken

    Standaardspecificaties A, F, e En G forceer de functie scanf() wijs gegevens toe aan variabelen van het type vlot. Als u een van deze specificaties voorafgaat met de modifier l, functie scanf() zal de leesgegevens toewijzen variabel type dubbele. Gebruik dezelfde modifier L betekent dat de resulterende waarde wordt toegewezen aan een variabele van het type lange dubbele.

    Moderne compilers die de faciliteiten ondersteunen voor het werken met dubbelbytetekens die in 1995 zijn toegevoegd, stellen u in staat een modifier toe te passen op een specificatie met l; dan wordt aangenomen dat de overeenkomstige aanwijzer naar een dubbelbyteteken wijst (d.w.z. gegeven soort wchar_t). Wijziger l kan ook worden gebruikt met formaatcode S; de overeenkomstige aanwijzer wordt dan geacht te verwijzen naar een reeks dubbelbytetekens. Daarnaast de modificator l kan worden gebruikt om aan te geven dat de tekenset die wordt gescand, uit dubbelbytetekens bestaat.

    Als er een scheidingsteken in de formaattekenreeks staat, dan is de functie scanf() slaat een of meer scheidingstekens in de invoerstroom over. Een scheidingsteken of witruimteteken betekent een spatie, tab of regelscheidingsteken (nieuwe regel). In wezen zal het hebben van een enkel scheidingsteken op de controleregel de functie veroorzaken scanf() leest, zonder op te slaan, een willekeurig aantal (mogelijk zelfs nul) scheidingstekens tot aan het eerste niet-scheidingsteken.

    Als er in de formatstring een ander teken dan een scheidingsteken wordt aangetroffen, dan wordt de function scanf() leest het en gooit het weg. Als de opmaakregel bijvoorbeeld %D, %D en vervolgens de functie scanf() zal eerst de gehele waarde lezen, vervolgens de komma lezen en weggooien, en uiteindelijk een ander geheel getal lezen. Als het opgegeven teken niet wordt gevonden, wordt de function scanf() voltooit de klus.
    Alle variabelen die waarden ontvangen met behulp van de functie scanf(), moeten via hun adressen worden verzonden. Dit betekent dat alle argumenten verwijzingen naar variabelen moeten zijn.
    Elementen van de invoerstroom moeten worden gescheiden door spaties, tabtekens of regelscheidingstekens. Tekens zoals komma, puntkomma, etc. worden niet herkend als scheidingstekens. Dit betekent dat de exploitant
    scannenf("%d%d", &r, enz); accepteert waarden ingevoerd als 10 20, maar verwerpt de tekenreeks 10,20.

    Symbool * , staande na het bord % en vóór de formaatcode leest gegevens van het opgegeven type, maar verbiedt de toewijzing ervan. Daarom de exploitant
    scannenf("%d%*c%d", &x, &y); wanneer ingevoerd als 10/20, wordt de waarde 10 in de x-variabele geplaatst, wordt het deelteken weggegooid en wordt de waarde 20 aan de y-variabele toegewezen.

    Opmaakopdrachten kunnen een modifier voor de maximale veldlengte bevatten. Het is een geheel getal dat tussen het teken wordt geplaatst % en een formaatcode die het aantal gelezen tekens voor alle velden beperkt. Als er bijvoorbeeld niet meer dan 20 tekens in de adresvariabele hoeven te worden gelezen, wordt de volgende instructie gebruikt.
    scannenf("%20s", adres);
    Als de invoerstroom meer dan 20 tekens bevat, begint het lezen de volgende keer dat de invoerbewerking wordt geopend vanaf de plaats waar de vorige functieaanroep "stopte" scanf(). Als de separator wordt aangetroffen vóór de maximale lengte velden, de gegevensinvoer is voltooid. In dit geval de functie scanf() gaat verder met het lezen van het volgende veld.

    Hoewel spaties, tabs en regelscheidingstekens worden gebruikt als veldscheidingstekens, worden ze bij het lezen van één teken net als elk ander teken gelezen. Als de invoerstroom bijvoorbeeld uit de tekens x y bestaat, dan is de operator
    scannenf("%c%c%c", &a, &b, &c); plaatst het teken x in variabele a, de spatie in variabele b en het teken y in variabele c.

    Vergeet niet dat alle symbolen controle lijn(inclusief spaties, tabs en nieuwe regels), die geen formaatspecificaties zijn, worden gebruikt om tekens uit de invoerstroom te matchen en te verwijderen. Elk teken dat daarmee overeenkomt, wordt weggegooid. Als de invoerstroom er bijvoorbeeld uitziet als 10t20, wordt de instructie
    scannenf("%dt%d", &x, &y); zal x de waarde 10 toekennen en y de waarde 20. Het t-teken wordt weggegooid omdat het aanwezig is in de controlereeks.

    Functie scanf() ondersteunt een formaatspecificatie voor algemene doeleinden genaamd set gescande tekens (scanset),In dit geval wordt een reeks tekens gedefinieerd die kunnen worden gelezen door de functie , scanf() en toegewezen aan de overeenkomstige tekenarray. Om een ​​dergelijke set te definiëren, moeten de te scannen tekens tussen vierkante haken staan. De openingsvierkante haak moet onmiddellijk het procentteken volgen. De volgende reeks gescande tekens geeft bijvoorbeeld aan dat alleen de tekens A, B en C mogen worden gelezen.
    % Bij gebruik van een gescande tekenset kan de functie scanf() gaat door met het lezen van tekens en plaatst deze in de juiste tekenarray totdat het een teken tegenkomt dat niet in de gegeven set voorkomt. De corresponderende setvariabele moet een verwijzing naar een karakterarray zijn. Bij terugkomst van een functie scanf() deze array bevat een reeks gelezen tekens, eindigend met een teken aan het einde van de regel.

    Als het eerste teken in de set een teken is ^ , dan krijgen wij omgekeerde werking: Het invoerveld wordt gelezen totdat een teken uit de opgegeven set gescande tekens wordt aangetroffen, d.w.z. teken ^ forceert de functie scanf() lees alleen de tekens die niet voorkomen in de reeks tekens die wordt gescand.
    Bij veel implementaties kan een bereik worden opgegeven met behulp van een koppelteken. De functie bijvoorbeeld scanf(), waarbij u een reeks gescande tekens in het formulier tegenkomt % , leest tekens die binnen het bereik van A tot Z vallen.

    Het is belangrijk om te onthouden dat de reeks tekens die wordt gescand, verschilt tussen hoofdletters en kleine letters. Als u zowel hoofdletters als kleine letters wilt scannen, moet u deze daarom afzonderlijk opgeven in de reeks tekens die u wilt scannen.

    Functie scanf() retourneert een getal dat gelijk is aan het aantal velden waaraan waarden zijn toegewezen. Deze velden bevatten niet de velden die zijn gelezen, maar de toewijzing heeft niet plaatsgevonden vanwege het gebruik van een modifier * , toewijzing onderdrukken. Als er een fout wordt gedetecteerd voordat de waarde van het eerste veld is toegewezen, wordt de functie scanf() geeft waarde terug EOF.

    Formaatmodifiers toegevoegd aan een functie scanf() Standaard C99

    In versie C99 voor gebruik in de functie scanf() formaatmodifiers toegevoegd hh, ll, J, z En T. Wijziger hh kan worden toegepast op specificaties D, i, O, u, X En N ondertekende char of Ongetekend char. Wijziger ll kan ook worden toegepast op specificaties D, i, O, u, X En N. Het betekent dat het corresponderende argument een verwijzing is naar een waarde van het type ondertekend lang lang int of niet ondertekend lang lang int.

    Formaatmodificator J D, i, O, u, X En N, betekent dat het overeenkomstige argument een verwijzing is naar een waarde van het type intmax_t of uintmax_t. Deze typen worden in de header aangegeven en worden gebruikt om gehele getallen met de maximaal mogelijke capaciteit op te slaan.

    Formaatmodificator z, wat van toepassing is op specificaties D, i, O, u, X En N maat_t en dient om het resultaat van de operatie op te slaan De grootte van.

    Formaatmodificator T, wat van toepassing is op specificaties D, i, O, u, X En N, betekent dat het overeenkomstige argument een verwijzing is naar een object van het type ptrdiff_t. Dit type wordt aangegeven in de header en dient om de verschilwaarde tussen twee wijzers op te slaan.

    Terwijl de functie printf() geformatteerde uitvoer levert, biedt de functie scanf() geformatteerde invoer. Dit betekent dat de invoergegevens volgens de opgegeven format(en) worden geconverteerd en naar de adres(sen) van de opgegeven variabele(n) worden geschreven:

    Scanf(format_string, variabele_adressen);

    De reden waarom scanf() adressen doorgeeft in plaats van variabele waarden ligt voor de hand. De functie scanf() moet de waarden wijzigen van de variabelen van de functies waaruit deze wordt aangeroepen. De enige manier- dit is om de adressen van geheugengebieden te verkrijgen.

    De gegevensformaatspecificaties die zijn toegestaan ​​in de formaatreeks voor scanf() zijn vrijwel identiek aan de specificaties die zijn beschreven voor de printf()-functie. In deze les gaan we niet in detail in op alle mogelijkheden van geformatteerde invoer met behulp van scanf() , maar bekijken we een aantal specifieke voorbeelden.

    Cijfers, symbolen en tekenreeksen invoeren

    Voorbeeld van invoer/uitvoer van gehele en reële getallen, karakter en string:

    int a; vlotter b; char ch, str[30] ; scanf ("%d%f%c%s" , & a, & b, & ch, str) ; printf("%d%.3f %c %s \N", a, b, ch, str) ;

    Resultaat:

    45 34.3456y hallo 45 34.346y hallo

    Hier werden, toen het programma werd uitgevoerd, alle gegevens op één regel ingevoerd. Het scheidingsteken tussen cijfers en tekenreeksen is een spatie, evenals elk ander witruimteteken (bijvoorbeeld "\n"). Bij het lezen van een teken wordt de spatie echter als teken geteld; Om dit te voorkomen, werd in het voorbeeld de letter direct na het cijfer geschreven. Gegevens kunnen worden ingevoerd door ze te scheiden door naar te gaan nieuwe lijn(nogmaals, u moet er rekening mee houden hoe het symbool wordt gelezen).

    In de formatstring van de scanf() functie is het volkomen acceptabel om spaties tussen specificaties te plaatsen: %d %f %c %s . Zij zullen geen enkele rol spelen. Het is duidelijk dat de gegevens als volgt kunnen worden verkregen:

    scanf ("%d" , & a) ; scanf ("%f", &b) ; scanf ("%c" , & ch) ; scanf ("%s" , str) ;

    Houd er rekening mee dat er geen ampersand vóór de str-variabele staat. Dit is geen typefout. In de volgende lessen zul je leren dat de naam van een array zelf een verwijzing naar de array is (met andere woorden: str bevat het adres van het begin van de array).

    In de functie scanf() specificeert de specificatie van het reële getalformaat niet de nauwkeurigheid van de getalrepresentatie. Als u %.3f of %.10lf schrijft, kunt u geen reëel getal verkrijgen. Om een ​​nummer van het type double te krijgen, gebruikt u het formaat %lf, voor long double - %Lf.

    Voor gehele getallen: lang geheel getal - %ld, kort geheel getal - %hd. Daarnaast zijn er specificaties voor het invoeren van octale en hexadecimale getallen.

    De functie scanf() retourneert het aantal succesvol gelezen gegevens; die. De door de functie geretourneerde waarde kan worden geanalyseerd om te bepalen of de gegevens correct zijn ingevoerd. Bijvoorbeeld:

    int a; dubbele b; char ch, str[30] ; ch = scanf ("%d %lf %s" , & a, & b, str) ; if (ch == 3 ) printf ("%d %.3lf %s \N", a, b, str) ; else printf("Fout bij invoer \N") ;

    Gebruik van gewone karakters

    Reguliere tekens zijn toegestaan ​​in de tekenreeks scanf(). In dit geval moeten bij het invoeren van gegevens ook deze tekens worden ingevoerd:

    int a, b, c; scanf ("%d + %d = %d" , &a, &b, &c) ; printf("Je antwoord is %d \nHet juiste antwoord is %d\n ", c, a+ b) ;

    In dit geval, wanneer het programma wordt uitgevoerd, zou de invoer er ongeveer zo uit moeten zien: 342+1024 = 1366. De tekens “+” en “=” moeten aanwezig zijn tussen de cijfers; de aanwezigheid van spaties of de afwezigheid ervan speelt absoluut geen rol. rol:

    45 + 839=875 Jouw antwoord is 875 Het juiste antwoord is 884

    Geen opdracht

    Als gegevens die door de gebruiker zijn ingevoerd, moeten worden genegeerd, gebruik dan het toewijzingsverbod door een asterisk * na het %-teken te plaatsen, maar vóór de opmaakletter. In dit geval worden de gegevens gelezen, maar niet aan een variabele toegewezen. Dit kan bijvoorbeeld worden gebruikt wanneer er enerzijds geen zekerheid bestaat over wat er als input wordt ontvangen en anderzijds de noodzaak om deze gegevens op te slaan:

    vlotter arr[3] ; int ik; voor (ik = 0; ik< 3 ; i++ ) scanf ("%*s %f" , & arr[ i] ) ; printf ("Sum: %.2f\N", arr[ 0 ] + arr[ 1 ] + arr[ 2 ] );

    Hierbij wordt ervan uitgegaan dat elk getal wordt voorafgegaan door een regel die moet worden genegeerd, bijvoorbeeld:

    Eerste: 23.356 Tweede: 17.285 Derde: 32.457 Som: 73.098

    "Sjablonen" gebruiken

    Er zijn een aantal formaatspecificaties voor de scanf()-functie die vaag op sjablonen lijken schelp enz. Met het formaat […] kunt u een string verkrijgen die alle tekens bevat die zijn opgegeven in vierkante haakjes. Zodra een teken wordt ingevoerd dat niet in de opgegeven set voorkomt, stopt het lezen van gegevens. Het [^...]-formaat daarentegen plaatst tekens die niet in de opgegeven set voorkomen in de string totdat deze een van de opgegeven tekens tegenkomt.

    In het onderstaande voorbeeld is het lezen van de invoer voltooid zodra een niet-cijfer wordt ontvangen. Bovendien, als het eerste teken geen getal is, wordt er helemaal niets naar str geschreven:

    char str[30] = "" ; scanf ("%" , str) ; printf("%s \N", str) ;

    En in dit geval krijgt de string een reeks tekens toegewezen vóór een van de opgegeven leestekens:

    scanf ("%[^;:,!?]" , str) ; printf("%s \N", str) ;

    Resultaat:

    Hallo Wereld! Hallo

    Enkele functies en beperkingen van de scanf()-functie

    Zodra er ongeldige gegevens binnenkomen, wordt de functie scanf() afgesloten. In het voorbeeld:
    scanf ("%d%f", &a, &b) ;

    Als u probeert een teken of string toe te wijzen aan variabele a, wat onmogelijk is, wordt variabele b niet langer verwerkt. Aangenomen kan worden dat dit betrouwbaarder zal zijn:

    scanf ("%d" , &a) ; scanf ("%f", &b) ;

    Het lijkt erop dat een mislukte lezing van a geen enkel effect zou moeten hebben op b, omdat dit is een andere scanf()-aanroep. Maar niet alles is zo eenvoudig: als de invoer onjuist is, blijven de gegevens in de buffer en proberen ze zichzelf op te dringen bij daaropvolgende scanf()-aanroepen. Daarom moet u bij het gebruik van scanf() nadenken over hoe in dit geval onjuiste invoer duidelijke buffer. Dit kan bijvoorbeeld worden gedaan zoals hieronder weergegeven, of door gebruik te maken van speciale functies(hier niet behandeld):

    als (scanf ("%d" , & a) != 1 ) // als de gegevens niet aan een variabele konden worden toegewezen, scanf("%*s"); // gooi ze dan weg als een string. scanf ("%f", &b) ;

    Het gegevensscheidingsteken voor scanf() bestaat uit witruimtetekens. Dit betekent dat er geen manier is om een ​​string met een onbekend aantal spaties in een enkele variabele te schrijven met alleen scanf(). U zult een andere functie moeten gebruiken (bijvoorbeeld getchar()), of een cyclische constructie moeten maken die één woord tegelijk leest en dit aan de totale reeks toevoegt.

    Ondanks de vrij grote mogelijkheden van scanf() brengt deze functie dus een aantal ongemakken en gevaren met zich mee.

    Probleemoplossing

    1. In de vorige les heb je een programma geschreven met functies die de faculteit van een getal en berekenen gegeven element Fibonacci-reeks. Pas dit programma zo aan dat het de gebruiker vraagt ​​of hij de faculteit of het Fibonacci-getal wil berekenen. Het programma vraagt ​​de gebruiker dan om het getal om de faculteit of het elementnummer van de Fibonacci-reeks te berekenen.
    2. Schrijf een programma dat de gebruiker om twee datums vraagt ​​in het formaat dd.mm.jjjj. Dagen, maanden en jaren moeten worden toegewezen aan variabelen met gehele getallen. Het programma moet informatie op het scherm weergeven over welke datum eerder is en welke later.
    3. Schrijf met behulp van een lus code die de gebruiker vraagt ​​gegevens in te voeren totdat hij dit correct doet, d.w.z. totdat alle variabelen gespecificeerd in scanf() hun waarden ontvangen. Test het programma.

    Tags: Geformatteerde invoer, geformatteerde uitvoer, printf, scanf, fgets, getch, formaatstring, formaatspecificatie, vlaggen, controletekens.

    Geformatteerde uitvoer

    Vandaag zullen we er twee bekijken belangrijke functies geformatteerde invoer en uitvoer. De structuur en werking van deze functies kunnen pas volledig worden begrepen na bestudering van het werken met pointers en functies variabel getal parameters. Maar u moet deze functies nu gebruiken, dus u zult enkele punten moeten overslaan.

    De geformatteerde uitvoerfunctie printf neemt als argumenten de formatstring en de argumenten die moeten worden afgedrukt volgens het formaat, en retourneert het aantal afgedrukte tekens. Retourneert in geval van een fout een negatieve waarde en stelt de waarde in op ferror. Als er meerdere fouten zijn opgetreden, is errno EILSEQ.
    int printf(const char * formaat, ...);

    #erbij betrekken #erbij betrekken void main() ( //de functie ontvangt geen andere argumenten dan de string printf("Hallo wereld"); getch(); )

    De functie doorloopt de tekenreeks en vervangt de eerste keer dat % voorkomt door het eerste argument, de tweede keer dat % voorkomt door het tweede argument, enzovoort. Vervolgens kijken we eenvoudig naar de lijst met vlaggen en gebruiksvoorbeelden.

    Syntaxis van algemene formaatspecificatie
    %[flags][width][.precision][length] specificatie
    De specificatie is het meest belangrijk onderdeel. Het definieert het type variabele en hoe deze wordt uitgevoerd.

    Tab. 1 Typespecificatie.
    Specificator Wat willen we uitstralen? Voorbeeld
    d of ik Geheel getal met inloggen decimale 392
    u Niet-ondertekend geheel getal in decimale notatie 7235
    O Ongesigneerd in octaal 657
    X Niet-ondertekend geheel getal in hexadecimaal 7fa
    X Niet-ondertekend geheel getal in hexadecimaal, hoofdletter 7FA
    f of F Drijvende-kommagetal 3.4563745
    e Wetenschappelijke vorm voor getallen met drijvende komma 3.1234e+3
    E Exponentiële vorm voor drijvende-kommagetallen, in hoofdletters 3,1234E+3
    G Kortste weergave van f- en e-formaten 3.12
    G Kortste weergave van de formaten F en E 3.12
    A Hexadecimale weergave van een getal met drijvende komma -0xc.90fep-2
    A Hexadecimale weergave met drijvende komma, hoofdletters -0xc.90FEP-2
    C Brief A
    S String (op nul eindigende reeks letters) Hallo Wereld
    P Wijzer adres b8000000
    N Er wordt niets afgedrukt. Het argument moet een verwijzing zijn naar een ondertekende int. Het aantal brieven dat vóór de %n vergadering is afgedrukt, wordt op dit adres opgeslagen
    % Twee opeenvolgende percentages geven een procentteken weer %

    #erbij betrekken #erbij betrekken void main() ( int a = 0x77, b = -20; char c = "F"; float f = 12.2341524; double d = 2e8; char* string = "Hallo wereld!"; printf("%s\n ", string); printf("a = %d, b = %d\n", a, b); printf("a = %u, b = %u\n", a, b); printf(" a = %x, b = %X\n", a, b); printf("dec a = %d, oct a = %o, hex a = %x\n", a, a, a); printf ("zwevende komma f = %f, exp f = %e\n", f, f); printf("dubbele d = %f of %E\n", d, d, d); ); printf("teken c = %c, als getal c = %d", c, c);

    De formaattekenreeks kan ook de volgende optionele subspecificaties bevatten: vlag, breedte, precisie en modifier (in die volgorde).

    Tab. 4 Nauwkeurigheid.
    .Nauwkeurigheid Beschrijving
    .nummer Voor geheeltallige specificaties (d, i, o, u, x, X) bepaalt de precisie minimale hoeveelheid tekens die moeten worden weergegeven. Als de waarde korter is, worden er nullen vóór het getal afgedrukt. De waarde wordt niet afgekapt, ook al is deze langer. Een nauwkeurigheid van 0 betekent dat er niets wordt uitgevoerd voor een waarde van 0.
    Voor specificaties met drijvende komma (a, A, e, E, f, F) is dit het aantal cijfers dat moet worden afgedrukt na de komma (standaard 6).
    Voor g en G is dit het aantal significante cijfers dat moet worden uitgevoerd.
    Voor s wordt het opgegeven aantal tekens weergegeven. Standaard worden alle tekens tot aan de voorloopnul weergegeven.
    Als het getal niet aanwezig is, is de standaardprecisie 0
    .* De precisie wordt niet gespecificeerd in de formatstring, maar wordt afzonderlijk doorgegeven als argument, dat vooraf moet gaan aan het uitvoernummer

    #erbij betrekken #erbij betrekken void main() ( int a = 0x77, b = -20; char c = "F"; float f = 12.2341524; double d = 2e2; char* string = "Hallo wereld!"; printf("%.3f\ n", f); printf("%.*f\n", 2, f); printf("%010.3f\n", d); printf("%*d\n", 6, a); printf("%+d\n", b); printf("%0.6d\n", a); printf("%.f\n", d); haal();

    De lengte-subspecificatie verandert de lengte van het type. Indien de lengte niet overeenkomt met het type, wordt deze indien mogelijk omgerekend naar het gewenste type.

    Tab. 5 Lengte.
    specificeerders
    Lengte d, ik u o x X f F e E g G een A C S P N
    (geen) int niet ondertekend int dubbele int teken* leegte* int*
    hh ondertekende char Ongetekend char ondertekend teken*
    H korte int niet-ondertekende korte int korte int*
    l lang int niet-ondertekend lange int wint_t wchar_t* lange int*
    ll lang lang int niet ondertekend lang lang int lang lang int*
    J intmax_t uintmax_t intmax_t*
    z maat_t maat_t maat_t*
    T ptrdiff_t ptrdiff_t ptrdiff_t*
    L lange dubbele

    #erbij betrekken #erbij betrekken void main() ( lang lang x = 12300000000579099123; kort i = 10; printf("%llu\n", x); printf("%d\n", i); printf("%hd\n", i );

    Geformatteerde invoer

    Laten we eens kijken naar geformatteerde invoer met behulp van de scanf-functie.
    int scanf(const char*, ...)
    De functie accepteert een invoerformaatreeks (deze is vergelijkbaar met de printf-formaatreeks) en adressen waarnaar de gelezen gegevens moeten worden geschreven. Retourneert het aantal succesvol geïnitialiseerde argumenten.
    Formaat invoerspecificatie
    %[*][width][length]kwalificatie

    Tab. 6 Typespecificatie.
    Specificator Beschrijving Geselecteerde karakters
    ik, u Geheel Een willekeurig aantal cijfers (0-9), mogelijk beginnend met + of -. Als het getal begint met 0, wordt het in octaal formaat gelezen, als het begint met 0x, dan in hexadecimaal.
    D Decimaal geheel getal Een willekeurig aantal cijfers (0-9), mogelijk beginnend met + of -.
    O octaal geheel getal Een willekeurig aantal cijfers (0-7), mogelijk beginnend met + of -.
    X Hexadecimaal geheel getal Een willekeurig aantal cijfers (0-F), mogelijk beginnend met + of - en voorafgegaan door 0x of 0X.
    f, e, g Drijvende-kommagetal Een getal dat bestaat uit een reeks cijfers 0-9, mogelijk met een decimaalteken (punt). Het is ook mogelijk om het in exponentiële vorm weer te geven. Met C99 kunt u ook een getal in hexadecimaal formaat invoeren.
    A
    C Symbool Als de breedte niet wordt doorgegeven, wordt er één teken gelezen. Als breedte wordt doorgegeven, wordt het vereiste aantal tekens gelezen en in de array geplaatst ZONDER het terminalteken aan het einde.
    S Lijn Leest alle niet-witruimtetekens. Als breedte is opgegeven, dan niet meer dan n tekens. Vervangt n+1 eindtekens.
    P Wijzer adres Een reeks tekens die worden geïnterpreteerd als een pointeradres. Het formaat is afhankelijk van de implementatie, maar is hetzelfde als wat printf uitvoert met de p-optie
    [karakters] Veel symbolen Leest alleen de tekens die tussen vierkante haakjes staan, C99
    [^tekens] Veel symbolen Leest alleen de tekens die niet tussen vierkante haakjes staan, C99
    N Leest niets Slaat het aantal tekens op dat al op het opgegeven adres is gelezen

    Net als in printf verwacht de breedte gespecificeerd door * een argument dat de breedte specificeert. De lengtevlag is hetzelfde als de printf-functievlag.

    #erbij betrekken #erbij betrekken void main() ( int jaar, maand, dag; char buffer; int count; //Vereist geformatteerde invoer, bijvoorbeeld 2013:12:12 printf("Voer gegevens in zoals x:x:x = "); scanf("% d :%d:%d", &jaar, &maand, &dag); printf("jaar = %d\nmaand = %d, dag = %d\n", jaar, maand, dag); //Lees de regel, geen 127 tekens meer. U hoeft geen & te schrijven, //aangezien de array is vervangen door een pointer printf("Enter string = "); "%s", getch();

    Behalve scanf-functies en printf zijn er nog een aantal andere functies waarmee u invoergegevens kunt ontvangen

    int getch()- retourneert het ingevoerde teken, maar voert het niet uit naar de console. #erbij betrekken #erbij betrekken void main() ( char c = 0; do ( c = getch(); printf("%c", c); ) while (c != "q"); )

    char * fgets (char * str, int num, FILE * stream)- met de functie kunt u een string met witruimtetekens lezen. Hoewel het met een bestand werkt, kan het ook gebruikt worden om uit de standaard invoerstroom te lezen. Het voordeel ten opzichte van Gets is dat u hiermee kunt specificeren maximumgrootte de regel die wordt gelezen en eindigt de regel met een terminalteken.

    #erbij betrekken #erbij betrekken #erbij betrekken void main() ( char buffer; //Lezen uit standaardinvoer fgets(buffer, 127, stdin); printf("%s", buffer); //Dit kan het wachten op het invoeren van een teken vervangen scanf("1" );

    Is niet volledige set verschillende symbolische invoer- en uitvoerfuncties. Er zijn veel van dergelijke functies, maar veel ervan zijn onveilig. Lees daarom de documentatie zorgvuldig door voordat u ze gebruikt.