8.Entrada y salida estándar.

8.1. Introducción.

8.2.Salida con formato (printf()).

8.3.Entrada con formato (scanf()).

8.4.Macros de entrada/salida de caracteres.


8.5.Lectura y escritura de cadenas.

8.6.Ejemplos de printf().

8.7.Ejemplos de scanf().

8.8.Ejemplos entrada/salida de caracteres.

8.9.Ejercicios.




8.1. Introducción.

A diferencia de otros lenguajes, C no dispone de sentencias de entrada/salida. En su lugar se utilizan funciones contenidas en la librería estándar y que forman parte integrante del lenguaje.

Las funciones de entrada/salida (Input/Output) son un conjunto de funciones, incluidas con el compilador, que permiten a un programa recibir y enviar datos al exterior.

Trabajan con el dispositivo estándar de E/S, que es la consola: el teclado para entradas y el monitor para salidas. En realidad las E/S están asociadas a tres ficheros:

  • Fichero estándar de entrada stdin asociado al teclado.
  • Fichero estándar de salida stdout asociado al monitor.
  • Fichero estándar de error stderr asociado también al monitor.

Para su utilización es necesario incluir, al comienzo del programa, el archivo stdio.h en el que están definidos sus prototipos:


#include <stdio.h>


Donde stdio proviene de standard-input-output.

8.2.Salida con formato (printf()).

La función printf() imprime en la unidad de salida (el monitor, por defecto), el texto, y las constantes y variables que se indiquen. La forma general de esta función se puede estudiar viendo su prototipo:


int printf ("cadena_de_control", arg1, arg2, ...)


La función printf() imprime el texto contenido en cadena_de_control junto con el valor de los otros argumentos, de acuerdo con los formatos incluidos en cadena_de_control. Los puntos suspensivos (...) indican que puede haber un número variable de argumentos. Cada formato comienza con el carácter (%) y termina con un carácter de conversión. Considérese el ejemplo siguiente:


...

int i;

double tiempo;

float masa;

printf("Resultado nº: %d. En el instante %lf la masa vale %f\n",i, tiempo, masa);

...



En el que se imprimen tres variables (i, tiempo y masa) con los formatos (%d, %lf y %f), correspondientes a los tipos (int, double y float), respectivamente. La cadena de control se imprime con el valor de cada variable intercalado en el lugar del formato correspondiente.

Especificadores de formato:

%d
Enteros con signo (int)
%u
Enteros sin signo (unsigned int)
%o
Enteros sin signo en octal (unsigned int)
%x
Enteros sin signo en hexadecimal (unsigned int) con caracteres 0...f .
%X
Enteros sin signo en hexadecimal (unsigned int) con caracteres 0...F .
%f
Real (float, double) en formato [-]ddd.ddd
%e
Real (float, double) en formato [-]ddd.ddde[+/-]ddd
%E

Real (float, double) en formato [-]ddd.dddE[+/-]ddd

%g
Real (float, double) %f o %e el que sea más corto.
%G
Real (float, double) %f o %E el que sea más corto.
%c
Carácter (char)
%s
Cadena de caracteres

%p

Puntero

Lo importante es considerar que debe haber correspondencia uno a uno entre los formatos que aparecen en la cadena_de_control y los otros argumentos (constantes, variables o expresiones).

Entre el carácter % y el carácter de conversión puede haber, por el siguiente orden, uno o varios de los elementos que a continuación se indican:


% [flags] [anchura] [.precisión] [prefijo_tipo] formato


Las opciones más usuales son las siguientes (Hay más):

  • flags: permite cambiar la justificación de la representación y actuar o no sobre la presentación del signo.
    • Un signo (-), que indica alineamiento por la izquierda (el defecto es por la dcha).
    • El signo (+) antepone el signo al número.
    • Un cero (0) completa el número, con ceros a la izquierda hasta el ancho total.
    • Un espacio en blanco pone un espacio al principio si el número es positivo.
  • anchura: permite fijar el número de posiciones que se reservarán en pantalla para la presentación del dato de salida.
  • .precisión: depende de el dato representado:
    • En los números enteros determina el número de dígitos mínimos de la representación.
    • En una cadena de caracteres, el nº máximo de caracteres a imprimir.
    • En reales el nº de decimales.
  • prefijo_tipo: es un cualificador del tipo a representar.
    • una h para short.
    • una l para long en enteros o double en los reales.
    • una L para long double.
  • formato: es un campo obligatorio que especifica el tipo de dato según la tabla anterior.

Además de lo anterior se pueden utilizar secuencias especiales (secuencias de escape) para representar códigos ASCII sin representación simbólica. Los más utilizados son:

\a
Alarma
\’
Comilla simple
\b
Espacio atrás
\”
Comilla doble
\f
Salto de página
\\
Barra invertida
\n
Nueva línea
\00
Carácter ASCII en octal
\r
Retorno de carro
\xHH
Carácter ASCII en hexadecimal
\t
Tabulador horizontal
\0
Carácter nulo

A continuación se incluyen algunos ejemplos de uso de la función printf(). El primer ejemplo contiene sólo texto, por lo que basta con considerar la cadena_de_control.


printf("Con cien cañones por”

“ banda,\nviento en popa a toda” “ vela,\n");



El resultado serán dos líneas con las dos primeras estrofas de la famosa poesía. No es posible partir cadena_de_control en varias líneas con caracteres intro, por lo que en este ejemplo se observa que se ha cortado la cadena con comillas dobles (“). Una forma alternativa, muy sencilla, clara y ordenada, de escribir la poesía sería la siguiente:


printf("%s\n%s\n%s\n%s\n",

"Con cien cañones por banda,",

"viento en popa a toda vela,",

"no cruza el mar sino vuela,",

"un velero bergantín.");



En este caso se están escribiendo cuatro cadenas constantes de caracteres que se introducen como argumentos, con formato %s y con los correspondientes saltos de línea.

Un ejemplo que contiene una constante y una variable como argumentos es el siguiente:


printf("En el año %s ganó %ld ptas.\n", "1993", beneficios);


Donde el texto 1993 se imprime como cadena de caracteres (%s), mientras que beneficios se imprime con formato de variable long (%ld).

Con el siguiente ejemplo se puede apreciar el efecto que producen los modificadores del formato:


printf("/%010.2f/\n", 1.234560e+003);


La salida en este caso sería:


/0001234.56/


Es importante hacer corresponder bien los formatos con el tipo de los argumentos, pues si no los resultados pueden ser muy diferentes de lo esperado.

La función printf() tiene un valor de retorno de tipo int, que representa el número de caracteres escritos en esa llamada.

8.3.Entrada con formato (scanf()).

La función scanf() es análoga en muchos aspectos a printf(), y se utiliza para leer datos de la entrada estándar (que por defecto es el teclado). La forma general de esta función es la siguiente:


int scanf("%x1%x2...", &arg1, &arg2, ...);


Donde x1, x2, ... son los caracteres de conversión, mostrados en la tabla siguiente, que representan los formatos con los que se espera encontrar los datos.

%d o %i
Enteros con signo en decimal (int)
%u
Enteros sin signo en decimal (unsigned int)
%o
Enteros sin signo en octal (unsigned int)
%x o %X
Enteros sin signo en hexadecimal (unsigned int) 0-f
%f,%e, %E, %g, %G
Real (float, double)
%c
Carácter (char)
%s
Cadena de caracteres
h, l
Modificador para short, long y double
L
modificador para long double

La función scanf() devuelve como valor de retorno el número de conversiones de formato realizadas con éxito.

La cadena de control de scanf() puede contener caracteres además de formatos. Dichos caracteres se utilizan para tratar de detectar la presencia de caracteres idénticos en la entrada por teclado. Si lo que se desea es leer variables numéricas, esta posibilidad tiene escaso interés.

En la función scanf() los argumentos que siguen a la cadena_de_control deben ser pasados por referencia, ya que la función los lee y tiene que trasmitirlos al programa que la ha llamado. Para ello, dichos argumentos deben estar constituidos por las direcciones de las variables en las que hay que depositar los datos, y no por las propias variables. Una excepción son las cadenas de caracteres, cuyo nombre es ya de por sí una dirección (un puntero), y por tanto no debe ir precedido por el operador (&) en la llamada.

Por ejemplo, para leer los valores de dos variables int y double y de una cadena de caracteres, se utilizarían la sentencia:


int n;

double distancia;

char nombre[20];

scanf("%d%lf%s", &n, &distancia, nombre);



En la que se establece una correspondencia entre n y %d, entre distancia y %lf, y entre nombre y %s. Obsérvese que nombre no va precedido por el operador (&). La lectura de cadenas de caracteres se detiene en cuanto se encuentra un espacio en blanco, por lo que para leer una línea completa con varias palabras hay que utilizar otras técnicas diferentes.

En los formatos de la cadena de control de scanf() pueden introducirse corchetes [...], que se utilizan como sigue.


scanf("%[AB \t]", s); /* se leen solo los caracteres indicados*/


Lee caracteres hasta que encuentra uno diferente de (’A’,’B’,’ ’,’\t’). En otras palabras, se leen sólo los caracteres que aparecen en el corchete. Cuando se encuentra un carácter distinto de éstos se detiene la lectura y se devuelve el control al programa que llamó a scanf().

Si los corchetes contienen un carácter (^), se leen todos los caracteres distintos de los caracteres que se encuentran dentro de los corchetes a continuación del (^). Por ejemplo:


scanf(" %[^\n]", s);


Lee todos los caracteres que encuentra hasta que llega al carácter nueva línea ’\n’. Esta sentencia puede utilizarse por tanto para leer líneas completas, con blancos incluidos.

Recuérdese que con el formato %s la lectura se detiene al llegar al primer delimitador (carácter blanco, tabulador o nueva línea).

8.4.Macros de entrada/salida de caracteres.

Una macro representa una sustitución de texto que se realiza antes de la compilación por medio del preprocesador. Para casi todos los efectos, estas macros pueden ser consideradas como funciones. Más adelante se explicarán las macros con algunos ejemplos.

Las macros getchar() y putchar() permiten respectivamente leer e imprimir un sólo carácter cada vez, en la entrada o en la salida estándar.

La macro getchar() recoge un carácter introducido por teclado y lo deja disponible como valor de retorno. La macro putchar() escribe en la pantalla el carácter que se le pasa como argumento.


/*Escribe el carácter a.*/

putchar(’a’);

/*Equivale a: printf("a");*/


/*Lee un carácter del teclado*/

c = getchar();

/*Equivale a: scanf("%c", &c);*/



Estas macros están definidas en el fichero stdio.h, y su código es sustituido en el programa por el preprocesador antes de la compilación.

Por ejemplo, se puede leer una línea de texto completa utilizando getchar():


...

int i=0, c;

char name[100];

while((c = getchar()) != ’\n’) /* se leen caracteres hasta el ’\n’*/

name[i++] = c; /* se almacena elcarácter en Name[]*/

name[i]='\0'; /* se añade el carácter fin de cadena*/

...



8.5.Lectura y escritura de cadenas.

Una cadena de caracteres es una secuencia de caracteres delimitada por comillas ("), como por ejemplo: "Esto es una cadena de caracteres".

Dentro de la cadena, pueden aparecer caracteres en blanco y se pueden emplear las mismas secuencias de escape válidas para las constantes carácter. Por ejemplo, las comillas (") deben estar precedidas por (\), para no ser interpretadas como fin de la cadena; también la propia barra invertida (\).

8.5.1.Lectura de cadenas.

Con la función scanf() es posible leer cadenas con el especificador de formato %s, con la particularidad de que la función leerá todos los caracteres hasta el primer carácter separador (espacio, tabulador o INTRO). La expresión sería:


scanf(“%s”,cadena);


CUIDADO leerá todos los caracteres hasta el primer espacio, que no es leído y se quedará en stdin, y será leído por la siguiente llamada a scanf().

Más apropiada para la lectura de cadenas es la función gets(), que lee del teclado caracteres hasta la pulsación de la tecla INTRO y los almacena en el array de caracteres cuyo nombre se pasa como argumento, sustituyendo el INTRO por ‘\0’. Se utiliza normalmente de la siguiente forma:


gets(nombre_de_la_cadena);


No se hace ninguna comprobación de desbordamiento del búfer, por lo que hay que tener la precaución de que el tamaño de la cadena sea suficiente para contener los datos, más el carácter nulo del final.

8.5.2.Escritura de cadenas.

La función printf() permite la escritura de cadenas de caracteres por distintos métodos:

Puede incluir la cadena entre comillas dobles como cadena de control:


printf(“\nEsto es una cadena mostrada con printf().”);


Mediante el especificador de formato %s y una constante:


printf(“%s”, “\nesto tambien está mostrado por printf()”);


Mediante el especificador %s y un nombre de variable:


char mensa[]=”\Otro más con printf()”;

printf(“%s”,mensa);



No obstante es más apropiado utilizar la función puts() que recibe como argumento el nombre del array y muestra en pantalla todos los elementos de la cadena, cambiando el carácter nulo de terminación de la cadena por ‘\n’. Se utiliza de la forma siguiente:


puts(nombre_de_la_cadena);

puts(“\nEsto también funciona”);


8.6.Ejemplos de printf().


/* imprime.c -- ejemplo de especificadores de conversión */

#include <stdio.h>

#define PI 3.141593

int main(void)

{

int numero = 5;

float ron = 13.5;

int coste = 3100;

printf("Las %d mujeres se bebieron %f vasos de ron.\n",numero, ron);

printf("El valor de pi es %f.\n", PI);

printf("Fazer non quiso que tal malandrín fablara.\n");

printf("%c%d\n",'$', 2 * coste);

return 0;

}




/* anchura.c -- anchuras de los campos */

#include <stdio.h>

#define PAGINAS 336

int main(void)

{

printf("/%d/\n", PAGINAS);

printf("/%2d/\n", PAGINAS);

printf("/%10d/\n", PAGINAS);

printf("/%-10d/\n", PAGINAS);

return 0;

}


La salida será:


/336/

/336/

/ 336/

/336 /




/* flotante.c -- combinaciones de punto flotante */

#include <stdio.h>

#define RENTA 1234.56

int main(void)

{

printf("/%f/\n", RENTA);

printf("/%e/\n", RENTA);

printf("/%4.2f/\n", RENTA);

printf("/%3.1f/\n", RENTA);

printf("/%10.3f/\n", RENTA);

printf("/%10.3e/\n", RENTA);

printf("/%+4.2f/\n", RENTA);

printf("/%010.2f/\n", RENTA);

return 0;

}


La salida es:


/1234.560000/

/1.234560e+03/

/1234.56/

/1234.6/

/ 1234.560/

/ 1.235e+03/

/+1234.56/

/0001234.56/



/* simbolos.c -- estudia controles de formatos */

#include <stdio.h>

int main(void)

{

printf("%x %X %#x\n", 31, 31, 31);

printf("**%d**% d**% d**\n", 42, 42, -42);

printf("**%5d**%5.3d**%05d**%05.3d**\n", 6, 6, 6, 6);

return 0;

}


El resultado es:


1f 1F 0x1f

**42** 42**-42**

** 6** 006**00006** 006**



/* tiras.c -- formatos de tiras */

#include <stdio.h>

#define PINTA "¡Alucinante acción!"

int main(void)

{

printf("/%2s/\n", PINTA);

printf("/%22s/\n", PINTA);

printf("/%22.5s/\n", PINTA);

printf("/%-22.5s/\n", PINTA);

return 0;

}


El resultado será:


/¡Alucinante acción!/

/ ¡Alucinante acción!/

/ ¡Alu/

/¡Alu /



/* prntval.c -- valor de retorno de printf() */

#include <stdio.h>

int main(void)

{

int n = 100;

int rv;

rv = printf("El punto de ebullición del agua es %d grados.\n", n);

printf("La función printf() ha impreso %d caracteres.\n", rv);

return 0;

}


La salida será:


El punto de ebullición del agua es 100 grados.

La función printf() ha impreso 48 caracteres.



/* largo.c -- impresión de tiras largas */

#include <stdio.h>

int main(void)

{

printf("Una forma de imprimir una ");

printf("tira larga.\n");

printf("Otra forma de imprimir una \

tira larga.\n");

printf("La nueva forma de imprimir una"

" tira larga.\n");/* ANSI C */

return 0;

}


El resultado será:


Una forma de imprimir una tira larga.

Otra forma de imprimir una tira larga.

La nueva forma de imprimir una tira larga.




/* secretos.c -- programa informativo totalmente inútil */

#include <stdio.h>

#define DENSIDAD 0.97 /* densidad del hombre en kg por litro */

int main(void)

{

float peso, volumen;

int sitio, letras;

char nombre[40];

printf("¡Hola! ¿Cómo te llamas?\n");

scanf("%s", nombre);

printf("%s, ¿cuál es tu peso en kg?\n", nombre);

scanf("%f", &peso);

sitio = sizeof nombre;

letras = strlen(nombre);

volumen = peso/DENSIDAD;

printf("Bien, %s, tu volumen es %2.2f litros.\n", nombre, volumen);

printf("Además, tu nombre tiene %d letras,\n", letras);

printf("y disponemos de %d bytes para guardarlo.\n", sitio);

return 0;

}



/* elogio2.c */

#include <stdio.h>

#define ELOGIO "¡Por Júpiter, qué gran nombre!"

int main(void)

{

char nombre[50];

printf("¿Cómo te llamas?\n");

scanf("%s", nombre);

printf("Hola, %s. %s\n", nombre, ELOGIO);

printf("Tu nombre de %d letras ocupa %d celdas de memoria.\n",

strlen(nombre), sizeof nombre);

printf("La frase de elogio tiene %d letras ", strlen(ELOGIO));

printf("y ocupa %d celdas de memoria.\n", sizeof ELOGIO);

return 0;

}



8.7.Ejemplos de scanf().


/* entradas.c -- cuándo se debe usar & */

#include <stdio.h>

int main(void)

{

int edad;

float sueldo;

char cachorro[30]; /* tira de caracteres */

printf("Confiese su edad, sueldo y mascota favorita.\n");

scanf("%d %f", &edad, &sueldo); /* use & aquí */

scanf("%s", cachorro); /* en cadena de caracteres no se usa & */

printf("Edad: %d, Sueldo: %.0f euros, Mascota: %s\n ",

edad, sueldo, cachorro);

return 0;

}



El resultado será:


Confiese su edad, sueldo y mascota favorita.

98

800 Gallipato

Edad: 98, Sueldo: 800 euros, Mascota: Gallipato




/* salta2.c -- salta los dos primeros enteros de la entrada */

#include <stdio.h>

int main(void)

{

int n;

printf("Introduzca tres enteros:\n");

scanf("%*d %*d %d", &n); //El asterisco significa siguiente

printf("El último entero leído es %d\n", n);

return 0;

}


La salida será:


Introduzca tres enteros:

25 45 22

El último entero leído es 22




IMPORTANTE

Los caracteres no leídos se quedan en el Buffer y pueden producir falsas lecturas. Para limpiar el Buffer utilizar fflush(stdin) o while(getchar()!='\n');



8.8.Ejemplos entrada/salida de caracteres.


/* cifrado1.c -- modifica la entrada conservando los espacios */

#include <stdio.h>

#define ESPACIO ' ' /* apóstrofo espacio apóstrofo */

int main(void)

{

char ch;

ch = getchar(); /* lee un carácter */

while (ch != '\n') /* mientras no sea fin de línea */

{

if (ch == ESPACIO) /* deja carácter espacio */

putchar(ch); /* sin modificar */

else

putchar(ch + 1); /* cambia los demás caracteres */

ch = getchar(); /* toma siguiente carácter */

}

return 0;

}


Resultado:


LLAMAME HAL

MMBNBNF IBM




/* cifrado2.c -- modifica la entrada conservado los espacios */

/* CON UN ESTILO MÁS “C” */

#include <stdio.h>

#define ESPACIO ' ' /* apóstrofo espacio apóstrofo */

int main(void)

{

char ch;

while ((ch = getchar()) != '\n')

{

if (ch == ESPACIO) /* deja carácter espacio */

putchar(ch); /* sin modificar */

else

putchar(ch + 1); /* cambia los demás caracteres */

}

return 0;

}




/* nombre1.c -- lee un nombre */

#include <stdio.h>

#define MAX 80

int main(void)

{

char nombre[81]; /* reserva espacio */

printf("Hola, ¿cómo te llamas?\n");

gets(nombre); /* introduce entrada en tira "nombre" */

printf("Bonito nombre, %s.\n", nombre);

return 0;

}



/* nombre2.c -- lee un nombre */

/*Otra manera de usar getchar*/

#include <stdio.h>

#define MAX 81

int main(void)

{

char nombre[MAX];

char *ptr; //char *gets(char *)

printf("Hola, ¿cómo te llamas?\n");

ptr = gets(nombre);

printf("¿%s? ¡Ah! ¡%s!\n", nombre, ptr);

return 0;

}


8.9.Ejercicios.

a) Elabora un programa que convierta de pesetas a euros y viceversa, mediante un menú que disponga de la opción salir.

b) Realiza un programa que imprima el calendario de un mes, pidiendo el día de la semana de comienzo y el nombre del mes en cuestión.

c) Elabora un programa que lea un carácter del teclado y muestre en pantalla el valor numérico de su código ASCII en decimal y en hexadecimal.

d) Crea un programa que lea una cadena del teclado y a continuación la presente en pantalla.

e)Realiza un programa que presente la tabla de caracteres ASCII con su equivalente decimal. Procura que la tabla quede ordenada.

f)Diseña un programa que tome tres palabras del teclado y luego las imprima separadas por guiones.

Last modified: Monday, 7 June 2010, 11:02 AM