Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
ESTRUCTURAS DE CONTROL
El lenguaje C pertenece a la familia de lenguajes del paradigma de la
programacin estructurada. En este captulo quedan recogidas las reglas
de la programacin estructurada y, en concreto, las reglas sintcticas
que se exige en el uso del lenguaje C para el diseo de esas estructuras.
El
objetivo
del
captulo
es
aprender
crear
estructuras
Introduccin.
Las reglas de la programacin estructurada son:
1. Todo programa consiste en una serie de acciones o sentencias que
Instruccin 1
Instruccin 2
Instruccin N
88
Conceptos previos.
La regla 3 de la programacin estructurada habla de tres estructuras de
control: la secuencia, la seleccin y la repeticin. Nada nuevo hay ahora
que decir sobre la secuencia, que vendra esquematizada en la figura
4.1. En la figura 4.2. se esquematizan diferentes posibles estructuras de
seleccin; y en la figura 4.3. las dos estructuras bsicas de repeticin.
Las dos formas que rompen el orden secuencial de ejecucin de
sentencias son:
1. Instruccin condicional: Se evala una condicin y si se cumple
se transfiere el control a una nueva direccin indicada por la
instruccin.
2. Instruccin incondicional. Se realiza la transferencia a una nueva
direccin sin evaluar ninguna condicin (por ejemplo, llamada a una
funcin).
En ambos casos la transferencia del control se puede realizar con o sin
retorno: en el caso de que exista retorno, despus de ejecutar el bloque
de instrucciones de la nueva direccin se retorna a la direccin que
sucede a la que ha realizado el cambio de flujo.
89
No
Condicin
No
Instruccin
Instruccin
Instruccin
Condicin
Instruccin
Instruccin
Bifurcacin abierta
Bifurcacin cerrada
No
Condicin
Instruccin
Instruccin
S
No
Instruccin
Condicin
Instruccin
Estructura while
Estructura do - while
sentencia
que
est
precedida
por
la
estructura
de
control
90
91
92
primer if */
segundo if */
tercer if */
alternativa al tercer if */
alternativa al 2 if */
alternativa al primer if */
C
S
S
S
S1
C3
C2
C1
No
No
No
S2
S3
S4
93
#include <stdio.h>
void main(void)
{
short D, d;
char opcion;
printf("Programa para dividir dos enteros...\n");
printf("Introduzca el dividendo ... ");
scanf("%hd",&D);
printf("Introduzca el divisor ... ");
scanf("%hd",&d);
if(d != 0)
printf("%hu / %hu = %hu", D, d, D / d);
else
{
printf("No se puede dividir por cero.\n");
printf("Introducir otro denominador (s/n)?");
opcion = getchar();
if(opcion == 's')
{
printf("\nNuevo denominador ... ");
scanf("%hd",&d);
if(d != 0)
printf("%hu / %hu = %hu", D, d, D/d);
else
printf("De nuevo ha introducido 0.");
}
}
}
La funcin getchar() est definida en la biblioteca stdio.h. Esta funcin
espera a que el usuario pulse una tecla del teclado y, una vez pulsada,
devuelve el cdigo ASCII de la tecla pulsada.
En este ejemplo hemos llegado hasta un tercer nivel de anidacin.
Escala if - else if
Cuando se debe elegir entre una lista de opciones, y nicamente una de
ellas ha de ser vlida, se llega a producir una concatenacin de
condiciones de la siguiente forma:
if(condicin1) setencia1;
else
{
if(condicin2) sentencia2;
else
{
if(condicin3) sentencia3;
94
else sentencia4;
}
El flujograma recogido en la Figura 4.4. representara esta situacin sin
ms que intercambiar los caminos de verificacin de las condiciones C1,
C2 y C3 recogidas en l (es decir, intercambiando los rtulos de S y
de No).
Este tipo de anidamiento se resuelve en C con la estructura else if, que
permite una concatenacin de las condicionales. Un cdigo como el
antes escrito quedara:
if(condicin1) sentencia1;
else if (condicin2) sentencia2;
else if(condicin3) sentencia3;
else sentencia4;
Como se ve, una estructura as anidada se escribe con mayor facilidad y
expresa tambin ms claramente las distintas alternativas. No es
necesario
que,
en
un
anidamiento
de
sentencias
condicionales,
95
96
97
switch(a)
{
case 1:
case 2:
case 3:
default:
}
printf(UNO\t);
printf(DOS\t);
printf(TRES\t);
printf(NINGUNO\n);
TRES
NINGUNO.
C
No
No
No
a=3
a=2
a=1
UNO
DOS
TRES
NINGUNO
98
C
No
No
No
a=3
a=2
a=1
UNO
break;
DOS
break;
TRES
break;
NINGUNO
F
99
switch(nota)
{
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
default:
printf(SUSPENSO);
break;
printf(APROBADO);
break;
printf(NOTABLE);
break;
printf(SOBRESALIENTE);
break;
printf(MATRCULA DE HONOR);
break;
printf(Nota introducida errnea.);
}
No se puede poner una etiqueta case fuera de un bloque switch. Y
tampoco tiene sentido colocar instrucciones dentro del bloque switch
antes de aparecer el primer case: eso supondra un cdigo que jams
podra llegar a ejecutarse. Por eso, la primera sentencia de un bloque
switch debe estar ya etiquetada.
Se pueden anidar distintas estructuras switch.
El ejemplo de las notas, que ya se mostr al ejemplificar una anidacin
de sentencias ifelseif puede servir para comentar una caracterstica
importante de la estructura switch. Esta estructura no admite, en sus
distintas entradas case, ni expresiones lgicas o relacionales, ni
expresiones aritmticas, sino literales. La nica relacin aceptada es,
pues, la de igualdad. Y adems, el trmino de la igualdad es siempre
entre una variable o una expresin entera (la del switch) y valores
literales: no se puede indicar el nombre de una variable. El programa de
las notas, si la variable nota hubiese sido de tipo float, como de hecho
quedo definida cuando se resolvi el problema con los condicionales if
elseif no tiene solucin posible mediante la estructura switch.
100
Un ejercicio planteado.
Planteamos ahora un ejercicio a resolver: solicite del usuario que
introduzca por teclado un da, mes y ao, y muestre entonces por
pantalla el da de la semana que le corresponde.
La resolucin de este problema es sencilla si se sabe el cmo. Sin un
correcto algoritmo que nos permita saber cmo procesar la entrada no
podemos hacer nada.
Por lo tanto, antes de intentar implementar un programa que resuelva
este problema, ser necesario preguntarse si somos capaces de
resolverlo sin programa. Porque si no sabemos hacerlo nosotros, menos
sabremos explicrselo a la mquina.
Buscando en Internet he encontrado lo siguiente: Para saber a qu da
de la semana corresponde una determinada fecha, basta aplicar la
siguiente expresin:
d = (26 M 2 ) 10 + D + A + A 4 + C 4 2 C mod7
101
D = 15
C = 19
es decir martes!
Queda ahora hacer el programa que nos d la respuesta al da de la
semana en el que estamos. Har falta emplear dos veces la estructura
de control condicional if y una vez el switch. El programa queda como
sigue:
#include <stdio.h>
void main(void)
{
unsigned short D, mm, aaaa;
unsigned short M, A, C;
printf("Introduzca la fecha ... \n");
printf("Da ... ");
scanf("%hu", &D);
printf("Mes ... ");
scanf("%hu", &mm);
102
mm + 10;
(aaaa - 1) % 100;
(aaaa - 1) / 100;
mm - 2;
aaaa % 100;
aaaa / 100;
103
Estructura while.
104
105
encuentra
extensamente
documentado
este
otros
muchos
106
5
5
4
20
3
60
2
120
1
120
0
120
donde todo es igual excepto que ahora se ha hecho uso del operador
compuesto en la primera sentencia del bloque. Pero an se puede
compactar ms:
1. La condicin de permanencia ser verdad siempre que n no sea cero.
Y por definicin de verdad en C (algo es verdadero cuando es
107
dos
sentencias
simples
iteradas
en
el
bloque
pueden
Esta lnea de programa espera una entrada por teclado. Cuando sta se
produzca comprobar que hemos tecleado el carcter a minscula; de
no ser as, volver a esperar otro carcter.
Una forma ms sencilla fcil de ver el significado de esta ltima lnea
de cdigo vista sera expresarlo de la siguiente manera:
while(ch != a)
ch = getchar();
teclado.
No es necesario explicar el concepto de mximo comn divisor. S es
necesario en cambio explicar un mtodo razonable de plantear al
ordenador cmo se calcula ese valor: porque este ejemplo deja claro la
importancia
de
tener
no
slo
conocimientos
108
de
lenguaje
de
109
Estructura dowhile.
toda
solucin
un
problema
resuelto
con
una
110
PROCESO
S
repetir
No
111
opcion
S
S
C2
C1
No
No
112
Estructura for.
s1
e1
No
s3
F
s2
113
Por ejemplo, veamos un programa que muestra por pantalla los enteros
pares del 1 al 100:
#include <stdio.h>
void main(void)
{
short i;
for(i = 2 ; i <= 100 ; i += 2)
printf("%5hd",i);
}
114
{
short i;
for(i = 2 ; i <= 100 ; i += 2)
{
printf("%5hd",i);
if(i % 10 == 0) printf("\n");
}
}
115
116
}
printf("Ha introducido el entero par %hd",num);
printf(" despus de %hd impares. ",i - 1);
}
i 1
num
C1 num mod2 = 0
i i +1
C1
i 1
i i +1
num
C1
Con break
Sin break
117
C1 nummod2 0
suma 0
suma
num
suma + num
suma
C1
118
que repetir la ejecucin del cdigo hasta que se pulse la tecla a, y que
ocasionar la ejecucin del break.
Una sentencia continue dentro de un bloque de instrucciones de una
estructura de iteracin interrumpe la ejecucin de las restantes
sentencias iteradas y vuelve al inicio de las sentencias de la estructura
de control, si es que la condicin de permanencia as lo permite.
Veamos, por ejemplo, el programa antes presentado que muestra por
pantalla los 100 primeros enteros pares positivos. Otro modo de
resolver ese programa podra ser el siguiente:
#include <stdio.h>
void main(void)
{
short i;
for(i = 1 ;i <= 100 ; i++)
{
if(i % 2) continue;
printf("%4hd\t",i);
}
}
i i +1
C2
C1 i 100
C 2 i mod2 0
119
iteracin.
Si alguna vez ha programado con esta palabra, la recomendacin es que
se olvide de ella. Si nunca lo ha hecho, la recomendacin es que la
ignore.
Y, eso s: hay que acordarse de que esa palabra es clave en C: no se
puede generar un identificador con esa cadena de letras.
120
para
introducir
datos.
Cuando
el
usuario
121
Recapitulacin.
Hemos presentado las estructuras de control posibles en el lenguaje C.
Las
estructuras
condicionales
de
bifurcacin
abierta
cerrada,
Ejercicios.
En todos los ejercicios que planteamos a continuacin quiz ser
conveniente que antes de abordar la implementacin se intente disear
un algoritmo en pseudocdigo o mediante un diagrama de flujo. Si en
algn caso el
ste
en
las
pginas
122
del
manual
Fundamentos
de
20.
#include <stdio.h>
void main(void)
{
long suma = 0;
short i;
for(i = 2 ; i <= 200 ; i += 2)
suma += i;
printf("esta suma es ... %ld.\n",suma);
}
21.
#include <stdio.h>
void main(void)
{
long suma;
short i, num;
for(i = 0, suma = 0 ; ; i++)
{
printf("Introduzca nmero ... ");
scanf("%hd",&num);
suma += num;
if(num == 0) break;
}
if(i == 0) printf("No se han introducido enteros.");
else printf("La media es ... %.2f.",(float)suma / i);
}
123
22.
#include <stdio.h>
void main(void)
{
short suma;
short i, num;
for(num = 2 ; num < 10000 ; num++)
{
for(i = 1, suma = 0 ; i <= num / 2 ; i++)
if(num % i == 0) suma += i;
if(num == suma)
printf("En entero %hd es perfecto.\n",num);
}
}
124
23.
#include <stdio.h>
void main(void)
{
unsigned short int a0,a1,a2,a3;
printf("Introduzca cuatro enteros ... \n\n");
printf("Primer entero ... ");
scanf("%hu",&a0);
printf("Segundo entero ... ");
scanf("%hu",&a1);
printf("Tercer entero ... ");
scanf("%hu",&a2);
printf("Cuarto entero ... ");
scanf("%hu",&a3);
if(a0 > a1)
{
a0 ^= a1;
a1 ^= a0;
a0 ^= a1;
}
if(a0 > a2)
{
a0 ^= a2;
a2 ^= a0;
a0 ^= a2;
}
if(a0 > a3)
{
a0 ^= a3;
a3 ^= a0;
a0 ^= a3;
}
if(a1 > a2)
{
a1 ^= a2;
a2 ^= a1;
a1 ^= a2;
}
if(a1 > a3)
{
a1 ^= a3;
a3 ^= a1;
a1 ^= a3;
125
}
if(a2 > a3)
{
a2 ^= a3;
a3 ^= a2;
a2 ^= a3;
}
printf("\nOrdenados... \n");
printf("%hu <= %hu <= %hu <= %hu.", a0, a1, a2, a3);
}
24.
126
25.
#include <stdio.h>
void main(void)
{
127
signed long a;
unsigned long Test;
char opcion;
do
{
Test = 0x80000000;
printf("\n\nIndique el entero ... ");
scanf("%ld", &a);
while(Test)
{
Test & a ? printf("1") : printf("0");
Test >>= 1;
}
printf("\nDesea introducir otro entero? ... ");
do
opcion = getchar();
while (opcion != 's' && opcion != 'n');
}while(opcion == 's');
}
128
26.
#include <stdio.h>
#include <math.h>
void main(void)
{
unsigned long int numero, raiz;
unsigned long int div;
char chivato;
printf("Dame el numero que vamos a testear ... ");
scanf("%lu", &numero);
chivato = 0;
raiz = sqrt(numero);
for(div = 2 ; div <= raiz ; div++)
{
if(numero % div == 0)
{
chivato = 1;
break;
}
}
if(chivato == 1)
printf("El numero %lu es compuesto",numero);
else printf("El numero %lu es primo",numero);
}
129
n .
Entonces
tendremos:
n = a b <
n n =nn<n
130
27.
131
28.
#include <stdio.h>
#include <math.h>
void main(void)
{
float a, b, c;
double r;
// introduccin de parmetros...
printf("Introduzca los coeficientes...\n\n");
printf("a --> "); scanf("%f",&a);
printf("b --> "); scanf("%f",&b);
printf("c --> "); scanf("%f",&c);
// Ecuacin de primer grado...
if(a == 0)
{
// No hay ecuacin ...
if(b == 0) printf("No hay ecuacin.\n");
else // S hay ecuacin de primer grado
{
printf("Ecuacin de primer grado.\n");
printf("Tiene una nica solucin.\n");
printf("x1 --> %lf\n", -c / b);
}
}
// Ecuacin de segundo grado. Soluciones imaginarias.
else if ((r = b * b - 4 * a * c) < 0)
{
printf("Ecuacin sin soluciones reales.\n");
r = sqrt(-r);
132
29.
#include <stdio.h>
void main(void)
{
long int numero;
long int div;
printf("Nmero --> ");
scanf("%ld",&numero);
printf("\n\nLos divisores de %ld son:\n\t", numero);
printf("1, ");
for(div = 2 ; div <= numero / 2 ; div++)
if(numero % div == 0)
printf("%ld, ",div);
printf("%ld.",numero);
}
133
30.
2
6
2.
k =1 k
#include <stdio.h>
#include <math.h>
#define LIMITE 10000
void main(void)
{
double PI = 0;
for(int i = 1 ; i < LIMITE ; i++)
PI += 1.0 / (i * i);
PI *= 6;
PI = sqrt(PI);
printf("El valor de PI es ... %lf.",PI);
}
debe poner como 1.0 para que el resultado del cociente no sea un
entero igual a cero sino un valor double.
31.
( 1)
2k +1
k =0
134
#include <stdio.h>
#define LIMITE 100000
void main(void)
{
double PI = 0;
for(int i = 1 , e = 4 ; i < LIMITE ; i += 2 , e = -e)
PI += e / (double)i;
printf("El valor de PI es ... %lf.",PI);
}
32.
2 2 4 4 6 6 8 8
... .
1 3 3 5 5 7 7 9
De nuevo el clculo del valor del nmero pi. Estos ejercicios son muy
sencillos de buscar (Internet est llena de definiciones de propiedades
del nmero pi) y siempre es fcil comprobar si hemos realizado un buen
cdigo: basta ejecutarlo y comprobar si sale el famoso 3.14.
En esta ocasin, el cdigo podra tomar la siguiente forma:
135
#include <stdio.h>
#define LIMITE 100000
void main(void)
{
double PI = 2;
for(int num = 2 , den = 1, i = 1 ;
i < LIMITE ; i++ , i % 2 ? num+=2 : den+=2)
PI *= num / (double)den;
printf("El valor de PI es ... %lf.",PI);
}
33.
b = 1, c = 2;
trabajo
que
acaban
agotados,
por
lo
que
deciden
136
tres marineros.
Al levantarse por la maana procedieron a repartirse los cocos
que quedaban entre ellos cinco, no sobrando ahora ninguno.
Cuntos cocos haban recogido inicialmente? Mostrar todas las
soluciones posibles menores de 1 milln de cocos.
137
34.
pero,
con
el
transcurrir
del
tiempo,
el
error
un
algoritmo
que
solicite
al
usuario
una
fecha
138
35.
e=
1
1
1
1
+
+
+
+ ...
0! 1! 2! 3!
#include <stdio.h>
void main(void)
{
double p = 1, e = 1;
for(short n = 1 ; n < 100 ; n++)
{
p *= 1.0 / n;
e += p;
}
printf("El numero e es ... %20.17lf.",e);
}
36.
Juego
de
las
15
cerillas:
Participan
dos
jugadores.
139
#include <stdio.h>
void main(void)
{
// Con cuntas cerillas se va a jugar.
unsigned short cerillas;
// Cuntas cerillas se pueden quitar cada vez.
unsigned short quitar;
// Cerillas que quita el ganador y el perdedor.
unsigned short qp, qg;
char ganador;
do
{
printf("\n\n\nCon cuntas cerillas
se va a jugar ... ");
scanf("%hu",&cerillas);
if(cerillas == 0) break;
do
{
printf("\Cuntas cerillas pueden
quitarse de una vez... ");
scanf("%hu",&quitar);
if(quitar >= cerillas)
printf("No pueden quitarse tantas
cerillas.\n");
}while(quitar >= cerillas);
qg = (cerillas - 1) % (quitar + 1);
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30))printf("\n\n");
}
printf("\n");
// Fin de MOSTRAR CERILLAS
if(qg)
{
printf("\nComienza la mquina...");
printf("\nMquina Retira %hu cerillas...
\n", qg);
140
cerillas -= qg;
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30))printf("\n\n");
}
printf("\n");
}
// FIN DE MOSTRAR CERILLAS
else printf("\nComienza el jugador...");
while(cerillas != 1)
{
do
{
printf("\nCerillas que retira el
jugador ... ");
scanf("%hu",&qp);
if(qp > quitar)
printf("\nNo puede quitar mas
de %hu.\n",quitar);
}while(qp > quitar);
cerillas -= qp;
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30)) printf("\n\n");
}
printf("\n");
// Fin de MOSTRAR CERILLAS
if(cerillas == 1)
{
ganador = 'j';
break;
}
qg = quitar - qp + 1;
printf("\nLa mquina retira %hu
cerillas.\n",qg);
cerillas -= qg;
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30))printf("\n\n");
}
printf("\n");
141
37.
1 = 1
3 = ( + 1) ( 1)
=1+1
= 1+
y otras
1
=1+
1
1
1+
=1+
1+
...
1
1+
142
1+
1+
1+
1
1 + ...
1
1+
1
1
procedimiento
haciendo,
por
ejemplo,
la
sustitucin
#include <stdio.h>
#define LIMITE 1000
void main(void)
{
double au = 1;
for(int i = 0 ; i < LIMITE ; i++)
au = 1 + 1 / au;
printf("El nmero ureo es ..... %lf.\n",au);
printf("ureo al cuadrado es ... %lf.\n",au * au);
}
38.
143
tenemos:
= 1 + = 1 + 1 + = 1 + 1 + 1 + = ... = 1 + 1 + 1 + 1 + 1 + ... 1 +
#include <stdio.h>
#include <math.h>
#define LIMITE 100000
void main(void)
{
double au = 1;
for(int i = 0 ; i < LIMITE ; i++)
au = sqrt(1 + au);
printf("El nmero ureo es ..... %lf.\n",au);
printf("ureo al cuadrado es ... %lf.\n",au * au);
}
39.
#include <stdio.h>
#include <math.h>
void main(void)
{
long a, b, div;
printf("Lmite inferior ... ");
scanf("%ld",&a);
printf("Lmite superior ... ");
scanf("%ld",&b);
printf("Los primos entre %ld y %ld son ...\n\t", a, b);
for(long num = a, primos = 0 ; num <= b ; num++)
{
144
El primer for recorre todos los enteros comprendidos entre los dos
lmites introducidos por teclado. El segundo for averigua si la variable
num codifica en cada iteracin del primer for un entero primo o
compuesto: si al salir del segundo for se tiene que num % div es igual a
cero, entonces num es compuesto y se ejecuta las sentencia continue
que vuelve a la siguiente iteracin del primer for. En caso contrario, el
valor de num es primo, y entonces sigue adelante con las sentencias del
primer for, que estn destinadas nicamente a mostrar por pantalla, de
forma ordenada, ese entero primo, al igual que habr mostrado
previamente todos los otros valores primos y mostrar los que siga
encontrando posteriormente.
La salida por pantalla del programa podra ser la siguiente:
Lmite inferior ... 123
Lmite superior ... 264
Los primos entre 123 y 264 son ...
127,
179,
233,
131,
181,
239,
137,
191,
241,
139,
193,
251,
149,
197,
257,
151,
199,
263,
157,
211,
163,
223,
167,
227,
173,
229,
145
146