Análisis y Diseño de
Algoritmos
Prof: Ing.
Victor Garro
Asistente:
Marco Elizondo Vargas
PROGRAMACION
EN C++
CAPITULO 3 Entradas
y SALIDAS
Entrada y Salida en C
La
biblioteca STDIO.H
Es la librería
estándar del lenguaje de programación C el archivo de cabecera que contiene las
definiciones de macros, las constantes, las declaraciones de funciones y la
definición de tipos usados por varias operaciones estándar de entrada y salida.
Por motivos de compatibilidad, el lenguaje de programación C++ (derivado de C)
también tiene su propia implementación de estas funciones, que son declaradas
con el archivo de cabecera cstdio.
Las funciones
declaradas en stdio.h
son sumamente populares.
Printf:
Imprimir en pantalla
Para utilizar la función printf
en nuestros programas debemos incluir la directiva:
#include
<stdio.h>
Si sólo queremos imprimir una
cadena basta con escribir la siguiente línea de código.
printf(
"Cadena" );
Como resultado muestra en pantalla:
Cadena
Lo que pongamos entre las
comillas es lo que vamos a sacar por pantalla.
Si volvemos a usar otro printf, por ejemplo:
#include <stdio.h>
void main()
{
printf(
"Cadena" );
printf(
"Segunda" );
}
Obtendremos:
CadenaSegunda
Este ejemplo nos muestra cómo
funciona printf. Para escribir en la pantalla se usa
un cursor que no vemos. Cuando escribimos algo el cursor va al final del texto.
Cuando el texto llega al final de la fila, lo siguiente que pongamos irá a la
fila siguiente. Si lo que queremos es sacar cada una en una línea deberemos
usar "\n". Es el indicador de retorno de carro. Lo que hace es saltar
el cursor de escritura a la línea siguiente:
#include <stdio.h>
void main()
{
printf( "Cadena\n" );
printf( "Segunda" );
}
y tendremos:
Cadena
Segunda
También podemos poner más
de una cadena dentro del printf:
printf(
"Primera cadena" "Segunda cadena" );
Lo que no podemos hacer es
meter cosas entre las cadenas:
printf(
"Primera cadena" texto en medio "Segunda cadena" );
esto no es válido. Cuando el
compilador intenta interpretar esta sentencia se encuentra "Primera
cadena" y luego texto en medio, no sabe qué hacer con ello y da
un error.
Pero ¿qué pasa si queremos
imprimir el símbolo " en pantalla? Por ejemplo imaginemos que
queremos escribir:
Esto es "extraño"
Si para ello hacemos:
printf(
"Esto es "extraño"" );
obtendremos unos cuantos
errores. El problema es que el símbolo " se usa para indicar al
compilador el comienzo o el final de una cadena. Así que en realidad le
estaríamos dando la cadena "Esto es", luego extraño y
luego otra cadena vacía "". Pues resulta que printf no admite esto y de nuevo tenemos errores.
La solución es usar \".
Veamos:
printf(
"Esto es \"extraño\"" );
Esta vez todo irá como la
seda. Como vemos la contrabarra '\' sirve para
indicarle al compilador que escriba caracteres que de otra forma no podríamos.
Esta contrabarra
se usa en C para indicar al compilador que queremos meter símbolos especiales. Pero ¿Y si lo que
queremos es usar '\' como un carácter normal y poner por ejemplo Hola\Adiós? Pues muy fácil, volvemos a usar '\':
printf(
"Hola\\Adiós" );
y esta doble '\' indica
a C que lo que queremos es mostrar una '\'.
Algo muy
usual en un programa es esperar que el usuario introduzca datos por el teclado.
Para ello contamos con varias posibilidades: Usar las funciones de la
biblioteca estándar, crear nuestras propias interrupciones de teclado (MS-Dos) o usar funciones de alguna
biblioteca diferente (como por ejemplo Allegro).
En este trabajo topare solo la primera
opción, usando las funciones de la biblioteca estándar. Pero veamos por encima
las otras posibilidades.
Las funciones estándar están
bien para un programa sencillito. Pero cuando queremos hacer juegos por ejemplo, no suelen ser
suficiente. Demasiado lentas o no nos dan todas las posibilidades que buscamos,
como comprobar si hay varias teclas pulsadas. Para solucionar esto tenemos dos
posibilidades:
La más complicada es crear
nuestras propias interrupciones de teclado. ¿Qué es una interrupción de
teclado? Es un pequeño programa en memoria que se ejecuta continuamente
y comprueba el estado del teclado. Podemos crear
uno nuestro y hacer que el ordenador use el que hemos creado en vez del suyo.
Otra posibilidad más sencilla
es usar una biblioteca que tenga funciones para controlar el teclado. Por
ejemplo si usamos la biblioteca Allegro, ella misma hace todo el trabajo y nosotros no tenemos más que
recoger sus frutos con un par de sencillas instrucciones. Esto soluciona mucho
el trabajo y nos libra de tener que aprender cómo funcionan los aspectos más
oscuros del control del teclado.
Vamos ahora con las funciones
de la biblioteca estándar antes mencionada.
Scanf
El uso de scanf
es muy similar al de printf con una diferencia, nos
da la posibilidad de que el usuario introduzca datos en vez de mostrarlos. No
nos permite mostrar texto en la pantalla, por eso si queremos mostrar un
mensaje usamos un printf delante. Un ejemplo:
#include
<stdio.h>
void
main()
{
int num;
printf(
"Introduce un número " );
scanf( "%i", &num );
printf( "Has tecleado el número
%i\n", num );
}
Primero vamos a ver unas nota
de estética, para hacer los programas un
poco más elegantes. Parece una tontería, pero los pequeños detalles hacen que
un programa gane mucho. El scanf no mueve el cursor
de su posición actual, así que en nuestro ejemplo queda:
Introduce un número _ /* La
barra horizontal indica dónde esta el cursor */
Esto es porque en el printf no hemos puesto al final el símbolo de salto de
línea '\n'. Además hemos dejado un espacio al final
de Introduce un número: para que así cuando tecleemos el número no salga
pegado al mensaje. Si no hubiésemos dejado el espacio quedaría así al
introducir el número 120 (es un ejemplo):
Introduce un número120
Veamos cómo funciona el scanf. Lo primero nos fijamos que hay una cadena entre
comillas. Esta es similar a la de printf, nos sirve
para indicarle al compilador qué tipo de datos estamos pidiendo. Como en este
caso es un integer usamos %i. Después de la coma
tenemos la variable donde almacenamos el dato, en este caso 'num'.
Fíjate que en el scanf la variable 'num' lleva
delante el símbolo &, este es muy importante, sirve para indicar al
compilador cual es la dirección (o posición en la memoria) de la variable.
Podemos preguntar por más de
una variable a la vez en un sólo scanf, hay que poner
un %i por cada variable:
#include <stdio.h>
void main()
{
int
a, b, c;
printf(
"Introduce tres números: " );
scanf(
"%i %i %i", &a, &b, &c );
printf(
"Has tecleado los números %i %i %i\n", a,
b, c );
}
De esta forma cuando el
usuario ejecuta el programa debe introducir los tres datos separados por un
espacio.
También podemos pedir en un
mismo scanf variables de distinto tipo:
#include <stdio.h>
void main()
{
int a;
float b;
printf( "Introduce dos números: " );
scanf( "%i %f", &a, &b );
printf( "Has tecleado los números %i
%f\n", a, b );
}
A cada modificador (%i, %f)
le debe corresponder una variable de su mismo tipo. Es decir, al poner un %i el
compilador espera que su variable correspondiente sea de tipo int. Si ponemos %f
espera una variable tipo float.
Si lo que queremos es que el
usuario introduzca un carácter por el teclado usamos las funciones getch y getche.
Estas esperan a que el usuario introduzca un carácter por el teclado. La
diferencia entre getche y getch
es que la primera saca por pantalla la tecla que hemos pulsado y la segunda no
(la e del final se refiere a echo=eco). Ejemplos:
#include
<stdio.h>
void
main()
{
char
letra;
printf(
"Introduce una letra: " );
fflush(
stdout );
letra = getche();
printf(
"\nHas introducido la letra: %c", letra );
}
Resultado:
Introduce una letra: a
Has introducido la letra: a
¿Qué es el fflush(
stdout )?. Pues bien, cuando usamos la función printf, no escribimos directamente en la pantalla, sino en
una memoria intermedia (lo que llaman un bufer).
Cuando este bufer se llena o cuando metemos un
carácter '\n' es cuando se envía el texto a la
pantalla. En este ejemplo yo quería que apareciera el mensaje Introduce una
letra: y el cursor se quedara justo después, es decir, sin usar '\n'. Si se hace esto, en algunos compiladores el mensaje no se muestra en
pantalla hasta que se pulsa una tecla (probar). Y la función fflush( stdout ) lo que hace es
enviar a la pantalla lo que hay en ese bufer.
Y ahora un ejemplo con getch:
#include <stdio.h>
void main()
{
char
letra;
printf(
"Introduce una letra: " );
fflush(
stdout );
letra = getch();
printf("\n
has introducido la letra :%c", letra );
}
Resultado:
Introduce una letra:
Has introducido la letra: a
Como vemos la única diferencia
es que en el primer ejemplo se muestra en pantalla lo que escribimos y en el
segundo no.
Usos
de printf y scanf |
|
printf("Mensaje"); |
Escribe Mensaje en la
pantalla |
scanf("%d",&Variable); |
Asigna valor entero a
Variable |
Nota
C++ ofrece una alternativa a
las llamadas de funcion printf
y scanf para manejar la entrada/salida de los tipos y
cadenas de datos estandar. Así en lugar de printf usamos el flujo estandar
de salida cout y el operador << ("colocar
en"); y en lugar de scanf usamos el flujo de
entrada estandar cin y el
operador >>("obtener de"). Estos operadores de inserción y
extracción de flujo, a diferencia de printf y scanf, no requieren de cadenas de formato y de formato y de
especificadotes de conversión para indicar los tipos de datos que son extraidos
o introducidos.
Las siguientes funciones nos
resultan indispensable para poder brindar una mejor
presentación de los datos en pantalla.
Gotoxy:
Posicionando el cursor (DOS)
Esta función sólo está
disponible en compiladores de C que dispongan de la biblioteca <conio.h>
Hemos visto que cuando usamos printf se escribe en la posición actual del cursor y
se mueve el cursor al final de la cadena que hemos escrito.
Vale, pero ¿qué pasa cuando
queremos escribir en una posición determinada de la pantalla? La solución está
en la función gotoxy. Supongamos que queremos
escribir 'Hola' en la fila 10, columna 20 de la pantalla:
#include <stdio.h>
#include <conio.h>
void main()
{
gotoxy( 20, 10 );
printf( "Hola" );
}
(Nota: para usar gotoxy hay que incluir la biblioteca conio.h).
Fíjate que primero se pone la
columna (x) y luego la fila (y). La esquina superior izquierda es la posición
(1, 1).
Clrscr:
Borrar la pantalla (DOS)
Ahora ya sólo nos falta saber
cómo se borra la pantalla. Pues es tan fácil como usar:
clrscr()
(clear
screen, borrar pantalla).
Esta función nó solo borra la pantalla, sino que además sitúa el cursor
en la posición (1, 1), en la esquina superior izquierda.
#include <stdio.h>
#include <conio.h>
void main()
{
clrscr();
printf( "Hola" );
}
Este método sólo vale para compiladores
que incluyan el fichero stdio.h.
Entrada y Salida en C++
3.1
La biblioteca iostream
C++ proporciona una nueva biblioteca de funciones
que realizan operaciones de E/S: la biblioteca iostream. Esta biblioteca es una implementación
orientada a objetos y está basada, al igual que stdio,
en el concepto de flujos. Cuando se introducen caracteres desde el teclado,
puede pensarse en caracteres que fluyen desde el teclado a las estructuras de
datos del programa. Cuando se escribe en un archivo, se piensa en un flujo de bytes que van del programa al disco.
Para acceder a la biblioteca iostream se debe incluir
el archivo iostream.h. Este archivo contiene
información de diferentes funciones de E/S. Define también los objetos cin y cout.
3.2
Manipuladores de salida
La biblioteca iostream
define varios operadores particulares, llamados manipuladores, que le permiten
controlar precisamente, el formato de los datos visualizados. Situando un
manipulador en la cadena de operadores <<,
se puede modificar el estado del flujo.
Cuando comienza la
ejecución de un programa escrito en C++ se abren de forma automática cuatro
flujos predefinidos:
Para realizar
operaciones de entrada y salida C++ permite utilizar los siguientes operadores,
que se encuentran sobrecargados
· cout << ``Cadena a imprimir por pantalla'' << nombre_variable
· << ``\n'';
De
esta forma se mostrará por pantalla el mensaje que se encuentra entre comillas,
en la misma línea el valor que tenga en ese momento nombre_variable
y a continuación un retorno de carro.
· cin >> variable_entrada;
De
esta forma en la variable de nombre variable_entrada
se almacenará el valor introducido desde teclado. Hay que notar que si se ha
tecleado una cadena de caracteres en variable_entrada
sólo se guardarán aquellos desde el comienzo hasta el primer espacio en blanco.
Una característica importante de un flujo que debe tratar con valores numéricos
es la base de los números. Hay tres manipuladores (dec, hex y oct) para controlar la situación. La base por omisión es 10 y por
tanto sólo será necesario indicar dec cuando se haya
fijado la base a otro valor:
cout <<oct<<x<<endl;
cout <<dec<<x<<endl;
Los manipuladores que toman argumentos se declaran
en iomanip.h, el resto en iostream.h.
Manipuladores |
Aplicación |
Descripción |
dec |
cout<<dec<<x; |
Conversión a decimal |
|
cin>>dec>>x; |
|
hex |
out<<hex<<x; |
conversión a hexadecimal |
|
cin>>hex>>x; |
|
oct |
cout<<oct<<x; |
Conversión a octal |
|
cin>>oct>>x; |
|
ws |
cin>>ws; |
Salta espacios en la entrada |
endl |
cout<<endl; |
Envía carácter fin de línea |
flush |
cout<<flush; |
Limpia el buffer |
setfill(int) |
cout<<setfill('*'; |
Fija el carácter de rellenado |
setprecision(int) |
cout<<setprecision(6); |
Fija la conversión en coma flotante al nº de
dígitos especificado |
setw(int) |
cout<<setw(6)<<x; |
Fija la anchura |
|
cin>>setw(10)>>x; |
|
Con setw() los valores
numéricos se justifican a derechas y los datos carácter a izquierdas.
La información de la justificación de la salida se
almacena en un modelo o patrón de bits de una clase llamada ios,
que constituye la base de todas las clases de flujos. Puede establecer o reinicializar bits específicos utilizando los manipuladores
setiosflags() y resetiosflags() respectivamente.
Para utilizar cualquiera de los indicadores de
formato hay que insertar el manipulador setiosflags()
con el nombre del indicador como argumento. Hay que utilizar resetiosflags() con el mismo argumento para invertir el
estado del formato antes de utilizar el manipulador setiosflags().
Indicador |
Significado
del indicador activado |
ios::left |
Justifica la salida a la izquierda |
ios::right |
Justifica la salida a la derecha |
ios::scientific |
Utiliza notación científica para números de coma
flotante |
ios::fixed |
Utiliza notación decimal para números de coma
flotante |
ios::dec |
Utiliza notación decimal para enteros |
ios::hex |
Utiliza notación hexadecimal
para enteros |
ios::oct |
Utiliza notación octal para enteros |
ios::showpos |
Muestra un signo positivo cuando se visualizan
valores positivos |
IMPORTANTE: C++ permite que se sigan utilizando printf()
y scanf(), sin embargo es más
conveniente la utilización de los operadores definidos porque éstos permiten
operar, además de con todos los tipos de datos que admite C, con objetos.