Sentencias iterativas 1. Objetivos Al finalizar esta actividad, serás capaz de: 1. Utilizar adecuadamente la sentencia while para generar la repetición en la ejecución de grupos de sentencias 2. Motivación Hasta ahora nuestros programas eran secuenciales, es decir, empezaban a ejecutarse en la primera sentencia dentro del main y después de la primera sentencia ejecutábamos la segunda que estaba en la línea inferior, y así sucesivamente hasta el final. Sólo en el caso de encontrar alguna sentencia condicional (if o switch) podía darse el caso de no ejecutar alguna instrucción. Pero en cualquier caso siempre avanzábamos hacia delante y nunca volvíamos a ejecutar una sentencia ya ejecutada anteriormente. Con las sentencias iterativas lo que logramos es iterar un grupo de instrucciones, es decir, ejecutar varias veces el mismo grupo de instrucciones mientras una condición especificada sea cierta. A estas sentencias también se las llama bucles, y las instrucciones que se repiten en un bucle se las denomina el cuerpo del bucle. 3. La sentencia while Aunque en lenguaje C hay varios tipos de sentencias iterativas, de momento sólo vamos a estudiar la sentencia while, porque es la más estándar, y podemos encontrarla en todos los lenguajes de programación, con una sintaxis bastante parecida. Sintaxis while(condición) { Sentencia 1; Sentencia 2; … Sentencia n; Mientras la condición que pongamos aquí sea cierta las instrucciones del cuerpo de bucle se ejecutarán. Estas llaves enmarcan el comienzo y el final de las instrucciones que se repetirán y que por lo tanto forman el cuerpo del bucle. } Si el cuerpo del bucle lo forma 1 sola sentencia las llaves no son necesarias. Ejemplo Queremos hacer un programa escriba por pantalla el doble de los números enteros que el usuario nos introduce por teclado. Para finalizar el usuario introducirá un 0 para indicar que ya no quiere hacer más cálculos. void main() 1 { int num; scanf(“%d”, &num); while (num !=0) { printf(“El doble de %d es %d\n”, num, num*2); scanf(“%d”, &num); } printf (“Fin del programa\n”); } El programa declara una variable llamada num de tipo entero (int), seguidamente pide por teclado el valor de un número entero, que lo almacena en la variable num. Seguidamente se evalúa la condición del bucle (num != 0). Si la condición es cierta se ejecutará el cuerpo del bucle, empezando por el printf, que muestra el mensaje por pantalla, y a continuación el scanf pidiendo el siguiente número. El siguiente paso vuelve a ser la evaluación de la condición del bucle (num != 0), si es cierta se vuelve a ejecutar las instrucciones del cuerpo del bucle, … y así hasta que la condición del bucle sea falsa (es decir, cuando el usuario escriba un 0). En ese caso se ejecutará el último printf mostrando el mensaje “Fin del programa”. Ejercicio 1: Escribe el anterior programa en el ordenador, compílalo y línkalo. ¿Funciona correctamente? La condición del bucle puede ser tan compleja como sea necesaria. En el caso anterior solamente era la comprobación de si una variable tenía un valor diferente a 0 pero podríamos unir condiciones con operadores lógicos (&&, ||). Ejercicio 2: Modifica el anterior programa de manera que la condición de finalización sea que el número introducido sea 0 o que el doble del último número sea mayor que 100. Comprueba que funciona correctamente. A priori, no se sabe cuántas vueltas o iteraciones dará el bucle. En el ejemplo anterior hasta que el usuario quiera y nos introduzca el 0. Incluso puede llegar a no ejecutarse nunca las instrucciones del cuerpo del bucle, en el caso de que la primera vez que se evalúa la condición ésta sea falsa. Otro ejemplo Una situación muy habitual se produce cuando sabemos el número de vueltas que debe dar el bucle. Entonces usaremos una variable que cuente el número de vueltas, y la condición del bucle verificará que esa variable todavía no haya llegado al límite previsto. Fíjate en el siguiente bucle par escribir la tabla de multiplicar el número 7. printf (“Tabla de multiplicar del numero 7\n”); i = 0; // esta es la variable que se usará como contador while (i<=10) { printf (“7 x %d = %d\n”,i, i*7); i = i+1; // incrementamos la variable contador } La variable contador empieza valiendo 0. En cada vuelta del bucle se incremente en 1, y el bucle acaba cuando el contador alcanza el valor 11 (primera ocasión en que no se cumple la condición del bucle). 2 4. Trucos, consejos y errores comunes Al trabajar con sentencias iterativas hay ciertos errores muy comunes y recurrentes, tener en cuenta esta lista te ayudará a entenderlos y no cometerlos. Cuerpo del bucle vacío El cuerpo de bucle puede estar formado por ninguna instrucción, es decir, puede estar vacío. Esto, que puede parecer extraño, el compilador no lo detecta como un error, puesto que no es un error sintáctico sino de lógica. Mira este ejemplo: while (num !=0); { printf(“El doble de %d es %d\n”, num, num*2); scanf(“%d”, &num); } Te puede parecer el mismo bucle del primer ejemplo de este documento, pero si te fijas después de la condición del while hay un punto y coma. Esto significa que el bucle acaba allí, y por lo tanto no hay ninguna instrucción a ejecutar. El resultado de este bucle es que nunca acabaría ya que num no se modifica nunca. Por lo tanto ojo con los puntos y coma. Bucles que nunca acaban En el anterior error común ya hemos visto que un bucle con while en el que al final hemos puesto un ; por error, no acabaría. Otra causa habitual de que el bucle no acabe es que se nos olvide incrementar la variable contador dentro del bucle. Recuerda el ejemplo de la tabla de multiplicar. Si dentro del bucle no hubiésemos puesto la sentencia i=i+1, el bucle no acabaría nunca (escribiría infinitas veces “7 x 0 = 0”). Condiciones mal escritas También son habituales los errores en las condiciones de entrada al bucle, especialmente cuando se trata de condiciones compuestas. Fíjate en esta posible solución al ejercicio 2 que se ha propuesto antes: void main() { int num,res; scanf(“%d”, &num); while ((num !=0) || (res < 100)) { res = num*2; printf(“El doble de %d es %d\n”, num, res); scanf(“%d”, &num); } printf (“Fin del programa\n”); } Recuerda que el bucle debe para cuando num sea 0 o el doble del último número leido del teclado sea mayor que 100. ¿Ves donde está el error? 3 Una iteración de más o una iteración de menos Este tipo de error suele provenir porque muchas veces no tenemos en cuenta el primer y el último caso que debe tratar el bucle. Éstos son casos especiales y tendremos que tratarlos como tales. Por ejemplo, el siguiente programa pretende calcular la potencia yx void main() { int res, x,y, i; scanf(“%d %d”, &y, &x); if (y==0) printf(“La potencia es 1\n”); else { res = y; i = 0; while (i<=x) { res = res * y; i = i+1; } printf (“La potencia es %d\n”, res); } } Escribe el anterior programa en el ordenador. ¿Funciona? ¿Por qué? ¿Cómo lo arreglarías? Solucionar problemas con bucles: debugger La mejor manera de solucionar los problemas de los bucles es utilizar el debugger. Es una herramienta básica para cualquier programador y muy útil para detectar estos errores. Ejercicio 3: El siguiente programa pide un número por teclado y calcula el número de dígitos que tiene ese número mayores que MAX. Escribe el siguiente programa en el ordenador, y ayudándote con el debugger indica por qué no funciona y arregla los fallos. #define MAX 7 void main() { int num, cont, original; scanf(“%d”, &num); original = num; while (num/10 != 0) { if (num %10 > MAX) cont ++; num = num / 10; } printf (“El número %d tiene %d dígitos mayores que %d\n”, original, cont, MAX); } Ejercicio 4: Escribe y prueba en el ordenador un programa que lea una secuencia de números enteros introducidos por el usuario a través del teclado. El programa irá sumando los valores a medida que se introducen, hasta que la suma supere un valor establecido previamente mediante una constante del programa. Cuando eso sucede el programa escribe en pantalla el valor de la suma y acaba. 4 Ejercicio 5: Escribe un programa que calcule la suma de todos los números entre 1 y 100 que son múltiplos de 5 o de 7. Para comprobar que X es múltiplo de Y basta con comprobar si el resto de la división entera de X entre Y es 0. 5