Download PRÁCTICA 5: TABLAS T RANSFORMACIÓN DE LEA A C
Document related concepts
Transcript
INTRODUCCIÓN A LA PROGRAMACIÓN 1 PRÁCTICA 5: TABLAS TRANSFORMACIÓN DE LEA A C LEA C DECLARACIÓN DE UNA TABLA Tabla unidimensional: nombre: tabla[dim] de tipo Tabla unidimensional: tipo nombre [dim]; Tabla multidimensional: nombre: tabla[dim1, dim2, ..., dimn] de tipo Tabla multidimensional: tipo nombre [dim1][dim2]...[dimn]; const TAM: 10 MAXCAR: 80 NHORAS: 24 NFIL: 2 NCOL: 5 var v: tabla[TAM] de entero palabra: tabla[MAXCAR] de caracter temperaturas: tabla[NHORAS] de real m: tabla[NFIL, NCOL] de entero #define TAM 10 #define MAXCAR 80 #define NHORAS 24 #define NFIL 2 #define NCOL 5 int v[TAM]; char palabra[MAXCAR]; double temperaturas[NHORAS]; int m[NFIL][NCOL]; Se puede inicializar la tabla al declararla: int v[TAM]={1,2,3,4,5,6,7,8,9,10}; int m[NFIL][NCOL]={{1,2,3,4,5},{2,4,6,8,10}}; DEFINICIÓN DE UN TIPO TABLA Nombre: tabla[dim1, dim2, ..., dimn] de tipo typedef tipo Nombre[dim1][dim2]...[dimn]; tipos Vector10: tabla[TAM] de entero Cadena: tabla[MAXCAR] de caracter Tempe: tabla[NHORAS] de real Matriz2x5: tabla[NFIL, NCOL] de entero var v: Vector10 palabra: Cadena temperaturas: Tempe m: Matriz2x5 typedef int Vector10[TAM]; typedef char Cadena[MAXCAR]; typedef double Tempe[NHORAS]; typedef int Matriz2x5[NFIL][NCOL]; Vector10 v; Cadena palabra; Tempe temperaturas; Matriz2x5 m; ACCESO A UN ELEMENTO DE UNA TABLA variable_tabla[índice] (el índice comienza en 1) variable_tabla[índice] (el índice comienza en 0) i := v[6] palabra[1] := 'A' m[2,5] := 5 i = v[5]; palabra[0] = 'A'; m[1][4] = 5; Práctica 5: Tablas 2 LEA C PASO DE UNA TABLA COMO PARÁMETRO Tabla unidimensional (entrada): Llamada: v: Vector10 n: entero funcion1 (v, n) Definición: proc funcion1 (ent vector: Vector10, num: entero) var i: entero prin desde i:=1 hasta num escribir vector[i] fdesde fin Tabla unidimensional (entrada/salida): Llamada: v: Vector10 n: entero funcion2 (n, v) Definición: proc funcion2 (ent num: entero; ent/sal vector: Vector10) var i: entero prin desde i:=1 hasta num vector[i] := vector[i] + 1 fdesde fin Tabla multidimensional: Llamada: m: Matriz2x5 n, l: entero funcion3 (m, n, l) Definición: proc funcion3 (ent matriz:Matriz2x5, elem_x:entero, elem_y:entero) var i, j: entero prin desde i:=1 hasta elem_x desde j:=1 hasta elem_y escribir matriz[i,j] fdesde fdesde fin EXPERIMENTOS Tabla unidimensional (entrada): Prototipo: a) void funcion1 (const Vector10, int); b) void funcion1 (const int [TAM], int); c) void funcion1 (const int [], int); Llamada: Vector10 v; int n; funcion1 (v, n); Definición para el prototipo a): void funcion1 (const Vector10 vector, int num) { int i; for (i=0; i<num; i++) printf ("%d\n", vector [i]); } Tabla unidimensional (entrada/salida): Prototipo a) void funcion2 (Vector10, int); b) void funcion2 (int [TAM], int); c) void funcion2 (int [], int); Llamada: Vector10 v; int n; funcion2 (v, n); Definición para el prototipo a): void funcion2 (Vector10 vector, int num) { int i; for (i=0; i<num; i++) vector[i]++; } Tabla multidimensional: Prototipo: a) void funcion3 (const Matriz2x5, int, int); b) void funcion3 (const int [NFIL][NCOL], int, int); c) void funcion3 (const int [][NCOL], int, int); Llamada: Matriz2x5 m; int n, l; funcion3 (m, n, l); Definición para el prototipo a): void funcion3 (const Matriz2x5 matriz, int elem_x, int elem_y) { int i, j; for (i=0; i<elem_x; i++) for (j=0; j<elem_y; j++) printf ("%d\n", matriz[i][j]); } Práctica 5: Tablas E.5.1 3 Escriba el siguiente código y ejecútelo paso a paso (con F10), controlando con la opción watch los valores de las tablas t1 y t2. Fíjese al final del primer bucle como cambia el valor de t1[0]. Al final de la ejecución el compilador le avisará de un error. ¿Por qué no funciona? Modifíquelo para que funcione sin problemas. #include <stdio.h> #define TAM 10 typedef int Tabla[TAM]; void main(void) { Tabla t1,t2; int i; for (i=0;i<=TAM;i++) { t1[i]=2*i; t2[i]=i*i; } for (i=0;i<=TAM;i++) printf("\n%d %d\n",t1[i],t2[i]); } E.5.2 Escriba, compile y ejecute el siguiente código. ¿Qué es lo que va mal? Indique a qué se debe y cómo debe modificarse el programa para solucionarlo. #include <stdio.h> #define TAM 10 typedef int Tabla[TAM]; void muestraTabla (const Tabla); void main(void) { Tabla tab; int i, n=7; for (i=0; i<n; i++) tab[i]=i; muestraTabla (tab); } void muestraTabla (const Tabla t) { int i; for (i=0; i<TAM; i++) printf ("\nElemento %d: %d", i, t[i]); } EJERCICIOS DE SINTAXIS PROPUESTOS S.5.1 Escriba la declaración de las siguientes variables de tipo tabla: · Una tabla temperaturas con 24 elementos de tipo float. · Una tabla nombre con 20 elementos de tipo char. · Una tabla ajedrez de 8x8 elementos de tipo int. · Una tabla diasmes con 12 elementos de tipo int que representen el número de días de los 12 meses del año (inicialice la tabla al declararla). · Una tabla alfabeto que contenga los 27 caracteres del alfabeto español (inicialice la tabla al declararla). S.5.2 Repita la cuestión anterior, pero esta vez defina en primer lugar un tipo y declare a continuación la variable utilizando dicho tipo. S.5.3 Escriba un programa que lea una lista de un máximo de 50 números enteros positivos, los almacene en una tabla, los ordene de menor a mayor y los imprima en dicho orden. Utilice la función de ordenación que se proporciona en LEA, definiendo adecuadamente el tipo tabla Tt. Práctica 5: Tablas 4 proc ordenacion_intercambio (ent n: entero; ent/sal v: Tt) var i: entero ordenado: lógico prin ordenado := falso mientras NO ordenado ordenado := cierto desde i:=1 hasta n-1 si v[i] > v[i+1] <v[i], v[i+1]> := <v[i+1], v[i]> ordenado := falso fsi fdesde fmientras fin S.5.4 Escriba un programa que lea una lista de un máximo de 50 números enteros positivos, los almacene en una tabla y los ordene de menor a mayor. Seguidamente, el programa pedirá un valor por teclado y lo buscará en la tabla, imprimiendo la posición que ocupa el valor en la misma, en caso de encontrarlo, o el mensaje "Elemento no encontrado" si no se encuentra. Utilice la función de búsqueda binaria que se proporciona: int busqueda_binaria_int ( ________________________ ) { int pos = -1; Logico encontrado = Falso; int bajo = 0, alto = n-1, central; while (bajo<=alto && !encontrado) { central = (bajo + alto)/2; if (v[central] == x) { pos = central; encontrado = Cierto; } else if (v[central] < x) bajo = central+1; else alto = central-1; } return (pos); } ¿Qué parámetros habrá que pasarle a la función anterior? ¿Cuál es la función de cada uno de ellos? Responda a estas preguntas y rellene adecuadamente el hueco con los parámetros que estime oportunos. S.5.5 Dado el siguiente programa que presenta en la salida estándar la posición (fila y columna) donde se encuentran los ceros de una tabla bidimensional notas de 5x5 enteros, describa todos los errores que hay en el mismo y escríbalo correctamente. include <stdio.h> define MAX 5; typedef int Tabla5X5[][]; void main (void) { int i, j, num; Tabla5X5 notas={0,2,5,7,6, 0,0,0,3,8, 2,9,6,3,4, 1,5,6,1,4, 0,9,2,5,0}; int filas[MAX*MAX]; int columnas[MAX*MAX]; i=0, cont=0; while i<MAX { Práctica 5: Tablas 5 j=0; while j<MAX { if (notas[i][j]=0) { cont++; filas[cont]=i; columnas[cont]=j; } } } printf (" FILAS COLUMNAS\n"); for (i=0; i<cont; i++) printf ("8%d\t8%d\n", filas[i]+1, columnas[i]+1); } En este programa la salida debería ser: FILAS 1 2 2 2 5 5 S.5.6 COLUMNAS 1 1 2 3 1 5 Sea el siguiente programa: #include <stdio.h> #define MAX 20 #define ESPACIOS " " /* tres espacios en blanco */ void misterio (int); void main (void) { int n; printf ("\nIntroduzca un número: "); scanf ("%d", &n); misterio (n); } void misterio (int n) { int i, j, t[MAX]={1}, s[MAX]; if (n > 0) { for (j=1; j<n; j++) printf ("%s", ESPACIOS); printf ("%3d\n", t[0]); for (i=1; i<n; i++) /* Bucle principal */ { /* Punto 1 */ s[0] = 1; for (j=1; j<i; j++) s[j] = t[j-1] + t[j]; s[j] = 1; for (j=1; j<n-i; j++) printf ("%s", ESPACIOS); for (j=0; j<=i; j++) { t[j] = s[j]; printf ("%3d%s", t[j], ESPACIOS); /* Punto 2 */ } printf ("\n"); } } } Siga la traza del mismo para el valor n=5, indicando el contenido de la tabla s en el punto 1 y el resultado impreso en el punto 2 para cada valor del índice i. Indique tan sólo el resultado impreso para n=7. Práctica 5: Tablas S.5.7 6 Escriba un módulo de funciones para el manejo de tablas de datos de tipo double. Dicho módulo contendrá las siguientes funciones: · lee_vector_double: lee una serie de valores de la entrada estándar y los almacena en una tabla. · escribe_vector_double: escribe en la salida estándar los valores de una tabla. · busqueda_secuencial_double: realiza una búsqueda secuencial de un elemento en una tabla. · busqueda_binaria_double: realiza una búsqueda binaria de un elemento en una tabla ordenada. · ordenacion_intercambio_double: ordena una tabla ascendentemente utilizando el esquema de intercambio. El fichero de cabecera del módulo, v_doble.h, será el siguiente: #define TAM 100 typedef enum {Falso, Cierto} Logico; typedef double Vector[TAM]; int lee_vector_double (Vector); void escribe_vector_double (const Vector, int); int busqueda_secuencial_double (const Vector, int, double); int busqueda_binaria_double (const Vector, int, double); void ordenacion_intercambio_double (Vector, int); S.5.8 El siguiente programa utiliza una función del módulo definido en el apartado anterior. Compile y ejecute el programa. #include <stdio.h> #include "v_doble.h" void main { Vector int n, double (void) v; posicion; x; n = lee_vector_double (v); printf ("\nIntroduzca un número: "); scanf ("%lf", &x); posicion = busqueda_secuencial_double (v, n, x); if (posicion != -1) printf ("\nElemento encontrado en la posición %d", posicion); else printf ("\nElemento no encontrado"); } S.5.9 El siguiente programa lee una tabla, la ordena y la presenta en la salida estándar, utilizando las funciones del módulo. Compile y ejecute el programa. #include <stdio.h> #include "v_doble.h" void main (void) { Vector v; int n; n = lee_vector_double (v); ordenacion_intercambio_double (v, n); escribe_vector_double (v, n); } EJERCICIOS DE ALGORÍTMICA PROPUESTOS A.5.1 Escriba un programa que declare una tabla de 10 elementos de tipo entero y la rellene con los cuadrados de los 10 primeros números naturales. A.5.2 Escriba una función Práctica 5: Tablas 7 void tabla_multiplos (int n, int multiplos[10]); que reciba como entrada un número entero y construya una tabla con los 10 primeros múltiplos de dicho número. A.5.3 Escriba un programa que declare una tabla de 10×10 elementos de tipo entero y la rellene de la siguiente forma: 1 2 11 12 21 22 ... 91 92 3 13 23 4 14 24 5 15 25 6 16 26 7 17 27 8 18 28 9 19 29 10 20 30 93 94 95 96 97 98 99 100 A.5.4 Escriba un programa que declare una tabla de 10×10 elementos de tipo entero y la rellene de la siguiente forma: 1 2 2 4 3 6 ... 10 20 3 6 9 4 8 12 5 10 15 6 12 18 7 14 21 8 16 24 9 18 27 10 20 30 30 40 50 60 70 80 90 100 A.5.5 Escriba un programa que lea una lista de números reales, los almacene en una tabla y calcule e imprima la suma, el valor máximo, el valor mínimo y el valor medio de todos ellos. El tamaño de la lista de números se conocerá de antemano, y en ningún caso excederá de 100. A.5.6 Modifique el programa anterior para que indique cuántos elementos son mayores y cuántos son menores que el valor medio. A.5.7 Escriba un programa que lea una lista de números enteros positivos, los almacene en una tabla y los imprima en orden inverso al que fueron leídos. El tamaño de la lista es desconocido, siendo 50 como máximo. El final de la lectura ocurrirá cuando se hayan leído 50 números o se lea un valor negativo o cero. A.5.8 Escriba un programa que lea una lista de un máximo de 50 números enteros positivos y los almacene en una tabla. Seguidamente, el programa pedirá un valor por teclado y lo buscará en la tabla, imprimiendo la posición que ocupa el valor en la misma, en caso de encontrarlo, o el mensaje "Elemento no encontrado" si no se encuentra. Utilice la función de búsqueda secuencial que se proporciona: int busqueda_secuencial_int (const int v[], int n, int x) { int pos = -1; Logico encontrado = Falso; int i = 0; while (i<n && !encontrado) { if (v[i] == x) { pos = i; encontrado = Cierto; } else i++; } return (pos); } A.5.9 Escriba una función void tabla_digitos (int n, int digitos[5]); que reciba como entrada un número entero y construya una tabla con sus dígitos. Si el número tiene menos de cinco cifras, las restantes se pondrán a cero. Por ejemplo, tras la llamada tabla_digitos (1835, tab); Práctica 5: Tablas 8 el contenido de la tabla tab será: 0 1 8 3 5 A.5.10 La función valida_dato, cuyo prototipo es int valida_dato (int dato, const int valores[10]); devuelve el propio valor dato si éste se encuentra en la tabla valores, y el primer elemento de la tabla en caso contrario. Un ejemplo de llamada es opcion = valida_dato (opcion, tablaopciones); Se desea modificar la función de forma que se llame de la forma valida_dato (&opcion, tablaopciones); Indique el nuevo prototipo y desarrolle el correspondiente código de la función. A.5.11 Se desea realizar una función que escriba en la pantalla los elementos de una tabla unidimensional que cumplen una determinada condición. Para ello se tiene la siguiente declaración: void procesa_tabla (const int t[], int n, int operador, int valor); donde · · · · t es la tabla a procesar. n es el número de elementos de la tabla. operador es el tipo de comparación a efectuar, y puede tomar los valores constantes MAYOR, MENOR o IGUAL (constantes definidas). valor es el valor con el cual hay que comparar. Por ejemplo, la llamada procesa_tabla (tab, n, MAYOR, 0); escribirá los elementos de la tabla tab que sean mayores que cero. A.5.12 Realice una función que reciba como parámetro una tabla de números enteros y suprima de la tabla todos aquellos números que no sean cuadrados perfectos, dejando en las primeras posiciones de la tabla sólo aquellos que sí lo sean. El prototipo de la función será void cuadrados_perfectos (int perfectos[TAM]); NOTAS: · La dimensión de la tabla viene dada por la constante TAM. · Los números que hay en la tabla son todos estrictamente positivos hasta que a partir de uno todos tienen valor -1. · Al terminar el proceso, las posiciones no ocupadas de la tabla deben quedar a -1. · Un cuadrado perfecto es un número estrictamente positivo con raíz cuadrada entera exacta. A.5.13 En el tratamiento de una imagen de vídeo se almacena el color de cada punto de la imagen como un valor entero en una matriz cuadrada N×N. Construya una función filtro según el prototipo #define N 4 void filtro (const int entrada[][N], int salida[][N-2]); que devuelva en una matriz (N-2)×(N-2) una nueva imagen formada por los puntos internos de la imagen inicial (no se consideran los bordes) en la que el valor de cada elemento sea la media aritmética entera de los 8 elementos Práctica 5: Tablas 9 circundantes y de él mismo. En el ejemplo que se muestra seguidamente se tratan los elementos de la parte sombreada de la primera matriz obteniéndose como resultado la segunda. Imagen inicial (entrada): 1 2 3 4 5 1 2 3 2 1 3 4 7 8 1 2 Imagen filtrada (salida): (1+2+3+5+1+2+2+1+3)/9=20/9 -> 2 2 <- (2+3+4+1+2+3+1+3+4)/9=23/9 (5+1+2+2+1+3+7+8+1)/9=30/9 -> 3 2 <- (1+2+3+1+3+4+8+1+2)/9=25/9 A.5.14 Una matriz de números reales se encuentra almacenada mediante los siguientes vectores: · · · · Un vector tval de MAXELEM elementos que contiene los valores de los elementos de la matriz, en cualquier orden. Un vector tcol de MAXELEM elementos donde tcol[i] es la columna del elemento i-ésimo del vector tval (siendo la primera columna la 0). Un vector tnex de MAXELEM elementos donde tnex[i] es la posición que ocupa en tval el elemento que sigue en la fila al elemento i-ésimo del vector tval. Si tval[i] es el último elemento de la fila, tnex[i] contendrá un valor -1. Un vector tcom de MAXFIL elementos donde tcom[i] contiene la posición en el vector tval del primer elemento de la fila i-ésima de la tabla. Si una fila está vacía, el elemento correspondiente de tcom valdrá -1. Por ejemplo, la matriz 1.5 0 4.2 0 0 0 0 0 0 0 0 0 1.0 2.3 1.1 2.9 0 5.1 2.0 0 estaría almacenada de la siguiente manera: tcom 3 -1 5 0 4 tval 2.3 1.0 2.9 1.5 1.1 4.2 5.1 2.0 tcol 2 2 3 0 2 0 3 3 tnex 7 6 -1 2 -1 1 -1 -1 Fila 0: Comienza en tcom[0]=3 -> 1er elto: tval[3]=1.5, columna: tcol[3]=0 Sigue en la posición tnex[3]=2 -> 2º elto: tval[2]=2.9, columna: tcol[2]=3 Sigue en la posición tnex[2]=-1 -> no hay más elementos Fila 1: Comienza en tcom[1]=-1 -> no hay elementos Fila 2: Comienza en tcom[2]=5 -> 1er elto: tval[5]=4.2, columna: tval[5]=0 Sigue en la posición tnex[5]=1 -> 2º elto: tval[1]=1.0, columna: tcol[1]=2 Práctica 5: Tablas 10 Sigue en la posición tnex[1]=6 -> 3er elto: tval[6]=5.1, columna: tcol[6]=3 Sigue en la posición tnex[6]=-1 -> no hay más elementos Fila 3: Comienza en tcom[3]=0 -> 1er elto: tval[0]=2.3, columna: tcol[0]=2 Sigue en la posición tnex[0]=7 -> 2º elto: tval[7]=2.0, columna: tcol[7]=3 Sigue en la posición tnex[7]=-1 -> no hay más elementos Fila 4: Comienza en tcom[4]=4 -> 1er elto: tval[4]=1.1, columna: tcol[4]=2 Sigue en la posición tnex[4]=-1 -> no hay más elementos Escriba una función con el prototipo double suma_columna (const int tcom[], const int tcol[], const int tnex[], const double tval[], int n_fil, int columna); que calcule y devuelva la suma de los elementos de la matriz situados en la columna que se pasa como parámetro. El parámetro n_fil indica el número de filas de la matriz. A.5.15 Construya una función Logico dia_habil (int dia, int mes, int anyo, int inicio, const int diasmes[2][12], const int dias_fiesta[TAM][2]); que reciba como entrada un día dado por dia, mes y anyo, que se supone válido, y devuelva Cierto si el día es hábil y Falso si no lo es. Se consideran días hábiles de lunes a sábado, ambos incluidos, exceptuando los días festivos, que se encuentran almacenados en una tabla. El parámetro inicio contiene un valor entre 1 y 7 que indica el día de la semana correspondiente al primer día del año anyo (1=lunes, 2=martes, ..., 7=domingo). La tabla diasmes contiene el número de días de cada mes del año (la primera fila es para años normales y la segunda para años bisiestos): 31 28 31 30 31 30 31 31 30 31 30 31 31 29 31 30 31 30 31 31 30 31 30 31 La tabla de fiestas dias_fiesta corresponde al año anyo y tiene dos columnas: la primera contiene el día (entre 1 y 31) y la segunda el mes (entre 1 y 12). El número de filas de la tabla viene dado por la constante TAM, y después de la última fiesta todos los elementos restantes de la tabla tienen valor 0 (véase ejemplo). 1 1 6 1 28 2 ... 25 12 0 0 0 0 Para construir la función escriba previamente las dos siguientes: int dias_transcurridos (int dia, int mes, int anyo,const int diasmes[2][12]); Obtiene el número de días transcurridos desde el 1 de enero de anyo hasta la fecha dada por dia, mes y anyo. Logico es_fiesta (int dia, int mes, const int dias_fiesta[TAM][2]); Indica si una fecha dada por dia y mes es festivo o no. A.5.16 Un determinado sistema está representado por un tipo que se ha denominado PORTADOR y que está Práctica 5: Tablas 11 representado en C por una tabla bidimensional de 10x10 enteros. Realice una función que haga evolucionar un ejemplar de dicho tipo conforme a las siguientes reglas: 1. 2. 3. Cada elemento de la tabla evoluciona de tal manera que en la siguiente generación dicho elemento será la media entera de todos los elementos de la tabla que lo rodean. Se formarán como máximo 10 generaciones o hasta que una generación se repita. Las distintas generaciones obtenidas se irán mostrando en la salida estándar. Por ejemplo, el siguiente PORTADOR 1 3 2 1 4 1 2 1 3 evoluciona en primera generación a 2 1 2 2 1 2 2 2 2 El prototipo de la función a realizar es: void evoluciona (PORTADOR a); A.5.17 Escriba el trozo de código C que realiza, mediante estructuras repetitivas, el recorrido en diagonal de la matriz cuadrada m de MAX×MAX elementos empezando en el extremo inferior izquierdo y finalizando en el último elemento de la diagonal principal. Por ejemplo, para la siguiente matriz 1 2 3 4 5 6 7 8 9 debe presentarse en pantalla 7 4 8 1 5 9 A.5.18 Una función tiene como parámetros una tabla de enteros, su número de elementos y una variable de tipo Lógico. Dicha función modifica el valor de la variable lógica, asignándole Cierto si la tabla está ordenada y Falso en caso contrario. Escriba el prototipo de la función y una llamada válida a la misma. Declare las variables que le sean necesarias. A.5.19 Escriba una función que reciba como parámetro un vector de enteros positivos (el final de los elementos válidos en el vector viene dado por un valor negativo) y devuelva la media de todos los elementos del vector. A.5.20 Una imagen de 256×256 pixels está representada por una tabla de 256x256 enteros. Cada elemento de la tabla representa el color del punto correspondiente de la imagen. Realizar una función en C que transforme dicha tabla en otra de la misma dimensión que tenga un marco de 2 pixels con un color definido que se pasa como parámetro a la función. Como ejemplo, sea la siguiente tabla, que por simplicidad se considera de 10x10 en lugar de 256x256: 1 1 1 1 2 2 3 3 1 1 1 1 1 1 2 2 3 3 1 1 1 1 1 2 2 2 3 3 1 1 1 2 2 2 2 3 3 3 2 1 2 2 2 2 3 3 3 2 2 2 3 3 3 3 3 3 2 2 2 2 3 3 3 3 3 3 2 2 2 2 3 3 3 3 3 3 3 2 2 1 1 1 1 3 3 3 3 1 1 1 1 1 1 1 1 3 3 3 1 1 Práctica 5: Tablas 12 Si se llama a la función con esta tabla y el 0 como color del marco, se obtiene la siguiente tabla: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 3 3 0 0 0 0 2 2 2 3 3 3 0 0 0 0 2 2 3 3 3 2 0 0 0 0 3 3 3 3 2 2 0 0 0 0 3 3 3 3 2 2 0 0 0 0 3 3 3 3 3 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 A.5.21 Un cuadrado mágico es una matriz cuadrada con un número impar de filas y columnas, cuyas filas y columnas (e incluso sus diagonales principal y secundaria) suman el mismo valor. Por ejemplo, la matriz siguiente es un cuadrado mágico de 3 por 3: 6 7 2 1 5 9 8 3 4 Los números en cada fila, cada columna y cada diagonal suman 15. Una técnica que se utiliza para generar cuadrados mágicos es la siguiente: se comienza fijando un valor de 1 en el elemento central de la primera fila. A continuación, se van escribiendo los sucesivos valores (2, 3, etc.) desplazándose desde la posición anterior una fila hacia arriba y una columna hacia la izquierda. Estos desplazamientos se realizan tratando la matriz como si estuviera envuelta sobre si misma, de forma que moverse una posición hacia arriba desde la fila superior lleva a la inferior y moverse una posición a la izquierda desde la primera columna conduce a la última. Si la nueva posición está ya ocupada, en lugar de desplazarse una fila hacia arriba y una columna hacia la izquierda, se moverá simplemente una fila hacia abajo y continuará el proceso. Escriba un programa en C que escriba el cuadrado mágico de dimensión n, siendo n un número impar que introduce el usuario y está comprendido entre 1 y 9.