TIPOS DE DATOS ESTRUCTURADOS HOMOGENEOS.








Introducción.
Tira de memoria de una computadora Los tipos de datos atómicos (char, int, float, double) dejan de ser realmente prácticos en cuanto es preciso tratar unos cuantos elementos, bien sea en forma de lista o en forma de tabla, que son las dos organizaciones más frecuentes. El lenguaje C es muy flexible a la hora de manejar listas y tablas, pero la forma en que se accede a los elementos de estas listas y tablas puede resultar sorprendente si no se tiene en cuenta la organización de los datos en memoria. Para comprender este asunto, basta examinar al forma en que está dispuesta la memoria de una computadora, según puede verse en la imagen. La memoria de una computadora tiene una disposición lineal: cada posición tiene su propia dirección, representable mediante un número entero. Las variables suelen organizarse de modo que su comienzo (el primer byte de la variable) coincida con la dirección de comienzo de una palabra de la computadora. De este modo se optimiza la velocidad de acceso.


Tabla en memoria Dada esta organización de memoria, es preciso representar todas las variables del programa en el marco de un segmento de memoria (desde una cierta dirección hasta otra) que está asociado a la aplicación. En otras palabras, hay que distribuir las variables de tal modo que puedan estar almacenadas en esta tira o lista monodimensional. Pues bien, en C las listas se organizan siempre por filas (lo que en inglés se verá como "row-major order"). Esto significa lo siguiente:
  • Una lista es una colección de elementos que ocupan posiciones contiguas de memoria.
  • Una tabla es una colección de filas (listas) situadas una tras otra en memoria
  • Una matriz tridimensional ("tarugo") es una colección capas, cada una de las cuales se almacena por filas.
y así sucesivamente. Se ve entonces que las listas monodimensionales se adaptan fácilmente a la estructura de memoria de la computadora.
Si se dispone de una tabla, como es el caso de la matriz 3x3 que se muestra en la figura, el compilador "desarma" la tabla en filas, que sitúa una tras otra. A continuación, cada fila se almacena en memoria por orden de columnas: la primera columna de la primera fila ocupa la posición más baja de memoria, y la última columna de la tercera fila ocupa la posicón más alta en memoria.

Listas, tablas y matrices de tipos atómicos : declaración e iniciación
La declaración de una lista, tabla o matriz de un tipo atómico tiene el aspecto siguiente:

tipo_base nombre_variable[dim_1][dim_2]...[dim_N];

en donde Insistimos en la palabra constantes, porque este tipo de declaración es tal que el compilador debe conocer el valor de cada uno de los dim en el momento en que arranca el programa. Esto significa que, en C, no es posible emplear este tipo de declaración para crear matrices de dimensiones variables durante la ejecución. El código siguiente, por tanto, es incorrecto:
#include<stdio.h>
int main(int argc, char * argv[])
{
  int n;
  float lista[n]; /* Esto no se admite */
  printf("Deme el número de elementos: ");
  scanf("%d", &n);
  return 0;
}


Ejemplos

 int lista[10];
/* Una lista de diez elementos numerados de 0 a 9 */
 float tabla[2][3];
/* Una tabla de dos filas por tres columnas, de 0 a 1 (filas) y de 0 a 2 (columnas) */
 char libro[3][3][3];
/* Una tabla de 3 capas por 3 filas por 3 columnas */



Siguiendo con el ejemplo anterior, la forma de dar valores iniciales a una variable matricial se puede esquematizar en la forma
tipo_base identificador[dim_1]...[dim_n] =
   {valor_1, valor_2, ..., valor_M};
en donde valor_1, ..., valor_M se irán asignando a elementos de la matriz, siguiendo exactamente su orden de construcción en memoria. El lenguaje C construye las matrices por filas, y estas de menor (índice 0) a mayor (índice dim_m-1). Dentro de cada fila, se sigue un orden ascendente de columnas; primero se llena la columna de índice 0, después la de índice 1 y así sucesivamente. La representación gráfica puede servir de guía. Véase también un Ejemplo.





Acceso y asignación
La forma de acceder a un elemento de una matriz puede esquematizarse en la forma siguiente:
identificador_matricial[indice_1]...[indice_n]
en donde se han utilizado tantos índices entre corchetes como dimensiones posea la matriz. Por ejemplo, libro[0][1][2] denota la capa 0, fila 1, columna 2. Pero también se puede utilizar un número de índices menor que el número de dimensiones que tenga la estructura en cuesión.

Si se utiliza un número de índices menor que el número de dimensiones declaradas, se obtiene el identificador formado considerando que la estructura total consta de dim_1 X dim_2 X dim_3 X ... X dim_N elementos. Se considera que los índices dados se asocian a las dimensiones situadas más a la izquierda; cuando faltan índices, se entiende que el elemento considerado es todo un bloque de tantas dimensiones como las restantes. Si se considera el ejemplo anterior, matriz[dim_1][dim_2][dim_3], entonces matriz[indice_1] denota la capa completa dada por indice_1, y matriz[indice_1][indice_2] denota la fila completa indice_2 de la capa indice_1. Por supuesto, matriz[indice_1][indice_2][indice_3] denota la columna indice_3 de la fila indice_2de la capa indice_1. Véase también el gráfico anterior. Una vez construida la expresión de acceso, es posible efectuar las oportunas asignaciones a elementos individuales, y también a los bloques construidos empleando menos índices que dimensiones. Por razones de eficiencia, no se permite asignar directamente una lista, tabla o matriz a otra; es preciso por tanto recurrir a iniciaciones (según se ha visto) o bien a funciones especializadas que permiten copiar el contenido de una estructura de memoria en otra. Es preciso comprobar cuidadosamente que la cantidad de memoria copiada no sobrepase los límites reservados en la variable de destino; en caso contrario el programa sufrirá un error por corrupción de los datos o código situados tras el final de esa variable. Véase el correspondiente Ejemplo.

Ejemplo 1.- Construir un programa que muestre la forma de declarar, iniciar y visualizar variables matriciales en C.
/*
  Este programa muestra la declaración y utilización de variables
  matriciales en C. Se supone que el tipo base es atómico.
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>

/*
  DECLARACIONES GENERICAS
*/

int fin;
char instruccion;
char menu[80];
char opcionesvalidas[80];

/*
  DECLARACIONES ESPECIFICAS
*/
  #define MAX_LISTA 10
  #define MAX_FILAS 2
  #define MAX_COLS 3
  #define DIM_1 3
  #define DIM_2 3
  #define DIM_3 3

  int lista[MAX_LISTA] =
              { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  float tabla[MAX_FILAS][MAX_COLS] =
              { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0};

  double matriz[DIM_1][DIM_2][DIM_3] =
              { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
                 10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,
                 19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0};

  int fila, columna, capa;


int main(int contador, char * argumento[])
{
  /* INICIACIONES GENERALES */

  fin = 0;
  strcpy(menu,"\nL)istas T)ablas M)atrices, S)alir A)yuda");
  strcpy(opcionesvalidas,"LTMSA");

  /* INICIACIONES ESPECIFICAS */


  /* EJECUCION DE INSTRUCCIONES */

  do {

    do {
      puts(menu);
      scanf("%c%*c",&instruccion);
      instruccion=toupper(instruccion);
    } while (!strchr(opcionesvalidas,instruccion));


    switch(instruccion)
    {
      case 'L': {
            puts("Listas.\n");
            for(fila=0;fila < MAX_LISTA; fila++)
              printf("%4d",lista[fila]);
            }
            break;
      case 'T': {
            puts("Tablas.\n");
            for(fila=0;fila<MAX_FILAS;fila++)
              {
              for(columna=0;columna<MAX_COLS;columna++)
                printf("%4f ",tabla[fila][columna]);
              printf("\n");
              }
            }
            break;
      case 'M': {
            puts("Matrices.\n");
            for(capa=0;capa<DIM_1;capa++)
              {
              printf("\nCapa %d:\n\n",capa);
              for(fila=0;fila<DIM_2;fila++)
              for(columna=0;columna<DIM_3;columna++)
                printf("matriz[%d][%d][%d]=%6g\n",
                  capa,fila,columna,matriz[capa][fila][columna]);
              }

            printf("\n\nO bien:\n\n");

            for(capa=0;capa<DIM_1;capa++)
              {

              printf("\nCapa %d:\n\n",capa);
              for(fila=0;fila<DIM_2;fila++)
                {
                for(columna=0;columna<DIM_3;columna++)
                  printf("%6g",matriz[capa][fila][columna]);
                printf("\n");
                }
              }
            }
            break;
      case 'S': {
            fin = 1;
            puts("Nos vamos!\n");
            }
            break;
      case 'A': {
            puts("\nEste programa muestra listas, tablas y matrices.\n");
            }
            break;
      default : {
            puts("Instrucción incorrecta.\n");
            }
            break;
    }

  }
  while (!fin);

  puts("\n\nThat's all folks!\n");
}
/*
  RESULTADO

L)istas T)ablas M)atrices, S)alir A)yuda
l
Listas.

   0   1   2   3   4   5   6   7   8   9
L)istas T)ablas M)atrices, S)alir A)yuda
t
Tablas.

0.000000 1.000000 2.000000
3.000000 4.000000 5.000000

L)istas T)ablas M)atrices, S)alir A)yuda
m
Matrices.


Capa 0:

matriz[0][0][0]=     1
matriz[0][0][1]=     2
matriz[0][0][2]=     3
matriz[0][1][0]=     4
matriz[0][1][1]=     5
matriz[0][1][2]=     6
matriz[0][2][0]=     7
matriz[0][2][1]=     8
matriz[0][2][2]=     9

Capa 1:

matriz[1][0][0]=    10
matriz[1][0][1]=    11
matriz[1][0][2]=    12
matriz[1][1][0]=    13
matriz[1][1][1]=    14
matriz[1][1][2]=    15
matriz[1][2][0]=    16
matriz[1][2][1]=    17
matriz[1][2][2]=    18

Capa 2:

matriz[2][0][0]=    19
matriz[2][0][1]=    20
matriz[2][0][2]=    21
matriz[2][1][0]=    22
matriz[2][1][1]=    23
matriz[2][1][2]=    24
matriz[2][2][0]=    25
matriz[2][2][1]=    26
matriz[2][2][2]=    27


O bien:


Capa 0:

     1     2     3
     4     5     6
     7     8     9

Capa 1:

    10    11    12
    13    14    15
    16    17    18

Capa 2:

    19    20    21
    22    23    24
    25    26    27

L)istas T)ablas M)atrices, S)alir A)yuda
a

Este programa muestra listas, tablas y matrices.


L)istas T)ablas M)atrices, S)alir A)yuda
s
Nos vamos!



That's all folks!

*/


Ejemplo 2.- Construir un programa que efectúe asignaciones entre listas, tablas y matrices. El programa deberá emplear las oportunas funciones de copia, tanto para el caso general como para el caso especial de listas,tablas o matrices formadas por caracteres.
/*
  Este programa muestra la forma de efectuar asignaciones
  en estructuras matriciales de tipo base numérico
  Se muestra el uso correcto de memcpy.

  MEMCPY(DONDE, QUE, CUANTO);

*/
/*
  lista2 = lista;
  tabla2 = tabla;       NO SE ADMITE!
  matriz2 = matriz;
*/

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

/*
  DECLARACIONES GENERICAS
*/

int fin;
char instruccion;
char menu[80];
char opcionesvalidas[80];

/*
  DECLARACIONES ESPECIFICAS
*/
  #define MAX_LISTA 10
  #define MAX_FILAS 2
  #define MAX_COLS 3
  #define DIM_1 3
  #define DIM_2 3
  #define DIM_3 3

  int lista[MAX_LISTA] =
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, lista2[MAX_LISTA];

  float tabla[MAX_FILAS][MAX_COLS] =
      { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0}, tabla2[MAX_FILAS][MAX_COLS];

  double matriz[DIM_1][DIM_2][DIM_3] =
    { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
      10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,
      19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0},
      matriz2[DIM_1][DIM_2][DIM_3];

  int fila, columna, capa;

void main(void)
{
  /* INICIACIONES GENERALES */

  fin = 0;
  strcpy(menu,"\nV)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda");
  strcpy(opcionesvalidas,"VLTMSA");

  /* EJECUCION DE INSTRUCCIONES */

  do {

    do {
        puts(menu);
        scanf("%c%*c",&instruccion);
        instruccion=toupper(instruccion);
    } while (!strchr(opcionesvalidas,instruccion));


    switch(instruccion)
    {
      case 'V': {
        printf("Definiciones y Tamaños.\n\n");
        printf("MAX_LISTA= %d, MAX_FILAS= %d, ", MAX_LISTA, MAX_FILAS);
        printf("MAX_COLS= %d, DIM_1= %d, ", MAX_COLS, DIM_1);
        printf("DIM_2= %d, DIM_3= %d\n\n", DIM_2, DIM_3);
        printf("int lista[MAX_LISTA];\n\n");
        printf("Tamaño de lista       : %d\n", sizeof(lista));
        printf("\nfloat tabla[MAX_FILAS][MAX_COLS];\n\n");
        printf("Tamaño de tabla       : %d\n", sizeof(tabla));
        printf("Tamaño de tabla[0]    : %d\n", sizeof(tabla[0]));
        printf("\ndouble matriz[DIM_1][DIM_2][DIM_3];\n\n");
        printf("Tamaño de matriz      : %d\n", sizeof(matriz));
        printf("Tamaño de matriz[0]   : %d\n", sizeof(matriz[0]));
        printf("Tamaño de matriz[0][0]: %d\n", sizeof(matriz[0][0]));
        }
      break;
      case 'L': {
              puts("Listas.\n");
              printf("Antes de asignar: \n\n");
              printf("lista : ");
              for(fila=0;fila < MAX_LISTA; fila++)
                printf("%4d",lista[fila]);
              printf("\nlista2: ");
              for(fila=0;fila < MAX_LISTA; fila++)
                printf("%4d",lista2[fila]);
              /* ASIGNACION */
              memcpy(lista2,lista,sizeof(lista));
              printf("\n\nDespués de asignar: \n\n");
              printf("lista : ");
              for(fila=0;fila < MAX_LISTA; fila++)
                printf("%4d",lista[fila]);
              printf("\nlista2: ");
              for(fila=0;fila < MAX_LISTA; fila++)
                printf("%4d",lista2[fila]);
              printf("\n");
            }
            break;
      case 'T': {
        puts("Tablas.\n");
        printf("Antes de asignar: \n\n");
        printf("tabla :\n");
        for(fila=0;fila<MAX_FILAS;fila++)
          {
            for(columna=0;columna<MAX_COLS;columna++)
              printf("%4f ",tabla[fila][columna]);
            printf("\n");
          }
        printf("tabla2:\n");
        for(fila=0;fila<MAX_FILAS;fila++)
          {
            for(columna=0;columna<MAX_COLS;columna++)
              printf("%4f ",tabla2[fila][columna]);
            printf("\n");
          }
        /* ASIGNACION */
        memcpy(tabla2,tabla,sizeof(tabla));
        printf("\n\nDespués de asignar: \n\n");
        printf("tabla :\n");
        for(fila=0;fila<MAX_FILAS;fila++)
          {
            for(columna=0;columna<MAX_COLS;columna++)
              printf("%4f ",tabla[fila][columna]);
            printf("\n");
          }
        printf("tabla2:\n");
        for(fila=0;fila<MAX_FILAS;fila++)
          {
            for(columna=0;columna<MAX_COLS;columna++)
              printf("%4f ",tabla2[fila][columna]);
            printf("\n");
          }
        }
        break;
      case 'M': {
        puts("Matrices.\n");
        printf("Antes de asignar:\n\n");
        printf("matriz :\n\n");
        for(capa=0;capa<DIM_1;capa++)
          {
            printf("\nCapa %d:\n\n",capa);
            for(fila=0;fila<DIM_2;fila++)
              for(columna=0;columna<DIM_3;columna++)
                printf("matriz[%d][%d][%d]=%6g\n",
                capa,fila,columna,matriz[capa][fila][columna]);
          }
        printf("\nmatriz2:\n\n");
        for(capa=0;capa<DIM_1;capa++)
          {
            printf("\nCapa %d:\n\n",capa);
            for(fila=0;fila<DIM_2;fila++)
              for(columna=0;columna<DIM_3;columna++)
                printf("matriz2[%d][%d][%d]=%6g\n",
                  capa,fila,columna,matriz2[capa][fila][columna]);
          }
        /* ASIGNACION */
        memcpy(matriz2, matriz, sizeof(matriz));
        printf("\n\nDespués de asignar:\n\n");
        printf("matriz :\n\n");
        for(capa=0;capa<DIM_1;capa++)
        {
          printf("\nCapa %d:\n\n",capa);
          for(fila=0;fila<DIM_2;fila++)
          for(columna=0;columna<DIM_3;columna++)
            printf("matriz[%d][%d][%d]=%6g\n",
              capa,fila,columna,matriz[capa][fila][columna]);
        }
        printf("matriz2:\n\n");
        for(capa=0;capa<DIM_1;capa++)
          {
            printf("\nCapa %d:\n\n",capa);
            for(fila=0;fila<DIM_2;fila++)
            for(columna=0;columna<DIM_3;columna++)
              printf("matriz2[%d][%d][%d]=%6g\n",
              capa,fila,columna,matriz[capa][fila][columna]);
          }
        }
        break;
      case 'S': {
              fin = 1;
              puts("Nos vamos!\n");
            }
            break;
      case 'A': {
              puts("\nEste programa muestra la asignación de");
              puts("listas, tablas y matrices numéricas.\n");
            }
            break;
      default : {
              puts("Instrucción incorrecta.\n");
            }
            break;
    }

  }
  while (!fin);

  puts("\n\nThat's all folks!\n");
}

/*
  RESULTADO

V)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda
v
Definiciones y Tamaños.

MAX_LISTA= 10, MAX_FILAS= 2, MAX_COLS= 3, DIM_1= 3, DIM_2= 3, DIM_3= 3

int lista[MAX_LISTA];

Tamaño de lista       : 40

float tabla[MAX_FILAS][MAX_COLS];

Tamaño de tabla       : 24
Tamaño de tabla[0]    : 12

double matriz[DIM_1][DIM_2][DIM_3];

Tamaño de matriz      : 216
Tamaño de matriz[0]   : 72
Tamaño de matriz[0][0]: 24

V)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda
l
Listas.

Antes de asignar:

lista :    0   1   2   3   4   5   6   7   8   9
lista2:    0   0   0   0   0   0   0   0   0   0

Después de asignar:

lista :    0   1   2   3   4   5   6   7   8   9
lista2:    0   1   2   3   4   5   6   7   8   9

V)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda
t
Tablas.

Antes de asignar:

tabla :
0.000000 1.000000 2.000000
3.000000 4.000000 5.000000
tabla2:
0.000000 0.000000 0.000000
0.000000 0.000000 0.000000


Después de asignar:

tabla :
0.000000 1.000000 2.000000
3.000000 4.000000 5.000000
tabla2:
0.000000 1.000000 2.000000
3.000000 4.000000 5.000000

V)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda
m
Matrices.

Antes de asignar:

matriz :


Capa 0:

matriz[0][0][0]=     1
matriz[0][0][1]=     2
matriz[0][0][2]=     3
matriz[0][1][0]=     4
matriz[0][1][1]=     5
matriz[0][1][2]=     6
matriz[0][2][0]=     7
matriz[0][2][1]=     8
matriz[0][2][2]=     9

Capa 1:

matriz[1][0][0]=    10
matriz[1][0][1]=    11
matriz[1][0][2]=    12
matriz[1][1][0]=    13
matriz[1][1][1]=    14
matriz[1][1][2]=    15
matriz[1][2][0]=    16
matriz[1][2][1]=    17
matriz[1][2][2]=    18

Capa 2:

matriz[2][0][0]=    19
matriz[2][0][1]=    20
matriz[2][0][2]=    21
matriz[2][1][0]=    22
matriz[2][1][1]=    23
matriz[2][1][2]=    24
matriz[2][2][0]=    25
matriz[2][2][1]=    26
matriz[2][2][2]=    27

matriz2:


Capa 0:

matriz2[0][0][0]=     0
matriz2[0][0][1]=     0
matriz2[0][0][2]=     0
matriz2[0][1][0]=     0
matriz2[0][1][1]=     0
matriz2[0][1][2]=     0
matriz2[0][2][0]=     0
matriz2[0][2][1]=     0
matriz2[0][2][2]=     0

Capa 1:

matriz2[1][0][0]=     0
matriz2[1][0][1]=     0
matriz2[1][0][2]=     0
matriz2[1][1][0]=     0
matriz2[1][1][1]=     0
matriz2[1][1][2]=     0
matriz2[1][2][0]=     0
matriz2[1][2][1]=     0
matriz2[1][2][2]=     0

Capa 2:

matriz2[2][0][0]=     0
matriz2[2][0][1]=     0
matriz2[2][0][2]=     0
matriz2[2][1][0]=     0
matriz2[2][1][1]=     0
matriz2[2][1][2]=     0
matriz2[2][2][0]=     0
matriz2[2][2][1]=     0
matriz2[2][2][2]=     0


Después de asignar:

matriz :


Capa 0:

matriz[0][0][0]=     1
matriz[0][0][1]=     2
matriz[0][0][2]=     3
matriz[0][1][0]=     4
matriz[0][1][1]=     5
matriz[0][1][2]=     6
matriz[0][2][0]=     7
matriz[0][2][1]=     8
matriz[0][2][2]=     9

Capa 1:

matriz[1][0][0]=    10
matriz[1][0][1]=    11
matriz[1][0][2]=    12
matriz[1][1][0]=    13
matriz[1][1][1]=    14
matriz[1][1][2]=    15
matriz[1][2][0]=    16
matriz[1][2][1]=    17
matriz[1][2][2]=    18

Capa 2:

matriz[2][0][0]=    19
matriz[2][0][1]=    20
matriz[2][0][2]=    21
matriz[2][1][0]=    22
matriz[2][1][1]=    23
matriz[2][1][2]=    24
matriz[2][2][0]=    25
matriz[2][2][1]=    26
matriz[2][2][2]=    27
matriz2:


Capa 0:

matriz2[0][0][0]=     1
matriz2[0][0][1]=     2
matriz2[0][0][2]=     3
matriz2[0][1][0]=     4
matriz2[0][1][1]=     5
matriz2[0][1][2]=     6
matriz2[0][2][0]=     7
matriz2[0][2][1]=     8
matriz2[0][2][2]=     9

Capa 1:

matriz2[1][0][0]=    10
matriz2[1][0][1]=    11
matriz2[1][0][2]=    12
matriz2[1][1][0]=    13
matriz2[1][1][1]=    14
matriz2[1][1][2]=    15
matriz2[1][2][0]=    16
matriz2[1][2][1]=    17
matriz2[1][2][2]=    18

Capa 2:

matriz2[2][0][0]=    19
matriz2[2][0][1]=    20
matriz2[2][0][2]=    21
matriz2[2][1][0]=    22
matriz2[2][1][1]=    23
matriz2[2][1][2]=    24
matriz2[2][2][0]=    25
matriz2[2][2][1]=    26
matriz2[2][2][2]=    27

V)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda
a

Este programa muestra la asignación de
listas, tablas y matrices numéricas.


V)er tamaños L)istas T)ablas M)atrices, S)alir A)yuda
s
Nos vamos!

That's all folks!

*/


Volver al principio de esta página

Ejercicios iniciales: listas, tablas, libros

  1. Construir un programa que muestre las opciones necesarias para leer una lista de 10 elementos de tipo int, calcular valores de interés, mostrar valores de interés y salir de programa. Los valores de interés de la lista son el máximo, el mínimo y el valor medio.
  2. Construir un programa que muestre las opciones necesarias para leer dos matrices de dimensiones 2x2 (formadas por elementos de tipo float), calcular la suma de las matrices, calcular la resta de las matrices, mostrar la suma, mostrar la resta y salir de programa.
  3. Construir un programa capaz de leer un "libro" basado en la siguiente estructura de datos:
    #define PAGINAS 3
    #define LINEAS 4
    #define COLUMNAS 10
    
    char libro[PAGINAS][LINEAS][COLUMNAS];
    
    El programa ofrecerá opciones para leer el libro (de teclado), mostrar una cierta página y salir del programa. Mejora.- Hacer que el programa lea de disco el contenido del libro, preguntando al usuario el nombre del fichero que lo contiene.
  4. Construir un programa que muestre en pantalla un tablero de damas. El programa debe ser capaz de admitir "movimientos"; esto es, partirá de un tablero con blancas y negras en sus posiciones, y permitirá al usuario "mover" fichas, mostrando en pantalla el resultado del movimiento.
    Mejoras
    1. Verificar la corrección de todos los movimientos.
    2. Permitir mover a blancas y a negras.
    3. Hacer que el tablero se muestre siempre en pantalla, en el último estado (después del último movimiento).
    4. (Más complicado)Sugerir movimientos al jugador de blancas. Los movimientos deben ser válidos, y a ser posible comportar alguna ventaja.
  5. Construir un programa que muestre en pantalla un tablero de ajedrez, con características similares a las del ejercicio anterior. El tablero debe ser capaz de admitir movimientos para todas las fichas. Comprobar la validez de los movimientos, y advertir al usuario si no son correctos.
  6. Construir un programa que admita dos vectores de ℜ³ y muestre el producto escalar, el productor vectorial, el módulo de los vectores, el coseno del ángulo que forman y el seno del ángulo que forman.
  7. Construir un programa que admita una matriz 3x3 y un vector de ℜ³ y calcula el producto del vector por la matriz y de la matriz por el vector. Sugerencia: si se llama f a la aplicación definida por la matriz, utilizar un vector de Ker(f) para comprobar que en efecto el resultado de aplicar la matriz al vector es el vector 0.

Ejercicios Iniciales - Soluciones

  1. #include <stdio.h>
    #include <stdlib.h>
    
    #define Tipo double
    
    int main()
    {
        Tipo lista[] = {1, 2, 3, 4, 5};
        int DB;
        Tipo * p;
        int i;
        p = lista;//&lista[0]
        printf("Direcciones de los elementos de la lista:\n");
        for (i=0;i<5;i++)
            printf("%u ",(unsigned int)&lista[i]);
        printf("\n");
        for (i=0;i<5;i++)
            printf("%u ",(unsigned int)(p+i));
    
        return 0;
    }
    
  2. #include <stdio.h>
    #include <string.h>
    
    #define FILAS 10
    #define COLUMNAS 10
    
    int main(int argc, char * argv[])
    {
      float a[FILAS][COLUMNAS], b[FILAS][COLUMNAS];
      int i,j;
      // Damos valor a la matriz a
      for(i=0;i<FILAS;i++)
      {
        for(j=0;j<COLUMNAS;j++)
        {
          a[i][j] = 10*i+j;
        }
      }
      // La matriz b todavía no tiene valor
      // Mostramos el contenido de la matriz a
      for(i=0;i<FILAS;i++)
      {
        printf("| ");
        for(j=0;j<COLUMNAS;j++)
          printf("%6.2f ", a[i][j]);
        printf("|\n");
      }
      // Vamos a copiar el contenido de a en b. Primero mostramos que b está vacía
      printf("El contenido de b es:\n");
      for(i=0;i<FILAS;i++)
      {
        printf("| ");
        for(j=0;j<COLUMNAS;j++)
          printf("%6.2f ", b[i][j]);
        printf("|\n");
      }
      /*
       Primer método de copia (empleando iteradores)
      for(i=0;i<FILAS;i++)
        for(j=0;j<COLUMNAS;j++)
          b[i][j] = a[i][j];
       */
      /*
       Segundo método de copia. Compacto!
      */
      memcpy(b,a,FILAS*COLUMNAS*sizeof(float));
      printf("El contenido de b después del segundo método de copia es:\n");
      for(i=0;i<FILAS;i++)
      {
        printf("| ");
        for(j=0;j<COLUMNAS;j++)
          printf("%6.2f ", b[i][j]);
        printf("|\n");
      }
    }
    
  3. #include <stdio.h>
    #include <ctype.h>
    /*
     Construir un programa que muestre las opciones necesarias para leer una lista de 10
     elementos de tipo int, calcular valores de interés, mostrar valores de interés y
     salir de programa. Los valores de interés de la lista son el máximo, el mínimo y
     el valor medio.
     */
    #define NUM_ELEMENTOS 10
    
    int main (int argc, const char * argv[]) {
        char menu[] = "\na) Leer b) Calcular c) Mostrar q) Salir";
      char opcion[64];
      int lista[NUM_ELEMENTOS];
      int max, min, ave=0;
      int i;
      do {
        printf("%s: ",menu);
        fgets(opcion, 64, stdin);
        switch (toupper(opcion[0])) {
        case 'A':
          printf("\nEscriba la lista:\n\n");
          for (i=0; i<NUM_ELEMENTOS; i++) {
            printf("Elemento nº %d: ",i);
            scanf("%d%*c",lista+i);
          }
          break;
        case 'B':
          ave = 0.0;
          max = min = lista[0];
          for (i=0; i<NUM_ELEMENTOS; i++) {
            if (lista[i] ≤ min) {
              min = lista[i];
            } else if (lista[i] ≥ max) {
              max=lista[i];
            }
            ave+=lista[i];
          }
          ave /= NUM_ELEMENTOS;
            printf("\n\nSe han efectuado los cálculos\n\n");
          break;
        case 'C':
          printf("\n\nmáximo: %d\nmínimo: %d\nmedia:  %d\n\n",max,min,ave);
          break;
        case 'Q':
          printf("\n\nSaliendo\n\n");
          break;
        default:
          printf("\n\nOpción incorrecta\n\n");
            break;
        }
      } while (toupper(opcion[0])!='Q');
        return 0;
    }
    
  4. #include <stdio.h>
    #include <ctype.h>
    /*
     Construir un programa que muestre las opciones necesarias para leer dos matrices
     de dimensiones 2x2 (formadas por elementos de tipo float), calcular la suma de las
     matrices, calcular la resta de las matrices, mostrar la suma, mostrar la resta
     y salir de programa.
     */
    #define DIMENSION 2
    
    int main (int argc, const char * argv[]) {
        char menu[] = "\na) Leer b) Sumar y Restar c) Ver suma"
      " d) Ver resta q) Salir";
      char opcion[64];
      float A[DIMENSION][DIMENSION], B[DIMENSION][DIMENSION];// Datos
      float C[DIMENSION][DIMENSION], D[DIMENSION][DIMENSION];// Resultados
      int i,j;
      do {
        printf("%s: ",menu);
        fgets(opcion, 64, stdin);
        switch (toupper(opcion[0])) {
          case 'A':
            printf("\nEscriba la matriz A:\n\n");
            for (i=0; i<DIMENSION; i++)
              for (j=0; j<DIMENSION; j++) {
                printf("A[%d][%d] = ",i,j);
                scanf("%f%*c", &A[i][j]);
              }
            printf("\nEscriba la matriz B:\n\n");
            for (i=0; i<DIMENSION; i++)
              for (j=0; j<DIMENSION; j++) {
                printf("B[%d][%d] = ",i,j);
                scanf("%f%*c", &B[i][j]);
              }
            break;
          case 'B':
            for (i=0; i<DIMENSION; i++)
              for (j=0; j<DIMENSION; j++) {
                C[i][j] = A[i][j] + B[i][j];
                D[i][j] = A[i][j] - B[i][j];
              }
            printf("\n\nSe han efectuado los cálculos\n\n");
            break;
          case 'C':
            printf("\n\nLa suma de estas matrices es:\n\n");
            for (i=0; i<DIMENSION; i++){
              printf("|");
              for (j=0; j<DIMENSION; j++) {
                printf("%4.2f ",A[i][j]);
              }
              printf("|\n");
            }
            printf("\n+\n\n");
            for (i=0; i<DIMENSION; i++){
              printf("|");
              for (j=0; j<DIMENSION; j++) {
                printf("%4.2f ",B[i][j]);
              }
              printf("|\n");
            }
            printf("\n=\n\n");
            for (i=0; i<DIMENSION; i++){
              printf("|");
              for (j=0; j<DIMENSION; j++) {
                printf("%4.2f ",C[i][j]);
              }
              printf("|\n");
            }
            break;
          case 'D':
            printf("\n\nLa resta de estas matrices es:\n\n");
            for (i=0; i<DIMENSION; i++){
              printf("|");
              for (j=0; j<DIMENSION; j++) {
                printf("%4.2f ",A[i][j]);
              }
              printf("|\n");
            }
            printf("\n-\n\n");
            for (i=0; i<DIMENSION; i++){
              printf("|");
              for (j=0; j<DIMENSION; j++) {
                printf("%4.2f ",B[i][j]);
              }
              printf("|\n");
            }
            printf("\n=\n\n");
            for (i=0; i<DIMENSION; i++){
              printf("|");
              for (j=0; j<DIMENSION; j++) {
                printf("%4.2f ",D[i][j]);
              }
              printf("|\n");
            }
            break;
          case 'Q':
            printf("\n\nSaliendo\n\n");
            break;
          default:
            printf("\n\nOpción incorrecta\n\n");
            break;
        }
      } while (toupper(opcion[0])!='Q');
      return 0;
    }
    
  5. #include <stdio.h>
    #include <ctype.h>
    /*
     Construir un programa capaz de leer un "libro" basado en la siguiente
     estructura de datos:
    
    #define PAGINAS 3
    #define LINEAS 4
    #define COLUMNAS 10
    
    char libro[PAGINAS][LINEAS][COLUMNAS];
    
    El programa ofrecerá opciones para leer el libro (de teclado),
     mostrar una cierta página y salir del programa.
      Mejora.- Hacer que el programa lea de disco el contenido del libro,
       preguntando al usuario el nombre del fichero que lo contiene.
    
    */
    #define PAGINAS 3
    #define LINEAS 4
    #define COLUMNAS 64
    
    int main (int argc, const char * argv[]) {
        char libro[PAGINAS][LINEAS][COLUMNAS];
        char menu[] = "\na) Leer b) Mostrar una página q) Salir";
      char opcion[64];
      int i,j, k;
      do {
        printf("%s: ",menu);
        fgets(opcion, 64, stdin);
        switch (toupper(opcion[0])) {
          case 'A':
            for (i=0; i<PAGINAS; i++) {
                        printf("Escriba la página %d por líneas (ponga \"linea\"):\n\n", i);
              for (j=0; j<LINEAS; j++) {
                printf("linea[%d] = ",j);
                fgets(libro[i][j],64,stdin);
                libro[i][j][strlen(libro[i][j])-1]='\0';
              }
                    }
            break;
          case 'B':
            printf("Qué página desea :");
                    scanf("%d%*c",&i);
                    for(j=0;j<LINEAS;j++)
                      printf("Línea %d: %s\n",j,libro[i][j]);
                    break;
          case 'Q':
            printf("\n\nSaliendo\n\n");
            break;
          default:
            printf("\n\nOpción incorrecta\n\n");
            break;
        }
      } while (toupper(opcion[0])!='Q');
      return 0;
    }
    
  6. #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define DIM_TABLERO 8
    
    int main()
    {
        char tablero[DIM_TABLERO][DIM_TABLERO];
        int fila, columna;
        int f_origen,c_origen;
        int f_destino,c_destino;
        char opcion;
        char menu[] ="a) Origen b) Destino q) Salir";
        /*
            Tablero en situación inicial
        */
        strcpy(tablero[0],"BBBBBBBB");
        strcpy(tablero[1],"BBBBBBBB");
        strcpy(tablero[2],"        ");
        strcpy(tablero[3],"        ");
        strcpy(tablero[4],"        ");
        strcpy(tablero[5],"        ");
        strcpy(tablero[6],"NNNNNNNN");
        strcpy(tablero[7],"NNNNNNNN");
        do
        {
    #ifdef __UNIX__
            system("clear");
    #else
            system("cls");
    #endif
            for (fila=0;fila<DIM_TABLERO;fila++)
            {
                printf("+---+---+---+---+---+---+---+---+\n");
                for (columna=0;columna<DIM_TABLERO;columna++)
                    printf("| %c ",tablero[fila][columna]);
                printf("|\n");
            }
            printf("+---+---+---+---+---+---+---+---+\n");
            printf("%s ",menu);
            scanf("%c%*c",&opcion);
            opcion = toupper(opcion);
            switch (opcion)
            {
            case 'A':
                printf("Indique fila y columna de la ficha que mueve (blancas): ");
                scanf("%d %d%*c",&f_origen,&c_origen);
                break;
            case 'B':
                printf("Indique fila y columna de destino: ");
                scanf("%d %d%*c",&f_destino,&c_destino);
                tablero[f_origen][c_origen]=' ';
                tablero[f_destino][c_destino] = 'B';
                break;
            case 'Q':
                break;
            default:
                printf("\n\nOpción incorrecta\7\n\n");
                break;
            }
        }
        while (opcion != 'Q');
        return 0;
    }
    /* Mejoras: convertir este programa en un juego razonable, aunque solo muestre
       las jugadas, sin intervención del ordenador en el juego. El programa debe
       permitir mover a blancas y negras, y comprobar q las jugadas son válidas
       (q hay una ficha en origen, que es del jugador, y que tienes sentido mover
       a ese destino). Idealmente, el programa debe "comer" automáticamente, y también
       promover a dama la ficha q llega a la fila base del contrario.
    
    */
    
  7. #include <stdio.h>
    #include <math.h>
    
    /*
    Construir un programa que admita dos vectores de ℜ³ y muestre el producto escalar,
     el productor vectorial, el módulo de los vectores, el coseno del ángulo que forman
    y el seno del ángulo que forman.
    */
    
    typedef float vector_r3[3];
    typedef float matriz_r3[3][3];
    
    int main (int argc, const char * argv[]) {
    
    	vector_r3 a,b;
    	float modulo_a = 0.0, modulo_b = 0.0;
    	float modulo_pv = 0.0;
    	float producto_escalar = 0.0;
    	float coseno = 0.0, seno = 0.0;
    	vector_r3 producto_vectorial;
    	int i;
    	/*
    	 Lectura de datos
    	 */
    	printf("Escriba el vector a: ");scanf("%f %f %f%*c",&a[0], &a[1], &a[2]);
    	printf("Escriba el vector b: ");scanf("%f %f %f%*c",&b[0], &b[1], &b[2]);
    	/*
    	 Cálculos - módulo del primer vector
    	*/
    	for (i=0; i<3; i++) {
    		modulo_a += a[i]*a[i];
    	}
    	modulo_a = sqrt(modulo_a);
    	/*
    	 Módulo del segundo vector
    	*/
    	for (i=0; i<3; i++) {
    		modulo_b += b[i]*b[i];
    	}
    	modulo_b = sqrt(modulo_b);
    	/*
    	 Producto escalar
    	 */
    	for (i=0; i<3; i++) {
    		producto_escalar += a[i]*b[i];
    	}
    	modulo_a = sqrt(modulo_a);
    	/*
    	 Coseno
    	*/
    	coseno = producto_escalar/(modulo_a*modulo_b);
    	/*
    	 Producto vectorial
    	*/
    	producto_vectorial[0] = a[1]*b[2] - a[2]*b[1];
    	producto_vectorial[1] = a[2]*b[0] - a[0]*b[2];
    	producto_vectorial[2] = a[0]*b[1] - a[1]*b[0];
    	/*
    	 Módulo del producto vectorial
    	*/
    	for (i=0; i<3; i++) {
    		modulo_pv += producto_vectorial[i]*producto_vectorial[i];
    	}
    	modulo_pv = sqrt(modulo_pv);
    	/*
    	 Seno
    	 */
    	seno = modulo_pv/(modulo_a*modulo_b);
    	/*
    	 Impresión de resultados
    	*/
    	printf("\n\nvector a: (");
    	for (i=0; i<3; i++) {
    		printf("%6.2f ",a[i]);
    	}
    	printf(")\nvector b: (");
    	for (i=0; i<3; i++) {
    		printf("%6.2f ",b[i]);
    	}
    	printf(")\n\n");
    	printf("Producto escalar: %6.2f\n\n",producto_escalar);
    	printf("Producto vectorial axb: (");
    	for (i=0; i<3; i++) {
    		printf("%6.2f ",producto_vectorial[i]);
    	}
    	printf(")\n\n");
    	printf("Coseno del ángulo que forman: %6.2f\n", coseno);
    	printf("Seno del ángulo que forman:   %6.2f\n", seno);
    	printf("\n\nTerminación normal del programa.\n\n");
        return 0;
    }
    
  8. #include <stdio.h>
    /*
     Construir un programa que admita una matriz 3x3 y un vector de ℜ³ y calcula
     el producto de la matriz por el vector. Sugerencia:
     si se llama f a la aplicación definida por la matriz, utilizar un vector de Ker(f)
     para comprobar que en efecto el resultado de aplicar la matriz al vector es el vector 0.
     */
    
    typedef float vector_3x1[3][1];
    typedef float matriz_3x3[3][3];
    
    /*
     Recuérdese q MxN x NxP = MxP
    
     En este no hay problema, son matrices cuadradas de dimensión N
     y el vector es de también de dimensión N ( = 3).
    
     Recuérdese también la expresión:
    
            N
           ---
           \
     w  =   >   a   * v
      i    /     ij    j
           ---
    	j = 1
    */
    
    
    int main (int argc, const char * argv[]) {
    
    	matriz_3x3 A;
    	vector_3x1 v;
    	vector_3x1 w;
    	int i,j;
    	printf("\n\nProducto de una matriz por un vector.\n\n");
    	/*
    	 Lectura de datos - matriz
    	 */
    	printf("Escriba los coeficientes de la matriz:\n\n");
    	for (i=0; i<3; i++) {
    		for (j=0; j<3; j++) {
    			printf("A[%d][%d] = ? ", i, j);
    			scanf("%f%*c",&A[i][j]);
    		}
    	}
    	printf("\n\nLa matriz considerada es:\n\n");
    	for (i=0; i<3; i++) {
    		printf("| ");
    		for (j=0; j<3; j++) {
    			printf("%6.2f ",A[i][j]);
    		}
    		printf("|\n");
    	}
    	/*
    	 Lectura de datos - Vector
    	 */
    	printf("\n\nEscriba el vector:\n\n");
    	for (i=0; i<3; i++) {
    		printf("v[%d] = ? ",i);
    		scanf("%f%*c",&v[i][0]);
    	}
    	printf("\n\nEl vector considerado es: \n\n");
    	for (i=0; i<3; i++) {
    		printf("| %6.2f |\n",v[i][0]);
    	}
    	/*
    	 Cálculo A * v = w
    	 */
    	for (i=0; i<3; i++) {
    		w[i][0] = 0.0;
    		for (j=0; j<3; j++)
    			w[i][0]+= A[i][j]*v[j][0];
    	}
    	/*
    	 Impresión de resultados
    	*/
    	printf("\n\nEl producto de la matriz por el vector es:\n\n");
    	for (i=0; i<3; i++) {
    		printf("| %6.2f |\n",w[i][0]);
    	}
    	printf("\n\nTerminación normal del programa.\n\n");
        return 0;
    }
    // Nota.- Obsérvese que no es necesario indicar que el número de
    //        columnas es 1; bastaría utilizar la definición normal,
    //        esto es, float v[3]. Sin embargo, se ha utilizado una definición
    //        que tiene en cuenta las filas y columnas para mostrar la conocida
    //        relación MxN x NxP = MxP, y que por tanto (si M=N=3 y P=1)
    //        el resultado de la multiplicación es un vector MxP = 3x1.
    //        Si se efectuase el cálculo vA (en lugar de Av), el resultado
    //        sería un vector 1x3 x 3x3 = 1x3, un vector fila (y no columna).
    

Ejercicios propuestos

  1. Ejercicio 0601r01.-Construir un módulo para la lectura y escritura de tablas de números de coma flotante (float y double). Emplear variables estáticas.

  2. Ejercicio 0601r02.-Construir un módulo capaz de realizar las operaciones siguientes en una tabla: Emplear variables estáticas.

  3. Ejercicio 0601r03.-Construir un módulo, ampliación del anterior, capaz de calcular Emplear variables estáticas.

  4. Ejercicio 0601r04.-Rehacer el ejercicio 1 con variables dinámicas.

  5. Ejercicio 0601r05.-Rehacer el ejercicio 2 con variables dinámicas.

  6. Ejercicio 0601r06.-Rehacer el ejercicio 3 con variables dinámicas.

  7. Ejercicio 0601r07.-Dar soporte en disco a los módulos anteriores.

  8. Ejercicio 0601r08.-Construir un programa sencillo de hoja de cálculo, basado en los módulos anteriores