Apéndice C: Bibliotecas estándar - Parte 2


Apéndice C: Bibliotecas estándar - Parte 2
 
Función printf()

Sintaxis:
int printf(const char *formato[, argumento, ...]); 

Escribe una cadena con formato a la salida estándar stdout.
Esta es probablemente una de las funciones más complejas de C. No es necesario que la estudies en profundidad, limítate a leer este capítulo, y considéralo como una fuente para la consulta. Descubrirás que poco a poco la conoces y dominas.

Esta función acepta listas de parámetros con un número indefinido de elementos. Entendamos que el número está indefinido en la declaración de la función, pero no en su uso, el número de argumentos dependerá de la cadena de formato, y conociendo ésta, podrá precisarse el número y tipo de los argumentos. Si no se respeta esta regla, el resultado es impredecible, y normalmente desastroso, sobre todo cuando faltan argumentos. En general, los sobrantes serán simplemente ignorados.
Cada argumento se aplicará a la cadena de formato y la cadena resultante se enviará a la pantalla.
Valor de retorno:

Si todo va bien el valor de retorno será el número de bytes de la cadena de salida. Si hay error se retornará con EOF.

Veremos ahora las cadenas de formato. Estas cadenas controlan cómo se tratará cada uno de los argumentos, realizando la conversión adecuada, dependiendo de su tipo. Cada cadena de formato tiene dos tipos de objetos:

-Caracteres simples, que serán copiados literalmente a la salida.
-Descriptores de conversión que tomarán los argumentos de la lista y les aplicarán el formato adecuado.
A su vez, los descriptores de formato tienen la siguiente estructura:

%[opciones][anchura][.precisión] [F|N|h|l|L] carácter_de_tipo  

Cada descriptor de formato empieza siempre con el carácter '%', después de él siguen algunos componentes opcionales y finalmente un carácter que indica el tipo de conversión a realizar.

ComponenteOpcional/ObligatorioTipo de control
[opciones]OpcionalTipo de justificación, signos de números, puntos decimales, ceros iniciales, prefijos octales y hexadecimales.
[anchura]OpcionalAnchura, mínimo número de caracteres a imprimir, se completa con espacios o ceros.
[precisión]OpcionalPrecisión, máximo número de caracteres. Para enteros, mínimo número de caracteres a imprimir.
[F|N|h|l|L]Opcional
Modificador de tamaño de la entrada. Ignora el tamaño por defecto para los parámetros de entrada.
F = punteros lejanos (far pointer)
N = punteros cercanos (near pointer)
h = short int 
l = long 
L = long double
Carácter_de_tipoObligatorioCarácter de conversión de tipos.

Opciones

Pueden aparecer en cualquier orden y combinación:

OpciónSignificado

-Justifica el resultado a la izquierda, rellena a la derecha con espacios, si no se da se asume justificación a la derecha, se rellena con ceros o espacios a la izquierda.
+El número se mostrará siempre con signo (+) o (-), según corresponda.
EspacioIgual que el anterior, salvo que cuando el signo sea positivo se mostrará un espacio.
#Especifica que el número se convertirá usando un formato alternativo
 
La opción (#) tiene diferentes efectos según el carácter de tipo especificado en el descriptor de formato, si es:

Carácter de tipoEfecto
c s d i uNo tiene ningún efecto.
x XSe añadirá 0x (o 0X) al principio del argumento.
e E f g GEn el resultado siempre mostrará el punto decimal, aunque ningún dígito le siga. Normalmente, el punto decimal sólo se muestra si le sigue algún dígito.
 
Anchura:
 
Define el número mínimo de caracteres que se usarán para mostrar el valor de salida.

Puede ser especificado directamente mediante un número decimal, o indirectamente mediante un asterisco (*). Si se usa un asterisco como descriptor de anchura, el siguiente argumento de la lista, que debe ser un entero, que especificará la anchura mínima de la salida. Aunque no se especifique o sea más pequeño de lo necesario, el resultado nunca se truncará, sino que se expandirá lo necesario para contener el valor de salida.

DescriptorEfecto
nAl menos n caracteres serán impresos, si la salida requiere menos de n caracteres se rellenará con blancos.
0nLo mismo, pero se rellenará a la izquierda con ceros.
*El número se tomará de la lista de argumentos

Precisión:

Especifica el número máximo de caracteres o el mínimo de dígitos enteros a imprimir.
La especificación de precisión siempre empieza con un punto (.) para separarlo del descriptor de anchura.
Al igual que el descriptor de anchura, el de precisión admite la especificación directa, con un número; o indirecta, con un asterisco (*).
Si usas un asterisco como descriptor de anchura, el siguiente argumento de la lista, que debe ser un entero, especificará la anchura mínima de la salida. Si usas el asterisco para el descriptor de precisión, el de anchura, o para ambos, el orden será, descriptor de anchura, de precisión y el dato a convertir.
 
DescriptorEfecto

(nada)Precisión por defecto
.0 ó .
Para los tipos d, i, o, u, x, precisión por defecto.
Para e, E, f, no se imprimirá el punto decimal, ni ningún decimal.
.nSe imprimirán n caracteres o n decimales. Si el valor tiene más de n caracteres se truncará o se redondeará, según el caso.
.*El descriptor de precisión se tomará de la lista de argumentos.
Valores de precisión por defecto:
1 para los tipos: d,i,o,u,x,X
6 para los tipos: e,E,f
Todos los dígitos significativos para los tipos; g, G
Hasta el primer nulo para el tipo s
Sin efecto en el tipo c
 
Si se dan las siguientes condiciones no se imprimirán caracteres para este campo:
-Se especifica explícitamente una precisión de 0.
-El campo es un entero (d, i, o, u, óx),
-El valor a imprimir es cero.
 
Cómo afecta [.precisión] a la conversión:

Carácter de tipoEfecto de (.n)
d i o u x XAl menos n dígitos serán impresos. Si el argumento de entrada tiene menos de n dígitos se rellenará a la izquierda, para x/X con ceros. Si el argumento de entrada tiene menos de n dígitos el valor no será truncado.
e E fAl menos n caracteres se imprimirán después del punto decimal, el último de ellos será redondeado.
g GComo máximo, n dígitos significativos serán impresos.
cNingún efecto.
sNo más de n caracteres serán impresos.

Modificador de tamaño [F|N|h|l|L]:

Indican cómo printf debe interpretar el siguiente argumento de entrada.

ModificadorTipo de argumentoInterpretación
FPuntero p s nUn puntero far
NPuntero p s nUn puntero near
hd i o u x Xshort int
Ld i o u x Xlong int
le E f g Gdouble
Le E f g Glong double

Caracteres de conversión de tipo

La información de la siguiente tabla asume que no se han especificado opciones, ni descriptores de ancho ni precisión, ni modificadores de tamaño.

Carácter de tipoEntrada esperadaFormato de salida
Números  
dEntero con signoEntero decimal
iEntero con signoEntero decimal
oEntero con signoEntero octal
uEntero sin signoEntero decimal
xEntero sin signoEntero hexadecimal (con a, b, c, d, e, f)
XEntero sin signoEntero hexadecimal (con A, B, C, D, E, F)
fComa flotanteValor con signo: [-]dddd.dddd
eComa flotanteValor con signo: [-]d.dddd...e[+/-]ddd
gComa flotanteValor con signo, dependiendo del valor de la precisión. Se rellenará con ceros y se añadirá el punto decimal si es necesario.
EComa flotanteValor con signo: [-]d.dddd...E[+/-]ddd
GComa flotanteComo en g, pero se usa E para los exponentes.
Caracteres  
cCarácterUn carácter.
sPuntero a cadenaCaracteres hasta que se encuentre un nulo o se alcance la precisión especificada.
Especial  
%NadaEl carácter '%'
Punteros  
nPuntero a intAlmacena la cuenta de los caracteres escritos.
pPunteroImprime el argumento de entrada en formato de puntero: XXXX:YYYY ó YYYY
 
Veamos algunos ejemplos que nos aclaren este galimatías, en los comentarios a la derecha de cada printf se muestra la salida prevista:

#include <cstdio> 
using namespace std;

int main() { 
   int i = 123; 
   int j = -124; 
   float x = 123.456; 
   float y = -321.12; 
   char Saludo[5] = "hola"; 

   printf("|%6d|\n", i); // | 123| 
   printf("|%-6d|\n", i); // |123 | 
   printf("|%06d|\n", i); // |000123| 
   printf("|%+6d|\n", i); // | +123| 
   printf("|%+6d|\n", j); // | -124| 
   printf("|%+06d|\n", i); // |+00123| 
   printf("|% 06d|\n", i); // | 00123| 
   printf("|%6o|\n", i); // | 173| 
   printf("|%#6o|\n", i); // | 0173| 
   printf("|%06o|\n", i); // |000173| 
   printf("|%-#6o|\n", i); // |0173 | 
   printf("|%6x|\n", i); // | 7b| 
   printf("|%#6X|\n", i); // | 0X7B| 
   printf("|%#06X|\n", i); // |0X007B| 
   printf("|%-#6x|\n", i); // |0x7b | 
   printf("|%10.2f|\n", x); // | 123.46| 
   printf("|%10.4f|\n", x); // |  123.4560| 
   printf("|%010.2f|\n", x); // |0000123.46| 
   printf("|%-10.2f|\n", x); // |123.46 | 
   printf("|%10.2e|\n", x); // | 1.23e+02| 
   printf("|%-+10.2e|\n", y);// |-3.21e+02 | 
   printf("|%*.*f|\n", 14, 4, x); // | 123.4560| 
   printf("%.2f  es el 10%% de %.2f\n", .10*x, x); // 12.35 es el 10% de 123.46 
   printf("%s es un saludo y %c una letra\n", Saludo, Saludo[2]); // hola es un saludo y l una letra 
   printf("%.2s es parte de un saludo\n", Saludo); // ho es parte de un saludo 
} 

Observa el funcionamiento de este ejemplo, modifícalo y experimenta. Intenta predecir los resultados.
 
Biblioteca de rutinas de conversión estándar stdlib.h

En esta biblioteca se incluyen rutinas de conversión entre tipos. Nos permiten convertir cadenas de caracteres a números, números a cadenas de caracteres, números con decimales a números enteros, etc.
Función atoi()
Convierte una cadena de caracteres a un entero. Puede leerse como conversión de "ASCII to Integer".
Sintaxis:

int atoi(const char *s); 

La cadena puede tener los siguientes elementos:
-Opcionalmente un conjunto de tabuladores o espacios.
-Opcionalmente un carácter de signo.
-Una cadena de dígitos.
El formato de la cadena de entrada sería: [ws] [sn] [ddd]
El primer carácter no reconocido finaliza el proceso de conversión, no se comprueba el desbordamiento, es decir si el número cabe en un int. Si no cabe, el resultado queda indefinido.
Valor de retorno:
atoi devuelve el valor convertido de la cadena de entrada. Si la cadena no puede ser convertida a un número int, atoi vuelve con 0.
Al mismo grupo pertenecen las funciones atol y atof, que devuelven valores long int y float. Se verán en detalle en otros capítulos.

Función system()

Ejecuta un comando del sistema o un programa externo almacenado en disco. Esta función nos será muy útil para detener el programa antes de que termine.
Si compilas los ejemplos, ejercicios o tus propios programas usando un compilador de Windows para consola, como Dev-C++, habrás notado que la consola se cierra cuando el programa termina, antes de que puedas ver los resultados del programa, para evitar eso podemos añadir una llamada a la función system para ejecutar el comando del sistema "pause", que detiene la ejecución hasta que se pulse una tecla. Por ejemplo:

#include <stdlib.h>
#include <iostream>
using namespace std;

int main()
{
   cout << "Hola, mundo." << endl;
   system("pause");
   return 0;
} 

De este modo el programa se detiene antes de devolver el control y de que se cierre la consola.

Nota: en este capítulo se menciona el concepto macro.
Una macro es una fórmula definida para el preprocesador. Es un concepto que se estudia en los capítulos 13 y 23. Consiste, básicamente, en una fórmula que se sustituye por su valor antes de compilar un programa, de eso se encarga el preprocesador.
La diferencia principal es que las funciones se invocan, y la ejecución del programa continúa en la dirección de memoria de la función, cuando ésta termina, retorna y la ejecución continúa en el programa que invocó a la función. Con las macros no es así, el código de la macro se inserta por el preprocesador cada vez que es invocada y se compila junto con el resto del programa, eso elimina los saltos, y aumenta el código.
De todos modos, no te preocupes demasiado por estos conceptos, el curso está diseñado para tener una progresión más o menos lineal y estos temas se tratan con detalle más adelante. 

Función abs()

Devuelve el valor absoluto de un entero.
Sintaxis:

int abs(int x); 

abs devuelve el valor absoluto del valor entero de entrada, x. Si se llama a abs cuando se ha incluido la biblioteca "stdlib.h", se la trata como una macro que se expandirá. Si se quiere usar la función abs en lugar de su macro, hay que incluir la línea:

#undef abs 

en el programa, después de la línea:

#include <stdlib.h> 

Esta función puede usarse con "bcd" y con "complejos".
Valor de retorno:
Esta función devuelve un valor entre 0 y el INT_MAX, salvo que el valor de entrada sea INT_MIN, en cuyo caso devolverá INT_MAX. Los valores de INT_MAX e INT_MIN están definidos en el fichero de cabecera "limit.h".

Función rand()

Generador de números aleatorios.
Sintaxis:

int rand(void);  

La función rand devuelve un número aleatorio entre 0 y RAND_MAX. La constante RAND_MAX está definida en stdlib.h.
Valor de retorno:
rand devuelve un número entre 0 y RAND_MAX.

Función srand()

Inicializa el generador de números aleatorios.
Sintaxis:

void srand(unsigned semilla); 

La función srand sirve para cambiar el origen del generador de números aleatorios.
Valor de retorno:
srand no devuelve ningún valor.
 
Biblioteca de tratamiento de caracteres ctype.h

En esta biblioteca contiene funciones y macros de tratamiento y clasificación de caracteres.

Función toupper()

Convierte un carácter a mayúscula.
Sintaxis:

int toupper(int ch); 

toupper es una función que convierte el entero ch (dentro del rango EOF a 255) a su valor en mayúscula (A a Z; si era una minúscula de, a a z). Todos los demás valores permanecerán sin cambios.
Valor de retorno:
toupper devuelve el valor convertido si ch era una minúscula, en caso contrario devuelve ch.

Función tolower()

Convierte un carácter a minúscula.
Sintaxis:

int tolower(int ch); 

tolower es una función que convierte el entero ch (dentro del rango EOF a 255) a su valor en minúscula (A a Z; si era una mayúscula de, a a z). Todos los demás valores permanecerán sin cambios.
Valor de retorno:
tolower devuelve el valor convertido si ch era una mayúscula, en caso contrario devuelve ch.
 
Macros is<conjunto>()

Las siguientes macros son del mismo tipo, sirven para verificar si un carácter concreto pertenece a un conjunto definido. Estos conjuntos son: alfanumérico, alfabético, ascii, control, dígito, gráfico, minúsculas, imprimible, puntuación, espacio, mayúsculas y dígitos hexadecimales. Todas las macros responden a la misma sintaxis:

int is<conjunto>(int c); 

FunciónValores
isalnum(A - Z o a - z) o (0 - 9)
isalpha(A - Z o a - z)
isascii0 - 127 (0x00-0x7F)
iscntrl(0x7F o 0x00-0x1F)
isdigit(0 - 9)
isgraphImprimibles menos ' '
islower(a - z)
isprintImprimibles incluido ' '
ispunctSignos de puntuación
isspaceespacio, tab, retorno de línea, cambio de línea, tab vertical, salto de página (0x09 a 0x0D, 0x20).
isupper(A-Z)
isxdigit(0 to 9, A to F, a to f)
Valores de retorno:
Cada una de las macros devolverá un valor distinto de cero si el argumento c pertenece al conjunto.