Escribe un programa que lea dos números enteros y escriba todos los números mayores que el primero y menores que el segundo
Ingresa el primer número: 38
Ingresa el segundo: 45
Los números son: 39 40 41 42 43 44
Muchas gracias por usar este programa
Un intento (incorrecto) de solución es:
int a,b;
printf ("Ingresa el primer número :");
scanf (%d,&a);
printf ("Ingresa el segundo:");
scanf (%d,&b);
print ("Los numeros son");
if (a+1<b) printf (%d\n,a+1);
if (a+2<b) printf (%d\n,a+2);
if (a+3<b) printf (%d\n,a+3);
if (a+4<b) printf (%d\n,a+4);
if (a+5<b) printf (%d\n,a+5);
if (a+6<b) printf (%d\n,a+6);
if (a+7<b) printf (%d\n,a+5);
if (a+8<b) printf (%d\n,a+6);
... etcétera
Hasta ahora todos los programas que hemos visto se caracterizan por el hecho de que las instrucciones se van ejecutando en orden y una sola vez. Esto impide realizar un programa como el queremos hacer.
Sin embargo, C, al igual que muchos otros lenguajes, permite repetir una cierta cantidad de instrucciones mientras una condición se cumpla.
Esta instrucción de control de flujo se llama while, se esquematiza en la figura 1 y su sintaxis es:
while (condicion) {
instrucciones;
}
while evalúa la condición entre paréntesis y si esta es verdadera, ejecuta todas las instrucciones entre los paréntesis { }. Cuando ha ejecutado la última instrucción, vuelve a evaluar la condición. El proceso se repite hasta que al terminar de ejecutar las instrucciones se evalúa la condición y esta es falsa.
Figura 1
En caso que sólo se repita una sola instrucción, se pueden eliminar los paréntesis
while (condicion)
instrucción;
Un primer ejemplo de while se ve en el siguiente programa:
int a,b,i;
printf ("Ingresa el primer número: ");
scanf(%d,&a);
printf ("Ingresa el segundo:");
scanf(%d,&b);
printf ("Los numeros son");
i=a+1;
while (i<b) {
printf (%d ",i);
i=i+1;
}
printf ("\nMuchas gracias por usar este programa\n");
Línea(s) |
Ejecución |
16-20 |
Se escriben los mensajes en la pantalla y se leen las respuestas del usuario desde el teclado Ingresa el primer número: 38 Ingresa el segundo: 45 Los números son : |
21 |
La variable auxiliar i se va a usar para escribir los valores a<i<b. Se inicializa con a+1, en este caso, 39. |
22
|
Si i es menor que b, entonces las instrucciones en las líneas 24 a 25 se ejecutan una vez. Si no es así se sigue la ejecución con la línea 27 |
24
|
Se escribe el valor de i Ingresa el primer número: 38 Ingresa el segundo: 45 Los números son : 39 |
25
|
El valor de i se incrementa en 1 i __40__ |
22
|
Cuando se llega al final de las instrucciones, el programa se devuelve a la instrucción while y la condición se reevalúa. En este caso se compara i (40) con b (45). Como i es menor que b la condición es verdadera y nuevamente se ejecutan las líneas 22 a 23 |
24-25
|
Se escribe el valor de i y luego se incrementa Ingresa el primer número: 38 Ingresa el segundo: 45 Los números son : 39 40 i __41__ |
22
|
Como nuevamente se llego al final de las instrucciones dentro del while, se reevalua la condición del while, que es verdadera y se vuelve a iterar. |
... |
... |
24-25 |
El programa ha seguido iterando, y se ha entrado a las instrucciones con un valor de i de 44. Se escribe el valor de i y se incrementa Ingresa el primer número: 38 Ingresa el segundo: 45 Los números son : 39 40 41 42 43 44 i __45__ |
22
|
Se vuelve a evaluar la condición del while, en este caso es falsa. C salta inmediatamente a la línea que sigue a las instrucciones del while, es decir, la línea 26 |
26
|
Se escribe el mensaje de agradecimiento y finaliza el programa Ingresa el primer número: 38 Ingresa el segundo: 45 Los números son : 39 40 41 42 43 44 Muchas gracias por usar estre programa |
A veces existen muchas formas de llevar a cabo una tarea. En el caso del programa que acabamos de analizar se puede usar un contador en el ciclo while.
Un contador es una variable auxiliar que se usa junto a un while para repetir un trozo de código una cierta cantidad de veces. En nuestro ejemplo, sabemos que la cantidad de números entre a y b son b-a-1. Por ejemplo, si a vale 5 y b 8, hay que escribir 8-5-1=2 números, que son 6 y 7.
Una nueva versión del programa es:
printf ("Ingresa el primer número: ");
...
printf ("Los numeros son");
i=b-a-1;
while (i>0) {
print (%d ,b-i);
i=i-1;
}
Otra versión, igualmente correcta es:
printf ("Ingresa el primer número: ");
...
printf ("Los numeros son");
i=b-a-1;
while (i>0) {
i=i-1;
printf (%d,b-(i+1));
}
|
El ámbito de una variable es la parte del programa donde la variable es conocida y puede ser usada. Como ya vimos, una variable puede ser usada sólo después que se ha definido. En C, el ámbito de la variable termina cuando se encuentra el paréntesis } que cierra al paréntesis { que precedía la declaración de la variable.
Cualquier referencia a una variable tiene que ser hecha dentro del ámbito de la variable, si no, C no compila el programa.
La siguiente tabla muestra el ámbito de las variables del código de ejemplo:
a |
b |
c |
Código |
int a; |
|||
scanf(%d,&a); |
|||
while (a<5) { |
|||
int b=a*2,c; |
|||
Printf (%d,b); |
|||
c=a-b-2; |
|||
Printf (%d,c); |
|||
} |
Por ejemplo, sería erróneo usar la variable b ó c fuera del while, ya que al ser declaradas dentro de él, su ámbito termina al cerrarse el bloque de instrucciones.
Las variables que son declaradas dentro de un while pierden su valor al fin de cada iteración, y se declaran nuevamente en la siguiente iteración (como si fueran "variables nuevas"). |
Indentar es ordenar un programa agregando espacios al lado izquierdo de las instrucciones. Dos formas de indentar un while son las siguientes:
Parentesis de comienzo de bloque en la misma línea de la cláusula while
while (condición) {
instrucción;
instrucción;
instrucción;
}
Paréntesis de comienzo de bloque en una nueva línea
while (condición)
{
instrucción;
instrucción;
instrucción;
}
En ambos casos se deja un espacio antes del comienzo de cada instrucción dentro del bloque para clarificar el programa. Nunca olvides indentar. Si bien no es obligación hacerlo te puede simplificar bastante entender lo que hace el programa.
Es perfectamente posible colocar un while dentro de otro while (while anidado). Como ejemplo, considera el siguiente programa, que escribe la tabla de multiplicar del 1 al 10:
|
La instrucción break interrumpe la ejecución del while que la contiene. Es útil en algunos contextos donde una condición hace que no sea deseable seguir con la iteración.
El siguiente pseudo-código muestra un contexto donde break es útil:
while (jugador1 ni jugador2 ha ganado) {
jugador1 mueve pieza
if jugador1_ganó {
escribe_mensaje (ganó jugador 1)
break;
}
jugador2 mueve pieza
if jugador2_ganó
escribe_mensaje (ganó jugador 2)
}
Un error muy común es creer que un while puede terminar (salir de) en la mitad del bloque de instrucciones, bastando que una instrucción haga que la condición del while sea falsa, olvidando que lo que realmente ocurre es que C evalúa la condición del while antes de entrar por primera vez al bloque y antes de reentrar en cada iteración. |
Considera el siguiente programa:
int i=3;
while (i>1) {
i=i-1;
printf (%d,i);
}
printf ("fin");
La traza (orden en que se ejecutan las instrucciones) de este programa es
(1)® (2) ® (3) ® (4) ® (2) ® (3) ® (4) ® (2) ® (6) |
y no |
(1) ® (2) ® (3) ® (4) ® (2) ® (3) ® (6) |
como podría pensar alguien que crea que el while termina abruptamente en la línea 44 cuando el valor de i se hace 1 (y por lo tanto la condición del while falsa)
Otro error es olvidar cual es el ámbito de una variable declarada dentro de un while. El siguiente programa, que calcula n!, tiene dos errores:
int i,n;
printf ("ingresa n:");
scanf(%d,&n);
i=1;
while (i<=n) {
int factorial=factorial*i;
i=i+1;
}
printf ("Factorial %d\n",factorial);
En la línea 6 se está tratando de asignar a la variable factorial su producto con i (lo que es indefinido, ya que factorial, al estar recién declarada no tiene valor)
En la última línea, se hace referencia a la variable factorial, cuyo ámbito va de la línea 6 a 7.
La solución correcta, que solo modifica ligeramente el programa, es:
int i,n,factorial=1;
printf ("ingresa n:");
scanf(%d,&n);
i=1;
while (i<=n) {
factorial=factorial*i;
i=i+1;
}
printf ("Factorial %d\n",factorial);
Problema 1: Factores de un número Escribe un programa que pida ingresar un número mayor que 1 y entregue todos los factores de ese número. Si el número ingresado no es mayor que 1, el programa debe terminar. Recuerda que cualquier número tiene al menos como factor al 1. |
Solución:
int n, factor;
/* Preguntamos por el numero */
printf("CALCULO DE FACTORES");
printf("Ingrese un numero mayor que 1 ? ");
scanf(%d,&n);
/* Verificamos que este en el rango */
if(n>1)
{
printf ("Los factores son: ");
factor=1;
/* Hacemos un ciclo probando todos los posibles factores */
while(factor<=n){
if (n%factor==0)
printf(%d ",factor);
factor++;
}
/* Indicamos que termina la lista */
printf(".\n");
}
else
printf("El numero debe ser mayor que 1\n");
Problema 2: Digito verificador del carné de identidad
El sistema de identificación que se usa en Chile sa basa en un código (llamado numero del carné de identidad) que corresponde a un número entero (que se le asigna a cada habitante) y un dígito verificador (que se calcula usando el numero anterior) para saber si algunos de los dígitos del carnet han sido modificados. Así, para saber si la cédula 12.575.538-1 está correcta, debemos calcular el dígito verificador para 12575538 y compararlo con 1. Si son iguales, el número está bien, si no, fue adulterado.
Para calcular el dígito verificador se utiliza el siguiente algoritmo:
Se multiplican los digitos del número entero, partiendo del último, respectivamente con 2,3,4,5,6,7,2 y 3
Luego se suman todos estos resultados parciales, y que se llamará SUMA.
Se calcula el digito verificador como: D = 11 - ( SUMA modulo 11 )
Si D=11 entonces el digito verificador es "0" (cero).
Si D=10, entonces el digito verificador es "K".
En cualquier otro caso el digito verificador es D.
Solución
int carnet,resultado;
/* Preguntamos por el numero */
printf("Ingrese un numero de carnet (mayor que 1) ? ");
scanf(%d,&carnet);
/* Verificamos que este en el rango */
if(carnet>1)
{
int factor=2,suma=0,digito=0;
/* Hacemos un ciclo que termina cuando carnet sea 0
Para rescatar los digitos rescatamos el ultimo y
lue go lo quitamos. */
while (carnet>0)
{
/* Rescatamos es ultimo digito */
digito=carnet%10;
/* Quitamos el ultimo digito del numero */
carnet=carnet/10;
suma=suma + digito*factor;
factor++;
if(factor>=8)
factor=2;
}
resultado=11-(suma%11);
if(resultado==11)
resultado=0;
/* Mostramos el resultado */
if (resultado==10)
printf("El digito verificador es: K");
else
printf("El digito verificador es: %d", resultado);
}
else
printf("El numero debe ser mayor que 1");
Problema 3: Sapo de Micro
Un sapo de micro calcula cuánto tiempo ha transcurrido entre el paso de dos micros del mismo recorrido. Un Sapo posmoderno usará un Notebook para ayudarse en el cálculo.
Escribe un programa en C que sostenga el siguiente diálogo :
A qué hora pasó la primera micro (minutos)? 65
A qué hora pasó la micro 2? 73
La diferencia entre la 1 y la 2 es de 8 minutos
A qué hora pasó la micro 3? 78
La diferencia entre la 2 y la 3 es de 5 minutos
A qué hora pasó la micro 4? -1
Muchas gracias por usar este programa
Es decir, que pregunte la hora en minutos. Supón que el programa se usa en un mismo día siempre.
b) Escribe el mismo programa, pero la hora se ingresa ahora de la siguiente forma:
A qué hora pasó la primera micro (minutos)? 1 5
A qué hora pasó la micro 2? 1 13
La diferencia entre la 1 y la 2 es de 8 minutos
A qué hora pasó la micro 3? 2 18
La diferencia entre la 2 y la 3 es de 1 hora 5 minutos
A qué hora pasó la micro 4? -1
Muchas gracias por usar este programa
Es decir, la hora se muestra en horas y minutos
Solución a)
int antes,actual,i;
printf ("A qué hora pasó la primera micro (minutos)?");
scanf(%d,&antes);
i=2;
while (antes!=-1) {
printf ("A que hora paso la micro %d?",i);
scanf(%d,&actual);
if (actual!=-1) {
printf ("La diferencia entre la %d y la %d",i-1,i);
printf (" es de %d minutos \n",actual-antes);
}
antes=actual;
i=i+1;
}
printf ("Muchas gracias por usar este programa\n");
Solución b)
int hora,minutos,antes,actual,i,difh,difm;
printf ("A qué hora pasó la primera micro (minutos)?");
scanf(%d %d,&hora,&minutos);
hora*60+minutos;
i=2;
while (antes!=-1) {
int hora;
printf ("A que hora paso la micro %d?",i);
scanf(%d %d,&hora,&minutos);
actual=hora*60+minutos;
if (actual!=-1){
difh=(actual-antes)/60;
difm=(actual-antes)%60;
printf ("La diferencia entre la %d y la %d es de ",i-1,i);
if (difh>0)
printf (%d horas y ",difh);
printf ("%d minutos",difm);
antes=actual;
i=i+1;
}
}
printf ("Muchas gracias por usar este programa\n");
Cuántas notas son? 4
Nota 1: 7.0
Nota 2: 6.0
Nota 3: 5.5
Nota 4: 4.0
Promedio: 5.5
Versión 1
Ingresa las notas (0=fin)
Nota 1: 7.0
Nota 2: 6.0
Nota 3: 5.0
Nota 5: 0
Promedio: 6.0
Versión 2
Un diagrama de flujo es una representación gráfica del orden en que se van ejecutando las instrucciones de un programa, cómo ya hemos visto de forma superficial en este capítulo y el anterior. Hasta ahora hemos visto tres tipos de ejecución: secuencial, cíclica y condicional, cada uno de los cuales tiene un diagrama asociado:
Secuencial |
Condicional |
Cíclica |
inst1; inst2; inst3; |
if (cond) inst1; else inst2; |
while (cond) inst; |
|
|
|
Para programas más complejos, basta con combinar los distintos diagramas.
Ejemplo de un diagrama de flujo
El siguiente código escribe si un número guardado en la variable x es positivo, negativo o igual a cero. A su derecha se ve su diagrama de flujo, que es una composición de dos diagramas de secuencias condicionales.
if (x>0) printf("positivo); else { if (x<0) printf("negativo"); else printf("cero"); } |
|
Los diagramas pueden ayudar a descubrir por qué un código no funciona. Por ejemplo, en el siguiente programa, que intenta hacer lo mismo que el anterior, el diagrama pone de manifiesto cual es el error cometido:
if (x>0) printf("positivo); if (x<0) printf("negativo"); else printf("cero"); |
|
En el caso en que el número sea negativo, la primera condición es falsa y se evalúa la segunda. Como esta es verdadera, se escribe "negativo" en la pantalla.
Si el número es cero, la primera condición es falsa, se evalúa la segunda, que también es falsa y se escribe "cero"
Si el número es positivo, se escribe "positivo". Sin embargo, el error se produce al pasar a evaluar la segunda condición, que es falsa, por lo que se escribe "cero". Es decir, si el número es mayor que cero, se escribe "positivo" y "cero" en la pantalla.
La ejecución paso a paso consiste en escribir el orden en que las instrucciones se van ejecutando al correr el programa. Para ello se le asigna un número a cada línea del programa. Al lado de cada línea se escribe:
Si la instrucción es ... |
Se debe escribir |
asignación |
el nuevo valor de la variable |
while o if |
el valor de verdad de la condición |
|
qué se escribe en la pantalla |
El siguiente programa lee números enteros desde el teclado y escribe cuánto vale su suma acumulada. El programa itera hasta que se ingresa un cero.
int suma= 0, num;
printf("? ");
scanf(%d,&num);
while (num!=0) {
suma= suma+num;
printf("Total= %d\n",suma);
printf("? ");
scanf(%d,&num);
}
printf("Fin!\n");
La siguiente pantalla muestra un ejemplo:
? 3
Total= 3
? 4
Total= 7
? 1
Total= 8
? 0
¿Cómo es su ejecución paso a paso?
(1) suma=0
(2) escribe "?"
(3) num=3
(4) Verdadero
(5) suma=3
(6) escribe "Total="
(6) escribe "3"
(7) escribe "?"
(8) num=4
(4) Verdadero
(5) suma=7
(6) escribe "Total="
(6) escribe "7"
(7) escribe "?"
(8) num=1
(4) Verdadero
(5) suma=8
(6) escribe "Total="
(6) escribe "8"
(7) escribe "?"
(8) num=0
(4) Falso
(10) escribe "Fin"
int x= 15;
int y= 24;
while (x!=y) {
if (x>y)
x= x-y;
else
y= y-x;
}
printf(%d,x);
Solución:
|
(1) x=15 (2) y=24 (3) Verdadero (4) Falso (7) y=9 (3) Verdadero (4) Verdadero (5) x=6 (3) Verdadero (4) Falso (7) y=3 (3) Verdadero (4) Verdadero (5) x=3 (3) Falso (9) Escribe 3 |
En C existe una forma abreviada de escribir un ciclo while: la instrucción for. No sólo abrevia, sino que ademas aporta claridad en ciertos casos. Su forma es
for (instrucción1; condición; instrucción2) {
instrucciones;
}
equivale a
instrucción 1;
while (condición) {
instrucciones;
instrucción2;
}
Los siguientes programas muestran ejemplos de la equivalencia entre while y for:
Con for... Con while...
Int i; for (i=0; i< 100; i++) printf ("El número es %d",i); |
int i=0; while (i<100) { printf ("El número es "+i); i++; } |
Float tiempo; for (tiempo=0.0;tiempo<10.0;tiempo+=0.1) { printf ("Tiempo = %f,posicion= %f",tiempo,pos); pos=0.1*velocidad; velocidad=velocidad+0.3; } |
float tiempo=0.0; while (tiempo<10.0) { printf ("Tiempo = %f,posicion= %f",tiempo,pos); pos=0.1*velocidad; velocidad=velocidad+0.3; } |