PRÁCTICA 5: EJERCICIOS RESUELTOS.

Ejercicio 1: Varias formas de utilizar el bucle for.
Ejercicio 2: Máximo elemento de un conjunto de números.
Ejercicio 3: Máximo valor algebraico de un conjunto de números enteros.
Ejercicio 4: Ordenar un conjunto de números enteros.
Ejercicio 5: Programa electoral, que no electoralista.
Ejercicio 6: Producto de matriz por vector.
Ejercicio 7: Producto de matrices.
Ejercicio 8: Un programa para un primo.
Ejercicio 9: Un programa para muchos primos.



Ejercicio 1: Varias formas de utilizar el bucle for.

Previo Siguiente Top

En el siguiente programa se muestran distintas formas de escribir un bucle for para sumar los enteros del 1 al 5. Escribe el siguiente programa y guárdalo con el nombre suma_for.c.

Solución comentada al Ejercicio 1.


/* fichero suma_for.c */
/* Programa para sumar los enteros del 1 al 5 */
#include <stdio.h>
main()
{
   int i=1, suma = 0;
   for ( ; i <= 5 ; )     /* primera forma */
   {
      suma += i;
      ++i;
   }
   printf("suma 1 = %d\n", suma);
   suma = 0;        /* segunda forma */
   for ( i = 1; i <= 5; ++i)
      suma += i;
   printf("suma 2 = %d\n", suma);
   for( i = 1, suma = 0; i <= 5 ; ++i, suma+=i)  /* tercera forma */
      ;
   printf("suma 3 = %d\n", suma);
   for( i = 1, suma = 0; i <= 5 ; suma+=i, ++i)  /* cuarta forma */
      ;
   printf("suma 4 = %d\n", suma);
}


Comentario: Para definir un bucle hace falta un contador o variable de control (que casi siempre es un entero y suele nombrarse con las letras típicas de subíndices: i, j, k, l,...). Esta variable de control es la que se chequea cada vez que comienza el bucle y la que permite continuar o no realizando las operaciones de dentro del bucle.

Por otra parte, en C, el bucle for tiene tres componentes separadas por punto y coma: la primera es una inicialización de la variable de control (u otras que pudieran afectar al bucle), la segunda es la sentencia de chequeo de la variable de control que siempre es necesaria (véase la primera forma); por último, la tercera son sentencias de actualización que se ejecutan al final del bucle (que también se podrían poner entre las llaves del bucle, detrás de las demás sentencias). Conociendo estas características, la forma más habitual de expresar un bucle es la segunda, ya que el bucle for contiene las instrucciones pertinentes a la variable de control.

La forma primera es más asimilable a un bucle while, ya que la instrucción for contiene sólo el chequeo de la variable.

La diferencia entre las formas tercera y cuarta es el orden en que se ejecutan las instrucciones: la forma tercera ejecuta antes el incremento de la variable que el chequeo y la suma, por tanto cuando i vale 6 ya se ha sumado a la variable suma y, por eso el resultado sale 20 en lugar de 15.



Ejercicio 2: Máximo elemento de un conjunto de números.

Previo Siguiente Top

Este programa calcula el máximo entre un conjunto de números enteros. Para ello se sigue el siguiente algoritmo: se crea una variable llamada max, a la que se da inicialmente el valor de conjunto[0]. Luego se recorren paso a paso todas las posiciones del vector, comparando el valor almacenado en la posición considerada del vector con el valor de la variable max. Si el valor de la posición considerada del vector es mayor que max entonces se copia (se sustituye el valor) en la variable max este valor. De esta forma, una vez recorrido todo el vector, la variable max contendrá el máximo valor. Guárdalo con el nombre maximo.c.

Solución comentada al Ejercicio 2.


/* fichero maximo.c */
/* Programa para calcular el m ximo de un conjunto de n£meros */
#include <stdio.h>
#define SIZE 5
void main(void)
{
    int i, max, imax;
    int conjunto[SIZE];
    printf("Introduzca %d valores:\n", SIZE);
    for (i=0; i<SIZE; i++) {
        printf("%d: ", i+1);
        scanf("%d", &conjunto[i] );
        printf("\n");
    }
    max = conjunto[0];
    imax = 0;
    for (i=0; i<SIZE ; i++) {
        if (conjunto[i] > max) {
            max = conjunto[i];
            imax = i;
        }
    }
    printf("\nEl máximo valor del conjunto es: %d.\n", max);
    printf("\ny está en la posición %d.\n", imax+1);
}


Comentario: Este programa es muy sencillo, si se entiende el algoritmo. La variable max acabará siendo igual al elemento mayor del conjunto, e imax indicará la posición del máximo.



Ejercicio 3: Máximo valor algebraico de un conjunto de números enteros.

Previo Siguiente Top

Modifica el programa anterior, maximo.c, de forma que calcule el mínimo valor del conjunto y guárdalo con el nombre minimo.c.

Solución comentada del Ejercicio 3.


/*fichero minimo.c */
#include <stdio.h>
#define SIZE 5
void main(void)
{
    int i;
    int min, imin;
    int conjunto[SIZE];
    printf("Introduzca %d valores:\n", SIZE);
    for (i=0; i<SIZE; i++) {
        printf("%d: ", i+1);
        scanf("%d", &conjunto[i] );
        printf("\n");
    }
    min = conjunto[0];
    imin = 0;
    for (i=0; i<SIZE; i++) {
        if (conjunto[i] < min) {
            min = conjunto[i];
            imin = i;
        }
    }
    printf("\nEl mínimo valor del conjunto es: %d.\n", min);
    printf("\ny está en la posición %d.\n", imin+1);
}


Comentario: Este programa es prácticamente idéntico al anterior. En lugar de las variables max e imax se emplean las varibles min e imin que almacena el valor mínimo y su posición respectivamente. Una vez hechos estos cambios de nombre de variables, la única línea del programa que varía es la correspondiente a la condición del if, que como se está buscando el valor mínimo, habrá de ser:

if (conjunto[i] < min)

Es decir, chequear si el elemento considerado es menor que el valor mínimo encontrado hasta ese momento.



Ejercicio 4: Ordenar un conjunto de números enteros.

Previo Siguiente Top

El siguiente programa, al que llamarás ordena.c, ordena un conjunto de números enteros almacenados en un vector, de la siguiente manera: se van recorriendo una a una todas las posiciones del vector, desde la primera hasta la penúltima. Estando en cada una de estas posiciones, se recorren, a su vez, todas las posiciones siguientes y se compara su valor con el de la posición actual. Si se encuentra un valor menor se intercambia con el de esta posición.

Para implementar este algoritmo son necesarios dos bucles: el primero, bucle i, recorre el vector desde la posición i=0 hasta i=SIZE-1. El segundo bucle, bucle j, recorre el vector desde la posición j=i+1 hasta el final. Para que quede más claro, vamos a ver con un ejemplo como funciona este algoritmo. Supongamos que queremos ordenar los siguientes cinco números: 7,3,5,1,4. Estos números se almacenarán en un vector de la siguiente manera:

vector0 vector1 vector2 vector3 vector4
7 3 5 1 4 

Vamos a recorrer las posiciones del vector desde i=0 hasta i=3.

i = 0 {7 3 5 1 4} 

Recorremos el vector desde j=1 hasta j=4 y comparamos vector0=7 con vectorj. Si vectorj < vector0 intercambiamos los valores de posición. Vamos a ver cómo quedaría el vector inicial una vez que termina cada bucle j.

j = 1 {3 7 5 1 4} Se intercambia 3 con 7
j = 2 {3 7 5 1 4} No se intercambia 3 con 5
j = 3 {1 7 5 3 4} Se intercambia 1 con 3
j = 4 {1 7 5 3 4} No se intercambia 1 con 4
i = 1 {1 7 5 3 4}

Recorremos el vector desde j=2 hasta j=4 y comparamos vector1=7 con vectorj.

j = 2 {1 5 7 3 4} Se intercambia 5 con 7
j = 3 {1 3 7 5 4} Se intercambia 3 con 5
j = 4 {1 3 7 5 4} No se intercambia 3 con 4
i = 2 {1 3 7 5 4} 
j = 3 {1 3 5 7 4} Se intercambia 5 con 7
j = 4 {1 3 4 7 5} Se intercambia 4 con 5
i = 3 {1 3 4 7 5}
j = 4 {1 3 4 5 7} Se intercambia 5 con 7 ¡Números ordenados!

Ya se ve que no es necesario que el bucle i llegue hasta 4.

Solución comentada al Ejercicio 4.


/* fichero ordena.c*/
/* Programa para ordenar un conjunto de números enteros*/
#include <stdio.h>
#define   SIZE   7
void main(void)
{
    int vector[SIZE];
    int j, i;
    int temp;
    printf("Introduzca los %d valores para ordenar:\n", SIZE);
    for(i=0; i<SIZE; i++) {
        printf("%d: ", i+1);
        scanf("%d", &vector[i]);
        printf("\n");
    }
    for(i=0; i<(SIZE-1); i++) {
        for (j=i+1; j<SIZE; j++) {
            if(vector[j]<vector[i]) {
                temp=vector[j];
                vector[j]=vector[i];
                vector[i]=temp;
            }
        }
    }
    printf("El vector ordenado es:\n");
    for(i=0; i<SIZE ; i++) {
        printf("%d  ", vector[i]);
    }
    printf("\n");
}


Comentario: Para intercambiar entre sí los valores de dos variables no se pueden emplear las dos instrucciones siguientes:

vector[j]=vector[i]; /* esta instrucción pone en la posición j el valor de la posición i, perdiéndose el valor de la posición j */

vector[i]=vector[j]; /* esta instrucción pone en la posición i el valor de la posición j, pero no el original, que se ha perdido, sino el nuevo */

Por eso es necesaria una variable intermedia, que en este caso hemos llamado temp, que guarde el valor de la posición j, por lo que se requieren tres instrucciones.



Ejercicio 5: Programa electoral, que no electoralista.

Previo Siguiente Top

Aprovechando las muy recientes elecciones al Parlamento Vasco, vamos a ver cómo se convierten en escaños los votos de los sufridos ciudadanos siguiendo el método d'Hont. ¿Estás familiarizado con este método? Por si acaso te los vamos a explicar.

Supongamos que concurren 3 partidos a las elecciones y que la provincia o distrito electoral dispone de 2 escaños. El primer escaño se lo llevará el partido más votado. Para el segundo escaño se dividen los votos de cada partido entre el número de escaños obtenidos más uno (el partido que no tenga todavía ningún escaño se dividirá entre 1). El escaño se asigna al partido que tras esta operación tenga más votos. Vamos a verlo con un ejemplo:

Partido 1: 6000 votos Se lleva el 1º escaño 6000/(1+1)=3000

Partido 2: 4000 votos 4000/(1+0)=4000 Se lleva el 2º escaño.

Partido 3: 2000 votos 2000/(1+0)=2000

El programa que te presentamos a continuación es para 3 partidos y 2 escaños, pero queda a tu entera disposión para que lo particularices -si dispones de datos- para el caso de las recientes elecciones. Ten mucho cuidado porque un fallo en la programación de este tipo de asuntos puede hacer caer sobre ti una acusación de fraude electoral. Llamaremos al programa escaño.c.

Lo primero que hace este programa es inicializar a cero el vector n_esca . En este vector se va a almacenar el número de escaños de cada partido: n_esca0 contendrá el número de escaños del partido número 1, n_esca1 los escaños del partido número 2, etc. Este vector se va a ir modificando a lo largo de la ejecución del programa.

A continuación se almacenan en el vector n_votos los números de votos obtenidos por cada partido, estos datos serán introducidos por el usuario a través del teclado.

La novedad de este programa es que incluye una función: next_esc(long *,int *). Esta función tiene como argumento dos punteros a sendos vectores, es decir, las direcciones de memoria o los nombres de dos vectores. Cuando se llama a la función, next_esc(n_votos, n_esc) se pasa la dirección de memoria de los vectores n_esca y n_votos . El nombre de un vector (como por ejemplo n_esca) es un puntero a la posición del primer elemento. La función devuelve el número del partido que ha conseguido el escaño y se almacena en la variable esca. Este número será cero si el escaño corresponde al primer partido, 1 si corresponde al segundo, etc.

Con esta pequeña explicación ya estás en condiciones de escribir el programa y comprobar cómo funciona.

Solución comentada al Ejercicio 5.


/* fichero escaño.c*/
/* Calculo de escaños por partido (d'Hondt). */
#include <stdio.h>
#define    N_ESC    2           /* número de escaños en liza. */
#define    N_PAR    3           /* número de partidos que concurren */
void main(void)
{
    int  i, esca;
    int  n_esc[N_PAR];     /* n_esc{[N_PAR]= nº de escaños por partido*/
    long n_votos[N_PAR];   /* n_votos[N_PAR]=nº de votos por partido*/
    int  next_esc(long *, int *);   /* definición de función */
    
    for(i=0; i<N_PAR; ++i)
        n_esc[i]=0;
    printf("Teclea el nº de votos de cada partido.\n");
    for (i=0; i<N_PAR; ++i) {
        printf("\nPartido %d: ", i+1);
        scanf("%ld", &n_votos[i]);
    }
    
    for(i=0; i<N_ESC; ++i) {           /* asignación de escaños */
        esca = next_esc(n_votos, n_esc);
        n_esc[esca] = n_esc[esca]+1;
    }
    for (i=0; i<N_PAR; ++i) 
        printf("\nEl partido %d ha obtenido %d escaños.", 
            i+1, n_esc[i]);
}
int next_esc( long n_votos[], int n_esc[]) 
{
    int  imaximo=0, i;
    long maximo=0;
    for( i=0; i<N_PAR; ++i) {
        if( maximo<(n_votos[i]/(n_esc[i]+1)) ) {
            maximo=n_votos[i]/(n_esc[i]+1);
            imaximo=i;
        }
    }
    return imaximo;
}



Ejercicio 6: Producto de matriz por vector.

Previo Siguiente Top

A estas alturas de la práctica seguro que ya les has cogido el truco a los bucles for, es más, ¡te han empezado a gustar! ¿te estará pasando algo?. No te preocupes, tienes los primeros síntomas de adicción a la programación en C, y si sigues así, terminarás por ser un experto programador, enfermedad que, para tu tranquilidad, no tiene ningún tipo de efectos secundarios.

Para que no dejes sin explotar todas las posibilidades de los bules for, te proponemos este sencillo programa que multiplica una matriz por un vector (en este orden). Escribe el programa y guárdalo como vmatriz.c.

Solución comentada al Ejercicio 6.


/* fichero vmatriz.c*/
/* Producto de matriz por vector */
#include <stdio.h>
#define  SIZE   3
void main(void)
{
    double matriz[SIZE][SIZE];
    double vector[SIZE];
    double solucion[SIZE];
    double sum;
    int    i,j;
    
    printf("Introduzca los datos de la matriz:\n");
    for(i=0; i<SIZE ; i++) {
        for(j=0; j<SIZE; j++) {
            printf("\nElemento (%d,%d): ", (i+1), (j+1));
            scanf(" %lf", &matriz[i][j]);
        }
    }
    printf("\n\nIntroduzca los datos del vector:\n");
    for(i=0; i<SIZE ; i++) {
        printf("\nElemento %d: ", (i+1));
        scanf("%lf", &vector[i]);
    }
    for(i=0; i<SIZE; i++) {
        sum=0;
        for(j=0; j<SIZE; j++) {
            sum += matriz[i][j]*vector[j];
        }
        solucion[i] = sum;
    }
    printf("\nEl vector solucion es:\n");
    for(i=0; i<SIZE; i++) {
        printf("Elemento %d = %lf\n", i+1, solucion[i]);
    }
}


Comentario: Se presentan en este programa algunos pasos típicos de manejo de matrices que son muy similares en todos aquellos programas que las manejan.

En cuanto al algoritmo, es ya conocida la forma de multiplicar una matriz por un vector columna: cada elemento del vector producto es el producto escalar (la suma de los productos elemento a elemento) de la fila correspondiente de la matriz por el vector columna. Para ello hacen falta dos bucles: uno recorre las filas de la matriz y el otro realiza el sumatorio propio del producto escalar. Obsérvese que para realizar el sumatorio, se inicializa cada vez la variable sum a cero.



Ejercicio 7: Producto de matrices.

Previo Siguiente Top

Basándote en el producto de matriz por vector anterior, haz un programa que multiplique dos matrices cuadradas y llámalo bimatriz.c.

Solución comentada del Ejercicio 7.


/* fichero bimatriz.c */
#include <stdio.h>
#define SIZE 5
void main(void)
{
    double matriz1[SIZE][SIZE], matriz2[SIZE][SIZE];
    double solucion[SIZE][SIZE], sum;
    int dimension, i, j, k;
    printf("Introduzca la dimensión de las matrices:\n");
    printf("Dimensión: ");
    scanf("%d", &dimension);
    printf("Introduzca los elementos de la primera matriz:\n");
    for (i=0; i<dimension; i++) {
        for (j=0; j<dimension; j++) {
            printf("a(%d,%d): ", i+1, j+1);
            scanf("%lf", &matriz1[i][j] );
        }
    }
    printf("\n");
    printf("Introduzca los elementos de la segunda matriz:\n");
    for (i=0; i<dimension; i++) {
        for (j=0; j<dimension; j++) {
            printf("b(%d,%d): ", i+1, j+1);
            scanf("%lf", &matriz2[i][j] );
        }
    }
    printf("\n");
    for (i=0; i<dimension; i++) {
        for (j=0; j<dimension ; j++) {
            sum = 0.0;
            for (k=0; k<dimension; k++)
                sum += matriz1[i][k] * matriz2[k][j];
            solucion[i][j] = sum;
        }
    }
    printf("Solución:\n\n\n");
    for (i=0; i<dimension; i++) {
        for (j=0; j<dimension; j++)
            printf("%5.2lf      ", solucion[i][j]);
        printf("\n");
    }
}


Comentario: Tal vez el aspecto más interesante de este programa es la necesidad de utilizar 3 bulces for para la multiplicación de dos matrices. Para verlo más claramente, sea aij un elemento de la primera matriz, bij un elemento de la tercera y cij un elemento de la matriz solución. Pensemos por un momento cómo se obtiene un elemento cualquiera de la matriz solución. El elemento c23, por ejemplo, se obtiene multiplicando los elementos de la fila 2 de la primera matriz por los elementos de la columna 3 de la segunda matriz. Suponiendo que las matrices son de dimensión 3 tendremos:

c23 = a21*b13+a22*b23+a23*b33 y en general:

cij = ai1*b1j+ai2*b2j+ai3*b3j

Por lo tanto, para poder acceder a los elementos de la fila i de la primera matriz y a los elementos de la columna j de la segunda matriz, y para realizar el sumatorio son necesarios tres bucles, para los que se han utilizado las variables i, j y k.



Ejercicio 8: Un programa para un primo.

Previo Siguiente Top

El siguiente programa comprueba si un número es primo o no. Recuerda que un número primo es aquél que puede dividirse únicamente por sí mismo y por la unidad. Una manera de decidir si un número es primo, es dividirlo por todos los números comprendidos entre el 1 y él mismo. Si se encuentra que el número es divisible por alguno de ellos, se deduce que ese número no es primo. Vamos a utilizar el operador módulo o resto de la división entera (%) para comprobar si la división es exacta. Este operador da como resultado el resto de la división del primer operando por el segundo. Por ejemplo, 5%2 es 1, puesto que el resto de dividir 5 entre 2 es 1.

Guarda el programa con el nombre primos.c.

Solución comentada al Ejercicio 8.


/* fichero primos.c */
/* programa para determinar si un n£mero es primo */
#include <stdio.h>
void main(void)
{
    int numero, divisor;
    printf("¿Qué número quieres saber si es primo?\n");
    scanf("%d", &numero);
    while(numero < 2) {
        printf("Lo siento, no acepto números menores que 2.\n");
        printf("Inténtalo de nuevo\n");
        scanf("%d", &numero);
    }
    for (divisor=2; numero%divisor!=0; divisor++)
        ;
    if (divisor == numero)
        printf("%d es primo.\n", numero);
    else
        printf("%d no es primo.\n", numero);
}


Comentario: El comentario más apropiado para este ejercicio es el algoritmo para calcular el primo con el ciclo for (divisor=2; numero%divisor!=0; divisor++);. Obsérvese, que este ciclo acaba con un punto y coma (es mejor ponerlo en la línea siguiente, para dejar claro que es una sentencia vacía), es decir, que no ejecuta ninguna sentencia dentro del bucle, por lo tanto, lo que se pretende con el bucle es obtener un valor de la variable divisor que cumpla una condición. Esta condición es que el número que hemos introducido en la variable numero (por el teclado) divido por el número que buscamos sea cero, es decir, que los dos números sean divisibles entre ellos.

Después de este ciclo tenemos una condición (un if), que compara el número que hemos obtenido en el ciclo (divisor) con el número que se ha introducido (numero). Si son iguales, el número es primo (ya que un número primo es aquel que sólo es divisible por 1 y por si mismo), si no son iguales, el número no es primo, ya que se ha encontrado en el bucle un divisor distinto de él mismo.



Ejercicio 9: Un programa para muchos primos.

Previo Siguiente Top

Basándote en el ejercicio anterior, realiza un programa que imprima todos los números primos comprendidos entre el 2 y un valor límite que se preguntará al ejecutar el programa. Guárdalo con el nombre primos1.c.

Solución comentada del Ejercicio 9.


/* fichero primos2.c */
#include <stdio.h>
void main(void)
{
    int numero, divisor;
    int n;
    printf("¨Hasta qué número desea conocer los primos?\n");
    printf("introduzca el valor: ");
    scanf("%d", &n);
    for (numero=2; numero<n; numero++) {
        for (divisor=2; numero%divisor!=0; divisor++);
        if (divisor == numero)
            printf("%d\n", numero);
    }
}


Comentario:çPara poder escribir todos los números primos hasta un límite, basta introducir un nuevo bucle for al programa anterior que vaya recorriendo todos los números enteros desde el 2 hasta dicho límite. En cada ejecución del bucle se comprueba si el número considerado es primo aprovechando las sentencias del programa anterior.