CURSOC
CURSOC
CURSOC
1. LECCION 1
El objetivo de este curso es ensear el lenguaje C, o dicho de otro modo, ensear a programar en lenguaje
C.
ORIGENES DEL C
El lenguaje C fue inventado por Dennis Ritchie en 1972 cuando trabajaba, junto con Ken Thompson, en el
diseo del sistema operativo UNIX.
El lenguaje C deriva del lenguaje B de Thompson, el cual, a su vez, deriva del lenguaje BCPL desarrollado
por Martin Richards.
Durante muchos aos el estndar de C fue la versin proporcionada con el sistema operativo UNIX versin
5. Pero pronto empezaron a surgir muchas implementaciones del C a raz de la popularidad creciente de los
microordenadores. Por este motivo, se hizo necesario definir un C estndar que est representado hoy por
el ANSI C.
En este tutor se va a estudiar el C estndar. No obstante, si la opcin turbo est activada, tambin se
incluye en la explicacin la versin Turbo C de Borland International, que es uno de los mejores
compiladores de C que existen en el mercado.
Esta ventana la ests viendo porque la opcin turbo est activada, sino no la veras.
Cuando nos referimos a Turbo C, estamos hablando indistintamente de las distintas versiones que existen
sobre los paquetes Turbo C, Turbo C++ y Borland C++, puesto que en todos ellos se puede programar en
C.
El lenguaje C suministrado por Turbo C es, simplemente, una ampliacin del ANSI C, sobre todo en el
nmero de funciones de librera suministradas.
Es un lenguaje de medio nivel. Este lenguaje permite programar a alto nivel (pensando a nivel lgico y
no en la mquina fsica) y a bajo nivel (con lo que se puede obtener la mxima eficiencia y un control
absoluto de cuanto sucede en el interior del ordenador).
Es un lenguaje porttil. Los programas escritos en C son fcilmente transportables a otros sistemas.
Como desventajas habra que resear que es ms complicado de aprender que otros lenguajes como
Pascal o Basic y que requiere una cierta experiencia para poder aprovecharlo a fondo.
USO DEL C
Los pasos a seguir desde el momento que se comienza a escribir el programa C hasta que se ejecuta son
los siguientes:
1. - Escribirlo en un editor.
2. - Compilarlo en un compilador.
3. - Enlazarlo en un enlazador.
4. - Ejecutarlo.
Paso 1: ESCRIBIRLO
El programa se puede escribir en cualquier editor que genere ficheros de texto estndar, esto es, que los
ficheros generados no incluyan cdigos de control y caracteres no imprimibles.
Estos ficheros que contienen cdigo C se llaman ficheros fuentes. Los ficheros fuentes son aquellos que
contienen cdigo fuente, es decir, ficheros con texto que el usuario puede leer y que son utilizados como
entrada al compilador de C.
Los programas pequeos suelen ocupar un solo fichero fuente; pero a medida que el programa crece, se va
haciendo necesario distribuirlo en ms ficheros fuentes.
Paso 2: COMPILARLO
El compilador produce ficheros objetos a partir de los ficheros fuentes. Los ficheros objetos son los ficheros
que contienen cdigo objeto, es decir, ficheros con cdigo m quina (nmero binario que tiene significado
para el microprocesador) y que son utilizados como entrada al enlazador.
La extensin de estos ficheros es OBJ, aunque tambin los hay con extensin LIB. A estos ltimos se les
llama tambin ficheros de librera o biblioteca; contienen cdigo m quina perteneciente a cdigo compilado
suministrado por el compilador.
Paso 3: ENLAZARLO
El enlazador produce un fichero ejecutable a partir de los ficheros objetos.
Los ficheros ejecutables son aquellos que contienen cdigo mquina y se pueden ejecutar directamente por
el sistema operativo. La extensin en estos ficheros es EXE o COM.
Paso 4: EJECUTARLO
El programa se puede ejecutar simplemente tecleando su nombre desde la lnea de comandos del sistema
operativo.
ESQUEMA
Los pasos anteriores se resumen en el siguiente esquema:
Hoy da los compiladores de C son muy sofisticados e incluyen entornos integrados desde los cuales
editamos, compilamos, enlazamos, y podemos realizar una multitud de servicios ms.
En algunos de ellos se pueden realizar los pasos de compilado, enlazado y ejecutado con la de una sola
tecla.
CTRL-F9: Ejecutar.
En programacin, la experiencia es el gran maestro. Por ello es conveniente empezar a hacer programas
en C cuanto antes.
A continuacin se van a presentar varios programas completos en C muy sencillos para ir familiarizndonos
en la programacin de este lenguaje.
#include <stdio.h>
main ()
{
printf ("Mi primer programa en C.");
}
Mi primer programa en C.
Los programas C estn compuestos de unidades de programa llamadas funciones, las cuales son los
mdulos bsicos del programa. En este caso, el programa est compuesto por una sola funcin llamada
main.
Un mtodo de comunicacin de datos entre funciones es el uso de argumentos. Los argumentos son los
datos que se les pasa a las funciones. Estos se encierran entre parntesis; main es una funcin sin
argumentos, lo que se indica mediante ().
La lnea con:
realiza una llamada a una funcin denominada printf, con el argumento Mi primer programa en C.; printf es
una funcin de biblioteca que realiza una escritura en la salida estndar. Normalmente la salida estndar es
el monitor.
La funcin printf escribe concretamente una cadena (conocido tambin con los nombres de cadena de
caracteres, constante de caracteres y string).
Cada instruccin en C termina con un punto y coma. La lnea del main () no va seguida de punto y coma
porque no se trata de una llamada a una funcin sino de la definicin de una funcin. La definicin de una
funcin especifica las instrucciones que posee dicha funcin as como los argumentos que tiene.
printf es una funcin de librera con prototipo en el fichero stdio.h (standard input/output header). Las
funciones de librera son aquellas suministradas por el compilador y que estn a nuestra disposicin. Para
utilizar una funcin de librera es necesario incluir el correspondiente fichero antes de utilizarla.
Cada fichero header incluye prototipos de muchas funciones. Por ejemplo, el fichero header stdio.h define
funciones de entrada y salida estndar. Pero en el fichero ejecutable de nuestro programa slo estn las
funciones de librera que hemos utilizado. De esta forma el tamao del cdigo ejecutable se reduce al
mnimo.
La funcin:
main ()
{
printf ("Mi primer programa en C.");
}
El C es sensitivo al caso. Esto significa que las letras maysculas son distintas a las minsculas. De este
modo, no es lo mismo para el C printf que PRINTF o que Printf.
Todas las lneas que empiezan con # no son en realidad instrucciones del lenguaje C sino que son lneas
para ser manipuladas por el preprocesador. El preprocesador realiza algunas tareas antes de empezar a
actuar el compilador.
La lnea
#include <stdio.h>
lo que hace es incluir la informacin que hay en el fichero stdio.h en nuestro programa.
Esta funcin est compuesta de una sola instruccin: llamada a la funcin printf para que escriba una
cadena en pantalla.
La definicin de la funcin printf est en el fichero stdio.h. Por lo tanto, hay que incluir (con #include) este
fichero para poder utilizar la funcin printf.
#include <stdio.h>
main ()
{
printf ("Mi segundo programa en C.\n");
printf ("Pulsa la tecla RETURN para terminar.");
getchar ();
}
Mi segundo programa en C.
Pulsa la tecla RETURN para terminar.
Hay dos novedades con respecto al primer ejemplo: la primera es la aparicin del cdigo \n dentro de la
cadena del primer printf. La segunda es la aparicin de una nueva funcin de librera: getchar ().
En C, todo lo que va entre comillas es una cadena. Ya dijimos antes que una cadena es una secuencia de
caracteres. La secuencia \n es un carcter especial que denota el carcter de nueva lnea. Al ser \n un
carcter se puede incluir en cualquier parte de una cadena como cualquier otro carcter. En nuestro
programa, si no se hubiese incluido, la salida habra sido:
#include <stdio.h>
main ()
{
printf ("Mi segundo programa en C.");
printf ("\nPulsa la tecla RETURN para terminar.");
getchar ();
}
#include <stdio.h>
main ()
{
printf ("Mi segundo programa en C.");
printf ("\n");
printf ("Pulsa la tecla RETURN para terminar.");
getchar ();
}
A todos los caracteres empezados por \ se les llaman secuencias de escape. Las secuencias de escape
son mecanismos para representar caracteres no imprimibles. Antes vimos la secuencia de escape \n que
representaba a la nueva lnea.
Otras secuencias de escape son \r para el retorno de carro, \t para el tabulador, \b para retroceso, \ para la
comilla, \' para el apstrofe y \\ para la barra diagonal invertida.
Si nuestro primer programa lo ejecutamos desde un entorno integrado, en muchos de estos entornos, a la
finalizacin de la ejecucin de nuestro programa C, la frase impresa desaparece inmediatamente y se
vuelve a la pantalla del entorno.
Una solucin alternativa es incluir la funcin getchar () al final de la funcin main (). getchar () es una
funcin que espera la de la tecla return por parte del usuario. Esta funcin no necesita argumentos pero los
parntesis son necesarios puesto que se trata de una funcin. getchar () tiene su prototipo en stdio.h, por lo
tanto, siempre que utilicemos esta funcin en un programa es necesario incluir la lnea:
#include <stdio.h>
#include <stdio.h>
main () /* Tercer ejemplo */
{
int horas, minutos;
horas = 3;
minutos = 60 * horas;
printf ("Hay %d minutos en %d horas.", minutos, horas);
getchar ();
}
En C, todo aquello que vaya entre un /* y un */ es ignorado. Las secuencias /* y */ denotan el principio y el
final de un comentario en C. Se deben utilizar comentarios en los programas para hacerlos ms
comprensibles.
La lnea:
El punto y coma final de la lnea de declaracin la identifican como una sentencia o instruccin C.
int horas;
int minutos;
Las variables son posiciones de memoria donde el valor de su contenido puede variar a lo largo del
programa. Nos la podemos imaginar como cajas donde podemos meter cualquier cosa que le venga bien a
la caja. En C, todas las variables utilizadas ha de ser declaradas antes de su uso. Las lneas:
horas = 3;
minutos = 60 * horas;
La primera lnea significa: dar a la variable horas el valor 3. La segunda lnea significa: dar a la variable
minutos el resultado de multiplicar 60 por horas. Ntese que las dos lneas terminan en punto y coma por
ser dos sentencias o instrucciones.
En la lnea
En las lneas
horas = 3;
minutos = 60 * horas;
Se les da valor a dichas variables (al contenido de los espacios reservados). Posteriormente se les puede
asignar a estas variables valores diferentes. = es el operador de asignacin y * es el operador de
multiplicacin.
Otros operadores son: + (nmero positivo usado como operador unario y suma usado como operador
binario), - (nmero negativo usado como operador unario y substraccin usado como operador binario), /
(operador de divisin), % (operador mdulo, esto es, resto de la divisin de dos nmeros enteros).
En este momento, se mencionan estos operadores para empezar a hacer pequeos programas. En
lecciones ulteriores s vern en detalle todos los operadores.
escribe:
Como se ve los dos %d no se han escrito y sin embargo se ha escrito en su lugar los valores de las
variables minutos y horas.
El smbolo % avisa a la funcin printf que se va a imprimir una variable en esta posicin; la letra d informa
que la variable a imprimir es entera (digit).
printf significa escritura (print) con formato (format) porque nos permite formatear la salida a nuestro gusto.
{
declaracin_de_variables
sentencias
}
tipo lista_de_variables;
Si no has entendido algo en los tres ejemplos vistos, no te preocupes, pues todo lo que hay ellos se va a
estudiar en profundidad en lecciones posteriores.
Con estos ejemplos lo que se ha pretendido es empezar a hacer programas completos en C desde un
primer momento, intentando ofrecer una visin global de este.
2. LECCION 2
En esta leccin vamos a hacer un estudio completo sobre los tipos, operadores y expresiones del lenguaje
C. Adems profundizaremos un poco ms en el estudio de la funcin printf a medida que vaya siendo
necesario.
A modo de introduccin vamos a dar unas definiciones muy breves que sern ampliadas a lo largo de toda
la leccin:
Las variables y constantes son los objetos bsicos que se manipulan en un programa.
Las declaraciones indican las variables que se van a utilizar y establecen su tipo y, quiz, su valor
inicial.
Los operadores especifican lo que se va a hacer con ellas.
Las expresiones combinan variables y constantes para producir nuevos valores.
Los programas funcionan con datos. Los datos son los nmeros y los caracteres que contienen la
informacin a utilizar.
Una segunda divisin de los datos la podemos hacer segn los tipos de que sean.
NOTA IMPORTANTE: La longitud en bytes, y por consiguiente, tambin el rango, de la tabla anterior,
depende de cada tipo de procesador y de cada compilador de C.
'TT' es incorrecto porque hay dos caracteres entre los apstrofos; l es incorrecto porque el compilador lo
interpreta como una variable; el 1 lo interpreta el compilador como un nmero y no como un carcter.
El valor de un constante carcter es el valor numrico del carcter en el conjunto de caracteres del sistema.
Por ejemplo, en el conjunto ASCII, el carcter cero, o '0', es 48, y en EBCDIC '0' es 240, ambos muy
diferentes del valor numrico 0.
A lo largo de este tutor se utilizar el cdigo ASCII y no el EBCDIC a fin de utilizar ejemplos concretos.
Las dos asignaciones anteriores son equivalentes, pero es preferible la primera asignacin porque es ms
porttil. A ch1 se le asigna en cualquier ordenador el carcter 'A'. Sin embargo, a la variable ch2, en
sistemas basados en cdigo ASCII se le asigna el carcter 'A' (el cdigo ASCII de 65 es 'A'), y en sistemas
basados en cdigo EBCDIC se le asigna un carcter distinto a 'A'.
Todas las variables en C han de ser declaradas antes de poder ser usadas.
tipo lista_variables;
Aqu, tipo debe ser un tipo de datos vlido de C y lista_variables puede consistir en uno o ms nombres de
identificadores separados por comas. Las declaraciones deben estar antes de la primera sentencia
ejecutable.
Ejemplos de declaraciones:
int i, j, k;
char caracter;
Los identificadores en C son los nombres usados para referenciar las variables, las funciones y otros
objetos definidos por el usuario. Los nombres de los identificadores estn compuestos por letras, dgitos y
el carcter de subrayado (_). El nmero de caracteres significativos de los identificadores depende del
compilador. El primer carcter de un identificador ha de ser letra o el carcter de subrayado.
Cdigo Significado
----------- ---------------------------------------------------------
\b retroceso
\f salta de pgina
\n nueva lnea
\r retorno de carro
\t tabulacin horizontal
\ comillas ()
\' apstrofo (')
\0 carcter nulo
\? interrogacin
\\ barra invertida (\)
\v tabulacin vertical
\a alerta (bell, campanilla)
\ddd constante octal (ddd son tres dgitos como mximo)
\xHHH constante hexadecimal (HHH son tres dgitos como mximo)
Hay otros caracteres no imprimibles que no tienen correspondencia en la tabla anterior. Estos caracteres se
pueden utilizar mediante los cdigos \ddd, \xddd o simplemente usando el nmero del cdigo ASCII.
char ch1, ch2, ch3, ch4; /*declaracin de cuatro variables tipo carcter*/
ch1 = '\n'; /* el carcter '\n' es el nmero 13 en ASCII */
ch2 = 13; /* 13 decimal <=> 12 octal <=> A hexadecimal */
ch3 = '\12'; /* tambin sera vlido: ch3 = '\012'; */
ch4 = '\xA'; /* tambin sera vlido: ch4 = '\xa'; */
La notacin preferida es la primera. Aunque para los caracteres no imprimibles que no tienen
correspondencia en la tabla anterior, la nica solucin es una de las tres ltimas asignaciones del ejemplo.
Es un nmero sin parte fraccionaria. Las constantes enteras se pueden escribir de uno de los tres modos
siguientes:
Las constantes de este tipo tienen parte real y parte fraccionaria. El tipo double tiene doble precisin que el
tipo float. Por lo dems, los dos tipos son iguales.
donde:
signo es + o -;
dgitos es una secuencia de dgitos;
. es el punto decimal;
exponente es E o e.
Los elementos que estn entre [] son opcionales, pero el nmero no puede empezar por e o E, ya que el
compilador lo interpretara en este caso como un identificador y no como un nmero.
Uno de los usos de void se puede observar al comparar estos dos programas:
Al poner void entre los parntesis de la definicin de una funcin, se define a sta como funcin que no
tiene argumentos. No confundir con llamada a funcin, en cuyo caso no se puede utilizar el void. Del mismo
modo, al poner void antes del nombre de la funcin en la definicin de esta, se est declarando como
funcin que no devuelve nada. La segunda versin es preferible y es la que se utilizar a lo largo de todo l
Tutor.
PROGRAMA EJEMPLO
#include <stdio.h>
void main (void)
{
int i = 1;
char c = 'c';
float f = 1.0;
double d = 1e-1;
printf (" i = %d\n c = %c\n f = %f\n d = %lf\n", i, c, f, d);
getchar ();
i=1
c=c
f = 1.000000
d = 0.100000
Como se puede observar en el programa, se puede asignar un valor a una variable en el momento de la
declaracin.
En la leccin 1 ya se dijo que %d indica a la funcin printf el lugar en que se ha de escribir una variable de
tipo entera. Los cdigos %c, %f y %lf indican a la funcin printf el lugar en la cadena de caracteres en la
que se han de escribir variables de tipo char, float y double respectivamente.
2.7. MODIFICADORES
A excepcin del tipo void, los tipos de datos bsicos pueden tener varios modificadores precedindolos.
Hay modificadores de tipo y de acceso.
a) MODIFICADORES DE TIPO
Un modificador de tipo se usa para alterar el significado del tipo base para que se ajuste ms precisamente
a las necesidades de cada momento.
Modificadores de tipo:
El uso de signed con enteros es redundante aunque est permitido, ya que la declaracin implcita de
entero asume un nmero con signo.
El estndar ANSI elimina el long float por ser equivalente al double. Sin embargo, como se puede observar
en el ltimo ejemplo visto, para escribir un double con la funcin printf es necesario utilizar el cdigo de
formato de printf: %lf; que significa: long float.
Se puede utilizar un modificador de tipo sin tipo; en este caso, el tipo se asume que es int.
b) MODIFICADORES DE ACCESO
Acabamos de hablar de los modificadores de tipos y hemos dicho que modifican el tipo bsico. Tambin
hay otra clase que son los modificadores de acceso. Como su propio nombre indica, estos modificadores
modifican el acceso a los tipos. Estos modificadores son:
Modificador Descripcin
--------------- ----------------
const constante
volatile voltil
Las variables de tipo const son aqullas a las que se les asigna un valor inicial y este valor no puede ser
cambiado a lo largo del programa. Se utilizan para declarar constantes.
Las variables de tipo volatile previenen al compilador que dicha variable puede ser cambiada por medios no
explcitamente especificados en el programa.
int v;
v = 1;
v = 2;
En estos casos, los compiladores suelen optimizar el cdigo y la primera sentencia de asignacin se
desecha y no se genera cdigo para ella ya que es redundante.
volatile v;
La optimizacin descrita no se realizara sobre la variable v, generndose cdigo para las dos asignaciones.
En C existen tipos derivados. Los tipos derivados son aquellos, que como su propio nombre indica, derivan
de los tipos bsicos.
A continuacin vamos a hablar de un tipo derivado muy comn en C: las cadenas de caracteres.
c) CADENAS DE CARACTERES
Una cadena de caracteres (tambin conocido por el nombre de string) es una secuencia de caracteres
encerrados entre comillas.
Ejemplos de cadenas:
Las comillas no forman parte de la secuencia. Sirven para especificar el comienzo y final de sta, al igual
que los apstrofos marcaban los caracteres individuales. Las cadenas son tratadas por el C como un array
de caracteres.
Un array (conocido tambin con el nombre de vector) es una secuencia de datos que se encuentran
almacenados en memoria de una forma consecutiva. Un array de caracteres es una secuencia de
caracteres.
a b c \0
El carcter '\0' se llama carcter nulo, y es utilizado por el C para marcar el final de la cadena en memoria.
El carcter nulo ('\0') no es la cifra 0 (cuyo cdigo ASCII es 48), sino un carcter no imprimible, cuyo cdigo
ASCII es 0.
Ntese que en este programa no se ha puesto: #include <stdio.h>. Esto se debe a que nuestro programa
no utiliza ninguna informacin contenida en dicho header.
En las asignaciones anteriores, a ch1 y ch2 se les asigna el carcter nulo, pero a las variables ch3 y ch4 se
le asigna el carcter cero.
Teniendo en cuenta el carcter nulo en la cadena abc, esta cadena es un array de tamao 4 (tres
caracteres ms el carcter nulo).
#include <stdio.h>
void main (void)
{
printf ("\nInvertir en conocimientos produce siempre los mejores intereses.\n(%s)", Benjamin Franklin);
}
En este ejemplo podemos observar la aparicin de dos cosas nuevas: la divisin de una cadena de
caracteres en varias lneas y el cdigo de formato %s. El cdigo %s le indica a la funcin printf que escriba
una cadena en su lugar.
Una cadena de caracteres se puede escribir en varias lneas de fichero cerrando las comillas al final de la
lnea y volvindolas a abrir en la lnea siguiente. Hacindolo de este modo, el compilador lo interpreta como
una sola cadena de caracteres escrita en varias lneas. En C, los finales de instrucciones no se detectan
con los finales de lnea sino con puntos y comas al final de cada instruccin.
La sentencia:
printf ("\nInvertir en conocimientos produce siempre los mejores intereses.\n(%s)", "Benjamin Franklin");
printf (
"\nInvertir
en conocimientos produce
siempre los mejores
intereses.
\n(%s)",
"Benjamin
Franklin"
);
'x' pertenece a un tipo bsico (char). x es de un tipo derivado (array compuesto de elementos del tipo bsico
char). x, en realidad, contiene dos caracteres, a saber, 'x' y '\0'.
El estudio de los array se estudia en profundidad en lecciones posteriores; pero para comprender un poco
mejor el concepto de array de caracteres, vamos a hablar un poco ms de ellos.
variable_array [numero_de_elemento];
Es muy importante tener siempre en mente que al primer elemento de un array se accede mediante:
variable_array [0];
y al segundo elemento:
variable_array [1];
Programa ejemplo:
#include <stdio.h>
void main (void)
{
int x[2]; /* se reserva memoria para dos elementos de tipo int */
x[0] = 10;
x[1] = 11;
/* el elemento x[2] no existe, mejor dicho, no se ha reservado memoria */
printf ("\nx[0] = %d \n x[1] = %d\n", x[0], x[1]);
}
x [2] = 3;
El compilador probablemente compilara sin problemas y no nos informara de ningn error. PERO AL
EJECUTAR EL PROGRAMA, EL VALOR 3 SE ESCRIBIRA EN UNA POSICION DE MEMORIA NO
ASIGNADA; ESTO PUEDE PRODUCIR RESULTADOS INESPERADOS; pensad que el valor 3 se podra
escribir sobre el cdigo del sistema operativo o cualquier otro programa que est en memoria en ese
momento.
Al hacer la declaracin
int x [2];
estamos reservando memoria para x[0] y x[1], dicho de otro modo, int x[2] reserva memoria para dos
elementos.
Repetimos: hemos hablado de los arrays lo mnimo para poder entender los arrays de caracteres; ms
adelante, en otra leccin, se va hablar a fondo sobre los arrays.
Un operador es un smbolo que realiza una determinada operacin sobre sus operandos. Un operando es
el dato que va a ser manipulado por el operador. Los operadores en C se pueden dividir en cuatro grupos:
Operadores aritmticos.
Operadores relacionales y lgicos.
Operadores a nivel de bits.
Operadores especiales.
e) EXPRESIONES
OPERADORES ARITMETICOS
Operador Accin
------------- ------------------------------
- Resta, tambin menos unario
+ Suma, tambin suma monaria
* Multiplicacin
/ Divisin
% Mdulo (resto de la divisin entera)
-- Decremento
++ Incremento
Los operadores de incremento y decremento pueden preceder o seguir al operando. Si el operador precede
al operando, C lleva a cabo la operacin antes de utilizar el valor del operando. Si el operador sigue al
operando, C utilizar su valor antes de incrementarlo o decrementarlo. Esto se ve muy bien en los dos
ejemplos siguientes:
int x, y; int x, y;
x = 2; x = 2;
y = ++x; y = x++;
/* ahora x tiene el valor 3 /* ahora x tiene el valor 3
e y tiene el valor 3 */ e y tiene el valor 2 */
MAYOR ++ --
+ (ms unario) - (menos unario)
* / %
MENOR + -
Los operadores del mismo nivel de precedencia son evaluados por el compilador de izquierda a derecha.
Se puede alterar el orden de evaluacin utilizando parntesis.
La palabra relacional se refiere a la relacin entre unos valores y otros. La palabra lgico se refiere a las
formas en que esas relaciones pueden conectarse entre s.
Los vamos a ver juntos porque ambos operadores se basan en la idea de cierto (true en ingls) y falso
(false en ingls). En C, cualquier valor distinto de cero es cierto, y el valor 0 es falso. Las expresiones que
son ciertas toman el valor de 1 y las que son falsas toman el valor de 0.
p q p && q p || q !p
-------- ----------- -------- -----
0 0 0 0 1
0 1 0 1 1
1 0 0 1 0
1 1 1 1 0
MAYOR !
> >= < <=
== !=
Ejemplo:
Una particularidad interesante del C es que la evaluacin de una expresin se termina en cuanto se sabe el
resultado de dicha expresin.
Veamoslo con un ejemplo:
0 && x
1 || x
En las dos expresiones anteriores NO se evala x puesto que es superfluo: en la primera expresin al ser
uno de los dos operandos 0, el otro no hace falta mirarlo; con la segunda expresin podemos decir lo
mismo. Como los operadores && y || se evalan de izquierda a derecha, podemos asegurar que es el
segundo operando (el que contiene la x) el que no se vala. Si la expresin fuera: x && 0, se valuara la x, y
si sta es cierta se evaluara el 0, y si la x fuera falsa, no se evaluara el 0.
Estos operandos realizan operaciones sobre los bits de un byte o una palabra (dos bytes). Slo se pueden
utilizar con los tipos char e int.
Operador Accin
------------- -----------------------------
& Y
| O
^ O exclusiva (XOR)
Complemento a uno (NOT)
>> Desplazamiento a la derecha
<< Desplazamiento a la izquierda
Las tablas de verdad de los operadores &, | e ^ son las mismas que las tablas de verdad de los operadores
&&, || y ! respectivamente; pero los operadores a nivel de bits trabajan bit a bit. La tabla de verdad para el
XOR es:
pq p^q
00 0
01 1
Signifiquemos que los operadores relacionales y lgicos siempre producen un resultado que es 0 1,
mientras que las operaciones entre bits producen cualquier valor arbitrario de acuerdo con la operacin
especfica. En otras palabras, las operaciones a nivel de bits pueden dar valores distintos de 0 1, pero los
operadores lgicos siempre dan 0 1.
Ejemplo:
a) Un desplazamiento no es una rotacin. O sea, los bits que salen por un extremo no se introducen por el
otro.
b) Normalmente, a medida que se desplaza los bits hacia un extremo se va rellenando con ceros por el
extremo opuesto. PERO NO EN TODOS LOS ORDENADORES ES ASI. Si queremos introducir ceros y
que el programa sea porttil lo tenemos que hacer explcitamente con una operacin and.
Tabla de precedencia:
MAYOR
<< >>
&
^
MENOR |
Ejemplos:
Bajo este apartado se recogen una serie de operadores no agrupables en ninguno de los grupos anteriores.
?
&*
sizeof
,
. ->
() []
El operador ? acta de la siguiente forma: Evala expresion_1. Si es cierta, evala expresion_2 y toma ese
valor para la expresin. Si expresion_1 es falsa, evala expresion_3 y toma su valor para la expresin.
Ejemplo:
int x, y;
x = 2 < 3 ? 4 : 5; /* a x se le asigna el valor 4: x = 4; */
y = 2 > 3 ? 4 : 5; /* a y se le asigna el valor 5: x = 5; */
x = 1 < 2 ? (4 > 3 ? 2 : 3) : 5; /* a x se le asigna el valor 2: x = 2;
Estos dos operadores operan con punteros. Los dos son unarios. Un puntero es una variable que contiene
una direccin de memoria. El significado que tiene en este caso el operador * no tiene absolutamente nada
que ver con el que tiene el operador aritmtico *. En el cdigo fuente no hay confusin entre uno y otro pues
el aritmtico es binario y el de punteros es unario. Lo mismo ocurre con el operador &.
En este momento no vamos a decir nada ms de estos dos operadores y de punteros. Ya llegar el
momento ms adelante.
OPERADOR sizeof.
El operador sizeof es un operador unario que toma el valor de la longitud, en bytes, de una expresin o de
un tipo; en este ltimo caso, el tipo ha de estar entre parntesis.
Ejemplo:
double d;
int longitud_en_bytes_de_la_variable_d, longitud_en_bytes_del_tipo_char;
longitud_en_bytes_de_la_variable_d = sizeof d;
longitud_en_bytes_del_tipo_char = sizeof (char);
/* en la mayora de los sistemas: sizeof d es 8 y sizeof (char) es 1 */
Ejemplos:
int a, b, c;
printf (%d%d%d, 1, 2, 3);
2) Como operador.
Como operador, la coma encadena varias expresiones. Estas expresiones son evaluadas de izquierda a
derecha y el valor de la expresin total es el valor de la expresin ms a la derecha.
Ejemplo:
int x;
x = (2, 3, 4); /* a x se le asigna el valor 4: x = 4; */
Estos dos operadores se utilizan con dos tipos compuestos: estruct (estructura) y union (unin).
El significado, tanto de los tipos compuestos struct y union, como de los operadores . y ->, se estudiarn en
lecciones posteriores.
Aqu se han nombrado estos dos operadores para saber que existen y para hacer una tabla de precedencia
con todos los operadores del C un poco ms adelante, en esta misma leccin.
Los parntesis se pueden considerar como operadores que aumentan la precedencia de las operaciones
que contienen.
Ejemplo:
Los parntesis tambin se usan, dentro de una expresin, para especificar la llamada a una funcin.
Los corchetes llevan a cabo el indexamiento de arrays. Ya hemos hablado anteriormente un poco de ellos y
se estudiarn en detalle en otras lecciones.
Ejemplo:
float f[3]; /* reserva memoria para tres float: f[0], f[1] y f[2] */
f[0] = 1.1; f[1] = 2.2; f[2] = 3.3; /* tres asignaciones */
SENTENCIAS DE ASIGNACION
Una sentencia de asignacin es una sentencia C en la que se asigna un valor a una variable. La forma
general de la sentencia de asignacin es:
Ejemplo:
int a, b, c;
a = 5;
b = 4 + a;
c = (a * b) - 1;
Una sentencia de asignacin es una expresin. El valor de esta expresin es el valor que se le asigna a la
variable. El operador de asignacin se evala de derecha a izquierda.
Ejemplo:
int x, y;
x = y = 2; /* el 2 se asigna primero a la y y despus a la x */
Hemos dicho que el operador de asignacin se evala de derecha a izquierda, as que primero se hace y =
2 y el valor de esta expresin es 2, este valor se asigna a x y el valor de la expresin total es 2.
INICIALIZACIONES DE VARIABLES
Tambin se pueden inicializar varias variables separadas por comas en una misma sentencia.
Ejemplos:
int x = 1; /* declaracin e inicializacin de x */
char ch1 = 'a', ch2 = 'b'; /* declaracin e inicializacin de ch1 y ch2 */
float f1 = 2.2, f2 = 3e3; /* declaracin e inicializacin de f1 y f2 */
int x, y = 3, z; /* declaracin de x, y, z pero inicializacin slo de y */
double d = 1.1 - 2.2; /* declaracin e inicializacin de d */
int a = 1 + 2, b = 4, c; /* declaracin de a, b, c pero esta ltima no se inicializa */
La conversin de tipos se refiere a la situacin en la que se mezclan variables de un tipo con variables de
otro tipo. Cuando esto ocurre en una sentencia de asignacin, la regla de conversin de tipo es muy fcil: el
valor de lado derecho de la expresin se convierte al del lado izquierdo.
Ejemplo:
El tipo que resulta de aplicar un operador con dos operandos de tipos diferentes, es el tipo de mayor
tamao (mayor longitud en bytes).
Ejemplo:
Es posible forzar a que una expresin sea de un tipo determinado utilizando una construccin denominada
molde.
El molde se puede considerar como un operador unario teniendo la misma precedencia que el resto de los
operadores unarios.
Ejemplos:
Expresin Valor de la expresin Tipo de la expresin
--------------- ---------------------------- --------------------------
3/2 int 1
3.0 / 2 float 1.5
(float) (3 / 2) float 1.0
(float) 3 / 2 float 1.5
En la expresin (float) 3 / 2, al ser (float) un operador unario, tiene ms prioridad que el operador binario /.
Una constante decimal, octal o hexadecimal seguida por la letra l o L, se interpreta como una constante
long.
4l
4L
(long) 4
Por ejemplo:
(2 + 3); /* expresin entera */
(void) (2 + 3); /* expresin sin ningn tipo */
PRECEDENCIA DE OPERADORES
Mayor () [] -> .
! ++ -- - (tipo) * & sizeof
* / %
<< >>
< <= > >=
== !=
Los operadores unarios, el condicional y los de asignacin asocian de derecha a izquierda; los dems
asocian de izquierda a derecha. Veamos los pasos que se siguen al evaluar algunas expresiones:
Expresin 2: x = (y = 3), y
Paso 1: a la variable y se le asigna el valor 3
Paso 2: el valor de la expresin coma es y, o sea, 3
Paso 3: a la variable x se le asigna el valor 3
Paso 4: el valor de toda la expresin es x, es decir, 3
En esta leccin vamos a estudiar todas las sentencias que posee el C para cambiar el flujo del programa.
Entre ellas estn las sentencias condicionales if y switch; las sentencias iterativas while, for y do; y las
sentencias break, continue, goto y return; La sentencia return slo se menciona aqu, pues se estudiarn
en la leccin dedicada al estudio de las funciones de C.
3.2. SENTENCIAS C
Las sentencias if, switch, while, for y do son sentencias simples. Todas estas sentencias las veremos en
esta leccin. Una sentencia compuesta est formada por ninguna, una o varias sentencias simples
delimitadas entre llaves. A las sentencias compuestas tambin reciben el nombre de bloques. Las
sentencias simples son todas aquellas que no son compuestas. borrar_ventana
La mayora de las sentencias de control de cualquier lenguaje estn basadas en condiciones. Una
condicin es una expresin cuya resolucin da como resultado cierto (true) o falso (false). Muchos
lenguajes de programacin incorporan los valores true y false; en C cualquier valor distinto de cero es true,
y el valor cero es false.
SENTENCIAS CONDICIONALES
C posee dos sentencias condicionales: if y switch. Adems, el operador ? es una posible alternativa para if
en ciertas situaciones.
a) Sentencia if
if (expresin)
sentencia
if (expresin)
sentencia_1
else
sentencia_2
EJEMPLOS
OBSERVACIONES
1) Lo siguiente es incorrecto:
if (expresin)
{
sentencias
};
else
sentencia
puesto que entre el if y el else slo puede haber una sentencia y aqu hay dos: { } y ;.
3) El else siempre est asociado al if ms cercano. Los dos siguientes ejemplos son distintos:
/* Ejemplo 1: */
if (n > 0)
if (a > b)
z = a;
else
z = b;
/* Ejemplo 2: */
if (n > 0)
{
if (a > b)
z = a;
}
else
z = b;
Las condiciones se evalan de arriba hacia abajo. Slo se ejecuta la sentencia correspondiente a la primera
expresin que sea cierta, si la hay. Si ninguna expresin es cierta, se ejecuta el else final si existe, sino no
se ejecuta ninguna sentencia.
5) El operador ? se puede utilizar para reemplazar las sentencias if-else. Este operador ternario se ha visto
en la leccin 2.
b) Sentencia switch
switch (expresin)
{
case expresin_constante_1:
sentencias_1
break;
case expresin_constante_2:
sentencias_2
break;
case expresin_constante_3:
sentencias_3
break;
.
.
.
default:
sentencias_n
}
DESCRIPCION
En muchas ocasiones es ms elegante utilizar la sentencia switch que la escala if-else-if. Una expresin
constante es una expresin en la que todos los operandos son constantes.
switch (operando)
{
case 1:
x *= y;
break;
case 2:
x /= y;
break;
case 3:
x += y;
break;
case 4:
x -= y;
break;
default:
printf (-ERROR!);
}
OBSERVACIONES
1) La sentencia default es opcional. Si fallan todas las comprobaciones de los case y no hay default, no
se ejecuta ninguna accin en el switch. Incluso el default puede ir en cualquier posicin y no
obligatoriamente al final.
En la sentencia switch slo se puede comprobar la igualdad entre las expresiones constantes y
expresin.
3) Las sentencias break en el switch son opcionales. El break hace que se produzca una salida inmediata
de la instruccin switch. Si no hay una sentencia break en un case, al ejecutarse las sentencias que
corresponden a ese case, tambin se ejecutaran las sentencias correspondientes al siguiente case y
as sucesivamente hasta encontrar un break o llegar al final del switch. La sentencia break puede ir en
cualquier sitio, no forzosamente al final de las sentencias de los case.
case 3:
x++;
break;
y++; /*esta sentencia nunca se ejecuta*/
c) SENTENCIAS ITERATIVAS
Los bucles o sentencias iterativas permiten que un conjunto de instrucciones sea ejecutado hasta que se
alcance una cierta condicin.
Sentencia while
while (expresin)
sentencia
DESCRIPCION
Se evala expresin. Si es cierta, se ejecuta sentencia y se vuelve a evaluar expresin. El ciclo contina
hasta que expresin es falsa, momento en que la ejecucin contina con lo que est despus de sentencia.
EJEMPLOS
/* /* /*
el bucle termina imprime los cinco pri- al <;> del while no
cuando encuentra meros nmeros naturales se llega nunca ya
un carcter dis- */ que el bucle no
tinto de blanco i = 1; hace ninguna itera-
en vectores while (i <= 5) cin.
*/ { */
i = 0; printf (\ni = %d, i); int condicion = 0;
while (s[i] == ' ') i++; while (condicion)
i++; } ;
Sentencia for
DESCRIPCION
expresin_1
while (expresin_2)
{
sentencia;
expresin_3;
}
EJEMPLOS
Nota: (s = 0, i = 1) es una expresin, ms concretamente, es una expresin formada por el operador coma,
cuyo operandos son expresiones de asignacin.
OBSERVACION
La instruccin
for (;;)
sentencia
es un bucle infinito.
Sin embargo, aunque en este bucle no nos podamos salir por la condicin del for, nos podemos salir por
otros medio (por ejemplo, mediante la sentencia break, que estudiaremos un poco ms adelante en esta
misma leccin).
Sentencia do
Su sintaxis es:
do
sentencia
while (expresin);
DESCRIPCION
En la instruccin do, primero se ejecuta sentencia y a continuacin se evala expresin. En caso de ser
cierta, se ejecuta sentencia de nuevo y as sucesivamente. La iteracin termina cuando la expresin se
convierte en falsa.
EJEMPLO
#include <stdio.h>
Las llaves en el ejemplo anterior no son necesarias al tratarse de una sola sentencia; pero en el caso de la
sentencia do, yo recomiendo que siempre se ponga las llaves para hacer el programa ms legible (para el
lector, no para el compilador). Obsrvese la misma instruccin sin llaves:
i = 1;
do
printf ("%d ", i++);
while (i <= 50);
Cuando un lector ve la lnea del while, puede pensar que se trata de la sentencia while, cuando en realidad
es la sentencia do-while.
Sentencia break
break;
DESCRIPCION
Esta sentencia provoca la salida inmediata de las sentencias switch, while, for y do. Por lo tanto, su uso
slo es correcto dentro de un bloque de una de estas sentencias.
EJEMPLO
OBSERVACION
Una sentencia break obliga a una salida inmediata del ciclo (o switch) ms interior. En el ejemplo anterior, la
ejecucin de la sentencia break provoca una salida del bucle for de la variable j, pero no tiene ningn efecto
sobre el bucle for de la variable i.
Sentencia continue
continue;
DESCRIPCION
La sentencia continue funciona de una forma algo similar a break. En vez de forzar la terminacin, continue
fuerza una nueva iteracin del bucle y salta cualquier cdigo que exista entre medias.
EJEMPLO
/*
este bucle imprime todos los nmeros no
negativos del vector vector_de_numeros
*/
OBSERVACION
En los ciclos while y do-while, una sentencia continue da lugar a que el control pase directamente a la
evaluacin de la condicin y prosiga el proceso del bucle. En el caso de un for, primero se ejecuta la parte
incremento del bucle, a continuacin se ejecuta la evaluacin de condicin, y finalmente el bucle prosigue.
Sentencia goto
goto etiqueta;
DESCRIPCION
El lenguaje C tiene la fatalmente seductora sentencia goto. La utilizacin de esta sentencia en un programa
es una de las mejores formas de hacerlo ilegible y difcilmente modificable.
La sentencia goto provoca un salto a una etiqueta que se encuentra en la misma funcin. Una etiqueta es
un identificador vlido de C seguido por dos puntos.
EJEMPLO
/*
Programa que imprime los 100 primeros nmeros naturales. */
#include <stdio.h>
En esta leccin se ha estudiado todas las sentencias de control de programa que posee el C. Entre ellas se
incluyen los constructores de bucles while, for y do, las sentencias condicionales if y switch; las sentencias
break, continue y goto. Aunque tcnicamente tambin la sentencia return afecta al flujo de control de un
programa, no se har referencia a ella hasta la siguiente leccin sobre funciones.
Consejo: No utilices las sentencias goto y continue a no ser que sea absolutamente necesario en un
programa; lo mismo digo para la sentencia break siempre que no sea en un switch (en este caso es nece-
sario). La utilizacin de estas sentencias disminuye la lectura de un programa, adems de que no hacen
ninguna falta ya que el C es un lenguaje muy rico en sentencias, operadores y funciones. Yo he
programado bastante en C y nunca he tenido la necesidad de utilizar estas sentencias; un ejemplo es la
programacin de este tutor.
Funciones de control de programa: exit (), _exit (), abort () y assert ().
Funciones de E/S: printf (), scanf (), putchar (), getchar (), puts () y gets ().
Funciones de consola: cprintf (), cscanf (), putch (), getch (), getche (), ungetch (), cputs (), cgets () y
kbhit ().
Funciones de consola de Turbo C: lowvideo (), highvideo () y normvideo ().
En Turbo C se ver adems dos constantes definidas en stdlib.h (EXIT_SUCCESS y EXIT_FAILURE) y una
variable definida en conio.h (directvideo).
En la leccin anterior hemos visto las sentencias de control de programa: if, switch, while, for, do, break,
continue y goto. A continuacin vamos a ver las funciones que pueden afectar al flujo de control de un
programa; estas funciones son: exit, abort y assert.
La funcin exit, que se encuentra declarada en la biblioteca estndar (stdlib.h), da lugar a la terminacin
automtica de un programa.
Al describir una funcin siempre hay que especificar los argumentos y el valor que devuelve si los hay. La
funcin exit no devuelve nada pero necesita un argumento que es recogido por el programa llamador
(normalmente el sistema operativo). Por convencin, el valor 0 indica terminacin normal; valores distintos
de 0 indican situaciones anormales.
En los programas que manipulan ficheros, stos han de abrirse, manipularse y cerrarse. Los datos de estos
ficheros no se manipulan directamente sino a travs de unos almacenamientos temporales llamados
buffers. La funcin exit cierra todos los ficheros abiertos, vaca todos los buffers de salida, y a continuacin
llama a la funcin _exit para terminar el programa. La funcin _exit provoca la terminacin inmediata del
programa sin realizar el vaciado de los buffers ni cerrar los ficheros; si se desea se la puede llamar
directamente; el argumento de _exit es el mismo que para exit.
Ejemplo:
De este modo, si nos olvidamos si el argumento 0 de exit significa terminacin normal o anormal, utilizamos
estas constantes que es ms difcil que se nos olvide. Adems hace el programa ms legible.
Ejemplos de utilizacin:
exit (EXIT_SUCCESS);
exit (EXIT_FAILURE);
La funcin abort aborta el programa. Es muy similar a la funcin exit. Se diferencia de la funcin exit en dos
aspectos fundamentales:
1) La funcin abort no acepta ningn argumento. Se le llama de la siguiente forma: abort ();
2) La funcin abort no vaca los buffers ni cierra ningn fichero. El principal uso de abort es prevenir una
fuga del programa cerrando los ficheros abiertos. Esta funcin se encuentra declarada en el fichero:
stdlib.h.
Cuando se desee terminar un programa inmediatamente es preferible intentar utilizar la funcin exit.
FUNCION assert ()
La funcin assert no devuelve nada y acepta una expresin como argumento. Esta funcin testea la
expresin dada; si la expresin es cierta no hace nada; si la expresin es falsa escribe un mensaje en la
salida de error estndar y termina la ejecucin del programa.
El mensaje presentado es dependiente del compilador pero suele tener la siguiente forma:
La funcin assert se suele utilizar para verificar que el programa opera correctamente.
Ejemplo:
Se llaman funciones de entrada/salida (input/output), abreviado funciones de E/S (I/O), a aqullas que
transportan datos entre el programa y la entrada y salida estndar.
El final de la entrada y salida se suele marcar (en el caso de ficheros de texto ocurre siempre) con un
carcter especial llamado Fin-De-Fichero y se simboliza EOF (End-Of-File). Hay una constante definida en
el fichero stdio.h que se llama EOF y tiene el valor de -1. El carcter de fin de fichero se suele escribir con
CONTROL-Z (cdigo ASCII 26) en el DOS y CONTROL-D en UNIX. Algunas funciones del C (por ejemplo,
scanf) devuelven el valor de EOF cuando leen el carcter de marca de fin de fichero.
En las operaciones de E/S, los datos utilizados suelen pasar por buffers. Un buffer es una zona de memoria
utilizada para meter y sacar datos.
Tras estos preliminares ya estamos en condiciones de ver las principales funciones de E/S: printf, scanf,
putchar, getchar, puts y gets.
El trmino con formato se refiere al hecho de que estas funciones pueden escribir y leer datos en varios
formatos que estn bajo su control.
La cadena de control est formada por caracteres imprimibles y cdigos de formato. Debe haber tantos
cdigos de formato como argumentos.
Cdigo Formato
---------- ------------------------------------------------------------------
%c Simple carcter
%d Entero decimal con signo
%i Entero decimal con signo
%e Punto flotante en notacin cientfica: [-]d.ddd e [+/-]ddd
%f Punto flotante en notacin no cientfica: [-]dddd.ddd
%g Usa %e o %f, el que sea ms corto en longitud
%o Entero octal sin signo
%s Cadena de caracteres
%u Entero decimal sin signo
%x Entero hexadecimal sin signo
%% Signo de tanto por ciento: %
%p Puntero
%n El argumento asociado debe ser un puntero a entero en el que se pone el nmero de
caracteres impresos hasta ese momento
Las rdenes de formato pueden tener modificadores. Estos modificadores van entre el % y la letra
identificativa del cdigo. Si el modificador es un nmero, especifica la anchura mnima en la que se escribe
ese argumento. Si ese nmero empieza por 0, los espacios sobrantes (si los hay) de la anchura mnima se
Ejemplos:
Sentencia printf () Salida
------------------------- --------------
(":%f:", 123.456) :123.456001:
(":%e:", 123.456) :1.234560e+02:
(":%g:", 123.456) :123.456:
(":%-2.5f:", 123.456) :123.45600:
(":%-5.2f:", 123.456) :123.46:
(":%5.5f:", 123.456) :123.45600:
(":%10s:", "hola") : hola:
(":%-10s:", "hola") :hola :
(":%2.3s:", "hola") :hol:
(":%x:", 15) :f:
(":%o:", 15) :17:
(":%05d:", 15) :00015:
(":abc:%n", &var_int) :abc:
(adems la variable var_int toma el valor de 5)
*********************************
Especificadores de formato
*********************************
*******************************************
Especificador de formato [bandera]
*******************************************
[bandera] Accin
************ *********
(ninguna) Justificado a la derecha; rellenos con 0 o blancos a la izq.
- Justificado a la izquierda; rellenos con espacios a la derecha
+ Siempre empieza con + o -
blanco Imprime signo para valores negativos solamente
# Convierte usando forma alternativa
[anchura] Accin
*********** **********
n Anchura mnima, rellenos con blanco
0n Anchura mnima, rellenos con 0 a la izquierda
* El prximo argumento de la lista es la anchura
****************************************
Especificador de formato [.prec]
****************************************
[.prec] Accin
********** **********
(ninguna) Precisin por defecto
.0 (d,i,o,u,x) Precisin por defecto
(e,E,f) Sin punto decimal
.n Al manos n caracteres
* El prximo argumento de la lista es la precisin
*************************************************
Especificador de formato [FNhl]
*************************************************
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Especificador de formato tipo
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
tipo Accin
********* **********************************
d signed decimal int
i signed decimal int
o unsigned octal int
u unsigned decimal int
x En printf = unsigned hexadecimal int;
en scanf = hexadecimal int
X En printf = unsigned hexadecimal int;
en scanf = hexadecimal long
f Punto flotante [-]dddd.ddd
e Punto flotante [-]d.ddd e [+/-]ddd
g Formato e o f basado en la precisin
E Igual que e excepto E par exponente
G Igual que g excepto E para exponente
c Carcter simple
s Imprime caracteres terminados en '\0' or [.prec]
% El carcter %
p Puntero: near = YYYY; far = XXXX:YYYY
Ejemplos:
Sentencia printf () Salida
---------------------- ----------
(%x, 2) 2
(%#x, 2) 0x2
(%#X, 2) 0X2
(%f, 1.2) 1.200000
(%g, 1.2) 1.2
(%#g, 1.2) 1.200000
(%*.*f, 5, 4, 1.2) 1.2000
Hay una diferencia muy importante entre los argumentos de printf y scanf. En printf los argumentos son
expresiones pero en scanf los argumentos han de ser direcciones de memoria (punteros).
Los punteros se van a estudiar en una leccin posterior. No obstante, hablaremos en este momento un
poco de ellos para saber utilizar la funcin scanf.
Los punteros hemos dicho que son direcciones de memoria. Para obtener la direccin de memoria de una
variable es necesario aplicar el operador monario & (no confundirlo con el operador binario, que es el and
entre bits) de la siguiente forma:
& variable
Hay un tipo de variable un poco especial a este respecto, que son los vectores (tambin llamados arrays),
cuyo nombre es un puntero que apunta al primer elemento del vector.
Ahora mismo se pretende que entendamos cmo usar la funcin scanf, si no los punteros, que es tema de
otra leccin; por cierto, el tema de los punteros es, quizs, una de los ms difciles del C.
Programa ejemplo:
/* Programa que lee nmeros enteros de teclado hasta que se introduce un 0. El programa no es muy til
pero s instructivo.*/
Las llamadas a funciones son expresiones y como el resultado de evaluar una expresin es un valor (a no
ser que el resultado de la expresin sea de tipo void), las funciones pueden devolver valores y la llamada a
esa funcin toma el valor devuelto por la funcin.
Supngamos que f() es una funcin que devuelve un entero, entonces, las siguientes expresiones son
correctas:
x = f ();
y = f () * 2;
f ();
(void) f ();
z = f () + f ();
if (f () < 0)
printf (ERROR);
La funcin printf devuelve un valor entero que contiene el nmero de caracteres escritos. En caso de error,
devuelve EOF.
La funcin scanf devuelve el nmero de campos que han sido asignados. Si ocurre un error o se detecta el
fin de fichero, se devuelve EOF.
Ejemplo:
Especificadores de formato.
Caracteres con espacios en blanco.
Caracteres sin espacios en blanco.
Sobre los especificadores de formato ya hemos hablado. Sin embargo, la funcin scanf() tiene otro
especial: Un * situado despus del % y antes del cdigo de formato lee los datos del tipo especificado pero
elimina su asignacin. As , dada la entrada como respuesta a la funcin
Un espacio en blanco en la cadena de control da lugar a que scanf() salte uno o ms espacios en blanco en
el flujo de entrada. Un carcter blanco es un espacio, un tabulador o un carcter de nueva lnea.
Esencialmente, un carcter espacio en blanco en una cadena de control da lugar a que scanf() lea, pero no
guarde, cualquier nmero (incluido 0) de espacios en blanco hasta el primer carcter no blanco.
Un carcter que no sea espacio en blanco lleva a scanf() a leer y eliminar el carcter asociado. Por ejemplo,
%d,%d da lugar a que scanf() lea primero un entero, entonces lea y descarte la coma, y finalmente lea otro
entero. Si el carcter especificado no se encuentra, scanf() termina.
Ambas funciones devuelven, en caso de xito, el carcter procesado (escrito o ledo), y en caso de error o
fin de fichero, EOF.
char ch;
ch = getchar ();
putchar (ch);
char ch;
scanf ("%c", &ch);
printf ("%c", &ch);
en el estilo C.
x = x + 1;
x = x + 2;
Veamos un programa en C:
/* fichero ejemplo.c */
#include <stdio.h> /* para poder utilizar: getchar (), putchar (), EOF */
Al ser el nombre del programa ejemplo.c, el nombre del fichero ejecutable ser ejemplo.exe.
ejemplo
se leen caracteres de teclado y se escriben en pantalla. Se leen caracteres hasta que se encuentra el
carcter de marca de fin de fichero que en el DOS se escribe con CONTROL-Z.
char ch;
pero esto tiene el inconveniente de que ch est en el rango -128 a 127 y ch no podra tomar los valores de
los caracteres ASCII entre 128 y 255.
As que siempre que manejen caracteres con las funciones de E/S es preferible declarar ch como entero:
int ch;
El bucle while
puede parecer un poco raro pero es la forma de leer caracteres en C hasta que se encuentra el caracter
EOF. Los parntesis son necesarios puesto que los operadores de asignacin son los penltimos con
menos precedencia (el operador, es el que tiene menos preferencia) y si no se incluyeran en el while
anterior, primero se ejecutara la comparacin != y el resultado de esta comparacin (1 0) se asignara a
la variable ch.
La funcin puts escribe una cadena de caracteres y un carcter de nueva lnea al final de la cadena en la
salida estndar. La funcin gets lee una cadena de caracteres de la entrada estndar hasta que se
encuentra el carcter '\n', aunque este carcter no es aadido a la cadena.
La funcin puts acepta como argumento una cadena (sin formato). Si tiene xito devuelve el ltimo carcter
escrito (siempre es '\n'). En otro caso, devuelve EOF.
La llamada a funcin
es equivalente a:
La funcin gets acepta como argumento un puntero al principio de la cadena, es decir, el nombre de la
variable cadena de caracteres; y devuelve dicho puntero si tiene xito o la constante NULL si falla.
NULL es una constante definida en el fichero stdio.h que tiene valor 0. Esta constante se suele utilizar para
denotar que un puntero no apunta a ningn sitio.
Las instrucciones
puesto que gets lee una cadena hasta que encuentre '\n' y scanf hasta que encuentre un carcter blanco ('
'), un tabulador ('\t') o un carcter de nueva lnea ('\n').
Con las funciones de lectura de cadenas es necesario tener una precaucin muy importante: en la
declaracin de cadena se ha reservado memoria para 100 caracteres; por lo tanto, si la funcin gets o scanf
leen ms de 100 caracteres, los caracteres a partir del 100 se estn escribiendo en memoria en posiciones
no reservadas con lo cual los resultados son impredecibles: pensemos que se puede estar escribiendo
datos en el cdigo del sistema operativo, del compilador de C, de programas residentes, ...
donde los caracteres introducidos a partir del nmero 100 son ignorados y no se escriben en la variable
cadena. Con la funcin gets no se puede hacer esto.
FUNCIONES DE CONSOLA
Las funciones de consola que vamos a describir no estn definidas en el estndar ANSI, ya que son
funciones, que por su propia naturaleza, dependen del entorno fijado y en gran parte no son portables. Sin
embargo, estos tipos de funciones tienen una importancia primordial a la hora de crear un software de
calidad.
Todo lo que se diga sobre estas funciones es vlido para los dos compiladores de C ms importantes: el de
Microsoft y el de Borland. Si utilizas otro compilador distinto a los anteriores, es probable que los nombres
de las funciones coincidan con las que vamos a ver, en caso contrario, estas funciones tendrn otros
nombres.
Las caractersticas de consola especficas de Borland slo se estudiar si la opcin turbo est on.
Todas las funciones, y en general toda la informacin, de consola, estn recogidas en el header <conio.h>
(consola input/output).
En esta leccin vamos a ver diez funciones de este header: cprintf, cscanf, putch, getch, getche, ungetch,
cputs, cgets y kbhit.
Adems veremos tres funciones ms, que pertenecen a Turbo C: lowvideo, higvideo y normvideo.
La funcin cprintf es similar a la funcin printf. Lo mismo sucede con los pares de funciones: cscanf-scanf,
cputs-puts, putch-putchar, getch-getchar, getche-getchar, cputs-puts y cgets-gets.
1) Las funciones de escritura de conio.h siempre escriben en pantalla. Las funciones de escritura de
stdio.h normalmente escriben en pantalla, pero si se redirige la salida (esto se puede hacer al ejecutar
el programa mediante los smbolos >, >> o ) ya no escribe en pantalla. Lo mismo se puede decir de
las funciones de lectura y el teclado.
2) En los programas interactivos no queda bien trabajar con buffers. Si has visto los ejemplos de
lecciones anteriores, getchar lee un carcter, pero lo lee una vez que se ha pulsado la tecla RETURN;
adems lo caracteres ledos hasta pulsar la tecla RETURN se mantienen en el buffer para ser ledos
posteriormente. Esto queda muy mal en los programas interactivos. Las funciones getch y getche, que
las estudiaremos un poco ms adelante, lee caracteres inmediatamente, es decir, tras pulsar la tecla.
3) Las funciones de escritura estndar siempre escriben en pantalla con los colores blanco sobre negro.
Las funciones de escritura de consola escriben con cualquier atributo de pantalla.
Estas dos funciones son exactamente iguales que sus correspondientes printf y scanf. Slo se diferencia en
dos cosas:
1) La funcin cprintf escribe en pantalla en la posicin actual del cursor y con el atributo de pantalla
actual. La funcin cscanf lee de teclado.
2) En la funcin cprintf, para pasar a la lnea siguiente, es necesario escribir dos caracteres: '\n' y '\r'.
Estas dos diferencias ocurren con todas las funciones de entrada y salida de conio.h.
Ejemplo:
cprintf ("Pasando al principio de la lnea siguiente\n\r");
En el header conio.h de Turbo C existe una variable de tipo entera que se llama directvideo. Esta variable
controla la salida: si directvideo tiene el valor 1, la salida va directamente a RAM de vdeo; si tiene el valor
0, la salida se escribe va llamadas a la ROM BIOS. El valor por defecto es directvideo = 1. Un valor de 1
hace la escritura ms rpida pero menos portable.
Ejemplo:
La funcin cputs escribe una cadena de caracteres en pantalla. Si recuerdas, las funcin puts escriba una
cadena y adems un caracter de nueva lnea; la funcin cputs no pasa a la lnea siguiente a no ser que se
encuentre en la cadena los caracteres de nueva lnea y retorno de carro. La funcin cputs, al igual que la
funcin puts, devuelve el ltimo caracter escrito.
La funcin cgets lee una cadena de caracteres de consola. Esta funcin es un poco diferente a la funcin
gets. El primer elemento de la cadena debe contener la longitud mxima de la cadena a ser leda. La
#include <conio.h> /* para poder utilizar las funciones cputs (), cgets (), cprintf () y getch () */
Las funciones getch y getche leen un carcter de consola, con eco a pantalla (getche) o sin eco (getch).
Son similares a getchar.
Las teclas especiales, tales como las teclas de funcin, estn representadas por una secuencia de dos
caracteres: un carcter cero seguido del cdigo de exploracin de la tecla presionada. As , para leer un
caracter especial, es necesario ejecutar dos veces la funcin getch (o getche).
La funcin ungetch devuelve un carcter al teclado. Acepta como parmetro el carcter a devolver y
devuelve el propio carcter si hace la operacin con xito o EOF si ha ocurrido un error.
Si hace ungetch, la prxima llamada de getch o cualquier otra funcin de entrada por teclado, leer el
carcter que devolvi la funcin ungetch. No se puede devolver ms de un carcter consecutivo.
Ejemplo:
#include <conio.h>
La funcin kbhit devuelve un valor cierto (distinto de cero) si hay una tecla disponible y falso (0) si no la hay.
Ejemplo:
Estas tres funciones pertenecen a Turbo C. La funcin lowvideo hace que los caracteres que se escriban a
partir de la llamada a esta funcin se escriban en baja intensidad. La funcin highvideo hace que los
caracteres que se escriban a partir de la llamada a esta funcin se escriban en alta intensidad. La funcin
normvideo hace que los caracteres que se escriban a partir de la llamada a esta funcin se escriban en
intensidad normal.
Ejemplo:
El objetivo de esta leccin es hacer un estudio completo en todo lo referente a las variables, funciones, y
directivas del preprocesador del C.
5.2. FUNCIONES
Los programas en C, al menos que sean muy simples, en cuyo caso estaran compuestos slo por la
funcin main, estn formados por varias funciones.
especificador_de_tipo es el tipo del valor que devuelve la funcin, si es void, la funcin no devuelve ningn
valor, si no se pone se supone que la funcin devuelve un entero; lista_de_declaraciones_de_param es una
lista de declaraciones separadas por comas donde cada declaracin consta de tipo y nombre de parmetro;
cuerpo_de_la_funcion es una lista de sentencias C, incluso puede no haber ninguna: 'nada () {}' en cuyo
caso la funcin no hace nada (ser til como un lugar vaco durante el desarrollo de un programa);
lista_de_parametros es una lista de nombres de parmetros separados por comas;
declaracion_de_los_parametros consiste en especificar el tipo de los parmetros.
La segunda forma aunque est permitida en el ANSI C es considerada como obsoleta. De hecho, las
palabras claves void, const y volatile vistas ya, no existen en el viejo C de Kernighan y Ritchie.
Veamos un ejemplo:
2+3=5
2 - 3 = -1
El funcionamiento de este ejemplo parace claro. Hay una observacin importante que hacer acerca del
mismo: Si la funcin main se hubiera definido antes de las funciones funcion_1 y funcion_2, el compilador al
procesar las llamadas a funcion_1 y funcion_2 no sabe de qu tipo son dichas funciones y nos puede
informar de un error o asumir que devuelven un entero. Es bueno declarar todas las funciones a utilizar
(excepto main) antes de su definicin para evitar problemas de este tipo.
#include <stdio.h>
El compilador, en esta nueva versin, al procesar las llamadas a las funciones funcion_1 y funcion_2 en la
funcin main ya sabe cmo son estas funciones.
En las declaraciones (no en las definiciones que son las descripciones completas de las funciones) es lcito
suprimir el nombre de los parmetros, as que tambin se podra haber hecho:
e incluso tambin:
VALORES DEVUELTOS
Todas las funciones, excepto aqullas del tipo void, devuelven un valor. Este valor se especifica
explcitamente en la sentencia return y si no existe sta, el valor es 0.
return expresin;
1) La sentencia return tiene dos usos importantes. Primero, fuerza a una salida inmediata de la funcin,
esto es, no espera a que se llegue a la ltima sentencia de la funcin para acabar. Segundo, se puede
utilizar para devolver un valor.
2) return no es una funcin sino una palabra clave del C, por lo tanto no necesita parntesis como las
funciones, aunque tambin es correcto: return (expresin); pero teniendo en cuenta que los parntesis
forman parte de la expresin, no representan una llamada a una funcin.
3) En las funciones de tipo void se puede hacer: return; y de esta forma se provoca la salida inmediata de
la funcin.
#include <stdio.h>
El mximo de 2 y 3 es 3.
4 elevado a 5 es 1024.
Existen tres lugares bsicos donde se pueden declarar variables: dentro de funciones, en la definicin de
parmetros de funciones y fuera de las funciones. Estas variables son, respectivamente, variables locales,
parmetros formales y variables globales.
a) VARIABLES LOCALES
Son aqullas que se declaran dentro de una funcin. Estas variables se declaran al principio de un bloque
de cdigo, se destruyen al llegar al final del bloque de cdigo y slo puede ser utilizada (ya que slo tiene
existencia) dentro de ese bloque. Recuerda que un bloque de cdigo empieza con una llave abierta y
termina con una llave cerrada.
Ejemplos:
void f1 (void)
{
int x; /* se reserva memoria para x */
x = 10; /* se le asigna un valor */
} /* se libera la memoria asignada a x */
void f2 (void)
{
int x = 1; /* se reserva memoria para x */
/* sentencias */
{
int y = 2; /* se reserva memoria para y */
/* sentencias */
} /* se libera memoria asignada a y */
/* sentencias */ /* en ese punto no existe la variable y */
} /* se libera memoria asignada a x */
void f3 (void)
{
int x, y; /* se reserva memoria para las variables x e y */
x = 1; /* se asigna 1 a la variable x */
y = x; /* se asigna x (1) a la variable y */
{ /* comienzo de un bloque de cdigo */
int x; /* se reserva memoria para x; sta es distinta a la anterior */
x = 2; /* se asigna 2 a la variable x de este bloque */
y = x; /* se asigna x (2) a la variable y */
} /* se libera memoria asignada a la variable x de este bloque */
y = x; /* se asigna x (1) a la variable y */
b) PARAMETROS FORMALES
Si una funcin va a usar argumentos, entonces debe declarar las variables que van a aceptar los valores de
esos argumentos. Estas variables son los parmetros formales de la funcin. Se comportan como cualquier
otra variable local de la funcin.
Ejemplos:
void f1 (int x)
{
/* x es una variable local a esta funcin */
}
void f2 (int x)
{
int x; /* ERROR: se ha intentado definir dos variables del mismo nombre en el mismo mbito */
}
c) VARIABLES GLOBALES
A diferencia de las variables locales, las variables globales se conocen a lo largo de todo el programa y se
pueden usar en cualquier parte del cdigo. Adems, mantienen su valor durante toda la ejecucin del
programa. Las variables globales se crean al declararlas en cualquier parte fuera de una funcin.
Ejemplo:
void f1 (void)
{
x = 10;
}
void f2 (void)
{
x = 11;
}
void f3 (void)
{
int x; /* esta variable x es local, es distinta a la global */
x = 12; /* se le asinga x a la variable x local, no a la global */
}
Existen cuatro especificadores de clase de almacenamiento soportados por C. Son: extern, static, register y
auto.
Se usan para indicar al compilador cmo se debe almacenar la variable que le sigue. El especificador de
almacenamiento precede al resto de la declaracin de variable. Su forma general es:
a) EXTERN
En la definicin de una variable se reserva un espacio de memoria para una variable. La declaracin le
indica al compilador que esa variable est o ser definida en otra parte, pero no reserva memoria para ella.
As pues, una variable slo se puede definir una vez pero se puede declarar todas las veces que se desee.
A partir de ahora, cuando se diga declarar, nos estaremos refiriendo a la declaracin y a la definicin, a no
ser que se distinga explcitamente entre ambos conceptos, ya que es el trmino ms utilizado en todos los
libros y programas.
El principal uso de extern se da cuando un programa est compuesto de varios ficheros y tenemos una
variable global a varios de ellos. Obsrvese el siguiente ejemplo:
/* Fichero 1 */ /* Fichero 2 */
int x; extern int x;
main () f2 ()
{ {
... ...
} }
f1 () f3 ()
{ {
... ...
} }
En la situacin anterior, a la variable x pueden acceder las cuatro funciones, es decir, los dos ficheros. Si no
hubisemos hecho extern int x; las funciones del fichero 2 no podran acceder a la variable x. Y si
hubisemos puesto: int x; en vez de: extern int x; en el fichero 2, entonces, el compilador dara un error
porque se est intentando definir dos veces la misma variable en el mismo mbito .
b) STATIC
Las variables globales son variables permanentes. Tienen dos significados diferentes dependiendo si son
locales o globales.
La diferencia con las variables locales normales es que su contenido no se pierde al salirse de la funcin,
de tal manera que al volver a entrar en la funcin, la variable esttica tiene el mismo valor que el que tena
cuando termin la funcin en la llamada anterior. La variable esttica slo es inicializada en la primera
llamada a la funcin.
#include <stdio.h>
void f1 (void)
{
static int x = 1;
printf ("\nx = %d", x);
x++;
}
void f2 (void)
{
int y = 1;
printf ("\ny = %d", y);
y++;
}
x=1
x=2
y=1
y=1
Cuando se aplica el modificador static a una variable global, se indica al compilador que cree una variable
global conocida nicamente en el fichero en el que se declara la variable global static. Esto significa que,
aunque la variable es global, las rutinas de otros ficheros no la reconocern ni alternarn su contenido
directamente; as , no estar sujeta a efectos secundarios.
c) REGISTER
El especificador register pide al compilador de C que mantenga el valor de las variables definidas con ese
modificador en un registro de la CPU en lugar de en memoria, que es donde se almacenan normalmente
las variables.
Varias observaciones:
2) Las variables register se almacenan en los registros si se puede, si no, se almacenan en memoria.
3) Las variables register slo pueden ser de tipo int y char, y adems han de ser locales no estticas o
parmetros de funcin.
4) En la mayora de los sistemas slo se permiten una o dos variables register al mismo tiempo. En la
prctica, se declaran variables register aqullas que se utilizan como ndices en los bucles.
d) AUTO
Las variables auto (automticas) son todas aquellas variables locales que no son estticas.
En la prctica, este especificador de clase de almacenamiento no se utiliza nunca, ya que todas las
variables locales que no llevan el especificador static son consideradas auto.
Las reglas de mbito de un lenguaje son las reglas que controlan si un fragmento de cdigo conoce o
tiene acceso a otro fragmento de cdigo o de datos.
Si queremos que una funcin f() pueda ser llamada desde dos ficheros distintos, hacemos lo siguiente:
/* Fichero 1 */ /* Fichero 2 */
Como se observa con las declaraciones (al principio de los dos ficheros) y las definiciones (la funcin f() se
define al final de primer fichero) ocurre lo mismo que con las declaraciones y definiciones de las variables
globales.
Si una funcin va a usar argumentos, debe declarar variables que tomen los valores de las argumentos.
Como se dijo antes, estas variables se llaman parmetros formales de la funcin. Se comportan como otras
variables locales dentro de la funcin, crendose al entrar en la funcin y destruyndose al salir.
Llamada por valor: este mtodo copia el valor del argumento en el parmetro formal.
LLamada por referencia: este mtodo copia la direccin del argumento (que ha de ser una variable) en
el parmetro formal.
#include <stdio.h>
En lecciones posteriores se van a estudiar los punteros (variables que contienen direcciones de memoria)
en profundidad, pero inevitablemente ya nos hemos vistos obligados a hablar algo de ellos en lecciones
anteriores, y otra vez vamos a estar obligados a hablar un poco ms de ellos en este momento si queremos
completar nuestro estudio sobre las funciones.
tipo *nombre_puntero;
Una variable puntero es una variable que contiene una direccin de memoria. Al valor de la direccin de
memoria apuntada por un puntero se accede de la siguiente manera:
*nombre_puntero
La direccin de una variable, como se dijo en lecciones anteriores, se obtiene de la siguiente forma:
&nombre_variable
En este caso, * es el operado de contenido y & es el operador de direccin. Son unarios. No confundir con
los operadores binarios de multiplicacin (*) y de and a nivel de bits (&).
Al hacer intercambiar (&x, &y);' estamos pasando a la funcin intercambiar las direcciones de las variables x
e y.
Al hacer la declaracin 'void intercambiar (int *px, int *py)' estamos declarando dos variables locales px e py
que son punteros a enteros, es decir, que contienen direcciones en las cuales hay valores enteros.
Hay un caso especial de llamada por referencia que es el paso de arrays como argumento de una funcin.
Tambin este caso se discuti cuando se describi la funcin scanf en la leccin anterior. Y tambin, al
igual que los punteros, se desarrollar los arrays en lecciones posteriores (concretamente en la leccin
siguiente). Pero, no obstante, hay que hacer algunas observaciones en este momento para explicar cmo
se pueden pasar como argumento a una funcin.
Recordemos que el nombre de la variable array es un puntero al primer elemento del array. De esta forma
cuando se usa un array como un argumento a una funcin, slo se pasa la direccin del array, no una copia
del array entero. Cuando se llama a una funcin con un nombre de array, se pasa a la funcin un puntero al
primer elemento del array.
Existen tres formas de declarar un parmetro que va a recibir un puntero a un array. Veamos con un
ejemplo las tres formas.
#include <stdio.h>
En la funcin funcion_ejemplo_3(), el parmetro <a> se declara como un puntero a entero. Esta es la forma
ms comn en los programas escritos profesionalmente en C. Esto se permite porque cualquier puntero se
puede indexar usando [] como si fuese un array. (En realidad, los arrays y los punteros estn muy
relacionados).
Los tres mtodos de declarar un parmetro de tipo array llevan al mismo resultado: un puntero.
Otro ejemplo:
#include <stdio.h>
b) ARGUMENTOS DE MAIN
Algunas veces es til pasar informacin al programa cuando se va a ejecutar. Los argumentos en la lnea
de rdenes son las informaciones que siguen al nombre del programa en la lnea de rdenes del sistema
operativo.
En este caso, la funcin main se declara para recibir dos parmetros especiales, argc y argv, que se utilizan
para recibir los argumentos de la lnea de rdenes.
El parmetro argc contiene el nmero de argumentos de la lnea de rdenes y es un entero. Siempre vale 1,
por lo menos, ya que el nombre del programa cuenta como el primer agumento.
El parmetro argv es un array donde cada elemento es una cadena de caracteres, la cual contiene la
informacin suministrada al programa a travs de la lnea de rdenes del sistema operativo. Dicho de otro
modo, un array donde cada elemento es un puntero al primer elemento de la cadena correspondiente.
Ejemplo:
/* Este programa acepta un nombre en la lnea de rdenes tras el nombre del programa e imprime un
mensaje de salutacin */
#include <stdio.h>
En Turbo C, tambin podemos utilizar un tercer parmetro en la funcin main, arge, con la misma estructura
que el parmetro argv, y que contiene las cadenas del entorno.
El ltimo elemento del vector arge (al igual que en argv) contiene el valor NULL; esto indica que el puntero
del ltimo elemento de arge no apunta a ningn sitio. Recordamos que NULL es una constante definida en
los headers <stdio.h> y <stdlib.h> entre otros, y equivale al valor 0.
Los nombres argc, argv y arge son una convencin ya que pueden tener cualquier nombre vlido de un
identificador en C.
Ejemplo:
/* Este programa acepta una serie de argumentos en la lnea de rdenes del sistema operativo y los
imprime */
c) RECURSIVIDAD
Las funciones en C se pueden llamar a s mismas. Si una expresin en el cuerpo de una funcin se llama a
s misma, la funcin es recursiva.
La funcin fact1 es la versin iterativa y fact2 es la versin recursiva del clculo del factorial de un nmero.
1. Es ms rpida.
2. Consume menos memoria.
La versin recursiva es preferible en aquellos casos en los que la lgica es mucho ms clara y sencilla que
en la versin iterativa.
En programas grandes es conveniente dividir el cdigo fuente en varios ficheros y compilarlos por
separados.
1. Mayor modularidad.
2. Tiempos de compilacin ms cortos, ya que cuando modificamos un fichero con cdigo fuente, slo
tenemos que compilar ese fichero y enlazar el programa.
En Turbo C, la compilacin separada se consigue creando un fichero proyecto (con extensin .PRJ) en el
cual se listan todos los ficheros fuentes que componen el proyecto. En todas las versiones hay una opcin
para manejar los proyectos: abrirlos, cerrarlos, obtener ayuda acerca de ellos, etctera.
En el header <stdarg.h> nos encontramos toda la informacin necesaria para declarar funciones en las que
el nmero y el tipo de parmetros es variable.
Vamos a mostrar inmediatamente un ejemplo y vamos a basar la explicacin de este apartado sobre el
ejemplo.
observamos que el primer argumento es una cadena (un puntero al primer elemento de la cadena, es decir,
un puntero al primer carcter) y a continuacin tenemos puntos suspensivos (...) que simbolizan que el
nmero y tipo de argumentos despus del primero es variable.
va_list puntero_a_los_argumentos;
es una llamada a la funcin va_start(). Esta funcin est declarada en el header <stdarg.h> y acepta dos
parmetros. El primero es de tipo va_list, es decir, es el puntero a los argumentos, y el segundo parmetro
ha de ser el parmetro conocido situado ms a la derecha en la funcin en que estamos, que en este caso
es la cadena de formato. La misin de la funcin va_start() es inicializar el puntero a los argumentos.
que es una llamada a la funcin vprintf(). La funcin vprintf() hace lo mismo que la funcin printf() con la
diferencia que est basada en una lista de argumentos variables. Lo mismo ocurre con las funciones
vscanf() y scanf().
va_end (puntero_a_los_argumentos);
es una llamada a la funcin va_end(). Esta funcin est declarada en el header <stdarg.h> y acepta un
parmetro que es de tipo va_list y debe ser el puntero a los argumentos. La misin de la funcin va_end()
es finalizar el acceso del puntero a los argumentos. Es importante llamar a esta funcin cuando ya no es
necesario utilizar el puntero a lo argumentos.
En el header <stdarg.h> tenemos slamente cuatro elementos: un tipo (va_list) y tres funciones (va_start(),
va_end() y va_arg()). La funcin va_arg() que es la que nos queda por explicar la vamos a ver, al igual que
las otras, con un ejemplo.
va_end (ptrarg);
return suma;
}
La novedad en este programa es la aparicin de la funcin va_arg(). Esta funcin est declarada en el
header <stdarg.h>. Acepta dos parmetros: el primero ha de ser el puntero a los argumentos y el segundo
es el parmetro conocido ms a la derecha en la funcin en la que estamos. La funcin va_arg() devuelve
el argumento al cual el puntero a los argumentos apunta actualmente.
EL PREPROCESADOR C
DIRECTIVA #include
Cuando el preprocesador encuentra un comando #include busca el fichero que atiende por el nombre que
est situado detr s y lo incluye en el fichero actual. El nombre del fichero puede venir de dos formas:
#include <stdio.h>
#include mifichero.h
El primer #include busca el fichero stdio.h en los directorios del sistema. El segundo #include busca el
fichero en el directorio en el que se est trabajando. Si se incluye path, lo busca en el directorio
especificado:
#include c:\programa\prog.h
Ejemplo:
/* Fichero p.h */
void f (void);
/* Fichero p.c */
#include p.h
void f (void)
{
}
Conceptualmente, una vez que este programa (compuesto de dos ficheros) ha sido procesado por el
preprocesador, el compilador encuentra un solo fichero:
/* Fichero p.h */
void f (void);
void f (void)
{
}
DIRECTIVA #define
La directiva #define sustituye en el cdigo fuente un determinado identificador por la cadena especificada.
Esta directiva hace que a partir de la definicin de la macro, cada vez que el preprocesador encuentre
identificador en el cdigo fuente, lo sustituya por cadena.
Las directivas no son sentencias C, por eso no llevan puntos y coma al final.
La cadena abarca desde el primer carcter no blanco despus de identificador hasta el final de la lnea.
Ejemplo:
#include <stdio.h>
#include <stdio.h>
En realidad, en este ejemplo, el procesador tambinsustituira la lnea del #include por el contenido del
fichero stdio.h, pero lo hemos obviado porque en este momento estamos explicando la directiva #define y
adems el contenido del fichero stdio.h depende de cada implementacin de compilador de C.
Las macros pueden ser utilizadas como parte de la definicin de otras macros. Por ejemplo:
#define UNO 1
#define DOS UNO + UNO
#define TRES UNO + DOS
x = 2+2 * 2+2;
x = (2+2) * (2+2);
Como se ve, en el primer caso se asigna el valor 8 a la variable x, mientras que en el segundo se asigna el
valor 16 a la variable x que es lo que realmente se desea.
Si el identificador aparece dentro de una cadena no se lleva a cabo sustituciones. Por ejemplo:
Cuando la cadena es ms larga de una lnea, se puede continuar en la siguiente poniendo una barra
invertida al final de la lnea. Por ejemplo:
#define MACRO \
if (x < y) \
f1 (); \
else \
f2 ();
Todas las instancias de id2 en cadena ser n reemplazadas con el texto actual definido por id2 cuando id1
es referenciado en el cdigo fuente.
Ejemplo:
#define SUMA(a,b) a + b
/* ... */
x = SUMA (5, 8);
Esto expande a:
x = 5 + 8;
Observar que en el #define es obligatorio que el parntesis vaya junto a SUMA; sin embargo, cuando se
llama a la macro no es obligatorio que el parntesis abierto vaya junto a SUMA.
#define PRODUCTO(a,b) (a * b)
/* ... */
x = PRODUCTO (2+3, 4);
x = (2+3 * 4);
x = ((2+3) * (4));
Como se ve, en el primer caso se asigna el valor 14 a la variable x, mientras que en el segundo se asigna el
valor 20 a la variable x que es lo que realmente se desea.
A las macros sin argumentos tambinse les llama constantes simblicas e incluso, en algunos sitios,
simplemente constantes. Constantes simblicas ya vistas son EOF y NULL. Las funciones va_arg(),
va_start() y va_end() vistas anteriormente, son macros en algunas implementaciones, pero esto es
transparente para el usuario.
Ejemplo:
/* Fichero prog_ej.h */
#include <stdio.h>
#define funcion_principal main
#define principio {
#define final }
#define numero_entero int
#define escribir_cadena(cadena) printf (cadena)
/* Fichero prog_ej.c */
#include prog_ej.h
void funcion_principal (void)
principio
numero_entero x;
escribir_cadena ("Introduce un nmero: ");
leer_numero_entero (x);
escribir_cadena ("x = ");
escribir_numero_entero (x);
final
El uso de macros con argumentos en lugar de funciones reales tiene principalmente una ventaja: las
sustituciones incrementan la velocidad del cdi- go porque no se gasta tiempo en llamar a la funcin. Sin
embargo, hay que pagar un precio por el aumento de velocidad: el tamao del programa aumenta debido a
la duplicacin del cdigo.
DIRECTIVA #undef
La directiva #undef elimina una definicin anterior de la macro que le sigue. La forma general es:
#undef identificador
Ejemplo:
_completas 1 9 80 24
La directiva del preprocesador #error fuerza al compilador a parar la compilacin y escribir un mensaje de
error.
#error mensaje
Ver un ejemplo de esta directiva al final de la descripcin de las directivas #if, #else, #elif y #endif.
Estas directivas permiten compilar selectivamente parte del cdigo fuente de un programa. Este proceso se
llama compilacin condicional.
#if expresion_constante
secuencia de sentencias
#endif
La expresin que sigue a #if se evala en tiempo de compilacin, por eso ha de ser una expresin
constante (que no contiene variables). Si la evaluacin de la expresin es cierta, es decir, es 1, entonces se
compilan la secuencia de sentencias que le siguen; en caso contrario, se compila la secuencia de
sentencias siguientes al #else si existe, o las sentencias siguientes al #endif si no hay #else.
#include <stdio.h>
#define MAX 10
main ()
{
#if MAX > 100
puts ("Compilacin 1");
#else
puts ("Compilacin 2");
#endif
}
La directiva #elif quiere decir else if y establece una escala del tipo if-else-if para opciones de compilacin
mltiples. La directiva #elif, al igual que la #if, va seguida de una expresin constante. Si la expresin es
cierta, ese bloque de cdigo se compila y no se comprueba ninguna expresin #elif ms. En otro caso, se
comprueba el bloque siguiente de la serie.
#if expresin
secuencia de sentencias
#elif expresin 1
secuencia de sentencias 1
#elif expresin 2
secuencia de sentencias 2
#elif expresin 3
secuencia de sentencias 3
.
.
.
#elif expresin N
secuencia de sentencias N
#endif
Ejemplo:
#if X > Y
#if X > Z
int xyz = 1;
#elif
En Turbo C, existe un operador, defined, que puede ser utilizada en las expresiones de estas directivas.
defined identificador
o
defined (identificador)
La expresin formada por este operador es 1 si identificador ha sido previamente definido (usando #define)
y no ha sido despus indefinido (usando #undef). En otro caso, este operador devuelve 0.
Este operador slo puede ser utilizado en las directivas #if y #elif.
Ejemplo 1:
#if defined(X)
v = 1;
#elif defined(Y)
v = 2;
#else
#error "Ni X ni Y han sido definidos."
#endif
Ejemplo 2:
#if !defined(MODELO)
#error "Modelo no definido"
#endif
Estas directivas, al igual que las #if y #elif, son directivas de compilacin condicional.
#ifdef identificador
secuencia de sentencias
#endif
Ejemplo:
#ifdef DEBUG
printf ("Espacio total %d\n", espacio);
#endif
#ifndef identificador
Ejemplo:
#ifndef ABC
printf ("ABC no definido");
#endif
DIRECTIVA #line
La directiva #line hace que el compilador crea que el nmero de lnea de la prxima lnea a la que est
esta directiva, sea la dada por <constante>, y el fichero de entrada corriente sea el dado por
<identificador>.
Ejemplo:
__LINE__ es una macro predefinida que contiene el nmero de la lnea de cdigo fuente actual.
__FILE__ es una macro predefinida que contiene el nombre del fichero fuente actual.
La macro #line lo que hace es cambiar los contenidos de estas dos macros.
DIRECTIVA #pragma
La directiva #pragma es una directiva definida por la implementacin que permite que se den varias
instrucciones al compilador.
#pragma <nombre_de_directiva>
Las instrucciones que se dan con esta directiva son dependientes del compilador. Esto tambinocurre con
cada versin de Turbo C. Comprueba el manual de usuario o la ayuda del entorno integrado de los distintos
compiladores de Turbo C para los detalles y opciones de esta directiva.
__DATE__ Literal Contiene una cadena de la forma mes/da/ao que en la string fecha de conversin del
cdigo fuente a cdigo fuente
__LINE__ Constante Contiene el nmero de la lnea actual del fichero decimal fuente que est siendo
procesado
__TIME__ Literal Contiene una cadena de la forma horas:minutos:segundos string que es la hora de
conversin del cdigo fuente al cdigo objeto
Ejemplo:
/*
Fichero EJ.C: Programa ejemplo para
probar las constantes predefinidas
*/
#ifdef __STDC__
printf (\n__STDC__ : %d, __STDC__);
#endif
}
Las versiones de Turbo C tienen bastante ms constantes simblicas predefinidas pero como varan en
cada seccin, no son muy utilizadas por el usuario medio y requieren conocimientos ms profundos del
sistema que hasta aqu citados, no las vamos a ver. Consulta el manual de usuario o la ayuda del entorno
integrado del compilador de Turbo C que usas.
Aunque hay una en todas las versiones de Turbo C que ses til:
__TURBOC__. El valor de esta macro es distinto para cada versin de Turbo C, por lo tanto, tiene dos usos
principales:
Ejemplo:
#ifdef __TURBOC__
#include <conio.h> /* highvideo (), cputs () */
#define alta_intensidad() highvideo()
#define escribir(cadena) cputs(cadena)
El ejemplo anterior se puede compilar en cualquier compilador de C, pero si se compila en uno de Borland
el mensaje aparecer en alta intensidad y si se compila en cualquier otro aparecer con intensidad normal.
LECCION 6
INTRODUCCION A LA LECCION 6
El objetivo de esta leccin es hacer un estudio completo en todo lo referente a la declaracin, utilizacin e
inicializacin de arrays, tanto unidimensionales, bidimensionales como multidimensionales.
ARRAYS
Un array es una coleccin de variables del mismo tipo que se referencia por un nombre comn. A un
elemento especfico de un array se accede mediante un ndice. En C todos los arrays constan de
posiciones de memoria contiguas. La direccin ms baja corresponde al primer elemento y la direccin ms
alta al ltimo elemento. Los arrays pueden tener de una a varias dimensiones.
ARRAYS UNIDIMENSIONALES
donde especificador_de_tipo es el tipo base, es decir, el tipo de cada elemento y tamao es el nmero de
elementos del array.
nombre_variable [indice]
char v[10];
C no comprueba los lmites de los arrays. Esto quiere decir que si hacemos v[20] para el array anterior, el C
no nos va a informar de ningn error. Es responsabilidad del programador el indexamiento correcto de un
array.
Hay tres formas de pasar un array unidimensional como parmetro a una funcin. Consultar el apartado
'ARGUMENTOS DE LAS FUNCIONES' de la leccin anterior para recordar cu les son las tres formas.
El uso ms comn de los arrays unidimensionales es, con mucho, como cadena de caracteres. En C una
cadena se define como un array de caracteres que termina en un carcter nulo. Un carcter nulo se
especifica como '\0' y generalmente es un cero. Por esta razn, para declarar arrays de caracteres es
necesario que sean de un carcter ms que la cadena ms larga que pueda contener.
Por ejemplo, si se desea declarar un array s para contener una cadena de 10 caracteres, se escribir
char s[11];
En C, todo lo que est encerrado entre comillas es una constante de cadena. Por ejemplo: "cadena"
En las constantes de cadenas no es necesario aadir explcitamente el carcter nulo, pues el compilador de
C lo hace autmaticamente.
ARRAYS BIDIMENSIONALES
Un array bidimensional es, en realidad, un array unidimensional donde cada elemento es otro array
unidimensional. Los arrays bidimensionales son un caso particular de los arrays multidimensionales.
As como a los arrays unidimensionales se les suele llamar vectores, a los arrays bidimensionales se les
suele llamar matrices.
0 1 2 3 4 5 6
1 2 3 4 5 6 7
2 3 4 5 6 7 8
3 4 5 6 7 8 9
El nombre de un array bidimensional es un puntero al primer elemento del array ([0][0]). Para pasar un array
bidimensional como argumento a una funcin se pasa el puntero al primer elemento. Sin embargo, la
funcin que recibe un array bidimensional como parmetro tiene que definir al menos la longitud de la
segunda dimensin. Esto es necesario debido a que el compilador de C necesita conocer la longitud de
cada fila para indexar el array correctamente.
#include <stdio.h>
#define num_filas 4
#define num_columnas 7
int i, j;
rellenar_matriz (matriz);
imprimir_matriz (matriz);
}
ARRAY DE CADENAS
En C es necesario a veces la utilizacin de un array de cadenas. Recordar el argv de la funcin main visto
en la leccin anterior.
Ejemplo de declaracin de un array de 100 elementos en el que cada elemento va a contener una cadena
de caracteres de 50 caracteres como mximo: char array_de_cadena [100] [51];
ARRAY DE CADENAS
ARRAYS MULTIDIMENSIONALES
C permite arrays de ms de dos dimensiones. El lmite exacto, si lo hay, viene determinado por el
compilador. La forma general de declaracin de un array multidimensional es:
ARRAYS Y PUNTEROS
En C los punteros y los arrays estn estrechamente relacionados. Por ejemplo, un nombre de array es un
puntero al primer elemento del array.
Ejemplo:
p == &p[0] : 1
INICIALIZACION DE ARRAYS
La lista_de_valores es una lista de constantes, separadas por comas, cuyo tipo es compatible con
especificador_de_tipo. Despus de } ha de haber un ;.
int v[5] = { 1, 2, 3, 4, 5 };
No es necesario que estn todos los elementos en las inicializaciones de arrays. Los elementos que falten
se inicializan a 0 o quedan sin valor fijo, segn el compilador. Por ejemplo:
int v[5] = { 1, 2 };
int v [] = { 2, 3, 4 };
Otro ejemplo:
En los arrays multidimensionales es necesario especificar el tamao de todas las dimensiones excepto el
de la primera que es opcional.
Ejemplo:
int m [] [4] =
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 }
};
La ventaja de las inicializaciones de arrays sin especificar tamao es que se puede insertar y quitar
elementos sin modificar las dimensiones del array. Otra ventaja es que nosotros no tenemos que contar
todos los elementos del array para dimensionarlo, as que dejamos que esta tarea la realice el compilador.
EJEMPLO
#include <stdio.h>
LECCION 7
INTRODUCCION A LA LECCION 7
El objetivo de esta leccin es hacer un estudio completo en todo lo referente a la declaracin, utilizacin e
inicializacin de punteros.
PUNTEROS
VARIABLES PUNTEROS
La forma general para declarar una variable puntero es: tipo *nombre; donde tipo es cualquier tipo vlido de
C (tambinllamado tipo base) y nombre es el nombre de la variable puntero.
OPERADORES DE PUNTEROS
Existen dos operadores especiales de punteros: & y *. Estos dos operados son unarios y no tienen nada
que ver con los operadores binarios de multiplicacin (*) y de and a nivel de bits (&).
OPERADOR &
Ejemplo:
#include <stdio.h>
void main (void)
{
int x = 10;
printf (" x = %d\n &x = %p\n", x, &x);
}
x = 10
&x = 8FBC:0FFE
NOTA: El valor y formato de las direcciones de las variables que se imprimen en esta leccin (con el cdigo
de formato %p) son dependientes de la implementacin. En mi caso las direcciones se escriben en formato
segmento:offset, y el valor de la direccin de una variable es distinto segn cu ndo y desde dnde se
ejecute el programa.
OPERADOR *
El operador * es el complemento de &. Es un operador unario que devuelve el valor de la variable localizada
en la direccin que sigue.
Ejemplo 1:
#include <stdio.h>
void main (void)
{
int x = 10;
printf (" x = %d\n", x);
printf (" *&x = %d", *&x);
}
Salida de ejemplo 1:
x = 10
*&x = 10
Ejemplo 2:
#include <stdio.h>
void main (void)
{
int x = 10;
int *px;
px = &x;
printf (" x = %d\n", x);
printf (" &x = %p\n", &x);
printf (" px = %p\n", px);
printf (" &px = %p\n", &px);
printf (" *px = %d", *px);
}
Salida de ejemplo 2:
x = 10
&x = 8FC4:0FFE
Gr ficamente:
px x
8FC4:0FFE 10
8FC4:0FFA 8FC4:0FFE
En el ejemplo anterior se observa que hay tres valores asociados a los punteros:
- Direccin en la que se encuentra.
- Direccin a la que apunta.
- Valor contenido en la direccin apuntada.
--OJO!! Al ejecutar el siguiente programa los resultados pueden ser inesperados ya que estamos asignando
el valor 10 en una posicin de memoria no reservada:
Sera correcto:
ARITMETICA DE PUNTEROS
Existen 4 operadores que realizan operaciones aritmticas que pueden utilizarse con punteros: +, -, ++, --
#include <stdio.h>
imprimir_p;
printf ("\tsizeof(*p) = %d", sizeof(*p));
p++; imprimir_p;
p -= 5; imprimir_p;
}
En el ejemplo anterior se aprecia que si hacemos p++; no aumenta el valor de p en 1 sino que aumenta en
2, que es el tamao en bytes de un int, es decir, el tamao del objeto al que apunta.
Por lo tanto, la sentencia p++ hay que interpretarla de la siguiente forma: p apunta al siguiente elemento
del tipo base. Lo mismo se puede decir de los dems operadores aritmticos aplicados a los punteros.
Toda la aritmtica de punteros est en relacin con el tipo base del puntero por lo que el puntero est
siempre apuntando al elemento apropiado del tipo base.
Supngase que queremos hacer un programa que lea n valores enteros introducidos por teclado por el
usuario, los almacene en un vector y los imprima en orden inverso.
#include <stdio.h>
do
{
printf ("\nIntroduce nmero de valores a leer (1-%d): ", NMAX);
scanf ("%d", &n);
} while (n < 1 n > NMAX);
Si el usuario introduce como valor de n, el valor 10, estaremos desperdiciando, si un int ocupa 2 bytes, 90*2
bytes de memoria. Adems, el usuario no puede introducir ms de NMAX valores. Estas restricciones
vienen impuestas poque el tamao de un array en la declaracin ha de ser una expresin constante. La
asignacin de memoria en este caso se dice que es esttica porque se determina en el momento de la
compilacin. Cuando la asignacin de memoria se determina en tiempo de ejecucin se dice que es
asignacin din mica.
Veamos cmo se hara el programa anterior con asignacin din mica y luego pasamos a explicarlo:
La funcin malloc reserva memoria; acepta como argumento los bytes de memoria a reservar y devuelve un
puntero al primer byte de la zona de memoria reservada; los bytes de memoria solicitados los reserva en un
espacio de memoria contiguo. Si no hay suficiente memoria, devuelve NULL. Un puntero que tiene el valor
NULL es un puntero que no apunta a ningn sitio.
El prototipo de esta funcin se encuentra en el fichero malloc.h (de ah el incluir este fichero en nuestro
ejemplo) y es el siguiente:
Vemos que devuelve un puntero a void; esto quiere decir que devuelve un puntero que apunta a cualquier
tipo base, o dicho de otro modo, un puntero que apunta a una direccin de memoria sin tener tipo base.
El C de Kernighan y Ritchie, como no tiene tipo void, el prototipo de esta funcin es:
En ambos casos, el tratamiento por parte del usuario de esta funcin es exactamente el mismo.
El argumento que le pasamos a malloc ha de ser el nmero de bytes de memoria a reservar. Esto siempre
se hace siguiendo la frmula:
n * sizeof (int)
n * sizeof (*v)
que suele ser muy corriente. Las dos formas son equivalentes.
La memoria asignada por malloc se desasigna con la funcin free(). Esta memoria asignada no se
desasigna al salir del bloque de cdigo en que fue asignada como ocurre con las variables locales sino con
la funcin free (liberar) o al terminar el programa. Por lo tanto, siempre que asignemos memoria con malloc,
tenemos que desasignarla con free cuando ya no nos sea necesaria.
Un puntero a void como parmetro indica que acepta cualquier puntero, independientemente del tipo base
al que apunta. El puntero que se le pasa a free como argumento ha de ser un puntero que apunta al
principio de una zona reservad anteriormente por malloc; si no es as , se puede caer el sistema.
Esta funcin es igual que malloc con la nica diferencia de sus parmetros.
En Turbo C, los prototipos de las funciones malloc(), calloc() y free(), adems de estar en el fichero alloc.h,
tambinestn en el fichero stdlib.h.
PUNTEROS Y ARRAYS
Exite una estrecha relacin entre los punteros y los arrays. Ya hemos dicho en varias ocasiones en
lecciones anteriores que el nombre de un array es un puntero al primer elemento del array.
Arrays unidimensionales:
p[i] == *(p+i)
Arrays bidimensionales:
p[i][j] == *(p+(i*longitud_fila)+k) == *(*(p+i)+j)
Arrays muldimensionaes:
/*
EJEMPLO DE ACCESO A UN ARRAY CON UN PUNTERO
*/
#include <stdio.h>
Los programadores profesionales de C suelen utilizar la notacin puntero en vez de la notacin array
porque es bastante ms rpido y ms cmodo, aunque para los no acostrumbrados a esta notacin se ve
un poco extrao al principio. Pensad que con notacin array, para acceder a un determinado elemento, el
compilador tiene que hacer una serie de c lculos para averiguar en qu posicin est , mientras que en la
notacin puntero basta con una simple suma. No obstante, cuando el cdigo queda ms claro en la
notacin array que con la notacin puntero es preferible la primera notacin.
Cuando se trabaja con cadenas de caracteres sse debe utilizar la notacin puntero, no ya slo por
eficiencia sino tambinpor convencin.
Una estructura comn en C es el array de punteros. Recordar que el argumento argv de la funcin main()
es un array de punteros a caracteres.
Para asignar la direccin de una variable entera llamada var al tercer elemento del array de punteros, se
escribe: x[2] = &var; Para encontrar el valor de var, se escribe: *x[2]
/*
Un array de punteros es lo mismo que punteros a punteros. Este ejemplo comprueba dicha afirmacin.
*/
#include <stdio.h>
A continuacin vamos a mostrar dos formas de implementar la siguiente funcin: la funcin a implementar
acepta como argumentos una matriz de enteros y un elemento, y devuelve 1 si ese elemento se encuentra
en la matriz o 0 si dicho elemento no se encuentra en la matriz.
/*
Las funciones buscar_en_matriz_version_1() y
buscar_en_matriz_version_2() son equivalentes
pero la segunda es mucho ms eficiente.
*/
#include <stdio.h>
#define N 3
return (encontrado);
}
return (encontrado);
}
resultado_1 = 1
resultado_2 = 0
resultado_3 = 1
resultado_4 = 0
INICIALIZACIONES DE PUNTEROS
Un puntero que tiene el valor NULL es un puntero que no apunta a ningn sitio.
char *p = cadena\n;
En este caso el compilador guarda cadena\n en memoria y hace que p apunte al principio de la cadena, es
decir, el carcter 'c'.
int x;
int x, *p, y; <==> int *p;
int y;
int *p;
int *p, *q, r = 10; <==> int *q;
int r = 10;
PUNTEROS A FUNCIONES
Una caracterstica algo confusa pero muy til de C es el puntero a funcin. La confusin surge porque una
funcin tiene una posicin fsica en memoria que puede asignarse a un puntero aunque la funcin no es
una variable. La direccin de la funcin es el punto de entrada de la funcin; por tanto, un puntero a funcin
puede utilizarse para llamar a la funcin.
Ejemplo:
pf = escribir;
escribir (1); /* llama a la funcin escribir */
(*pf) (2); /* llama a la funcin escribir a travs de un puntero */
}
Una utilidad de los punteros a funciones la tenemos en las funciones qsort() y bsearch() cuyos prototipos
estn en el fichero stdlib.h.
void qsort (void *base, unsigned int num, unsigned int tam,
int (*compara) (void *arg1, void *arg2));
La funcin qsort() ordena el array apuntado por base utilizando el mtodo de ordenacin de C.A.R. Hoare
(este mtodo se ha explicado en el ejemplo 3 de la leccin 5). El nmero de elementos en el array se
especifica mediante num, y el tamao en bytes de cada elemento est descrito por tam.
La funcin compara se utiliza para comparar un elemento del array con la clave. La comparacin debe ser:
size_t es un tipo definido en el fichero stdlib.h y suele ser unsigned int; (const void *) no es lo mismo que
(void *), la diferencia entre ellos se va a estudiar unas tres o cuatro ventanas ms adelante, pero podemos
intuirla: en (const void *) el objeto apuntado es constante, es decir, no se puede modificar, en (void *) el
objeto apuntado por el puntero sse puede modificar.
Veamos un ejemplo de la utilizacin de esta funcin, donde podemos apreciar adems, dos formas posibles
de declaracin y utilizacin de la funcin de comparacin requerida por la funcin qsort().
/*
el molde del cuarto argumento convierte el tipo
(int (*) (const int *, const int *))
al tipo
(int (*) (const void *, const void *))
que es el que requiere la funcin qsort
*/
qsort (num, 10, sizeof (int),
(int (*) (const void *, const void *)) comparar_decreciente);
Array desordenado: 3 2 8 9 2 2 1 -2 3 2
Array ordenado en orden creciente: -2 1 2 2 2 2 3 3 8 9
Array ordenado en orden decreciente: 9 8 3 3 2 2 2 2 1 -2
La funcin bsearch() realiza una bsqueda binaria en el array ordenado apuntado por base y devuelve un
puntero al primer elemento que se corresponde con la clave apuntada por clave. El nmero de elementos
en el array est especificado por num y el tamao (en bytes) de cada elemento est descrito por tam.
La funcin apuntada por compara se utiliza para comparar un elemento del array con la clave. La forma de
la funcin de comparacin debe ser:
El array debe estar ordenado en orden ascendente con la menor direccin conteniendo el elemento ms
Pequeo. Si el array no contiene la clave, se devuelve un puntero nulo.
void *bsearch (const void *clave, const void *base, unsigned int *num,
unsigned int tam, int (*compara) (const void *arg1, const void *arg2));
Los tipos size_t y (const void *) se han explicado en la ventana anterior: qsort().
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
int array_de_numeros[] = { 123, 145, 512, 627, 800, 933, 333, 1000 };
/* El molde (int (*) (const void *, const void *)) es necesario para
return 0;
}
lfind () y lsearch ()
Estas dos funciones no pertenecen al ANSI C actual pero sestn incluidas en las versiones de Turbo C.
Ambas funciones realizan una bsqueda lineal. Sus prototipos estn en el fichero stdlib.h y son los
siguientes:
void *lsearch (const void *clave, void *base, size_t *num, size_t anchura,
int (*func_de_comp) (const void *elem1, const void *elem2));
Estas funciones utilizan una rutina definida por el usuario (func_de_comp) para la bsqueda de la clave, en
un array de elementos secuenciales. El array tiene num elementos, cada uno de tamao anchura bytes y
comienza en la direccin de memoria apuntada por base. Devuelve la direccin de la primera entrada en la
tabla que coincida con la clave buscada. Si la clave buscada no se encuentra, lsearch la aade a la lista;
lfind devuelve 0.
La rutina *func_de_comp debe devolver cero si *elem1 == *elem2, y un valor distinto de cero en caso
contrario.
#include <stdio.h>
#include <stdlib.h>
clave = 99;
resultado = lfind(&clave, array, &nelem, sizeof (int),
(int (*) (const void *, const void *)) comparar);
if (resultado)
printf ("Nmero %d encontrado\n", clave);
else
printf ("Nmero %d no encontrado.\n", clave);
return 0;
}
Nmero 99 encontrado.
#include <stdlib.h>
#include <stdio.h>
int numeros[10] = { 3, 5, 1 };
int nnumeros = 3;
if (aniadir_elemento (clave))
printf ("%d est ya en la tabla de nmeros.\n", clave);
else
printf ("%d est aadido a la tabla de nmeros.\n", clave);
return 0;
Hasta esta leccin hemos visto que el tipo void tiene dos usos:
Aplicados a punteros tiene otro uso: los punteros a void son punteros genricos que pueden apuntar a
cualquier objeto. Pero los punteros a void no pueden ser referenciados (utilizando *) sin utilizar moldes,
puesto que el compilador no puede determinar el tamao del objeto al que apunta el puntero. Ejemplo:
int x; float f;
void *p = &x; /* p apunta a x */
int main (void)
{
*(int *) p = 2;
p = &r; /* p apunta a f */
*(float *) p = 1.1;
}
El modificador de acceso const aplicado a punteros ofrece varias posibilidades. Ve mosla en los siguientes
ejemplos:
p1++; /* correcto */
p2++; /* correcto */
p3++; /* error */
p4++; /* error */
p1 = p2; /* warning */
p1 = p3; /* correcto */
p1 = p4; /* warning */
p3 = p1; /* error */
p3 = p2; /* error */
p3 = p4; /* error */
p4 = p1; /* error */
p4 = p2; /* error */
p4 = p3; /* error */
}
Las lneas que contienen el mensaje de error provocan un error de compilacin. Las lneas que contienen el
mensaje de warning provoca en algunos compiladores un mensaje de conversin de puntero sospechosa
que se puede solucionar haciendo la conversin de una forma explcita:
p1 = (char *) p2;
p1 = (char *) p4;
Si ahora hacemos:
*p1 = 'd';
estamos modificando los valores apuntados por p2 y p4; es decir, los valores apuntados por p2 y p4 no
pueden ser modificados por estos punteros pero spueden ser modificados indirectamente por otro puntero.
Otro ejemplo de cmo se puede modificar el valor de una constante indirectamente a travs de un puntero:
DECLARACIONES CURIOSAS
El C permite la creacin de formas de datos muy elaboradas. Cuando se hace una declaracin, el nombre
(o identificador) que usamos se puede modificar aadindole uno o varios modificadores:
Modificador Significado
----------- --------------------
* indica un puntero
() indica una funcin
[] indica un array
La clave para desentraar las declaraciones que mostraremos a continuacin es averiguar el orden en que
se aplican los modificadores. Para ello se siguen tres reglas:
3. Se pueden usar parntesis para agrupar parte de la expresin otorg ndole la mxima prioridad.
Ejemplos:
En MS-DOS se suele direccionar memoria en la forma: segmento:offset donde cada segmento son 64K y
offset es el desplazamiento dentro de cada segmento.
Los modificadores de tipo near, far y huge, que slo se pueden aplicar a punteros y funciones, estn
relacionados con el direccionamiento de memoria. El modificador near (cerca) fuerza que el valor de un
puntero o una funcin estn en un slo segmento mientras que far (lejos) y huge (enorme) hacen que un
puntero pueda apuntar a cualquier direccin de la memoria y una funcin puede estar en cualquier lugar de
la memoria disponible.
near (modificador de tipo)
Fuerza a los punteros a ser near (estar cerca, un mismo segmento), genera cdigo de funciones para
llamadas near y devuelve un valor near.
La primera versin de near declara un puntero de tamao una palabra (2 bytes) con un rango de 64K. Este
modificador de tipo es usado normalmente cuando se compila en los modelos de memoria medium, large y
huge para forzar a que los punteros sean near (ya que por defecto, son far, en los modelos de memoria
mencionados).
Ejemplo
Cuando near es usado con una declaracin de funcin, Turbo C genera cdigo de funcin para una llamada
near y devuelve near.
Ejemplo
far (modificador de tipo)
Fuerza a los punteros a ser far (estar lejos, cualquier segmento), genera cdigo de funciones para llamadas
far y devuelve un valor far.
La primera versin de far declara un puntero de tamao dos palabras (4 bytes) con un rango de 1
megabyte. Este modificador de tipo es usado normalmente cuando se compila en los modelos de memoria
tiny, small y compact para forzar a que los punteros sean far (ya que por defecto, son near, en los modelos
de memoria mencionados).
Ejemplo
Cuando far es usado con una declaracin de funcin, Turbo C genera cdigo de funcin para una llamada
far y devuelve far.
Ejemplo
El modificador huge es similar al modificador far pero tiene dos caractersticas adicionales:
Los punteros huge pueden ser incrementados sin el temor de que sobrepase un segmento.
En resumen, la utilizacin de punteros huge es ms segura que la utilizacin de punteros far, pero su uso
es ms lento porque requieren ms comprobaciones.
Opciones de modelo
Las opciones de modelo especifican qu modelo de memoria se quiere usar. El modelo de memoria elegido
determina el mtodo de direccionamiento de memoria por defecto.
Segmentos Punteros
Modelo CdigoDatos Pila CdigoDatos
Tiny
Usa el modelo tiny (muy Pequeo) cuando la cantidad de memoria a consumir es muy importante y ha de
ser la menor posible.
Los cuatro registros de segmentos (CS, DS, ES, SS) toman la misma direccin, de este modo tenemos un
total de 64K para cdigo, datos y pila. Siempre se usan punteros near.
Small
Los segmentos de cdigo y datos son diferentes, as que tenemos 64K de cdigo y 64K de datos y pila.
Medium
El modelo medium (medio) es mejor para grandes programas que no guardan muchos datos en memoria.
Los punteros far son usados para cdigo pero no para datos. Esto da como resultado que los datos y la pila
juntos estn limitados a 64K, pero el cdigo puede ocupar hasta 1MB.
Compact
Usa el modelo compact (compacto) si tu cdigo es Pequeo pero necesitas direccionar una gran cantidad
de datos.
El modelo compact es el contrario al modelo medium: los punteros far son usados para los datos pero no
para el cdigo; el cdigo est limitado entonces a 64K, mientras que los datos tienen un rango de 1Mb.
Todas las funciones son near por defecto y todos los punteros de datos son far por defecto.
Large
Los punteros far son usados para cdigo y datos, dando un rango de 1Mb para ambos. Todas las funciones
y punteros de datos son far por defecto.
Huge
Usa el modelo huge (muy grande) para aplicaciones muy grandes solamente. Los punteros far son usados
para el cdigo y los datos.
Turbo C limita normalmente el tamao de los datos a 64K; el modelo de memoria huge aparta ese lmite
permitiendo a los datos ocupar ms de 64K.
El modelo huge permite mltiples segmentos de datos (cada uno de 64K de tamao), hasta 1MB para el
cdigo, y 64K para la pila.
LECCION 8
INTRODUCCION A LA LECCION 8
El objetivo de esta leccin es hacer un estudio completo en todo lo referente a la declaracin, utilizacin e
inicializacin de tipos compuestos de datos y explicar cmo se pueden crear nuevos tipos de datos a partir
de los ya existentes.
- Estructuras (struct).
- Campos de bits.
- Uniones (union).
- Enumeraciones (enum).
- Tipos definidos por el usuario (typedef).
Al terminar la leccin se presenta una tabla de precedencia de todos los operadores del lenguaje C.
ESTRUCTURAS
En el lenguaje C una estructura es un conjunto de variables que se referencia bajo un mismo nombre,
proporcionando un medio conveniente de mantener junta informacin relacionada.
DECLARACION DE ESTRUCTURAS
Una estructura se declara con la palabra struct seguida de una lista de declaraciones encerradas entre
llaves. Ejemplo:
struct
{
int dia;
int mes;
int anio;
};
struct fecha
{
int dia;
int mes;
int anio;
};
En los ejemplos anteriores no se han declarado realmente variables, sino que slo se han definido la forma
de los datos.
struct
{
int dia, mes, anio;
} fecha_creacion;
struct
{
o bien:
Tambinse puede crear un tipo estructura y una variable de tipo estructura al mismo tiempo:
struct
{
int dia, mes, anio;
} fecha1, fecha2, fecha3;
struct nombre_tipo_estructura
{
tipo_1 nombre_variable_1;
tipo_2 nombre_variable_2;
...
tipo_n nombre_variable_n;
} nombres_variables_estructura;
INICIALIZACION DE ESTRUCTURAS
El tamao en bytes de un tipo estructura en memoria es la suma de los tamaos en bytes de cada uno de
los tipos de sus componentes:
Los elementos individuales de la estructura se referencia utilizando el operador punto (.). La forma general
es:
fecha_creacion.dia = 3;
printf (%d, fecha_creacion.dia); /* muestra el valor 3 */
Un elemento de una estructura, el nombre de una estructura y una variable ordinaria pueden tener el mismo
nombre; siempre se pueden distinguir a travs del contexto. Por supuesto que estas cosas se deben evitar
en lo posible si disminuyen la legibilidad del cdigo. Por ejemplo:
struct x { int x; } x;
ARRAYS DE ESTRUCTURAS
struct x struct x
{ {
char *s; char *s;
int d; int d;
} y[] = o tambin } y[] =
{ {
s1, 4, { s1, 4 },
s2, 3, { s2, 3 },
s3, 10 { s3, 10 }
}; };
Utilizacin:
Declaracin:
struct x
{
int a[10];
float b;
} y;
Utilizacin:
y.a[1] = 2;
Declaracin:
struct persona
{
char nombre[TAMNOMBRE], direccion[TAMDIRECCION];
struct fecha fecha_nacimiento;
} empleado;
Utilizacin:
empleado.fecha_nacimiento.dia = 10;
PUNTEROS A ESTRUCTURAS
Declaracin:
Utilizacin:
1) (*pfecha).dia = 20;
Los parntesis son necesarios porque el operador . tiene ms prioridad que el operador *.
2) pfecha->dia = 20;
El operador -> se utiliza para acceder a un elemento de una estructura a travs de un puntero.
Esta forma es mucho ms comn que la anterior, es ms, el primer mtodo se considera arcaico en los
estndares actuales.
Debido a que este tipo de operacin es tan comn, C proporciona un operador especfico para realizar
esta tarea: el operador flecha (->).
ESTRUCTURAS Y FUNCIONES
Con respecto a las estructuras, a una funcin le podemos pasar como argumento:
Cuando se pasa un elemento de una variable de estructura a una funcin, se est realmente pasando el
valor de ese elemento a la funcin. Adems, si ese elemento es de tipo simple, se est pasando una
variable simple.
Ejemplo:
struct x
{
int i;
char c;
char s[10];
} y = { 2, 'd', string };
Cuando se utiliza una estructura como argumento de una funcin, se pasa la estructura ntegra mediante el
uso del mtodo estndar de llamada por valor. Esto significa, por supuesto, que todos los cambios
realizados en los contenidos de la estructura, dentro de la funcin a la que se pasa, no afectan a la
estructura utilizada como argumento.
#include <stdio.h>
void f (param)
struct { int x, y; } param;
{
printf ("%d", param.x);
}
#include <stdio.h>
void f (param)
struct st param;
{
printf ("%d", param.a);
}
En la prctica nunca se pasan las estructuras completas a funciones porque ese procedimiento es
tremendamente ineficiente (en cuanto atiempo y memoria consumida). Lo que se hace en lugar de ello es
pasar ladireccin de la variable estructura como argumento y declarar el parmetro de la funcin como un
puntero a esta estructura.
void f (param)
struct st *param;
{
printf (%d, param->a);
}
Si consideramos que sizeof(struct st *)==2 y sizeof(int)==2, entonces sizeof(struct st)==4. Por lo tanto, al
pasar la estructura ntegra pasamos 4 bytes a la funcin y al pasar el puntero a la estructura slo pasamos
2 bytes a la funcin. En el ejemplo visto la diferencia no parece muy significativa, pero si sizeof(struct
st)==1000, al pasar la estructura ntegra pasamos 1000 bytes mientras que con su direccin pasamos 2
bytes.
Para los usuarios que tengan la opcin turbo on, recordar n que los punteros near ocupan 2 bytes (slo
contienen el desplazamiento dentro del segmento de memoria) y los punteros far 4 bytes (contienen
segmento y desplazamiento dentro del segmento). Al suponer en el p rrafo anterior que sizeof(struct st
*)==2, estamos suponiendo que el puntero es near.
CAMPO DE BITS
DECLARACION
struct nombre_estructura
{
tipo1 nombre1 : longitud1;
tipo2 nombre2 : longitud2;
...
};
Un campo de bits tiene que declararse como int, unsigned, o signed. Los campos de bits de longitud 1
deben declararse como unsigned debido a que un bit individual no puede tener signo. Los nombres de los
campos son opcionales.
EJEMPLO
struct operacion
{
A los campos de bits se accede de la misma forma que a los campos de cualquier estructura:
operacion_fichero.abrir = 1;
Los campos de bits tienen algunas restricciones: no se puede tomar la direccin de una variable de campos
de bits; en algunas m quinas, los campos se disponen de izquierda a derecha y en otras de derecha a
izquierda, esto implica cdigo menos portable.
Se puede mezclar elementos normales de estructura con elementos de campos de bits. Por ejemplo:
struct st
{
char ch;
unsigned c1: 1;
unsigned c2: 3;
};
El tamao de esta estructura, sizeof (struct st), es 2: 1 byte para ch y 1 byte para c1 y c2.
UNIONES
Las uniones son similares a las estructuras. Su declaracin y utilizacin es exactamente igual que el de las
estructuras con la excepcin que utiliza la palabra clave union en vez de struct.
La diferencia que hay entre una variable estructura y una variable unin es que es esta ltima todos sus
elementos ocupan la misma posicin de memoria.
Ejemplo:
#include <stdio.h>
void main (void)
{
union { int x, y; } u;
u.x = 10; /* tambinestamos haciendo u.y = 10, puesto
que x e y comparten la misma posicin de memoria */
printf ("%d", u.y); /* imprime 10 */
}
El tamao del tipo union es el tamao del elemento que necesita ms memoria.
Ejemplo:
#include <stdio.h>
void main (void)
{
union
{
char ch;
int i;
} u;
u.i = 257;
printf ("%d %d", u.ch, (char) u.i); /* imprime: 1 1 */
ENUMERACIONES
Una enumeracin es un conjunto de constantes enteras con nombre que especifica todos los valores v lidos
que una variable de ese tipo puede tomar. La forma general de declaracin es:
Aqu, al igual que con las estructuras, tanto el nombre de la enumeracin nombre_tipo_enum como
lista_variables son opcionales.
Ejemplo:
Dada esta declaracin y definicin la variable color solo puede tomar tres valores posibles: azul, rojo o
amarillo.
Ejemplo:
color = rojo;
if (color == azul)
printf ("el color es azul");
Cada uno de los smblos del conjunto de enumeracin es un valor entero, tomando el primero el valor 0, el
segundo el valor 1 y as sucesivamente.
Ejemplo:
Podramos haber dado otros valores numricos a los smbolos si hubisemos declarado es, por ejemplo, del
siguiente modo:
Como se ve, los smbolos no inicializados toman el valor numrico siguiente al del smbolo anterior, excepto
el primero que toma el valor 0 si no es inicializado.
El programador puede crear (dar nombre en realidad) tipos a partir de los tipos ya definidos mediante la
palabra clave typedef. La forma general de la sentencia typedef es: typedef tipo nombre; donde tipo es
cualquier tipo de datos permitido y nombre es el nuevo nombre para ese tipo.
El uso de typedef hace ms f cil de leer el cdigo y ms f cil de transportar a una nueva m quina. Pero
recuerda: NO se crea ningn tipo de datos nuevo, slo se da otro nombre.
Ejemplos:
struct st { int x, y; };
typedef struct st s;
s estructura2; /* equivalente a: struct st estructura; */
PRECEDENCIA DE OPERADORES
Con los operadores punto (.) y flecha (->) hemos completado el estudio de todos los operadores de C. A
continuacin mostramos la tabla completa de precedencia de operadores.
Precedencia de Operadores
Los operadores que estn dentro de una misma categora tienen igual precedencia.
Los operadores unarios (categora #2), condicional (categora #13), y de asignacin (categora #14) se
asocian de derecha a izquierda; todos los dems operadores se asocian de izquierda a derecha.
3. Multipli- * Multiplica
cativo / Divide
4. Aditivo + Ms binario
- Menos binario
7. Igualdad == Igual a
!= Distinto a
12. OR lgico
LECCION 9
INTRODUCCION A LA LECCION 9
El objetivo de esta leccin es hacer un estudio completo en todo lo referente a la entrada y, salida (E/S) en
C, estudiando tambinlos dos sistemas de ficheros que existen en este lenguaje.
- Pasos a realizar para manipular un fichero: declarar variable de fichero, abrirlo, operar con l y cerrarlo.
- Estructura FILE.
ENTRADA Y SALIDA
Las operaciones de entrada y salida (abreviadamente E/S) no forman parte del lenguaje C propiamente
dicho, sino que estn en una biblioteca o librera. Todo programa que utilice funciones de entrada y salida
estndar deber contener la lnea:
#include <stdio.h>.
E/S estndar
Por defecto, la entrada estndar es el teclado y la salida estndar es la pantalla o monitor. Hay dos formas
b sicas de cambiar la entrada y la salida estndar:
1. Con los smbolos de redireccin (<, >, <<, >>) o de tubera () del sistema operativo al ejecutar el
programa desde la lnea de rdenes.
FLUJOS Y FICHEROS
Hay dos conceptos muy importantes en C relacionados con la E/S: flujos (streams, en ingls) y ficheros. Los
flujos son sucesiones de caracteres a travs de los cuales realizamos las operaciones de E/S. Para el
programador todos los flujos son iguales. Para el C (en general para el sistema operativo) un fichero es un
concepto lgico que puede ser aplicado a cualquier cosa desde ficheros de discos a terminales. A cada
fichero se le asigna un flujo al realizar la operacin de apertura sobre l. Para el programador un fichero es
un dispositivo externo capaz de una E/S. Todos los ficheros no son iguales pero todos los flujos s. Esto
supone una gran simplificacin para el usuario, ya que slo tiene que pensar en trminos de flujo y no de
dispositivos concretos. Por ejemplo, si el usuario hace: printf (mensaje); sabe que mensaje se escribe en
el flujo estndar de salida, ya sea la pantalla, un fichero de disco, una cinta, ...
TIPOS DE FLUJOS
Cuando hemos dicho que todos los flujos son iguales, es cierto que lo son en su utilizacin por parte del
programador, pero en realidad, podemos distinguir dos tipos:
- Flujos de texto: son una sucesin de caracteres originado en lneas que finalizan con un carcter de
nueva-lnea. En estos flujos puede no haber una relacin de uno a uno entre los caracteres que son
escritos (ledos) y los del dispositivo externo, por ejemplo, una nueva-lnea puede transformarse en un par
de caracteres (un retorno de carro y un carcter de salto de lnea).
- Flujos binarios: son flujos de bytes que tienen una correspondencia uno a uno con los que estn
almacenados en el dispositivo externo. Esto es, no se presentan desplazamientos de caracteres. Adems el
nmero de bytes escritos (ledos) es el mismo que los almacenados en el dispositivo externo.
Esta diferencia de flujos es importante tenerla en cuenta al leer ficheros de discos. Supongamos que
tenemos un fichero de disco con 7 caracteres donde el cuarto carcter es el carcter fin de fichero (en
sistema operativo DOS es el carcter con cdigo ASCII 26). Si abrimos el fichero en modo texto, slo
podemos leer los 3 primeros caracteres, sin embargo, si lo abrimos en modo binario, leeremos los 7
caracteres ya que el carcter con cdigo ASCII 26 es un carcter como cualquier otro.
Al finalizar el programa, bien volviendo de la funcin main al sistema operativo o bien por una llamada a
exit(), todos los ficheros se cierran automtica mente. No se cerrar n si el programa termina a travs de una
llamada a abort() o abortando el programa.
En Turbo C, adems de abrirse los tres flujos anteriores se abren otros dos flujos de texto predefinidos:
Como todo lo que acabamos de decir puede resultar un poco confuso a las personas que tienen poca
experiencia en C, vamos a hacer un Pequeo resumen en trminos generales:
1. En C, cualquier cosa externa de la que podemos leer o en la que podemos escribir datos es un fichero.
2. El programador escribe (lee) datos en estos ficheros a travs de los flujos de cada fichero. De esta forma
el programador escribe (lee) los datos de la misma forma en todos los tipos de ficheros independientemente
del tipo de fichero que sea.
3. Aunque conceptualmente todos los flujos son iguales, en realidad hay dos tipos: flujos de texto y flujos
binarios.
4. Hay tres flujos de texto predefinidos que se abren automtica mente al principio del programa: stdin,
stdout y stderr. Estos tres flujos se cierran automtica mente al final del programa.
Los pasos a realizar para realizar operaciones con un fichero son los siguientes:
1) Crear un nombre interno de fichero. Esto se hace en C declarando un puntero de fichero (o puntero a
fichero). Un puntero de fichero es una variable puntero que apunta a una estructura llamada FILE. Esta
estructura est definida en el fichero stdio.h y contiene toda la informacin necesaria para poder trabajar
con un fichero. El contenido de esta estructura es dependiente de la implementacin de C y del sistema, y
no es interesante saberlo para el programador.
Ejemplo:
2) Abrir el fichero. Esto se hace con la funcin fopen() cuyo prototipo se encuentra en el fichero stdio.h y es:
El parmetro nombre_fichero puede contener la ruta completa de fichero pero teniendo en cuenta que la
barra invertida (\) hay que repetirla en una cadena de caracteres.
Modo Interpretacin
---- -----------------------------------------------
r Abrir un fichero texto para lectura
w Crear un fichero texto para escritura
a Aadir a un fichero texto
rb Abrir un fichero binario para lectura
wb Crear un fichero binario para escritura
ab Aadir a un fichero binario
r+ Abrir un fichero texto para lectura/escritura
w+ Crear un fichero texto para lectura/escritura
a+ Abrir un fichero texto para lectura/escritura
rb+ Abrir un fichero binario para lectura/escritura
wb+ Crear un fichero binario para lectura/escritura
ab+ Abrir un fichero binario para lectura/escritura
Si se utiliza fopen() para abrir un fichero para escritura, entonces cualquier fichero que exista con ese
nombre es borrado y se comienza con un fichero nuevo. Si no existe un fichero con ese nombre, entonces
se crea uno. Si lo que se quiere es aadir al final del fichero, se debe utilizar el modo a. Si no existe el
fichero, devuelve error. Abrir un fichero para operaciones de lectura necesita que el fichero exista. Si no
existe devuelve error. Finalmente, si se abre un fichero para operaciones de lectura/escritura, no se borra
en caso de existir. Sin embargo, si no existe se crea.
Ejemplo:
FILE *pf;
pf = fopen ("c:\\autoexec.bat", r);
if (pf == NULL) /* siempre se debe hacer esta comprobacin */
{
puts ("No se puede abrir fichero.");
exit (1);
}
3) Realizar las operaciones deseadas con el fichero como pueden ser la escritura en l y la lectura de l. Las
funciones que disponemos para hacer esto las veremos un poco ms adelante.
4) Cerrar el fichero. Aunque el C cierra automtica mente todos los ficheros abiertos al terminar el
programa, es muy aconsejable cerrarlos explcitamente. Esto se hace con la funcin fclose() cuyo prototipo
es:
La funcin fclose() cierra el fichero asociado con el flujo pf y vuelca su buffer. Si fclose() se ejecuta
correctamente devuelve el valor 0. La comprobacin del valor devuelto no se hace muchas veces porque no
suele fallar.
Ejemplo:
FILE *pf;
if ((pf = fopen (prueba, rb)) == NULL)
{
puts ("Error al intentar abrir el fichero.");
exit (1);
}
/* ... */
if (fclose (pf) != 0)
{
puts ("Error al intentar cerrar el fichero.");
exit (1);
2) Abrirlo el fichero.
if ((pf = fopen (nombre_fichero, modo_apertura)) == NULL)
error ();
else
/* ... */
4) Cerrar el fichero.
if (fclose (pf) != 0)
error ();
else
/* ... */
GLOSARIO:
Sintaxis:
int fclose (FILE *flujo);
Un error puede ocurrir por ejemplo cuando se intenta cerrar un fichero que ha sido ya cerrado.
Ejemplo:
FILE *pf;
/* ... */
feof Macro que devuelve un valor distinto de cero si se se ha detectado el fin de fichero en
un flujo.
Sintaxis:
int feof (FILE *flujo);
Una vez alcanzado el final del fichero, las operaciones posteriores de lectura devuelven EOF hasta que se
cambie la posicin del puntero del fichero con funciones como rewind() y fseek().
La funcin feof() es particularmente til cuando se trabaja con ficheros binarios porque la marca de fin de
fichero es tambinun entero binario
v lido.
Ejemplo:
Sintaxis:
int ferror (FILE *flujo);
Ejemplo:
Sintaxis:
int fflush (FILE *flujo);
Si el flujo est asociado a un fichero para escritura, una llamada a fflush() da lugar a que el contenido del
buffer de salida se escriba en el fichero. Si flujo apunta a un fichero de entrada, entonces el contenido del
buffer de entrada se vaca. En ambos casos el fichero permanece abierto.
Ejemplo:
Sintaxis:
int fgetc (FILE *flujo);
La funcin fgetc() devuelve el siguiente carcter desde el flujo de entrada e incrementa el indicador de
posicin del fichero. El carcter se lee como un unsigned char que se convierte a entero.
Si se alcanza el final del fichero, fgetc() devuelve EOF. Recuerda que EOF es un valor entero. Por tanto,
cuando trabajes con ficheros binarios debes utilizar feof() para comprobar el final del fichero. Si fgetc()
encuentra un error, devuelve EOF tambin. En consecuencia, si trabajas con ficheros binarios debe utilizar
ferror() para comprobar los errores del fichero.
Ejemplo:
Sintaxis:
int fgetchar (void);
Si tiene xito, getchar() devuelve el carcter ledo, despus de convertirlo a int sin extensin de signo. En
caso de fin de fichero o error, devuelve EOF.
Ejemplo:
ch = getchar ();
Sintaxis:
char *fgets (char *s, int n, FILE *flujo);
La funcin fgets() lee hasta n-1 caracteres desde el flujo y los sita en el array apuntado por s. Los
caracteres se leen hasta que se recibe un carcter de nueva lnea o un EOF o hasta que se llega al lmite
especificado. Despus de ledos los caracteres, se sita en el array un carcter nulo inmediatamente
despus del ltimo carcter ledo. Se guarda un carcter de nueva lnea y forma parte de s.
Si fgets() tiene xito devuelve la direccin de s; se devuelve un puntero nulo cuando se produce un error.
Ya que se devuelve un puntero nulo cuando se produce un error o cuando se alcanza el final del fichero,
utiliza feof() o ferror() para identificar lo que ocurre realmente.
Ejemplo:
Sintaxis:
FILE *fopen (const char *nombre_fichero, const char *modo_apertura);
Devuelve un puntero al flujo abierto si tiene xito; en otro caso devuelve NULL.
Ejemplo:
FILE *pf;
Sintaxis:
int fprintf (FILE *flujo, const char *formato[, argumento, ...]);
Esta funcin es idntica a la funcin printf() con la excepcin que printf() escribe en la salida estndar (flujo
stdout) y la funcin fprintf() escribe en la salida especificada (flujo indicado en su primer argumento).
Ejemplo:
Sintaxis:
int fputc (int c, FILE *flujo);
La funcin fputc() escribe un carcter c en el flujo especificado a partir de la posicin actual del fichero y
entonces incrementa el indicador de posicin del fichero. Aunque ch tradicionalmente se declare de tipo int,
es convertido por fputc() en unsigned char. Puesto que todos los argumentos de tipo carcter son pasados
a enteros en el momento de la llamada, se seguir n viendo variables de tipo carcter como argumentos. Si
se utilizara un entero, simplemente se eliminara el byte ms significativo.
El valor devuelto por fputc() es el valor de nmero de carcter escrito. Si se produce un error, se devuelve
EOF. Para los ficheros abiertos en operaciones binarias, EOF puede ser un carcter v lido. En estos casos,
para determinar si realmente se ha producido un error utiliza la funcin ferror().
Sintaxis:
int fputchar (int c);
Ejemplo:
fputchar ('a');
Sintaxis:
int fputs (const char *s, FILE *flujo);
La funcin fputs() escribe el contenido de la cadena de caracteres apuntada por s en el flujo especificado.
El carcter nulo de terminacin no se escribe.
La funcin devuelve 0 cuando tiene xito, y un valor no nulo bajo condicin de error.
Si se abre el flujo en modo texto, tienen lugar ciertas transformaciones de caracteres. Esto supone que
puede ser que no haya una correspondencia uno a uno de la cadena frente al fichero. Sin embargo, si se
abre en modo binario, no se producen transformaciones de caracteres y se establece una correspondencia
uno a uno entre la cadena y el fichero.
Ejemplo:
Sintaxis:
int fread (void *buf, int tam, int n, FILE *flujo);
Lee n elementos de tam bytes cada uno. Devuelve el nmero de elementos (no bytes) realmente ledos. Si
se han ledo menos caracteres de los pedidos en la llamada, es que se ha producido un error o es que se
ha alcanzado el final del fichero. Utiliza feof() o ferror() para determinar lo que ha tenido lugar.
Si el flujo se abre para operaciones de texto, el flujo de retorno de carro y salto de lnea se transforma
automtica mente en un carcter de nueva lnea.
float buf[10];
Sintaxis:
FILE *freopen (const char *nombre_fichero, const char *modo, FILE *flujo);
El flujo es cerrado. El fichero nombre_fichero es abierto y asociado con el flujo. Devuelve flujo si tiene xito
o NULL si fall.
Ejemplo:
#include <stdio.h>
Sintaxis:
int fscanf (FILE *flujo, const char *formato[, direccion, ...]);
Esta funcin es idntica a la funcin scanf() con la excepcin que scanf() lee de la entrada estndar (flujo
stdin) y la funcin fscanf () lee de la entrada especificada (flujo indicado en su primer argumento).
Ejemplo:
int d;
float f;
fscanf (pf, %d %f, &d, %f);
Sintaxis:
int fseek (FILE *flujo, long desplazamiento, int origen);
Origen Nombre
-------------------- --------
Comienzo del fichero SEEK_SET
Posicin actual SEEK_CUR
Final del fichero SEEK_END
En la mayor parte de las implementaciones y en el estndar ANSI, desplazamiento debe ser un long int
para soportar ficheros de ms de 64K bytes.
Ejemplo:
#include <stdio.h>
Sintaxis:
long ftell (FILE *flujo);
Ejemplo:
Sintaxis:
int fwrite (const void *buf, int tam, int n, FILE *flujo);
Escribe n elementos de tam bytes cada uno. Devuelve el nmero de elementos (no bytes) escritos
realmente.
Ejemplo:
float f = 1.2;
Sintaxis:
int getc (FILE *flujo);
Devuelve el carcter ledo en caso de xito o EOF en caso de error o que se detecte el fin de fichero.
Las funciones getc() y fgetc() son idnticas, y en la mayor parte de las implementaciones getc() est
definida por la siguiente macro:
Ejemplo:
Sintaxis:
int getchar (void);
Si tiene xito, getchar() devuelve el carcter ledo, despus de convertirlo a int sin extensin de signo. En
caso de fin de fichero o error, devuelve EOF.
Las funciones getchar() y fgetchar() son idnticas, y en la mayor parte de las implementaciones getchar()
est simplemente definida como la siguiente macro:
Ejemplo:
ch = getchar ();
Sintaxis:
char *gets (char *string);
Lee caracteres de stdin hasta que un carcter de nueva lnea (\n) es encontrado. El carcter \n no es
colocado en el string. Devuelve un puntero al argumento string.
Ejemplo:
char nombre_fichero[128];
gets (nombre_fichero);
Sintaxis:
void perror (const char *s);
Imprime un mensaje de error en stderr. Primero se imprime el argumento de string s, despus se escriben
dos puntos, a continuacin se escribe un mensaje de error acorde al valor corriente de la variable errno, y
por ltimo se escribe una nueva lnea.
errno es una variable global que contiene el tipo de error. Siempre que ocurre un error en una llamada al
sistema, a errno se le asigna un valor que indica el tipo de error.
En Turbo C, la variable errno est declarada en los ficheros errno.h, stddef.h y stdlib.h, siendo su
declaracin: int errno; Los posibles valores que puede tomar esta variable no interesa en este momento, as
que se dir n cu les son cuando se estudie el header <errno.h>.
Ejemplo:
/*
Este programa imprime:
No es posible abrir fichero para lectura: No such file or directory
*/
#include <stdio.h>
FILE *fp;
Sintaxis:
int printf (const char *formato [, argumento, ...]);
Sintaxis:
int putc (int c, FILE *flujo);
Una de las funciones putc() y fputc() se implementa como macro de la otra. Las dos son funcionalmente
equivalentes.
Ejemplo:
Sintaxis:
int putchar (int c);
Una de las funciones putchar() y fputchar() se implementa como macro de la otra. Las dos son
funcionalmente equivalentes.
Ejemplo:
putchar ('a');
Sintaxis:
int puts (const char *s);
Si la escritura tiene xito, puts() devuelve el ltimo carcter escrito. En otro caso, devuelve EOF.
Sintaxis:
int remove (const char *nombre_fichero);
La funcin remove() borra el fichero especificado por nombre_fichero. Devuelve 0 si el fichero ha sido
correctamente borrado y -1 si se ha producido un error.
Ejemplo:
#include <stdio.h>
if (remove (fichero) == 0)
printf ("Fichero %s borrado.\n", fichero);
else
printf ("No se ha podido borrar el fichero %s.\n", fichero);
return 0;
}
Sintaxis:
int rename (const char *viejo_nombre, const char *nuevo_nombre);
La funcin rename() cambia el nombre del fichero especificado por viejo_nombre a nuevo_nombre. El
nuevo_nombre no debe estar asociado a ningn otro en el directorio de entrada. La funcin rename()
devuelve 0 si tiene xito y un valor no nulo si se produce un error.
Ejemplo:
#include <stdio.h>
return 0;
}
Sintaxis:
void rewind (FILE *flujo);
La funcin rewind() mueve el indicador de posicin del fichero al principio del flujo especificado.
Tambininicializa los indicadores de error y fin de fichero asociados con flujo. No devuelve valor.
Ejemplo:
rewind (pf);
Sintaxis:
int scanf (const char *formato [, ...]);
Sintaxis:
void setbuf (FILE *flujo, char *buf);
La funcin setbuf() se utiliza para determinar el buffer del flujo especificado que se utilizar o -si se llama con
buf a nulo- para desactivar el buffer. Si un buffer va a ser definido por el programador, entonces debe ser de
BUFSIZ caracteres. BUFSIZ est definido en stdio.h. La funcin setbuf() no devuelve valor.
Ejemplo:
#include <stdio.h>
return 0;
}
Sintaxis:
int setvbuf (FILE *flujo, char *buf, int tipo, int tam);
La funcin setvbuf() permite al programador especificar el buffer, su tamao y su modo para el flujo
especificado. El array de caracteres apuntado por buf se utiliza como buffer de flujo para las operaciones de
E/S. El tamao del buffer est fijado por tam, y tipo determina como se usar . Si buf es nulo, no tiene lugar
ninguna operacin sobre el buffer.
Los valores legales de tipo son _IOFBF, _IONBF y _IOLBF. Estn definidos en stdio.h. Cuando se activa el
modo _IOFBF se produce una operacin de buffer completa. Este es el modo por defecto. Cuando se activa
_IONBF, el flujo no utiliza buffer independientemente del valor de buf. Si el modo es _IOLBF, el flujo utiliza
buffer por lneas, lo que supone que el buffer es volcado en el fichero cada vez que se escribe un carcter
de salto de lnea para los flujos de salida; para los flujos de entrada lee todos los caracteres hasta un
carcter de salto de lnea. En cualquier caso, el buffer es volcado en el fichero cuando se llena.
El valor de tam debe ser mayor que 0. La funcin setvbuf() devuelve 0 en caso de xito; en caso de fallo
devuelve un valor distinto de cero.
Ejemplo:
Sintaxis:
int sprintf (char *buffer, const char *formato [, argumento, ...]);
Esta funcin es igual que la funcin printf() con la diferencia de que la salida de la funcin printf() va al flujo
stdout y la salida de la funcin sprintf() va al string buffer.
Ejemplo:
char cadena[80];
sprintf (cadena," %s %d %c", abc, 5, 'd');
Sintaxis:
int sscanf (const char *buffer, const char *formato [, direccion, ...]);
Devuelve el nmero de bytes escritos. En caso de error, sprintf() devuelve EOF. Devuelve el nmero de
campos ledos, explorados, convertidos y almacenados con xito. Si sscanf intenta leer ms all del final de
buffer, entonces el valor devuelto es EOF.
Ejemplo:
char cadena[80];
int i;
sscanf (abc 6," %s%d", cadena, &i);
Sintaxis:
FILE *tmpfile (void);
La funcin tmpfile() abre un fichero temporal para actualizarlo y devuelve un puntero a un flujo. La funcin
utiliza automtica mente un nico nombre de fichero para evitar conflictos con los ficheros existentes. La
funcin devuelve un puntero nulo en caso de fallo; en cualquier otro caso devuelve un puntero a un flujo.
El fichero temporal creado por tmpfile() se elimina automtica mente cuando el fichero es cerrado o cuando
el programa termina.
Ejemplo:
FILE *pftemp;
Sintaxis:
char *tmpnam (char *nombre_fichero);
La funcin tmpnam() genera un nico nombre de fichero y lo guarda en el array apuntado por nombre. El
objetivo de tmpnam() es generar el nombre de un fichero temporal que sea diferente de cualquier otro que
exista en el directorio.
La funcin puede ser llamada hasta un nmero de veces igual a TMP_MAX, que est definido en stdio.h.
Cada vez se genera un nuevo nombre de fichero temporal.
En caso de xito se devuelve un puntero a una cadena de caracteres; en cualquier otro caso se devuelve
un puntero nulo.
Ejemplo:
#include <stdio.h>
tmpnam (nombre);
printf ("Nombre temporal: %s\n", nombre);
return 0;
}
Sintaxis:
int ungetc (int c, FILE *flujo);
La prxima llamada a getc (u otras funciones de entrada de flujos) para flujo devolver c.
La funcin ungetc() devuelve el carcter c si tiene xito. Devuelve EOF si la operacin falla.
Ejemplo:
Sintaxis:
int vfprintf (FILE *fp, const char *formato, va_list lista_de_arg);
Sintaxis:
int vfscanf (FILE *flujo, const char *formato, va_list lista_de_arg);
Sintaxis:
int vprintf (const char *formato, va_list lista_de_arg);
Sintaxis:
int vscanf (const char *formato, va_list lista_de_arg);
Sintaxis:
int vsprintf (char *buffer, const char *formato, va_list lista_de_arg);
Sintaxis:
int vsscanf (const char *buffer, const char *formato, va_list lista_arg);
Devuelve el nmero de campos ledos, explorados, convertidos y almacenados con xito. Devuelve EOF en
caso de que se detecte el fin de fichero.
Las funciones vprintf(), vfprintf() y vsprintf() son funciones equivalentes a printf(), fprintf() y sprintf()
respectivamente. Las funciones vscanf(), vfscanf() y vsscanf() son funciones equivalentes a scanf(), fscanf()
y sscanf() respectivamente. La diferencia se encuentra en que la lista de argumentos se sustituye por un
puntero a una lista de argumentos. Este puntero est definido en stdarg.h.
Consulta la discusin del fichero stdarg.h en la leccin 5 para tener ms detalles y ver un ejemplo.
GLOSARIO:
Sintaxis:
void clearerr (FILE *flujo);
La funcin clearerr() borra los indicadores de error y fin de fichero para el flujo especificado.
Ejemplo:
#include <stdio.h>
if (ferror( fp))
{
/* visualiza un mensaje de error */
printf ("Error leyendo de PRUEBA.TXT\n");
fclose (fp);
return 0;
}
Sintaxis:
int fcloseall (void);
Devuelve el nmero total de flujos cerrados, o EOF si fue detectado algn error.
Ejemplo:
#include <stdio.h>
if (flujos_cerrados == EOF)
/* imprime un mensaje de error */
printf ("Ha ocurrido un error al intentar cerrar los ficheros.\n");
else
/* imprime resultado de la funcin fcloseall(): */
printf("%d flujos fueron cerrados.\n", flujos_cerrados);
return 0;
}
Sintaxis:
FILE *fdopen (int descriptor, char *tipo);
Los valores posibles del argumento tipo son los mismos que para los de la funcin fopen(). Consiste en un
string con una combinacin de los siguientes caracteres:
Tipo Significado
r Abre para lectura solamente
w Crea para escritura; sobreescribe fichero existente
a Aade, abre para escritura al final del fichero, o crea
fichero para escritura
+ Smbolo de suma para permitir operaciones de lectura/escritura
b Abre en modo binario
t Abre en modo texto
Las funciones de stdio.h: fileno() y fdopen(), utilizan el concepto de descriptor de fichero; este concepto se
explica en las ventanas inmediatamente siguientes.
Sintaxis:
int fgetpos (FILE *flujo, fpos_t *pos);
La posicin almacenada en *pos puede ser pasada a la funcin fsetpos() para poner la posicin del puntero
de fichero.
Devuelve 0 en caso de xito y un valor distinto de cero en otro caso. fpos_t es un tipo declarado con typdef
en el fichero stdio.h que indica posicin de fichero.
Ejemplo:
fclose (flujo);
return 0;
}
Sintaxis:
int fileno (FILE *flujo);
Las funciones de stdio.h: fileno() y fdopen(), utilizan el concepto de descriptor de fichero; este concepto se
explica en las ventanas inmediatamente siguientes.
Sintaxis:
int flushall (void);
Vaca los buffers para los flujos de entradas y escribe los buffers en los ficheros para los flujos de salida.
Ejemplo:
#include <stdio.h>
/* crea un fichero */
flujo = fopen (FICHERO, w);
/* cierra el fichero */
fclose (flujo);
return 0;
}
Sintaxis:
int fsetpos (FILE *flujo, const fpos_t *pos);
La nueva posicin apuntada por pos es el valor obtenido por una llamada previa a la funcin fgetpos().
fpos_t es un tipo declarado con typdef en el fichero stdio.h que indica posicin de fichero.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
/* cierra el fichero */
fclose (flujo);
return 0;
}
Sintaxis:
int getw (FILE *flujo);
Devuelve el prximo entero en el flujo de entrada, o EOF si ocurre un error o se detecta el fin de fichero.
Usa las funciones feof() o ferror() para verificar eof o error.
Ejemplo:
Sintaxis:
int putw (int d, FILE *flujo);
Ejemplo:
Debido a que el lenguaje C se desarroll inicialmente bajo el sistema operativo UNIX, se cre un segundo
sistema de ficheros. A este sistema se le llama E/S sin buffer, E/S de bajo nivel o E/S tipo UNIX. Hoy en
da, este sistema de ficheros est totalmente en desuso y se considera obsoleto, adems el nuevo
estndar ANSI ha decidido no estandarizar el sistema de E/S sin buffer tipo UNIX. Por todo lo dicho no se
puede recomendar este sistema a los nuevos programadores C. Sin embargo, todava existen programas
que lo usan y es soportado por la mayora de los compiladores de C. As que incluimos una breve
explicacin al respecto.
DESCRIPTORES DE FICHEROS
A diferencia del sistema de E/S de alto nivel, el sistema de bajo nivel no utiliza punteros a ficheros de tipo
FILE; el sistema de bajo nivel utiliza descriptores de fichero de tipo int. A cada fichero se le asocia un
nmero (su descriptor de fichero).
0 entrada estndar
1 salida estndar
2 salida de errores estndar
Los cuatro pasos para la manipulacin de ficheros con E/S de alto nivel que vimos antes se transforman en
la E/S de bajo nivel en los siguientes pasos:
Tanto las funciones open() como close() como todas las que tenemos disponibles con relacin al sistema
de ficheros de bajo nivel se explican en la siguiente ventana, pero slo para aquellos usuarios que tengan la
opcin de turbo puesta a on, debido a que estas funciones no pertenecen ya al estndar ANSI y por lo tanto
no son portables entre distintas implementaciones del C.
GLOSARIO:
Sintaxis:
int access (const char *nombre_fichero, int modo_acceso);
Si el acceso requerido es permitido, devuelve 0; en otro caso, devuelve -1 y se asigna un valor a la variable
errno.
#include <stdio.h>
#include <io.h>
Sintaxis:
int chmod (const char *path, int modo_acceso);
Cuando tiene xito chmod() cambia el modo de acceso al fichero y devuelve 0. En otro caso chmod()
devuelve -1.
El parmetro modo_acceso puede tomar alguno de los siguientes valores definidos en <sys\stat.h>:
Ejemplo:
#include <sys\stat.h>
#include <stdio.h>
#include <io.h>
Sintaxis:
int _chmod (const char *path, int func [ , int atrib ] );
Si func es 0, _chmod() devuelve los atributos del fichero. Si func es 1, los atributos son puestos. Si la
operacin tiene xito, _chmod() devuelve la palabra de atributo del fichero; en otro caso, devuelve -1. En el
caso de un error se asigna valor a errno.
El parmetro atrib representa los atributos de fichero de MS-DOS y puede tomar los siguientes valores
definidos en dos.h:
Sintaxis:
int chsize (int descriptor, long tamanio);
Ejemplo:
/* cierra el fichero */
close(handle);
return 0;
}
Sintaxis:
int _close (int descriptor);
int close (int descriptor);
Si tiene xito, close() y _close() devuelven 0; en caso contrario, estas funciones devuelven -1 y se le da
valor a errno.
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
/* cierra el fichero */
close (descriptor);
}
else
{
printf ("Error abriendo fichero\n");
}
return 0;
}
Sintaxis:
int _creat (const char *path, int atrib);
int creat (const char *path, int modo_acceso);
La funcin creat() abre el fichero en el modo dado por la variable global _fmode. La funcin _creat() siempre
abre en modo binario. Si la operacin tiene xito, el descriptor del nuevo fichero es devuelto; en caso
contario, un -1 es devuelto y asignado valor a errno.
La variable global _fmode est definida en los ficheros fcntl.h y stdlib.h de esta forma: int _fmode; Por
defecto, se inicializa con el valor O_TEXT.
Ejemplo:
#include <sys\stat.h>
#include <string.h>
/* cierra el fichero */
close (descriptor);
return 0;
}
Sintaxis:
int creatnew (const char *path, int modo);
La funcin creatnew es identica a la funcin _creat() con la excepcin de que es devuelto un error si el
fichero ya existe. (Versiones del DOS 3.0 o superiores)
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <dos.h>
#include <io.h>
if (descriptor == -1)
printf ("FICHERO.FIC ya existe.\n");
else
{
printf ("FICHERO.FIC creado con xito.\n");
write (descriptor, buf, strlen (buf));
close (descriptor);
}
return 0;
}
Sintaxis:
int creattemp (char *path, int atrib);
Esta funcin es similar a la funcin _creat(), excepto que el nombre de fichero es el nombre de path que
debe terminar con un \. El nombre de fichero debera ser bastante grande para alojar el nombre de fichero.
(Versiones de MS-DOS 3.0 o superiores)
Los valores posibles para atrib son los mismos que para la funcin creat().
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <io.h>
Sintaxis:
int dup (int descriptor);
Si la operacin tiene xito, dup() devuelve el descriptor del nuevo fichero; en otro caso, dup() devuelve -1 y
se asigna valor a errno.
Sintaxis:
int dup2 (int viejo_descriptor, int nuevo_descriptor);
Sintaxis:
int eof (int descriptor);
Valor Significado
1 Fin de fichero
0 No fin de fichero
-1 Error; errno es asignado
Sintaxis:
long filelength (int descriptor);
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
/* cierra el fichero */
close (descriptor);
return 0;
}
Sintaxis:
int getftime (int descriptor, struct ftime *pftime);
Sintaxis:
int ioctl (int descriptor, int func [ , void *argdx, int argcx ] );
Para valores de func de 2 hasta 5, el valor devuelto es el nmero de bytes transferidos realmente.
IOCTL (Control de entrada/salida para los dispositivos) es la funcin 68 (44 hexadecimal) de la interrupcin
21 hexadecimal del DOS. Esta funcin del DOS tiene varias subfunciones que realizan distintas tareas. En
las versiones DOS-3 haba 11 subfunciones. El argumento func de ioctl() del C se corresponde con dichas
subfunciones. Para saber lo que hace cada subfuncin debe consultar tu manual del DOS.
Sintaxis:
int isatty (int descriptor);
Ejemplo:
#include <stdio.h>
#include <io.h>
Sintaxis:
int lock (int descriptor, long desplazamiento, long longitud);
Previene el acceso de lectura o escritura por otro programa para la regin que empieza en la direccin
desplazamiento y abarca longitud bytes.
Sintaxis:
long lseek (int descriptor, long desplazamiento, int desde_donde);
Sintaxis:
int open (const char *path, int acceso [ , unsigned modo ] );
Si la operacin se hace correctamente, open() devuelve un descriptor de fichero; en cualquier otro caso
devuelve -1 y le da valor a errno.
Las definiciones de bits para el argumento acceso estn en el fichero fcntl.h y son las siguientes:
Para _open(), el valor de acceso en MS-DOS 2.x est limitado a O_RDONLY, O_WRONLY y O_RDWR.
Para MS-DOS 3.x, los siguientes valores adicionales pueden ser usados tambin:
Slo una de las opciones O_DENYxxx pueden ser incluidas en una simple apertura.
Los valores posibles que puede tomar el argumento modo se describieron en la funcin chmod().
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
Sintaxis:
int _open (const char *nombre_de_fichero, int flags);
Si la operacin tiene xito, _open() devuelve un descriptor de fichero; en cualquier otro caso devuelve -1.
Las definiciones de bits para el argumento flags son las mismas que para el argumento acceso en la
descripcin de la funcin open().
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
Sintaxis:
int read (int descriptor, void *buffer, unsigned longitud);
Si la operacin tiene xito, devuelve un entero indicando el nmero de bytes colocados en el buffer; si el
fichero fue abierto en modo texto, read() no cuenta retornos de carros o caracteres Ctrl-Z en el nmero de
bytes ledos.
Sintaxis:
int _read (int descriptor, void *buffer, unsigned longitud);
Devuelve el nmero de bytes ledos; si se detecta el fin de fichero, devuelve 0; si ocurre un error devuelve -
1 y da valor a errno.
Sintaxis:
int setftime (int descriptor, struct ftime *ptime);
struct ftime {
unsigned ft_tsec : 5; /* intervalo de dos segundos */
unsigned ft_min : 6; /* minutos */
unsigned ft_hour : 5; /* horas */
unsigned ft_day : 5; /* das */
unsigned ft_month : 4; /* meses */
unsigned ft_year : 7; /* ao */
};
Sintaxis:
int setmode (int descriptor, int modo);
Ejemplo:
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
Sintaxis:
sopen (path, acceso, shflag, modo)
Est incluido para compatibilidad con las distintas versiones de Turbo C y otros compiladores.
El significado de los parmetros acceso y modo se han explicado en las funciones open() y chmod()
respectivamente. El parmetro shflag contiene el modo de comparticin de ficheros y las constantes
definidas para ello en el fichero share.h son las siguientes:
Sintaxis:
long tell (int descriptor);
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
Sintaxis:
int unlink (const char *nombre_de_fichero);
Si el nombre de fichero tiene atributo de slo lectura, unlink fallar . Llama a chmod() primero para cambiar el
atributo de fichero.
El prototipo de esta funcin est en los ficheros dos.h, io.h y stdio.h. La funcin remove() cuyo prototipo se
encuentra en stdio.h es en realidad una macro que se expande a una llamada a unlink().
Sintaxis:
int write (int descriptor, void *buffer, unsigned longitud);
Sintaxis:
int _write (int descriptor, void *buffer, unsigned longitud);
HANDLE_MAX (#define)
LECCION 10
INDICE DE LA LECCION 10
- Primera parte:
- Segunda parte:
Aunque las bibliotecas (ficheros con extensin .LIB) son parecidas a los ficheros objetos (fichero con
extensin .OBJ), existe una diferencia crucial: No todo el cdigo de una biblioteca se aade al programa.
Cuando se enlaza un programa que consta de varios ficheros objetos, todo el cdigo de cada fichero objeto
se convierte en parte del programa ejecutable final. Esto ocurre se est o no utilizando el cdigo. En otras
palabras, todos los ficheros objetos especificados en tiempo de enlace se unen para formar el programa.
Sin embargo, este no es el caso de los ficheros de biblioteca.
Una biblioteca es una coleccin de funciones. A diferencia de un fichero objeto, un fichero de biblioteca
guarda una serie de informacin para cada funcin de tal forma que cuando un programa hace referencia a
Para utilizar una funcin de biblioteca debemos incluir su correspondiente fichero de para que nuestro
programa conozca el prototipo de la funcin a utilizar. En los ficheros de (suelen tener extensin .H)
adems de los prototipos de las funciones puede haber ms informacin como macros, declaracin de
tipos, declaracin de variables globales, etc.
Fichero de Propsito
------------------- ----------------------------------------------------
Fichero de Propsito
------------------- ----------------------------------------------------
El resto de esta leccin y las dos lecciones siguientes estar n dedicadas a la descripcin de cada fichero de
.h.
Nota: las caractersticas ya estudiadas en lecciones anteriores no se volver n a explicar (por ejemplo,
ficheros stdarg.h y assert.h).
En el fichero de <limits.h> se encuentra una serie de macros que definen valores lmites para algunos tipos
de datos.
FICHERO DE LIMITS.H
CONSTANTES SIMBOLICAS:
**********************
CHAR_xxx (#defines)
Estos valores son independientes de si tipo char est definido como signed o unsigned por defecto.
INT_xxx (#defines)
LONG_xxx #defines
SCHAR_xxx (#defines)
SHRT_xxx (#defines)
UCHAR_MAX (#define)
UINT_MAX (#define)
ULONG_MAX (#define)
USHRT_MAX (#define)
El estndar ANSI define unos cuantos tipos estndares y macros en el fichero <stddef.h>.
FICHERO DE STDDEF.H
El estndar ANSI define unos cuantos tipos estndares y macros en el fichero stddef.h. Uno de los tipos es
ptrdiff_t que es un tipo entero con signo y el resultado de restar dos punteros. La macro size_t es el tipo
entero sin signo del resultado del operador de tiempo de compilacin sizeof. Las dos macros son NULL
(que se corresponde con los punteros nulos) y ERRNO (que se corresponde con el valor modificable
utilizado para guardar los diferentes cdigos de error generados por las funciones de biblioteca).
En Turbo C, la variable global errno sustituye a la macro ERRNO. Adems el fichero stddef.h incluye el
fichero errno.h. En el fichero errno.h se encuentran declaradas dos variables globales (errno y _doserrno) y
las definiciones de los nmeros de error.
La utilizacin de las funciones de caracteres requieren la inclusin del fichero <ctype.h>; y la utilizacin de
las funciones de caracteres requieren la inclusin del fichero <string.h>.
En C una cadena es un array de caracteres que finaliza con un carcter nulo. Puesto que el C no tiene
asociadas operaciones de comprobacin de cadenas, es responsabilidad del programador proteger los
arrays del desbordamiento. Si un array se desborda, el comportamiento queda indefinido.
Las funciones de caracteres toman un argumento entero, pero slo se utiliza el byte menos significativo. En
general, nosotros somos libres de utilizar un argumento de tipo carcter ya que automtica mente se
transforma en entero en el momento de la llamada.
FICHERO DE CTYPE.H
Prototipo Qu hace
El error cometido se ve claramente: en el primer caso nuestra intencin era leer un slo carcter y en
realidad leemos dos, y en el segundo caso nuestra intencin era incrementar en uno el puntero p y en
realidad lo incrementamos en dos. Si isdigit() fuera una funcin en vez de una macro no habra ningn
problema.
En el ejemplo 1 de esta leccin se muestra cmo usar estas macros y estas funciones.
FICHERO DE STRING.H
GLOSARIO:
Sintaxis:
char *stpcpy (char *destino, const char *fuente);
Ejemplo:
#include <string.h>
#include <stdio.h>
Sintaxis:
Near: char *strcat (char *destino, const char *fuente);
Far: char far * far _fstrcat (char far *destino, const char far *fuente);
Devuelve destino.
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strchr (const char *s, int c);
Far: char far * far _fstrchr (const char far *s, int c);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
int strcmp (const char *s1, const char *s2);
int far _fstrcmp (const char far *s1, const char far *s2);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
int strcmpi (const char *s1, const char *s2);
Esta rutina est implementada como una macro para compatibilidad con otros compiladores. Es igual que
stricmp().
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
int strcoll (char *s1, char *s2);
La funcin strcoll() compara el string apuntado por s1 con el string apuntado por s2, segn los valores
puestos por setlocale().
Ejemplo:
#include <stdio.h>
#include <string.h>
Devuelve destino.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: size_t strcspn (const char *s1, const char *s2);
Far: size_t far far _fstrcspn (const char far *s1, const char far *s2);
Devuelve la longitud del substring inicial apuntado por s1 que est constituido slo por aquellos caracteres
que no estn contenidos en el string 2. Dicho de otra forma, strcspn() devuelve el ndiceel primer carcter
en el string apuntado por s1 que est como carcter del string apuntado por s2.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strdup (const char *s);
Far: char far * far _fstrdup (const char far *s);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
char *_strerror (const char *s);
El mensaje de error est constituido por s, dos puntos, un espacio, el mensaje de error ms reciente
generado por el sistema, y un carcter de nueva lnea.
El string s debe tener 94 caracteres o menos. Devuelve un puntero al string que contiene el mensaje de
error.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
char *strerror (int numerr);
Ejemplo:
#include <stdio.h>
#include <string.h>
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: size_t strlen (const char *s);
Far: size_t _fstrlen (const char far *s);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strlwr (char *s);
Far: char far * far _fstrlwr (char char far *s);
Devuelve un puntero a s.
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strncat (char *destino, const char *fuente, size_t longmax);
Far: char far * far _fstrncat (char far *destino, const char far *fuente,
size_t longmax);
Devuelve destino.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: int strncmp (const char *s1, const char *s2, size_t longmax);
Far: int far _fstrncmp (const char far *s1, const char far *s2,
size_t longmax);
Ejemplo:
Sintaxis:
int strncmpi (const char *s1, const char *s2, size_t n);
La funcin strncmpi() ejecuta una comparacin con signo entre s1 y s2, para una longitud mxima de n
bytes, empezando con el primer carcter de cada string y continuando con los caracteres siguientes hasta
encontrar caracteres correspondientes diferentes o hasta que se han examinado n caracteres.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strncpy (char *destino, const char *fuente, size_t longmax);
Far: char far * far _fstrncpy (char far *destino, const char far *fuente,
size_t longmax)
Si son copiados longmax caracteres, no es aadido el carcter nulo; por lo tanto, el contenido de destino no
es un string terminado en nulo.
Devuelve destino.
Ejemplo:
printf ("%s", (strncpy (s1, s2, n1), *(s1+n1) = 0, s1)); /*imprime ab*/
printf ("%s", strncpy (s1, s2, n2)); /* imprime abcd */
}
Sintaxis:
Near: int strnicmp (const char *s1, const char *s2, size_t longmax);
Far: int far _fstrnicmp (const char far *s1, const char far *s2,
size_t longmax);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strnset (int *s, int ch, size_t n);
Far: char far * far _fstrnset (char far *s, int ch, size_t n);
Se para cuando los n caracteres son copiados o se encuentra NULL. Devuelve un puntero a s.
#include <stdio.h>
#include <string.h>
printf ("%s", strnset (s, c1, n1)); /* s contiene xxx e imprime xxx */
printf ("%s", strnset (s, c2, n2)); /* s contiene yyx e imprime yyx */
}
Sintaxis:
Near: char *strpbrk (const char *s1, const char *s2);
Far: char far * far _fstrpbrk (const char far *s1, const char far *s2);
Devuelve un puntero al primer carcter del string apuntado por s1 que se corresponde con algn carcter
en el string apuntado por s2. El carcter nulo de terminacin no se incluye. Si no hay correspondencia, se
devuelve un puntero nulo.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strrchr (const char *s, int c);
Far: char far * far _fstrrchr (const char far *s, int c);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strrev (char *s);
Far: char far * far _fstrrev (char far *s);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strset (char *s, int ch);
Far: char far * far _fstrset (char far *s, int ch);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: size_t strspn (const char *s1, const char *s2);
Far: size_t far _fstrspn (const char far *s1, const char far *s2);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strstr (const char *s1, const char *s2);
Far: char far * far _fstrstr (const char far *s1, const char far *s2);
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strtok (char *s1, const char *s2);
Far: char far * far _fstrtok (char far *s1, const char far *s2);
s2 define caracteres separadores; strtok() interpreta el string s1 como una serie de tokens separados por
los caracteres separadores que hay en s2.
En las llamadas siguientes a strtok() con NULL como primer argumento, usa el string previo s1, empezando
despus del ltimo token encontrado.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
Near: char *strupr (char *s);
Far: char far * far _fstrupr (char far *s);
Devuelve un puntero a s.
Ejemplo:
#include <stdio.h>
#include <string.h>
Sintaxis:
size_t strxfrm (char *s1, char *s2, size_t n);
Es equivalente a strncpy().
Ejemplo:
OBSERVACIONES:
1) Aquellas funciones que tienen al principio de la descripcin: (TC) no estn en el ANSI C y sen TURBO
C. Asimismo, la distincin entre funciones near y far no est en el ANSI, sino que tambines propio de
TURBO C: el prototipo de near en aquellas funciones que no tienen (TC) es el prototipo de la funcin en el
ANSI. No obstante, aquellos usuarios que tengan la opcin turbo a off, ver n todas las funciones ya que
muchas de estas funciones que no pertenecen al ANSI C estn en muchos compiladores y adems as
tienen una visin ms amplia de la variedad de operaciones que se pueden hacer con los strings (llamados
en castellano cadenas).
FICHERO DE MEM.H
GLOSARIO:
Sintaxis:
Near: void *memccpy (void *destino, const void *fuente, int c, size_t n);
Far: void far * far _fmemccpy (void far *destino, const void far *fuente,
int c, size_t n);
Esta funcin se para despus de copiar un byte que coincida con c y devuelve un puntero al byte en
destino inmediatamente siguiente a c; en otro caso devuelve NULL.
Ejemplo:
#include <stdio.h>
#include <mem.h>
printf ("%s", memccpy (s1, s2, c1, strlen (s2))); /* imprime (null) */
printf ("%s", memccpy (s1, s2, c2, strlen (s2))); /* imprime c */
}
Sintaxis:
Near: void *memchr (const void *s, int c, size_t n);
Far: void far * far _fmemchr (const void far *s, int c, size_t n);
Ejemplo:
#include <stdio.h>
#include <mem.h>
#include <string.h>
Sintaxis:
Near: int memcmp (const void *s1, const void *s2, size_t n);
Far: int far _fmemcmp (const void far *s1, const void far *s2, size_t n);
Ejemplo:
#include <stdio.h>
#include <mem.h>
#include <string.h>
Sintaxis:
Near: void *memcpy (void *destino, const void *fuente, size_t n);
Far: void far *far _fmemcpy (void far *destino, const void far *fuente,
size_t n);
Devuelve destino.
Ejemplo:
#include <stdio.h>
#include <mem.h>
#include <string.h>
Sintaxis:
Near: int memicmp (const void *s1, const void *s2, size_t n);
Ejemplo:
#include <stdio.h>
#include <mem.h>
#include <string.h>
Sintaxis:
void *memmove (void *destino, const void *fuente, size_t n);
Devuelve destino.
Ejemplo:
#include <stdio.h>
#include <mem.h>
Sintaxis:
Near: void *memset (void *s, int c, size_t n);
Far: void far * far _fmemset (void far *s, int c, size_t n);
Devuelve s.
Ejemplo:
#include <stdio.h>
#include <mem.h>
Sintaxis:
void movedata(unsigned segmento_fuente, unsigned desplazamiento_fuente,
unsigned segmento_destino, unsigned desplazamiento_destino,
size_t n);
Ejemplo:
movedata (FP_SEG (s2), FP_OFF (s2), FP_SEG (s1), FP_OFF (s1), strlen (s2));
s1[strlen(s1)] = 0;
printf ("%s", s1); /* imprime abc */
}
Sintaxis:
void movmem (void *fuente, void *destino, unsigned longitud);
Ejemplo:
#include <stdio.h>
#include <mem.h>
#include <stdio.h>
#include <mem.h>
FUNCIONES MATEMATICAS
Las funciones matemticas toman argumentos de tipo double y devuelven valores de tipo double. Estas
funciones se dividen en las siguientes categoras
Todas las funciones matemticas necesitan la <math.h> en cualquier programa que las utilice. Adems, al
declarar las funciones matemticas, esta define tres macros: EDOM, ERANGE, y HUGE_VAL. Si uno de
los argumentos de las funciones matemticas no se encuentra en uno de los dominios para el cual est
definido, se devuelve un valor definido por la implementacin y la variable global errno se activa a EDOM
(error de dominio). Si el resultado de una rutina es demasiado grande como para ser representado por un
tipo double, se produce desbordamiento. Esto da lugar a que la rutina devuelva HUGE_VAL, y errno se
active a ERANGE (que indica error de rango). Si se produce un desbordamiento por abjao, la rutina
devuelve 0 y activa errno a ERANGE.
FICHERO DE MATH.H
GLOSARIO:
*********
acos Arcocoseno.
asin Arcoseno.
atan Arcotangente.
cos Coseno.
tan Tangente.
FUNCIONES:
**********
Sintaxis:
int abs (int x);
En Turbo C, el prototipo de abs() est en math.h y en stdlib.h. En el ANSI C slo se encuentra en el fichero
stdlib.h
acos Arcocoseno.
Sintaxis:
double acos (double x);
asin Arcoseno.
Sintaxis:
double asin (double x);
Devuelve el arcoseno de x (valores en el rango -/2 a /2). El argumento x debe estar en el rango de -1 a 1;
en cualquier otro caso se produce un error de dominio.
atan Arcotangente.
Sintaxis:
double atan (double x);
Sintaxis:
double atan2 (double y, double x);
Devuelve el arcotangente de y/x (un valor en el rango - a ). Utiliza el signo de sus argumentos para
obtener el cuadrante del valor devuelto.
Sintaxis:
double atof (const char *s);
En Turbo C, el prototipo de atof() est en math.h y en stdlib.h. En el ANSI C slo se encuentra en el fichero
stdlib.h
Sintaxis:
double cabs (struct complex z);
#include <stdio.h>
#include <math.h>
z.x = 2.0;
z.y = 1.0;
val = cabs (z);
printf ("El valor absoluto de %.2lfi %.2lfj es %.2lf", z.x, z.y, val);
return 0;
}
Sintaxis:
double ceil (double x);
Por ejemplo, dado 1.02, ceil() devuelve 2.0. Dado -1.02, ceil() devuelve -1.
cos Coseno.
Sintaxis:
double cos (double x);
Sintaxis:
double cosh (double x);
Sintaxis:
double exp (double x);
Sintaxis:
double fabs (double x);
Sintaxis:
double floor (double x);
Por ejemplo, dado 1.02, floor() devuelve 1.0. Dado -1.02, floor() devuelve -2.0.
Sintaxis:
double fmod (double x, double y);
Sintaxis:
double frexp (double x, int *exp);
La funcin frexp() descompone el nmero x en una mantisa de rango entre 0.5 y 1 y en un exponente
entero tal que x = mantisa * (2 elevado a exp). Se devuelve la mantisa, y el exponente se guarda en la
variable apuntada por exp.
Sintaxis:
double hypot (double x, double y);
Devuelve hipotenusa de un tri ngulo rect ngulo en el que los catetos son x e y.
Sintaxis:
long int labs (long int x);
En Turbo C, el prototipo de labs() est en math.h y en stdlib.h. En el ANSI C slo se encuentra en el fichero
stdlib.h
Sintaxis:
double ldexp (double x, int exp);
Sintaxis:
double log (double x);
Sintaxis:
double log10 (double x);
Sintaxis:
int matherr (struct exception *e);
Esta funcin no puede ser llamada directamente por el usuario. Cuando ocurre un error matem tico, el
sistema llama automtica mente a esta funcin. El usuario puede suministrar su propia funcin matherr para
controlar los errores detectados por la librera matemtica.
La funcin matherr() debe devolver un valor distinto de cero para indicar que se resuelve problema; en otro
caso devueve 0.
Ejemplo 1:
#include <stdio.h>
#include <math.h>
log (-1);
pow (0, -2);
exp (-1000);
sin (10e70);
x = exp (1000);
printf ("x = %lg", x);
}
Ejemplo 2:
#include <stdio.h>
#include <math.h>
log (-1);
pow (0, -2);
exp (-1000);
sin (10e70);
x = exp (1000);
printf ("x = %lg", x);
}
La ejecucin del programa del ejemplo 1 imprime lo siguiente (en la versin 2.0 de Borland C++):
La ejecucin del programa del ejemplo 2 imprime lo siguiente (en cualquier versin de Turbo C):
Ver al final de esta ventana cmo es struct exception y el sinificado de los tipos enumerados y constantes
simblicas que aparecen en el segundo ejemplo.
Sintaxis:
double modf (double x, double *parte_entera);
La funcin modf() descompone x en sus partes entera y fraccionaria. Devuelve la parte fraccionaria y sita
la parte entera en la variable apuntada por parte_entera.
Sintaxis:
double poly (double x, int grado, double coefs[]);
Ejemplo:
#include <stdio.h>
#include <math.h>
Sintaxis:
double pow (double base, double exponente);
Devuelve base elevado a exponente. Se produce un error de dominio si base es 0 y exponente es menor o
igual que 0. Tambinpuede ocurrir si base es negativo y exponente no es entero. Un desbordamiento
produce un error de rango.
Sintaxis:
double pow10 (int p);
Devuelve 10 elevado a p.
Sintaxis:
double sin (double x);
Sintaxis:
double sinh (double x);
Sintaxis:
double sqrt (double x);
Devuelve la raz cuadrada de x. Si se llama con un nmero negativo se produce un error de dominio.
tan Tangente.
Sintaxis:
double tan (double x);
Sintaxis:
double tanh (double x);
struct complex {
double x, y;
};
EDOM (#define)
Cdigo de error para errores de dominios matem ticos, es decir, cuando el argumento de la funcin
matem tica est fuera del dominio.
ERANGE (#define)
EXCEPTION (struct)
struct exception {
int type;
char *name;
double arg1, arg2, retval;
};
Ver ejemplo en la descripcin de la funcin matherr() para saber cmo usar esta estructura.
HUGE_VAL (#define)
Ver ejemplo en descripcin de la funcin matherr() para ver cmo se puede usar.
M_xxxx (#defines)
M_E El valor de e.
PI (#defines)
M_PI
M_PI_2 Un medio de (/2)
M_PI_4 Un cuarto de (/4)
M_1_PI Uno divido por (1/)
M_2_PI Dos divido por (2/)
M_1_SQRTPI Raz cuadrada de ()
M_2_SQRTPI Mitad de la raz cuadrada de (()/2)
M_SQRTxx (#defines)
_mexcep (enum)
Ver ejemplo en descripcin de la funcin matherr para saber cmo usar estas constantes.
Las funciones de pantalla y de grficos no estn definidas por el estndar ANSI. Esto ocurre por una
simple razn: son, por naturaleza, dependientes del entorno fijado y en gran parte no portables.
Actualmente no hay una interfaz gr fica que sea ampliamente aceptada, ni hay un conjunto universal de
rdenes de control de pantalla. Sin embargo, estos tipos de funciones son de importancia primordial cuando
se crea software que requiere control de pantalla de alta resolucin y de calidad de grficos para el
mercado de software. Las funciones descritas en las dos siguientes pantallas pertenecen al Turbo C.
Estas funciones se descomponen en dos grupos: aquellas que desempean funciones relacionadas con las
pantallas de texto y aquellas que se refieren a los gr ficos. Las funciones grficos requieren la <graphics.h>
y las funciones de pantalla requieren la <conio.h>.
Tanto en modo texto como en modo gr fico, la mayora de las funciones trabajan con una ventana. Una
ventana es un trozo rectangular de la pantalla que hace la funcin de pantalla completa. Por defecto, la
ventana de trabajo es la pantalla completa; pero se puede cambiar con la funcin window() en modo texto y
GLOSARIO:
*********
FUNCIONES:
**********
Sintaxis:
char *cgets (char *cad);
cad[0] debe contener la longitud mxima de la cadena a ser leda. A la vuelta, cad[1] contiene el nmero de
caracteres ledos realmente. La cadena empieza en cad[2]. La funcin devuelve &cad[2].
Sintaxis:
void clreol (void);
Sintaxis:
void clrscr(void);
Sintaxis:
int cprintf (const char *formato [, argumento,...]);
Sintaxis:
int cputs (const char *cad);
Sintaxis:
int cscanf (char *formato [ , direccion, ... ]);
Devuelve el nmero de campos procesados con xito. Si una funcin intenta leer en final de fichero, el valor
devuelto es EOF.
getch and getche Lee carcter de consola, con eco a pantalla (getche),
o sin eco (getch).
Sintaxis:
int getch (void);
int getche (void);
Ambas funciones devuelven el carcter ledo. Los caracteres estn disponibles inmediatamente (no hay
buffer de lneas completas).
Las teclas especiales tales como las teclas de funcin y las teclas de los cursores estn representadas por
una secuencia de dos caracteres: un carcter cero seguido por el cdigo de exploracin para la tecla
presionada.
Sintaxis:
char *getpass (const char *prompt);
El valor devuelto es un puntero a una cadena esttica que es sobreescrita en cada llamada.
Sintaxis:
int gettext (int izq, int ar, int der, int ab, void *destino);
Las son absolutas, no son relativas a la ventana actual. La esquina superior izquierda es (1,1). Devuelve
un valor distinto de cero si tiene xito.
Sintaxis:
void gettextinfo (struct text_info *r);
El resultado es devuelto en r.
Sintaxis:
void gotoxy (int x, int y);
Sintaxis:
void highvideo (void);
Afecta a subsecuentes llamadas a funciones de ventana de texto tales como putch() y cprintf().
Sintaxis:
void insline (void);
Las lneas por debajo de la posicin del cursor son subidas una lnea hacia arria y la ltima lnea se pierde.
Sintaxis:
int kbhit (void);
Si una tecla est disponible, kbhi() devuelve un entero distino de cero; si no es as , devuelve 0.
Sintaxis:
void lowvideo (void);
Afecta a la salida subsiguiente escritas con funcines de ventana de texto tales como putch() y cprintf().
Sintaxis:
int movetext (int izq, int ar, int der, int ab, int izqdest, int ardest);
Sintaxis:
void normvideo (void);
Afecta a la salida subsecuente de funciones de ventana de texto tales como putch() y cprintf().
Sintaxis:
int putch (int ch);
Sintaxis:
int puttext (int izq, int ar, int der, int ab, void *fuente);
Las son de pantalla absoluta, no relativas a la ventana actual. La esquina superior izquierda es (1,1).
Sintaxis:
void _setcursortype (int t_cur);
_NOCURSOR el cursor no se ve
_SOLIDCURSOR bloque slido
_NORMALCURSOR cursor compuesto de varias lneas inferiores
Sintaxis:
void textattr(int newattr);
Sintaxis:
void textbackground (int nuevo);
Sintaxis:
void text (int nuevo);
Sintaxis:
void textmode (int nuevomodo);
Sintaxis:
int ungetch (int ch);
La prxima llamada a getch() o cualquier otra funcin de entrada de consola devolver ch.
Devuelve el carcter ch si tiene xito. Si devuelve EOF, indica que hubo un error.
Sintaxis:
int wherex (void);
Sintaxis:
int wherey (void);
Sintaxis:
void window (int izq, int ar, int der, int ab);
S (enum)
BLACK DARKGRAY
BLUE LIGHTBLUE
GREEN LIGHTGREEN
CYAN LIGHTCYAN
BLINK
Esta constante se le suma a de fondo para visualizar caracteres parpadeantes en modo texto.
int directvideo;
Para usar directvideo = 1, el hardware de vdeo de nuestro sistema debe ser idntico a los adaptadores de
visualizacin de IBM.
Poner directvideo = 0 permite que la salida a consola trabaje con cualquier sistema que sea compatible a
nivel BIOS con IBM.
TEXT_INFO (struct)
struct text_info
{
unsigned char winleft, wintop;
unsigned char winright, winbottom;
unsigned char attribute, normattr;
unsigned char currmode;
unsigned char screenheight;
unsigned char screenwidth;
unsigned char curx, cury;
};
text_modes (enum)
LASTMODE BW80
BW40 C80
C40 C4350
MONO
extern int_wscroll;
La variable global _wscroll es un flag (bandera) de E/S de consola. Podemos usarla para dibujar entre los
ojos de una ventana sin provocar un scroll de la pantalla.
NOTA: En el ejemplo 3 de esta leccin se muestra cmo se pueden utilizar estas funciones en un programa
GLOSARIO:
*********
graphdefaults Pone todos los valores grficos a sus valores por defecto.
FUNCIONES:
**********
Sintaxis:
void far arc (int x, int y, int ang_comienzo, int ang_final, int radio);
(x,y) es el punto central; ang_comienzo y ang_final son los ngulos de comienzo y final en grados; radio es
el radio.
Sintaxix:
void far bar (int izq, int ar, int der, int ab);
Sintaxis:
void far bar3d (int izq, int ar, int der, int ab, int profundidad,
int flag_de_encima);
Sintaxis:
void far circle (int x, int y, int radio);
Sintaxis:
Sintaxis:
void far clearviewport (void);
Sintaxis:
void far closegraph (void);
Sintaxis:
void far detectgraph (int far *graphdriver, int far *graphmode);
Sintaxis:
void far drawpoly (int numero_de_puntos, int far *puntos_de_poligono);
*puntos_de_poligono apunta a numero_de_puntos pares de valores. Cada par da los valores de x e y para
un punto del polgono.
Sintaxis:
void far ellipse (int x, int y, int ang_comienzo, int ang_final,
int radiox, int radioy);
(x,y) es el punto central; ang_comienzo y ang_final son los ngulos de comienzo y final en grados; radiox y
radioy son los radios horizontal y vertical.
Sintaxis:
void far fillellipse (int x, int y, int radiox, int radioy);
Usa (x,y) como el punto central y rellena el arco usando el patrn de relleno actual; radiox y radioy son los
radios horizontal y vertical.
Sintaxis:
void far fillpoly(int numpoints, int far *polypoints[]);
Sintaxis:
void far floodfill (int x, int y, int _borde);
Sintaxis:
void far getarccoords (struct arccoordstype far *coords_arc);
Sintaxis:
void far getaspectratio (int far *cuadx, int far *cuady);
cuadx debera ser 10000. Usa cuadx=10000 cuando los pixels son cuadrados
(VGA); <10000 para pixels altos.
Sintaxis:
int far getbk (void);
Sintaxis:
int far get (void);
Sintaxis:
struct palettetype *far getdefaultpalette (void);
Devuelve un puntero a la estructura de paleta por defecto para el controlador actual inicializado mediante
una llamada a initgraph().
Sintaxis:
El puntero far devuelto apunta a una cadena que identifica el controlador gr fico actual.
Sintaxis:
void far getfillpattern (char far *patron);
Sintaxis:
void far getfillsettings (struct fillsettingstype far *fillinfo);
Sintaxis:
int far getgraphmode (void);
Sintaxis:
void far getimage(int izq, int ar, int der, int ab, void far *bitmap);
Sintaxis:
void far getlinesettings (struct linesettingstype far *infolinea);
Sintaxis:
int far getmax(void);
Sintaxis:
int far getmaxmode (void);
El modo mnimo es 0.
Sintaxis:
int far getmaxx(void);
int far getmaxy(void);
Sintaxis:
char * far getmodename (int numero_de_modo);
El puntero devuelto apunta al nombre (cadena) del modo especificado por numero_de_modo.
Sintaxis:
void far getmoderange (int controlador_grafico, int far *mode_bajo,
int far *mode_alto);
Sintaxis:
void far getpalette (struct palettetype far *paleta);
Sintaxis:
int far getpalettesize (void);
Devuelve el nmero de entradas de la paleta permitidas para el modo de controlador gr fico actual.
Sintaxis:
unsigned far getpixel (int x, int y);
Sintaxis:
void far gettextsettings (struct textsettingstype far *texttypeinfo);
Sintaxis:
void far getviewsettings (struct viewporttype far *viewport);
Sintaxis:
int far getx (void);
Sintaxis:
int far gety (void);
graphdefaults Pone todos los valores grficos a sus valores por defecto.
Sintaxis:
void far graphdefaults (void);
Sintaxis:
char *far grapherrormsg (int codigo_de_error);
Devuelve un puntero a una cadena asociada con el valor devuelvto por graphresult().
Esta funcin es llamada por las rutinas que hay en la biblioteca grfica para liberar memoria. Podemos
controlar esta asignacin de memoria suministrando nuestras propias funciones _graphgetmem() y
_graphfreemen().
Sintaxis:
void far * far _graphgetmem (unsigned tamanio);
Esta funcin es llamada por las rutinas que hay en la biblioteca grfica para asignar memoria. Podemos
controlar esta asignacin de memoria suministrando nuestras propias funciones _graphgetmem() y
_graphfreemen().
Devuelve el cdigo de error para la ltima operacin gr fica que inform de un error y pone el nivel de error
a grOK.
Sintaxis:
unsigned far imagesize (int izq, int ar, int der, int ab);
Si el tamao requerido para la imagen seleccionada es mayor o igual que 64K - 1 bytes, imagesize()
devuelve 0xFFFF.
Sintaxis:
void far initgraph (int far *controlador_grafico, int far *modo_grafico,
char far *path_para_controlador);
..\\bgi\\drivers
donde
bgi\drivers el el nombre de directorio donde buscar los controladores
el parmetro est encerrado entre comillas
el path para los ficheros de controladores grficos incluyen dos
barras invertidas
Sintaxis:
int far installuserdriver (char far *nombre, int huge (*detect) (void));
El parmetro nombre es el nombre del nuevo fichero de controlador de dispositivo (.BGI) y detect es un
puntero a una funcin de autodeteccin opcional que puede acompaar al nuevo controlador. Esta funcin
de autodeteccin no tiene ningn parmetro y devuelve un valor entero.
Sintaxis:
int far installuserfont (char far *nombre);
El parmetro nombre es el nombre del fichero que contiene las caractersticas del nuevo tipo de carcter en
modo grfico.
Sintaxis:
void far linerel (int dx, int dy);
Sintaxis:
void far lineto (int x, int y);
Sintaxis:
void far moverel (int dx, int dy);
Sintaxis:
void far moveto (int x, int y);
Sintaxis:
void far outtext (char far *cadena_de_texto);
Sintaxis:
void far outtextxy (int x, int y, char far *cadena_de_texto);
Sintaxis:
void far pieslice (int x, int y, int ang_comienzo, int ang_final,
int radio);
Sintaxis:
void far putimage (int izq, int ar, void far *bitmap, int op);
bitmap apunta a un mapa de bits, normalmente creado por la funcin getimage(). El valor op especifica
cmo se combina la imagen con el contenido actual del rea en (izq,ar).
Sintaxis:
void far putpixel (int x, int y, int color);
Sintaxis:
void far rectangle (int izq, int ar, int der, int ab);
Sintaxis:
int registerbgidriver (void (*driver) (void));
Informa al sistema gr fico que el controlador dispositivo apuntador por driver fue incluido en tiempo de
enlazado.
Sintaxis:
int registerbgifont (void (*font) (void));
Informa al sistema gr fico que el estilo de texto apuntado por font fue incluido en tiemo de enlazado.
Sintaxis:
void far restorecrtmode (void);
Sintaxis:
x e y definen el punto central; ang_comienzo y ang_final definen los ngulos de comienzo y final; radiox y
radioy son los radios horizontal y vertical.
Sintaxis:
void far setactivepage (int pagina);
Las salidas gr ficas siguientes a la llamada a esta funcin ir n a la p gina de visualizacin especificada. Esta
p gina puede no ser la p gina visual que es la que actualmente est visualizada.
Sintaxis:
void far setallpalette (struct palettetype far *paleta);
Sintaxis:
void far setaspectratio (int cuadx, int cuady);
cuadx debera ser 10000. Usa cuadx=10000 cuando los pixels son cuadrados (VGA); <10000 para pixels
altos.
Sintaxis:
void far setbk(int );
Sintaxis:
void far set (int );
Sintaxis:
void far setfillpattern (char far *patron_usuario, int );
Sintaxis:
void far setfillstyle (int patron, int );
Para poner un patrn de relleno definido por el usuario, llamar a la funcin setfillpattern().
Sintaxis:
unsigned far setgraphbufsize (unsigned tambuf);
Esta funcin debe ser llamada antes de llamar a la funcin initgraph(). Devuelve el tamao previo del buffer
interno.
Sintaxis:
void far setgraphmode (int modo);
Sintaxis:
void far setlinestyle (int estilo_de_linea, unsigned patron_usuario,
int grosor);
Sintaxis:
void far setpalette (int num_de_, int );
Sintaxis:
void far setrgbpalette (int num, int rojo, int verde, int azul);
El parmetro num es la entrada de la paleta a ser cargada (nmero entre 0 y 255). Los parmetros rojo,
verde y azul definen los es componentes.
Slo el byte menos significativo de estos valores es usado, y slo sus 6 bits ms significativos son cargados
en la paleta.
Sintaxis:
void far settextjustify (int horiz, int vert);
Afecta a la salida de texto con outtext(), etc. El texto es justificado horizontalmente y verticalmente.
Sintaxis:
void far settextstyle (int estilo, int direccion, int tamanio_de_caracter);
Sintaxis:
void far setusercharsize (int multx, int divx, int multy, int divy);
Sintaxis:
void far setviewport(int izq, int ar, int der, int ab, int clip);
Sintaxis:
void far setvisualpage (int pagina);
Algunos adaptadores grficos tienen ms de una p gina de memoria. La p gina visual es la p gina que est
actualmente visualizada en la pantalla. Las funciones gr ficas escriben en la p gina activa, definida por
setactivepage().
Sintaxis:
void far setwritemode (int modo);
Si el modo es 1, una operacin exclusive OR (XOR) es ejecutada entre los pixels de la lnea y los puntos
correspondientes sobre la pantalla.
Sintaxis:
int far textheight (char far *cadena_con_texto);
La funcin textwidth() es til para ser usadas con funciones gr ficas tales como outtext().
Sintaxis:
int far textwidth (char far *cadena_con_texto);
La funcin textwidth() es til para ser usadas con funciones gr ficas tales como outtext().
ARCCOORDSTYPE (struct)
Usado por la funcin getarccords() para obtener las de la ltima llamada a arc().
struct arccoordstype
{
int x, y; /* punto central */
int xstart, ystart; /* posicin inicial */
int xend, yend; /* posicin final */
};
EGA_xxxx (#defines)
EGA_BLACK EGA_DARKGRAY
EGA_BLUE EGA_LIGHTBLUE
EGA_GREEN EGA_LIGHTGREEN
EGA_CYAN EGA_LIGHTCYAN
EGA_RED EGA_LIGHTRED
EGA_MAGENTA EGA_LIGHTMAGENTA
EGA_BROWN EGA_YELLOW
EGA_LIGHTGRAY EGA_WHITE
fill_patterns (enum)
FILLSETTINGSTYPE (struct)
Usado para obtener los valores de relleno actuales por la funcin getfillsettings().
struct fillsettingstype
{
int pattern;
int color;
};
font_names (enum)
DEFAULT_FONT
TRIPLEX_FONT
SMALL_FONT
SANS_SERIF_FONT
GOTHIC_FONT
graphics_drivers (enum)
CGA MCGA
EGA EGA64
EGAMONO IBM8514
HERCMONO ATT400
VGA PC3270
DETECT (Requiere autodeteccin)
graphics_errors (enum)
grOk grNoInitGraph
graphics_modes (enum)
line_styles (enum)
SOLID_LINE
DOTTED_LINE
CENTER_LINE
line_widths (enum)
NORM_WIDTH
THICK_WIDTH
MAXS (#define)
PALETTETYPE (struct)
Contiene informacin de la paleta para el controlador gr fico actual. Esta estructura es usada por las
funciones getpalette(), setpalette() y setallpalette().
struct palettetype
{
unsigned char size;
signed char s[MAXS+1];
};
POINTTYPE (struct)
de un punto.
struct pointtype
{
int x ;
int y ;
};
putimage_ops (enum)
COPY_PUT Copia
XOR_PUT Exclusive OR
OR_PUT Inclusive OR
AND_PUT AND
NOT_PUT Copia inversa de fuente
text_just (enum)
TEXTSETTINGSTYPE (struct)
Usado para obtener los valores de texto actual por la funcin gettextsettings().
struct textsettingstype
{
int font;
int direction;
int charsize;
int horiz;
int vert;
};
USER_CHAR_SIZE (#define)
Tamao de los caracteres definidos por el usuario (tamao de caracteres = amplificacin de caracteres en
salida gr fica).
VIEWPORTTYPE (struct)
Estructura usada para obtener informacin sobre el viewport corriente por la funcin getviewsettings().
struct viewporttype
{
int left;
int top;
int right;
int bottom;
int clip;
};
LECCION 11
INDICE DE LA LECCION 11
- Primera parte:
Saltos no locales (setjmp.h).
Envo y recepcin de seales(signal.h).
Asignacin din mica (alloc.h en Turbo C).
Funciones de proceso (process.h).
- Segunda parte:
Funciones de directorio (dir.h).
Funciones del DOS (interrupt y dos.h).
Funciones de la ROM BIOS (bios.h).
SALTOS NO LOCALES
En el fichero de <setjmp.h> tenemos la informacin necesaria para poder realizar saltos no locales, es
decir, saltos de una funcin a otra.
Recordar que la instruccin goto del C slo puede realizar un salto dentro de una funcin.
FICHERO DE SETJMP.H
Sintaxis:
void longjmp (jmp_buf jmpb, int valdev);
La instruccin longjmp() da lugar a que la ejecucin del programa se retome en el punto en que se llam
por ltima vez a setjmp(). Estas dos funciones son la forma en que C permite saltar entre funciones. Tenga
en cuenta que se necesita la setjmp.h.
La funcin longjmp() opera inicializando la pila ya descrita por jmpb, que debe haber sido activada en una
llamada anterior a setjmp(). Esto da lugar a que la ejecucin del programa se retome en la sentencia
siguiente al setjmp() que la llam. En otras palabras, la computadora es engaada hacindole pensar que
nunca dej la funcin que llam a setjmp().
El buffer jmpb es de tipo jmp_buf, que est definido en la setjmp.h. El buffer debe haber sido activado a
travs de una llamada a setjmp(), anterior a la llamada a longjmp().
El valor de valdev se transforma en el valor de vuelta de setjmp() y puede preguntarse por l para determinar
de dnde viene longjmp(). El nico valor no permitido es 0, puesto que setjmp() devuelve este valor cuando
se le llama por primera vez.
Es importante comprender que longjmp() se debe llamar antes de que la funcin que llam a setjmp()
vuelva. Si no, el resultado queda indefinido. (Realmente, la mayor parte de las veces el programa aborta.)
La funcin setjmp() guarda el contenido de la pila del sistema en el buffer jmpb para ser utilizado ms tarde
por longjmp().
La funcin setjmp() devuelve 0 despus de la llamada. Sin embargo, longjmp() pasa un argumento a
setjmp() cuando se ejecuta, y es este valor (que siempre es disntino de cero) el valor de setjmp() despus
de la llamada a longjmp().
A continuacin se presenta la estructura del buffer para estas dos funciones en Turbo C, si utilizas otro
compilador puedes ver cmo es en el tuyo visualizando el fichero setjmp.h. De todas formas no es de
mucha utilidad saber cu l es el contenido de esta estructura.
jmp_buf (tipo)
Un buffer de tipo jmp_buf es usado para salvar y restaurar el estado de un programa en un determinado
momento.
typedef struct
{
unsigned j_sp, j_ss,
unsigned j_flag, j_cs;
unsigned j_ip, j_bp;
unsigned j_di, j_es;
unsigned j_si, j_ds;
} jmp_buf[1];
Veamos un ejemplo bastante ilustrativo de cmo poder realizar un salto no local. Este ejemplo corresponde
al primer ejemplo de esta leccin, de este modo lo puedes ejecutar.
/*
Este programa imprime 1 2 3
*/
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
En el fichero de <signal.h> hay declaradas dos funciones junto con algunas macros para poder enviar y
recibir seales(interrupciones) en un programa en ejecucin.
FICHERO DE SIGNAL.H
Este fichero slo declara dos funciones: raise() y signal(). Al ser estas dos funciones dependientes del
sistema, el ANSI C no da una sintaxis general para estas funciones, sino que nos dice que la funcin raise()
enva una seal a un programa en ejecucin y la funcin signal() define la funcin que se ejecutar en un
programa cuando ste reciba una determinada seal; el ANSI C tambindefine las macros: SIGABRT,
SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIG_DFL y SEIG_IGN, todas ellas declaradas, junto con
las funciones raise() y signal(), en el fichero de signal.h. Una descripcin completa de todas estas macros y
funciones se realizar en las siguientes lneas para aquellos usuarios que tengan la opcin de turbo a on.
Sintaxis:
int raise (int sig);
Un programa se puede enviar seales asmismo usando raise(). Esta funcin ejecuta el manejador
instalado por signal() para ese tipo de seal (o el manejador por defecto).
Sintaxis:
void (* signal (int sig, void (*func) (int sig [,int subcode]))) (int);
La funcin a la cual apunta func ser llamada cuando una seal de tipo sig sea enviada.
Las sealesson enviadas cuando ocurre una condicin de excepcin o cuando es llamada la funcin raise().
void (* signal (int sig, void (*func) (/* int */))) (int);
lo que quiere decir que los parmetros de func estn indefinidos pero que normalmente suele ser un int.
SIG_xxx (#defines)
Las funciones predefinidas para manejar las sealesgenerados por la funcin raise() o por sucesos
externos son:
SIGABRT Abortar
SIGFPE Trampa de punto flotante
SIGILL Instruccin ilegal
SIGINT Interrupcin
SIGSEGV Violacin de acceso a memoria
SIGTERM Terminar
Veamos a continuacin tres ejemplos sobre las funciones y macros del fichero de signal.h.
Ejemplo 1:
#include <stdio.h>
#include <signal.h>
x = 1; y = 0;
printf ("x/y: %d", x / y);
}
Ejemplo 2:
#include <stdio.h>
#include <signal.h>
x = 1; y = 0;
printf ("x/y: %d", x / y);
}
Ejemplo 3:
#include <stdio.h>
#include <signal.h>
raise (SIGFPE);
}
ASIGNACION DINAMICA
Hay dos modos fundamentales por los que un programa en C puede guardar informacin en la memoria
central de la computadora. El primero utilizando variables globales y locales (incluyendo arrays y
estructuras). El segundo modo por el que se puede guardar informacin es mediante el sistema de
asignacin din mica de C. Por este mtodo se asigna de la memoria libre tanto espacio como se necesite.
La zona de memoria libre se encuentra entre el rea de almacenamiento permanente del programa y la pila.
(Para la familia de procesadores 8088, el montn se supone que est en el segmento de datos por
defecto.)
El ncleo del sistema de asignacion din mica son las funciones malloc() y free() que se encuentran en la
biblioteca estndar de C. Cada vez que se hace una peticin de memoria mediante malloc(), se asigna una
porcin del resto de la memoria libre. Cada vez que se hace una llamada para liberar memoria mediante
free(), la memoria se devuelve al sistema. La forma ms comn para implementar malloc() y free() es
organizar la memoria libre en una lista enlazada. Sin embargo, el estndar ANSI propuesto afirma que el
mtodo de gestin de memoria depende de la implementacin.
El estndar ANSI propuesto especifica que la informacin de necesaria para el sistema de asignacin
din mica se encuentra en stdlib.h y slo define cuatro funciones para el sistema de asignacin din mica:
calloc(), malloc(), free() y realloc(). Sin embargo, los compiladores suelen suministrar ms funciones bien en
el fichero de malloc.h o bien en el fichero alloc.h, dependiendo del compilador.
Las funciones aadidas al ANSI C son necesarias para soportar eficientemente la arquitectura segmentada
de la familia de procesadores 8088. Etas funciones no son v lidas para compiladores diseados para otros
procesadores como el 68000. Debido a la segmentacin de memoria que presenta la familia de
procesadores 8088, se incorporan dos nuevos modificadores de tipo no estndares que generalmente son
soportados por compiladores construidos para estos procesadores. Son near y far, que se utilizan
normalmente para crear punteros de otro tipo que el normalmente utilizado por el modelo de memoria del
Esencialmente, es posible organizar la memoria de una computadora basada en el 8088 en uno de estos
cuatro modelos (se presentan en orden creciente de tiempo de ejecucin):
Pequeo: Todo el cdigo debe ajustarse a un segmento de 64K y todos los datos deben ajustarse a un
segundo segmento de 64K. Todos los punteros son de 16 bits. Este modelo da lugar a la ejecucin ms
rpida del programa.
Medio: Todos los datos deben contenerse en un segmento de 64K, pero el cdigo puede utilizar varios
segmentos. Todos los punteros a datos son de 16 bits. Este modelo permite un rpido acceso a los datos,
pero una ejecucin del cdigo lenta.
Compacto: Todo el cdigo debe ajustarse a un segmento de 64K, pero los datos pueden utilizar varios
segmentos. Todos los punteros a datos son de 32 bits. La organizacin compacta de la memoria supone un
acceso lento a los datos, pero una ejecucin de cdigo rpida.
Grande: Cdigo y datos utilizan varios segmentos. Todos los punteros son de 32 bits. Este modelo da
lugar a la ejecucin ms lenta del programa.
Como puedes imaginar, el acceso a memoria utilizando punteros de 16 bits es mucho ms rpido que
utilizando punteros de 32 bits. Sin embargo, los punteros de 32 bits son necesarios cuando el cdigo, los
datos, o ambos superan la barrera de los 64K. Una forma de evitar el uso de los punteros de 32 bits es
permitir la creacin de punteros de 16 32 bits explcitamente por parte del programa, pasando por alto as
el valor implcito. Tpicamente, esto ocurre cuando un programa necesita gran cantidad de datos para una
determinada operacin. En este caso se crea un puntero far, y la memoria se asigna utilizando la versin no
estndar de malloc() que asigna memoria fuera del segmento de datos por defecto. De esta forma todos los
dems accesos a memoria son r pidos, y el tiempo de ejecucin no se incrementa tanto como si se hubiera
utilizado un modelo grande. A la inversa tambinpuede ocurrir. Un programa que utilice un modelo grande
puede fijar un puntero near a un fragmento de memoria frecuentemente accedido para incrementar el
rendimiento.
En la siguiente ventana estudiaremos todas las funciones que estn declaradas en el fichero de <alloc.h>
que se encuentra en Turbo C.
Las funciones de asignacin din mica que define el ANSI C y que en el estndar estn declaradas en el
fichero de <stdlib.h>, en el caso de Turbo C, estn declaradas tambinen el fichero alloc.h. Estas
funciones son: calloc(), malloc(), free() y realloc().
Sintaxis:
int brk (void *addr);
Pone el tope del segmento de datos del programa en la localizacin de memoria apuntada por addr. Si la
operacin tiene xito, brk() devuelve el valor de 0. Si ocurre un fallo, devuelve el valor de -1 y da valor a
errno.
Ejemplo:
/*
Este programa imprime (en mi sistema):
Cambiando asignacin con brk().
Antes de la llamada a brk(): 63488 bytes libres.
Despus de la llamada a brk(): 62496 bytes libres.
*/
Sintaxis:
void *calloc (size_t nelems, size_t tam);
Asigna espacio para nelems elementos de tam bytes cada uno y almacena cero en el rea. Devuelve un
puntero al nuevo bloque asignado o NULL si no existe bastante espacio.
Sintaxis:
Modelos tiny, small, y medium:
unsigned coreleft (void);
El lector de este texto quizs se pregunte cmo puede declararse la misma funcin coreleft() con dos tipos
diferentes. Esto es muy f cil hacerlo utilizando las directivas de compilacin condicional:
Ejemplo:
/*
Este programa imprime (en mi sistema):
La diferencia entre el bloque asignado ms alto
y la cima del montn es: 63552 bytes.
*/
Sintaxis:
void far *farcalloc (unsigned long nunids, unsigned long tamunid);
Asigna espacio para nunids elementos de tamunid cada uno. Devuelve un puntero al nuevo bloque
asignado, o NULL si no hay suficiente memoria para el nuevo bloque.
Sintaxis:
unsigned long farcoreleft (void);
Devuelve la cantidad total de espacio libre (en bytes) entre el bloque asignado ms alto y el final de la
memoria.
Sintaxis:
void farfree (void far *bloque);
Sintaxis:
int farheapcheck (void);
La funcin farheapcheck() camina a travs del montn far y examina cada bloque, chequeando sus
punteros, tamao, y otros atributos crticos.
El valor devuelto es menor de cero si ocurre un error y mayor de cero si tiene xito.
Sintaxis:
int farheapcheckfree (unsigned int valorrelleno);
El valor devuelto es menor de cero si ocurre un error y mayor de cero si tiene xito.
Sintaxis:
int farheapchecknode (void *nodo);
Sintaxis:
int farheapfillfree (unsigned int valorrelleno);
El valor devuelto es menor de cero si ocurre un error y es mayor de cero si tiene xito.
Sintaxis:
int farheapwalk (struct farheapinfo *hi);
La funcin farheapwalk() asume que el montn es correcto. Usa farheapcheck() para verificar el montn
antes de usar farheapwalk(). _HEAPOK es devuelto con el ltimo bloque en el montn. _HEAPEND ser
devuelto en la prxima llamada a farheapwalk().
struct heapinfo
{
void huge *ptr;
unsigned long size;
int in_use;
};
Sintaxis:
void far *farmalloc (unsigned long nbytes);
Devuelve un puntero al nuevo bloque asignado, o NULL si no existe suficiente espacio para el nuevo
bloque.
Sintaxis:
void far *farrealloc (void far *viejobloque, unsigned long nbytes);
Devuelve la direccin del bloque reasignado, o NULL si falla. La nueva direccin puede ser diferente a la
direccin original.
Sintaxis:
void free (void *bloque);
Sintaxis:
int heapcheck (void);
La funcin farheapcheck() camina a travs del montn y examina cada bloque, chequeando sus punteros,
tamao, y otros atributos crticos.
El valor devuelto es menor de cero si ocurre un error y mayor de cero si tiene xito.
Ejemplo:
#include <stdio.h>
#include <alloc.h>
p = malloc (100);
free (p+1);
if (heapcheck () < 0)
printf ("El montn est corrompido.\n");
else
printf ("El montn es correcto.\n");
}
Sintaxis:
int heapcheckfree (unsigned int valorrelleno);
El valor devuelto es menor de cero si ocurre un error y mayor de cero si tiene xito.
Sintaxis:
int heapchecknode (void *nodo);
Si un nodo ha sido liberado y heapchecknode() es llamado con un puntero al bloque libre, heapchecknode()
puede devolver _BADNODE en vez del esperado _FREEENTRY. Esto sucede porque los bloques libres
adyacentes en el montn son unidos, y el bloque en cuestin no existe.
El valor devuelto es menor de cero si ocurre un error y mayor de cero si tiene xito.
Ejemplo:
#include <stdio.h>
#include <alloc.h>
#define NUM_PTRS 10
#define NUM_BYTES 16
Sintaxis:
int heapfillfree (unsigned int valorrelleno);
El valor devuelto es menor de cero si ocurre un error y es mayor de cero si tiene xito.
Sintaxis:
int heapwalk (struct heapinfo *hi);
La funcin heapwalk() asume que el montn es correcto. Usa heapcheck() para verificar el montn antes de
usar heapwalk(). _HEAPOK es devuelto con el ltimo bloque en el montn. _HEAPEND ser devuelto en la
prxima llamada a heapwalk().
La funcin heapwalk() recibe un puntero a una estructura de tipo heapinfo (declarada en alloc.h). Para la
primera llamada a heapwalk(), pon el campo hi.ptr a null. La funcin heapwalk() devuelve en hi.ptr la
direccin del primer bloque. El campo hi.size contiene el tamao del bloque en bytes. El campo h.in_use es
un flag que se pone a 1 si el bloque est actualmente en uso.
struct heapinfo
{
void *ptr;
unsigned int size;
int in_use;
};
Sintaxis:
void *malloc (size_t tam);
El parmetro tam est en bytes. Devuelve un puntero al nuevo bloque asignado, o NULL si no existe
suficiente espacio para el nuevo bloque. Si tam == 0, devuelve NULL.
Sintaxis:
void *realloc (void *bloque, size_t tam);
Ejemplo:
/*
Este programa imprime (en mi sistema):
El string es Hola
Est en la direccin 05A0
El string es Hola
Est en la nueva direccin 05AE
*/
#include <stdio.h>
#include <alloc.h>
#include <string.h>
/* libera memoria */
free (str);
}
Sintaxis:
void *sbrk (int incr);
Suma incr bytes al valor umbral. Si la operacin tiene xito, sbrk() devuelve el viejo valor umbral. Si falla,
devuelve -1 y le da valor a errno.
Ejemplo:
/*
Este programa imprime (en mi sistema):
Cambiando asignacin con sbrk().
Antes de la llamada a sbrk(): 63504 bytes libres.
Despus de la llamada a sbrk(): 62496 bytes libres.
*/
FUNCIONES DE PROCESO
En el fichero <process.h> de Turbo C nos encontramos la declaracin de una serie de funciones que las
podemos dividir en dos grupos: las que terminan el programa en ejecucin para volver al sistema operativo
y las que ejecutan otro programa.
GLOSARIO:
*********
FUNCIONES:
**********
Sintaxis:
void abort (void);
Sintaxis:
int execl (char *path, char *arg0, .., NULL);
int execle (char *path, char *arg0, .., NULL, char **env);
int execlp (char *path, char *arg0, ..);
int execlpe (char *path, char *arg0, .., NULL, char **env);
Cuando se hace una llamada exec..., el proceso hijo ocupa el lugar del proceso padre. Debe haber
suficiente memoria disponible para cargar y ejecutar el proceso hijo.
Usa execl(), execle(), execlp() y execlpe() cuando conoces todos los argumentos que tendr el proceso hijo
a ejecutar.
Usa execv(), execve(), execvp() y execvpe() cuando no conoces a priori los argumentos que tendr el
proceso hijo a ejecutar.
Si tiene xito, las funciones exec no devuelven nada. En caso de error, las funciones exec devuelven -1 y
asigna a errno el cdigo de error.
Sintaxis:
void exit (int estado);
Antes de terminar, la salida buffereada es volcada, los ficheros son cerrados y las funciones exit() son
llamadas.
Sintaxis:
void _exit (int estado);
Usa spawnl(), spawnle(), spawnlp() y spawnlpe() cuando conoces todos los argumentos que tendr el
proceso hijo a ejecutar.
Usa spawnv(), spawnve(), spawnvp() y spawnvpe() cuando no conoces a priori los argumentos que tendr el
proceso hijo a ejecutar.
Si la ejecucin tiene xito, el valor devuelto es el estado de salida del proceso hijo (0 para terminacin
normal).
Sintaxis:
int system (const char *comando);
comando puede ejecutar un comando interno del DOS tales como DIR, un fichero de programa .COM o
.EXE, o un fichero batch .BAT.
Devuelve 0 en caso de xito, -1 en caso de error y se le asigna a errno uno de los siguientes valores:
ENOENT, ENOMEM, E2BIG o ENOEXEC.
La funcin system() tambinse encuentra declarada en los ficheros stdlib.h y system.h. En el fichero
system.h slo se encuentra el prototipo de la funcin system().
P_xxxx (#defines)
Direccin del segmento del PSP (Prefijo de Segmento de Programa) del programa.
FUNCIONES DE DIRECTORIO
En el fichero de <dir.h> de Turbo C tenemos declaradas una serie de funciones relacionadas con los
directorios.
GLOSARIO:
*********
Sintaxis:
int chdir (const char *path);
Si la operacin tiene xito, chdir() devuelve 0. En otro caso, devuelve 1 y asigna a errno cdigo de error.
FUNCIONES:
**********
Sintaxis:
int findfirst (const char *nombrepath, struct ffblk *ffblk, int atributo);
int findnext (struct ffblk *ffblk);
? (coincidencia de un carcter)
* (coincidencia de una serie de caracteres)
Devuelve 0 si tiene xito; devuelve -1 si ocurre un error, y se le asigna a errno el cdigo de error.
Ejemplo:
#include <stdio.h>
#include <dir.h>
return 0;
}
Sintaxis:
void fnmerge (char *path, const char *unidad, const char *dir,
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <dir.h>
elementos separados */
strcpy (fichero, "DATOS");
strcpy (ext, ".TXT");
fnmerge (s, unidad, dir, fichero, ext); /*fusiona todas las componentes*/
puts (s); /* visualiza el string resultado */
return 0;
}
Sintaxis:
int fnsplit (const char *path, char *unidad, char *dir, char *nombre,
char *ext);
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
#include <dir.h>
return 0;
}
Sintaxis:
int getcurdir (int unidad, char *directorio);
Sintaxis:
char *getcwd (char *buffer, int longitud_buffer);
Devuelve un puntero a buffer; en caso de error, devuelve NULL y a errno se le asigna el cdigo de error.
Ejemplo:
#include <stdio.h>
#include <dir.h>
Sintaxis:
int getdisk (void);
Ejemplo:
#include <stdio.h>
#include <dir.h>
Sintaxis:
int mkdir (const char *path);
Ejemplo:
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <dir.h>
clrscr ();
estado = mkdir (asdfjklm);
(! estado) ? (printf ("Directorio creado\n)") :
(printf ("No es posible crear directorio\n)");
getch ();
system (dir);
getch ();
return 0;
}
Sintaxis:
char *mktemp (char *nomfich);
Reemplaza nomfich por un nombre de fichero nico y devuelve la direccin de nomfich; nomfich debera ser
una cadena terminada en nulo con 6 X's restantes. Por ejemplo, MIFICHXXXXXX.
Ejemplo:
#include <dir.h>
#include <stdio.h>
Sintaxis:
int rmdir (const char *path);
Devuelve 0 si tiene xio; en caso de error, devuelve -1 y en errno se pone el cdigo de error.
Ejemplo:
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <dir.h>
getch ();
system (dir/p);
getch ();
return 0;
}
Devuelve un puntero a una cadena con el nombre de path completo de fichero si tiene xito; en otro caso,
devuelve NULL. Esta cadena est en un rea esttica que es sobreescrita en cada nueva llamada.
Ejemplo:
#include <stdio.h>
#include <dir.h>
return 0;
}
Sintaxis:
int setdisk (int unidad);
0=A
1=B
2=C
etc.
Ejemplo:
#include <stdio.h>
#include <dir.h>
return 0;
}
FFBLK (struct)
struct ffblk
{
char ff_reserved[21];
char ff_attrib;
unsigned ff_ftime;
unsigned ff_fdate;
long ff_fsize;
char ff_name[13];
};
fnsplit (#defines)
Definiciones de bits devueltos por fnsplit para identificar qu partes de un nombre de fichero fueron
encontrados durante la descomposicin.
FUNCIONES DE INTERRUPCION
Turbo C posee la palabra clave interrupt que define una funcin como un manejador de interrupcin. La
sintaxis de esta palabra clave es:
interrupt definicion_de_funcion;
Cuando en Turbo C usemos la palabra clave interrupt en un programa tenemos que desactivar el chequeo
de pila y el uso de variables registros en el entorno.
GLOSARIO:
*********
FUNCIONES:
**********
Sintaxis:
int absread (int drive, int nsects, long lsect, void *buffer);
int abswrite (int drive, int nsects, long lsect, void *buffer);
drive es 0 = A, 1 = B, 2 = C, etc.
nsects es el nmero de sectores a leer/escribir
lsect es el sector lgico de comienzo (0 es el primero)
buffer es la direccin del rea de datos
64K es la cantidad de memoria ms grande por llamada que puede ser leda o escrita.
Devuelve 0 si tiene xito; en caso de error, devuelve -1 y pone en errno el nmero de error.
Sintaxis:
int allocmem (unsigned tam, unsigned *pseg);
tam es el nmero de p rrafos a asignar (un p rrafo son 16 bytes). La direc- cin del segmento del rea
asignada es almacenada en *pseg; el offset = 0.
Devuelve -1 si tiene xito. En otro caso devuelve el tamao del bloque disponible ms grande, y pone en
_doserrno y errno el cdigo de error.
Ejemplo:
#include <dos.h>
#include <alloc.h>
#include <stdio.h>
return 0;
}
Sintaxis:
int bdos (int dosfun, unsigned dosdx, unsigned dosal);
Ejemplo:
#include <stdio.h>
#include <dos.h>
Sintaxis:
int bdosptr (int dosfun, void *argument, unsigned dosal);
El valor devuelto por bdosptr() es el valor de AX si tiene xito, o -1 si falla. En caso de fallo, se pone errno y
_doserrno con el cdigo de error.
Sintaxis:
struct COUNTRY *country (int xcode, struct COUNTRY *pc);
Ejemplo:
#define USA 0
Sintaxis:
void ctrlbrk (int (*manejador) (void));
La funcin manejador devuelve 0 para abortar el programa actual; en otro caso el programa continuar la
ejecucin.
Ejemplo:
#include <stdio.h>
#include <dos.h>
#define ABORT 0
Sintaxis:
void delay (unsigned milisegundos);
Sintaxis:
void disable (void);
Sintaxis:
int dosexterr (struct DOSERROR *eblkp);
Rellena los campos de *eblkp basados en la ltima llamada al DOS. Devuelve el valor del campo
de_exterror de la estructura.
Sintaxis:
long dostounix (struct date *d, struct time *t);
Devuelve la versin de UNIX de la hora actual: nmero de segundos desde el 1 de Enero de 1970 (GMT).
Sintaxis:
void __emit__ (argument, ...);
Ejemplo:
#include <dos.h>
Sintaxis:
void enable (void);
Ejemplo:
int cont = 0;
return 0;
}
Sintaxis:
unsigned FP_OFF (void far *p);
unsigned FP_SEG (void far *p);
void far *MK_FP (unsigned seg, unsigned ofs);
Sintaxis:
int freemem (unsigned segx);
Sintaxis:
void geninterrupt (int num_interrup);
El estado de todos los registros despus de la llamada es dependiente de la interrupcin llamada. Cuidado:
las interrupciones pueden dejar registros usados por Turbo C en un estado impredecible.
Sintaxis:
int getcbrk (void);
Ejemplo:
#include <stdio.h>
#include <dos.h>
return 0;
}
Sintaxis:
void getdate (struct date *pfecha);
Ejemplo:
#include <dos.h>
#include <stdio.h>
getdate (&d);
printf ("El da actual es: %d\n", d.da_day);
printf ("El mes actual es: %d\n", d.da_mon);
printf ("El ao actual es es: %d\n", d.da_year);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <dir.h>
#include <dos.h>
return 0;
}
Sintaxis:
char far *getdta (void);
Ejemplo:
#include <dos.h>
#include <stdio.h>
Sintaxis:
void getfatd (struct fatinfo *dtable);
Sintaxis:
int getftime (int descriptor, struct ftime *pftime);
Sintaxis:
unsigned getpsp (void);
Sintaxis:
void gettime (struct time *phora);
Ejemplo:
#include <stdio.h>
#include <dos.h>
gettime (&t);
printf ("La hora actual es: %2d:%02d:%02d.%02d\n",
t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
return 0;
}
Sintaxis:
void interrupt (*getvect (int num_interrupcion)) ();
Sintaxis:
int getverify (void);
Ejemplo:
#include <stdio.h>
#include <dos.h>
Sintaxis:
void harderr (int (*manejador) ());
La funcin apuntada por manejador ser llamada cuando el DOS encuentre un error crtico (INT 0x24).
Ejemplo:
/*
Este programa atrapa los errores de disco y pregunta al usuario la
accin a realizar. Intenta ejecutarlo con ningn disco en la unidad A:
para invocar sus funciones.
*/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define IGNORAR 0
#define REINTENTAR 1
#define ABORTAR 2
int buf[500];
cputs (msj);
{
valdev = ABORTAR;
break;
}
if (valdev == 'r' || valdev == 'R')
{
valdev = REINTENTAR;
break;
}
if (valdev == 'i' || valdev == 'I')
{
valdev = IGNORAR;
break;
}
}
return (valdev);
}
/* pragma warn -par reduce los warnings (avisos) que ocurren debidos al
no uso de los parmetros errval, bp y si en manejador() */
#pragma warn -par
int manejador (int errval, int ax, int bp, int si)
{
static char msj[80];
unsigned di;
int unidad;
int numerror;
di= _DI;
/*si no es un error de disco entonces fue otro problema de dispositivo*/
if (ax < 0)
{
/* informa del error */
error (Error de dispositivo);
Sintaxis:
void hardresume (int axret);
El manejador de error establecido por harderr() puede devolver el control de la ejecucin a la rutina del
COS que provoc el error crtico va esta funcin. El valor en axret es devuelto al DOS.
Valor
devuelto Significado
0 ignorar
1 reintentar
2 abortar
Sintaxis:
void hardretn (int retn);
El manejador de error establecido por harderr puede volver directamente al programa de aplicacin
llamando a hardretn().
El valor en retn es devuelto al programa de usuario en lugar del valor normal devuelto de la funcin DOS
que gener el error crtico.
Sintaxis:
int inp (int portid);
Sintaxis:
unsigned char inportb (int portid);
Sintaxis:
int int86 (int intno, union REGS *inregs, union REGS *outregs);
Esta funcin carga los registros de la CPU con los valores almacenados en inregs, ejecuta la interrupcin
intno, y almacena los valores resultados de los registros de la CPU en outregs.
Ejemplo:
#include <stdio.h>
#include <conio.h>
#include <dos.h>
Sintaxis:
Esta funcin carga los registros de la CPU con los valores almacenados en inregs y segregs, ejecuta la
interrupcin intno, y almacena los valores resultados de los registros de la CPU en outregs y segregs.
Sintaxis:
int intdos (union REGS *inregs, union REGS *outregs);
Esta funcin carga los registros de la CPU con los valores almacenados en inregs, ejecuta la interrupcin
DOS (int 33 o 0x21), y almacena los valores resultados de los registros de la CPU en outregs.
Sintaxis:
int intdosx (union REGS *inregs, union REGS *outregs,
struct SREGS *segregs);
Esta funcin carga los registros de la CPU con los valores almacenados en inregs y segregs, ejecuta la
interrupcin DOS (int 0x21), y almacena los valores resultados de los registros de la CPU en outregs y
segregs.
Sintaxis:
void intr (int intno, struct REGPACK *preg);
Esta funcin carga los registros de la CPU con los valores almacenados en preg, ejecuta la interrupcin
intno, y almacena los valores resultados de los registros de la CPU en preg.
Sintaxis:
void keep (unsigned char estado, unsigned tamanio);
Esta funcin vuelve al DOS con valor de salida en estado, pero el programa queda en memoria. La porcin
de programa residente ocupa tamao p rrafos y la memoria del programa restante es liberada.
Sintaxis:
void nosound (void);
Sintaxis:
Sintaxis:
void outport (int portid, int value);
Sintaxis:
void outportb (int portid, unsigned char value);
Sintaxis:
char *parsfnm (const char *cmdline, struct fcb *fcb, int opt);
Despus de analizar con xito el nombre del fichero, parsfnm() devuelve un puntero al byte siguiente
despus del final del nombre del fichero. Si no se produce ningn error en el an lisis del nombre del fichero,
devuelve 0.
Sintaxis:
int peek (unsigned segmento, unsigned desplazamiento);
Sintaxis:
char peekb (unsigned segmento, unsigned desplazamiento);
Sintaxis:
void poke(unsigned segmento, unsigned desplazamiento, int valor);
Sintaxis:
void pokeb (unsigned segmento, unsigned desplazamiento, char valor);
Sintaxis:
Si devuelve 0 todos los registros han sido ledos correctamente, si devuelve otro valor ha habido algn
problema.
Sintaxis:
int randbwr (struct fcb *fcb, int rcnt);
Si devuelve 0 todos los registros han sido escritos correctamente, si devuelve otro valor ha habido algn
problema.
Sintaxis:
void segread (struct SREGS *segp);
#include <stdio.h>
#include <dos.h>
segread (&segs);
printf ("Valores de los registros del segmento actual\n");
printf ("CS: %X DS: %X\n", segs.cs, segs.ds);
printf ("ES: %X SS: %X\n", segs.es, segs.ss);
return 0;
}
Sintaxis:
int setblock (unsigned segx, unsigned nuevotam);
En caso de error, devuelve el tamao del bloque posible ms grande y a _doserrno se le asigna el cdigo
de error.
Sintaxis:
int setcbrk (int valorcbrk);
Si valorcbrk es 1, chequea el Ctrl-Break en cada llamada al sistema. Si es 0, chequea slo en las llamadas
de E/S de consola, impresora y comunicaciones.
Sintaxis:
void setdate (struct date *pfecha);
Sintaxis:
void setdta (char far *dta);
Sintaxis:
void settime (struct time *phora);
Sintaxis:
void setvect (int interruptno, void interrupt (*isr) ( ));
isr apunta a una funcin que ser llamada cuando ocurra el nmero de interrupcin interrruptno. Si isr es
una funcin C, debera ser definida con la palabra clave interrupt.
Ejemplo:
#include <stdio.h>
#include <dos.h>
#include <conio.h>
int cont = 0;
return 0;
}
Sintaxis:
void setverify (int valor);
Si valor=1, cada operacin de escritura en disco ser seguida por una operacin de lectura para asegurar
resultados correctos. (0 significa no lectura de comprobacin.)
Sintaxis:
void sleep (unsigned segundos);
Ejemplo:
#include <dos.h>
#include <stdio.h>
Sintaxis:
void sound (unsigned frequencia);
Sintaxis:
void unixtodos (long time, struct date *d, struct time *t);
Sintaxis:
int unlink (const char *nombre_de_fichero);
Si el fichero nombre_de_fichero tiene el atributo de slo lectura, unlink() fallar . En este caso es necesario
llamar primero a chmod() para cambiar el atributo del fichero.
Si el programa est ejecut ndose en una m quina con coprocesador matemtico, _8087 es distinto de cero:
valor Coprocesador
_8087 matem tico
1 8087
2 80287
3 80387
0 (no detectado)
BYTEREGS (struct)
WORDREGS (struct)
struct BYTEREGS
{
unsigned char al, ah, bl, bh;
unsigned char cl, ch, dl, dh;
};
struct WORDREGS
{
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
COUNTRY (struct)
La estructura COUNTRY especifica cmo se van a formatear ciertos datos dependientes del pas.
struct COUNTRY
{
int co_date; /* formato de fecha */
char co_curr[5]; /* smbolo de moneda */
char co_thsep[2]; /* separador de millar */
char co_desep[2]; /* separador decimal */
char co_dtsep[2]; /* separador de fecha */
char co_tmsep[2]; /* separador de tiempo */
char co_currstyle; /* estilo de moneda */
char co_digits; /* dgitos significativos en moneda */
char co_time;
long co_case;
char co_dasep[2]; /* separador de datos */
char co_fill[10];
};
DATE (struct)
struct date
{
int da_year;
char da_day;
char da_mon;
DEVHDR (struct)
struct devhdr
{
long dh_next;
short dh_attr;
unsigned short dh_strat;
unsigned short dh_inter;
char dh_name[8];
};
DFREE (struct)
struct dfree
{
unsigned df_avail; /* Clusters disponibles */
unsigned df_total; /* Clusters totales */
unsigned df_bsec; /* Bytes por sector */
unsigned df_sclus; /* Sectores por cluster */
};
int _doserrno;
Cuando en una llamada al sistema MS-DOS ocurre un error, a _doserrno se le asigna el cdigo de error
DOS actual.
Los mnemotcnicos para los cdigos de error de DOS actual que pueden ser asignados a _doserrno son:
dosSearchInfo (tipo)
typedef struct
{
char drive;
char pattern [13];
char reserved [7];
char attrib;
short time;
short date;
long size;
char nameZ [13];
} dosSearchInfo;
FATINFO (struct)
struct fatinfo
{
char fi_sclus; /* sectores por cluster */
char fi_fatid; /* el byte identificador de la FAT */
int fi_nclus; /* nmero de clusters */
int fi_bysec; /* bytes por sector */
};
FCB (struct)
struct fcb
FA_xxxx (#defines)
unsigned _heaplen
El valor de _heaplen al principio de la ejecucin del programa determina el tamao del montn near que
ser asignado. El valor de 0, por defecto, hace un montn de tamao mximo.
NFDS (#define)
Direccin del segmento del PSP (Prefijo de Segmento de Programa) del programa.
REGPACK (struct)
struct REGPACK
{
unsigned r_ax, r_bx, r_cx, r_dx;
unsigned r_bp, r_si, r_di;
unsigned r_ds, r_es, r_flags;
};
REGS (union)
La unin REGS es usada para pasar y recibir informacin en las funciones intdos(), intdosx(), int86() y
int86x().
union REGS
{
struct WORDREGS x;
struct BYTEREGS h;
};
SREGS (struct)
La estructura de los registros de segmentos pasadas y rellenadas en las funciones intdosx(), int86x() y
segread().
struct SREGS
{
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
Para poner un tamao de pila diferente, debes declarar _stklen en tu fichero fuente como una variable
global. (Colcala fuera de todas las funciones.)
Por ejemplo, para poner un tamao de pila de 20000 bytes, usa la siguiente declaracin:
TIME (struct)
Estructura de la hora usada por las funciones dostounix(), gettime(), settime() y unixtodos().
struct time
{
unsigned char ti_min;
unsigned char ti_hour;
unsigned char ti_hund;
unsigned char ti_sec;
};
BYTEREGS (struct)
WORDREGS (struct)
struct BYTEREGS
{
unsigned char al, ah, bl, bh;
unsigned char cl, ch, dl, dh;
};
struct WORDREGS
{
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
XFCB (struct)
struct xfcb
{
char xfcb_flag;
char xfcb_resv[5];
char xfcb_attr;
struct fcb xfcb_fcb;
is
Cada una de las funciones declaradas en el fichero de <bios.h> de Turbo C representa una rutina de
servicio de la ROM BIOS. Todas estas funciones se pueden implementar con las funciones int86() y int86x()
del fichero de <dos.h>. Para conocer ms detalles sobre las funciones del fichero bios.h tendr s que
consultar un manual en el que se describan las funciones de la ROM BIOS.
beginvis
no_multiatributo
FICHERO DE BIOS.H (TC)
_completas 1 2 80 24
03
Sintaxis:
int bioscom (int cmd, char byte, int puerto);
Los 8 bits ms significativos del valor devuelto son los bits de estado.
Los 8 bits menos significativos dependen del cmd especificado.
Sintaxis:
int biosdisk (int cmd, int unidad, int cabeza, int pista, int sector,
int nsects, void *buffer);
Para saber los valores que puede tomar cmd y el significado de cada uno de ellos consulta la interrupcin
13 hex. de la ROM BIOS.
Sintaxis:
int bioskey (int cmd);
cmd Accin
Sintaxis:
int biosmemory (void);
Ejemplo:
#include <stdio.h>
#include <bios.h>
Sintaxis:
int biosprint (int cmd, int byte, int puerto);
Sintaxis:
long biostime (int cmd, long nuevahora);
Ejemplo:
#include <stdio.h>
#include <bios.h>
is
end leccin 11
; LECCION 12
INDICE DE LA LECCION 12
- Primera parte:
- Segunda parte:
FUNCIONES VARIAS
15 3
La stdlib.h tambindefine los tipos div_t y ldiv_t que son los valores devueltos por div() y ldiv(),
respectivamente. Adems define las macros: ERANGE (valor asignado a errno si se produce un error de
rango), HUGE_VAL (mayor valor representable por rutinas en coma flotante) y RAND_MAX (mximo valor
que puede ser devuelto por la funcin rand()).
beginvis
no_multiatributo
FICHERO DE STDLIB.H
_completas 1 2 80 24
03
GLOSARIO:
*********
(TC)
_lrotl and _lrotr Rota un valor long a la izquierda (_lrotl).
Rota un valor long a la derecha (_lrotr).
max y min (TC) Macros que generan cdigo en lnea para encontrar el
valor mximo y mnimo de dos enteros.
(TC)
_rotl and _rotr Rota un valor unsigned int a la izquierda (_rotl).
Rota un valor unsigned int a la derecha (_rotr).
FUNCIONES:
**********
Sintaxis:
void abort (void);
Ejemplo:
#include <stdio.h>
#include <stdlib.h>
Sintaxis:
int abs (int x);
Ejemplo:
#include <stdio.h>
#include <math.h>
Sintaxis:
int atexit (atexit_t func);
La funcin atexit() fija la funcin apuntada por func como la funcin a ser llamada una vez alcanzada la
terminacin normal del programa. Es decir, al final de la ejecucin de un programa, se llama a la funcin
especificada.
La funcin atexit() devuelve 0 si la funcin queda establecida como funcin de terminacin; en cualquier
otro caso devuelve un valor distinto de cero.
Se pueden fijar varias funciones de terminacin siendo llamadas en orden inverso al de su establecimiento.
En otras palabras, la naturaleza del proceso de registro es como una pila.
Ejemplo:
#include <stdio.h>
#include <stdlib.h>
Sintaxis:
double atof (const char *s);
La funcin atof() convierte la cadena apuntada por s a un valor de tipo double. La cadena debe contener un
nmero vlido en como flotante. Si no es este el caso, se devuelve el valor 0.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
f = atof (str);
printf (string = %s float = %f\n, str, f);
return 0;
}
Sintaxis:
int atoi (const char *s);
La funcin atoi() convierte la cadena apuntada por s a un valor int. La cadena debe contener un nmero
entero v lido. Si no es este el caso, se devuelve el valor 0.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
n = atoi (str);
printf (string = %s integer = %d\n, str, n);
return 0;
}
Sintaxis:
long atol (const char *s);
La funcin atol() convierte la cadena apuntada por s a un valor long int. La cadena debe contener un
nmero entero de tipo long v lido. Si no es este el caso, se devuelve el valor 0.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
l = atol (str);
printf (string = %s integer = %ld\n, str, l);
return (0);
}
Sintaxis:
void *bsearch (const void *clave, const void *base, unsigned int *num,
unsigned int tam, int (*compara) (const void *arg1, const void *arg2));
unsigned int tam, int (*compara) (void *arg1, void *arg2));
La funcin bsearch() realiza una bsqueda binaria en el array ordenado apuntado por base y devuelve un
puntero al primer elemento que se corresponde con la clave apuntada por clave. El nmero de elementos
en el array est especificado por num y el tamao (en bytes) de cada elemento est descrito por tam.
La funcin apuntada por compara se utiliza para comparar un elemento del array con la clave. La forma de
la funcin de comparacin debe ser:
El array debe estar ordenado en orden ascendente con la menor direccin conteniendo el elemento ms
Pequeo. Si el array no contiene la clave, se devuelve un puntero nulo.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
int array_de_numeros[] = { 123, 145, 512, 627, 800, 933, 333, 1000 };
/* El molde (int (*) (const void *, const void *)) es necesario para
evitar un error de tipo distinto en tiempo de compilacin. Sin
embargo, no es necesario: puntero_a_elemento = (int *) bsearch (...
debido a que en este caso es el compilador el que realiza la
conversin de tipos */
puntero_a_elemento = bsearch (&clave, array_de_numeros,
NUM_ELEMENTOS (array_de_numeros), sizeof (int),
(int (*) (const void *, const void *)) comparacion_de_numeros);
return 0;
}
Sintaxis:
void *calloc (size_t nelems, size_t tam);
Asigna espacio para nelems elementos de tam bytes cada uno y almacena cero en el rea.
Ejemplo:
#include <stdio.h>
#include <alloc.h>
/* visualiza string */
printf (El string es %s\n, str);
/* libera memoria */
free (str);
return 0;
}
Sintaxis:
div_t div (int numer, int denom);
La funcin div() divide dos enteros y devuelve el cociente y el resto como un tipo div_t. Los parametros
numer y denomson el numerador y el denominador respectivamente. El tipo div_t es una estructura de
enteros definida (con typdef) en stdlib.h como sigue:
typedef struct
{
long int quot; /* cociente */
long int rem; /* resto */
} div_t;
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
Sintaxis:
char *ecvt (double valor, int ndig, int *dec, int *sign);
char *fcvt (double valor, int ndig, int *dec, int *sign);
Para ecvt(), ndig es el nmero de dgitos a almacenar, mientras que en fcvt() es el nmero de dgitos a
almacenar depus del punto decimal. El valor devuelto apunta a un rea esttica que es sobreescrita en la
prxima llamada.
Ejemplo:
clrscr ();
valor = 9.876; /* nmero regular */
string = ecvt (valor, ndig, &dec, &sign);
printf (string = %s\tdec = %d\tsign = %d\n, string, dec, sign);
return 0;
}
Sintaxis:
void exit (int estado);
Antes de terminar, la salida buffereada es volcada, los ficheros son cerrados y las funciones exit() son
llamadas.
Ejemplo:
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
Sintaxis:
void _exit (int estado);
Sintaxis:
void free (void *bloque);
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <alloc.h>
/* visualiza string */
printf (El string es %s\n, str);
/* libera memoria */
free (str);
return 0;
}
Sintaxis:
char *gcvt (double valor, int ndec, char *buf);
Sintaxis:
char *getenv (const char *nombre);
La funcin getenv() devuelve un puntero a la informacin de entorno asociada con la cadena apuntada por
nombre en la tabla de informacin de entorno definida por la implementacin. La cadena devuelta no debe
ser cambiada nunca por el programa.
El entorno de un programa puede incluir cosas como nombres de caminos y los dispositivos que estn
conectados. La naturaleza exacta de estos datos viene definida por la implementacin.
Si se hace una llamada a getenv() con un argumento que no se corresponde con ninguno de los datos del
entorno, se devuelve un puntero nulo.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
s = getenv (COMSPEC);
printf (Procesador de comando: %s\n,s);
return 0;
}
Sintaxis:
char *itoa (int valor, char *cad, int radix);
La funcin itoa() convierte el entero valor a su cadena equivalente y sita el resultado en la cadena
apuntada por cad. La base de la cadena de salida se determina por radix, que se encuentra normalmente
en el rango de 2 a 16.
La funcin itoa() devuelve un puntero a cad. Lo mismo se puede hacer con sprintf().
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
Sintaxis:
long int labs (long int x);
Ejemplo:
#include <stdio.h>
#include <math.h>
return 0;
}
Sintaxis:
ldiv_t ldiv (long int numer, long int denom);
La funcin div() divide dos longs y devuelve el cociente y el resto como un tipo ldiv_t. Los parametros numer
y denomson el numerador y el denominador respectivamente. El tipo ldiv_t es una estructura de enteros
definida (con typdef) en stdlib.h como sigue:
typedef struct
{
long int quot; /* cociente */
long int rem; /* resto */
} ldiv_t;
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
Sintaxis:
void *lfind (const void *clave, const void *base,
size_t *num, size_t anchura,
int (*func_de_comp) (const void *elem1, const void *elem2));
void *lsearch (const void *clave, void *base, size_t *num, size_t anchura,
int (*func_de_comp) (const void *elem1, const void *elem2));
Estas funciones utilizan una rutina definida por el usuario (func_de_comp) para la bsqueda de la clave, en
un array de elementos secuenciales.
El array tiene num elementos, cada uno de tamao anchura bytes y comienza en la direccin de memoria
apuntada por base.
Devuelve la direccin de la primera entrada en la tabla que coincida con la clave buscada. Si la clave
buscada no se encuentra, lsearch la aade a la lista; lfind devuelve 0.
La rutina *func_de_comp debe devolver cero si *elem1 == *elem2, y un valor distinto de cero en caso
contrario.
#include <stdio.h>
#include <stdlib.h>
clave = 99;
resultado = lfind (&clave, array, &nelem, sizeof (int),
(int (*) (const void *, const void *)) comparar);
if (resultado)
printf (Nmero %d encontrado\n, clave);
else
printf (Nmero %d no encontrado.\n, clave);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
int numeros[10] = { 3, 5, 1 };
if (aniadir_elemento (clave))
printf (%d est ya en la tabla de nmeros.\n, clave);
else
printf (%d est aadido a la tabla de nmeros.\n, clave);
return 0;
}
(TC)
_lrotl and _lrotr Rota un valor long a la izquierda (_lrotl).
Rota un valor long a la derecha (_lrotr).
Sintaxis:
unsigned long _lrotr (unsigned long val, int cont);
unsigned long _lrotl (unsigned long val, int cont);
Ejemplo:
/* ejemplo lrotl */
#include <stdlib.h>
#include <stdio.h>
return 0;
}
/* ejemplo lrotr */
#include <stdlib.h>
#include <stdio.h>
return 0;
}
Sintaxis:
char *ltoa (long valor, char *cadena, int radix);
Para una representacin decimal, usa radix=10. Para hexadecimal, usa radix=16.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
return 0;
}
El parmetro tam est en bytes. Devuelve un puntero al nuevo bloque asignado, o NULL si no existe
suficiente espacio para el nuevo bloque. Si tam == 0, devuelve NULL.
Ejemplo:
#include <stdio.h>
#include <string.h>
#include <alloc.h>
#include <stdlib.h>
free (str);
return 0;
}
max y min (TC) Macros que generan cdigo en lnea para encontrar el
valor mximo y mnimo de dos enteros.
Sintaxis:
max(a,b) mximo de dos enteros a y b
min(a,b) mnimo de dos enteros a y b
Sintaxis:
int putenv (const char *nombre);
La funcin qsort() ordena el array apuntado por base utilizando el mtodo de ordenacin de C.A.R. Hoare
(este mtodo se ha explicado en el ejemplo 3 de la leccin 5). El nmero de elementos en el array se
especifica mediante num, y el tamao en bytes de cada elemento est descrito por tam.
La funcin compara se utiliza para comparar un elemento del array con la clave. La comparacin debe ser:
/*
el molde del cuarto argumento convierte el tipo
(int (*) (const int *, const int *))
al tipo
(int (*) (const void *, const void *))
que es el que requiere la funcin qsort
*/
qsort (num, 10, sizeof (int),
(int (*) (const void *, const void *)) comparar_decreciente);
Sintaxis:
int rand (void);
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
Sintaxis:
int random (int num);
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
Sintaxis:
void randomize (void);
Inicializa el generador de nmeros aleatorios con un valor aleatorio. Esta funcin usa la funcin time(), as
que debemos incluir time.h cuando usemos esta rutina.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
Sintaxis:
void *realloc (void *bloque, size_t tam);
Intenta achicar o expandir el bloque asignado previamente a tam bytes. Devuelve la direccin del bloque
reasignado, la cual puede ser diferente de la direccin original.
Ejemplo:
#include <stdio.h>
#include <alloc.h>
#include <string.h>
/* libera memoria */
free (str);
}
(TC)
_rotl and _rotr Rota un valor unsigned int a la izquierda (_rotl).
Rota un valor unsigned int a la derecha (_rotr).
Sintaxis:
unsigned _rotl (unsigned val, int cont);
unsigned _rotr (unsigned val, int cont);
Ejemplo:
/* ejemplo de _rotl */
#include <stdlib.h>
#include <stdio.h>
valor = 32767;
resultado = _rotl (valor, 1);
printf (El valor %u rotado un bit a la izquierda es: %u\n,
valor, resultado);
return 0;
}
/* ejemplo de _rotr */
#include <stdlib.h>
#include <stdio.h>
valor = 32767;
resultado = _rotr (valor, 1);
printf (El valor %u rotando un bit a la derecha es: %u\n,
valor, resultado);
return 0;
}
La funcin srand() utiliza semilla para fijar un punto de partida para el flujo generado por rand(), que
devuelve nmeros pseudoaleatorios.
La funcin srand() se utiliza normalmente para permitir que ejecuciones mltiples de un programa utilicen
diferentes flujos de nmeros pseudoaleatorios.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
Sintaxis:
double strtod (const char *inic, char **fin);
La funcin strtod() trabaja de la siguiente forma. Primero, se elimina cualquier carcter en blanco de la
cadena apuntada por inic. A continuacin cada carcter que constituye el nmero es ledo. Cualquier
carcter que no pueda ser parte de un nmero en coma flotante dar lugar a que el proceso se detenga.
Esto incluye el espacio en blanco, signos de puntuacin distintos del punto, y caracteres que no sean E o e.
Finalmente fin se deja apuntando al resto, si lo hay, de la cadena original. Esto supone que si strtod() se
llama con 10.10abc, se devuelve el valor de 10.10 y fin apunta a la 'a' de abc.
Si se produce un error de conversin, strtod() devuelve HUGH_VAL para desbordamiento por arriba
(overflow) o HUGN_VAL para desbordamiento por abajo (underflow). Si no se produce la conversin se
devuelve 0.
#include <stdio.h>
#include <stdlib.h>
Sintaxis:
long strtol (const char *inic, char **final, int radix);
La funcin strtol() trabaja de la siguiente forma. Primero, elimina cualquier espacio en blanco de la cadena
apuntada por inic. A continuacin, se lee cada uno de los caracteres que constituyen el nmero. Cualquier
carcter que no pueda formar parte de un nmero de tipo long int finaliza el proceso. Finalmente, fin se deja
apuntando al resto, si lo hay, de la cadena original. Esto supone que si strtol() se llama con 100abc, se
devuelve el valor 100L y fin apunta al carcter 'a' de la cadena abc.
Si se produce un error de conversin, strtol() devuelve LONG_MAX en caso de desbordamiento por arriba o
LONG_MIN en caso de desbordamiento por abajo. Si no se produce la conversin, se devuelve 0.
sb = espacios en blanco Todos los elementos
sn = signo (+ o -) que estn entre []
ddd = dgitos son opcionales
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
return 0;
}
Sintaxis:
unsigned long strtoul (const char *inic, char **final, int radix);
La funcin strtoul() trabaja de la siguiente forma. Primero, cualquier espacio en blanco en la cadena
apuntada por inic es eliminado. A continuacin, se lee cada carcter que constituye el nmero. Cualquier
carcter que no pueda formar parte de un unsigned long int da lugar a que el proceso se detenga. Esto
incluye espacios en blanco, signos de puntuacin y caracteres. Finalmente, fin se deja apuntando al resto,
si lo hay, de la cadena original. Esto supone que si strtoul() se llama con 100abc, el valor que se devuelve
es 100L y fin apunta a la 'a' de abc.
Si se produce un error de conversin, strtoul() devuelve ULONG_MAX para el desbordamiento por encima o
ULONG_MIN para desbordamiento por abajo. Si la conversin no tiene lugar se devuelve 0.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
return 0;
}
Sintaxis:
void swab (char *fuente, char *destino, int nbytes);
Copia nbytes bytes de fuente a destino intercambiando cada par de bytes adyacentes durante la
transferencia.
fuente[0] = destino[1]
fuente[1] = destino[0]
...
Ejemplo:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Sintaxis:
int system (const char *comando);
comando puede ejecutar un comando interno del DOS tales como DIR, un fichero de programa .COM o
.EXE, o un fichero batch .BAT.
Devuelve 0 en caso de xito, -1 en caso de error y se le asigna a errno uno de los siguientes valores:
ENOENT, ENOMEM, E2BIG o ENOEXEC.
La funcin system() tambinse encuentra declarada en los ficheros process.h y system.h. En el fichero
system.h slo se encuentra el prototipo de la funcin system().
Ejemplo:
#include <stdlib.h>
Sintaxis:
char *ultoa (unsigned long valor, char *cadena, int radix);
#include <stdlib.h>
#include <stdio.h>
return 0;
}
div_t (tipo)
int _doserrno;
Cuando en una llamada al sistema MS-DOS ocurre un error, a _doserrno se le asigna el cdigo de error
DOS actual.
Los mnemotcnicos para los cdigos de error de DOS actual que pueden ser asignados a _doserrno son:
int errno;
Siempre que ocurre un error en una llamada al sistema, a errno se le asigna un cdigo de error que indica
el tipo de error ocurrido.
Constantes que definen condiciones de salida para las llamadas a la funcin exit().
int _fmode;
ldiv_t (type)
NULL (#define)
Direccin del segmento del PSP (Prefijo de Segmento de Programa) del programa.
RAND_MAX (#define)
size_t (tipo)
En Turbo C, definido tambinen los ficheros alloc.h, mem.h, stddef.h, stdio.h y string.h.
char *sys_errlist[]
Esta variable es un array de cadenas de mensajes que corresponden a errno y es usada por la funcin
perror().
Mnemotcnico Significado
int sys_nerr;
is
El estndar ANSI define varias funciones que utilizan la fecha y hora del sistema al igual que el tiempo
transcurrido. Estas funciones requieren la <time.h> en la declaracin de funciones y tambin define
algunos tipos. Los tipos clock_t y time_t permiten representar la hora y fecha del sistema como un entero
extendido. El estndar ANSI se refiere a este tipo de representacin como hora de calendario. El tipo de
estructura tm mantiene la fecha y la hora separada en sus componentes. Adems, time.h define la macro
CLK_TCK que es el nmero de pulsos de reloj del sistema por segundo.
GLOSARIO:
*********
FUNCIONES:
**********
Sintaxis:
char *asctime (const struct tm *punt);
La funcin asctime() devuelve un puntero a una cadena que convierte la informacin almacenada en la
estructura apuntada por punt de la siguiente forma:
El buffer utilizado por asctime() para mantener la cadena de salida con formato se sita est ticamente en un
array de caracteres y se sobreescribe cada vez que se llama a la funcin. Si se desea salvar el contenido
de la cadena, es necesario copiarlo en otro lugar.
Ejemplo:
#include <stdio.h>
#include <string.h>
#include <time.h>
t.tm_sec = 1; /* Segundos */
t.tm_min = 30; /* Minutos */
t.tm_hour = 9; /* Hora */
t.tm_mday = 22; /* Da del mes */
t.tm_mon = 11; /* Mes */
t.tm_year = 56; /* Ao - no incluye centenas */
t.tm_wday = 4; /* Da de la semana */
t.tm_yday = 0; /* No mostrado en asctime */
t.tm_isdst = 0; /* Es horario de verano; no mostrado en asctime */
return 0;
}
Sintaxis:
clock_t clock (void);
Devuelve el tiempo de procesador usado desde el comienzo de la ejecucin del programa medido en
pulsos de reloj. Para transformar este valor en segundos, se divide entre CLK_TCK. Se devuelve el valor -1
si el tiempo no est disponible.
Ejemplo:
#include <time.h>
#include <stdio.h>
#include <dos.h>
return 0;
}
Sintaxis:
char *ctime (const time_t *time);
Ejemplo:
#include <stdio.h>
#include <time.h>
time (&t);
printf (La fecha y hora de hoy es: %s\n, ctime(&t));
return 0;
}
Sintaxis:
double difftime (time_t hora2, time_t hora1);
Ejemplo:
#include <time.h>
#include <stdio.h>
#include <dos.h>
Sintaxis:
struct tm *gmtime (const time_t *hora);
La funcin gmtime() devuelve un puntero a la forma de hora en una estructura tm. La hora est
representada en hora de Greenwich. El valor de hora se obtiene normalmente a travs de una llamada a
time().
La estructura utilizada por gmtime() mantiene la hora separada en una posicin esttica y se sobreescribe
en ella cada vez que se llama a la funcin. Si se desea guardar el contenido de la estructura, es necesario
copiarlo a otro lugar.
Ejemplo:
#include <stdio.h>
#include <time.h>
t = time (NULL);
local = localtime (&t);
printf (Hora y fecha local: %s, asctime (local));
gm = gmtime (&t);
printf (Hora y fecha segn Greenwich: %s, asctime (gm));
return 0;
}
Sintaxis:
struct tm *localtime (const time_t *hora);
La funcin localtime() devuelve un puntero a la forma esperada de hora en la estructura tm. La hora se
representa en la hora local. El valor hora se obtiene normalmente a travs de una llamada a time().
La estructura utilizada por localtime() para mantener la hora separada est situada de forma esttica y se
reescribe cada vez que se llama a la funcin. Si se desea guardar el contenido de la estructura, es
necesario copiarla en otro lugar.
Ejemplo:
#include <time.h>
#include <stdio.h>
return 0;
}
Sintaxis:
time_t mktime (struct tm *t);
La funcin mktime() devuelve la hora de calendario equivalente a la hora separada que se encuentra en la
estructura apuntada por hora. Esta funcin se utiliza principalmente para inicializar el sistema. Los
elementos tm_wday y tm_yday son activados por la funcin, de modo que no necesitan ser definidos en el
momento de la llamada.
Si mktime() no puede representar la informacin como una hora de calendario v lida, se devuelve -1.
Ejemplo:
#include <stdio.h>
#include <time.h>
/* imprime el da de la semana */
printf (Este da es %s\n, dia_semana [chequeo_de_hora.tm_wday]);
return 0;
}
Sintaxis:
int stime (time_t *pt);
Devuelve el valor 0.
Ejemplo:
#include <stdio.h>
#include <time.h>
t = time (NULL);
printf (Nmero de segundos desde 1-1-1970: %ld\n, t);
printf (Hora local: %s, asctime (localtime (&t)));
t++;
printf (Aadido un segundo: %s, asctime (localtime (&t)));
t += 60;
printf (Aadido un minuto : %s, asctime (localtime (&t)));
t += 3600;
printf (Aadido una hora : %s, asctime (localtime (&t)));
t += 86400L;
printf (Aadido un da : %s, asctime (localtime (&t)));
t += 2592000L;
printf (Aadido un mes : %s, asctime (localtime (&t)));
t += 31536000L;
printf (Aadido un ao : %s, asctime (localtime (&t)));
return 0;
}
Sintaxis:
size_t strftime (char *cad, size_t maxtam, const char *fmt,
const struct tm *t);
La funcin strftime() sita la hora y la fecha (junto con otra informacin) en la cadena apuntada por cad. La
informacin se sita de acuerdo a las rdenes de formato que se encuentran en la cadena apuntada por fmt
y en la forma de hora separada t. Se sitan un mximo de maxtam caracteres en cad.
La funcin strftime() trabaja de forma algo parecida a sprintf() en el que se reconoce un conjunto de
rdenes de formato que comienzan con el signo de porcentaje (%) y sita su salida con formato en una
cadena. Las rdenes de formato se utilizan para especificar la forma exacta en que se representan
diferentes informaciones de hora y fecha en cad. Cualquier otro carcter que se encuentre en la cadena de
formato se pone en cad sin modificar. La hora y fecha presentadas estn en hora local. Las rdenes de
formato se presentan en la siguiente tabla. Observa que muchas rdenes distinguen entre maysculas y
minsculas.
La funcin strftime() devuelve el nmero de caracteres situados en la cadena apuntada por cad. Si se
produce un error, la funcin devuelve 0.
Ejemplo:
#include <stdio.h>
#include <time.h>
int main(void)
{
struct tm *hora_act;
time_t segs_act;
char str[80];
time (&segs_act);
hora_act = localtime (&segs_act);
return 0;
}
Sintaxis:
time_t time (time_t *hora);
La funcin time() devuelve la hora actual de calendario del sistema. Si el sistema no tiene hora, devuelve -1.
La funcin time() puede llamarse con un puntero nulo o con un puntero a una variable de tipo time_t. Si se
utiliza este ltimo, el argumento es tambin asignado a la hora de calendario.
Ejemplo:
#include <time.h>
#include <stdio.h>
t = time (NULL);
printf (El nmero de segundos transcurridos desde el 1 de Enero
de 1970 es %ld, t);
return 0;
}
Sintaxis:
void tzset (void);
TZ=...
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
return 0;
}
clock_t (tipo)
Este tipo de datos devuelto por la funcin clock() almacena un tiempo transcurrido medido en pulsos de
reloj.
int daylight;
time_t (tipo)
Este tipo de variable define el valor usado por las funciones de tiempo.
TM (struct)
struct tm
{
int tm_sec; /* segundos, 0-59 */
int tm_min; /* minutos, 0-59 */
int tm_hour; /* horas, 0-23 */
int tm_mday; /* da del mes, 1-31 */
int tm_mon; /* mes, 0-11, Enero = 0 */
int tm_year; /* ao, ao actual menos 1900 */
int tm_wday; /* da de la semana, 0-6, Domingo = 0 */
int tm_yday; /* da del ao, 0-365, 1 de Enero = 0 */
int tm_isdst; /* indicador de horario de verano */
};
Un array de punteros a cadenas conteniendo las abreviaciones para los nombres de zonas horarias.
is
El fichero de <locale.h> declara funciones que proporcionan informacin especfica de los lenguajes y
pases.
beginvis
no_multiatributo
FICHERO DE LOCALE.H
_completas 1 2 80 24
03
Sintaxis:
struct lconv *localeconv (void);
localeconv pone la moneda especfica del pas y otros formatos numricos. Sin embargo, Borland C++
actualmente slo soporta el lugar C.
Sintaxis:
char *setlocale (int categoria, char *lugar);
La funcin setlocale() permite al usuario pedir o activar ciertos parmetros que son sensibles al lugar donde
se utiliza el programa. Por ejemplo, en Europa, la coma se utiliza en lugar del punto decimal; del mismo
modo los formatos de la hora y la fecha difieren.
Si lugar es nulo, setlocale() devuelve un puntero a la actual cadena de localizacin. En cualquier otro caso,
setlocale() intenta utilizar la cadena de localizacin especificada para poner los parmetros de lugar segn
se especifica en categoria.
LC_ALL
LC_COLLATE
LC_CTYPE
LC_MONETARY
LC_NUMERIC
LC_TIME
LC_ALL hace referencia a todas las categoras de localizacin. LC_COLLATE afecta a la operacin de la
funcin strcoll(). LC_CTYPE modifica la forma de trabajo de las funciones de caracteres. LC_NUMERIC
cambia el carcter del punto decimal para las funciones de entrada/salida con formato. Finalmente,
LC_TIME determina el comportamiento de la funcin strftime().
El estndar define dos posibles cadenas para lugar. La primera es C, que especifica el mnimo entorno para
la compilacin de C. El segundo es , la cadena vaca, que especifica el entorno de implementacin definido
por defecto. El resto de los valores para locale() estn definidos por la implementacin y afectan a la
portabilidad.
En Borland C++ (compilador con el que se ha desarrollado este programa), el nico lugar soportado es C.
Ejemplo:
#include <locale.h>
#include <stdio.h>
return 0;
}
LCONV (struct)
struct lconv
{
char *decimal_point;
char *thousands_sep;
char *grouping;
is
partir
El fichero de <sys\timeb.h> de Turbo C declara la funcin ftime() y la estructura timeb para obtener la
hora actual.
beginvis
no_multiatributo
FICHERO DE SYS\TIMEB.H (TC)
_completas 1 2 80 24
03
Sintaxis:
void ftime (struct timeb *buf);
TIMEB (struct)
struct timeb
{
long time ; /* segundos desde 1-1-70 hora Greenwitch */
short millitm ; /* fraccin de segundo (en milisegundos) */
short timezone ; /* diferencia entre hora local y hora Greenwitch */
short dstflag ; /* 0 si no es horario de verano */
};
El fichero de <sys\stat.h> de Turbo C declara dos funciones que obtienen informacin de un fichero
abierto: fstat() y stat(). Adems define la estructura stat que contiene la informacin sobre los ficheros y
tambin define una serie de constantes para identificar el estado de los ficheros.
beginvis
no_multiatributo
FICHERO DE SYS\STAT.H (TC)
_completas 1 2 80 24
03
Sintaxis:
int fstat (int descriptor, struct stat *statbuf);
#include <sys\stat.h>
#include <stdio.h>
#include <time.h>
return 0;
}
Sintaxis:
int stat (char *path, struct stat *statbuf);
Ejemplo:
#include <sys\stat.h>
#include <stdio.h>
#include <time.h>
fclose (stream);
return 0;
}
S_Ixxxx (#defines)
STAT (struct)
struct stat
{
short st_dev, st_ino;
short st_mode, st_nlink;
int st_uid, st_gid;
short st_rdev;
long st_size, st_atime;
long st_mtime, st_ctime;
};
is
El fichero de <values.h> de Turbo C define constantes compatibles con UNIX para valores lmite
de los tipos float y double.
beginvis
no_multiatributo
FICHERO DE VALUES.H (TC)
_completas 1 2 80 24
03
BITSPERBYTE (#define)
Lmites float y double (#defines)
is
En el fichero de <float.h> de Turbo C estn definidas una serie de funciones relacionadas con el
coprocesador matem tico o con el emulador en su defecto, esto es, con las operaciones de coma flotante.
beginvis
no_multiatributo
FICHERO DE FLOAT.H (TC)
_completas 1 2 80 24
03
Sintaxis:
unsigned int _clear87 (void);
Los bits del valor devuelto indican el viejo estado de coma flotante. Para obtener informacin acerca de los
estados, ver las constantes definidas en el fichero de float.h.
Ejemplo:
#include <stdio.h>
#include <float.h>
_clear87 ();
printf (Estado despus de borrar el error: %X\n, _status87 ());
y = x;
return 0;
}
Sintaxis:
void _fpreset (void);
Esta funcin se suele usar junto con las funciones de systema exec y spawn puesto que un proceso hijo
podra alterar el estado de coma flotante del proceso padre.
Ejemplo:
#include <stdio.h>
#include <float.h>
#include <setjmp.h>
#include <signal.h>
#include <process.h>
#include <conio.h>
jmp_buf reentrada;
if (setjmp (reentrada) == 0)
uno /= dos;
Sintaxis:
unsigned int _control87 (unsigned int nuevo, unsigned int mascara);
Si un bit en la mscara es 1, el correspondiente bit en nuevo contiene el nuevo valor para el mismo bit en la
palabra de control. Si mascara es 0, la palabra de control no es alterada.
Sintaxis:
unsigned int _status87 (void);
Ejemplo:
#include <stdio.h>
#include <float.h>
return 0;
}
CW_DEFAULT (#define)
14 1
_completas 1 3 80 23
no_multiatributo
El C es un lenguaje muy potente, pero hay veces que puede interesar escribir algunas intrucciones en
ensamblador. Hay tres razones para ello:
Aqu no nos vamos a extender mucho en este tema, slo nos vamos a limitar a comentar cmo se pueden
incluir instrucciones ensamblador en un programa de C en el caso de Turbo C.
#pragma inline
Ejemplo:
Si se quiere incluir varias instrucciones en ensamblador, se crea un bloque (con dos llaves) despus de
asm.
Ejemplo:
asm
{
pop ax; pop ds
iret
}
Ejemplo:
/*
Este ejemplo instala una rutina manejadora para la seal SIGFPE,
atrapa una condicin de desbordamiento de entero, hace un reajuste
del registro AX y vuelve.
*/
#pragma inline
#include <stdio.h>
#include <signal.h>
/*
Este ejemplo instala una rutina manejadora para la seal SIGFPE,
atrapa una condicin de desbordamiento de entero, hace un reajuste
del registro AX y vuelve.
*/
#include <stdio.h>
#include <signal.h>
_AX--;
geninterrupt (4);
_AX--;
geninterrupt (4);
}