FUNCIONES DE ENTRADA/SALIDA







Introducción: funciones de entrada/salida con formato de texto
Uno de los formatos de E/S de mayor uso es precisamente el formato de texto. Este formato se caracteriza porque se impone una restricción a los bytes empleados: deben ser caracteres imprimibles, incluyendo ciertos caracteres de control (salto de línea, retorno de carro, etc). El lenguaje C ofrece numerosas funciones con este fin; pasamos a reseñar las funciones de salida o impresion más habituales, que forman parte del archivo de encabezado stdio.h .

Tabla de funciones de impresión o escritura

int printf(const char *fmto, ...) Esta es la ya conocida función de escritura en pantalla. La función printf() , como las demás de su grupo, proporciona el número de caracteres impresos.
int fprintf(FILE *fp, const char *fmto, ...) Esta función en análoga a printf() , con una salvedad: admite como primer argumento un puntero de archivo, y la información impresa no se envía a la pantalla, sino al archivo en cuestión.
int sprintf(char *cad, const char *fmto, ...) Una nueva variante de printf() , que envía sus resultados a la cadena que se le proporciona como primer argumento.
int snprintf(char *cad, size_t tamaño, const char *fmto, ...) Esta función también imprime sus argumentos en una cadena, con una característica adicional: se limita a un máximo de tamaño el número de caracteres impresos, incluyendo el '\0'.

La expresión const char *fmto denota una cadena que se emplea para especificar la conversión aplicada antes de proceder a escribir las variables correspondientes. fmto contiene tres tipos de objetos:
  1. Caracteres normales, que se copian sin variación.
  2. Secuencias de escape, que se convierten en los caracteres de control equivalente y se imprimen.
  3. Especificaciones de formato, que dan lugar a la impresión del argumento correspondiente.


Si sobran especificadores de formato (si hay menos variables que especificadores de formato), entonces se toma como valor numérico el cero, y como valor alfanumérico la cadena nula. Si sobran variables, se reutilizan los especificadores de formato.

Respecto a las secuencias de escape, su lista y significado es como sigue:

\e Escribir un carácter de <escape>.
\a Escribir un carácter de <pitido>.
\b Escribir un carácter de <retroceso>.
\f Escribir un carácter de <salto de página>.
\n Escribir un carácter de <salto de línea>.
\r Escribir un carácter de <retorno de carro>.
\t Escribir un carácter de <tabulador>.
\v Escribir un carácter de <tabulador vertical>.
\' Escribir un carácter de <comillas sencillas>.
\\ Escribir un carácter de barra invertida.
\número Escribir un carácter de 8 bits cuyo valor ASCII es el número octal que (de 1, 2 o 3 dígitos) que se adjunta.

Especificadores de formato. Estas expresiones constan de:
  1. Signo de % , obligatorio.
  2. Indicadores opcionales. Estos indicadores son:
  3. Anchura de campo, opcional. Es una cadena de dígitos que indican la anchura; si sobra espacio, se rellena con blancos salvo indicación en contra.
  4. Precisión, opcional. Es un punto seguido por cero o más dígitos, que indican el número de decimales en formatos reales o la anchura máxima si es una cadena. Si no hay dígitos, se entiende que deseamos precisión cero, sin decimales.
  5. Un carácter, de la serie diouxXfwEgGbcs , que indica el tipo de formato. Los significados de estos caracteres son como sigue:
    Carácter Formato
    d ó i Formato decimal con signo
    o Formato octal sin signo
    u Formato decimal sin signo
    x ó X Formato hexadecimal sin signo
    f Formato de coma flotante. Si no se especifica precisión (q.v.), se muestran seis cifras. Si se indica precisión 0, se muestra únicamente la parte entera del número, sin punto decimal.
    e ó E Formato de coma flotante con notación exponencial (aaa.bbbE±cc). Hay u solo número delante del punto decimal; detrás habrá seis cifras decimales si no se indica precisión. Si se indica precisión 0, no hay cifras decimales ni punto decimal.
    g ó G Formato de coma flotante. Se emplea el formato f o el E, buscando el que propocione la precisión completa en menor espacio.
    b Formato de secuencias de escape expandidas, aplicable sólo a cadenas.
    c Formato de carácter, imprime el primer carácter de una cadena (o un único carácter)
    s Formato de cadena. Se imprimen tantos caracteres como indique la precisión. Si no hay precisión, o es 0, se imprimen todos los caracteres.


Tabla de funciones de entrada o lectura

int scanf (const char *formato, ...) Esta es la función de lectura por excelencia. Su primer argumento es una cadena que contiene especificaciones de conversión; esas especificaciones se aplicarán a los argumentos proporcionados a través de stdin y el resultado se irá almacenando en las variables homólogas señaladas por las direcciones que se aportan como argumentos segundo y siguientes. Los especificadores de conversión se denotan mediante el signo % , que puede ir seguido por uno de los caracteres que se indican en la Tabla de modificadores de conversión, más abajo. Además de estos indicadores, puede existir un campo de longitud máxima, que se expresa como un valor decimal inserto entre el % y el indicador de conversión. Cuando se emplea este indicador de longitud máxima del campo, se descartan los posibles espacios en blanco sin contarlos como parte del mismo.
int fscanf(FILE *flujo, const char *formato, ...) Esta función lee del flujo proporcionado como primer argumento, respetando las mismas convenciones que son de aplicación para la función scanf() .
int sscanf(const char *cad, const char *formato, ...) Esta función lee de la cadena proporcionada como primer argumento, respetando las mismas convenciones que son de aplicación para la función scanf()

Tabla de modificadores de conversión
* Suprime la asignación de esta conversión. La conversión se realiza, pero su resultado se descarta.
h Indica que la conversión siguiente es dioux ó n y que el puntero siguiente señala un short int (no un int ). Se trata, por tanto, de la conversión de un valor numérico de precisión sencilla.
l Indica que la conversión siguiente es dioux ó n y que el puntero siguiente señala un long int , o bien que la conversión va a ser ef ó g y el próximo puntero es de un double (no de un float ). Esto denota la conversión de un valor numérico de doble precisión
q Indica que la conversión siguiente es dioux ó n y que el puntero siguiente señala un quad_t (no un int ). Se trata, por tanto, de la conversión de un valor numérico de precisión cuádruple.
L Indica que la conversión será ef ó g y que el próximo puntero es de un long double . Es una conversión de cuádruple precisión.

Tabla de indicadores de conversión
% Denota precisamente el signo de %. Esto es, la conversión %% se corresponde con un único %; no hay conversión ni se devuelve valor alguno.
d Indica la conversión de un entero (que puede tener signo). El puntero correspondiente tiene que ser de un int .
D Equivale a D./td>
i Denota la conversión de un entero, que puede tener signo. Si el entero empieza por '0x' o '0X', se entiende que está escrito en hexadecimal y se efectúa la conversión en consecuencia. Si empieza por '0' se interpreta en octal, y si empieza por cualquier otro signo se interpreta en base 10. Sólo se utilizan los caracteres que correspondan a la base.
o Indica conversión a octal. El puntero correspondiente debe ser de unsigned int .
O Equivale a io.
u Denota la converesión de un entero decimal que puede tener signo. El puntero asociado debe ser de un unsigned int .
x Indica la conversión de un entero hexadecimal que puede tener signo. El puntero debe ser de un unsigned int .
X Equivale a x.
f Denota la conversión de un número de coma flotante y simple precisión, que podrá tener signo. El puntero asociado debe ser de float .
e Equivale a f .
g Equivale a f .
E Equivale a f .
G Equivale a f .
s Denota una sucesión de caracteres que no sean espacios en blanco. Se descartan los espacios iniciales, si los hay. El puntero asociado debe ser de char, y la variable señalada debe disponer de espacio suficiente para almacenar todos los caracteres leídos, y el carácter NULL final. La lectura se detiene al llegar a un espacio en blanco, o cuando se ha leído el número máximo de caracteres.
c Denota una sucesión de caracteres que no sean espacios en blanco. No se descartan los espacios iniciales; si se desea hacerlo, se antepone un espacio a este formato de conversión. El puntero asociado debe ser de char, y la variable señalada debe disponer de espacio suficiente para almacenar todos los caracteres leídos; no se añade el carácter NULL final. La lectura se detiene al llegar a un espacio en blanco, o cuando se ha leído el número máximo de caracteres. Por defecto, el número máximo de caracteres es 1; si se desea leer otra cantidad de caracteres, es preciso indicarlo.
[ Este carácter, junto con el corchete de cierre, permite especificar el conjunto de caracteres admisibles o inadmisibles para la próxima conversión. Esta especificación seguirá leyendo caracteres, y añadiéndolos a la cadena correspondiente (que debe disponer de espacio suficiente) hasta llegar a un carácter queno esté admitido. Los caracteres admitidos se pueden especificar individualmente (como en [abc] , que admite únicamente los caracteres a , b o c y se detiene en cuanto llega a uno que no pertenece a este grupo), y también se pueden admitir grupos de caracteres, separando el principio final del rupo mediante un guión (como en [a-z] , que admite todas las minúsculas sin signos diacríticos, y se detiene en cuanto llega a un carácter que no pertenezca a este grupo). Si se desea prohibir uno o más caracters, es preciso anteponer el signo de acento circunflejo ("^"). Por ejemplo, la especificación [^abc] admite cualquier carácter que no sea a , b ni c , y se detiene en cuanto llega a una a , b o c . Si se desea no admitir el guión específicamente, deberá colocarse en último lugar, al final de la lista de caracteres prohibidos, como en [^abc-] , que admitiría cualquier carácter menos a , b , c o - , y se detendrá en cuanto encuentre uno de ellos. Por ejemplo, la expresión [^*] denota que debe aceptarse cualquier carácter menos un asterisco; esto será útil en el tratamiento de archivos delimitados, pues permite leer un campo y se detiene al llegar al asterisco. Si el delimitador es un tabulador, emplearemos [^\t] , etc. El puntero correspondiente debe ser de char , y la variable señalada deberá disponer, insistimos, de espacio suficiente para almacenar todos los caracteres leídos. El conjunto de caracters admitidos recibe el nombre de scanset . Véase también la función strtok() .
p Denota conversión a puntero. El puntero asociado debe ser un puntero de void .
n Esto no es una conversión, pues se limita a escribir el número de caracters leídos hasta el momento en la variable señalada por el puntero asociado, que debe ser un puntero de int .


Ejercicios propuestos



  1. Ejercicio 0501r01.- Se dispone de tres números enteros con signo, a, b y c. Se pide construir un programa que a, b y c de teclado, y que después muestre una tabla formada por tres columnas y diez filas. La primera columna será el producto de a por el índice de fila, escrito en un total de doce columnas y con signo antepuesto. La segunda será el número b más el índice de fila, escrito en ocho columnas y ajustado a la izquierda. La tercera columna será el índice de fila, escrito en quince columnas y con relleno formado por ceros.

  2. Ejercicio 0501r02.- Se dispone de tres números float llamados a, b y c. Se pide construir un programa que lea los tres números del teclado y muestre en pantalla una tabla de tres filas por diez columnas. La primera columna tomará el valor del primer número elevado al cubo por el índice de fila, con un formato de doce columnas y seis decimales (sin exponentes). La segunda columna será el logaritmo natural del número por el índice de fila, con tres decimales en diez columnas. La tercera columna será el número por el índice de fila, en formato exponencial y nueve columnas, ajustado a la izquierda.

  3. Ejercicio 0501r03.- Se dispone de una tabla de float , de formato MxN siendo M y N constantes conocidas. Se pide construir una función adecuada para mostrar en pantalla la tabla con formato de columnas. Las columnas tendrán relleno de ceros. Las columnas pares (0, 2, 4, ...) tienen quince caracteres de anchura y están ajustadas a la derecha. Las columnas impares (1, 3, 5, ...) tienen diez columnas de anchura y están ajustadas a la izquierda.

  4. Ejercicio 0501r04.- Se dispone de una tabla de precios de artículos, de formato float , formada por números desconocidos a priori de filas y columnas. Se pide construir una función capaz de mostrar la tabla con formato encolumnado, independientemente del número de filas y columnas. Las columnas estarán alineadas a la izquierda, y tendrán diez caracteres de anchura con tres decimales.

  5. Ejercicio 0501r05.- Se dispone de una lista de artículos formada por registros de cuatro campos: Se pide construir un programa capaz de mostrar en pantalla informes en columna. Los informes se crearán por cualquiera de los campos.

  6. Ejercicio 0501r06.- Se dispone de una tabla de datos experimentales en formato double . La tabla posee M filas por N columnas. Se pide mostrar la tabla con formato de columnas, empleando diez caracteres de anchura para cada columna. Los datos se mostrarán ajustados a la derecha y con la notación científica habitual. El programa deberá mostrar, además, los valores máximo y mínimo de cada columna.

  7. Ejercicio 0501r07.- Se dispone de una lista de palabras almacenadas en una lista de cadenas. Se pide escribir un programa que muestre en primer lugar las palabras que empiecen por letras de la a a la g, y después las palabras que empiezan por letras de la h a la z. Todas ellas se escribirán con un formato de diez columnas. El primer bloque de palabras estará ajustado a la izquierda, y el segundo se ajustará a la derecha.

  8. Ejercicio 0501r08.- Se dispone de una lista de artículos formada por registros de cuatro campos: Se pide construir las funciones adecuadas para imprimir en pantalla un volcado de esta lista con formato encolumnado o delimitado.Los valores numéricos se ajustarán a la izquierda, con un formato que no suponga pérdida de precisión