Capítulo 4. Estructura general de un programa. Estructuras básicas... control. Entrada y salida de datos.

Anuncio
Capítulo 4.
Estructura general de un programa. Estructuras básicas de
control. Entrada y salida de datos.
1. Estructura general de un programa. Pseudocódigo y C.
1.1. Sentencia simple.
1.2. Sentencia compuesta.
2. Programación estructurada. Estructuras básicas de control.
2.1. Estructura secuencial.
2.2. Estructura alternativa.
2.3. Estructura repetitiva.
3. Entrada y salida de datos.
3.1. Entrada de datos.
3.2. Salida de datos.
1
1. Estructura general de un programa. Pseudocódigo y C.
De un modo muy general se puede decir que un programa está formado
por 4 partes principales:
- Declaraciones: la parte donde se declaran o crean los objetos
(variables, constantes, etc.) necesarios para el programa.
- Entrada de datos: la parte donde se solicitan y se recogen los datos
que necesita el programa para operar.
- Proceso o algoritmo: la parte que realiza las operaciones sobre los
datos para obtener unos resultados.
- Salida de resultados: la parte que muestra o guarda los resultados
obtenidos tras el proceso.
En realidad, las 3 últimas partes no suelen tener una separación tan
definida, mezclándose a lo largo del programa.
El pseudocódigo es una notación empleada para escribir algoritmos, la
cual no está sujeta a las reglas sintácticas de ningún lenguaje, por lo que su
uso es rápido y sencillo. La estructura general de un algoritmo en
pseudocódigo consiste simplemente en etiquetar el inicio y el final del
programa, colocando entre ambas etiquetas todas las sentencias a realizar, sin
necesidad de declarar las variables, constantes, etc.
En C, la estructura general de un programa es la siguiente:
/* Esto es una muestra de la estructura
general de un programa C */
#include <libreria1.h>
#include <libreria2.h>
...
#define <constante1> <valor1>
#define <constante2> <valor2>
...
<Declaración de variables globales>
// Comienzo del módulo principal
void main(void)
{
<Declaración de variables locales>
Instrucciones: entrada, proceso y salida;
}
// Fin del programa
Los comentarios que se deseen incluir en un programa en C se inician
con /* y se finalizan con */, pudiendo englobar varias líneas. También a
continuación de // se puede incluir una sola línea de comentario.
Toda sentencia que comience por # se denomina directiva de
preprocesador. Es una de las características del C. Con la directiva #include
<libreria.h> se indica al compilador que recupere el código del archivo
predefinido libreria.h. Los archivos cabecera libreria.h son vulgarmente
llamados “includes”. Estos archivos contienen identificadores, constantes,
2
macros, prototipos de funciones, etc. permitiendo tener las declaraciones fuera
del programa principal. Da más modularidad al programa.
Todo programa en C debe tener una función main(). Es la función
principal y establece el punto en el que comienza la ejecución.
1.1. Sentencia simple.
Es una línea que contiene una expresión válida en C acabada en punto y
coma “;”.
Ej.
Calcula_minimo(x, y);
A = b * c;
//Llamada a una función
//Sentencia de asignación
1.2. Sentencia compuesta.
Una sentencia compuesta es un grupo de sentencias que se trata como
si fuera una única sentencia.
En C, las sentencias compuestas comienzan con una llave { y terminan
con la llave complementaria }.
Generalmente las sentencias compuestas se usan para indicar el
conjunto de operaciones a realizar cuando se cumplen ciertas condiciones
(estructuras alternativas IF-ELSE), o bien el conjunto de operaciones que se
quieren repetir hasta que se cumpla una condición (estructuras repetitivas
FOR, WHILE, ...).
Dentro de una sentencia compuesta, al principio, pueden crearse
variables, que serán locales para ese bloque delimitado por { y }.
2. Programación estructurada. Estructuras básicas de control.
Como ya se ha mencionado, la programación estructurada está basado
en el uso de solamente de las tres estructuras básicas de control: secuencial,
alternativa y repetitiva. Veamos cada una de ellas.
2.1. Estructura secuencial.
La estructura de control secuencial simplemente dice que las sentencias
de un programa se ejecutan en el orden en que están escritas.
2.2. Estructura alternativa.
La estructura de control alternativa será desarrollada en un capítulo
posterior.
2.3. Estructura repetitiva.
La estructura de control alternativa será desarrollada en un capítulo
posterior.
3. Entrada y salida de datos.
Las instrucciones de entrada y salida de datos se usan para poder
comunicarse con el programa.
3
3.1. Entrada de datos.
Mediante las instrucciones de entrada se puede guardar en una variable
del programa datos que proceden de un dispositivo externo, como un teclado,
un disco duro, etc.
En pseudocódigo la instrucción de entrada desde el teclado será:
Leer <Nombre_Variable>
Cuando el procesador ejecuta esa sentencia, se realiza una pausa en la
ejecución del programa, esperando a que se teclee un dato y se pulse
<ENTER>. El dato tecleado será guardado en la variable <Nombre_Variable>.
En C existen varias formas de realizar entradas desde teclado:
- Funciones para entrada de un carácter:
a) int getchar(void)
Está en la librería stdio.h. Esta función tiene un problema, ya que fue
definida para ser compatible con la versión original de C basada en UNIX:
guarda los caracteres que se tecleen en el buffer de entrada, hasta que se
pulse <ENTER>. Después recoge sólo el primer carácter y lo almacena en la
variable especificada. Esto hace que puedan quedar uno o más caracteres en
el buffer de entrada. Así, las posteriores funciones de entrada en el programa
leerán esos caracteres del buffer, obteniéndose resultados inesperados.
Ej.
char letra;
letra = getchar();
En caso de error devuelve EOF, constante definida en stdio.h con valor
igual a –1.
b) int getche(void)
Está en la librería conio.h. El carácter tecleado será almacenado y
visualizado en pantalla (tiene eco). La ejecución del programa continuará sin
necesidad de pulsar <ENTER>.
Ej.
char letra;
letra = getche();
c) int getch(void)
Está en la librería conio.h. Funciona exactamente como la anterior,
excepto que el carácter tecleado no será visualizado en pantalla (sin eco).
- Función de entrada de cadenas, gets: está en la librería stdio.h.
4
char * gets(char * cadena)
Recoge una cadena de caracteres introducida por teclado hasta pulsar
<ENTER> y la guarda en la dirección apuntada por su argumento (cadena). El
salto de carro no se introduce en la cadena, se sustituye por el carácter nulo
‘\0’. En C, todos los nombres de cadenas son punteros al primer carácter de la
cadena.
Una cadena es una sucesión de caracteres. Se declara de la forma:
char cadena[nºcaracteres];
Ej.
char cadena[25];
gets(cadena);
La función gets no controla automáticamente la longitud de la cadena, es
decir que si se teclean más caracteres que la longitud de la cadena, pueden
ocurrir errores inesperados.
- Función de entrada con formato, scanf: está en la librería stdio.h.
int scanf( char * cadena_control, lista_de_argumentos)
En caso de error devuelve EOF.
La lista_de_argumentos está formada por las direcciones de memoria
(punteros) de las variables donde se quiere guardar los valores tecleados. Por
tanto, debe usarse el operador & delante del nombre de cada variable, excepto
para cadenas (ya son punteros).
La cadena_control se escribe entre comillas dobles y está formada por:
Especificadores de formato
Caracteres de espacios en blanco
Caracteres de no-espacios en blanco
Cada especificador de formato se corresponderá con una variable de la
lista de argumentos, según el orden en que estén escritos. Por lo tanto, debe
haber el mismo número de especificadores de formato que argumentos en la
lista. Los especificadores de formato tienen la forma:
%[nº_de_caracteres]type
El valor de type puede ser:
Código
c
d
Significado
Lee un único carácter
Lee un entero
5
i
ld
e
f
lf
Lf
g
o
s
x
p
n
u
[...]
Lee un entero
Lee un entero de tipo long
Lee un número en coma flotante
Lee un número en coma flotante
Lee un número en coma flotante double
Lee un número en coma flotante long double
Lee un número en coma flotante
Lee un número octal
Lee una cadena
Lee un número hexadecimal
Lee un puntero
Recibe un valor entero igual al número de caracteres leídos
Lee un entero sin signo
Muestrea un conjunto de caracteres (cadenas)
El nº de caracteres será un número entero opcional que se coloca entre
% y type. Ese número indica el número máximo de caracteres a almacenar en
la variable correspondiente, de forma que el exceso no se tendrá en cuenta.
Ej.
int edad;
scanf( "%3d",&edad);//Después de teclear 3 números,
//lo que se teclee no se guarda.
int i,j;
scanf( "%o%x",&i,&j); //Uno en octal y otro en hexade.
char a,b,c;
scanf( "%c%c%c", &a,&b,&c); // Lee tres letras.
El type [...] se usa para cadenas de caracteres e indicará que sólo serán
guardados los caracteres tecleados que coincidan con los especificados entre
los corchetes. Cuando se teclee un carácter que no esté entre los corchetes, no
se almacenarán más caracteres en la variable correspondiente.
Ej.
char cad[3];
scanf("%[ABCD]",cad);
//cad no lleva &, ya que el
//nombre de una cadena es una dirección.
Si se teclea
A
AB
aB
DD
BH
EA
Se asigna a cad
CAD = "A"
CAD = "AB"
CAD = ""
CAD = "DD"
CAD = "B"
CAD = ""
6
El type [^....] se usa para cadenas de caracteres e indicará que sólo
serán almacenados los caracteres tecleados que no coincidan con los
especificados dentro de los corchetes.
La función scanf deja de guardar en la variable los caracteres tecleados
cuando se pulsa espacio en blanco, \t (tabulador) o \n (retorno de carro o
<ENTER>), lo cual causa problemas en el caso de teclear cadenas de
caracteres que incluyan espacios en blanco.
Ej.
char nombre[20];
scanf ("%s",nombre);
//Si se teclea: “Fco. Javier” se guarda en la
//variable nombre = "Fco.", el esp.blanco corta.
Ese problema se puede solucionar con el type [^\n], es decir almacenar
todos los caracteres tecleados, excepto el retorno de carro.
Ej.
scanf ("%[^\n]",nombre);
//Guarda nombre = "Fco. Javier"
También scanf deja de almacenar los caracteres tecleados cuando no se
cumpla el type especificado, con lo que pueden quedar caracteres en el buffer
de entrada, de manera que la siguiente instrucción de entrada recogería esos
caracteres del buffer.
Ej.
int i;
scanf("%d", &i);
//Si se teclea "A12", en i queda i=0, ya que %d
//espera un nºentero y A no lo cumple; lo que se
//teclee después de la A (el 12) ya no se guarda en i.
Para eliminar los caracteres que pueden quedar en el buffer de teclado,
siempre debe usarse la función fflush(stdin) después de cada scanf.
Ej.
int num;
char car;
scanf("%d", &num); fflush(stdin);
scanf("%c", &car); fflush(stdin);
Como decíamos antes, en la cadena de control, además de los
especificadores de formato, pueden colocarse caracteres de espacios en
7
blanco y caracteres de no-espacios en blanco, que se usan cuando un scanf
incluye varios especificadores de formato.
Un carácter de espacio en blanco antes o después del especificador de
formato hace que scanf lea los caracteres blancos pero no los almacena. Esta
es la opción por defecto, no es necesario especificarla.
Un carácter de espacio en blanco puede ser un espacio en blanco, un
tabulador (\t) o un retorno de carro (\n).
Ej.
int edad;
double salario;
scanf("%d\n%lf",&edad,&salario);
//Al teclear un blanco, un tabulador o <enter> se deja
//de guardar en edad para guardar en salario.
Un carácter de no-espacio en blanco es cualquier carácter que no sea
blanco, \t o \n. Si se coloca una serie de caracteres no-espacios blanco en la
cadena de control, scanf obliga a que se tecleen esos caracteres pero no los
almacena. Si no se tecleean esos caracteres en la posición indicada, no se
guarda lo tecleado en la variable.
Ej.
int i;
double j;
scanf("$%d", &i); //Si se teclea $74 se asigna i=74
//Si se teclea 74 se asigna i=0
scanf("%d:%lf",&i,&j);
//Al pulsar ':' se deja de
//asignar a i, y se comienza a asignar a j.
3.2. Salida de datos.
Mediante las instrucciones de salida se puede enviar a un dispositivo
externo (monitor, disco duro, etc.) los datos que están en las variables de un
programa.
En pseudocódigo la instrucción de salida al monitor (visualizar) será:
Escribir <Nombre_Variable>
Cuando el procesador ejecuta esa sentencia, se visualiza en pantalla el
valor almacenado en la variable <Nombre_Variable>.
En C existen varias formas de realizar salidas a monitor:
- Funciones para salida de un carácter: está en la librería stdio.h.
8
int putchar(int c)
El entero c es convertido a carácter y se envía al monitor. En caso de
error devuelve EOF.
Ej.
char car;
car = getchar();
putchar(car);
- Función de salida de cadenas, puts: está en la librería stdio.h.
int * puts(char * cadena)
Visualiza en el monitor el contenido de cadena, realizando a
continuación un salto de línea. En caso de error devuelve EOF, si no devuelve
un valor distinto de cero. Reconoce las mismas secuencias de control
(secuencias de backslash) que la función printf, que veremos más adelante. La
función puts es más rápida que printf, ya que tiene menos código.
Ej.
char cadena[25];
gets(cadena);
puts(cadena);
- Función de salida con formato, printf: está en la librería stdio.h.
int printf(char * cadena_control, lista_de_argumentos)
Esta función puede visualizar varios datos por pantalla. Devuelve un
valor entero que coincide con el número de caracteres visualizados. En caso de
error, devuelve un valor negativo.
La cadena_control se escribe entre comillas dobles y está formada por
especificadores de formato y por los caracteres que se desee visualizar.
Los especificadores de formato tienen la siguiente forma:
%[flags] [ancho de campo] [precisión] type
Como se ve, cada especificador de formato comienza por %; este
carácter y type son obligatorios, el resto son opcionales (entre corchetes).
La lista_de_argumentos del prototipo de printf está formada por las
variables o constantes que se quiera visualizar. Cada argumento de la lista
debe tener su especificador de formato.
El modificador type del especificador de formato puede ser:
9
Código
c
d
i
ld
e
E
f
lf
Lf
g
G
o
s
u
x
X
p
n
%%
Formato
Carácter
Enteros con signo
Enteros con signo
Enteros con signo long
Coma flotante, notación científica (e minúscula)
Coma flotante, notación científica (E mayúscula)
Coma flotante float
Coma flotante double
Coma flotante long double
Usa e o f, el más corto
Usa E o f, el más corto
Octal sin signo
Cadena de caracteres
Enteros decimales sin signo
Hexadecimales sin signo (letras minúsculas:a - f)
Hexadecimales sin signo (letras mayúsculas:A –F)
Mostrar un puntero
El argumento asociado será un puntero a entero al
que se le asigna el número de caracteres escritos
Visualizar el signo %
Ej.
char car;
float num;
car = getch();
num = 12.25;
printf("Carácter: %c
Número: %f", car, num);
Si se visualiza una variable con un tipo (type en el printf) que no se
corresponde con el que se ha declarado, el C realiza la conversión de forma
automática, según se ha visto anteriormente. Veamos un ejemplo para el caso
de la conversión de caracteres a números.
Ej.
char car = ‘Ñ’;
unsigned char uncar = ‘Ñ’;
printf(“%c”, car);
//Visualiza Ñ.
printf(“%c”, uncar); //Visualiza Ñ.
printf(“%d”, car);
//Visualiza –91, ya que se tiene
//en cuenta el bit de signo al convertir a decimal.
printf(“%d”, uncar); //Visualiza 165, ya que no se
//tiene en cuenta el bit de signo en la conversión.
Los especificadores %e y %E, que se usan para coma flotante, muestran
su argumento en notación científica, que es:
10
%e
%E
->
->
x.dddddde +/- yy
x.ddddddE +/- yy
Con %g da la salida más corta entre %f y %e; con %G da la salida más
corta entre %f y %E.
Ej.
double d = 100.0;
printf( "%g",d);
d = 100000000.0;
printf( "%g",d);
//Visualiza con formato %f
//Visualiza con formato %e; es más
corto que %f.
Con %p se muestra una dirección de memoria, en un formato compatible
con el tipo de direccionamiento utilizado por la computadora.
Ej.
int i;
printf( "La dirección de esa variable es %p", &i);
El especificador %n guarda en el argumento asociado el número de
caracteres impresos hasta el momento de encontrarse el %n; el argumento
será un puntero a una variable (&<Variable>).
Ej.
int imp;
printf( "Contará los caracteres hasta aquí%n y luego"
"lo comprobamos.", &imp);
printf( "Se han impreso %d caracteres.", imp);
Dentro de un especificador de formato, hemos visto que se puede poner
la anchura del campo, como un número entero que se sitúa entre el % y el
type:
%[flags] [ancho de campo] [precisión] type
Ese número entero especificará la longitud mínima que ocupará el dato
al visualizarse, teniendo en cuenta el punto decimal y los decimales.
Ej.
int i = 100;
printf("i = %6d", i); // Sale i = bbb100; 3 blancos
// ya que la longitud mínima es 6.
Si la longitud del dato es mayor que la especificada en el formato, se
11
visualiza todo el dato, no se tiene en cuenta esa longitud mínima.
Si en lugar de rellenar con blancos, se desea rellenar con ceros, se
coloca un 0 entre el % y el entero que indica la longitud:
Ej.
int i = 100;
printf( "i = %05d", i);
// Sale i = 00100;
Dentro de un especificador de formato, se puede poner la precisión:
%[flags] [ancho de campo] [precisión] type
Se coloca entre el % y el type, después del ancho del campo si existe,
con la forma .número, o sea un punto seguido de un número entero. Ese
entero indica la precisión, es decir el número de decimales a visualizar,
completando con ceros por la derecha si es necesario, o truncando los
decimales si no caben en la precisión indicada (redondeando al valor más
cercano).
Ej.
float num = 100.18;
printf("Número = %f", num);
//Sale: f = 100.180000
printf("Número = %7.1f",num); //Sale: f = bbbb100.2
printf("Número = %.3f", num); //Sale: f = 100.180
Si se usa con cadenas (%s), la precisión indicará la longitud máxima que
se visualizará; la longitud mínima viene dada por el ancho de campo indicado.
“%8.10s”
Escribe la cadena de 8 a 10 caracteres.
Si no se especifica la precisión se toma una por defecto que es:
- para tipos f, e y E son 6 dígitos decimales.
- para tipos g y G son todos los dígitos significativos.
Si se pone precisión .0 se redondea al entero más cercano.
Veamos las banderas o flags:
%[flags] [ancho de campo] [precisión] type
Flag
+
b
Significado
Justifica a la izquierda, inserta blancos a dcha.
Visualiza el signo +/Un blanco hace que sólo visualice el signo
negativo, y en lugar del positivo sale un blanco
12
Ej.
printf ("|%-15s|", "hola"); //Sale |holabbbbbbbbbbb|
printf ("|%15s|", "hola"); //Sale |bbbbbbbbbbbhola|
Existen las secuencias de backslash (o secuencias de escape) para
realizar operaciones de control que pueden ser ejecutadas con printf como
otros caracteres. Estas secuencias son:
Secuencia
\a
\b
\f
\n
\r
\t
\v
\\
\'
\"
\0
\ddd
\xdd
Significado
Sonido
Espacio atrás (backspace)
Salto de página (sólo impresora)
Salto de línea
Retorno de carro
Tabulación horizontal
Tabulación vertical (sólo impresoras)
Barra invertida
Comilla simple
Comilla doble
Nulo
Tres dígitos que son la rep.octal del
carácter ASCII a visualizar.
Una 'x' más dos dígitos que son la
rep.hexadec. del carácter ASCII.
13
EJERCICIOS - CAPITULO 4:
Realizar los siguientes algoritmos en pseudocódigo y en C.
1. Introducir 2 números reales y visualizar la suma, la resta, el producto, la
división y el resto de la división entera. Sólo deben visualizarse 2 decimales.
2. Introducir nombre, edad, sueldo y teléfono para 5 personas. Después deben
visualizarse todos los datos tecleados, sacando una persona en cada fila. El
sueldo tendrá 2 decimales.
3. Introducir un capital y un porcentaje de interés tres veces. Visualizar a
continuación los 3 capitales, sus 3 porcentajes de interés, el interés que
produce cada capital y la suma de cada capital con su interés producido. Al
final debe visualizarse también el total de las tres sumas calculadas. Todas
las cantidades tendrán 2 decimales.
Notas:
 La función gotoxy(columna, fila) coloca el cursor en la columna (de 1 a 80,
izquierda a derecha) y fila (de 1 a 25, arriba a abajo) indicada de la pantalla.

La función clrscr() borra la pantalla completa.
14
Descargar