Enrere Mòdul 7
Fonaments de programació. Llenguatge C/C++---
Pràctica    Resum teòric Exercicis
Pràctica d'ampliació

 
Construcció d'una matriu dinàmicament

En aquesta pràctica aprendrem a construir una matriu bidimensional sense reservar memòria en temps de compilació, és a dir, dinàmicament.

 

Desenvolupament de la pràctica

Definiu un projecte nou anomenat m7pa1 i afegiu-li un arxiu de font C/C++ anomenat m7pa1.cpp. Escriviu el següent codi:

//m7pa1.cpp: Construcció d'una matriu dinàmicament

#include <stdio.h>
#include <stdlib.h>

void main(){
    int i,j,n;
    double *a;

    printf("introduïu la dimensió de la matriu");
    scanf("%d", &n);

    a=(double*)calloc(n*n, sizeof(double));
    //alternativa1: a=(double*)malloc(n*n*sizeof(double));
    //alternativa2:
a=new double[n*n];


    //lectura dels elements de la matriu

    for (i=0;i<n;i++){
        for (j=0;j<n;j++){
          printf("a(%d,%d)= ", i+1,j+1);
          scanf("%lf", a+i*n+j);
        }
    }

    //escriptura dels elements de la matriu

    for (i=0;i<n;i++){
        for (j=0;j<n;j++){
             printf("a(%d,%d)= %lf\n", i+1, j+1,*(a+i*n+j));

        }
    }
    free (a);
    //  si s'ha fet servir l'alternativa 2: delete(a);

}

Explicació del programa

En aquest programa, la dimensió de la matriu i, per tant, l'espai de memòria necessari per emmagatzemar-la no se sap fins que s'executa el programa i s'introdueix el valor de la variable n.

L'assignació de memòria es pot fer de diverses formes. En aquest programa es fa servir una d'aquestes formes, però explicarem dues alternatives més.

primera alternativa: funció calloc().

 
 a=(double*)calloc(n*n, sizeof(double));

Aquesta funció necessita dos arguments, el nombre de dades i el nombre d'octets de cada dada. En aquest cas reservem espai per nxn dades de 8 octets. Aquesta funció torna un punter void a la primera posició de memòria reservada, és per tant necessari fer una conversió anteposant (double*) al nom de la funció. Fixeu-vos que la variable a s'ha declarat com un punter  a double.
El protocol de la funció calloc() es troba a l'arxiu de capçelera stdlib.h.

segona alternativa: funció malloc().

 
  a=(double*)malloc(n*n*sizeof(double));

Aquesta funció necessita només un argument, el nombre d'octets total a reservar. A més, no fa cap tipus d'inicialització com la funció anterior. Aquesta funció també torna un punter void que s'ha de convertit com la funció anterior. El protocol d'aquesta funció es troba també a l'arxiu de capçalaer stdlib.h.

tercera alternativa: L'operador de C++ new

 
 a=new double[n*n];

Aquest operador és propi de C++ i no pertany a l'estàndard ANSI C. De fet, juntament amb l'operador delete forma part de les paraules reservades C++ i no necessiten cap arxiu de capçalera per poder fer-les servir.

Aquest operador té una doble avantatge respecte a l'operador malloc(), per una part, no és necessari fer ús de l'operador sizeof() per calcular el nombre d'octets i, per altra part, no és necessari cap conversió ja que aquest operador ja torna un punter al tipus especificat a la dreta de l'operant.

És una bona pràctica alliberar la memòria reservada quan aquesta no es faci servir més. Si s'ha reservat la memòria amb calloc() o malloc() això s'aconsegueix amb la funció free(). Aquesta funció necessita com argument un punter a la primera posició de memòria reservada. Si s'ha reservat la memòria amb new l'alliberament es fa amb l'operador delete.

Quan les funcions malloc() o calloc() o bé l'operador new no poden reservar la memòria per falta d'espai, tornen un punter NULL, és per tant, una bona pràctica comprovar el punter tornat per aquestes funcions o operador per evitar errors.

 En aquest programa les nxn dades s'interpreten com els elements d'una matriu quadrada d'ordre n. Per referir-nos a l'element i,j es fa servir l'expressió: *(a+i*n+j). i i j van de 0 a (n-1).