Documente Academic
Documente Profesional
Documente Cultură
Instrucțiuni Intrare/Ieșire
Introducere
În majoritatea cazurilor aplicațiile interacționează cu utilizatorul, fie într-un sens (prin
afișarea unor informații), fie în celălalt sens (prin citirea datelor date de utilizator sau din alte
surse), fie în ambele sensuri (citire și afișare). Limbajul C/C++ pune la dispoziția programatorului
mai multe funcții pentru efectuarea operațiilor de intrare/ieșire (I/O). Aceste funcții se găsesc în
bilbiotecile compilatorului, pentru limbajul C biblioteca care conține funcțiile I/O este stdio.h.
1. Instrucțiuni de ieșire
Operația de iesire a datelor din program către utilizator (consolă sau fișier) se mai
numește și afișare a datelor. Biblioteca stdio.h pune la dispoziția programatorului funcții
pentru:
- afișarea caracterelor - putc(), fputc(), putchar()
- afișarea șirurilor de caractere - puts(), fputs()
- afișarea formatată (cu specificarea detaliată a modului de afișare) a datelor - printf(),
fprintf()
O parte din aceste funcții se folosesc pentru scrierea datelor în fișiere de date si vor fi
studiate în alte capitole. Programele vor afișa datele la terminalul standard de ieșire stdout
(consola în cazul nostru) și vor citi datele de la terminalul standard de intrare stdin (tot consola
dar în momentul în care aceasta permite introducerea datelor de la tastatură). Trebuie avut în
vedere că din punct de vedere al SC, atât stdout cât și stdin sunt accesate ca niște fișiere de
date, utilizarea acestora fiind implicită în cazul în care nu se specifică alte resurse ca fișiere de
date.
1
Prototipurile (signaturile) funcțiilor de afișare a datelor sunt următoarele:
#include <stdio.h>
În signaturile funcțiilor de mai sus acolo unde este specificată variabilă de tip FILE
*stream trebuie specificată o resursă de tip fișier, aceste funcții vor fi discutate ulterior.
A. Afișarea caracterelor
Pentru afișarea caracterelor la ieșirea standard se va utiliza funcția putchar() din biblioteca
stdio.h a cărei primitivă este afișată mai sus. Funcția afișează (“pune”) în consolă un caracter al
cărui cod ASCII este furnizat ca argument al funcției (int c). Funcțiilepentru afișarea caracterelor
nu adaugă după caracterul afișat și carcaterul special ‘\n’ care semnifică linie nouă. Dacă se
dorește trecerea la o altă linie in terminal (sau fișier) se va trimite spre afișare caracterul special
‘\n’.
Alte caractere speciale:
\b 08 Backspace
\n 0A Linie nouă(Line
Feed);
2
Carriage Return
\r 0D
Horizontal Tab
\t 09
Vertical Tab
\v 0B
Backslash
\\ 5C
Apostrof
\' 27
Ghilimele
\" 22
Semnul ?
\? 3F
#include <stdio.h>
int a = ‘P’;
int b = 65 + 2; // ‘A’ = 65
putchar(a);
putchar(b);
putchar(a-4);
putchar(a);
Având în vedere că și funcțiile putc() și fputc() afișează un caracter, dar într-un fișier, dacă
fișierul specificat va fi stdout, efectul funcției putc() sau fputc() va fi același ca al funcției
putchar().
putc(‘P’, stdout);
fputc(‘C’,stdout);
3
B. Afișarea șirurilor de caractere
S-a vazut la capitolul “Arii de date” că se pot crea zone de memorie care pot reține șiruri de
caractere. Pentru a afișa șirurile de caractere păstrate în astfel de zone de memorie se poate
apela și funcțiile puts() sau fputs(). Diferența este că una dintre ele are ca argumente și numele
unui fișier pentru ieșire (cea care are ca prefix litera f ).
Un exemplu de utilizare puts() și fputs() este listat mai jos:
puts(disciplina1);
puts(" si");
fputs(disciplina2,stdout);
Funcția puts() adaugă implicit la sfârșitul textului aifșat caracterul ‘\n’ astfel că următoarea
afișare se va face pe linia următoare. Funcția fputs() nu adaugă carcaterul ‘\n’.
OBS. Funcțiile afișează conținutul memoriei care începe de la adresa (const char *)
furnizată ca argument. Sfârșitul șirului este semnalat prin prezența caracterului ‘\0’ (carcaterul
NULL, neprintabil). În exemplul nostru dimensiunea variabilei de tip arie de caractere
disciplina1 este de 6 caractere, primele 5 fiind literele PCLP1, al 6-lea carcater fiind caracterul
‘\0’ care semnalizează și sfârșitul șirului disciplina1. Dacă dintr-o greșeală de programare
caracterul ‘\0’ este șters, funcția va afișa toate caracterele care încep de la adresa indicată până
la apariția primului ‘\0’.
C. Afișarea cu format
Cea mai utilizată funcție utilizată pentru afișare este funcția de afișare cu format printf()
deoarece permite personalizare completă a valorilor afișate. Practic, orice mod de afișare a
unor variabile este posibil.
Vom aminti din nou primitiva funcției printf():
4
Din linia de declarare a funcției se observă că singurul argument (parametru)
obligatoriu este formatul textului care se dorește a fi afișat. Textul respectiv trebuie să
conțină formatul (modul de vizualizare) datelor variabile ce urmează a fi afișate. În
limbajul de programare C, setul “...” în signatura unei funcții semnifică faptul că se pot
introduce 0 sau mai multe argumente.
Funcția printf() convertește, formatează și afișează argumentele la ieșirea standard
efectuând conversiile specificate în formatul textului. Acesta este alcătuit din două feluri
de caractere:
- caractere normale, care sunt pur și simplu copiate în consolă, printre acetsea se
numără și carcaterele speciale prefixate de ‘\’
- specificatori de format.
Specificatorii de format descriu cum parametrul respectiv (aflat în lista parametrilor
de după ”,”) va fi convertit și formatat inainte de afișare. Numărul și tipul specificatorilor
de format trebuie să fie identic cu cel al argumentelor următoare, în caz contrar,
afișarea fiind incorectă și impredictibilă.
Principalii specificatori de format sunt:
- %c - afișează un caracter
- %d - afișează un număr întreg în baza 10
- %x - afișează un număr întreg în baza 16
- %f - afișează un număr real de precizie simplă sau dublă (float sau double),
implicit afișează 6 zecimale
- %p - afișează o valoare de tip pointer (adresa unei locații de memorie)
- %s - afișează un șir de caractere începând de la adresa furnizată ca argument
până la primul caracter ‘\0’. Atenție: în cazul ariilor de date numele tabloului
coincide cu adresa de memorie de unde începe tabloul de date.
5
Corespondența dintre specificatorii de format și tipurile de variabile este afișată în
tabelul următor:
int %d, %x
unsigned int %u
float %f %g %e %E
Afișare personalizată
Pentru afișare personalizată specificatorul de format se poate introduce si sub
forma urmatoare:
%[flags][width][.precision]specifier
unde:
● flags:
- Aliniere la stânga corespunzător dimensiunii câmpului – dat de width. Alinierea la
dreapta este implicită.
Ex. printf("%20d...\n%-20d...",10,10); va afișa
10… //afisare aliniată la dreapta spațiului prevăzut
10 … //afisare aliniată la stânga spațiului prevăzut
6
+ Forțează apariția semnului valorii (+ sau -) chiar pentru numerele pozitive. Implicit,
numai numerele negative vor fi afișate precedate de semn. Acest lucru poate fi util în
cazurile în care se dorește afișarea numerelor ca operanzi si se poate evita apariția
semnului - după +.
Ex. printf("%+d",10); va afișa
+10 //afisare cu forțarea semnului
● width:
valoare numerică – (s-a folosit în exemplele de mai sus) numărul minim de caractere pe
care va fi afișată valoarea. Dacă valoarea are mai puține caractere decât numărul
prevăzut aici, se va completa cu spații sau cu zerouri (corespunzător cu flags). Valorile
nu se trunchiază, astfel că dacă valoarea de afișat are mai multe caractere ea va fi afișată
în totalitate.
* - dimensiunea nu este dată numeric, ci este furnizată de o variabilă situată în lista
argumentelor înaintea valorii ce trebuie afișată. Dacă sunt mai multe variabile de afișat,
valoarea corespunzătoare * va fi furnizată imediat înaintea variabilei de afișat.
Ex. printf("%0*d",5,10); va afișa
7
00010 //afișare cu completare cu zerori, pe * carcatere, * = 5 (primul
argument)
● precision:
.valoare – pentru specificatorii de tip întreg (d, i, o, u, x, X): specifică numărul de
caractere pentru afișare (dar completează cu zerouri). Pentru specificatorii de tip real
(e,E,f) valoarea reprezintă numărul de zecimale.
* - numărul de zecimale nu este dat de o valoare explicită ci se regăsește ca variabilă în
lista argumentelor.
Ex. printf("%10.5d",10); va afișa
00010 //afișare pe 10 caractere, 5 prin completare cu zerouri
● %n:
Nu este foarte folosit dar va salva numărul total de caractere tipărite în locația
specificată ca argument, asemănător valorii de tip int returnte de printf().
Ex. int nrCaractere1;
int nrCaractere2;
nrCaractere1 = printf("%d %4.2f%n",21,12.345678,&nrCaractere2);
printf("\n%d caractere \n%d caractere",nrCaractere1, nrCaractere2);
va afișa:
21 12.35
8 caractere
8 caractere
8
Un exemplu complet de afișare cu format este prezentat în figura următoare:
Programul va afișa:
9
int nota1 = 10;
int nota2 = 7;
printf("Suma notelor = %d", nota1 + nota2);
Suma notelor = 17
10
Prototipurile (signaturile) funcțiilor de citire a datelor sunt următoarele:
#include <stdio.h>
În signaturile funcțiilor de mai sus acolo unde este specificată variabilă de tip FILE
*stream trebuie specificată o resursă de tip fișier, aceste funcții vor fi discutate ulterior.
A. Citirea caracterelor
Pentru citirea caracterelor de la intrarea standard se va utiliza funcția getchar() din
biblioteca stdio.h a cărei primitivă este afișată mai sus. Funcția citește din consolă un caracter al
cărui cod ASCII este returnat în program.
Exemple de apel al funcției getchar():
int a;
a = getchar();
putchar(a + 1);
În momentul rulării acestui program consola IDE-ului va deveni activă afișând un cursor
care semnifică faptul că se așteaptă introducerea unor valori. Pentru a obține aplicații ușor de
rulat (“user-friendly”) este indicat ca orice etapă de citire date din consolă să fie precedată de o
instrucțiune de afișare a unui mesaj ajutător. De exemplu, programul de mai sus ar fi mai
intuitiv dacă ar fi avut următorul cod sursă:
int a;
puts("Introduceti un caracter si apoi apsati Enter:");
a = getchar();
puts("Caracterul alfabetic urmator celui introdus este:");
putchar(a + 1);
11
În momentul rulării acest program va afișa primul mesaj, va aștepta introducerea unui
caracter și apăsarea tastei Enter și apoi va trece la afișarea celui de-al doilea mesaj și a
carcaterului specificat ca argument.
Exemplificăm consola aplicației pentru cazul în care s-a tastat caracterul ‘r’:
Având în vedere că și funcțiile getc() și fgetc() citesc un caracter, dar dintr-un fișier, dacă
fișierul specificat va fi stdin, efectul funcției getc() sau fgetc() va fi același ca al funcției
getchar(). De aceea, caracterele mai pot fi citite și astfel:
int a;
a = getc(stdin);
// sau
a = fgetc(stdin);
Trebuie menţionat că atunci cînd se introduc date de la tastatură, toate valorile introduse
sunt salvate într-un buffer (zonă memorie tampon) de intrare, citirea terminându-se în
momentul apăsării tastei Enter. În buffer-ul de intrare, la sfârşitul caracterelor se va afla și
caracterul ‘\n’ pentru că acesta este defapt ultimul caracter introdus. Acest lucru poate crea
nefuncționalități ale programelor care vor încerca să citească mai multe caractere în mod
continuu. În cazul în care se doreşte citirea mai multor caractere consecutiv, se recomandă
două posibilități de citire:
- pot fi mai multe instrucţiuni de citire caractere consecutive caz în care este indicat ca în
consolă să se introducă toate caracterele care urmează a fi citite fără spaţii, urmând ca
ele să fie citite de fiecare instrucţiune de citire pe rând
Acest caz este exemplificat în programul următor:
int a, b;
puts("Introduceti doua caractere si apoi apasati Enter:");
a = getc(stdin);
putchar(a + 1);
b = getc(stdin);
12
putchar(b + 2);
sau
int a, b;
puts("Introduceti doua caractere si apoi apasati Enter:");
a = getc(stdin);
b = getc(stdin);
putchar(a + 1);
putchar(b + 2);
- după fiecare instrucţiune de citire caracter să mai fie în program o citire “fără efect” a
caracterului ‘\n’. Acest caz este exemplificat în programul:
int a, b;
puts("Introduceti un caracter si apoi apasati Enter:");
a = getc(stdin);
getc(stdin);
putchar(a + 1);
puts("Introduceti alt caracter si apoi apasati Enter:");
b = getc(stdin);
putchar(b + 2);
char sir[20];
puts("Introduceti un sir de caractere:");
gets(sir);
puts("Sirul citit este:");
puts(sir);
Datorită faptului că această funcţie citeşte date fără a cunoaşte dimensiunea buffer-ului de
intrare este recomandat ca gets() să nu se folosească deloc, funcţia aflându-se încă în unele
compilatoare doar pentru a asigura funcţionalitatea unor coduri scrise cu mulţi ani în urmă. În
exemplul de mai sus, dacă şirul citit de la tastatură conţine mai mult de 19 caractere (la care se
13
adună ‘\n’) va scrie datele peste zone de memorie alocate altor variabile (sau nealocate)
generând erori în program.
Se recomandă în schimb utilizarea funcţiei fgets() care prin signatura sa impune
specificarea dimensiunii bufferului ce urmează a fi citit. Exemplul anterior de citire a unui şir de
caractere de la tastatură poate fi modificat pentru a citi şirul cu funcţia fgets() astfel:
char sir[20];
puts("Introduceti un sir de caractere:");
fgets(sir,sizeof(sir),stdin);
puts("Sirul citit este:");
puts(sir);
char sir[20];
puts("Introduceti un sir de caractere:");
fgets(sir,4,stdin);
puts("Sirul citit este:");
puts(sir);
Se observă cum funcţia fgets() va citi doar 4 caractere din buffer-ul de intrare. S-a tastat
“TESTING”, iar în variabila sir se va păstra doar şirul “TES\0”.
Funcţia fgets() citeşte şi salvează inclusiv caracterul ‘\n’ astfel că dacă se doreşte utilizarea
şirurilor ca variabile în program trebuie suprascris caracterul respectiv cu caracterul ‘\0’. În
exemplul următor este prezentată adăugarea caracterului la sfârşitul şirului citit de la consolă:
14
O soluţie posibilă pentru eliminarea acestui mic incovenient este înlocuirea acestui
caracter cu caracterul ‘\0’. Acest lucru este exemplificat în exemplul următor:
char sir[20];
char *p;
15
puts("Introduceti un sir de caractere:");
fgets(sir,sizeof(sir),stdin);
p = strchr(sir1,'\n'); // #include <string.h>
*p = '\0';
puts("Sirul citit este:");
puts(sir);
În exemplul de mai este utilizată funcţia strchr() din biblioteca string.h. Această funcţie caută în
şirul de caractere primit ca prim argument caracterul primit ca argument secund. La prima
apariţie a caracterului căutat funcţia se opreşte şi returnează un pointer la adresa respectivului
caracter din cadrul şirului. Prin atribuirea valorii ‘\0’ pointerului p se înlocuieşte caracterul new
line cu carcaterul NULL care va semnaliza sfârşitul şirului. Abia din acest moment variabila de
tip şir poate fi folosită în program ca o variabilă care conţine un şir de caractere finalizată prin
NULL.
16
- modul de declarare a variabilelor ale căror valori se "citesc" determină înscrierea unor
informaţii eronate în locaţiile variabilelor.
În general aceste erori nu sunt semnalate de către SC.
Vom aminti din nou primitiva funcției scanf():
Asemănător funcţiei printf(), primul argument al funcţiei scanf() este şirul format
care specifică ce date urmează a fi citite, al doilea argument reprezentând adresele
variabilelor unde se vor scrie datele. O diferenţă faţă de printf() este că acest şir nu
conţine decât specificatori de format. Ca şi în cazul printf(), principalii specificatori de
format sunt:
- %c - se citeşte un caracter
- %d - se citeşte un număr întreg în baza 10
- %x - se citeşte un număr întreg în baza 16
- %f - se citeşte un număr real
- %d - se citeşte un număr real de tip double
- %s - se citeşte un șir de caractere
După lista specificatorilor de format se vor trece adresele variabilelor unde se vor
memora valorile citite. Adresa unei variabile se obţine folosind semnul & urmat de
numele variabilei (vezi Laboratorul Alocarea dinamică a memoriei).
Un exemplu de citire a unui număr întreg:
int a;
scanf("%d", &a);
Exemplul de mai sus va afişa un cursor activ în consolă care semnifică faptul că
utilizatorul terbuie să introducă o valoarei. Deoarece în cazul în care se pot face mai
17
multe citiri programul ar fi confuz se recomandă precedarea instrucţiunilor de citire date
cu instrucţiuni de afişare care să informeze asupra operaţiilor care urmează a se efectua.
În acest caz, exemplul de mai sus devine:
int a;
printf("Introduceti un numar intreg:");
scanf("%d", &a);
Un exemplu de citire a unei variabile de tip şir de caractere şi un număr real este
afişat în continuare:
char nume[20];
float inaltime;
printf("Introduceti numele:");
scanf("%s", nume); // nume reprezinta adresa sirului de
// caractere
printf("Introduceti inaltimea [m]:");
scanf("%f",&inaltime);
18
tipuri, prin specificarea în ordinea introducerii a formatului şi respectiv a adreselor unde
vor fi salvate datele respective. Exemplul anterior devine:
char nume[20];
float inaltime;
printf("Introduceti numele si inaltimea [m]:");
scanf("%s%f", nume, &inaltime);
char nume[20];
printf("Introduceti numele si prenumele:");
scanf("%[^\n]s", nume);
Exemplul de mai sus permite citirea unui şir de caractere având ca şi caracter
terminal Enter. Va permite deci salvarea celorlalte tipuri de Spaţii (BlankSpace şi Tab).
19
20