<<Pagina Materiale

 
 
 Tablouri 
Tablouri unidimensionale

Definitie:

Tabloul este o colectie finita de elemente de acelasi tip, numit tip de baza al tabloului, care ocupa un spatiu continuu de memorie.

Sintaxa:
 

tip_de_baza nume_tablou[dimensiune]={const0,const1,...};

dimensiune - este o expresie intreaga constanta, precizand numarul de elemente ale tabloului ( se precizeaza de obicei printr-o constanta simbolica ).
Memoria ocupata de tablou este: dimensiune*sizeof(tip_de_baza)

Tabloul poate fi initializat la definire - vezi partea optionala marcata -  prin precizarea constantelor de initializare. Daca numarul acestora:

  • ==dimensiune - elementele tabloului se initializeaza cu constantele precizate
  • <dimensiune  - constantele neprecizate sunt implicit 0
  • >dimensiune  - apare eroare in compilare.
Daca este prezenta partea de initializare, dar lipseste dimensiune, aceasta este implicit egala implici cu numarul constantelor.

Exemple:

int tab[10];// defineste un tablou de 10 elemente intregi, care ocupa 20 octeti

#define N 10

int tab[N]; // definitie echivalenta cu cea de mai sus

#define NR_ELEM 5
float t[NR_ELEM]={1.2,5,3}; //primele trei elemente se initializeaza cu constantele precizate, urmatoarele doua cu 0

double a[]={2,5.9}; //tabloul a este de dimensiune 2, dimensiunea fiind data de numarul constantelor de initializare

Selectarea unui element de tablou:
 

nume_tablou[indice] //se foloseste operatorul de indexare []

indice - expresie intreaga cu valori intre 0 si dimensiune -1
Un element de tablou poate fi prelucrat ca orice variabila avand tipul de baza.

Observatii:

  • Nici compilatorul, nici mediul de executie nu verifica valorile indicilor; programatorul trebuie sa codifice astfel incat expresiile indice sa ia valori in intervalul 0 .. dimensiune -1; altfel pot apare erori imprevizibile, cum ar fi modificarea nedorita a altor variabile:

  •  
    #define N 10
    int tab[N];

    tab[N]=5;   //se modifica zona de 2 o urmatoare tabloului
    tab[-10]=6; //se modifica o zona de 2 o situata la o adresa cu 20 o inferioara tabloului

  • Pentru a realiza o prelucrare asupra tuturor elementelor tabloului se foloseste instructiunea for cu o variabila contor care sa ia toate valorile indicilor ( intre 0 si dimensiune -1 );

  •  
    #define N 10
    int tab[N],i;

    for(i=0;i<N;i++)
      *prelucrare tab[i] 

  • Copierea unui tablou in altul se face prin copiere fiecarui element ( vezi programul urmator, functia copiere );
  • Se poate ca nu toate elementele tabloului sa fie prelucrate, ci doar primele nr_elem<=dimensiune ( vezi programul urmator, se pot citi doar primele nr_elem ).
Exemplu:

1. Se considera un tablou de N elemente intregi ( N este constanta predefinita ). Sa se prelucreze tabloul astfel:
  • sa se citeasca cele N elemente de la tastatura ( varianta: pana la CTRL/Z - se decomenteaza linia comentata din functia citire si se comenteaza cea anterioara )
  • sa se afiseze elementele
  • sa se afiseze maximul si media aritmetica pentru elementele tabloului
  • sa se caute in tablou o valoare citita de la tastatura
  • sa se construiasca un tablou copie al celui dat
  • sa se afiseze elementele tabloului copie in ordinea inversa.
     
    #include <stdio.h>
    #include <conio.h>
    #define N 8

    int tablou[N], copie[N], nr_elem; /* tablou va contine nr_elem de prelucrat */

    void citire(void);  //prototipuri
    void tiparire(void);
    void tip_inv(void);
    void copiere(void);
    void info(void);
    void cautare(void);

    void main(void){

      clrscr();

      citire();
      tiparire();
      info();
      cautare();

      copiere();
      tip_inv();

      getch();
    } //main

    //definitiile functiilor

    void citire(void){
      int i;
      puts("Introduceti elementele tabloului:");
      for(i=0;i<N;i++){
        printf("elem[%d]=",i); /* se afiseaza indicele elem ce se citeste */
            scanf("%d",&tablou[i]); 
            //if(scanf("%d",&tablou[i])==EOF)break; 
      }//for
      nr_elem=i;
    } //citire

    void tiparire(void){
      int i;
      puts("Elementele tabloului:");
      for(i=0;i<nr_elem;i++)
        printf("elem[%d]=%d\n",i,tablou[i]);
    } //tiparire

    void tip_inv(void){
      int i;
      puts("Elementele tabloului copie in ordine inversa:");
      for(i=nr_elem-1;i>=0;i--)
        printf("copie[%d]=%d\n",i,copie[i]);
    } //tip_inv

    void copiere(void){  //copierea se face prin cea a fiecarui element
      int i;
      for(i=0;i<nr_elem;i++)
        copie[i]=tablou[i];
    } //copiere

    void info(void){ 
      int i,max,suma; float meda;
      for(i=suma=0,max=tablou[0];i<nr_elem;i++){
        suma+=tablou[i];
        if(tablou[i]>max)max=tablou[i];
      }
      printf("*** val maxima=%d, media aritm=%f\n",max,(float)suma/nr_elem);
    } //info

    void cautare(void){ 
      int i,de_cautat;
      printf("Se cauta:"); scanf("%d",&de_cautat);
      for(i=0;i<nr_elem;i++)
        if(de_cautat==tablou[i])break;
      //cele doua linii de mai sus se pot scrie echivalent:
      // for(i=0;i<nr_elem && de_cautat!=tablou[i];i++)
      if(i<nr_elem)
        printf("*** s-a gasit la indicele %d\n",i);
      else
        puts("*** nu s-a gasit");
    } //cautare

Sus
Tablouri multidimensionale

Definirea unui tablou multidimensional:
 

tip_de_baza nume_tablou[dim1][dim2]...[dimn]={{const10,...},{const20,...},...,{constn0,...}};

dim1,dim2,...,dimn - expresii intregi constante ( de obicei constante simbolice ).
Memoria continua ocupata de tablou este de dimensiune:dim1*dim2*...*dimn*sizeof(tip_de_baza).
Elementele tabloului multidimensional sunt memorate astfel incat ultimul indice variaza cel mai rapid.

Tabloul poate fi initializat la definire - vezi parte optionala marcata - prin precizarea constantelor de initializare.

Tablourile bidimensionale se numesc matrici, prima dimensiune reprezentand numarul de linii, iar a doua, de coloane.

Exemple:

int m[10][5]; // defineste un tablou dimensional de elemente intregi, cu 10 linii si 5 coloane, care ocupa 10*5*2=100 octeti

#define NL 10
#define NC 5
int m[NL][NC]; // definitie echivalenta cu cea de mai sus

double a[3][2]={{2},{5.9,1},{-9}}; //elementele pe linii sunt: 2 0 5.9 1 -9 0

double a[3][2]={2,5.9,1,-9}; //elementele pe linii sunt: 2 5.9 1 -9 0 0

Selectarea unui element de tablou:
 

nume_tablou[ind1][ind2]...[indn]

ind1,ind2,...,indn - expresii intregi cu valori intre 0 si dimi-1, i=1..n
Un element de tablou poate fi prelucrat ca orice variabila avand tipul de baza.

Exemplu:

Sa se scrie un program care realizeaza urmatoarele prelucrari asupra unei matrici patratice M de ordin N ( constanta simbolica ), avand elemente intregi, fiecare prelucrare fiind realizata de cate o functie void fara parametri:

  • citeste- elementele matricii pe coloane
  • afiseaza - elementele matricii pe linii
  • modifica - aduna la fiecare element al matricii suma indicilor elementului respectiv; se afiseaza apoi matricea modificata prin apelul functiei de mai sus
  • verif_sim- verifica daca matricea este simetrica, afisand un mesaj corespunzator
  • det_linia - determina linia din matrice care are produsul elementelor maxim, afisand indicele liniei si produsul
  • calc_sume - calculeaza si afiseaza patru sume: a elementelor aflate pe diagonala principala, a celor de pe diagonala secundara, a celor aflate deasupra diagonalei principale si a elementelor aflate pe "marginile" matricii
  • transpusa - construieste si afiseaza transpusa matricii M.
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#define N 10

char optiune;
int n,matrice[N][N]; 

void citire(void){
  int i,j;
  do{ //citire cu validare a ordinului matricii
   printf("\nIntroduceti nr de linii si coloane:(1..%d)",N);
   scanf("%d",&n);
  }while(n<=0||n>N);
  for (j=0;j<n;j++)
    for (i=0;i<n;i++){
      printf("elem[%d][%d]:",i,j);
      scanf("%d",&matrice[i][j]);
    }
}

void afisare(void){
  int i,j;
  puts("Matricea:");
  for (i=0;i<n;i++){
    for (j=0;j<n;j++)
      printf("%d\t",matrice[i][j]);
    putchar('\n');
  }
}

void modifica(void){
  int i,j;
  afisare();
  for (i=0;i<n;i++)
    for (j=0;j<n;j++)
      matrice[i][j]+=i+j;
  puts("Dupa modificare:");
  afisare();
}

void verif_sim(void){
  int i,j;
  for (i=0;i<n;i++) // se compara fiecare elem de deasupra
    for (j=i+1;j<n;j++)// diag cu simetricul sau
      if (matrice[i][j]!=matrice[j][i]){
         puts("Matricea nu este simetrica");
         return;
      }
  puts("Matricea este simetrica");
}

void linia_max(void){
  int i,j,linia;long produsmax,produs;
  for (i=0;i<n;i++){
    for (produs=1,j=0;j<n;j++) // calcul produs linia i
      produs*=matrice[i][j];
    if(i==0){
      produsmax=produs;
      linia=0;
    }
    else if (produs>produsmax){
       produsmax=produs;
       linia=i;
    }
  } // for i
  printf("Produsul maxim este %ld,se afla pe linia d;", produsmax,linia);
}

void calc_sume(void){
  int i,j,diagprinc=0,diagsec=0,deasupradiagprinc=0,margine=0;
  for (i=0;i<n;i++){
       diagprinc+=matrice[i][i];
       diagsec=diagsec+matrice[i][n-1-i];
       margine+=matrice[i][0];
       margine+=matrice[i][n-1];
       for (j=i+1;j<n;j++)
         deasupradiagprinc+=matrice[i][j];
  }
  for (j=1;j<n-1;j++){
       margine+=matrice[0][j];
       margine+=matrice[n-1][j];
  }
  afisare();
  printf("\nSuma elementelor de pe diagonala principala este %d;",diagprinc);
  printf("\nSuma elementelor de pe diagonala secundara este %d;",diagsec);
  printf("\nSuma elementelor de deasupra diag principale  %d;",deasupradiagprinc);
  printf("\nSuma elementelor de pe marginea matricii  %d;",margine);
}

void transpusa(void){
  int i,j,transp[N][N];
  for (i=0;i<n;i++)
    for (j=0;j<n;j++)
      transp[j][i]=matrice[i][j];
  afisare();
  printf("\nMatricea transpusa este:\n");
  for (i=0;i<n;i++){
    for (j=0;j<n;j++)
      printf("%d\t",transp[i][j]);
    putchar('\n');
  }
}

void citire_optiune(void)
{
 clrscr();
 putchar('\n');
 puts("[I]ntroducere matrice;");
 puts("[A]fisare matrice;");
 puts("[M]odifica matricea adunand indicii la element;");
 puts("[V]erifica daca matricea este simetrica;");
 puts("[L]inia din matrice care are produsul elem max;");
 puts("[C]alculeaza diferite sume;");
 puts("[T]ranspusa matricii;");
 puts("E[x]it;\n");
 puts("Optiunea dvs.:");
 optiune=getche();
 putchar('\n');
}

void main(void)
{
 n=0;
 do{ 
  clrscr(); 
  citire_optiune();
  switch(toupper(optiune)){
   case 'I':citire();break;
   case 'A':afisare();break;
   case 'M':modifica();break;
   case 'V':verif_sim();break;
   case 'L':linia_max();break;
   case 'C':calc_sume();break;
   case 'T':transpusa();break;
   case 'X':puts("La revedere!");break;
   default:puts("*** Optiune eronata ***\n");
  }
  getch(); 
 }while(toupper(optiune)!='X');
}
 

Sus
Quiz

Iata cateva autoteste prin care sa verificati intelegerea notiunilor de mai sus. Programele exemplu au fost deja rulate, nu?

1.Se defineste un  tablou de 5 elemente de tip float:

int nr=5;
float tablou_reali[nr];

2.Se defineste un tablou de 4 elemente intregi:

int tablou_intregi[]={3,2,8,6};

3.Se initializeaza elementele tabloului tab cu patratele indicilor:

#define DIM 10
int i, tab[DIM];
for(i=0;i<=DIM;i++)
   tab[i]=i*i;

4.Se defineste matricea matr cu L linii si C coloane, avand elemente intregi:

#define L 5
#define C 7
int matr[L][C];

5.Se tiparesc elementele matricii de mai sus pe coloane:

int i,j;
for(j=0;j<C;j++){
  for(i=0;i<L;i++)
      printf("%d ",matr[i][j]);
      putchar('\n');
}

Sus
Exercitii

1.Sa se ruleze programul exemplu. Sa se adauge prelucrarile:
-modificarea elementelor tabloului initial la patratul lor
-afisarea tabloului dupa modificare.
Sa se tranforme programul intr-unul interactiv, fiecare prelucrare executandu-se la o comanda corespunzatoare ( citirea la comanda 'C' sau 'c', s.a.m.d. ). Vezi instructiunea switchsi rezolvarea problemei urmatoare.

2.Sa se scrie un program interactiv care prelucreaza un tablou de max N intregi ( N - constanta predefinita ), prin urmatoarele comenzi - optiunile marcate cu ? trebuie adaugate:
  I - initializeaza tabloul, prin citirea dimensiunii sale si apoi a elementelor
  V ? initializeaza tabloul, prin citirea elementelor pana la introducerea lui CTRL/Z sau a numarului maxim de elemente
  A ? initializeaza tabloul, fiecare element fiind egal cu indicele sau
  B ? initializeaza tabloul astfel: primele doua elemente cu 0, 1, iar urmatoarele ca suma anterioarelor doua (numerele Fibonacci)
  L - listeaza elementele tabloului
  O - listeaza elementele tabloului ordonate crescator ( in tablou elementele trebuie sa ramana in ordinea introducerii )
  D ? analog cu O, dar in ordine descrescatoare
  C - cauta o valoare in tablou, afisand indicele in cazul gasirii
  M ? cauta o valoare in tablou, pe care o sterge in cazul gasirii - dimensiunea tabloului va scadea astfel cu o unitate ( nr_elem, nu N!!!); stergerea se realizeaza prin mutarea cu o pozitie inspre indicii mici, a tuturor elementelor de tablou urmatoare celui care se sterge; o alta varianta este de a copia ultimul element peste cel care se sterge
  P - afiseaza maximul, suma, produsul, media aritmetica si cea geometrica
  X - terminare.
 

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <math.h> //pentru functia pow

#define N 10
#define NL '\n'
#define MIN -32768

int tablou[N], copie[N], nr_elem;  /* tablou va contine nr_elem de prelucrat, copie salveaza tablou inainte de ordonare */
char optiune;  /* caracterul ce indica operatia */

void citire_optiune(void){  /* fara validare */
  printf("Optiunea(I,L,O,C,P,X)=");optiune=getche();
  putchar(NL);
}

void citire_numar_elem(void){  /* cu validare */
  do{
    printf("numar elem(1..%d)=",N);scanf("%d",&nr_elem);
  }while(nr_elem<1 || nr_elem>N);
}

void citire_elem(void){
  int i;
  puts("Introduceti elementele tabloului");
  for(i=0;i<nr_elem;i++){
    printf("elem[%d]=",i);scanf("%d",&tablou[i]); /* se afiseaza indicele 
            elem ce se citeste */
  }
}

void init(void){
  citire_numar_elem();
  citire_elem();
}

void list(void){  /* se listeaza elem din tablou */
  int i;
  puts("Elementele tabloului:");
  for(i=0;i<nr_elem;i++)
    printf("elem[%d]=%d%c",i,tablou[i],NL);
}

void salv(void){  /* se salveaza tablou in copie */
  int i;
  for(i=0;i<nr_elem;i++)
    copie[i]=tablou[i];
}

void refac(void){  /* se reface tablou din copie */
  int i;
  for(i=0;i<nr_elem;i++)
    tablou[i]=copie[i];
}

void ordonare(void){  /* se ordoneaza elem din tablou prin metoda bubblesort*/
  int i,ordonat,aux;
  do{ 
    ordonat=1;
    for(i=0;i<nr_elem-1;i++)
      if(tablou[i]>tablou[i+1]){ /* interschimbare */
         aux=tablou[i+1];
         tablou[i+1]=tablou[i];
         tablou[i]=aux;
         ordonat=0;
      }
  }while(!ordonat);
}

void list_ord(void){  /* se face ordonarea elem din tablou, dupa listare, 
    tablou revine la configuratia de la citire */
  salv();
  ordonare();
  list();
  refac();
}

void prel(void){
  int max=MIN, suma=0, i;
  float produs=1, media_aritm, media_geom;
  for(i=0;i<nr_elem;i++){
    if(tablou[i]>max) max=tablou[i];
    suma+=tablou[i];
    produs*=tablou[i];
  } 
  media_aritm=(float)suma/nr_elem;
  media_geom=pow(produs, 1/(float)nr_elem);
  printf("max=%d, suma=%d, produs=%0.0f, media aritm=%f, media geom=%f%c", 
   max,suma,produs,media_aritm,media_geom,NL);
}

void cauta(void){
  int pe_cine,i;
  printf("valoare cautata:");
  scanf("%d",&pe_cine);
  for(i=0;i<nr_elem;i++)
    if(tablou[i]==pe_cine)break;
  if(i==nr_elem)puts("***Nu exista***");
  else printf("gasita la indicele %d\n",i);
}

void main(void){
  clrscr();
  do{
    citire_optiune();
    switch(toupper(optiune)){
      case 'I':init();break;
      case 'L':list();break;
      case 'O':list_ord();break;
      case 'C':cauta();break;
      case 'P':prel();break;
      case 'X':puts("La revedere");break;
      default:puts("*** Optiune eronata ***");
    }
  }while(toupper(optiune)!='X');
  getch();
}

3.Sa se scrie un program care citeste coeficientii unui polinom de x, cu gradul maxim N ( N este o constanta predefinita), calculand apoi valoarea sa in puncte x citite, pana la introducerea pentru x a valorii 0. Sa se afiseze si valoarea obtinuta prin apelarea functiei de biblioteca poly. Sa  se modifice programul astfel incat sa citeasca ciclic polinoame, pe care sa le evalueze.
 

#include <stdio.h>
#include <conio.h>
#include <math.h>

#define N 10

double coeficient[N+1],x,val;//numarul de coeficienti e cu 1 mai mare decat gradul
int grad; //grad variabil <=N

void citire_grad(void){  /* cu validare */
  do{
    printf("grad maxim(0..%d)=",N);scanf("%d",&grad);
  }while(grad<0 || grad>N);
}

void citire_coef(void){
  int i;
  citire_grad();
  puts("Introduceti coeficientii:");
  for(i=0;i<=grad;i++){
    printf("coef[%d]=",i);scanf("%lf",&coeficient[i]); /* se afiseaza indicele 
            elem ce se citeste */
  }
}

void list_polin(void){  /* se listeaza polinomul */
  int i;
  printf("P(x)=");
  for(i=grad;i>0;i--)
    if(coeficient[i])
      printf("%lf*x^%d+",coeficient[i],i);
  if(coeficient[0])
    printf("%lf\n",coeficient[0]); /* termenul liber */
}

void eval(void){
  int i;
  val=coeficient[grad];
  for(i=grad-1;i>=0;i--){
    val*=x;
    val+=coeficient[i];
  }
}

void main(void){
  clrscr();
  citire_coef();
  list_polin(); 
  while(printf("x="),scanf("%lf",&x),x){
     /* while(printf("x="),scanf("%lf",&x) != EOF )//daca oprire la CTRL/Z */
    eval();
    printf("P(%lf)=%lf\n",x,val);
    printf("poly(%lf)=%lf\n",x,poly(x,grad,coeficient)); /* evaluare cu functia de
                 biblioteca poly - cititi Help-ul pentru poly, dand CTRL/F1 avand cursorul pe un car din poly*/
  }
  getch();
}

4.Pentru o matrice cu NL linii si NC coloane ( NL, NC constante simbolice ), declarata ca variabila globala si avand elemente intregi, sa se scrie urmatoarele functii void fara parametri:

  • citire - citeste elementele matricii pe coloane
  • tiparire - tipareste elementele matricii pe linii
  • det_maxim - determina si afiseaza  valoare si pozitia elementului maxim din matrice
  • constr_tab - construieste un tablou unidimensional declarat ca variabila globala, ale carui elemente sunt sumele elementelor de pe cate o linie a matricii
  • interschimbare - interschimba elementele de pe doua coloane ale matricii cu indicii cititi
  • cauta - cauta in matrice o valoare citita, afisandu-i pozitia.
Ce mai trebuie adaugat pentru a avea un program C complet?
Mai jos sunt definite functiile de citire si tiparire.
 
#define NL 5
#define NC 3

int m[NL][NC];

void citire(void){ //citire pe coloane
  int i,j;
  printf("Introduceti elementele matricii de %d linii si %d coloane, pe\ coloane\n",NL,NC);
  for(j=0;j<NC;j++)
    for(i=0;i<NL;i++){
      printf("elem %d,%d:",i,j);scanf("%d",&m[i][j]);
    }
} /* citire */

void tiparire(void){ /* elementele unei linii a matricii se tiparesc separate printr-un blanc, apoi se trece la un rand nou pe ecran */
  int i,j;
  puts("Elementele matricii pe linii");
  for(i=0;i<NL;i++)
    { for(j=0;j<NC;j++) printf("%d ",m[i][j]); putchar('\n'); } /* for i */
    /* linia de mai sus mai poate fi scrisa:
    for(j=0;j<NC;j++) printf("%d%c",m[i][j],j==NC-1?' ':'\n'); */
} /* tiparire */

void main(void){
  citire();
  tiparire();
}

5.Sa se scrie un program care calculeaza si afiseaza matricea suma a doua matrici de elemente intregi, initializate la declarare. Suma si afisarea vor fi realizate de cate o functie void fara parametri, iar cele trei matrici se vor considera variabile globale.

6.Sa se scrie un program care calculeaza si afiseaza matricea produs a doua matrici de elemente intregi, initializate la declarare. Produsul si afisarea vor fi realizate de cate o functie void fara parametri, iar cele trei matrici se vor considera variabile globale.

Sus
<<Pagina Materiale


Copyright © 2001-2002. Carmen Holotescu
All rights reserved. Published by Timsoft