Professional Documents
Culture Documents
1
VI. Funcţii predefinite
sir2 aabb11c
Figura 12.6.1.2 c
c) Concatenarea (suma) a două şiruri de caractere este efectul apelului funcţiei
predefinite strat(). Linia de definiţie a acestei funcţii este următoarea:
char *strat(char *sir1, const char *sir2).
Şirul al doilea de caractere se memorează în spaţiul alocat lui sir1, după valoarea
acestuia, aşa cum se prezintă în figura 12.6.1.3.
sir2 sir2
Figura 12.6.1.3
2
d) Compararea a două şiruri de caractere se rezolvă, prin apelul fucţiei
predefinite strcmp(), după schema:
- dacă sir1 < sir2, atunci funcţia întoarce –1;
- dacă sir1 > sir2, atunci funcţia întoarce 1; în caz contrar se întoarce 0.
Antetul de definiţie al funcţiei strcmp() este următorul:
int strcmp(const char *sir1, const char *sir2).
e) Prin apelul funcţiei predefinită strcpy(), care are linia de definiţie
char *strcpy(char *sir1, const char *sir2), se realizează copierea şirului al doilea de
caractere în zona de memorie afectată lui sir1. Operaţia de copiere poate fi urmărită în
reprezentarea grafică din figura 12.6.1.2, schimbînd doar sensul săgeţii verticale.
f) Funcţia strchr() caută într-un şir de caractere prima apariţie a unui caracter dat şi
întoarce pointer la acea apariţie, după cum se observă în figura 12.6.1.4. Sintaxa generală
a antetului de definiţie este următoarea:
char *strchr(const char *sir1, int c).
c c
sir1
Figura 12.6.1.4
În programul 12.6.1.1 intervin funcţiile strlen() şi strcat(). Prin apelul funcţiei
strlen() se află lungimea tuturor şirurilor de caractere manipulate în program, iar
rezultatul returnat prin apelarea funcţiei strcat() este sir3, care reprezintă concatenarea
şirurilor de caractere sir1 cu sir2.
/*Utilizarea functiilor strlen() si strcat() */
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main(void)
{ clrscr();
char *sir1 = “Programare”;
char *sir2 = “ in Turbo C++”;
char *sir3;
printf("\n Sirul %s are lungimea de %d caractere ", sir1, strlen(sir1));
printf("\n Sirul %s are lungimea de %d caractere ", sir2, strlen(sir2));
sir3 = strcat(sir1, sir2);
printf("\n Sirul %s are lungimea de %d caractere ", sir3, strlen(sir3));
getch(); }
Sirul Programare are 10 caractere
Sirul in Turbo C++ are 13 caractere
Sirul Programare in Turbo C++ are 23 caractere
Programul 12.6.1.1
Pentru a stîrni mai mult curiozitatea cititorilor, textul definiţiilor funcţiilor
strlen() şi strcat() se prezintă în cele ce urmează.
/* Functia strlen() */
unsigned long strlen(const char * sir)
3
{ register int n;
for(n=0; *sir != ‘\0’; ++sir) ++n; return n; }
Funcţia 12.6.1.1
După cum se observă, se utilizează registrele de memorie pentru alocarea
numărătorului de paşi, în vederea optimizării procesării structurii repetitive for. De cîte
ori se găseşte un caracter diferit de caracterul terminator de şir de caractere (\0) se
incrementează valoarea contorului n.
/* Functia strcat() */
char*strcat(char * sir1, const char *sir2)
{ register char *p = sir1;
while(*p) ++p;
while(*p++ = *sir2++); return sir1; }
Funcţia 12.6.1.2
Cu prima instrucţiune while se localizează terminatorul de sfîrşit de şir de
caractere pentru sir1, apoi cu a doua instrucţiune while se memorează, în continuare,
caracter după caracter, conţinutul lui sir2. Zona de memorie afectată lui sir2 nu suportă
nici o modificare.
4
După prelucrarea tabloului x, din exemplul de mai sus, se impune eliberarea
memorie afectate acestuia, prin free(x);.
Prin programul 12.6.2.1 se citeşte, de la tastatura computerului, un număr
nedeterminat de valori reale nenule şi diferite între ele, a căror sumă se află şi se tipăreşte
pe ecranul monitorului în modulul principal de program.
/* Functii de alocare dinamica */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
float *cit_nr(int );
void main(void)
{ clrscr();
int k, i = 0 ;
float suma, *t;
printf("\n Introduceti numarul valorilor intregi : ");
scanf("%d", &k);
t = cit_nr(k);
for ( suma =0., i = 0; i < k; ++i) suma +=*t+i; //Aflarea sumei
printf("\nSuma =%f", suma); //Tiparirea sumei
free(t); //Eliberarea memoriei
getch();
}
/* Functia de citire numere intregi */
float *cit_nr(int k)
{ int i; float *p;
if(!(p = (float *) malloc(k*sizeof(float)))) //Alocare dinamica
{ puts("memorie insuficienta");
return NULL; }
printf("\n Nr. sint : ");
for (i = 0; i < k; ++i) //Citirea sirului de valori
{ scanf("%f", p+i); printf(" \n ");}
return p; }
Introduceti numarul valorilor intregi : 2
Nr. sint: 4
5
Suma = 9.000000
Programul 12.6.2.1
Absenţa funcţiei free(t); în modulul principal are ca efect neeliberarea variabilei
dinamice t şi în consecinţă, zona de memorie Heap rămîne alocată şi neadresată pînă la
încheierea execuţiei programului. Absenţa argumentului local p în cadrul instrucţiunii
return are de asemenea efecte nedorite. Domeniul de vizibilitate al lui p este blocul
funcţiei cit_nr() şi dispariţia ei nu implică eliberarea zonei de memorie Heap alocate
dinamic şi adresată dinamic pînă la terminarea execuţiei acesteia. În modulul principal,
variabila dinamică t nu mai poate fi accesată deşi ea există în memorie şi nici eliberată
pentru că pointerul p dispare odată cu revenirea în funcţia main().
5
b) În plus, pentru limbajul C++ există mai multe variante de organizare a
spaţiului de memorie afectat variabililor dinamice, numite modele de memorie. Acestea
necesită cunoştinţe de programare avansată.
6
va_start(v, msg); /*initializarea variabilei v */
while(( arg = va_arg(v, dbl)) != 0.) {total += arg;}
printf (msg, total); va_end(v); }
/*incheie citirea parametrilor */
void main(void)
{ dbl x = 7., t[] ={4,5, 6,9, 0};
suma("suma =%lf\n", t[1], 4., t[3], 1., 3., 3., x, t[2], 0.) }
Suma = 38.000000
Programul 12.6.3.1
4. Funcţia main()
Funcţia main() determină modulul principal de program. Deci, cu ea se începe şi se
încheie execuţia oricărui program.
Prin funcţia main() se pot transmite informaţii necesare lansării în execuţie a
programului, cum ar fi: indentificatorul de recunoaştere al programului, opţiuni de
compilare şi date iniţiale. Aceste informaţii se numesc argumente din linia de comandă,
deoarece sînt editate de sistemul de operare în cadrul comenzii de lansare în execuţie a
programului respectiv.
Funcţia main() are următoarea structură:
[tip_de_dată] main([int argc, char *argv[]],[char *env[]])
{…………………..}
Atît tipul funcţiei cît şi lista de argumente sînt opţionale. În general, tipul de date
care precede cuvîntul rezervat main este void. Dacă funcţia main() întoarce un rezultat,
prin utilizarea instrucţiunii return, către programul apelant (adică, sistemul de operare),
atunci acesta este 0, care indică terminarea normală a execuţiei funcţiei, sau un cod de
eroare în caz de eşec.
Argumentele argv[] şi env[] sînt tablouri de pointeri. Parametrul argc fixează
dimensiunea tabloului argv[] şi trebuie să verifice condiţia argc≥1.
Linia de comandă cuprinde şiruri de caractere delimitate de spaţiu sau Tab.
Adresele acestora se memorează, în ordine, în tablourile de pointeri argv[] şi env[]. La
adresa argv[0] se înscrie numele programului. Numărul de adrese conţinute de tabloul
argv[] depinde de valoarea argumentului argc. În figura 12.6.4.1 se reprezintă grafic
conţinutul următoarei linii de comandă:
nume_program o lista de sase argumente, unde argc = 6.
“nume_progra
argv[0] m”
argv[1] “o”
argv[2] “lista“
argv[3] “de“
“sase“
argv[4]
“argumente
“
7
argv[5]
Figura 12.6.4.1
Următoarele şiruri de caractere vor fi înregistrate la adrese succesive în tabloul de
pointeri env[]. Aceste şiruri de caractere pot constitui valori pentru unii parametri ai
sistemului de operare, cum ar fi tipul prompt-ului tipărit la începutul unei linii de
comandă sau căi implicite de căutare în directoare. La ultima adresă din env[] se înscrie
valoarea NULL, care marchează sfîrşitul listei de opţiuni.
Programul următor vizualizează numele autorului în conformitate cu informaţiile
luate din linia de comandă: C:> Test Popescu I. Gheorghe <Enter>
/* Functia main()
#include <stdio.h>
#include <conio.h>
int main(argc, char* argv[]) { int i; printf("\nAutor :");
for (i = 1; i < argc; i++) printf(" %s ", argv[i]); return 0; getch(); }
Autor:
Popescu I. Ghoerghe
Programul 12.6.4.1
8
să fie un tip de structură descris anterior, existînd astfel posibilitatea reprezentării şi
organizării a unor structuri de date complexe şi imbricate.
Lista de variabile de tip structură încheie construcţia sintactică de declarare a unei
structuri. Ca separator de variabile în cadrul listei se admite doar virgula..
Este posibil să absenteze, fie numele simbolic al structurii, fie lista de variabile. Prima
situaţie este mai rară, permiţînd declararea unei structuri anonime. Lista de variabile de
tip structură poate fi precizată ulterior, numai cînd identificatorul de recunoaştere al
structurii este cunoscut, printr-o construcţie de forma:
struct nume_tip_structura lista_var_tip_struct; .
O declarare mai simplă a variabililor de tip structură se poate obţine prin utilizarea
specificatorului typedef (vezi, secţiunea 2.4.2).
Referirea unui cîmp dintr-o variabilă de tip structură se realizează, prin calificare,
cu operatorul de selectare punct (.), astfel:
nume_variabila . nume_cîmp_i, unde i= 1, n . O astfel de referire poate să
intervină ca operand în expresii de atribuire sau ca parametru actual în funcţii de
citire/scriere.
Menţionăm doar că operatorul utilizat în aces caz este cel de selectare indirectă,
notat prin săgeată ().
Iniţializarea unei variabile de tip structură se obţine prin indicarea, în ordine,
pentru fiecare cîmp component cîte o valoare corespunzătoare, după cum urmează:
struct nume_tip_structura nume_variabila = (lista_valori);.
Separatorul de valori în lista_valori este tot virgula. Ulterior, aceste valori pot fi afişate,
modificate sau utilizate în diverse operaţii matematice.
În programul de mai jos se descrie o structură, de tip catalog şcolar, cu
următoarele cîmpuri componente: nume_prenume, adresa, discipline şi medie. A doua
linie din programul principal precizează valorea iniţială pentru variabila student de tip
structură catalog. Ulterior, o parte din aceste valori sînt schimbate prin instrucţiuni de
atribuire, şi anume notele de la a treia disciplină şi a patra şi media. Tipărirea valorii
variabilei student se face prin intermediul primelor trei funcţii de scriere printf() şi
succede un text de tip comentariu. Alte amănunte despre structura programului sînt date
la sfîrşitul secţiunii.
/* Declarare structura catalog */
#include <stdio.h>
#include <conio.h>
struct catalog
{ char nume_prenume[25];
char adresa[35];
int discipline[5];
float medie; };
void main(void)
{ clrscr();
struct catalog student={"Popescu Ioan","M Eminescu 30 Iasi",
10, 9, 9, 8, 10, 9.2};
student.discipline[2] = 10; student.discipline[3] = 10;student.medie=9.80;
printf("\n Variabila student este: ");
printf("\n%s %s", student.nume_prenume, student.adresa);
9
printf("\n %d %d %d %d %d %5.2f\n", student.discipline[0],
student.discipline[1], student.discipline[2], student.discipline[3],
student.discipline[4], student.medie);
struct catalog elev;
elev = student;
printf("\n Introduceti nume elev: \n");
gets(elev.nume_prenume);
elev.discipline[1]=10;
elev.medie=(elev.discipline[0]+elev.discipline[1]+elev.discipline[2]
+ elev.discipline[3]+elev.discipline[4])/5.;
printf("\n Variabila elev este: ");
printf("\n%s %s",elev.nume_prenume,elev.adresa);
printf("\n %d %d %d %d %d %5.2f", elev.discipline[0],
elev.discipline[1], elev.discipline[2], elev.discipline[3],
elev.discipline[4], elev.medie); getch(); }
Variabila student este:
Popescu Ioan M Eminescu 30 Iasi
10 9 10 10 10 9.80
Introduceti nume elev:
Ionescu Mihai
Variabila elev este:
Ionescu Mihai M Eminescu 30 Iasi
10 10 10 10 10 10.00
Programul 13.3.1.1
Variabilele, cu tipul structură identic, pot să apară în expresii de atribuire.
Asignările se realizează în ordinea apariţiei cîmpurilor din componenţa structurii
respective. În cazul programului de mai sus, atribuirea student = elev; este corectă şi se
întinde asupra tuturor cîmpurilor componente, adică: nume şi prenume, adresă, discipline
şi medie aritmetică. Numele şi prenumele elevului s-au citit de la tastatura calculatorului
cu ajutorul funcţiei gets(). După schimbarea notei la a doua disciplină, se recalculează
media aritmetică generală. Ultimele trei funcţii de scriere printf() afişează valoarea
variabilei elev.
10
Conţinutul logic al fişierelor de tip utilizator este determinat de noţiunea de structură, în
care se precizează numărul şi tipurile cîmpurilor componente structurii. Astfel, fişierul
logic de tip utilizator este un ansamblu organizat de un număr nedeterminat de structuri.
De fapt, fişierul logic de tip utilizator poate fi considerat un tablou multidimensional de
lungime variabilă, în care coloanele au diferite tipuri de date.
O situaţie specială o constituie fişierele predefinite (dispozitivele logice predefinite), care
sînt gestionate automat la lansarea în execuţie a programului de tip C. Fişierele
predefinite asociate claviaturii stdin şi stderr permit numai operaţii de citire, iar fişierele
predefinite asociate ecranului şi imprimantei stdout şi respectiv stdprn permit numai
operaţii de scriere. Fişierul predefinit auxiliar stdaux este de intrare/ieşire. Cele 5 cuvinte
cheie sînt constante pointer de tip file declarate în stdio.h.
Operaţiile de intrare/ieşire suportate de un fişier se efectuează cu ajutorul funcţiilor
predefinite care formează conţinutul fişierelor antet stdio.h şi conio.h. Aceste fişiere nu
fac parte integrantă din structura limbajelor de tip C, aşa cum se întîmplă cu toate
celelalte fişere cu extensia .h. De aceea, este necesar să se prevadă introducerea lor, în
antetul programului C++, prin directiva #include <nume_fişier_antet>.
Cînd apare o cerere de citire/scriere, sistemul de operare iniţiază o procedură de
control şi execuţie cu privire la transferul de informaţii, între dispozitivul fizic de
intrare/ieşire (ecran, tastatură, imprimantă, unitate de disc) şi dispozitivul logic de intrare/
ieşire similar, numit stream (flux).
Deschiderea stream-ului asociat unui anumit dispozitiv logic de intrare/ieşire
presupune, pe de o parte crearea indicatorilor standard de stare (variabile de tip File)
corespunzători şi poziţionarea acestora pe valorile iniţiale iar pe de alta, alocarea
necesarului de memorie zonei tampon (buffer-ului) prin intermediul căreia se realizează
efectiv transferul de informaţie. Rezultatul controlului transferului de informaţie de către
sistemul de operare se va reflecta în valorile actualizate ale indicatorilor de stare, care pot
fi aflate printr-o serie de funcţii standard, aşa cum vom vedea mai tîrziu. Închiderea
stream-ului va permite eliberarea memoriei afectate zonei tampon după golirea acesteia.
Stream-urile pot fi de tip text sau de tip binar.
Un stream de tip text transferă şiruri de texte organizate în linii de lungime
variabilă, în concordanţă cu numărul maxim de caractere gestionat de dispozitivul logic
de intrare/ieşire. Separarea liniilor se face prin caracterele de control sfîrşit de linie (0DH)
şi salt la linia următoare (0AH). Un astfel de stream se poate asocia cu stdin, stderr şi
stdout, din care numai stdin necesită o zonă tampon de memorie, cu dimensiunea egală
cu lungimea maximă a linei de text transferată.
Un stream de tip binar transferă o secvenţă de cifre binare fără o structură anume.
Completarea zonei tampon se face automat dacă şirul binar este mai scurt, avînd în
vedere că dimensiunea standard a zonei tampon este de 256 octeţi. Un stream de tip binar
se poate asocia cu stdprn şi stdaux.
În paragraful următor se prezintă prototipul funcţiilor predefinite care permit
operaţii de citire/scriere direct legate de dispozitivele logice predefinite de intrare/ieşire şi
care sînt mai des utilizate în structura programelor de tip C.
11
formatare lor. Funcţiile getch(), getche(), getchar() şi gets() permit o citire cu afişare, cu
excepţia lui getche() şi fără formatare. Atît tipărirea pe ecran, cît şi formatarea datelor
citite se realizează cu funcţia scanf().
Corespunzător, pentru operaţia de scriere fără formatare pe ecranul monitorului s-
au conceput funcţiile putchar() şi puts(), iar pentru cea cu formatare printf().
Lungimea şirului de intrare/ieşire diferă la ambele categorii de funcţii astfel
getch(), getche(), getchar() şi putchar() prelucrează un singur caracter şi nu are
importanţă în rest.
12
din şirul de formatare şi variabilile a căror adrese sînt precizate în lista_adrese_variabile.
Orice neconcordanţă va fi sancţionată cu un mesaj de eroare.
Şirul de formatare poate să conţină:
- descriptori de format, care sînt şiruri de caractere precedate de ‘%’ conforme cu
tipurile de date atribuite variabililor a căror adrese intervin în lista_adrese_variabile. Lista
acestora se precizează în figura 5.2.2.1.
- secvenţele escape ‘\n’ (linie nouă) şi ‘\t’ (tab);
- blancul (spaţiul liber);
- orice alt caracter ASCII.
Funcţia scanf() citeşte în ordine caracterele tastate de la claviatura calculatorului,
care constituie valoarea unei variabile de intrare, le interpretează conform precizărilor
furnizate de descriptorul de format corespunzător şi le depune la adresa alocată în
memorie variabilei respective. După satisfacerea întregii liste de variabile, funcţia
returnează numărul de valori citite. Dacă lista de adrese de variabile este vidă, atunci
rezultatul întors este nul. Ultimile două categorii de caractere din şirul de formatare
declanşează citirea fără memorare a caracterului citit din stdin, dacă există identitate între
ele.
Sintaxa generală a unui descriptor de format se prezintă astfel:
%[*][n1[.n2]][c1][c2]indentificator_descriptor, unde singurile argumente obligatorii sînt
% şi indentificator_descriptor. Lista descriptorilor de fomat se prezintă în tabelul 5.2.2.1.
Celelelalte argumente sînt cu următoarele semnificaţii:
- * precizează că următoarea valoare citită nu se mai atribuie variabilei care
urmează în lista de adrese;
- n1 reprezintă numărul maxim de caractere alocate unei valori;
- n2 este numărul de cifre situate după punctul zecimal în cazul unei valori
raţionale;
- c1 reprezintă un modificator de adresă pentru variabila de intrare
corespunzătoare, şi anume: F pentru far (modelul depărtat) sau N pentru near (modelul
apropiat);
- c2 reprezintă un modificator de tip pentru argumentul de intrare respectiv, după
cum urmează:
h (short int) pentru descriptorii de format d, i, o, u şi x;
b) l (long int) pentru descriptorii de format d, i, o, u şi x sau în situaţia tipului double
pentru descriptorii de format e, f şi g;
c) L (long double) pentru descriptorii de format e, f şi g.
Dacă n1 este precizat în componenţa descriptorului de format, atunci citirea valorii
respective se termină după preluarea din stdin a unui număr de caractere egal cu n1 sau la
întîlnirea unui caracter incompatibil cu formatul precizat. Dacă n1 este absent, atunci
citirea valorii respective se încheie după întîlnirea unui blanc, a unui tab, a unui caracter
incompatibil cu formatul precizat sau după tastarea unui sfîrşit de linie (Enter).
Indentificator Valoarea de intrare Tip variabilă
descriptor *
c caracter char
s şir de caractere char
d întreg zecimal int
D întreg zecimal int
13
u întreg zecimal fără semn unsigned
U întreg zecimal fără semn unsigned
e, f, g, E, G număr raţional long
o întreg octal float
O întreg octal int
x întreg hexazecimal fără semn long
X întreg hexazecimal fără semn int
i întreg (d, o sau x) long
I întreg (D, O sau X) int
n - long
p adresa în hexazecimal: int
far: YYYY:ZZZZ pointer
near: ZZZZ
Tabelul 13.2.2.1
Se precizează că descriptorul de format n specifică lungimea şirului de intrare în
citirea curentă.
Dacă şirul de intrare este prea lung, ultimele caractere sînt ignorate la citirea
curentă, dar rămînînd în dispozitivul de intrare pot afecta următoarea citire. Cu
funcţia predefinită fflush() se înlătură, prin program, balastul rămas în dispozitivul de
intrare. Dacă lista adreselor de variabile nu se satisface complet, şirul de intrare fiind prea
scurt, atunci computerul intră într-o stare de aşteptare. Indiferent de lungimea şirului de
intrare, execuţia funcţiei scanf() se încheie la citirea unui caracter incompatibil cu
specificaţia de format interpretată, cu afişarea unui mesaj de eroare corespunzător.
Cîteva exemple. 1. …………….
char c1,s1;
int i;
long j;
float x;
double y;
……………
scanf (“%c%s”, c1, s1);
scanf(“%3d%4D%f%lf”, &i, &j, &x, &y);
……………………………………………..
Pentru şirul de intrare aABCD12312347.5 -16.35 se produc următoarele atribuiri:
c1 = ’a’, s1 = “ABCD”, i = 123, j = 1234, x = 7.5 şi y = -16.35 şi funcţiile scanf se
termină normal.
2. …………….
float z[10];
int i;
for ( i = 0; i<10; ++i)
scanf(“%f”, z[i]);
fflush(stdin);
…………………………..
În situaţia şirului de intrare 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12
instrucţiunea for se încheie normal, dar este necesar să se prevadă funcţia fflush() pentru
14
golirea dispozitivului de intrare, altfel ultimile două valori din şir pot afecta citirea
următoarea din program.
3. …………..
int a, b;
scanf (“%d%d”, a, b);
…………………………..
Funcţia scanf() se termină cu eroare în cazul şirului de intrare 15 1x3y, deoarece a
doua valoare conţine litere în locul a două cifre zecimale.
15
cu a, …, f (sau A, …, F)
% caracterul % -
n la adresa indicată afişează int *
numărul de caractere transferate
curent
p adresa în hexazecimal: pointer
far: YYYY:ZZZZ
near: ZZZZ
Tabelul 5.2.4.1
În această situaţie, spre deosebire de operaţia de citire cu formatare, structura
descriptorilor de format poate fi completată cu o serie de precizări privitoare la alinierea
valorilor în limitele spaţiului alocat, la semn, la punctul zecimal sau la prefixul datelor
octale şi hexazecimale, după cum urmează:
%[a][n1[.n2]][c1][c2]indentificator_descriptor, unde singurile argumente obligatorii,
după cum se ştie, sînt % şi indentificator_descriptor. Majoritatea argumentelor sînt cu
semnificaţii similare celor prezentate în paragraful 5.2.2. Urmează să discutăm doar
semnificaţia lui a. Alinierea valorilor în spaţiul precizat prin descriptorul de format se
face ţinînd cont de regulile de mai jos:
- alinierea implicită (în absenţa lui a) a valorilor numerice se face la dreapta, iar a
şirurilor de caractere la stînga şi completare cu spaţii sau 0 în rest. Precizia implicită
pentru valorilor de tip raţional este de 6 cifre zecimale (adică, după punctul zecimal se
afişează 6 cifre, eventual cu adăugare de zerouri);
- dacă a este –, atunci alinierea valorilor numerice se face la stînga şi completare cu spaţii
în dreapta;
- dacă a este +, atunci valorilor numerice sînt precedate de + sau -;
- dacă a este spaţiu liber, numai valorile negative sînte precedate de semnul minus;
- dacă a este #, atunci se produc inserări de caractere distinctive, astfel:
se adaugă prefixul 0 la valorile octale (pentru o);
2) se adaugă prefixul 0x sau 0X la valorile hexazecimale (pentru x sau X);
3) se înscrie punctul zecimal pentru e, E, f, g sau G, iar în cazul descriptorilor g şi G nu se
elimină digiţii 0 finali.
Cîteva exemple. 1. În tabelul 13.2.4.2 se descriu cîteva formate de scriere pentru
tipuri de date întregi şi raţionale în simplă precizie:
Tip de dată Descriptor de format Format de scriere
întregi
153 %d 153
153 %3d 153
153 %2d (se ignoră) 153
153 %5d 153
raţoinale
7.52 %f 7.520000
7.52 %f4.2 7.52
7.5 %f4.2 7.50
7.5 %f6.2 7.50
17.52 %f3.1 (se ignoră) 17.52
Tabelul 13.2.4.2
16
…………….
int k = 14;
double z = -335.3;
printf(“\nk=%3d\tz=%9.2lf”, k, z);
Şirul de formatare cuprinde secvenţe de evitare, caractere ASCII şi descriptorii de
format d şi lf. Valorile variabililor k şi z vor fi tipărite în clar, la linie nouă, iar spaţiul
liber între ele este egal cu o tabulare standard.
17
În concluzie, pentru a se lucra corect cu fişiere utilizator trebuie să se parcurgă
următoarele etape:
- să se precizeze numele formal al fişierului printr-o variabilă de tip FILE în
partea de declaraţii a unităţii de program corespunzătoare. Trebuie să existe concordanţă
de nume între fişierul formal (declarat ca o variabilă FILE) şi numele unui fişier ce există
sau va exista pe un suprt magnetic;
- să se deschidă fişierul prin fopen(), cu precizarea tipurilor operaţiei de
citire/scriere şi stream-ului (text sau binar) executate;
- să se scrie/citească în fişier cu funcţia predefinită fwrite()/fread();
- să se închidă fişierul cu fclose().
Indentificatorii declaraţi în domeniul fişierului cu caracter global au, în mod
implicit, legătură de tip extern. Cu specificatorul static ultimul atribut poate fi schimbat în
unul de tip intern. Indentificatorii neglobali au legătură identică cu cea rezultată din
declaraţia indentificatorilor globali, dacă există şi este cu vizibilitate. În mod similar,
specificatorul static poate determina o legătură internă, iar specificatorul extern una
externă.
Urmărirea reperelor anunţate mai sus se poate face în exemplu prezentat în ultima
secţiune.
18