Sunteți pe pagina 1din 17

Autor: José C.

Riquelme (Universidad de Sevilla)

TEMA 4. El tipo Array


1. Definición de tipos
1.1 Redenominación de tipos. Como ya hemos señalado en temas anteriores, el
lenguaje C define un conjunto muy limitado de tipos básicos. Por tanto, es labor del
programador definir tipos más complejos a partir de los tipos básicos cuando sea
necesario. Recuérdese que cuando se vio la estructura de un programa en C (Tema 2), la
definición de tipos se sitúa en un programa en C después de la declaración de
importaciones y de la definición de constantes y antes de la declaración de las
funciones. Aunque C no obliga a definir previamente un tipo, sino que pueden
declararse directamente variables de tipos complejos, en este manual recomendamos
fehacientemente, y así se lo exigimos a nuestros alumnos, que hay que definir un tipo
antes de declarar una variable de un tipo que no sea básico. La razón es obvia, se facilita
la escritura, el mantenimiento y la legibilidad del código. Normalmente distinguiremos
un identificador de tipo porque su primera letra será mayúscula.

La definición de tipos se realiza mediante la clausula typedef. Por ejemplo, puede ser
útil en la documentación del programa redefinir tipos básicos con nombres que indiquen
su función. Por ejemplo si vamos a definir variables que van a ser contadores, el
programador puede definir un tipo Contador, renombrando el tipo int, para dejar claro
que esas variables tienen esa función. Igualmente en una aplicación de la Secretaría de
un Centro puede resultar adecuado definir el tipo CódigoAsignatura como una
denominación particular del tipo long. Así se pondría en la sección de definición de
tipos:

typedef int Contador;


typedef long CodigoAsignatura;

y entonces podríamos declarar variables:

Contador numAlumnos, numAsignaturas;


CodigoAsignatura asignaturaRepetida;

1.1 Los tipos enumerados. C permite definir un tipo especial de datos para aquellos
valores que sólo pueden tomar un conjunto finito de valores, normalmente etiquetas.
Por ejemplo, imaginemos una aplicación que maneja sólo tres posibles colores: azul,
rojo y verde y que queremos definir una variable color_pantalla que sólo pueda tomar
esos valores. ¿Cómo lo haríamos?:

typedef enum {azul, rojo, verde} Color;

y la variable:
Tema 4. El tipo Array

Color color_pantalla, color_marco;

De esta manera, la variable color_pantalla sólo podrá tomar los valores señalados:

color_pantalla = azul;
color_marco = verde;

Nótese que azul o verde son etiquetas, no cadenas de caracteres (no hay ni debe haber
dobles comillas). Internamente en la memoria del ordenador las variables enumeradas se
guardan como valores enteros a partir del cero. Esto es, en la definición anterior azul es
el valor 0, rojo el valor 1 y verde el 2.

1.2 El tipo Lógico. Como hemos señalado anteriormente la versión ANSI del lenguaje
C no tiene predefinido un tipo booleano para guardar los valores de cierto y falso, sino
que a partir de valores enteros simula el valor de falso con un cero y el valor de cierto
con cualquier valor distinto de cero. Una forma de soslayar este inconveniente es definir
nuestro propio tipo booleano:

typedef enum {falso, cierto} Logico;

Nótese que el orden de las etiquetas debe ser obligatoriamente primero falso (igual a 0)
y después cierto (igual a 1). De esta forma podemos definir o incluso inicializar
variables booleanas:

Logico encontrado = falso, ordenado = cierto;

y usarlas en condiciones de sentencias while o if:

if (encontrado){


}

while(!ordenado){


}

2. El tipo array

2.1 Motivación. En las aplicaciones software normalmente se trabaja con colecciones


de datos. Por ejemplo, en el ámbito de gestión universitaria, tendríamos un conjunto de
profesores, listados de alumnos, listas de asignaturas, etc. En el ámbito comercial,
tendríamos un conjunto de clientes, catálogos de productos, listado de las ventas de un
Autor: José C. Riquelme (Universidad de Sevilla)

día, etc. La gestión de un aeropuerto tiene colecciones de vuelos, listas de pasajeros, etc.
En el ámbito de la salud, listas de pacientes, conjuntos de médicos, resultados de
experimentos, etc.

Un ejemplo más simple es cómo definir en C un punto en tres dimensiones. Sabemos


que un punto en el espacio viene dado por tres valores reales. Hasta este tema si
nosotros queríamos definir una variable punto3D, tendríamos que haber puesto:

float punto3D_x, punto3D_y, punto3D_z;

lo cual es una solución al menos engorrosa ya que tendríamos que manejar tres variables
para un solo concepto. La mejor solución es agrupar las tres coordenadas en un solo
tipo, como vemos en la siguiente sección.

2.2 El tipo array. Al ser C un lenguaje antiguo sólo dispone de un tipo “colección”1, un
tipo que podríamos llamar vector, tabla o por su nombre en inglés: array2. Podemos
entonces definir un array como un conjunto indexado de datos del mismo tipo
agrupados bajo un mismo identificador. En un array hay que tener en cuenta los
siguientes conceptos:

 Los elementos de un array ocupan posiciones consecutivas en la memoria. Esta


propiedad no es importante para el programador (se dice que es transparente)
pero si es importante para entender cómo funciona por dentro un array.
 Como se ha dicho todos los elementos de un array son del mismo tipo, por tanto
ocupan los mismos bytes en memoria.
 El nombre de la variable de tipo array es la dirección de memoria donde está a
primera posición del array.
 Estas tres propiedades anteriores hacen posible el acceso directo a cualquier
elemento del array como si fuera una variable independiente.
 El acceso directo en los arrays se lleva a cabo por indexación mediante el
operador corchete [ ] y un valor de tipo entero que se sitúa entre los corchetes y
es el índice a la posición.
 En un array hay que distinguir entre dimensión o tamaño máximo y el tamaño
real o simplemente tamaño. Lógicamente el tamaño debe ser siempre menor o
igual que la dimensión. La dimensión se fija en tiempo de compilación, esto es,
no puede modificarse durante la ejecución del programa. El tamaño del array si
puede cambiar, con el límite lógico de la dimensión.
 Siempre que trabajemos con un array en C debe venir acompañado de una
variable entera que indique su tamaño.

1
Java tiene este problema perfectamente resuelto.
2
Nosotros en este manual emplearemos normalmente el nombre de array, ya que vector es un
concepto matemático y tabla se suele reservar para representaciones bidimensionales tipo matriz. En
algunos textos hispano-americanos incluso es fácil encontrar la palabra “arreglo”.
Tema 4. El tipo Array

 La dimensión de un array debe ser una constante entera, que aconsejamos se


defina en la sección correspondiente mediante #define o cláusula const.
 Cada elemento de un array de tamaño n tiene asociado un índice (valor que se
pone entre corchetes): el primer elemento tiene índice 0 y el último tiene índice
n–13.
 Los arrays pueden contener elementos de cualquier tipo, arrays inclusive. Un
array de arrays debe entenderse como una tabla bidimensional o matriz.

2.3 Definición de un array. Como hemos dicho anteriormente el C permite definir


variables de un tipo no básico sin definir previamente el tipo. Así en C se podría definir
la variable punto3D de la siguiente forma:

float punto3D[3];

Entonces podremos dar el valor (1.1, 3.2, -4.5) con tres sentencias de asignación:

punto3D[0]=1.1;
punto3D[1]=3.2;
punto3D[2]=-4.5;

También se podría haber inicializado en la declaración:

float punto3D[3]= {1.1, 3.2, -4.5};

Sin embargo, ya se ha señalado que un buen programa (y por tanto un buen


programador) debe definir previamente la constante de la dimensión del array y el tipo.
De nuevo, téngase en cuenta que cada declaración debe ir en la posición adecuada
dentro de la estructura de un programa en C:

#define DIM 3

typedef int Vector3D[DIM];

Vector3D punto3D = {1.1, 3.2, -4.5};

Una representación gráfica de la variable punto3D es:

3
Esta es la explicación por la que los bucles for se suelen iniciar en 0 y terminar en n-1, en vez de
empezar en 1 y acabar en n.
Autor: José C. Riquelme (Universidad de Sevilla)

Una de las cuestiones que más trabajo cuesta entender a un alumno principiante es la
diferencia entre dimensión y tamaño real. Intentemos explicarlo:

 Cuando se define la dimensión de un array, se está fijando el número máximo de


elementos que ese array puede contener. Esto debe ser así porque al declarar un
array estamos reservando una cantidad de memoria fija4 y lógicamente hay que
decirle al compilador cuanta.
 ¿Eso significa que todos los arrays definidos de ese tipo están siempre
completos? Evidentemente no. Si yo trabajo con un array de alumnos se puede
decidir que no hay ningún grupo con más de 100 alumnos (dimensión igual a
100), pero puede haber grupos de 60, 75 u 80.
 ¿Qué pasa con las posiciones del array que no se están usando? Pues no pasa
nada, normalmente estarán en esas posiciones valores desconocidos, que reciben
el nombre de “basura”.
 Entonces si estamos usando un array ¿cómo se sabe cuáles son las posiciones
“válidas” y cuáles basura? Pues no se puede saber, salvo que en una variable de
tipo int guardemos el tamaño real del array, esto es el número de elementos
válidos que contiene el array.
 Por tanto la dimensión del array es la constante que se pone en la declaración del
typedef. El tamaño real es una variable de tipo int que deberá acompañar
siempre a un array y cuyo valor será menor que la dimensión.

2.4 Uso de un array. Las variables de tipo array no se pueden asignar con un operador
de asignación (=) o no se pueden comparar con un operador ==. Las variables de tipo
array se deben manejar posición a posición mediante el operador [ ] y un índice. Por
tanto, la mejor opción son los bucles for.

2.4.1 Bucles for. Como se ha señalado anteriormente los arrays tienen un número de
elementos que es su tamaño real. Por tanto, su tamaño aunque puede ser variable es
conocido por el programador y por eso, el uso habitual de los arrays es mediante bucles
for. Por ejemplo, cómo almacenar los n primeros cuadrados perfectos en un array:

Ejemplo 1:

#define DIM 20

4
Es la memoria que se conoce como memoria estática, en contraposición con la memoria dinámica que
se puede reservar en tiempo de ejecución y que no será materia de este manual.
Tema 4. El tipo Array


typedef int VectorEntero[DIM];

void main(void){
int i,n;
VectorEntero v;

printf("¿Cuántos números quiere (menor de 20)?\n");


scanf("%d",&n);
for(i=0;i<n;i++){
v[i]=i*i;
}
printf("Los primeros %d cuadrados perfectos son:\n",n);
for(i=0;i<n;i++){
printf("%d\n",v[i]);
}
}

Sin embargo, ya hemos señalado que la programación en C debe ser modular y que, por
tanto, es imprescindible manejar los arrays en las funciones de C.

2.4.1 ¿Cómo se pasa un argumento de tipo array a una función? Hay varias maneras de
que una función reciba y devuelva un array. Aunque profundizaremos en temas
posteriores sobre el uso de argumentos de entrada/salida en las funciones en C, en este
momento nos basta con saber dos cuestiones importantes:

 Una función en C no puede devolver un array en el nombre de la función.


 Siempre que un array se pasa a una función es argumento de entrada/salida. Esto
es, si un array es parámetro formal de una función y se modifica en la misma,
entonces el parámetro real también se modifica.

Para entender este problema, ejecutemos el siguiente código:

Ejemplo 2:
#include <stdio.h>
#define DIM 20
typedef int VectorEntero[DIM];

void prueba_argumento(int);
void prueba_array(VectorEntero);

void main(void){
int i,n;
VectorEntero v={1,2,3,4,5};

n=1;
prueba_argumento(n);
printf("n vale %d\n",n);

printf("valores de v antes de función\n");


Autor: José C. Riquelme (Universidad de Sevilla)

for(i=0;i<5;i++){
printf("%d\n",v[i]);
}

prueba_array(v);

printf("valores de v después de función\n");


for(i=0;i<5;i++){
printf("%d\n",v[i]);
}
}
void prueba_argumento(int a){
a++;
printf("a vale %d\n",a);
}
void prueba_array(VectorEntero t){
t[0]++;
}

Si se ejecuta esté código, la salida es la siguiente:

a vale 2
n vale 1
valores de v antes de función
1
2
3
4
5
valores de v después de función
2
2
3
4
5

¿Qué quiere decir este experimento? Que el valor int cómo argumento de la función
prueba_argumento es sólo de entrada, de forma que si el parámetro formal a se modifica
en la función sí cambia de valor dentro de la función, pero cuando se termina el
parámetro real n sigue valiendo lo mismo. Esto mismo hubiera ocurrido con argumentos
de tipo float, long, char, etc. Si embargo, con el argumento v no pasa lo mismo en la
función prueba_array. El parámetro real v tiene unos valores {1,2,3,4,5} antes de la
invocación, y el parámetro formal t cambia el primer valor del array. Este nuevo valor
de t queda reflejado en v cuando la función termina y el control vuelve al programa
principal.

¿Por qué sucede esto? Es decir ¿Por qué los argumentos de tipos básicos (int, float,
char, …) se comportan de forma diferente a los arrays cuando son argumentos de
funciones? La razón viene dada porque los argumentos reales de tipo básico son
“copiados” en los parámetros formales, pero no comparten zona de memoria. Sin
Tema 4. El tipo Array

embargo, por razones de eficiencia5 (de espacio y tiempo) los arrays no son copiados,
sino que el parámetro real (v en el caso anterior) y el formal (t) comparten zona de
memoria, y por tanto, toda acción sobre t tiene su efecto sobre v.

Para evitar efectos colaterales no deseados cuando una función recibe un vector que no
se debe modificar en la función, C proporciona el mecanismo de declararlo de tipo
constante. Para ello basta con poner la palabra const delante del tipo vector tanto en el
prototipo como en la cabecera de la definición:

void prueba_array(const VectorEntero);


void prueba_array(const VectorEntero t){

En este caso, el compilador nos avisaría de que estamos intentando modificar un valor
declarado constante cuando compila la sentencia t[0]++.

2.4.2 Ejercicio. Necesitamos almacenar un número indeterminado de notas de alumnos


para después calcular la media. No sabemos cuántas notas se leerán porque el número
de alumnos del grupo se introducirá por teclado una vez empezado el programa pero sí
sabemos que serán menos de 100.

Podemos intuir que este programa tiene dos partes claramente diferenciadas. En la
primera parte, deberemos leer un número indeterminado de valores reales y
almacenarlos para posteriormente usar esos valores para sumarlos y dividir por el
número de valores leídos. Es importante señalar que la división del problema en estas
dos partes, no sólo se hace por dividir el problema en tareas diferentes, sino que además
conseguimos que los “módulos” definidos puedan ser reutilizados con posterioridad.

Resolvamos entonces este problema en distintas fases. En primer lugar, tendremos que
definir los tipos necesarios para el problema. Necesitamos almacenar un número
indeterminado de valores reales pero menos de 100. Es decir, necesitamos un array de
datos de tipo float de dimensión 100. Para ello definiremos una constante MAXALUM
de valor 100 y un tipo VectorNotas de dimensión MAXALUM.

#define MAXALUM 100



typedef float VectorNotas[MAXALUM];

En la segunda fase tendremos que definir una función que lleve a cabo la lectura de los
valores. ¿Qué valores debe recibir esta función para llevar a cabo su cometido? ¿Qué
valores debe devolver? Hay dos posibilidades que el número de valores a leer se lea
también dentro de la función o que se lea antes de su invocación en el programa
principal. En el primer caso la función no necesita recibir ningún valor (void) y debe

5
Recuerde que el C es un lenguaje de los años 70 del siglo pasado
Autor: José C. Riquelme (Universidad de Sevilla)

devolver el array y el número de elementos leídos (tamaño del array). En el segundo


caso debe recibir el número de elementos a leer y devolver el array. Vamos a
implementar esta segunda posibilidad, dejando al lector la implementación de la
primera.

Para ello, la función debe recibir un entero con el número de valores a leer (será un
argumento de entrada) y debe devolver un array que como ya hemos dicho no puede ser
devuelto en el nombre de la función. Entonces el prototipo de esta función es:

void leerNotas(int, VectorNotas);

El código de esta función será básicamente un bucle for para leer el número de valores
que indique el argumento de tipo int y guardarlos en el VectorNotas:

void leerNotas(int n, VectorNotas t){


int i;
for(i=0;i<n;i++){
printf("Introduzca la nota %d: ",i+1);
scanf("%f",&t[i]);
}
}

Finalmente la función que calcule la media deberá recibir como argumento de entrada el
vector con las notas y el número de notas (tamaño real del vector) y devolver un valor
real con la media. Este valor de tipo float si puede ser devuelto en el nombre de la
función que tendrá un argumento de tipo int y otro const de tipo VectorNotas. El código
puede ser:

float notaMedia (int n, const VectorNotas t){


float suma=0;
int i;

for(i=0;i<n;i++){
suma = suma + t[i];
}
return suma/n;
}

De esta manera el programa principal podría ser:

void main(void){
int i,n;
VectorNotas vnotas;
float media;

printf ("introduce el número de notas\n");


scanf("%d",&n);
Tema 4. El tipo Array

leerNotas(n,vnotas);
media=notaMedia(n,vnotas);

printf("la media de las notas es %f\n",media);


}

¿Cuál es la principal ventaja de este código? Su reutilización, con muy pocos cambios
nos sirve para leer cualquier lista de valores reales y calcular su media.

3. Cadenas de caracteres.

3.1 Tipo Cadena. Aunque casi todos los lenguajes modernos tienen un tipo predefinido
para las cadenas de caracteres (normalmente con el nombre de String), sin embargo el
ANSI C no lo tiene. Por tanto, las cadenas de caracteres se implementan mediante un
array de tipo char6. Para ello, lo más cómodo es al igual que hacemos con el tipo
Logico, definir nuestro propio tipo Cadena:

#define MAXCAR 256



typedef char Cadena[MAXCAR];

De esta manera, definir variables de tipo Cadena sería:

Cadena palabra ="Hola", dni;

Nótese que la variable palabra es inicializada con la palabra Hola mientras que dni no
está inicializada a ningún valor.

3.2 Uso del tipo Cadena. No debemos olvidar que una variable de tipo Cadena es
realmente un array. Eso significa que no se le puede asignar valor directamente
mediante el símbolo = (salvo la inicialización a la vez que la declaración). Sin embargo,
a diferencia de otros arrays y debido al gran uso que este tipo de variables tiene, C
proporciona un conjunto de funciones predefinidas para el manejo de las cadenas de
caracteres:

 strlen (s): devuelve un entero con la longitud o número de caracteres de la


cadena s.
 strcpy(s,t): asigna el contenido de la cadena t a la cadena s. El valor previo
de s se pierde. El argumento t puede ser una variable o una constante entre
dobles comillas.

6
En los libros de texto tradicionales las cadenas de caracteres se implementan de diversos modos,
incluyendo punteros a char. Desde nuestro punto de vista es un error inducir al alumno principiante en
esa forma de definir y usar las cadenas de caracteres debido a la gran probabilidad de cometer errores
por no tener bien reservada la memoria que se usa.
Autor: José C. Riquelme (Universidad de Sevilla)

 strcat(s,t): concatena la cadena t a la cadena s.


 strcmp(s,t): compara las cadenas s y t, si son iguales devuelve cero. Si la
cadena s es mayor que t en orden léxico-gráfico (orden del diccionario) y
teniendo en cuenta que las mayúsculas van antes que las minúsculas, entonces
devuelve un valor positivo. Si por el contrario, t es mayor que s, entonces
devuelve un valor negativo.

Todas estas funciones se encuentran en la librería string.h que deberá ser importada
antes de su uso7.

Finalmente las variables de tipo Cadena pueden ser leídas y escritas mediante las
sentencias scanf y printf8 usando el formato %s. Es importante señalar que la función
scanf para cadenas de caracteres no antepondrá un símbolo & antes de la variable, como
ha sucedido hasta ahora.

Ejemplo 3 (Uso de cadenas de caracteres): Escriba un programa que lea tres cadenas de
caracteres con el nombre y dos apellidos de una persona y forme e imprima una cadena
de caracteres con el formato:
Primer_apellido Segundo_apellido, Inicial del nombre.

#include <stdio.h>
#include <string.h>
#define MAXCAR 256
typedef char Cadena[MAXCAR];

void main(void){
Cadena apel1, apel2, nombre;
Cadena inicial, resultado;
printf("escriba el nombre\n");
scanf("%s",nombre);
printf("escriba el primer apellido\n");
scanf("%s",apel1);
printf("escriba el segundo apellido\n");
scanf("%s",apel2);
inicial[0]=nombre[0];
inicial[1]='.';
inicial[2]='\0';

7
Una característica importante de las cadenas de caracteres y que es fundamental para poder usar las
funciones de la librería string.h es responder a la pregunta de cómo sabe el C cuando termina una
cadena. Dicho de otra manera, cómo distingue el compilador entre tamaño real y dimensión.
Recordemos que cuando se manipulan los arrays de tipo int o float debe usarse una variable que indique
el tamaño real de ese array. En las cadenas de caracteres ese problema está solucionado porque el
compilador añade un símbolo especial (‘\0’) al final de una cadena de caracteres. Este símbolo es usado
por el compilador de C para calcular la longitud de una cadena y a partir de esa información implementa
las funciones como strcpy o strcat. Esta cuestión es transparente para el programador salvo que se
vayan a manipular las cadenas de caracteres posición a posición, esto es, carácter a carácter.
8
Existen otras funciones para leer o escribir cadenas de caracteres en C, como gets o puts.
Tema 4. El tipo Array

strcpy(resultado,apel1);
strcat(resultado," ");
strcat(resultado,apel2);
strcat(resultado,", ");
strcat(resultado,inicial);
printf("%s\n",resultado);
}

4. Arrays de Cadenas de Caracteres.

Como se ha señalado en el último párrafo de la sección 2.2 de este tema, el tipo base de
un array puede ser cualquier tipo, incluyendo un array. En el caso de las cadenas de
caracteres, una forma habitual de uso en programación es organizarlas en tablas o arrays
de cadenas.

4.1 Definición de un array de cadenas. El código necesario para definir un array de


cadenas es el siguiente:

#define MAXCAR 256


#define NUMCAD 10

typedef char Cadena[MAXCAR];


typedef Cadena TablaCadena[NUMCAD];

Para definir una variable de tipo TablaCadena basta con poner el tipo y la lista de
variables:

TablaCadena listaPalabras;
TablaCadena diasSemana={"lunes", "martes", "miércoles", "jueves",
"viernes", "sábado", "domingo"};

4.2 Uso de un array de cadenas. Los arrays de cadenas de caracteres se usan igual que
el resto de los arrays, salvo que hay que tener en cuenta que sus elementos son cadenas
de caracteres. Por tanto, no se pueden asignar o comparar directamente sino usando las
funciones de string.h. Por ejemplo vamos a resolver el siguiente:

4.2.1 Ejercicio. Se quiere realizar un programa que lea desde teclado una lista de
palabras (menos de 100) hasta leer la palabra FIN y después lea una palabra s, indicando
cuántas veces está s en las palabras leídas.

Para resolver este problema habrá que construir dos funciones, una que lea la lista de
palabras y otra que cuente las apariciones. La primera debe devolver el array de cadenas
y (MUY IMPORTANTE) el número de palabras leídas. La segunda debe recibir el array
Autor: José C. Riquelme (Universidad de Sevilla)

de cadenas leídas, la palabra a contar y (MUY IMPORTANTE) el número de palabras


que hemos leído, es decir, el tamaño del array.

#include <stdio.h>
#include <string.h>
#define MAXCAR 256
#define NUMCAD 100

typedef char Cadena[MAXCAR];


typedef Cadena TablaCadena[NUMCAD];

int leePalabras(TablaCadena);
int cuentaPalabra(const TablaCadena, int, Cadena);

void main(void){
int npal,contador;
Cadena palabra;
TablaCadena listaPalabras;

npal= leePalabras(listaPalabras);

printf("Introduzca la palabra a buscar: ");


scanf("%s",palabra);
contador = cuentaPalabra(listaPalabras, npal, palabra);
printf("el número de veces que aparece %s es
%d\n",palabra,contador);
}

int leePalabras(TablaCadena t){


Cadena palabra;
int i=0;
printf("introduzca una serie de palabras acabada en FIN\n");
scanf("%s", palabra);
while (strcmp(palabra,"FIN")!=0){
strcpy(t[i], palabra);
i++;
scanf("%s",palabra);
}
return i;
}

int cuentaPalabra(const TablaCadena t, int n, Cadena s){


int i,cont=0;

for(i=0;i<n;i++){
if (strcmp(t[i],s)==0){
cont++;
}
}
return cont;
}
Tema 4. El tipo Array

5. Arrays bidimensionales.

Los arrays de cadenas de caracteres que hemos estudiado en la anterior sección son
realmente un array de array o array bidimensional9. Un array bidimensional corresponde
con el concepto matemático de matriz, entendiendo que una matriz no es más que un
array de filas y donde cada fila es a su vez un array.

5.1 Definición de un array bidimensional. Al igual que hemos comentado en los


arrays, se pueden definir variables de tipo matriz directamente sin definir previamente
un tipo. Aunque por supuesto recomendamos la declaración del tipo.

#define NUMFIL 4
#define NUMCOL 6

typedef float MatrizReal[NUMFIL][NUMCOL];

MatrizReal m;

Con la declaración de m se están reservando 4 posiciones de memoria (una por fila) y en


cada una de ellas se reservan 6 posiciones (una por columna).

5.2 Uso de un array bidimensional. C permite usar los arrays bidimensionales de dos
maneras: por filas tratando cada una como un array de dimensión el número de
columnas o elemento a elemento. En general, los arrays bidimensionales presentan el
mismo problema respecto a diferenciar entre tamaño real y dimensión pero para cada
dimensión. Por tanto, cuando se usan deben venir acompañados de dos variables de tipo
entero que indiquen el número real de filas y columnas usadas.

Entonces el recorrido típico de una matriz es con un doble bucle for con dos índices
distintos (normalmente i, j) que para cada valor de i desde 0 hasta el número de filas
9
C permite arrays de cualquier número de dimensiones
Autor: José C. Riquelme (Universidad de Sevilla)

(menor estricto), esto es para cada fila, recorre las columnas con un bucle en que la j
varía de 0 hasta el número de columnas:

for(i=0;i<nf;i++){
for(j=0;j<nc;j++){
// acción sobre t[i][j]

5.2.1 Ejercicio. Escriba un programa que lea dos valores enteros indicando un número
de filas (menor de 4) y columnas (menor de 6) y después lea los elementos de una
matriz de reales y posteriormente sume todos los valores.

La solución debe tener dos funciones: la primera para leer la matriz que recibirá el
número de filas y columnas y devolverá la matriz leída; y la segunda, para sumar los
elementos que recibirá la matriz, el número de filas y columnas y devolverá en el
nombre de la función el valor de la suma.

void main(void){
int n,m;
MatrizReal mat;
float suma;

printf("Deme el número de fila (<=4) :");


scanf("%d", &n);
printf("Deme el número de columnas (<=6) :");
scanf("%d", &m);

leeMatriz(mat,n,m);
suma = sumaMatriz(mat,n,m);

printf("la suma vale %f \n",suma);


}

void leeMatriz (MatrizReal t, int nf, int nc){


int i,j;

for(i=0;i<nf;i++){
for(j=0;j<nc;j++){
printf("deme el elemento (%d,%d): ",i,j);
scanf("%f",&t[i][j]);
}
}
}

float sumaMatriz(const MatrizReal t, int nf, int nc){


float sum=0.0;
int i,j;

for(i=0;i<nf;i++){
for(j=0;j<nc;j++){
sum= sum + t[i][j];
Tema 4. El tipo Array

}
}
return sum;
}

6. Problemas.

Para los siguientes problemas construya también un programa principal que invoque a
la función con distintos argumentos.

1. Construya una función tal que dado un array de números reales y un valor real p
devuelva cuántos elementos hay que sumar desde el primer valor para superar p.

2. Dado un valor entero n, construya una función que devuelva en un array los n
primeros valores primos. Supongamos n menor de 100.

3. Tenemos un array de cadenas con los nombres de unos alumnos y un array de


valores reales con sus notas (ambos del mismo tamaño). Construya una función
que dados ambos arrays devuelva otro con los alumnos que han aprobado (nota
mayor o igual que 5).

4. Dada una matriz de números reales construya una función que devuelva su valor
máximo.

5. Dada una matriz de números reales construya una función que devuelva un array
con la suma de sus elementos por filas.

6. Dada una matriz de números reales construya una función que devuelva un array
con la suma de sus elementos por columnas.

7. Construya una función que dada una matriz de reales cuadrada devuelva en un
array su diagonal principal.

8. Construya una función que dada una matriz de reales cuadrada devuelva en un
array su diagonal secundaria.

9. Construya una función que reciba dos matrices reales de la misma dimensión y
devuelva su suma.

10. Dada una matriz y un índice de fila devuelva un vector con la fila que
corresponde.
Autor: José C. Riquelme (Universidad de Sevilla)

11. Dada una matriz y un índice de columna devuelva un vector con la columna que
corresponde.

S-ar putea să vă placă și