ARREGLOS
DEFINICIÓN: Un arreglo es una coleción de variables del mismo tipo, las cuales se referencian por el mismo nombre. Un arreglo se declara de la siguiente manera:
tipo identificador [límite];Donde "límite" indica la cantidad de variables que se desea definir para el arreglo.
int a[10];INICIALIZACIÓN: Como cualquier variable, un arreglo puede ser inicilizado en el momento de su declaración. Esta opracón se realiza de la siguiente manera:
ð donde "a" es el nombre que identifica al arreglo de tipo int, el cual se define con 10 elementos, estos son:
a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8] y a[9]
int a[10] = {3, 5, 1, 7, 0, 2, 6, 9, 8, 4};Si se colocan menos valores de inicialización que la capacidad del arreglo, el resto de elementos del arreglo se inicializa en cero. Si por ejemplo:
Esto signfica que a la variable a[0] se le asigna el valor de 3,a la variable a[1] ï 5, ... a la varble a[9] ï 4
int a[5] = {3, 5, 1};También, como se muestra a continuación, al definir un arreglo con valores iniciales se puede omitir el tamaño de éste:
Esto signfica que:
a[0] ï 3, a[1] ï 5, a[2] ï 1, a[3] ï 0, a[4] ï 0.
int a[ ] = {3, 7, 9, 5};El número de elementos del arrglo lo define la cantidad de valores con el que se desea inicializar.
Luego a[0] ï 8, a[1] ï 7, a[2] ï 9, a[3] ï 5Sin embargo, se debe tener en cuenta que de alguna manera se debe indiar al compilador el tamaño del arreglo, ya sea colocando un valor constante entre los corchetes ([ ]) o mediante valores iniciales, es por eso que:
int a[ ]; /* es un error porque no se le indica el tamaño del arreglo. */Otro error que se comete cuando se define un arreglo es que se pretende definir el tamaño con una variable, esto es:
int n;El siguiente ejemplo muestra otro error muy común:
printf("Ingrese el tamaño del arreglo: ");
scanf("%d", &n);
int a[n]; /* es un error debido a que el tamaño de un arreglo se define en tiempo de compilación y aquí se pretende definir en tiempo de ejecución. */
int funcPrueba(int n)ASIGNACIÓN DE VALORES: Asignar valores a un elemento de un arreglo es una tarea relativamente sencilla, la asignación se realiza colocando el nombre del arreglo seguido de un par de corchetes, entre los cuales se coloca una expresión que, al ser evaluada, determine a qué elemento del arreglo se le quiere asignar un valor, luego se coloca un signo de asignación seguido de una expresión que, al ser evaluada, dará el valor que se desea asignar al alemento del arreglo.
{ int a[n]; /* es un error por la misma razón que la del ejemplo anterior. */
int a[5], n = 2 , p = 15;La tarea de asignar valores a los elementos de un arreglo, como se ha podido ver, es una tarea sencilla, sin embargo debido a que el compilador de C/C++ no verifica los rangos para los que se ha definido el arreglo, si no se toma el cuidado necesario se podría incurrir en errores muy serios.
a[2] = 35;
a[0] = p*3; /* asigna 45 (resultado de evaluar p*3) al primer elemento del arreglo (a[0]) */
a[n + 1] = 17; /* asigna 17 al cuarto elemento del arreglo (n+1 = 3) */
a[p/3-1] = 23*n/5; /* asigna 9 (23*n/5=9) al quinto elemento del arreglo (p/3-1 = 4) */
DMAn = DMA + n x sizeof(TA)Donde:
DMA es la dirección de memoria donde empieza el arreglo a.Este cálculo lo realiza el sistema a ciegas, es decir que no verifica si el valor dado como n sea positivo o negativo o si es más grande que el número de elementos definidos para el arreglo.
DMAn es la dirección de memoria del elemnto n del arreglo a.
sizeof(TA) es el tamaño del tipo de dato del arreglo a.
Ejemplos:
Al ejecutar este programa obtendremos como resultado algo similar a esto:#include <stdio.h> void main (void) { int a=10, b=20, c=30, d[5], e=40, f=50,g=60; printf("Direcciones de memoria de la variables:\n"); printf("A=%X B=%X C=%X D=%X E=%X F=%X G=%X\n\n",&a,&b,&c,d,&e,&f,&g); printf("Valores iniciales de la variables:\n"); printf("A=%d B=%d C=%d E=%d F=%d G=%d\n\n", a,b,c,e,f,g); d[-1]=22; printf("Asaignamos 22 a d[-1]\n"); printf("A=%d B=%d C=%d E=%d F=%d G=%d\n\n", a,b,c,e,f,g); d[-2]=77; printf("Asaignamos 77 a d[-2]\n"); printf("A=%d B=%d C=%d E=%d F=%d G=%d\n\n", a,b,c,e,f,g); d[6]=55; printf("Asaignamos 55 a d[6]\n"); printf("A=%d B=%d C=%d E=%d F=%d G=%d\n\n", a,b,c,e,f,g); d[7]=99; printf("Asaignamos 99 a d[7]\n"); printf("A=%d B=%d C=%d E=%d F=%d G=%d\n\n", a,b,c,e,f,g); }
Observe las direcciones de memoria asignadas a cada variable, en la versión en que fue ejecutado el programa los entero se almacenan en dos bytes , haciendo cálculos muy sencillo se puede dar cuenta del porqué de esos resultados. En compiladores que trabajan con enteros de 4 bytes debrá corregir, en las asignaciones, los índices 6 y 7.Direcciones: A=FFF4 B=FFF2 C=FFF0 D=FFE6 E=FFE4 F=FFE2 G=FFE0 Valores iniciales: A=10 B=20 C=30 E=40 F=50 G=60 Asaignamos 22 a d[-1] A=10 B=20 C=30 E=22 F=50 G=60 Asaignamos 77 a d[-2] A=10 B=20 C=30 E=22 F=77 G=60 Asaignamos 55 a d[6] A=10 B=20 C=55 E=22 F=77 G=60 Asaignamos 99 a d[7] A=10 B=99 C=55 E=22 F=77 G=60
Ejemplos: A continuación se muestran algunos ejemplos que utilizan areglos unidimensionales:
/* Este programa lee una frase y verifia si ésta es palíndrome o no. La coincidencia la hace notar eliminando los caracteres blancos, hacendo coincidir las mayúsculas y minusculas. */ #include <stdio.h> void main (void ) { char frase[50],esarf[50]; int i=0, j, numCar; while ((frase[i++]=getchar()) != EOF); // Luego de la lectura, el índice i queda adelantado // dos posiciones, ver figura. numCar = i-1; // Eliminamos los caracteres blancos y pone en mayúsculas las letras for(i=0,j=0; i<numCar; i++) { if (frase[i] != ' ') frase[j++] = frase[i] - ('a'-'A')*(frase[i]>='a' && frase[i]<='z'); } numCar = j; // Corregimos la nueva cantidad de caracteres // Copiamos los caracteres al revés for(i=0,j=numCar-1; i<numCar; i++,j--) { esarf[j] = frase[i]; } // verificamos si son iguales for(i=0; i<numCar && esarf[i] == frase[i]; i++); if (i==numCar) printf("La frase es palíndrome\n"); else printf("La frase NO es palíndrome\n"); }/* Este programa permite elaborar una distribución de frecuencia de las letra contenidas en un archivo de textos(las mayúsculas y minúsculas se consideran iguales */ #include <stdio.h> #define TAM_ARREGLO 'z'-'a'+1 void main (void) { int c, ContCar[TAM_ARREGLO], i; // Inicializamos el arreglo con ceros for (i=0; i <= TAM_ARREGLO; i++) ContCar [i] = 0; while ((c=getchar( ))!=EOF) if(c >='a' && c <='z' || c >='A' && c <='Z') ++ ContCar[c >= 'a'? c-'a' : c-'A']; printf("Frecuencia de caracteres\n"); for (i=0; i < TAM_ARREGLO; i++) printf("%2c -> %3d\n", i+'A', ContCar[i]); }
/* El siguiente programa prmite leer una serie de valores enteros, llenar un arreglo con los valores, ordenar el arrreglo empleando el método de Quick Sort y finalmente imprimir los datos ordenados. */ #include <stdio.h> void leeArreglo (int [], int &); void quickSort (int [], int, int); void imprime(int [],int); void cambiar (int [], int, int); void main(void) { int dato[50], numDat; leeArreglo (dato, numDat); quickSort (dato, 0, numDat-1); imprime(dato,numDat); } void leeArreglo (int dato[], int &numDat) { int datoAux; numDat=0; while(1) { if (scanf("%d",&datoAux)==EOF)break; dato[numDat]=datoAux; numDat++; } } void quickSort (int dato[], int izq, int der) { int i, ultimo; if (izq >=der) return; cambiar (dato, izq, (izq+der)/2); ultimo=izq; for (i=izq+1; i<=der; i ++) if (dato[i] < dato[izq]) cambiar (dato, ++ultimo, i); cambiar (dato, izq, ultimo); quickSort (dato, izq, ultimo-1); quickSort (dato, ultimo+1, der); } void cambiar (int dato[], int i, int j) { int aux; aux=dato[i]; dato[i] = dato[j]; dato[j]=aux; } void imprime(int dato[], int numDat) { for (int i=0; i<numDat; i++) printf ("%4d", dato[i]); putchar('\n'); }
ARREGLOS MULTIDIMENSIONALES
Un arreglo multidimensional es aquel que se maneja con más de un índice. El lenguaje C/C++ permite la definición de este tipo de arreglos. Un arreglo multidimensional en C/C++ se define de la siguiente manera:
tipo identificador [límite1] [límite2] [límite3] ...
Ejemplo:
int M[20][20];
En el primer caso se definen las variable:
float f [5][10][3];
Se debe tener en cuenta que cada índice del arreglo se manaja por separado, de ahí que cada uno se encierra entre corchetes ([]), NO se puede escribir M [0,1] como se hace en otros lenguajes de programación como el Pascal.
M [0][0], M [0][1], M [0][2], ... M [0][19] M [1][0], M [1][1], M [1][2], ... M [1][19] ... M [19][0], M [19][1], M [19][2], ... M [19][19]
Al definir un arreglo como int a[3][3], los elementos del arreglo distribuirán en la memoria el computador de la siguiente manera:
DMAi,j = DMA + (i x nCol + j) x sizeof(TA)Donde:
DMA es la dirección de memoria donde empieza el arreglo a.Observe que en la fórmula requiere de un valor que corresponde al número de elementos con el que se definió el segundo índice del arreglo. Esto quiere decir que si se define un arreglo como float a[10][20]; el tamaño de la segunda dimensión, en este caso 20, se emplea para poder determinar la posición de memeoria de un elemento del arreglo.
DMAi,j es la dirección de memoria del elemnto [i][j] del arreglo a.
nCol es el número de elementos con el que se definió el segundo índice del arreglo.
sizeof(TA) es el tamaño del tipo de dato del arreglo a.
Así:
int a[3][6] = {{0,1,2,3,4,5}, {0,2,4,6,8,10}, {1,3,5,7,9,11}}; /* es correcto. */
int a[ ][ ] = {{2,2,2}, {1,1,1}}; /* es un ERROR porque no se indica el tamaño de la segunda dimensión del arreglo. */
int a [ ][3]= { {2,2,2}, {1,1,1}}; /* es correcto, a pesar que no se indica el tamaño de la primera dimensión del arreglo. */
int leeArreglo1 (float a[ ][ ]); /* es un ERROR porque en el prototipo de la función no se indica el tamaño de la segunda dimensión del arreglo. */
int leeArreglo2 (float a[ ][5]); /* es correcto, a pesar que en el prototipo de la función no se indica el tamaño de la primera dimensión del arreglo. */
Ejemplo:
/* Este programa lee dos matrices y, si es que las dimensiones de ambas lo permite, las multiplica e imprime el resultado. El programa también calcula, si las condiciones lo permiten, el determinante de la primera matriz */ #include <stdio.h> const int DIMMAX=5; // Máximo número de filas y columnas de una matriz // Prototipos de funciones: void leeMat (float [][DIMMAX], int &, int &); void multMat (float [][DIMMAX], int, int, float [][DIMMAX], int, int, float [][DIMMAX], int &, int &); void imprimeMat (float [][DIMMAX], int, int); float determinante (float [][DIMMAX], int); void reduceMat (float [][DIMMAX], int, int, float [][DIMMAX]); void main (void) { float a[DIMMAX][DIMMAX], b[DIMMAX][DIMMAX], c[DIMMAX][DIMMAX]; int nFilA, nColA, nFilB, nColB, nFilC, nColC; float determ; // Lectura de las matrices y sus dimensiones printf("Matriz A:\n"); leeMat (a, nFilA, nColA); printf("Matriz B:\n"); leeMat (b, nFilB, nColB); // Verifica si se pueden multiplicar if (nColA != nFilB) { printf("Las dimensiones de las matrices no son correctas\n"); return; } // Calcula lal multiplicación de ambas matrices multMat (a, nFilA, nColA, b, nFilB, nColB, c, nFilC, nColC); printf("El producto de A y B =\n"); imprimeMat (c, nFilC, nColC); // Calcula el determinanate de la primera matriz if (nFilA != nColA) { printf("Las dimensiones de esta matriz no permiten\ncalcular el determinante\n"); return; } determ = determinante (a,nFilA); printf("El determinante de esta matriz es: %f\n", determ); } void leeMat (float x[][DIMMAX], int &nFil, int &nCol) { printf("Ingrese el n£mero de filas y columnas de la matriz: "); scanf("%d %d", &nFil, &nCol); for (int fil = 0; fil < nFil; fil++) for (int col = 0; col < nCol; col++) scanf("%f", &x [fil][col]); } void multMat (float a [][DIMMAX], int nFilA, int nColA, float b [][DIMMAX], int nFilB, int nColB, float c[][DIMMAX], int &nFilC, int &nColC) { nFilC = nFilA; nColC = nColB; for (int fil = 0; fil < nFilC; fil++) for (int col = 0; col < nColC; col++) { c[fil][col] = 0; for (int k = 0; k < nColA; k++) c[fil][col] += a[fil][k] * b[k][col]; } } void imprimeMat (float x[][DIMMAX], int nFil, int nCol) { for (int fil = 0; fil < nFil; fil++) { for (int col = 0; col < nCol; col++) printf("%7.2f", x[fil][col]); putchar('\n'); } } float determinante (float x[][DIMMAX], int dim) { float det=0.0, aux[DIMMAX][DIMMAX]; if (dim==1) return x[0][0]; for (int col=0; col < dim; col++) { reduceMat (x, dim, col, aux); det += x[0][col] * (col%2 ? -1 : 1) * determinante (aux,dim-1); } return det; } void reduceMat (float x[][DIMMAX], int dim, int colElim, float aux[][DIMMAX]) { int fil, col; for (fil = 1; fil < dim; fil++) for (col = 0; col < dim; col++) aux[fil-1][col] = x[fil][col]; for (fil = 0; fil < dim-1; fil++) for (col = colElim+1; col < dim; col++) aux[fil][col-1] = aux[fil] [col]; }
![]() |
![]() ![]() |