Vous êtes sur la page 1sur 280

Contenido

1. Introduccin 1
Breve historia 1
Ejemplo 1: #include, main(), printf() 2
Ejemplo 2: scanf() 4
Ejemplo 3: Funciones con argumentos 6
Ejemplo 4: Funciones que devuelven valores 8
Ejercicios
2. Elementos de un programa C 11
!ntroducci"n 11
#onstantes 11
!denti$icadores 14
%ala&ras 'eservadas 14
#omentarios 1(
)peradores, e*presiones, sentencias 1(
E$ecto lateral 2(
+as directivas #include , #define 26
Ejercicios 28
3. Tipos bsicos de datos 31
-ipos &.sicos de datos 31
#"mo declarar varia&les 32
/odi$icadores del tipo de una varia&le 33
0aria&les locales , varia&les glo&ales 34
#lases de almacenamiento 36
!niciali1aci"n de varia&les 3
Ejercicios 42
. E!" bsica 1
-ipos de E34 41
E34 de caracteres 41
E34 de cadenas de caracteres 43
E34 $ormateada 44
i
+a $unci"n fprintf () (1
#ontrol de la pantalla de te*to (1
Ejercicios 62
#. "entencias de control $2
+a estructura if 62
+a estructura s%itc& 63
Bucles 66
4entencia brea' 53
4entencia continue 53
Etiquetas , sentencia goto 54
Funci"n e(it() 5(
Ejercicios 55
$. )unciones *1
!ntroducci"n 81
6rgumentos de $unciones 82
0alores de retorno de una $unci"n 84
%rototipos de $unciones 8(
'ecursividad 85
+a &i&lioteca de $unciones 8
Ejercicios 1
+. ,atrices - punteros .#
78u9 es una matri1: (
78u9 son los punteros: (
/atrices unidimensionales
#adenas de caracteres 121
%unteros , matrices 126
/atrices &idimensionales 125
/atrices de m.s de 2 dimensiones 12
#"mo iniciali1ar matrices 112
/atrices como argumentos de $unciones 111
6rgumentos de la $unci"n main() 113
/atrices de punteros 11(
%unteros a punteros 11(
%unteros a $unciones 116
Ejercicios 118
*. /tros tipos de datos 123
!ntroducci"n 123
-ipos de$inidos por el usuario 123
ii
Estructuras 124
;niones 132
Enumeraciones 135
Ejercicios 13
.. 0signacin dinmica de memoria 11
6lmacenamiento est.tico , din.mico 141
+as $unciones malloc() , free() 142
/atrices asignadas din.micamente 144
#olas din.micas 146
Ejercicios 14
11. )ic&eros 1#1
#anales , $icheros 1(1
6&rir , cerrar $icheros 1(2
#ontrol de errores , $in de $ichero 1(4
E34 de caracteres 1((
E34 de cadenas de caracteres 1(5
E34 de &loques de datos 1(8
E34 con $ormato 162
6cceso directo 162
Ejercicios 16(
11. )ic&eros inde(ados2 la interfase 3trie4e 1$.
!ntroducci"n 16
<escripci"n de Btrieve 16
=esti"n de $icheros Btrieve 152
El =estor de <atos Btrieve 152
El utilitario B;-!+ 153
!nter$ase de Btrieve con -ur&o # 155
)peraciones Btrieve 158
Ejemplos 182
#"digos de error Btrieve 188
Ejercicios 18
12. Compilacin - enla5ado 1.3
!ntroducci"n 13
/odelos de memoria 13
El compilador -## 1(
El enla1ador -+!>? 15
El &i&liotecario -+!B 1
iii
+a utilidad /6?E 222
;n ejemplo sencillo 221
13. 6a biblioteca de funciones de Turbo C 21+
!ntroducci"n 225
Funciones de E34 225
Funciones de cadenas de caracteres 212
Funciones de memoria 212
Funciones de caracteres 214
Funciones matem.ticas 216
Funciones de sistema 215
Funciones de asignaci"n din.mica de memoria 22(
Funciones de directorio 226
Funciones de control de procesos 22
Funciones de pantalla de te*to 232
)tras $unciones 234
1. "oluciones a los e7ercicios 23.
#ap@tulo 1: !ntroducci"n 23
#ap@tulo 2: Elementos de un programa # 242
#ap@tulo 3: -ipos &.sicos de datos 244
#ap@tulo 4: E34 &.sica 244
#ap@tulo (: 4entencias de control 248
#ap@tulo 6: Funciones 2(3
#ap@tulo 5: /atrices , punteros 262
#ap@tulo 8: )tros tipos de datos 25(
#ap@tulo : 6signaci"n din.mica de memoria 258
#ap@tulo 12: Ficheros 282
#ap@tulo 11: Ficheros inde*ados: la inter$ase Btrieve 28(
1
Introduccin
iv
3re4e &istoria
El +enguaje # $ue creado en 152 por <ennis 'itchie en un %<%A11 de
<igital Equipment #orporation &ajo el sistema operativo ;>!BC Fue el resultado
$inal de un pro,ecto que comen1" con un lenguaje llamado B#%+ DBasic
#om&ined %rogramming +anguageE diseFado por /artin 'ichards en 165, que a
su ve1 esta&a in$luenciado por el lenguaje #%+ D#om&ined %rogramming
+anguageE desarrollado por las universidades de #am&ridge , +ondresC 6 partir
del B#%+, ?en -hompson cre" un lenguaje llamado B, que $ue el que condujo al
desarrollo del +enguaje #C
<urante muchos aFos el est.ndar para # $ue el que se suministra&a con la
versi"n ( de ;>!BC %ero con la creciente popularidad de los microordenadores
aparecieron muchas implementaciones di$erentes D8uicG # de /icroso$t, -ur&o #
de Borland, etcCE que, aunque eran altamente compati&les entre s@, ten@an algunas
di$erenciasC %or ello, en 183 se cre" un comit9 que ela&or" el documento que
de$ine el est.ndar 6>4! de #C
El +enguaje # es un lenguaje de nivel medio, es decir, sin ser un lenguaje de
alto nivel como #)B)+, B64!# o %ascal, tampoco es un +enguaje Ensam&ladorC
+as principales caracter@sticas del +enguaje # son:
-iene un conjunto completo de instrucciones de controlC
%ermite la agrupaci"n de instruccionesC
!nclu,e el concepto de puntero Dvaria&le que contiene la direcci"n de otra
varia&leEC
+os argumentos de las $unciones se trans$ieren por su valorC %or ello,
cualquier cam&io en el valor de un par.metro dentro de una $unci"n no
a$ecta al valor de la varia&le $uera de ellaC
+a E34 no $orma parte del lenguaje, sino que se proporciona a trav9s de
una &i&lioteca de $uncionesC
%ermite la separaci"n de un programa en m"dulos que admiten
compilaci"n independienteC
)riginalmente el +enguaje # estuvo mu, ligado al sistema operativo ;>!B
que, en su ma,or parte, est. escrito en #C /.s adelante se comen1" a utili1ar en
otros sistemas operativos para programar editores, compiladores, etcC 6unque se le
conoce como un lenguaje de programaci"n de sistemas, no se adapta mal al resto
de aplicacionesC <e hecho, ho, en d@a un alto porcentaje de so$tHare para
ordenadores personales est. escrito en +enguaje #C %or ejemplo, el sistema
operativo /4A<)4C
En este cap@tulo reali1aremos un r.pido recorrido por algunas de las
caracter@sticas del lenguaje a trav9s de unos ejemplos mu, sencillosC En los
siguientes cap@tulos estudiaremos con mucho m.s detalle la ma,or parte de los
aspectos del +enguaje #C Este estudio lo &asaremos en la implementaci"n de
v
Borland: el -ur&o #C Estos programas pueden ejecutarse desde el entorno
integrado de -ur&o # o compil.ndolos , enla1.ndolos desde la l@nea de "rdenes del
<)4 D#ap@tulo 12EC
E7emplo 12 #include8 main()8 printf()
#omen1aremos por un ejemplo sencillo: un programa que muestra en
pantalla una $raseC
/* EjempIo 1. Programa DOCENA.C */
#incIude <stdio.h>
main ()
{
int docena;
docena = 12;
printf ("Una docena son %d unidades\n", docena);
}
Este programa hace aparecer en pantalla la $rase I;na docena son 12
unidadesIC 0eamos el signi$icado de cada una de las l@neas del programaC
!9 E7emplo 1. :rograma ;/CE<0.C 9!
Es un comentarioC El compilador de -ur&o # ignora todo lo que est. entre
los s@m&olos de comien1o D!9E , $in D9!E de un comentarioC +os comentarios
delimitados por estos s@m&olos pueden ocupar varias l@neasC
#include =stdio.&>
+e dice a -ur&o # que en el proceso de compilaci"n inclu,a un archivo
denominado stdio.&C Este $ichero se suministra como parte del compilador de
-ur&o # , contiene la in$ormaci"n necesaria para el correcto $uncionamiento de la
E34 de datosC
+a sentencia #include no es una instrucci"n #C El s@m&olo J la identi$ica
como una directiva, es decir, una orden para el preprocesador de #, responsa&le de
reali1ar ciertas tareas previas a la compilaci"nC
vi
+os archivo 9.& se denominan arc&i4os de cabeceraC -odos los programas
# requieren la inclusi"n de uno o varios archivos de este tipo, por lo que
normalmente es necesario utili1ar varias l@neas #includeC
main ()
Es el nom&re de una $unci"nC ;n programa # se compone de una o m.s
$unciones, pero al menos una de ellas de&e llamarse main(), pues los programas #
empie1an a ejecutarse por esta $unci"nC
+os par9ntesis identi$ican a main() como una $unci"nC =eneralmente, dentro
de ellos se inclu,e in$ormaci"n que se env@a a la $unci"nC En este caso no ha,
traspaso de in$ormaci"n por lo que no ha, nadaescrito en su interiorC 6Kn as@ son
o&ligatoriosC
El cuerpo de una funcin Dconjunto de sentencias que la componenE va
enmarcado entre llaves ? , @C Ese es el signi$icado de las llaves que aparecen en el
ejemploC
int docenaA
Es una sentencia declarativaC !ndica que se va a utili1ar una varia&le llamada
docena que es de tipo enteroC +a pala&ra int es una pala&ra clave de # que
identi$ica uno de los tipos &.sicos de datos que estudiaremos en el #ap@tulo 3C En
# es o&ligatorio declarar todas las varia&les antes de ser utili1adasC El IAI identi$ica
la l@nea como una sentencia #C
docena B 12A
Es una sentencia de asignaci"nC 6lmacena el valor 12 a la varia&le docenaC
)&s9rvese que aca&a con punto , comaC #omo en la ma,or@a de los lenguajes, el
operador de asignaci"n en # es el signo igual IBIC
printf (CDna docena son Ed unidadesFnC8 docena)A
Esta sentencia es importante por dos ra1ones: en primer lugar, es un ejemplo
de llamada a una $unci"nC 6dem.s ilustra el uso de una $unci"n est.ndar de salida:
la $unci"n printf()C
+a sentencia consta de dos partes:
El nom&re de la $unci"n: printf()C
+os argumentosC En este caso ha, dos separados por una coma:
A CDna docena son Ed unidadesFnC
A docena
#omo toda sentencia # aca&a con punto , comaC
vii
+a $unci"n printf() $unciona de la siguiente $orma: el primer argumento es
una cadena de formatoC Esta cadena ser. lo que, &.sicamente, se mostrar. en
pantallaC En la cadena de $ormato pueden aparecer cdigos de formato ,
caracteres de escapeC
;n cdigo de formato comien1a por el s@m&olo E e indica la posici"n
dentro de la cadena en donde se imprimir. el segundo argumento, en este caso, la
varia&le docenaC /.s adelante estudiaremos todos los c"digos de $ormato de
-ur&o #C En este ejemplo, Ed indica que en su lugar se visuali1ar. un nKmero
entero decimalC
;n carcter de escape comien1a por el s@m&olo FC 4on caracteres que tienen
una interpretaci"n especialC +a secuencia Fn es el car.cter nue4a lGnea , equivale a
la secuencia +FL#' Dsalto de l@nea L retorno de cursorEC
+a $unci"n printf() pertenece a la &i&lioteca est.ndar de #C +as de$iniciones
necesarias para que $uncione correctamente se encuentran en el archivo stdio.&, de
ah@ que sea necesaria la sentencia #include =stdio.&>C
E7emplo 22 scanf()
El siguiente programa reali1a la conversi"n de pies a metros usando la
equivalencia:
1 pie M 2C3284 metros
El programa solicita por teclado el nKmero de pies , visuali1a en pantalla los
metros correspondientesC
/* EjempIo 2. Programa PIES.C */
#incIude <stdio.h>
main ()
{
int pies;
fIoat metros;
printf ("\nPies?: ");
scanf ("%d", &pies);
metros = pies * 0.3084;
printf ("\n%d pies equivaIen a %f metros\n", pies, metros);
}
viii
Estudiaremos ahora las novedades que aparecen en este programaC
float metrosA
Es una sentencia declarativa que indica que se va a utili1ar una varia&le
llamada metros, que es del tipo floatC Este tipo de dato se utili1a para declarar
varia&les num9ricas que pueden tener decimalesC
printf (CFnH:iesI2 C)A
Es la $unci"n printf() comentada antesC En esta ocasi"n s"lo tiene un
argumento: la cadena de control sin c"digos de $ormatoC Esta sentencia
simplemente sitKa el cursor al principio de la siguiente l@nea DFnE , visuali1a la
cadena tal como aparece en el argumentoC
scanf (CEdC8 Jpies)A
scanf() es una $unci"n de la &i&lioteca est.ndar de # Dcomo printf()E, que
permite leer datos del teclado , almacenarlos en una varia&leC En el ejemplo, el
primer argumento, Ed, le dice a scanf() que tome del teclado un nKmero enteroC
El segundo argumento, Jpies, indica en qu9 varia&le se almacenar. el dato le@doC
El s@m&olo J antes del nom&re de la varia&le es necesario para que scanf()
$uncione correctamenteC 6clararemos este detalle en cap@tulos posterioresC
metros B pies 9 1.31*A
4e almacena en la varia&le metros el resultado de multiplicar la varia&le pies
por 1.31*C El s@m&olo 9 es el operador que usa # para la multiplicaci"nC
printf (CFnEd pies eKui4alen a Ef metrosFnC8 pies8 metros)A
6qu@ printf() tiene 3 argumentosC El primero es la cadena de control, con
dos c"digos de $ormato: Ed , EfC Esto implica que printf() necesita dos
argumentos adicionalesC Estos argumentos encajan en orden, de i1quierda a
derecha, con los c"digos de $ormatoC 4e usa Ed para la varia&le pies , Ef para la
varia&le metrosC
print$ DINnEd pies equivalen a Ef metrosNnI, pies, metrosEO
i*
El c"digo Ef se usa para representar varia&les del tipo floatC
E7emplo 32 )unciones con argumentos
0eremos ahora dos ejemplos de programas que utili1an $unciones creadas
por el programadorC ;na $unci"n es una su&rutina que contiene una o m.s
sentencias #C 0iene de$inida por un nom&re, seguida de dos par9ntesis () entre los
que puede ha&er o no argumentosC +os argumentos son valores que se le pasan a la
$unci"n cuando se llamaC
0eamos, en primer lugar, un ejemplo de una $unci"n sin argumentosC
/* EjempIo 3.1 - Programa FUNCION1.C */
#incIude <stdio.h>
main ()
{
printf ("\nEste mensaje Io muestra Ia funcin main()");
MiFuncion ();
}
/* Definicin de Ia funcin MiFuncion() */
MiFuncion ()
{
printf ("\nEste otro Io muestra MiFuncion()");
}
En este ejemplo se utili1a la $unci"n ,i)uncion() para mostrar en pantalla
una $raseC #omo se ve, ,i)uncion() se invoca igual que printf() o scanf(), es
decir, simplemente se escri&e el nom&re de la $unci"n , los par9ntesisC +a
de$inici"n de ,i)uncion() tiene el mismo aspecto que main(): el nom&re de la
$unci"n con los par9ntesis ,, seguidamente, el cuerpo de la $unci"n encerrado entre
llavesC
El siguiente ejemplo ilustra el uso de una $unci"n con argumentosC El
programa visuali1a el cuadrado de un nKmero entero por medio de una $unci"n que
reci&e dicho nKmero como argumentoC
/* EjempIo 3.2 - Programa FUNCION2.C */
#incIude <stdio.h>
main ()
*
{
int num;
printf ("\nTecIee un nmero entero: ");
scanf ("%d", &num);
cuadrado (num);
}
/* Definicin de Ia funcin cuadrado() */
cuadrado (int x)
{
printf ("\nEI cuadrado de %d es %d\n", x, x * x);
}
cuadrado (int ()
Es la declaraci"n de la $unci"n cuadrado()C <entro de los par9ntesis se pone
la varia&le que reci&ir. el valor pasado a cuadrado() , de qu9 tipo esC 6s@, si se
teclea el valor $, se almacena en num , al hacer la llamada cuadrado (num)8 la
varia&le num se copia en la varia&le (, que es con la que tra&aja internamente la
$unci"n cuadrado()C
Es importante mantener claros dos t9rminos:
1C El t9rmino 0LMD,E<T/ se re$iere a la varia&le usada al llamar la
$unci"nC
2C El t9rmino :0LN,ETL/ )/L,06 se re$iere a la varia&le de una
$unci"n que reci&e el valor de los argumentosC
-am&i9n es importante tener claro que la copia de varia&les se hace s"lo en
una direcci"n: del argumento al par.metro $ormalC #ualquier modi$icaci"n del
par.metro $ormal reali1ado dentro de la $unci"n no tiene ninguna in$luencia en el
argumentoC
... ARGUMENTO
...
cuadrado (num)
...
...
Al hacer la llamada a la funcin cuadrado() el
ARGUMENTO num se copia en el PARMETRO
FORMAL x.
Cuadrado (int x)
{ PARMETRO
printf (... ); FORMAL
}
*i
)tro detalle a tener en cuenta es que el tipo de argumento que se utili1a para
llamar a una $unci"n de&e ser el mismo que el del par.metro $ormal que reci&e el
valorC 6s@, no de&e llamarse a la $unci"n cuadrado con un argumento de tipo float
Dm.s adelante veremos que # permite cierta $le*i&ilidad en este aspectoEC
E7emplo 2 )unciones Kue de4uel4en 4alores
%ara $inali1ar el cap@tulo veremos un ejemplo que utili1a una $unci"n que
devuelve un valorC El siguiente programa lee dos nKmeros enteros del teclado ,
muestra su producto en pantallaC %ara el c.lculo se usa una $unci"n que reci&e los
dos nKmeros , devuelve el producto de am&osC
/* EjempIo 4 - Programa MULT.C */
#incIude <stdio.h>
main ()
{
int a, b, producto;
printf ("\nTecIee dos nmeros enteros: ");
scanf ("%d %d", &a, &b);
producto = muItipIica (a, b);
printf ("\nEI resuItado es %d", producto);
}
/* Definicin de Ia funcin muItipIica() */
muItipIica (int x, int y)
{
return (x * y);
}
+as novedades que se presentan en este programa se comentan a continuaci"nC
scanf (CEd EdC8 Ja8 Jb)A
+a cadena de control de scanf() contiene dos c"digos de $ormatoC 6l igual
que ocurre en printf(), se precisan dos argumentos m.s, uno por cada c"digo de
$ormatoC +os dos nKmeros se teclean separados por espacios en &lanco,
ta&uladores o por la tecla !ntroC
return (( 9 -)A
*ii
+a pala&ra clave return se usa dentro de las $unciones para salir de ellas
devolviendo un valorC El valor devuelto mediante return es el que asume la
$unci"nC Eso permite tener sentencias como
producto B multiplica (a8 b)A
es decir, sentencias en las que la $unci"n est. a la derecha del operador de
asignaci"nC %ara nuestros prop"sitos actuales podemos decir Daunque esto no sea
e*actoE que despu9s de la sentencia return la $unci"n multiplica() actKa como si
$uese una varia&le que almacena el valor devueltoC
+os par9ntesis son opcionales, se inclu,en Knicamente para clari$icar la
e*presi"n que acompaFa a returnC >o de&en con$undirse con los par9ntesis de las
$uncionesC
E7ercicios
1. Encuentra todos los errores del siguiente programa #:
incIude studio.h
/* Programa que dice cuntos das hay en una semana /*
main {}
(
int d
d := 7;
print (Hay d das en una semana);
2. !ndica cu.l ser@a la salida de cada uno de los siguientes grupos de sentencias:
aE printf (COistorias de cronopios - famas.C)A
printf (C0utor2 Pulio Cort5arC)A
&E printf (CHCuntas lGneas Fnocupa estoIC)A
cE printf (CEstamos Fnaprendiendo !naprogramar en CC)A
dE int numA
num B 2A
printf (CEd Q Ed B EdC8 num8 num8 num Q num)A
*iii
3. Escri&e un programa que calcule el .rea de un c@rculo de radio ' , la
longitud de su circun$erenciaC 4olicitar el valor de ' por teclado, mostrando
en la pantalla los mensajes necesarios D4 M '
2
O + M 2 'EC
. 4ean dos cuadrados de lados +1 , +2 inscritos uno en otroC #alcula el .rea
de la 1ona comprendida entre am&os, utili1ando para ello una $unci"n Dque se
llamar. 0reaCuadradoE que devuelve el .rea de un cuadrado cu,o lado se
pasa como argumentoC
2
Elementos de un
programa C
Introduccin
B.sicamente el # est. compuesto por los siguientes elementos
#onstantes
!denti$icadores
%ala&ras reservadas
#omentarios
)peradores
%ara representar estos elementos se utili1an los caracteres ha&ituales Dletras,
nKmeros, signos de puntuaci"n, su&ra,ados, CCCE aunque no todos los elementos
pueden usar todos estos caracteresC
;na caracter@stica importante del +enguaje # es que en todos los elementos
anteriormente enumerados distingue letras ma,Ksculas , minKsculasC 6s@, int es una
pala&ra reservada del lenguaje que sirve para declarar varia&les enteras, mientras que
Int podr@a ser el nom&re de una varia&leC
Constantes
*iv
+as constantes que se pueden usar en # se clasi$ican de la siguiente $orma:
Enteras
'eales
<e car.cter
Constantes enteras
4on nKmeros sin parte $raccionariaC %ueden e*presarse en decimal, octal o
he*adecimalC
;na constante octal de&e comen1ar con un cero:
216 16 octal M 14 decimal
;na constante he*adecimal de&e comen1ar con un cero seguida de ( " RC
2*63 63 he* M 163 decimal
Esta constante se puede escri&ir tam&i9n de cualquiera de las 3 $ormas siguientes:
2B63 2*a3 2*63
+as constantes enteras se consideran positivas a menos que va,an precedidas
por el signo menos DSE:
A1(2 A263 A2*6
Constantes Leales
-am&i9n se denominan constantes de coma flotanteC -ienen el siguiente
$ormato:
Tparte enteraU T.parte fraccionariaU Te(ponente de 11U
#ualquiera de las 3 partes es opcional, pero si no ha, parte entera de&e ha&er parte
$raccionaria , viceversaC El e*ponente de 12 tiene el $ormato
?EVe@e(ponente
pudiendo ser el e*ponente un nKmero positivo o negativoC 4on constantes v.lidas:
13C21 21C35E1 2C232221 32e2 A81eA8 AC3 AC3EA5
Constantes de caracteres
*v
%ueden ser de 2 tipos:
4imples
#adenas de caracteres
"imples2 Est.n $ormadas por un solo car.cter , se encierran entre comillas
simplesC %or ejemplo:
PaP P6P PP
+os caracteres 64#!! no imprimi&les se de$inen mediante la &arra invertida DNE
segKn el cuadro que se muestra a continuaci"nC En 9l tam&i9n se muestra la
representaci"n de los caracteres &arra invertida, comilla simple , comillas do&les, que
en # tienen un tratamiento especialC
CDIGO ASCII CARCTER BARRA SIGNIFICADO
7 \a Alarma (Beep)
8 \b Retroceso (BS)
9 \t Tabulador Horizontal (HT)
10 \n ue!a "#nea ("$)
11 \! Tabulador %ertical (%T)
1& \' ue!a ()*ina ($$)
1+ \r Retorno
+, \- .omillas dobles
+9 \/ .omilla simple
9& \\ Barra in!ertida
-am&i9n se pueden representar caracteres 64#!! mediante su c"digo octal o
he*adecimal, usando el $ormato:
Fnumoctal o &ien F(numhe*adecimal
que representan, respectivamente, el car.cter cu,o c"digo 64#!! es numoctal o
num&e(adecimalC 6s@, la letra 6 puede representarse de cualquiera de las tres
$ormas que se indican a continuaci"n:
P6P PN121P PN*41P
>o es v.lido PNB41PC #ualquier otro car.cter despu9s de N se interpreta literalmenteC
6s@ N> se interpreta como la letra >C
*vi
Cadenas2 4on secuencias de caracteres simples encerradas entre comillas
do&lesC 6 las cadenas de caracteres el compilador les aFade un car.cter nulo DPN2PE de
terminaci"n, , los almacena como una matri1 de caracteresC 6s@, la cadena IQolaI
est. compuesta por los ( caracteres PQP, PoP, PlP, PaP,PN2PC
Identificadores
4on los nom&res dados a varia&les, $unciones, etiquetas u otros o&jetos
de$inidos por el programadorC ;n identi$icador puede estar $ormado por:
+etras Dma,Ksculas o minKsculasE
>Kmeros
#ar.cter de su&ra,ado
con la condici"n de que el primer car.cter no sea un nKmeroC En determinados casos,
que se estudiar.n en el #ap@tulo , un identi$icador de un dato puede incluir el puntoC
Ejemplos de identi$icadores v.lidos son:
Precio_Venta
Num1
_123
D_i_5
>o son v.lidos:
Precio Venta +leva un espacio en &lanco
1Num Empie1a por un nKmero
Precio-Venta +leva un gui"n
<e un identi$icador s"lo son signi$icativos los 32 primeros caracteresC
:alabras reser4adas
4on pala&ras especiales que no pueden usarse para nom&rar otros elementos
del lenguajeC En el cap@tulo anterior vimos algunas de ellas, como int , floatC El
nKmero de pala&ras reservadas en # es signi$icativamente menor que el de otros
lenguajesC En -ur&o # ha, 43, algunas m.s en -ur&o #LL , menos en 6>4! #C
<urante el resto de cap@tulos se ir.n conociendoC
Es preciso insistir en que # hace distinci"n entre ma,Ksculas , minKsculasC %or
lo tanto, la pala&ra reservada for no puede escri&irse como )/L, pues el compilador
no la reconoce como una instrucci"n, sino que la interpreta como un nom&re de
varia&leC
*vii
Comentarios
#omo se vio en el cap@tulo anterior, el compilador reconoce como comentario
cualquier grupo de caracteres situados entre 3R , R3, aunque est9n en di$erentes l@neasC
%or ejemplo,
/* Este es un comentario que
ocupa ms de una Inea */
Estos comentarios pueden anidarse en -ur&o #LL, aunque no es aconseja&le
para permitir la compati&ilidad del c"digoC
4e pueden de$inir comentarios de una sola l@nea mediante 33C
// Este comentario ocupa una soIa Inea
En el caso de comentarios de una sola l@nea no ha, indicador de $in de
comentarioC
/peradores8 e(presiones8 sentencias
;n operador es un s@m&olo que indica alguna operaci"n so&re uno o varios
o&jetos del lenguaje, a los que se denomina operandosC
6tendiendo al nKmero de operandos so&re los que actKa un operador, estos se
clasi$ican en:
;narios: actKan so&re un solo operando
Binarios: I I 2 operandos
-ernarios: I I 3 I
6tendiendo al tipo de operaci"n que reali1an, se clasi$ican en :
6ritm9ticos
'elacionales
+"gicos
<e tratamiento de &its
Especiales
Estudiaremos en este cap@tulo la ma,or parte de ellosC !remos viendo el resto a
medida que se necesitenC
*viii
+os operadores, junto con los operandos, $orman e(presionesC En una
e*presi"n, los operandos pueden ser constantes, varia&les o llamadas a $unciones que
devuelvan valores Dcomo la $unci"n multiplica () que aparece en la p.gina 8EC
;na e*presi"n se convierte en una sentencia cuando va seguida de un punto ,
comaC #uando un grupo de sentencias se encierran entre llaves S T, $orman un
bloKue, sint.cticamente equivalente a una sentenciaC
/peradores aritmWticos
+os operadores aritm9ticos se e*ponen en el cuadro siguiente:
OPERADOR DESCRIPCIN
UNARIOS 0 .ambio de si*no
0 0 1ecremento
22 3ncremento
BINARIOS 0 Resta
2 Suma
4 (roducto
5 1i!isi6n
7 Resto de di!isi6n
entera
+os operadores A, L , R $uncionan del mismo modo que en el resto de los
lenguajes de programaci"nC
El valor devuelto por el operador 3 depende del tipo de los operandosC 4i estos
son enteros, devuelve la parte entera del cocienteO si alguno de ellos es real, devuelve
el resultado como nKmero realC El operador U es equivalente al operador mod de
%ascal o 8uicGAB64!#C %roporciona el resto de la divisi"n entera de los operandos,
que han de ser enterosC %or ejemplo, dadas las sentencias
int x, y;
x = 9;
y = 2;
la operaci"n ( ! - devuelve el valor , mientras que la operaci"n ( E - devuelve 1C
4in em&argo, despu9s de las sentencias
fIoat x;
int y;
x = 9.0;
y = 2;
*i*
la operaci"n ( ! - devuelve .#, no pudi9ndose aplicar, en este caso, el operador E
puesto que uno de los operandos no es enteroC
+os operadores LL , AA aumentan o disminu,en, respectivamente, en una
unidad el operando so&re el que actKanC 6s@, las e*presiones
x++; x- -;
producen el mismo e$ecto so&re la varia&le ( que
x = x + 1; x = x - 1;
, el mismo que
++x; --x;
Es importante tener en cuenta la posici"n de los operadores LL , AA cuando se
encuentran dentro de una e*presi"n m.s complejaC 4i el operador est. antes de la
varia&le, la operaci"n de incremento o decremento se reali1a antes de usar el valor de
la varia&leC 4i el operador est. despu9s, primero se usa el valor de la varia&le ,
despu9s se reali1a la operaci"n de incremento o decrementoC %ara aclarar esto,
tomemos un ejemploC <espu9s de las sentencias
x = 10;
y = ++x;
los valores que se almacenan en las varia&les ( e - son, en am&os casos, 11C %uesto
que el operador est. antes de la varia&le (, primero se incrementa 9sta Dasumiendo el
valor 11E, , despu9s se asigna el valor de ( a la varia&le -C 4in em&argo, despu9s de
las sentencias
x = 10;
y = x++;
los valores para ( e - ser.n, respectivamente, 11 , 12C En este caso, puesto que el
operador est. despu9s de la varia&le (, primero se usa el valor de 9sta D12E , se asigna
a -O despu9s se reali1a la operaci"n de incremento, pasando ( a almacenar el valor 11C
/peradores relacionales
4e usan para e*presar condiciones , descri&ir una relaci"n entre dos valoresC
En la p.gina siguiente se muestra una ta&la con todos ellosC
Estos operadores se usan en sentencias del tipo
if (a == b) printf ("Son iguaIes");
que de&e leerse Isi el contenido de la varia&le a es igual al de la varia&le b muestra en
pantalla la $rase Son igualesIC
El resultado de una e*presi"n relacional s"lo puede ser verdadero o falso, lo
que en # se identi$ica con los valores distinto de cero , cero, respectivamenteC En la
**
sentencia anterior, la e*presi"n a BB b se evaluar. como 2 si a , b son di$erentes, ,
como distinto de 2 si son igualesC
OPERADOR DESCRIPCIN
BINARIOS 8 9a:or ;ue
8< 9a:or o i*ual ;ue
= 9enor ;ue
=< 9enor o i*ual ;ue
<< 3*ual ;ue
>< 1i'erente ;ue
/peradores lgicos
6ctKan so&re e*presiones &ooleanas, es decir, so&re valores verdadero o falso
generados por e*presiones como las e*plicadas en el caso anteriorC 4on los
siguientes:
OPERADOR DESCRIPCIN
UNARIOS ! no
BINARIOS !! and
"" or
El resultado de una operaci"n l"gica viene dado por su ta&la de verdadC +a
ta&la de verdad de los operadores X, JJ , VV se muestra a continuaci"n:
a b !a a && b a || b
$ $ % $ $
$ % % $ %
% $ $ $ %
% % $ % %
<ado que el lenguaje interpreta como $also el valor 2 , como cierto cualquier
valor di$erente de cero, se pueden emplear operadores aritm9ticos en las e*presiones
l"gicas , de comparaci"nC %or ejemplo, si (, - , 5 almacenan, respectivamente, los
valores 22, 4 , (, las e*presiones siguientes son v.lidas:
x == y Se interpreta como FALSO (0)
**i
x = y Se interpreta como VERDADERO (4)
1
x == (y * z) Se interpreta como VERDADERO (1)
/peradores de tratamiento de bits
# incorpora ciertas operaciones so&re &its propias del +enguaje Ensam&lador,
como despla1amientos o manipulaci"n individual de &itsC +os operadores que reali1an
estas operaciones son los siguientes:
OPERADOR DESCRIPCIN
UNARIOS # no
BINARIOS ! and
" or
$ or e%clusi&o
'' despla(amieno a la derecha
)) despla(amieno a la i(*uierda
+os operadores J DandE, V DorE , Y DnotE se rigen por la misma ta&la de verdad
que go&ierna a los operadores l"gicos equivalentes DJJ, VV, XEC +a di$erencia entre
unos , otros consiste en que J, V , Y actKan a nivel de &its individuales , no so&re
valores completos como JJ, VV , XC 6s@, si las varia&les a , b almacenan,
respectivamente, los valores
a 0xA1B2
b 0xF0F0
las siguientes e*presiones se evalKan como sigue:
a && b 1 (Verdadero) a & b 0xA0B0
a || b 1 (Verdadero) a | b 0xF1F2
!a 0 (FaIso) ~a 0x5E4D
+os operadores J, V, , Y son id9nticos, respectivamente, a las instrucciones del
+enguaje Ensam&lador 6><, )' , >)-C %or tanto, el operador J permite poner
ciertos &its a 2 dejando el resto como esta&an, el operador V permite poner ciertos &its
a 1 dejando el resto inalterado, , el operador Y cam&ia los &its 1 por 2 , viceversa
D0er ejercicio 12 al $inal del cap@tuloEC
El operador Z Dor e*clusivoE es id9ntico a la instrucci"n B)' de +enguaje
Ensam&ladorC 4u ta&la de verdad es la siguienteC
a b a^b
1
0eremos m.s adelante que el operador B devuelve el valor asignadoC En este caso, la e*presi"n C( B - devuelve el valor ,
que se evalKa como ciertoC
**ii
$ $ $
$ % %
% $ %
% % $
%or ejemplo, si a , b almacenan los valores
a 0xA1B2
b 0x1234
la siguiente e*presi"n produce el resultado indicado
a ^ b 0xB386
El operador Z permite cam&iar ciertos &its a su valor contrario, dejando el
resto sin modi$icar D0er ejercicio 12 al $inal del cap@tuloEC
+os operadores de despla1amiento >> , ==, mueven todos los &its de una
varia&le a la derecha o a la i1quierda, respectivamente, un nKmero de posiciones
determinadoC El $ormato general es:
4ariable == n o &ien 4ariable >> n
6s@, la sentencia
a = b << 4;
almacena en a el contenido de b, despu9s de reali1ar un despla1amiento de b de 4 &its
a la i1quierdaC El contenido de b permanece inalteradoC
6l igual que en +enguaje ensam&lador, # distingue entre despla1amientos
aritm9ticos , l"gicos:
;espla5amientos aritmWticos2 4e reali1an so&re datos enteros , mantienen
el signoC
;espla5amientos lgicos2 4e reali1an so&re datos declarados como sin
signo DunsignedE
2
, simplemente aFade cerosC
0eamos un ejemploC 4ea a una varia&le declarada como entera Dcon signoE, que
almacena el valor he*adecimal 0132:
a 0xA1B2
a = a << 4 produce a 0x1B20
a = a >> 4 produce a 0xFA1B
4in em&argo, si a se declara como unsigned,
2
unsigned es una pala&ra reservada que se puede aplicar al tipo de dato intC +as varia&les as@ declaradas se entienden siempre
como positivasC
**iii
a = a << 4 produce a 0x1B20
a = a >> 4 produce a 0x0A1B
/peradores de asignacin
+as asignaciones se reali1an mediante el operador MC El uso de este operador
tiene ciertos aspectos que lo distinguen del de otros lenguajesC En primer lugar, se
puede emplear cualquier nKmero de veces en una e*presi"nC 6s@, podemos tener
sentencias como
a = b = c = 3;
que asigna el valor 3 a las varia&les a, b , cC Esto es as@ porque la operaci"n de
asignaci"n, adem.s de asignar el valor, devuelve el valor asignadoC 6s@, la e*presi"n
c B 3 devuelve el valor 3, que se asigna a b, , as@ sucesivamenteC -am&i9n son
posi&les sentencias como
x = 3;
y = x + (z = 6);
que asigna a (, -, , 5 los valores 3, , 6, respectivamenteC
El operador de asignaci"n se com&ina con los operadores 9, !, E, Q, S, ==, >>,
J, V, Z, para operaciones acumulativasC %or ejemplo,
m *= 5; m = m * 5;
m += b; m = m + b;
m += y - 3;
es equivalente a
m = m + y - 3;
m - = (y = 5); m = m - (y = 5);
m >>= (2 * x + 1); m = m >> (2 * x + 1);
/perador condicional (I2)
Es un operador ternario que se usa para reempla1ar sentencias simples del tipo
if...elseC El $ormato de este operador es:
=condicin> I =e(presin[sG> 2 =e(presin[no>
Funciona del siguiente modo: primero se evalKa =condicin>O si es verdadera
se evalKa =e(presin[sG>, en caso contrario se evalKa =e(presin[no>C %or
ejemplo, en la sentencia
y = (x > 9 ? 100 : 200);
la varia&le - toma el valor 122 cuando ( > ., , el 222 en caso contrarioC
/peradores de punteros (J8 9)
**iv
Estos operadores, desa$ortunadamente, se identi$ican con el mismo s@m&olo
que el 6>< de manipulaci"n de &its , el producto, respectivamenteC <e cualquier
$orma no ha, posi&ilidad de con$usi"n, pues actKan en conte*tos di$erentesC
OPERADOR DESCRIPCIN
UNARIOS ! +ireccin de
, -onenido de
El operador J actKa so&re una varia&le , devuelve su direcci"n de memoriaC
<espu9s de
dir_a = &a;
la varia&le dir[a almacena la direcci"n de aC
El operador 9 actKa so&re varia&les que contienen direcciones DpunterosE ,
devuelven el contenido de la posici"n de memoria almacenada en la varia&le so&re la
que actKanC 4i dir[a es una varia&le que almacena una direcci"n de memoria, la
e*presi"n
b B 9dir[aA
almacena en la varia&le b el contenido de la posici"n de memoria apuntada por dir[aC
<e igual modo, la e*presi"n
9dir[a B *1A
almacena el valor *1 en la direcci"n de memoria apuntada por dir[aC
3
<espu9s de la siguiente secuencia, las varia&les m , 5 almacenan los valores
, 2 respectivamenteC
m = 1;
n = 2;
direcc = &m; (direcc direccin de m)
*direcc = 4; ( m 4)
direcc = &n; (direcc direccin de n)
z = *direcc; (z 2)
/perador de tama\o (si5eof)
Es un operador unario que devuelve el tamaFo en &,tes del operandoC +a
sinta*is es:
sizeof (m)
3
%ara que las sentencias en las que interviene la varia&le dir[a $uncionen correctamente, 9sta de&e declararse de un modo
especial, que e*plicaremos en el #ap@tulo 5, en el que se estudiar.n los punterosC
**v
, devuelve los valores 1, 2 , 4 si m es, respectivamente, de tipo car.cter, entero o
$loatC 4i m es una matri1 devuelve el tamaFo, en &,tes, ocupado por ellaC -am&i9n
devuelve el tamaFo de ciertos o&jetos del #, denominados estructuras, que se
estudiar.n en el #ap@tulo 8C
/perador secuencial (8)
4e utili1a para concatenar e*presionesC El lado i1quierdo de la coma se evalKa
primeroC %or ejemplo, despu9s de la e*presi"n
x = ( y = 45, y++, y * 2);
las varia&les ( e - almacenan, respectivamente, los valores 2 , 46C
/peradores . - S>
4e estudiar.n detenidamente en el #ap@tulo 8, dedicado a uniones , estructurasC
/perador de moldeado (cast)
%ermite cam&iar el tipo de una e*presi"nC +a sinta*is es:
(tipo) expresin
donde tipo es uno de los tipos &.sicos de datos que estudiaremos en el pr"*imo
cap@tulo Den el anterior ,a se vieron int , floatEC %or ejemplo, en la secuencia
int x;
x = 5;
y = x / 2;
el valor asignado a la varia&le - ser. 2, pues ! reali1a una divisi"n enteraC 4i se desea
que - tenga parte $raccionaria, se utili1ar. el operador de moldeado:
int x;
x = 5;
y = (fIoat) x / 2;
6hora, la varia&le - almacena el valor 2C(C
<e cualquier modo, ha, que ser cuidadosos con este operadorC En la secuencia
int x;
x = 5;
y = (fIoat) (x / 2);
no se asigna a - el valor 2C(, sino 2, ,a que los par9ntesis que envuelven a la
e*presi"n ( ! 2 hacen que primero se e$ectKe la divisi"n entera , luego se convierta a
$loatC
**vi
/peradores T U - ( )
+os corchetes se utili1an para acceder a los elementos de una matri1C 4e
estudiar.n en el #ap@tulo 5C
+os par9ntesis sirven para clari$icar una e*presi"n o para modi$icar las reglas de
prioridad entre operadoresC Estas reglas de prioridad quedan re$lejadas en la ta&la de
la p.gina siguienteC
+as prioridades de esta ta&la pueden alterarse por medio de los par9ntesisC
#uando alguna e*presi"n se enmarca entre par9ntesis, se evalKa primeroC 4i ha,
anidamiento, se evalKan primero los m.s internosC %or ejemplo, la e*presi"n
x + 5 * y
se evalKa del siguiente modo:
1C 4e calcula # 9 -, pues el operador 9 tiene ma,or prioridad que el operador
QC
2C 4e suma a ( el resultado de la operaci"n anteriorC
4in em&argo, si escri&imos
(x + 5) * y
los par9ntesis modi$ican la prioridad, evalu.ndose en primer lugar la e*presi"n ( Q #,
, multiplicando este valor por -C
#uando en una e*presi"n intervienen operadores con el mismo nivel de
prioridad, se evalKan en el sentido indicado en la primera columna de la ta&laC
Evaluacin a iual
niv!l "! #$i%$i"a"
Niv!l "!
#$i%$i"a"
O#!$a"%$!&
'( ) * + , - ./
0(
! 1 22 .. )ca&3* 4
4
&
(

&i5!%6
7( 4 8 9
:( 2 .
;( << //
=( < <> / />
?( >> !>
@( &
4
)perador contenido deC
5
)perador direccin deC
**vii
A( ^
'B( |
''( &&
'0( ||
'7( CD
':( %#!$a"%$!& "! a&inacin
';( E
Efecto lateral
#uando en una e*presi"n se emplea m.s de una ve1 un mismo operando, , en
alguna de ellas se modi$ica su valor, pueden producirse errores de e$ecto lateralC %or
ejemplo, sea la secuencia
i = 2;
matriz[i] = x + (i = 4);
En la segunda sentencia, el elemento matri5TiU se re$iere el elemento iA9simo de un
vector llamado matri5C 4in em&argo, en esa e*presi"n no se asegura que el resultado
se almacene en matri5T2U o en matri5TUC
%ara evitar este tipo de pro&lemas es necesario seguir las siguientes reglas:
>o utili1ar operadores QQ o SS so&re varia&les que se empleen m.s de una
ve1 en una e*presi"nC
>o utili1ar operadores QQ o SS so&re varia&les que se empleen m.s de una
ve1 como argumento de una $unci"nC
6as directi4as #include - #define
Estudiaremos ahora dos directivas que se utili1an pr.cticamente en todos los
programas #C
#include
!ndica al compilador que inclu,a un archivo $uenteC El $ormato es
#incIude "nom_fich"
**viii
o &ien,
#incIude <nom_fich>
siendo nom[fic& un nom&re v.lido de $ichero <)4C
%uede decirse que cuando el compilador se encuentra una l@nea #include,
reempla1a dicha l@nea por el $ichero nom[fic&C
El uso de comillas do&les II o .ngulos V W a$ecta a d"nde se &uscar. el $ichero
nom[fic&C En el primer caso se &usca en el siguiente orden:
1C <irectorio en el que se est. tra&ajandoC
2C <irectorios indicados al compilar el programa desde la l@nea de "rdenes del
<)4C
3C <irectorios indicados en la implementaci"n de -ur&o #C
En el segundo caso el orden de &Ksqueda es el siguiente:
1C <irectorio de$inido con la opci"n A! del compiladorC
2C <irectorio indicado en el /enK %rincipal de -ur&o #C
3C <irectorios de$inidos en la implementaci"n de -ur&o #C
En am&os casos se supone que el nom&re del $ichero no va acompaFado de
ninguna tra,ectoria de directorioC En caso de que el nom&re del $ichero inclu,a una
ruta de acceso, s"lo se &uscar. en ese directorioC 6s@, en el caso
#incIude "C:\MIDIR\MIFICH.H"
o &ien
#incIude <C:\MIDIR\MIFICH.H>
la &Ksqueda se reali1a s"lo en el directorio C2F,I;IL, produci9ndose un mensaje de
error si no se encuentra el archivoC
+a directiva #include se usa principalmente para la inclusi"n de los
denominados arc&i4os de cabeceraC +a inclusi"n de estos archivos es necesaria
cuando se utili1an las funciones de bibliotecaC Estas $unciones emplean tipos de
datos , varia&les propias que se de$inen en esos archivosC %or ejemplo, el archivo de
ca&ecera requerido por las $unciones printf() , scanf() Djunto con otras muchas m.sE
se llama stdio.&, , por ello siempre que un programa maneje esas $unciones de&er.
incluir una l@nea como
#incIude <stdio.h>
<e cualquier modo, puede utili1arse para incluir cualquier archivo $uenteC
#define
**i*
En su $orma m.s simple se usa para asociar a un identi$icador una cadena de
caracteres que lo sustituir. cada ve1 que lo encuentre el compilador en el programaC
6l identi$icador se le denomina macro , al proceso de sustituir el identi$icador por la
cadena de caracteres se le llama sustitucin de macroC El $ormato general para esta
directiva es
#define macro cadena
%or ejemplo, en
#define CIERTO 1
#define FALSO 0
cuando el compilador encuentra el nom&re de macro CIELT/ lo sustitu,e por el
valor 1C #uando encuentra el nom&re )06"/ lo sustitu,e por el valor 1C -am&i9n es
v.lido
#define MENSAJE "Error de E/S \n"
...
...
printf (MENSAJE);
que es equivalente a la sentencia
printf ("Error de E/S \n");
>o se produce el proceso de sustituci"n de macro en el caso
printf ("MENSAJE");
que muestra en pantalla la cadena de caracteres ,E<"0PEC -am&i9n se pueden
escri&ir sentencias como
#define TECLA printf ("\nPuIse cuaIquier tecIa...")
...
...
TECLA;
;na ve1 de$inida una macro, puede utili1arse en la de$inici"n de macros
posteriores:
#define A 1
#define B 2
#define TRES A + B
4i la de$inici"n de la macro es demasiado larga, se indica mediante una &arra
invertida F , se continKa la de$inici"n en la siguiente l@neaC
#define LARGO "Este mensaje es \
demasiado Iargo"
%or convenio, los nom&res de macros se escri&en en ma,KsculaC
E7ercicios
***
1. 'epresenta de 3 maneras di$erentes el car.cter nueva l@neaC
2. !ndica el signi$icado de cada uno de los siguientes elementos
aE 12 &E 212 cE 2*12 dE 2B12
eE PN>P $E PN*12P gE PN*21&P hE PN234P
3. !ndica cu.les de los siguientes identi$icadores no son correctos , por qu9C
aE contador &E #)>-6<)' cE Xhola dE holaX
eE dias2 $E 2dias gE 4umaX-otal hE 4umaA-otal
. 4ean (, -, 5, u, 4 , t, varia&les que contienen, respectivamente, los valores 2, 3,
4, (, 6 , 5, 7qu9 almacenar.n despu9s de ejecutar las siguientes sentencias:
x++;
y = ++z;
t = - -v;
v = x + (y *= 3) / 2;
u = x + y / 2;
#. 78u9 di$erencia ha, entre PNaP , PN6P: 7Y entre P6P , I6I:
$. !ndica cu.les de las e*presiones siguientes son verdaderas , cu.les $alsas,
suponiendo que (, -, 5 , t, almacenan, respectivamente los valores 22, 12, ( ,
2C
a) x > y && z > t b) x < y && z > t c) x < y || z > t
d) !0 e) !1 f) 0 != 1
g) 0 != !1 h) 0 == !1 i) 200 || x
j) x * 0 k) x * y l) !!0
m) !(0 == 0) n) 10 > 5 && !(10 < 9) || 3 <= 4
) 1 && !0 || 1 o) 1 && !(0 || 1)
+. 4ea ( una varia&le entera que almacena el valor 11 78u9 almacenar. - despu9s
de las siguientes sentencias:
a) y = (x > 9 ? ++x : -- x);
b) y = (x > 9 ? x++ : x--);
7Y si ( almacenase el valor *:
*. ;na temperatura en grados cent@grados #, puede ser convertida en su valor
equivalente de la escala Fahrenheit de acuerdo a la siguiente $"rmula:
***i
F M D 3 (E # L 32
Escri&e un programa # que solicite una temperatura en grados cent@grados por
teclado , presente en pantalla la temperatura Fahrenheit equivalenteC
D6-E>#!Z> a la divisi"n 3(EC
.. Escri&e un programa que lea un nKmero he*adecimal entero del teclado
Dc"digo de $ormato E(E, intercam&ie los &,tes alto , &ajo, , presente el
resultado en he*adecimal en la pantallaC D>)-6: <eclara la varia&le que
almacenar. el valor he*adecimal como unsigned int , utili1a los operadores
== , >>EC
11. Escri&e un programa que lea un nKmero he*adecimal del teclado , manipule
sus &its de acuerdo al siguiente criterio:
%oner a 2 los &its 2, 3, 6 , C
%oner a 1 los &its 2, (, 8 , 11C
#am&iar el estado del restoC
%resenta en pantalla el resultado en he*adecimalC D>)-6: <eclara la varia&le
que almacenar. el valor he*adecimal como unsigned int , utili1a los
operadores de tratamiento de &itsEC
11. Escri&e un programa que lea dos nKmeros enteros del teclado , presente en
pantalla el triple de la di$erencia entre el ma,or , el menorC D%ara sa&er cu.l es
el ma,or utili1a el operador I2E
12. Escri&e un programa que capture por teclado un nKmero entero de 4 ci$ras , lo
redondee a la centena m.s pr"*ima, presentando el resultado en pantallaC
3
Tipos bsicos
de datos
Tipos bsicos de datos
***ii
En # es necesario declarar todas las varia&les antes de ser utili1adasC 6l
declarar una varia&le de&emos asignarle uno de los ( tipos &.sicos de datosC Estos
tipos &.sicos son los que se muestran en la siguiente ta&laC
TIPO PAFABRA
RESERGADA
TAHAIO EN BJTES
sin !alor !oid 0
car)cter c?ar 1
entero int &
coma 'lotante (simple
precisi6n)
'loat ,
coma 'lotante (doble
precisi6n)
double 8
-oda varia&le declarada de uno de los tipos anteriores Dsalvo 4oidE se supone
que puede ser positiva o negativa a menos que se aplique uno de los modi$icadores
que veremos m.s adelanteC
El tipo 4oid se usa para de$inir $unciones que no devuelven ningKn valor Dno
tienen sentencia returnEC %or ejemplo, ninguna de las $unciones main() utili1adas
hasta ahora devuelve valoresC Esto provoca un I[arningI en la compilaci"n, que se
evita escri&iendo 4oid main (), en lugar de escri&ir simplemente main()C 6dem.s, el
tipo 4oid se usa en ciertas operaciones de punteros que se estudiar.n en el #ap@tulo
5C
+as varia&les de tipo c&ar se usan para almacenar caracteres simples o nKmeros
enteros de tamaFo &,teC #uando se asigna un car.cter simple a una varia&le de tipo
c&ar, se almacena su c"digo 64#!!C Esto permite hacer operaciones matem.ticas con
este tipo de varia&lesC %or ejemplo, el siguiente programa
#incIude <stdio.h>
void main ()
{
char caracter;
caracter = '$';
caracter *= 2;
printf ("%c %d", caracter, caracter);
}
muestra en pantalla O +2, puesto que la asignaci"n del car.cter P\P a la varia&le
caracter almacena en la varia&le su c"digo 64#!! D36EC El Ec es el c"digo de
$ormato para visuali1ar caracteres simplesC
***iii
El tipo int se utili1a para declarar varia&les que almacenar.n nKmeros enteros,
sin decimalesC
+os tipos float , double permiten almacenar nKmeros con decimalesC
Cmo declarar 4ariables
;na sentencia # que declare varia&les de&e respetar la siguiente sinta*is:
Tclase de almacenamientoUTmodificadorU tipo 4ariableT8 4ariable8 ...UA
+as clases de almacenamiento , los modificadores del tipo se estudiar.n en los
pr"*imos apartados del cap@tuloC
Ejemplos v.lidos de declaraci"n de varia&les son:
char Ietra1, Ietra2;
int m, n;
fIoat p, q;
doubIe z;
Estas declaraciones de&en situarse al principio de la $unci"n , antes de cualquier
instrucci"n o llamada a $unci"nC %ueden ir precedidas por alguno de los modi$icadores
de tipo que estudiaremos a continuaci"nC
,odificadores del tipo de una 4ariable
;n modificador del tipo es una pala&ra reservada que antecede a la de$inici"n
del tipo de la varia&le, , permite cam&iar el tamaFo, rango , la caracter@stica de
signo3sin signoC +os modi$icadores de tipo son:
s&ort
long
signed
unsigned
Estos modi$icadores se aplican Knicamente a los tipos c&ar e int, salvo el long, que
en un caso se puede aplicar al tipo doubleC
+a ta&la siguiente muestra los rangos , tamaFos de cada tipo, segKn se apliquen
los modi$icadoresC
***iv
Ti#% H%"i6ica"%$!& Ran% Ocu#a
c?ar unsi*ned 0 a &@@ 1 b:te
si*ned 01&8 a 1&7 1 b:te
int s?ort unsi*ned 0 a A@B@+@ & b:tes
si*ned 0+&B7A8 a +&B7A7 & b:tes
lon* unsi*ned 0 a ,B&9,B9A7B&9@ , b:tes
si*ned 0&B1,7B,8+BA,8 a
&B1,7B,8+BA,7
, b:tes
'loat C+D,410
0+8
a C+D,410
2+8
, b:tes
double C1D7410
0+08
a C1D7410
2+08
8 b:tes
lon* C+D,410
0,9+&
a C1D1410
2,9+&
10 b:tes
'especto de estos modi$icadores ha, que tener en cuenta los siguientes
aspectos:
aE El modi$icador signed no es necesarioC -odas las varia&les enteras, por
de$ecto, se consideran con signoC
signed c&ar equivale a c&ar
signed int I int
&E El tipo de dato c&ar no es a$ectado por los modi$icadores s&ort , longC
s&ort c&ar equivale a long c&ar , a c&ar
cE -ur&o # permite una notaci"n &reve para declarar enteros sin usar la pala&ra
reservada intC
unsigned equivale a unsigned int
s&ort I s&ort int
long I long int
unsigned s&ort I unsigned s&ort int
unsigned long I unsigned long int
dE +os modi$icadores signed , unsigned provocan un error si se aplican a los
tipos float , doubleC
eE +os modi$icadores s&ort , long no a$ectan a floatC
$E 6l tipo double no le a$ecta el modi$icador s&ortC El modi$icador long se
puede aplicar a partir de la versi"n 2C22 de -ur&o #C
gE +a precisi"n que se puede o&tener para los tipos de datos reales viene dada
por la siguiente ta&la:
***v
TIPO PRECISIN
'loat 7 d#*itos
double 1@ d#*itos
lon* double 19 d#*itos
]ariables locales - 4ariables globales
<ependiendo del lugar del programa en que se declare una varia&le, a 9sta se le
llama local o globalC ;na varia&le puede declararse en 4 lugares di$erentes de un
programa:
Fuera de todas las $unciones DglobalE
<entro de una $unci"n Dlocal a la $unci"nE
<entro de un &loque enmarcado por llaves S T Dlocal al &loqueE
#omo par.metro $ormal Dlocal a la $unci"nE
;na varia&le global es conocida por todo el programa, mientras que una
varia&le local s"lo es conocida por la $unci"n o &loque en donde est. de$inidaC
]ariables globales
#uando una varia&le est. declarada $uera de todas las $unciones, incluso $uera
de main (), se denomina M6/306 , es conocida por todas las $unciones del
programaC
]ariables locales
;na varia&le es 6/C06 cuando se declara:
dentro de una $unci"n
como argumento de una $unci"n
en un &loque de sentencias enmarcado por S T
En cualquiera de estos casos, la varia&le s"lo es conocida por la $unci"n o
&loque en donde est. de$inidaC 4e crea al entrar a la $unci"n o &loque , se destru,e al
salirC Esto permite que dos varia&les locales a di$erentes $unciones pueden tener el
mismo identi$icador, pero se consideran dos varia&les di$erentesC %or claridad, no se
recomienda utili1ar nom&res iguales para varia&les di$erentesC
***vi
6 continuaci"n se muestra un programa que pretende ilustrar las di$erencias
entre varia&les locales , glo&alesC En 9l se declara una varia&le glo&al -, conocida por
todas las partes del programa, , varias varia&les locales, todas con el mismo nom&re
(: una local a main(), otra local a un &loque dentro de main(), , otra local a una
$unci"nC
#incIude <stdio.h>
int y; ., Glo/al0 -onocida ano por main12 como por MiFuncion12 ,.
main ()
{
int x; ., Esa % es local a main 12 ,.
y = 100;
x = 1;
printf ("x=%d, y=%d", x, y) ., 3isuali(a %456 74588 ,.
{ ., -omien(a /lo*ue ,.
int x; ., Esa % es local al /lo*ue ,.
x = 2;
printf ("x=%d, y=%d", x, y) ., 3isuali(a %496 74588 ,.
MiFuncion () ., 3isuali(a %4:6 74588 ,.
printf ("x=%d, y=%d", x, y) ., 3isuali(a %496 74588 ,.
} ., Fin del /lo*ue ,.
printf ("x=%d, y=%d", x, y) ., 3isuali(a %456 74588 ,.
}
MiFuncion ()
{
int x; ., Local a MiFuncion12 ,.
x = 3;
printf ("x=%d, y=%d", x, y) ., 3isuali(a %4:6 74588 ,.
}
Clases de almacenamiento
E*isten cuatro clases de almacenamiento, que se identi$ican con las pala&ras
reservadas:
auto
e(tern
static
register
que anteceden al tipo de dato en la declaraci"n de las varia&lesC
El modo de almacenamiento de una varia&le determina
qu9 partes del programa la conocen DmbitoE
qu9 tiempo permanece en la memoria Dtiempo de 4idaE
]ariables automticas (auto)
***vii
;na varia&le es de clase auto si es local a una $unci"n o &loqueC +a varia&le se
crea cuando se llama a la $unci"n , se destru,e al salir de ellaC
El especi$icador auto es redundante, pues todas las varia&les locales son
automticas por de$ectoC
...
Funcion ( ...
{
auto int a; /* DecIara Ia variabIe como IocaI a Funcion */
...
]ariables e(ternas (e(tern)
#uando una varia&le se de$ine $uera de una $unci"n se clasi$ica como e(terna ,
tiene alcance glo&alC
;na varia&le glo&al puede volver a declararse dentro del cuerpo de una $unci"n,
aFadiendo la pala&ra reservada e(ternC
...
int a; /* VariabIe gIobaI */
main ()
{
extern int a; /* Es Ia misma variabIe */
...
Esta redeclaraci"n es innecesaria cuando todas las $unciones est.n en el mismo
m"duloC 4in em&argo, si un programa consta de varios m"dulos di$erentes, es
necesaria la pala&ra e(tern para que sea reconocida por m"dulos distintos del que
contiene la declaraci"n de la varia&leC
%or ejemplo, supongamos que %')=1C# , %')=2C# son dos m"dulos que se
compilan separadamente ,, posteriormente, se enla1an para $ormar un solo m"dulo
ejecuta&leC
PROG1.C PROG2.C
#incIude <stdio.h> #incIude <stdio.h>
int x; extern int x, y;
int y;
FuncionExterna ()
main () {
{ printf ("x=%d, y=%d", x, y);
x = 10; y = 20; }
printf ("x=%d, y=%d", x, y);
***viii
FuncionInterna ();
FuncionExterna ();
}
FuncionInterna ()
{
printf ("x=%d, y=%d", x, y);
}
En el m"dulo %')=1C# Dque se compilar. a %')=1C)B]E ha, una llamada a
)uncionInterna()C Esta $unci"n no necesita la redeclaraci"n de ( e - puesto que
reside en el mismo m"dulo en el que estas varia&les est.n declaradas como glo&alesC
4in em&argo, ha, una llamada a )uncionE(terna(), , esta $unci"n reside en un
m"dulo distinto D%')=2C#E que se compilar. por separado Da %')=2C)B]EC %ara
que )uncionE(terna() pueda reconocer a las varia&les ( e - que est.n declaradas
como glo&ales en %')=1C#, es necesario redeclararlas como de clase e(ternC En
caso contrario, %')=2C# Icreer@aI que son varia&les locales propias no declaradas,
por lo que se generar@a un error en la compilaci"nC
6 partir de los m"dulos o&jeto %')=1C)B] , %')=2C)B], mediante el
enla1ador, se crea un m"dulo ejecuta&le, por ejemplo %')=CEBEC Este programa
visuali1ar@a en 3 ocasiones la l@nea
x=10, y=20
puesto que para las tres $unciones Amain(), )uncionInterna() , )uncionE(terna()A
las varia&les ( e - son las mismasC
]ariables estticas (static)
;na varia&le esttica e*iste durante todo el tiempo de ejecuci"n del programaC
4i se aplica la clase static a una varia&le local, -ur&o # crea un
almacenamiento permanente para ella, como si $uese glo&alC +a di$erencia entre una
varia&le local esttica , una varia&le global es que la primera s"lo es conocida por la
$unci"n o &loque en que est. declaradaC 4e puede decir que una varia&le local
esttica es una varia&le local que mantiene su valor entre llamadasC
%or ejemplo, cada ve1 que se llama a la $unci"n
incremento ()
{
int n;
n++;
printf ("n=%d", n);
}
***i*
se visuali1a nB1
6
, mientras que si la $unci"n es
incremento ()
{
static int n;
n++;
printf ("n=%d", n);
}
se visuali1a, sucesivamente, nB1, nB2, CCC
#uando se aplica la clase static a una varia&le global, esta se convierte en
global slo del archivo en ue est! declaradaC 6s@, en el ejemplo de la p.gina
anterior, si en %')=1C# en lugar de la l@nea declaramos ( de la $orma
static int x;
se producir@a un error en el enla1ado, incluso aunque en %')=2C# ( est9 declarada
como e(ternC
Clase registro (register)
+a clase registro es id9ntica a la clase auto, por tanto s"lo se puede aplicar a
varia&les localesC 4"lo se di$erencian en el lugar en que se almacenanC
#ualquier varia&le se almacena, por de$ecto, en la memoriaC 4i se declaran de
clase register, -ur&o # intentar. mantenerlas en un registro de la #%;, en cu,o caso
se acelerar.n los procesos en los que intervenganC %uesto que el nKmero de registros
de la #%; es limitado, -ur&o # mantendr. las varia&les en un registro, si es posi&leC
En caso contrario la convertir. en autoC
;na varia&le de clase registro de&e ser de los tipos c&ar o int, , son ideales
para contadores de &uclesC
6 estas varia&les no se les puede aplicar el operador J Ddirecci"n deEC
Iniciali5acin de 4ariables
6l declarar una varia&le se le puede asignar un valor inicial, independientemente
de que lo mantenga o no a lo largo de todo el programaC 6s@, son v.lidas sentencias
como:
unsigned int x = 40000;
char Ietra = 'F';
register int b = 35;
char cadena[12] = "Buenos das";
6
En realidad no se puede sa&er cu.l es el valor de n pues, como veremos, n no se iniciali1a con ningKn valorC %ero para este ejemplo
podemos suponer que se iniciali1a a 2C
*l
+as varia&les glo&ales o est.ticas se iniciali1an a 2 si no se especi$ica ningKn
valorC 6m&as de&en iniciali1arse con e*presiones constantesC
+as varia&les est.ticas son iniciali1adas por el compilador una sola ve1, al
comien1o del programaC
+as varia&les autom.ticas , de registro tienen valores desconocidos hasta que
se les asigne unoC 4i tienen valores iniciales, se asignan cada ve1 que se ejecuta el
&loque donde se de$inenC
*li
E7ercicios
1. !ndica el tipo de dato m.s adecuado para declarar varia&les que almacenen los
valores cu,os rangos se muestran a continuaci"n:
aE >Kmeros enteros del 2 al 52C222
&E >Kmeros enteros del 1 al 122
cE >Kmeros reales del 1 al 122
dE >Kmeros enteros del A122 al L122
eE >Kmeros reales del A122 al L122
$E >Kmeros enteros del 2 al 12C222
gE #ualquier letra ma,Kscula
hE >Kmeros enteros del 2 al (C222C222C222
iE >Kmeros del A12C( al 2C12(
2. 78u9 hace el siguiente programa:
#incIude <stdio.h>
void main ()
{
unsigned char caracter;
scanf ("%c", &caracter);
caracter > 127 ? caracter++ : caracter--;
printf ("%c", caracter);
}
3. !ndica el tipo de varia&le Dlocal3glo&alE, .m&ito , tiempo de vida de las varia&les
a, b, c , d de un programa que tenga la estructura que se muestra a
continuaci"n:
int a;
void main ()
{
int b;
...
}
MiFuncion ()
{
int c;
static int d;
...
}

*lii
E!" bsica
Tipos de E!"
Ya qued" dicho en el #ap@tulo 1 que # no tiene pala&ras reservadas espec@$icas
que se encarguen de la E34C Estas operaciones se reali1an mediante $unciones de
&i&liotecaC Estas $unciones reali1an operaciones de E34 que se clasi$ican del siguiente
modo:
E!" de alto ni4el, de$inida por el est.ndar 6>4!C -am&i9n se denomina
sistema de archivos con &K$$erC
E!" de ba7o ni4el, o E34 de tipo ;>!BC
E!" por consolaC
+os dos est.ndares 6>4! , ;>!B son redundantesC -ur&o # admite los dos,
pero no de&en utili1arse dentro de un mismo programa $unciones de am&osC
En el presente cap@tulo se estudiar.n operaciones &.sicas de E34 por consola,
entendiendo por ello las operaciones reali1adas so&re la E34 est.ndar del sistema, por
de$ecto teclado , pantallaC 0eremos tam&i9n que tanto la entrada como la salida
puede redireccionarse a otros dispositivos, , c"mo hacerlo, , tam&i9n c"mo reali1ar
operaciones de salida a impresoraC %or Kltimo, estudiaremos c"mo reali1ar cierto
control so&re la pantalla en modo te*to Dcolor, posicionamiento, etcCEC +as
operaciones de E34 a $icheros se estudiar.n en los #ap@tulos 12 , 11C
E!" de caracteres
)unciones getc&e() - getc&()
4on las dos $unciones &.sicas que capturan caracteres simples por tecladoC +os
programas que utili1an estas $unciones de&en incluir el archivo de ca&ecera conio.&
mediante una sentencia #includeC 6m&as $unciones devuelven el car.cter le@do del
teclado Dsin esperar a pulsar la tecla EC +a $unci"n getc&e() muestra en pantalla el
car.cter tecleadoC >o as@ la $unci"n getc&()C El uso correcto de estas $unciones es
mediante sentencias del tipo
char a; /* Tambin puede decIararse como int */
...
...
*liii
a = getche (); /* o bien a = getch (); */
Estas $unciones no tienen argumentosC >o es o&ligatorio capturar en una
varia&le el car.cter le@doC 6s@, es correcto escri&ir:
printf ("\nPuIse una tecIa para continuar ...");
getch ();
que detiene el programa hasta que ha,a un car.cter disponi&le en el tecladoC
//EjempIo: VisuaIiza eI cdigo ASCII de un carcter tecIeado
#incIude <stdio.h>
#incIude <conio.h>
void main ()
{
unsigned int caracter;
printf ("\nPuIse una tecIa: ");
caracter = getche ();
printf ("\nSu cdigo ASCII es %u", caracter);
}
Este programa produce un resultado casi id9ntico utili1ando la $unci"n getc&()C
+a Knica di$erencia es la no visuali1aci"n del car.cter que se tecleaC El c"digo de
$ormato Eu se utili1a en printf() para visuali1ar nKmeros declarados unsignedC
)uncin putc&ar()
%ara la presentaci"n de caracteres en pantalla se puede usar, adem.s de printf()
con el c"digo de $ormato Ec, la $unci"n putc&ar()C +os programas que usen esta
$unci"n de&en incluir el archivo de ca&ecera stdio.&C El uso correcto de putc&ar() es
char a; /* Tambin puede decIararse como int */
...
...
putchar (a);
4i la varia&le a es de tipo int se visuali1a en pantalla el car.cter almacenado en el &,te
menos signi$icativoC +as sentencias
char Ietra;
...
...
Ietra = 65;
putchar (Ietra);
provocan la visuali1aci"n en pantalla del car.cter 0, cu,o c"digo 64#!! es 6(C Es
equivalente a
*liv
putchar ('A');
-am&i9n son posi&les sentencias como
putchar (getch ());
cu,o e$ecto es id9ntico al que produce la $unci"n getc&e()C
E!" de cadenas de caracteres
En # no ha, un tipo de dato espec@$ico para declarar cadenas de caracteresC
#omo ,a qued" dicho, una cadena de caracteres se de$ine como un vector de
caracteres terminado con el car.cter nulo ^F1^C 6s@, para declarar una cadena de hasta
32 caracteres se de&e escri&ir
char cadena[31];
6unque se pro$undi1ar. en el estudio de las cadenas de caracteres en el
#ap@tulo 5, es necesario adelantar que # no reali1a ningKn control de l@mites so&re
matricesC Ese cometido queda en manos del programadorC
)uncin gets()
+a $unci"n &.sica de entrada de cadenas caracteres por teclado es gets()C Esta
$unci"n lee caracteres del teclado hasta pulsar la tecla , almacen.ndolos en la cadena
indicada en el argumento , aFadiendo el car.cter nulo al $inalC
char frase[31];
...
...
gets (frase);
+a $unci"n gets() no hace compro&aci"n del l@miteC En la secuencia anterior nada
impedir. al usuario teclear m.s de 32 caracteresC +a consecuencia de ello es
imprevisi&le, aunque con toda seguridad el programa no $uncionar. correctamenteC
Es importante tener en cuenta que no se permite la asignaci"n de cadenas de
caracteres mediante el operador BC Este tipo de operaciones se reali1an mediante
$unciones de la &i&lioteca est.ndarC 6lguna de ellas se estudiar.n e el #ap@tulo 6C
frase = gets ();
)uncin puts()
+a $unci"n &.sica de salida de cadenas de caracteres es puts()C Esta $unci"n
escri&e en pantalla la cadena de caracteres especi$icada en el argumento , provoca,
*lv
adem.s, un salto de l@neaC Es m.s r.pida que printf() pero no permite $ormatear la
salidaC
-anto gets() como puts() precisan la inclusi"n del $ichero stdio.&C
//EjempIo con gets() y puts()
#incIude <stdio.h>
void main ()
{
char frase[31];
puts ("\nTecIee una frase: ");
gets (frase);
printf ("\nUsted ha tecIeado: %s", frase);
}
En el ejemplo anterior el c"digo de $ormato Es se re$iere a cadenas de
caracteresC ;n e$ecto similar al programa anterior lo produce la sentencia
puts (gets (frase));
E!" formateada
+a E34 con $ormato se reali1a por medio de las $unciones scanf() , prinft()
que ,a conocemosC +as estudiaremos ahora con m.s detalleC
)uncin printf()
#omo ,a hemos visto, esta $unci"n precisa la inclusi"n del archivo de ca&ecera
stdio.& , su $ormato general es:
printf (cadena de control8 lista de argumentos)A
+a cadena de control determina como se presentar.n el resto de argumentos
mediante los caracteres de $ormatoC %or cada car.cter de $ormato de la cadena de
control de&e ha&er un argumento en la listaC En caso contrario el resultado no ser.
correctoC +os caracteres de $ormato v.lidos vienen especi$icados en la ta&la siguienteC
TIPO DE
ARGUHENTO
CARCTER
DE
FORHATO
FORHATO DE
SAFIDA
umErico 7d si*ned decimal int
7i si*ned decimal int
*lvi
7o unsi*ned octal int
7u unsi*ned decimal int
7F unsi*ned ?eFadecimal int (con aD BBBD
')
7G unsi*ned ?eFadecimal int (con AD BBBD
$)
7' H0IddddBdddd
7e H0IdBdddd o bien eH250Iddd
7* el m)s corto de 7e : 7'
7J H0IdBdddd o bien JH250Iddd
7K el m)s corto de 7J : 7'
.ar)cter 7c car)cter simple
7s cadena de caracteres
77 el car)cter 7
(unteros 7n se re'ieren a punteros : se
7p estudiar)n en el .ap#tulo 7
/ediante los caracteres de $ormato pueden controlarse ciertos aspectos de la
presentaci"n de los datos, como la longitud, el nKmero de decimales , la justi$icaci"n
a i1quierda o derechaC
%ara indicar la longitud de un campo &asta incluir un nKmero entero entre el
signo E , el car.cter de $ormatoC 6s@, E#d indica que se va a presentar un nKmero
entero en un campo de ( posiciones, justi$icando a la derecha Dmientras no se indique
lo contrario la justi$icaci"n es siempre a la derechaEC 6s@,
printf ("\n[%5d]", 47); visualiza [47]
printf ("\n[%4d]", 47); visualiza [47]
printf ("\n[%3d]", 47); visualiza [47]
donde el s@m&olo representar. el resto del cap@tulo un espacio en &lancoC +os
corchetes se ponen s"lo para ver el e$ecto de los caracteres de $ormatoC
4i se desea justi$icaci"n a la i1quierda, se indica con un signo menosC
printf ("\n[%-5d]", 47); visualiza [47]
printf ("\n[%-4d]", 47); visualiza [47]
printf ("\n[%-3d]", 47); visualiza [47]
#uando se presenta un valor num9rico justi$icando a la derecha, puede hacerse
que el campo se rellene con ceros en lugar de espacios en &lanco, poniendo un 2 antes
del indicador de tamaFoC 6s@, la sentencia
printf ("\n[%05d]", 47); visualiza [00047]
Este e$ecto no se produce si se solicita justi$icaci"n i1quierda
printf ("\n[%-05d]", 47); visualiza [47]
#uando el dato so&repasa el tamaFo del campo, se imprime completo
printf ("\n[%3d]", 1234); visualiza [1234]
*lvii
4i lo dicho anteriormente se aplica a cadenas de caracteres, el resultado es el
que se indica a continuaci"n:
printf ("\n[%5s]", "ABC"); visualiza [ABC]
printf ("\n[%05s]", "ABC"); visualiza [ABC]
printf ("\n[%-5s]", "ABC"); visualiza [ABC]
printf ("\n[%-05s]", "ABC"); visualiza [ABC]
printf ("\n[%5s]", "ABCDEF"); visualiza [ABCDEF]
6plicado a caracteres simples
printf ("\n[%3c]", 'A'); visualiza [A]
printf ("\n[%-3c]", 'A'); visualiza [A]
4i se quiere dar $ormato a un nKmero con parte decimal se utili1a el c"digo de
$ormato
EmCnf
siendo m la longitud total del campo Dinclu,endo el puntoE , n el nKmero de
decimalesC 6s@, el especi$icador de $ormato E+.2f de$ine un campo de 5 posiciones
del siguiente modo: 4 para la parte entera, 1 para el punto , 2 para los decimalesC
printf ("\n[%7.2f]", 12.3); visualiza [12.30]
printf ("\n[%07.2f]", 12.3); visualiza [0012.30]
printf ("\n[%-7.2f]", 12.3); visualiza [12.30]
#uando el nKmero de decimales es ma,or que n, se redondea la Kltima ci$ra
printf ("\n[%7.2f]", 12.348); visualiza [12.35]
printf ("\n[%7.2f]", 12.342); visualiza [12.34]
4i este $ormato se aplica a cadenas de caracteres o nKmeros enteros, n
especi$ica el tamaFo m.*imo del campoC 6s@, E3.#s de$ine un campo de presentaci"n
para una cadena de al menos 3 caracteres , no m.s de (C 4i la cadena so&repasa el
tamaFo m.*imo, se truncaC
printf ("\n[%3.5s]", "ABC"); visualiza [ABC]
printf ("\n[%-3.5s]", "ABC"); visualiza [ABC]
printf ("\n[%3.5s]", "ABCDEFG"); visualiza [ABCDE]
printf ("\n[%3.5s]", "AB"); visualiza [AB]
printf ("\n[%5.3s]", "ABCDE"); visualiza [ABC]
%ueden utili1arse modi$icadores de $ormato para visuali1ar enteros s&ort ,
long, poniendo, respectivamente, & , l antes de d, u, o, (, RC
E&d para visuali1ar varia&les s&ort int
Eld para visuali1ar varia&les long int
E&u para visuali1ar varia&les unsigned s&ort int
Elu para visuali1ar varia&les unsigned long int
El modi$icador l tam&i9n se puede aplicar a e, f, g, E, MC
*lviii
Elf para visuali1ar varia&les long double
)uncin scanf()
Es la $unci"n de entrada de datos con $ormato de prop"sito general que hemos
visto en el #ap@tulo 1C +a sinta*is es similar a la de printf():
scanf (cadena de control8 lista de argumentos)A
aunque aqu@ la cadena de control no de&e interpretarse igual que en printf()C
#lasi$icaremos los caracteres que pueden aparecer en la cadena de control en 6
categor@as:
Especi$icadores de $ormato
#aracteres &lancos
#aracteres no &lancos
#ar.cter R
/odi$icadores de longitud
]uego de inspecci"n
Especificadores de formato2 4on los mismos que en printf() salvo Eg , Eu
, aFadiendo E&C 6s@, la sentencia
char a; /* Tambin se puede decIarar como int */
...
...
scanf ("%c", &a);
captura un car.cter , lo almacena en la varia&le aC El operador J es necesario en
scanf() para simular las llamadas "or referencia
5
, , hace que la $unci"n tra&aje
internamente con la direcci"n de la varia&leC >o es necesario cuando el dato a
capturar es una cadena de caracteresC
char cadena[80];
...
...
scanf ("%s", cadena);
aunque tendr@a el mismo e$ecto la sentencia
scanf ("%s", &cadena);
+a ra1"n por la que no es necesario el operador J cuando se trata de cadenas, es que
el nom&re de una cadena Den general, de una matri1E sin @ndices identi$ica la direcci"n
del primer elementoC
5
En las llamadas "or referencia a $unciones, cualquier cam&io operado so&re los par.metros dentro de la $unci"n tienen e$ecto
so&re las varia&les utili1adas en la llamadaC >o ocurre as@ en las llamadas "or valor en las que los cam&ios en los par.metros dentro de la
$unci"n no se re$lejan en las varia&les de la llamadaC Estudiaremos esto con detalle en el #ap@tulo 6, dedicado a FuncionesC
*li*
Caracteres blancos2 4on separadores de datos de entradaC 4e entiende como
car.cter &lanco cualquiera de los siguientes:
EspacioDsE en &lanco
-a&uladorDesE
'eturn, !ntro o salto de l@nea DE
#uando se especi$ica un car.cter &lanco en la cadena de control, scanf() lee,
pero no guarda, cualquier nKmero de caracteres &lancos hasta que encuentre el
primero que no lo seaC +a sentencia
scanf ("%c %d %s", &a, &b, &c);
almacena en a, b , c, respectivamente, datos introducidos de cualquiera de los
siguientes modos:
Y Y V-6BW 1 Y 1 Qola
1 Qola
Qola
, cualquier com&inaci"n similarC
Qa, que tener precauciones con el uso de los espacios en &lancoC ;na sentencia
como
scanf ("%s ", cadena);
no volver. hasta que no se teclee un car.cter no &lanco, puesto que el espacio que
ha, despu9s de Es hace que se lean , descarten espacios, ta&uladores , saltos de
l@neaC
Caracteres no blancos2 4e toman como separadores de los datos de entradaC
%or ejemplo, en la sentencia
scanf ("%dHOLA%c", &num, &car);
se lee un entero , se almacena en num, los caracteres O/60 , se descartan Des
necesario teclearlosE, , un car.cter cualquiera , se almacena en carC <e&ido a ello ha,
que poner especial cuidado en no usar la cadena de control de scanf() como en
printf(), , >) E4#'!B!' sentencias como:
scanf ("TecIee un nmero: %d", &num);
Carcter 92 #uando se coloca un 9 entre el s@m&olo E , el car.cter de
$ormato, se lee el tipo de dato especi$icado pero no se asigna a ninguna varia&leC +a
sentencia
scanf ("%d %*c %d", &num1, &num2);
lee un entero , lo almacena en num1, lee un car.cter , lo descarta Dno se asigna a
ninguna varia&le, , lee otro entero , lo guarda en num2C <e este modo, si a una
sentencia como la anterior se responde tecleando algo como
l
11S21
se almacenar@a el valor 11 en num1 , el valor 21 en num2C
,odificadores de longitud2 Es posi&le limitar el nKmero de caracteres que se
admiten en un campo escri&iendo un nKmero despu9s del s@m&olo E del car.cter de
$ormatoC 6s@, la sentencia
scanf ("%5s", frase);
captura cualquier cadena de caracteres tecleada, pero s"lo almacena en frase los (
primerosC 4in em&argo el resto de caracteres no se descartan, sino que quedan en el
&K$$er del teclado disponi&les para ser le@dos por otra sentencia scanf()C El siguiente
programa ilustra el uso de scanf() con modi$icadores de longitudC
//EjempIo de scanf() con modificador de Iongitud
#incIude <stdio.h>
void main ()
{
Iong int n1, n2;
printf ("\nTecIee 2 nmeros enteros: ");
scanf ("%5Id %5Id", &n1, &n2);
printf ("\nLos nmeros tecIeados son %Id y %Id", n1, n2);
}
4i en este programa a la sentencia scanf() se responde con
123#$
se muestra en pantalla
6os n_meros tecleados son 123# - $
Puego de inspeccin2 4e utili1a s"lo con Es , permite especi$icar qu9
caracteres se aceptar.nC 4e indican entre corchetesC %or ejemplo
char frase[30];
...
...
scanf ("%[abc]s", frase);
admite s"lo los caracteres a, b, cC #uando se teclea un car.cter que no est. en el
juego de inspecci"n $inali1a la entrada para esa varia&leC 4in em&argo, la sentencia
continuar. admitiendo caracteres hasta que se teclee , dejando los caracteres no
capturados en el &K$$er del teclado, disponi&les para otra sentencia scanf() posteriorC
%or ello, si se tienen dos sentencias como
scanf ("%[abc]s", frase);
scanf ("%s", cadena);
li
, se teclea, por ejemplo
abcbbapabcfgts
en frase se almacenar. la cadena abcbba, mientras que en cadena se almacenar.
abcfgtsC El car.cter p, primero di$erente de TabcU, actKa como $inali1ador de la
entrada para la varia&le fraseC
%ueden especi$icarse rangosC %or ejemplo
scanf ("%[a-z]s", frase);
admite cualquier car.cter comprendido entre la a , la 5C -am&i9n, la sentencia
scanf ("%[0-9][p-t]s", frase);
admite cualquier d@gito num9rico , los caracteres pKrstC
Es posi&le de$inir juegos inversos de inspecci"n mediante el car.cter ZC ^ste le
indica a scanf() que de&e aceptar cualquier car.cter ue no est# en el juego de
inspecci"nC %or ello, la sentencia
scanf ("%[^0-9]s", frase);
$inali1a la entrada al teclear un d@gito num9ricoC
6a funcin fprintf()
Esta $unci"n es pr.cticamente id9ntica a printf()C %ero fprintf() permite
asociar la salida a di$erentes dispositivos Dpantalla, impresora, archivo de te*to u
otroEC +a sinta*is correcta para esta $unci"n es
fprintf (dispositi4o8 cadena de control8 lista de argumentos)A
es decir, inclu,e un primer argumento que relaciona la salida con un dispositivoC En
realidad, ese primer argumento de&e ser un puntero a una estructura prede$inida en #
llamada )I6E, de la que ha&laremos en el #ap@tulo 12C <e cualquier modo, para
nuestros prop"sitos actuales, nos &asta con identi$icarlo de algKn modo con un
dispositivoC
#omo veremos en su momento, # asocia los dispositivos a unas 1onas o
&K$$ers de memoria denominados canalesC #uando un programa empie1a a ejecutarse
se a&ren autom.ticamente ( canales, entre ellos el asociado a la impresoraC 6 este
dispositivo se le re$erencia mediante la pala&ra stdprnC
%or lo tanto, fprintf() direcciona su salida a la impresora cuando se escri&e de
la $orma
fprintf (stdprn8 cadena de control8 lista de argumentos)A
-odas las dem.s caracter@sticas de fprintf() son id9nticas a las de printf()C
lii
Control de la pantalla de te(to
El control de la pantalla puede esta&lecerse por dos v@asC En primer lugar,
-ur&o # proporciona gran nKmero de $unciones para controlar la pantalla tanto en
modo te*to como en modo gr.$icoC Estudiaremos en este apartado algunas $unciones
de control en modo te*to &.sicasC -odas ellas necesitan que se inclu,a el archivo de
ca&ecera conio.&C )tra $orma de controlar la pantalla es por medio de secuencias de
escape 6>4!C
)unciones de biblioteca
)uncin clrscr()2 Borra la pantalla , sitKa el cursor en la esquina superior
i1quierdaC >o necesita argumentos ni devuelve ningKn valorC
)uncin clreol()2 Borra una l@nea de la pantalla desde la posici"n del cursor
hasta el $inal de dicha l@neaC -ampoco necesita argumentos ni devuelve valor algunoC
)unciones insline() - delline()2 +a $unci"n insline() inserta una l@nea en
&lanco de&ajo de la del cursor, despla1ando el resto una l@nea hacia a&ajoC
6n.logamente, la $unci"n delline() elimina la l@nea en donde est. el cursor,
despla1ando las de de&ajo hacia arri&aC
)unciones goto(-()8 %&ere(() - %&ere-()2 +a $unci"n goto(-() se encarga
del posicionamiento del cursorC 4e escri&e
int fiIa, coIumna;
...
...
gotoxy (coIumna, fiIa);
+as $unciones %&ere(() , %&ere-() devuelven las coordenadas de la posici"n
actual del cursor:
int fiIa, coIumna;
...
...
coIumna = wherex ();
fiIa = wherey ();
En estas 3 $unciones, las varia&les fila , columna de&en declararse de tipo intC
)uncin mo4ete(t()2 #opia te*to de una 1ona de la pantalla a otraC +a sinta*is
de esta $unci"n es
int x1, y1, x2, y2, x3, y3;
...
...
movetext (y1, x1, y2, x2, y3, x3);
liii
siendo:
(18 -1: columna, $ila de la esquina superior i1quierda de la 1ona de la
pantalla a despla1arC
(28 -2: @dem de la esquina in$erior derechaC
(38 -3: columna, $ila de la esquina superior i1quierda de la pantalla a donde
se despla1a el te*toC
+a $unci"n no &orra el te*to de la posici"n originalC <evuelve 2 si alguna
coordenada est. $uera de rango, , 1 en caso contrarioC
)unciones &ig&4ideo()8 lo%4ideo() - norm4ideo()2 +as dos primeras ponen,
respectivamente, el te*to de la pantalla en alta , &aja intensidadC +a $unci"n
norm4ideo() restaura la intensidad de la pantalla al estado en que se encontra&a al
iniciarse el programaC
)unciones te(tcolor()8 te(tbac'ground() - te(tattr()2 +a $unci"n te(tcolor()
esta&lece el color del te*to que se presenta a partir del momento en que se ejecuta la
$unci"nC
textcoIor (coIor_de_carcter);
El par.metro color[de[carcter es un nKmero comprendido entre 2 , 1(C #ada uno
de estos nKmeros tiene asociado un colorC 6dem.s, en el archivo conio.& se de$ine
una macro para cada colorC Esto queda re$lejado en la ta&la siguiente:

GAFOR COFOR HACRO
0 e*ro B"A.L
1 Azul B"MJ
& %erde KRJJ
+ Tur;uesa .NA
, RoOo RJ1
@ 9orado 9AKJTA
A 9arr6n BRPQ
7 Blanco "3KHTKRAN
8 Kris 1ARLKRAN
9 Azul intenso "3KHTB"MJ
10 %erde intenso "3KHTKRJJ
11 Tur;uesa intenso "3KHT.NA
1& RoOo intenso "3KHTRJ1
1+ 9orado intenso "3KHT9AKJTA
1, Amarillo NJ""PQ
1@ Blanco intenso QH3TJ
1&8 (arpadeo B"3L
-eniendo esto en cuenta, para conseguir que un te*to se presente, por ejemplo,
en color verde, previamente a su escritura de&e hacerse
textcoIor (2);
o &ien
liv
textcoIor (GREEN);
4in em&argo, esto no tiene e$ecto si se utili1an las $unciones printf(), puts(),
gets() , putc&ar()C En su lugar, de&en utili1arse las $unciones cprintf(), cputs(),
cgets() , putc&(), respectivamenteC 4igue siendo v.lida la $unci"n getc&e()C
%ara conseguir el parpadeo del car.cter de&e hacerse una operaci"n )' entre
el color , el valor 128 DB+!>?EC %or lo tanto, si queremos presentar un te*to en
amarillo parpadeante de&emos escri&ir
textcoIor (YELLOW | BLINK);
+a $unci"n te(tbac'ground() esta&lece el color de $ondo para todo te*to que
se escri&a en pantalla a continuaci"nC
textbackground (coIor_de_fondo);
siendo color[de[fondo un valor comprendido entre 2 , 5, correspondiente a la ta&la
anteriorC
+a $unci"n te(tattr() esta&lece el &,te de atri&uto completo Dcolor de car.cter,
color de $ondo, parpadeo si3no e intensidad alta3&ajaEC 4e escri&e
textattr (atributo);
donde atributo es un &,te cu,o signi$icado se muestra a continuaci"n
+ $ # 3 2 1 1
: ) ) ) I C C C
donde ### son los &its que codi$ican el color del car.cter, ! es el &it de intensidad,
FFF indican color de $ondo, , % es el &it de parpadeoC +a $orma m.s c"moda de usar
esta $unci"n es la siguiente: se multiplica el nKmero del color de $ondo de la ta&la por
16 , se hace una operaci"n )' con el color de car.cterC 4i adem.s se quiere que el
te*to parpadee, de&e hacerse una operaci"n )' con el valor 128 DB+!>?EC 6s@, para
o&tener un te*to en amarillo parpadeando so&re $ondo a1ul, de&e hacerse:
textattr (YELLOW | BLINK | BLUE * 16);
)uncin te(tmode()2 6signa un determinado modo de v@deo a la pantalla de
te*to:
textmode (modo_de_vdeo);
+os valores permitidos para modo[de[4Gdeo , las macros asociadas se
muestran en la ta&la siguienteC
HODO DE
GKDEO
DESCRIPCIN HACRO
lv
0 Blanco : ne*roD ,0
columnas
BQ,0
1 .olorD ,0 columnas .P,0
& Blanco : ne*roD 80
columnas
BQ80
+ .olorD 80 columnas .P80
7 9onocromo 9PP
01 9odo anterior "AST9P1J
6l asignar un modo de v@deo se iniciali1a la pantallaC
"ecuencias de escape 0<"I
El archivo 6>4!C4Y4 es un controlador de pantalla , teclado que permite
cam&iar la presentaci"n de te*tos , gr.$icos en pantalla, controlar el cursor ,
cam&iar las asignaciones de las teclasC #ada una de estas $unciones se de$ine
mediante una secuencia de esca"e $NS%, que es una cadena de caracteres que
comien1a por los caracteres E"C T, siendo E"C el car.cter E"C0:E, de c"digo
64#!! 25 D233 octalEC Estas secuencias de escape est.n descritas a continuaci"nC
OPERACIN SECUENCIA
DE ESCAPE
DESCRIPCIN
1esplazamiento
s del cursor
JS.HRSRH .oloca el cursor en la posici6n de la
pantalla seTalada con RSR (el primer
nUmero indica la 'ila : el se*undo la
columna)
JS.HRA 9ue!e el cursor R l#neas ?acia arriba
JS.HRB 9ue!e el cursor R l#neas ?acia abaOo
JS.HR. 9ue!e el cursor R columnas ?acia la
derec?a
JS.HR1 9ue!e el cursor R columnas ?acia la
iz;uierda
JS.Hs Kuarda la posici6n actual del cursor
JS.Hu Recupera la posici6n del cursor
pre!iamente *uardada con la secuencia
anterior
Borrado JS.H&V Borra la pantalla : coloca el cursor en la
es;uina superior iz;uierda de la pantalla
JS.HL Borra todos los caracteres desde la
posici6n actual del cursor ?asta el 'inal de
la l#nea
Jstablecer
modo de
*r)'icos
JS.HRSBBBSRm "lama a las 'unciones *r)'icas
especi'icadas mediante los d#*itos RB Jstas
'unciones permanecen acti!as ?asta la
si*uiente aparici6n de esta secuencia de
escapeB "os !alores permitidos para R se
muestran en la tabla de la p)*ina si*uiente
Jstablecer
modo de !#deo
JS.H<R? .ambia el anc?o o el tipo de pantallaB "os
!alores permitidos para R se muestran en
la tabla de la p)*ina si*uiente
JS.H<Rl Restablece el modo utilizando los mismos
lvi
!alores ;ue utiliza la secuencia anteriorD
sal!o el modo 7 ;ue desacti!a el aOuste
autom)tico de l#neaB Jl Ultimo car)cter de
la secuencia es la " minUscula
Reasi*naci6n de
cadenas para el
teclado
JS.HRScadSR
p
(ermite cambiar la de'inici6n de las teclas
a una cadena espec#'icaB Jl s#mbolo R
representa el c6di*o o c6di*os *enerados
por la tecla a reasi*narB ca" es el c6di*o
AS.33 correspondiente a un solo car)cter o
a una cadena entre comillasB
JOemplo 1WX
ESC+=;L==# con!ierte la A en BB
JOemplo &WX
ESC+BL;ALMCFSML'7# Asi*na a la tecla $1
(;ue *enera los c6di*os 0 : @9) la cadena
."S Ounto con (c6di*o 1+)B
%alores permitidos ATR3BMTPS 0 1esacti!a todos los atributos
para R en la 1J TJGTP 1 Alta intensidad acti!ada
secuencia de
escape
, Subra:ado (monitor monocromo)
ESC+NL---LNO @ (arpadeo acti!ado
7 %#deo in!erso acti!ado
8 Pculto acti!ado
.P"PR 1J +0 e*ro
.ARY.TJR +1 RoOo
+& %erde
++ Amarillo
+, Azul
+@ 9a*enta
+A %ioleta
+7 Blanco
.P"PR 1J ,0 e*ro
$P1P ,1 RoOo
,& %erde
,+ Amarillo
,, Azul
,@ 9a*enta
,A %ioleta
,7 Blanco
%alores permitidos 0 ,0F&@ monocromo (teFto)
para R en la 1 ,0F&@ color (teFto)
secuencia de
escape
& 80F&@ monocromo (teFto)
ESC+>NP + 80F&@ color (teFto)
, +&0F&00 color (*r)'icos)
@ +&0F&00 monocromo (*r)'icos)
A A,0F&00 monocromo (*r)'icos)
7 Acti!a aOuste autom)tico de l#nea
1+ +&0F&00 color (*r)'icos)
1, A,0F&00 color (*r)'icos 1A
colores)
1@ A,0F+@0 mono (*r)'icos & colores)
1A A,0F+@0 color (*r)'icos 1A
colores)
17 A,0F,80 mono (*r)'icos & colores)
18 A,0F,80 color (*r)'icos 1A
lvii
colores)
19 +&0F&00 color (*r)'icos &@A
colores)
;na secuencia de escape 6>4! se env@a, por ejemplo, mediante la $unci"n
printf()C #on ello no se visuali1an los caracteres de la secuencia de escape, sino
que se consigue el e$ecto descrito para cada una de ellasC %ero para que estas
secuencias tengan el e$ecto esperado es necesario instalar el controlador
6>4!C4Y4 en el archivo #)>F!=C4Y4 mediante una sentencia <E0!#E o
<E0!#EQ!=QC +a sinta*is de la instalaci"n de este controlador es:
;E]ICE B _unidad:` _ruta` 0<"I."`"
de modo que si el archivo 6>4!C4Y4 est. en el directorio N<)4 de la unidad #:,
en el $ichero #)>F!=C4Y4 de&e ha&er una l@nea
de4ice B c2FdosFansi.s-s
o, si se desea instalar en memoria superior
de4ice&ig& B c2FdosFansi.s-s
0eamos algunos ejemplos que ilustran el uso de estas secuencias de escapeC
:osicionamiento del cursor2 +a secuencia de escape para posicionar el
cursor es
E"C T$AcO ($ M $ila, c M columnaE
%ara situar el cursor en la $ila (, columna 22, se hace
printf ("\033[5;20H");
, produce e*actamente el mismo e$ecto que
gotoxy (20, 5);
>o o&stante para este tipo de operaciones es m.s conveniente de$inir una
$unci"n que reci&a en los par.metros las coordenadas:
pon_cursor (int fiIa, int coIumna)
{
printf ("\033[%d;%dH", fiIa, coIumna);
}
En un programa se llamar@a a esta $unci"n, por ejemplo, mediante
pon_cursor (5, 20);
3orrado de pantalla2 +a secuencia 6>4! que &orra la pantalla es
E"C T2P
lviii
%or tanto, la sentencia
printf ("\033[2J");
produce el mismo e$ecto que la $unci"n de &i&lioteca clrscr()C 4e puede a&reviar la
escritura de esta secuencia mediante una macro como
#define CLS printf ("\033[2J")
, utili1ar en el programa sentencias
CLS;
Ledefinicin de teclas2 /ostraremos el uso de esta secuencia mediante un
ejemplo que asigna a la tecla )1 Dque al ser pulsada genera los c"digos 2 , (E la
cadena de caracteres ;IL C2!: C Esto se consigue con la secuencia
E"C T1A#.AC;IL C2!:CA13p
#on una $unci"n printf() esto se escri&e
printf ("\033[0;59;\"DIR C:/P\";13p");
o tam&i9n
printf ("\033[0;59;%c%s%c;13p", 34, "DIR C:/P", 34);
donde ha, que tener en cuenta que el c"digo 64#!! del car.cter comilla do&le DIE
es 34C
Ledireccionamiento de la E!"
+as operaciones de E34 reali1adas por $unciones re$eridas a la consola
Dprintf(), scanf(), CCCE pueden redirigirse a otros dispositivos mediante los
operadores
> redirecci"n de la salida
= redirecci"n de la entrada
Ledireccin de la salida
4ea el programa de la p.gina 2, compilado , linGado como <)#E>6CEBEC
4i desde el indicador del <)4 escri&imos:
C2F> docena >prn
li*
la $rase I;na docena son 12 unidadesI no se muestra en pantalla, sino que se dirige
al dispositivo prn DimpresoraEC 4e puede tam&i9n redireccionar la $rase a un $ichero
de te*to llamado, por ejemplo, F'64EC-B-, mediante
C2F> edad >frase.t(t
Esta orden crea en el directorio ra@1 un $ichero de te*to llamado F'64EC-B- que
almacena la $rase I;na docena son 12 unidadesIC 4i el $ichero ,a e*iste, se pierde
su contenido anteriorC
#ada ve1 que se redirecciona la salida a un $ichero, 9ste se crea de nuevoC
6s@, la secuencia
C2F> prog1 >fic&.t(t
C2F> prog2 >fic&.t(t
crea un archivo F!#QC-B- que almacena la salida Knicamente de %')=2C 4i se
desea aFadir la salida de un programa a un $ichero e*istente sin destruir su
contenido, se utili1a el operador >>C +a secuencia
C2F> prog1 >fic&.t(t
C2F> prog2 >>fic&.t(t
almacena en F!#QC-B- la salida de am&os programas %')=1 , %')=2C
Ledireccin de la entrada
4ea ahora el programa %!E4C# de la p.gina ( compilado , linGado como
%!E4CEBEC #reemos un $ichero de te*to llamado <6-)C<6- que almacene el
nKmero 3C Esto se consigue desde el indicador del <)4 mediante la secuencia
C2F> cop- con dato.dat
3
Za
C2F>
4i escri&imos
C2F> pies =dato.dat
la sentencia scanf() del programa ,a no lee el dato del tecladoC 6l estar la entrada
redireccionada, lo toma del archivo <6-)C<6-C 0er@amos entonces en pantalla
los mensajes generados por printf()C 6lgo como
H:iesI2
3 pies B 1..2#211 metros
l*
Ledireccin de la entrada - de la salida
4e puede redireccionar a la ve1 tanto la entrada como la salidaC 4i escri&imos
C2F> pies =dato.dat >mensa7es.t(t
no veremos en pantalla nada, , se crea un $ichero de te*to en el directorio ra@1
llamado /E>46]E4C-B- que almacena los mensajes generados por las dos
sentencias printf()C
l*i
E7ercicios
8
1. Escri&e un programa que lea del teclado un c"digo 64#!! Dentero
comprendido entre 2 , 2((E , presente en pantalla el car.cter
correspondienteC
2. Escri&e un programa que lea del teclado un car.cter cualquiera , presenta en
pantalla su c"digo 64#!! en decimal, octal , he*adecimalC
3. Escri&e un programa que lea del teclado dos nKmeros en coma $lotante cu,a
parte entera se asume que no supera 3 d@gitos, , muestre en pantalla su suma
ajustada a la derechaC %or ejemplo, si los nKmeros son 23C6 , 185C(4 el
programa de&e mostrar:
23,62
185,(4
AAAAAAAAAA
211,14
. Escri&e un programa que lea 2 nKmeros enteros de 3 d@gitos e imprima su
productoC %or ejemplo, si los nKmeros son 32( , 426 se presentar. en el
$ormato
32(
* 426
AAAAAAAAAAAA
1(2
6(2
1322
AAAAAAAAAAAA
1384(2
#. +a $echa de %ascua corresponde al primer <omingo despu9s de la primera
+una llena que sigue al equinoccio de %rimavera, , se calcula con las
siguientes e*presiones:
6 M resto de DaFo 3 1E
B M resto de DaFo 3 4E
# M resto de DaFo 3 5E
< M resto de D1 R 6 L 24E 3 32
E M resto de D2 R B L 4 R # L 6 R < L (E 3 5
> M 22 L < L E
8
;tili1ar en todas las salidas a pantalla $unciones de control de la pantalla de te*to o secuencias de escape 6>4! D&orrado de
pantalla, posicionamiento del cursor, colores, etcCE
l*ii
en el que > indica el nKmero del d@a del mes de /ar1o D6&ril si > W 31, en
cu,o caso el d@a es > A 31E correspondiente al <omingo de %ascuaC Escri&e
un programa que acepte un aFo por teclado , muestre en pantalla la $echa del
primer <omingo de %ascua con el $ormato dd3mm3aaaaC
$. Escri&e un programa que lea del teclado los siguientes datos de 2 personas:
nom&re, edad, altura , pesoC El programa enviar. a impresora un listado con
el $ormato:
>)/B'E E<6< 6+-;'6 %E4)
********************** ** **,* ***,**
********************** ** **,* ***,**
/edia: **,** **,** ***,**
#
"entencias de control
6a estructura if
+a estructura if adopta una de las dos $ormas siguientes:
if (e&"resin) sentencia'
o &ien
if (e&"resin) sentencia'
else sentencia'
en donde e&"resin es una sentencia que se evalKa como verdadera Ddevuelve un
valor no nuloE o $alsa Ddevuelve ceroEC +a pala&ra sentencia puede ser una sentencia
simple terminada con un punto , coma, o un grupo de sentencias encerradas entre
llaves STC 6lgunos ejemplos v.lidos de sentencias if son:
if (x > 0) puts ("POSITIVO");
if (x) puts ("Verdadero");
eIse puts ("FaIso");
if (c >= 'a' && c <= 'z') {
puts ("La variabIe c aImacena un carcter aIfabtico");
puts ("EI carcter es una Ietra minscuIa");
}
l*iii
if (num <= 40000) {
printf ("\nOctaI: %o", num);
printf ("\nHexadecimaI: %X", num); }
eIse {
puts ("EI nmero es mas grande que 40000");
printf ("Su vaIor es %u", num);
}
+as estructuras if pueden anidarse sin m.s que tomar un m@nimo de
precaucionesC En las sentencias
if (x)
if (y) puts ("1");
eIse puts ("2");
el else est. asociado a if (-)C # siempre asocia los else al if m.s cercano que no tenga
,a un elseC %ara que en la sentencia anterior el else se asocie a if ((), ha, que colocar
adecuadamente las llaves STC
if (x) {
if (y) puts ("1"); }
eIse puts ("2");
En # tam&i9n se dispone de la estructura
if (condicin1) sentencia1A
else if (condicin2) sentencia2A
else if (condicin3) sentencia3;
...
else sentenciaNA
que va evaluando, sucesivamente, condicin1, condicin2, CCC #uando encuentra una
cierta, se ejecuta la sentencia correspondiente , se $inali1a el ifC 4i ninguna es cierta se
ejecuta la sentencia que acompaFa al else Dque no es o&ligatorioEC #omo siempre,
sentencia1, sentencia2, CCC, pueden ser una sola sentencia o un grupo de ellas, en cu,o
caso se encierran entre llaves STC
El siguiente programa usa esta estructura para determinar si un nKmero es
positivo, negativo o ceroC
#incIude <stdio.h>
#incIude <conio.h>
void main ()
{
int n;
cIrscr ();
printf ("TecIee un nmero entero: ");
scanf ("%d", &n);
if (n > 0) puts ("Positivo");
eIse if (n < 0) puts ("Negaivo");
eIse puts ("Cero");
}
l*iv
6a estructura s%itc&
+a estructura s%itc& inspecciona una varia&le , la va comparando con una
lista de constantesC #uando encuentra una coincidencia, se ejecuta la sentencia o
grupo de sentencias asociadoC +a $orma de s%itc& es
s%itc& (variable) ?
case cte12 sentenciaA
brea'A
case cte22 sentenciaA
brea'A
...
...
default2 sentenciaA
@
donde variable es una varia&le o cualquier e*presi"n que devuelva un valorC +a
sentencia s%itc& compara la varia&le con cte1, cte2, CCC, , si encuentra una
coincidencia, ejecuta la sentencia correspondienteC %or sentencia de&emos entender
tanto una sentencia simple como un grupo de sentencias Dque, en este caso, no se
encierran entre llavesEC 4i no se encuentra ninguna coincidencia se ejecuta la secci"n
default Dque no es o&ligatoriaEC
El siguiente segmento de programa muestra c"mo se utili1a la sentencia
s%itc&C
char c;
...
...
c = getche ();
switch (c) {
case 'a': funcion_a ();
break;
case 'b': funcion_b ();
break;
defauIt: puts ("No se ha puIsado ni a ni b");
}
Fij9monos que la sentencia s%itc& &usca coincidencias e*actas, por lo que no
es una alternativa a programas como el de la p.gina anterior, ,a que >) E4-a
%E'/!-!<) imponer condiciones de desigualdadC >o es correcto, por tanto
int n;
...
...
switch (n) {
case > 0: puts ("Positivo");
break;
case < 0: puts ("Negativo");
break;
defauIt: puts ("Cero");
l*v
}
+a sentencia brea' es opcionalC #uando se encuentra, provoca la salida de
s%itc&C En caso contrario continua la siguiente secuencia case o default aunque no
se cumpla la condici"nC %ara aclarar esto, tomemos el siguiente ejemplo:
int c;
...
...
scanf ("%d", &c);
switch (c) {
case 1:
case 2: Funcion2 ();
case 3: Funcion3 ();
break;
case 4: Funcion4_1 ();
Funcion4_2 ();
break;
case 5: Funcion_5 ();
defauIt: FuncionX ();
}
+a siguiente ta&la indica qu9 $unci"n se ejecuta dependiendo del valor de cC
Si &! #ul&a S! !Q!cu3a
1 $uncion&() : $uncion+()
& $uncion&() : $uncion+()
+ $uncion+()
, $uncion,Z1() :
$uncion,Z&()
@ $uncion@() : $uncionG()
cual;uier otra
cosa
$uncionG()
+a sentencia default es opcionalC #uando no est. no se ejecuta ninguna acci"n
al $allar todas las coincidenciasC 4implemente se a&andona el s%itc& sin hacer nadaC 4i
ha, sentencia default, el &loque de sentencias asociado se ejecuta cuando $allan todas
las comparaciones o no ha, un brea' anterior que lo impidaC +as sentencias s%itc&
pueden anidarse, con lo que se permiten estructuras del tipo:
switch (m) {
case 1: Funcion1 ();
break;
case 2: switch (n) {
case 21: Funcion21 ();
break;
defauIt: switch (p) {
l*vi
case 31: Funcion31 ();
break;
case 31: Funcion32 ();
}
}
break;
defauIt: FuncionX ();
}
3ucles
E*isten en # tres tipos de &ucles: for, %&ile , do!%&ileC
3ucles for
El &ucle for es mu, potente , $le*i&leC 6dem.s de permitir las mismas
operaciones que cualquier for de otros lenguajes, tiene caracter@sticas que lo
di$erencian claramente de ellosC En su $ormato tradicional este &ucle tiene la $orma
for (iniciali(acinA condicinA incremento) cuer"o_del_bucle;
0emos que for tiene tres secciones: iniciali(acin, en d"nde se da un valor
inicial a una varia&le de control del &ucleO condicin, que es una e*presi"n que
devuelve un valor verdadero o $also, , hace que el &ucle se repita mientras sea ciertaO
e incremento, en d"nde se determina la cuant@a del incremento o decremento de la
varia&le de controlC +as tres secciones est.n separadas por punto , comaC El cuer"o
del bucle puede estar $ormado por una o por varias sentenciasC En este Kltimo caso
de&en encerrarse entre llaves STC El $lujo de sentencias en este &ucle es el siguiente:
iniciali(acin
F6+46
condicin
0E'<6<E'6
cuer"o_del_bucle
incremento
l*vii
Fij9monos que el for se sigue ejecutando /!E>-'64 la condicin sea
verdaderaC
0eamos un par de ejemplosC En la siguiente secuencia se muestran en pantalla
los nKmeros del 1 al 12 , sus cuadradosC
register int i;
...
...
for (i = 1; i <= 10; i++) {
printf ("\nVaIor de i: %d", i);
printf ("\nVaIor de i
2
: %d", i * i);
}
En esta, se muestran en pantalla las letras ma,Ksculas de la 6 a la bC
char Ietra;
...
...
for (Ietra = 'A'; Ietra <= 'Z'; Ietra++) printf ("\n%c", Ietra);
%uede ponerse un incremento3decremento di$erente de 1C El siguiente ejemplo
muestra en pantalla los nKmeros pares comprendidos entre 1 , 122,
descendentemente:
register int i;
...
...
for (i = 100; i >= 1; i = i - 2) printf ("\n%d", i);
Estudiaremos ahora algunas $ormas de for que se apartan del uso tradicionalC
Es posible tener ms de una 4ariable de control del bucle2 En el &ucle for
las secciones de iniciali(acin e incremento pueden tener, a su ve1, su&secciones, en
cu,o caso van separadas por el operador secuencial D8EC ;n ejemplo es
register int i, j;
...
...
for (i = 0, j = 1; i + j < N; i++, j++) printf ("\n%d", i + j);
que visuali1a los > primeros nKmeros imparesC >o de&e con$undirse esta sentencia
con un anidamiento de &ucles forC ;n anidamiento tiene el siguiente aspecto:
register int i, j;
...
...
for (i = 0; i <= 100; i++) {
...
for (j = 0; j <= 100; j++) {
cuerpo;del;/ucle<
}
...
}
l*viii
6a condicin de salida del bucle no tiene por KuW referirse a la 4ariable de
control2 Esto queda ilustrado en el siguiente ejemplo:
char a;
register int i;
...
...
for (i = 1; a != 's'; i++) {
printf ("\n%d", i);
a = getch ();
}
En este ejemplo se van mostrando en pantalla los nKmeros 1, 2, CCC hasta que se teclee
el car.cter sC
El bucle for puede no tener cuerpo2 Esta caracter@stica permite crear retardos
en un programaC El &ucle
register int i;
...
...
for (i = 1; i <= 100; i++);
provoca un retardo de 122 ciclosC
El bucle for puede tener 4acGa cualKuier seccin2 En un &ucle for puede
$altar una, dos o las tres seccionesC %or ejemplo, es correcto escri&ir
register int i;
...
...
for (i = 0; i != 10; ) { /* FaIta Ia 3 seccin (incremento) */
scanf ("%d", &i);
printf ("\n%d", i);
}
que va mostrando en pantalla los valores que se tecleen, $inali1ando al teclear el
nKmero 12 Dque tam&i9n se visuali1aEC
-am&i9n es correcto un &ucle como
for ( ; ; ) {
cuerpo;del;/ucle<
}
que es un &ucle sin $inC Estudiaremos m.s adelante, en este mismo cap@tulo, c"mo
a&andonar un &ucle in$initoC
CualKuier e(presin 4lida en C puede estar en cualKuier seccin de un
bucle for2 +a $orma del &ucle for no tiene que ajustarse necesariamente a la mostrada
en la p.gina 65C En realidad la $orma correcta es:
for (e&"resin1A e&"resin2A e&"resin3) cuer"o del bucleA
siendo e&"resinN cualquier e*presi"n v.lida #C %odemos decir que, en general, el
$lujo de sentencias de un &ucle for es:
l*i*
e&"resin1
F6+46
e&"resin2
0E'<6<E'6
cuer"o_del_bucle
e&"resin3
6clararemos esto con el programa siguiente:
#incIude <stdio.h>
void main ()
{
int t;
for (mensaje (); t = Iee_numero (); cuadrado (t));
}
mensaje ()
{
printf ("\nTecIee un nmero (0 finaIiza): ");
}
Iee_numero ()
{
int n;
scanf ("%d", &n);
return n;
}
cuadrado (int x)
{
printf ("\nEI cuadrado es %d", x * x);
}
0amos a $ijarnos en el &ucle for de la $unci"n main() , e*plicarlo mediante el
diagrama de $lujo de la p.gina anteriorC
1C 4e ejecuta la $unci"n mensa7e() que muestra la cadena I-eclee un nKmero
D2 $inali1aE: IC D!/%)'-6>-E: Esta $unci"n s"lo se ejecuta esta ve1EC
l**
2C 4e evalKa la e*presi"n t B lee[numero(), es decir, lee[numero() captura un
nKmero entero del teclado , lo devuelve almacen.ndolo en tC
2C1 4i la e*presi"n t B lee[numero () devuelve F6+4), es decir, si se ha
tecleado 2, $inali1a el &ucleC
2C2 En caso contrario continKa el &ucleC
3C 4e ejecuta el cuerpo del &ucleC En este caso, dado que for $inali1a con punto
, coma, no ha, cuerpo del &ucleC
4C 4e ejecuta la $unci"n cuadrado(t) que visuali1a el cuadrado del nKmero
tecleadoC
(C 4e vuelve al paso 2C
El bucle %&ile
-iene la $orma
%&ile (e&"resin) cuer"o_del_bucleA
siendo e&"resin cualquier e*presi"n # v.lidaC El cuer"o_del_bucle, puede estar
$ormado por una sentencia sencilla o por un &loque de sentencias, en cu,o caso, se
encierran entre llaves STC El $lujo de sentencias es
F6+46
e&"resin
0E'<6<E'6
cuer"o_del_bucle
%or lo tanto, en el &ucle %&ile el cuer"o_del_bucle se repite mientras
e&"resin se evalKe como ciertaC 0eamos algunos ejemplosC
char c;
...
...
whiIe (c != 's' && c != 'n') c = getche ();
l**i
En esta sentencia se solicita un car.cter del teclado mientras no se teclee el
car.cter n ni el car.cter sC #uando se teclea alguno de estos caracteres, se almacena
en c , se a&andona el &ucleC
El siguiente ejemplo es un caso de &ucle %&ile sin cuerpoC
whiIe (getch () != 13);
El programa est. detenido en esta sentencia hasta que se teclee Dc"digo 64#!! 13EC
El siguiente programa utili1a un &ucle %&ile para solicitar del usuario que
adivine un nKmeroC
#incIude <stdio.h>
#incIude <stdIib.h>
void main ()
{
int num;
int n = 0;
randomize (); // Las funciones randomi(e12 7 random12
permien
num = random (20) + 1; // =enerar n>meros aleaorios
whiIe (n != num) {
printf ("\nTecIee un nmero entre 1 y 20: ");
scanf ("%d", &n);
if (n == num) puts ("ACERTASTE);
eIse if (n < num) puts ("TU NMERO ES MENOR");
eIse puts ("TU NMERO ES MAYOR");
}
}
'especto del &ucle %&ile es conveniente tener presente lo siguiente:
El cuerpo del &ucle no se ejecutar. >;>#6 si la primera ve1 no se cumple
la condici"nC
El &ucle puede ser !>F!>!-) si no se modi$ican adecuadamente las
varia&les de la condici"n dentro del &ucleC
El bucle do!%&ile
-iene la $orma
do
cuer"o_del_bucleA
%&ile (e&"resin)A
l**ii
siendo sentencia una sentencia simple o un grupo de sentencias encerradas entre
llaves ST, , e&"resin cualquier e*presi"n v.lida #C El $lujo de ejecuci"n es el
siguiente:
cuer"o_del_bucle
0E'<6<E'6
e&"resin
F6+46
%or lo tanto, en un &ucle do!%&ile el cuer"o_del_bucle se ejecuta al menos una
ve1, incluso aunque e&"resin se evalKe como $alsa, puesto que la evaluaci"n se hace
al $inal, justo lo contrario del &ucle %&ile, en el que la evaluaci"n de e&"resin se
hace al principioC
En el siguiente ejemplo se solicita un car.cter del teclado hasta que se pulse
cualquiera de los caracteres P4P o P>PC
#incIude <stdio.h>
void main ()
{
char tecIa;
do {
printf ("\nPuIse S o N: ");
tecIa = getch ();
} whiIe (tecIa != 'S' && tecIa != 'N');
}
"entencia brea'
Es la misma sentencia que hemos visto para $inali1ar los case de la sentencia
s%itc&C %ero adem.s permite $or1ar la salida inmediata de un &ucle Dfor, %&ile o
do!%&ileE en cualquier momento, ignorando el resto de sentenciasC 0eamos un
ejemplo:
#incIude <stdio.h>
void main ()
l**iii
{
int n;
for ( ; ; ) {
printf ("\nTecIee un nmero: ");
scanf ("%d", &n);
if (!n) break;
printf ("\nEI cuadrado es %d", n * n);
}
}
En este ejemplo, el &ucle for se ejecutar@a sin $in a no ser por la sentencia
if (!n) break; ..Es lo mismo *ue if (n !) "r#a$%
4e van solicitando nKmeros por teclado , visuali1ando sus cuadrados hasta que se
teclee un 2 DXn se evaluar@a como ciertoE, en cu,o caso se ejecuta la sentencia brea',
que provoca la salida inmediata del &ucle sin que se ejecute la sentencia printf del
$inalC
"entencia continue
Esta sentencia se utili1a en los &ucles for, %&ile , do!%&ileC #uando se ejecuta
$uer1a un nuevo ciclo del &ucle, salt.ndose cualquier sentencia posteriorC %or
ejemplo, el &ucle
int i, n;
...
...
for (i = 1; i <= 100; i++) {
n = i / 2;
if (i == 2 * n) continue;
printf ("\n%d", i);
}
muestra en pantalla s"lo los nKmeros impares, puesto que para los nKmeros pares la
e*presi"n i BB 2 9 n se evalKa como cierta, ejecut.ndose la sentencia continue que
$uer1a de inmediato un nuevo ciclo del &ucleC
El siguiente programa muestra como actKa la sentencia continue en un &ucle
do!%&ileC
#incIude <stdio.h>
#incIude <conio.h>
void main ()
{
int n;
int positivos = 0;
l**iv
cIrscr ();
do {
printf ("\nTecIea un nmero (-99 finaIiza): ");
scanf ("%d", &n);
if (n <= 0) continue;
positivos++;
} whiIe (n != -99);
printf ("\nHas tecIeado %d nmeros positivos", positivos);
}
+a sentencia positi4osQQ s"lo se ejecuta cuando n es un nKmero positivoC 4i n
es negativo o vale 2, se ejecuta continue que $uer1a una nueva evaluaci"n de la
condici"n de salida del &ucleC
EtiKuetas - sentencia goto
En # e*iste la sentencia de salto incondicional goto que $uer1a un salto del
programa a una l@nea identi$icada por una etiquetaC +a etiqueta se de$ine con un
identi$icador v.lido #, seguido por dos puntos D:EC
goto etiuetaA
CCC
CCC
etiueta2 sentenciaA
CCC
CCC
+a etiueta puede estar antes o despu9s del goto, pero siempre en la misma
$unci"nC
'ealmente, en lenguajes con su$icientes estructuras de control Dcomo #E no
suelen presentarse situaciones que hagan necesaria la sentencia gotoC 4in em&argo, en
alguna ocasi"n puede ser conveniente, &ien porque la velocidad de proceso es
importante Dun salto con goto es m.s r.pido que otro tipo de controles de
&i$urcaci"nE, o &ien porque su uso clari$ica el c"digoC El caso m.s ha&itual es la salida
de varios niveles de anidamientoC
for (...) {
whiIe (...) {
for (...) {
...
...
if (...) goto saIir;
...
...
}
}
}
saIir: ...
l**v
...
En este ejemplo, la Knica alternativa a goto ser@a la reali1aci"n de varias
compro&aciones en cada &ucle que $or1ase sentencias brea', lo cual har@a m.s
ilegi&le el c"digoC
)uncin e(it()
Esta $unci"n permite la $inali1aci"n del programa en cualquier punto del mismoC
<evuelve el control al sistema operativo o a otro proceso padre, enviando un valor de
retornoC >ecesita la inclusi"n del archivo de ca&ecera process.&, por medio de una
sentencia #includeC
4i en un programa escri&imos
if (condicin) exit (0);
se produce el $inal del programa cuando condicin es cierta, en cu,o caso se
devuelve el valor 2 al proceso padreC
El programa que se muestra a continuaci"n D4!>)C#E ser. ejecutado desde un
archivo B6- Dproceso padreEC El programa 4!>) pasar. un valor de retorno al
proceso padre por medio de la $unci"n e(it()C El proceso padre inspecciona este valor
de retorno mediante E'')'+E0E+C
., Pro=rama ?@NO0-A Admie por eclado el carBcer CsC o el carBcer CnC0 En el primer caso
1CsC2 enre=a un &alor de reorno 5
En el se=undo caso 1CnC2 enre=a un &alor de reorno 8 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
void main ()
{
char Ietra;
do
Ietra = getch ();
whiIe (Ietra != 's' && Ietra != 'n');
if (Ietra == 's') exit (1);
exit (0);
printf ("\nFin deI programa"); ..Esa senencia no se eDecua nunca
}
l**vi
#ompilamos , enla1amos este programa como 4!>)CEBE , lo incluimos en un
archivo por lotes como el siguiente:
@ECHO OFF
ECHO PuIsa S N
SINO
IF ERRORLEVEL == 1 GOTO SI
GOTO NO
:SI
ECHO PuIsaste S
GOTO FIN
:NO
ECHO PuIsaste NO
:FIN
@ECHO ON
Este archivo visuali1a el mensaje I%ulsaste 4cI cuando en 4!>) se teclea el
car.cter s, , visuali1a el mensaje I%ulsaste >)I si en 4!>) se teclea el car.cter nC En
ningKn caso se visuali1a el mensaje IFin del programaI de la Kltima l@nea de 4!>)C#
l**vii
E7ercicios
1. Escri&e un programa que asigne una cali$icaci"n literal a un estudiante, &asada
en la siguiente ta&la de puntuaci"n:
8C( a 12 4o&resaliente
5 a 8C( >ota&le
6 a 5 Bien
( a 6 4u$iciente
3C( a ( !nsu$iciente
2 a 3C( /u, de$iciente
El programa capturar. un valor num9rico del teclado , visuali1ar. la
cali$icaci"n correspondienteC +os suspensos se mostrar.n en amarillo
parpadeando so&re $ondo rojo, el so&resaliente en amarillo so&re $ondo a1ul, ,
el resto en negro so&re $ondo verdeC
2. Escri&e un programa para determinar si un atleta es seleccionado para correr
una marat"nC %ara seleccionar a un corredor, de&e ha&er terminado una
marat"n anterior en un determinado tiempoC +os tiempos de cali$icaci"n son
1(2 minutos para hom&res menores de 42 aFos, 15( minutos para hom&res
ma,ores de 42 aFos, , 182 minutos para mujeresC +os datos a introducir son:
se*o DQ3/E, edad , tiempo e$ectuado en su anterior marat"nC El programa
visuali1ar. el mensaje I4eleccionadoI o I>o seleccionadoIC
3. +os empleados de una $.&rica tra&ajan en dos turnos: diurno , nocturnoC 4e
desea calcular el jornal diario de acuerdo al siguiente &aremo:
aE +as horas diurnas se pagan a 1222 pesetasC
&E +as horas nocturnas se pagan a 1622 pesetasC
cE #aso de ser domingo, la tari$a se incrementar. en 422 pesetas el turno
diurno , en 622 el nocturnoC
. Escri&e un programa que calcule e imprima la suma de los pares , de los
impares comprendidos entre dos valores 0 , 3 que se introducen por teclado
D0 = 3EC
#. Escri&e un programa que calcule (
n
, siendo ( , n dos nKmeros enteros que se
introducen por tecladoC
$. Escri&e un programa que calcule el $actorial de un nKmero entero positivo que
se introduce por tecladoC
+. Escri&e un programa que encuentre el primer valor < para el que la suma
l**viii
1 L 2 L 3 L CCC L >
e*cede a un valor , que se introduce por tecladoC
*. Escri&e un programa que calcule el primer elemento de la serie de Fi&onacci
que sea ma,or o igual que un valor introducido por tecladoC +a serie de
Fi&onacci se de$ine mediante:
a
2
M a
1
M 1 a
n
M a
nA1
L a
nA2
.. El valor de puede calcularse mediante la serie
M 4 R D 1 A 133 L 13( A 135 L 13 CCCE
Escri&e un programa que calcule el valor de C %ara elegir el nKmero de
t9rminos de la serie adopta el criterio de que la di$erencia a&soluta entre el valor
real de D3C141(2E , el valor calculado sea menor que 12
A3
C #rea una $unci"n
que devuelva el valor a&soluto de una e*presi"nC
$
)unciones
Introduccin
;na de las $ormas m.s adecuadas de resolver un pro&lema de programaci"n
consiste en descomponerlo en su&pro&lemasC 6 cada uno de ellos se le asocia una
$unci"n que lo resuelve, de tal modo que la soluci"n del pro&lema se o&tiene por
medio de llamadas a $uncionesC 6 su ve1, cada $unci"n puede descomponerse en
su&$unciones que realicen tareas m.s elementales, intentando conseguir que cada
$unci"n realice una , s"lo una tareaC
En +enguaje # una $unci"n se de$ine de la siguiente $orma:
tipo <ombre)uncin (parmetros formales)
?
...
cuerpo de la funcin
...
@
l**i*
El tipo es el tipo de dato que devuelve la $unci"n por medio de la sentencia
return cu,o estudio se adelant" en la p.gina 8C #uando no se especi$ica un tipo, se
asume que el tipo devuelto es intC El <ombre)uncin es un identi$icador v.lido en
#C Es el nom&re mediante el cual se invocar. a la $unci"n desde main() o desde otras
$uncionesC +os parmetros formales son las varia&les locales mediante las cuales la
$unci"n reci&e datos cuando se le invocaC <e&en ir encerrados entre par9ntesisC
!ncluso si no ha, par.metros $ormales los par9ntesis de&en aparecerC +a siguiente
$unci"n devuelve el ma,or de dos nKmeros enteros:
int mayor (int x, int y)
{
int max;
if (x > y) max = x;
eIse max = y;
return max;
}
6l manejar $unciones en # de&emos tener en cuenta que a una $unci"n s"lo se
puede acceder por medio de una llamadaC >unca se puede saltar de una $unci"n a otra
mediante una sentencia gotoC -ampoco est. permitido declarar una $unci"n dentro de
otraC
En #, a di$erencia de otros lenguajes, como %ascal, no e*iste distinci"n entre
$unciones , procedimientosC %or ello, una $unci"n puede estar o no dentro de una
e*presi"nC 4i la $unci"n devuelve un valor, son v.lidas sentencias del tipo:
a = b * funcion (c, d);
%ero tam&i9n podemos encontrar $unciones solas en una l@nea de programa,
funcion (a, b, c);
incluso aunque la $unci"n devuelva algKn valorC En ese caso la $unci"n reali1ar@a la
tarea encomendada , el valor devuelto se perder@aC Esto no provoca ningKn errorC
%or Kltimo, hemos de tener en cuenta que, aunque una $unci"n puede $ormar
parte de una e*presi"n compleja, nunca se le puede asignar un valorC %or tanto, es
incorrecto escri&ir sentencias como
funcion () = variabIe;
que ser@a tan improcedente como escri&ir
5 = variabIe;
El Knico m9todo para que una $unci"n reci&a valores es por medio de los
par.metros $ormalesC
l***
0rgumentos de funciones
+os par.metros $ormales son varia&les locales que se crean al comen1ar la
$unci"n , se destru,en al salir de ellaC 6l hacer una llamada a la $unci"n los
par.metros $ormales de&en coincidir en tipo , en nKmero con las varia&les utili1adas
en la llamada, a las que denominaremos argumentos de la funcinC 4i no coinciden,
puede no detectarse el errorC Esto se evita usando los llamados "rototi"os de
funciones que estudiaremos m.s adelante, en este cap@tuloC
+os argumentos de una $unci"n pueden ser:
valores Dllamadas por valorE
direcciones Dllamadas por re$erenciaE
6lamadas por 4alor
En las llamadas por valor se hace una copia del valor del argumento en el
par.metro $ormalC +a $unci"n opera internamente con estos KltimosC #omo las
varia&les locales a una $unci"n D, los par.metros $ormales lo sonE se crean al entrar a
la $unci"n , se destru,en al salir de ella, cualquier cam&io reali1ado por la $unci"n en
los par.metros $ormales no tiene ningKn e$ecto so&re los argumentosC 6claremos esto
con un ejemploC
#incIude <stdio.h>
void main ()
{
int a = 3, b = 4;
intercambia (a, b);
printf ("\nVaIor de a: %d - VaIor de b: %d", a, b);
}
void intercambia (int x, int y)
{
int aux;
aux = x;
x = y;
y = aux;
}
+a salida de este programa es:
l***i
]alor de a2 3 S ]alor de b2
es decir, >) intercam&ia los valores de las varia&les a , bC #uando se hace la llamada
intercambia (a, b);
se copia el valor de a en (, , el de b en -C +a $unci"n tra&aja con ( e -, que se
destru,en al $inali1ar, sin que se produ1ca ningKn proceso de copia a la inversa, es
decir, de ( e - hacia a , bC
6lamadas por referencia
En este tipo de llamadas los argumentos contienen direcciones de varia&lesC
<entro de la $unci"n la direcci"n se utili1a para acceder al argumento realC En las
llamadas por re$erencia cualquier cam&io en la $unci"n tiene e$ecto so&re la varia&le
cu,a direcci"n se pas" en el argumentoC Esto es as@ porque se tra&aja con la propia
direcci"n de memoria, que es Knica, , no ha, un proceso de creaci"n3destrucci"n de
esa direcci"nC
6unque en # todas las llamadas a $unciones se hacen por valor, pueden
simularse llamadas por re$erencia utili1ando los operadores J Ddirecci"nE , 9 Den la
direcci"nEC /ediante J podemos pasar direcciones de varia&les en lugar de valores, ,
tra&ajar internamente en la $unci"n con los contenidos, mediante el operador 9C
El siguiente programa muestra c"mo se puede conseguir el intercam&io de
contenido en dos varia&les, mediante una $unci"nC
#incIude <stdio.h>
void main ()
{
int a = 3, b = 4;
intercambio (&a, &b);
printf ("\nVaIor de a: %d - VaIor de b: %d", a, b);
}
void intercambio (int *x, int *y)
{
int aux;
aux = *x;
*x = *y;
*y = aux;
}
Este programa 4c intercam&ia los valores de a , b, , muestra el mensaje
l***ii
]alor de a2 S ]alor de b2 3
6dem.s, a di$erencia del de la p.gina 83, tra&aja con direccionesC #omo veremos en
el siguiente cap@tulo, en la declaraci"n
void intercambio (int *x, int *y);
los par.metros ( e - son unas varia&les especiales, denominadas punteros, que
almacenan direcciones de memoriaC En este caso, almacenan direcciones de enterosC
]alores de retorno de una funcin
#omo ,a vimos, de una $unci"n se puede salir de dos $ormas distintas: &ien
porque se IencuentraI la llave @ que cierra la $unci"n, &ien porque se ejecuta una
sentencia returnC En este Kltimo caso la $orma de la sentencia puede ser cualquiera de
las siguientes:
return constanteA
return variableA
return e&"resinA
donde e&"resin puede, por claridad, ir entre par9ntesisC El valor devuelto por return
de&e ser compati&le con el tipo declarado para la $unci"nC
#omo vimos al principio del cap@tulo, si a una $unci"n no se le asigna ningKn
tipo devuelve un valor de tipo int, por lo que de&e tener una sentencia return de
salida que devuelva un enteroC 4in em&argo, la ausencia de esta sentencia s"lo
provoca un barning en la compilaci"nC <e cualquier manera, si una $unci"n no
devuelve ningKn valor Dno ha, sentencia returnE lo correcto es declararla del tipo
4oidC
-ampoco es necesario declarar $unciones de tipo c&ar, pues # hace una
conversi"n limpia entre los tipos c&ar e intC
:rototipos de funciones
#uando una $unci"n devuelve un tipo no entero, antes de utili1arla, ha, que
Ihac9rselo sa&erI al resto del programa usando los prototipos de funcionesC ;n
prototipo de $unci"n es algo que le indica al compilador que e*iste una $unci"n , cu.l
es la $orma correcta de llamarlaC Es una especie de IplantillaI de la $unci"n, con dos
cometidos:
identi$icar el tipo devuelto por la $unci"nC
l***iii
identi$icar el tipo , nKmero de argumentos que utili1a la $unci"nC
+a $orma de de$inir un prototipo de $unci"n es:
tipo <ombre)uncin (lista de tipos)A
Entre par9ntesis se ponen los tipos de los argumentos separados por comas Dno
es necesario poner el nom&reE en el mismo orden en el que de&en estar en la llamadaC
6s@, un prototipo como el siguiente
fIoat EjempIo (int, char);
indica que el programa va a utili1ar una $unci"n llamada E7emplo que devuelve,
mediante una sentencia return, un valor de tipo float, , reci&e dos valores en sus
argumentos: el primero es un valor entero , el segundo un car.cterC -am&i9n es un
prototipo v.lido
fIoat EjempIo (int x, char y);
En un programa, los prototipos de $unciones se sitKan antes de la $unci"n
main()C 6 continuaci"n se muestra un programa que de$ine un prototipo de $unci"nC
#incIude <stdio.h>
fIoat muItipIica (fIoat, fIoat); ., Prooipo de la funcin
mu&'i(&ica() ,.
main ()
{
fIoat a, b, totaI;
printf ("\nTecIee dos nmeros: ");
scanf ("%f %f", &a, &b);
totaI = muItipIica (a, b);
printf ("\nEI producto de ambos es %f", totaI);
}
fIoat muItipIica (fIoat m, fIoat n)
{
return m * n;
}
En este programa si en lugar de la l@nea
totaI = muItipIica (a, b);
escri&i9semos
totaI = muItipIica (a);
l***iv
el compilador, alertado por el prototipo, in$ormar@a del errorC
-anto en los prototipos como en las declaraciones de $unciones, las re$erencias
a cadenas de caracteres se reali1an mediante la e*presi"n c&ar 9C El signi$icado de
esta e*presi"n se entender. m.s claramente en el pr"*imo cap@tuloC 6s@, el prototipo
de una $unci"n que devuelve una cadena de caracteres , tiene como Knico argumento
una cadena de caracteres es
c&ar 9)uncion (c&ar 9)A
#uando una $unci"n tiene un nKmero varia&le de argumentos, se especi$ica por
medio de 3 puntos suspensivosC Este es el caso de la $unci"n printf() cu,o prototipo
es:
int printf (const char *, ...);
+a pala&ra reservada const aqu@ signi$ica que la cadena re$erida con c&ar 9 puede
ser, &ien una varia&le, como en
printf (cadena);
o &ien una constante, como en
printf ("Cadena constante");
%ara indicar Hque una $unci"n no tiene argumentos se pone la pala&ra
reservada 4oid entre los par9ntesisC <el mismo modo, se indica con 4oid que una
$unci"n no devuelve ningKn valor Dno ha, sentencia returnEC %or ejemplo, la $unci"n
de prototipo
void funcion (void);
no devuelve nada ni reci&e valoresC
#uando deseamos que una $unci"n devuelva una cadena de caracteres, el
prototipo se escri&e
c&ar 9funcion (lista de parmetros)A
En el pr"*imo cap@tulo estudiaremos m.s pro$undamente el signi$icado de la
e*presi"n c&ar 9C
-odos los programas que utilicen $unciones de la &i&lioteca est.ndar de&en
incluir sus prototiposC Estos prototipos , otras de$iniciones usadas por las $unciones
est.n en los archivos de ca&ecera como stdio.&, por lo que el programa de&er. tener
las sentencias #include necesariasC
Lecursi4idad
l***v
+a recursividad es un concepto de l"gica matem.tica que consiste en de$inir
una $unci"n en t9rminos de s@ mismaC %or ejemplo, la de$inici"n del $actorial de un
nKmero es una de$inici"n recursiva:
nX B n c (n S 1)X
1X B 1
En programaci"n una $unci"n es recursiva si puede llamarse a s@ mismaC >o
todos los lenguajes permiten la recursividadC ;na de$inici"n recursiva de una $unci"n
requiere dos partes:
;na condicin de salida o clusula de escapeC
;n paso en el que los valores restantes de la $unci"n se de$inen en &ase a
valores de$inidos anteriormenteC
+a recursividad es una alternativa a la iteraci"nC 4in em&argo, en general, una
soluci"n recursiva es menos e$iciente, en t9rminos de tiempo, que una soluci"n
iterativaC 6dem.s, las soluciones recursivas utili1an mucha memoria de pila, pues
cada llamada a la $unci"n hace que se copie en la pila Dcada ve1E todo el juego de
argumentosC Esto puede crear pro&lemas cuando se llega a niveles pro$undos de
recursi"nC #"mo decidir cu.ndo un pro&lema se resuelve recursivamente o mediante
iteraciones depende del pro&lema en s@C +a soluci"n recursiva suele ser la m.s sencilla,
, de&e elegirse si no ha, grandes requerimientos de velocidad del proceso ni
pro&lemas con el tamaFo de la memoriaC En otro caso de&emos elegir la soluci"n
iterativa, mucho m.s r.pida, aunque a menudo m.s complejaC +a siguiente $unci"n
resuelve recursivamente el c.lculo del $actorial
Iong factoriaI (int n)
{
if (!n) return 1;
return n * factoriaI (n - 1);
}
'epresentaremos ahora en un esquema el proceso de recursi"n al llamar, por
ejemplo, a factorial(3)C
factorial (3)
1d llamada a la $unci"n
3 9 factorial (2) 3 9 2 B $
2d llamada a la $unci"n
2 9 factorial (1) 2 9 1 B 2
l***vi
3d llamada a la $unci"n
1 9 factorial (1) 1 9 1 B 1
0KuG se encuentra con la
condicin de salida
if (Xn) return 1A
4e puede comparar este proceso con el que genera la soluci"n iterativa:
Iong factoriaI (int n)
{
register int i;
Iong totaI = 1;
for (i = 1; i <= n; i++) totaI *= i;
return totaI;
}
En el primer caso se hacen varias llamadas a la $unci"n, situando en la pila los valores
correspondientes , Idejando pendientesI los c.lculos intermedios, hasta que se llega a
la condici"n de salidaC En ese momento comien1a el proceso inverso, sacando de la
pila los datos previamente almacenados , solucionando los c.lculos que Iquedaron
sin resolverIC )&viamente esta soluci"n es m.s lenta que la iterativa en la que el
resultado se o&tiene con una sola llamada a la $unci"n , con menos requerimientos de
memoriaC
4in em&argo, mientras que en el caso del c.lculo del $actorial de un nKmero
parece m.s aconseja&le la soluci"n iterativa, ha, otros ejemplos en lo que ocurre lo
contrarioC %or ejemplo, la $unci"n de 6cGerman se de$ine del siguiente modo:
( ) ( )
( ) ( )
6cG s, t M
t L 1
6cG s A 1, 1
6cG s A 1, 6cG s, t A 1
si
s M 2
s 2 , t M 2
s 2 , t 2

El diseFo recursivo de esta $unci"n consiste, simplemente, en aplicar la de$inici"n


int Ack (int s, int t)
{
if (!s) return t + 1;
eIse if (!t) return Ack (s - 1, 1);
eIse return Ack (s - 1, Ack (s, t - 1));
}
+a soluci"n no recursiva de la $unci"n de 6cGerman es mucho m.s complicadaC
l***vii
6a biblioteca de funciones
Qa, una serie de $unciones , macros de$inidas por el est.ndar 6>4! que
reali1an tareas que $acilitan enormemente la la&or del programadorC 6dem.s, cada
$a&ricante de so$tHare inclu,e sus propias $unciones , macros, generalmente
relacionadas con el mejor aprovechamiento de los ordenadores personales , del /4A
<)4C 'especto a esto, de&e tenerse en cuenta que la compati&ilidad del c"digo s"lo
est. asegurado si se utili1an e*clusivamente $unciones pertenecientes al est.ndar
6>4!C #omo ,a qued" dicho, los prototipos de estas $unciones, as@ como
declaraciones de varia&les, macros , tipos de datos utili1ados por ellas, est.n
de$inidos en los archivos de ca&ecera 9.&C %or ello, es necesario incluirlos mediante
sentencias #include cuando el programa hace uso de ellasC
+a ta&la de la p.gina siguiente muestra los archivos de ca&ecera est.ndar
usados por -ur&o #LLC En el #ap@tulo 13 se muestran algunas de las $unciones de la
&i&lioteca est.ndarC
FENGUA
RE
ARCSIGO
DE
CABECER
A
DESCRIPCIN
A""P.BH 1e'ine 'unciones de asi*naci6n din)mica
de memoria
AS3 . ASSJRTBH 1eclara la macro de depuraci6n a&&!$3
.22 B.1BH 1e'ine la clase bc"
B3PSBH 1e'ine 'unciones utilizadas en rutinas de
RP90B3PS
.22 .P9("JGB
H
1e'ine las 'unciones matem)ticas
compleOas
.22 .P3PBH 1e'ine !arias 'unciones utilizadas en las
llamadas a rutinas de J5S por consola en
1PS
AS3 . .TN(JBH .ontiene in'ormaci6n utilizada por las
macros de con!ersi6n : clasi'icaci6n de
caracteres
13RBH .ontiene de'iniciones para trabaOar con
directoriosB
1PSBH 1eclara constantes : da las declaraciones
necesarias para llamadas espec#'icas del
808A : del 1PS
AS3 . JRRPBH 1eclara mnem6nicos constantes para
c6di*os de error
$.T"BH 1eclara constantes simb6licas utilizadas
en coneFiones con la biblioteca de rutinas
%#!n)*
AS3B. $"PATBH .ontiene par)metros para rutinas de
coma 'lotante
l***viii
.22 $STRJA9B
H
1e'ine los 'luOos de .22 ;ue soportan J5S
de arc?i!os
.22 KJJR3.BH .ontiene macros para declaraciones de
clase *enEricas
.22 KRA(H3.SB
H
1e'ine prototipos para las 'unciones
*r)'icas
3PBH 1eclaraciones de rutinas de J5S tipo M3G
.22 3P9A3(BH 1e'ine los *estores de 'luOos de J5S de .2
2 : contiene macros para creaci6n de
*estores de par)metros
.22 3PSTRJA9B
H
1e'ine rutinas b)sicas de 'luOo de J5S de
.22 (!&B0)
AS3 . "393TSBH (ar)metros : constantes sobre la
capacidad del sistema
AS3 . "P.A"JBH 1e'ine 'unciones sobre el pa#s e idioma
AS3 . 9ATHBH 1e'ine prototipos para las 'unciones
matem)ticas
9J9BH 1e'ine las 'unciones de *esti6n de
memoria
(RP.JSSBH .ontiene estructuras : declaraciones para
las 'unciones &#aTn)*D !U!c)*
AS3 . SJTV9(BH 1eclaraciones para dar soporte a saltos
no locales
SHARJBH (ar)metros utilizados en 'unciones ;ue
utilizan ar?i!os0compartidos
AS3 . S3KA"BH 1eclara constantes : declaraciones para
utilizarlos en 'unciones &inal)* : $ai&!)*
AS3 . ST1ARKBH Soporte para aceptar un nUmero !ariable
de ar*umentos
AS3 . ST11J$BH 1eclara !arios tipos de datos : macros de
uso comUn
AS3 . ST13PBH 1eclara tipos : macros para J5S est)ndar
.22 ST13PSTRB
H
1eclara las clases de 'luOo para utilizar
con estructuras del arc?i!o &3"i%-P
AS3 . ST1"3BBH 1e'ine al*unas de las rutinas
comUnmente utilizadas
.22 STRJA9BH 1e'ine las clases de 'luOo de .22 para
utilizarlas con arra:s de b:tes en
memoria
AS3 . STR3KBH 1e'ine !arias rutinas de manipulaci6n de
cadenas : de memoria
SNS\STATB
H
1eclara constantes simb6licas utilizadas
para abrir : crear arc?i!os
SNS\T39JBB
H
1e'ine la 'unci6n 63iO!)* : la estructura
3iO!b
.22 SNS\TN(JSB
H
1e'ine el tipo 3iO!V3
AS3 . T39JBH Jstructuras : prototipos para 'unciones de
l***i*
tiempo
%A"MJSBH 1eclara constantes dependientes de la
m);uina
E7ercicios
1. El seno de un .ngulo puede calcularse mediante la serie
( ) sen * M * A
3e
L
(e
A
5e
L
3 ( 5
* * *

donde ( se e*presa en radianes D radianes M 182 gradosEC Escri&e un programa
que calcule , muestre en pantalla el seno de un .ngulo mediante la serie
anteriorC Finali1a el c.lculo en el t9rmino de la serie cu,o valor sea menor o
igual a12
A3
C %ara el c.lculo de (
n
crea una $unci"n no recursiva de prototipo
double potencia (duble (8 int n)A
<e igual modo, para el c.lculo de nX crea una $unci"n no recursiva de prototipo
double factorial (int n)A
El .ngulo de&e ser un valor comprendido entre 2 , 362C En caso se enviar. un
mensaje a pantallaC
2. Escri&e un programa que calcule (
n
, siendo ( , n dos enteros positivos que se
introducen por tecladoC %ara el c.lculo crea una $unci"n recursiva de prototipo
long potencia (int (8 int n)A
que solucione el c.lculoC
3. Escri&e un programa que muestre los < primeros t9rminos de la sucesi"n de
Fi&onacci, utili1ando una $unci"n recursiva
int )ibonacci (int <)A
que devuelva el elemento <C El valor < se leer. del tecladoC
. Escri&e un programa que muestre en pantalla la in$ormaci"n del equipo
proporcionada por las $unciones de &i&lioteca bioseKuip() , biosmemor-()C
#. %or medio de la $unci"n bios'e-() constru,e un programa que muestre en
pantalla el estado de pulsaci"n del teclado con el siguiente $ormato:
*c
/a,Ksculas derecha: 4!3>)
/a,Ksculas i1quierda: 4!3>)
-ecla #ontrol: 4!3>)
-ecla 6lt: 4!3>)
-ecla Bloq <espl: 4!3>)
-ecla Bloq >um: 4!3>)
-ecla Bloq /a,Ks: 4!3>)
-ecla !ns: 4!3>)
</T02 %ara evitar el e$ecto que produce el cursor en la presentaci"n de la
pantalla Dha, que estar continuamente imprimiendo la in$ormaci"n en la
pantallaE elim@nalo usando la $unci"n [setcursort-pe() de la &i&lioteca
est.ndarC
$. Escri&e una $unci"n de prototipo
char *Intro (int f, int c, int tam, char *cad);
que utilice la $unci"n cgets() para capturar en la $ila f, columna c, una cadena
de caracteres de longitud m.*ima tam, , la almacene en cadC <evuelve cadC
+. Escri&e una $unci"n de prototipo
int strdigit (char *cad);
que inspeccione la cadena cad , devuelva 1 si cad est. compuesta por d@gitos
num9ricos, , 1 si algKn car.cter de cad no es num9ricoC ;tili1a la $unci"n
isdigit()C
*. Escri&e una $unci"n de prototipo
char *Format_fecha (char *fecha, int tipo, char *format);
que reci&e en la cadena fec&a una $echa con $ormato <<//6666 , pone en
la cadena format esta $echa en un $ormato indicado por tipoC +os valores
permitidos por tipo , sus $ormatos correspondientes se muestran en la
siguiente ta&la:
3i#% 6%$Oa3
0 115995AA
1 115995AAAA
& 11 de 9999999999 de AAAA
+ diasemanaD 11 de 9999999999
de AAAA
4i fec&a no es una $echa v.lida o tipo est. $uera de rango, format ser. la
cadena nulaC <evuelve formatC ;tili1a la $unci"n sprintf()C
*ci
.. Escri&e una $unci"n de prototipo
int VaIida_fecha (char *fecha);
que reci&e en la cadena fec&a una $echa en $ormato <<//6666 , devuelve
un valor de 1 a $ si la $echa es correcta, indicando con los valores 2 a 6 el d@a
de la semana a que corresponde fec&a D2Mdomingo, 1Mlunes, CCCEC 4i la $echa no
es correcta, devolver. S1C ;tili1a la $unci"n intdos para hacer las llamadas a las
$unciones 26h , 2Bh de la !>- 21hC
11. Escri&e una $unci"n de prototipo
int TecIa (int *scan);
que captura una pulsaci"n de tecla , devuelve en scan el c"digo de
e*ploraci"n, , mediante return, su c"digo 64#!!C ;tili1a la $unci"n bios'e-()C
11. Escri&e una $unci"n de prototipo
int Mensaje (int st, int fiI, int coI, char *cad);
que presenta en pantalla la cadena cad en la $ila fil, columna colC 4i st vale 1,
espera a que se pulse una tecla, devolviendo mediante return su c"digo 64#!!
si se puls" una tecla normal, , 1222Lc"digo de e*ploraci"n si se puls" una
tecla especialC 4i st vale 1, no espera a que se pulse ninguna teclaC
+
,atrices - punteros
HduW es una matri5I
;na matri1 es una estructura de datos interna que almacena un conjunto de
datos del mismo tipo &ajo un nom&re de varia&le comKnC +a posici"n de un elemento
dentro de la matri1 viene identi$icada por uno o varios @ndices, de tal modo que a
cada elemento se accede mediante el nom&re de la matri1 , sus @ndicesC
+a dimensin de una matri1 es el nKmero de @ndices necesario para identi$icar
un elementoC
*cii
HduW son los punterosI
;n puntero es una varia&le que contiene una direcci"n de memoriaC %or
ejemplo, la direcci"n de otra varia&leC
<irecciones de memoria
1386 1385 1388 138 132 131 132 133 134 13(
13.3 dato
El puntero almacenado en la posici"n
de memoria 1388 apunta al dato almacenado
en la posici"n de memoria 133
+as varia&les puntero se declaran de la siguiente $orma:
tipo 9nombreA
siendo nombre el identi$icador de la varia&le puntero, , tipo el tipo de varia&le a la
que apuntaC %or ejemplo,
c&ar 9mA
int 9nA
float 9pA
En estas declaraciones, las varia&les m, n , p son punteros que a"untan,
respectivamente, a datos de tipo c&ar, int , floatC Es importante darse cuenta de
que ni m es una varia&le de tipo c&ar, ni n de tipo int, ni p de tipo floatC +os tipos
de$inen el tipo de dato al que apunta el puntero
m 185 188 18 12 11 12 13 14
1*.
m apunta a un dato c&ar
n 185 188 18 12 11 12 13 14
1*.
n apunta a un dato int
p 185 188 18 12 11 12 13 14
*ciii
1*.
p apunta a un dato float
+os operadores de punteros son los que estudiamos en el #ap@tulo 2, , se
de$inieron en la p.gina 22, es decir,
J direcci"n de
9 en la direcci"n de
El operador 9 s"lo se puede aplicar a punterosC <espu9s de
fIoat m;
fIoat *p;
...
...
m = *p;
la varia&le m almacena el contenido de la direcci"n apuntada por pC <el mismo
modo despu9s de
*p = m;
el valor de m se almacena en la direcci"n apuntada por pC +a siguiente asignaci"n
int vaIor = 100, q;
...
...
q = vaIor;
puede conseguirse tam&i9n mediante
int vaIor = 100, q, *m;
...
...
m = &vaIor;
q = *m;
es decir, se almacena en la varia&le K el valor 111C
El c"digo de $ormato para visuali1ar varia&les puntero mediante $unciones
tipo printf() es EpC 6s@,
int *m;
...
...
printf ("%p", m);
muestra en pantalla la direcci"n almacenada por mC +a visuali1aci"n se hace en
he*adecimalC )tro c"digo de $ormato relacionado con punteros es EnC Este
c"digo da lugar a que el nKmero de caracteres que se han escrito en el momento en
que se encuentra En, se asocien a una varia&le cu,a direcci"n se especi$ica en la
lista de argumentosC El siguiente programa muestra en pantalla la $rase
*civ
"e &an escrito 11 caracteres
#incIude <stdio.h>
#incIude <conio.h>
void main (void)
{
int p;
cIrscr ();
printf ("HoIa mundo %n", &p);
printf ("\nSe han escrito %d caracteres", p);
}
+as operaciones permitidas con punteros son:
6signaci"n
!ncremento 3 <ecremento
4uma 3 'esta
#omparaci"n
0amos a descri&ir cada una de ellasC
0signacin
<adas las declaraciones
fIoat x;
fIoat *p, *q;
la $orma de asignar a p , K la direcci"n de ( es:
p = &x;
q = &x;
6hora p , K almacenan la misma direcci"n de memoria: la de la varia&le (C El
mismo e$ecto se consigue con la asignaci"n directa entre punteros:
p = &x;
q = p;
>o es correcta una sentencia como
p = x;
puesto que ( es una varia&le de tipo float Dalmacena un dato float), mientras que p
almacena la direccin de un dato de tipo floatC
%or medio de punteros pueden hacerse asignaciones de contenidosC %or
ejemplo:
fIoat a, b;
fIoat *p, *q;
*cv
...
...
a = 1.5;
p = &b;
q = &a;
*p = *q;
En esta secuencia, p , K almacenan valores di$erentes Dla direcci"n de b , la
direcci"n de a, respectivamenteEC +a Kltima sentencia asigna contenidos, es decir,
almacena en el lugar apuntado por p Dla varia&le bE lo que ha, en el lugar apuntado
por K Dla varia&le aEC Es, por tanto, equivalente a
b = a;
Incremento ! ;ecremento
%ara comprender estas operaciones, de&emos tener en cuenta que hacen
re$erencia a elementos de memoria , no a direccionesC Esto quiere decir que los
operadores QQ , SS actKan de modo di$erente segKn el tipo apuntado por el
punteroC 4i p es un puntero a caracteres Dc&ar 9pE la operaci"n pQQ incrementa el
valor de p en 1C 4i em&argo, si p es un puntero a enteros Dint 9pE, la misma
operaci"n pQQ incrementa el valor de p en 2 para que apunte al siguiente
elemento, pues el tipo int ocupa dos &,tesC <el mismo modo, para el tipo float la
operaci"n pQQ incrementa el valor de p en C
+o dicho para el operador QQ se cumple e*actamente igual, pero
decrementando, para el operador SSC
"uma ! Lesta
)curre e*actamente lo mismo que con las operaciones de incremento ,
decrementoC 4i p es un puntero, la operaci"n
p = p + 5;
hace que p apunte ( elementos m.s all. del actualC 4i p esta&a de$inido como un
puntero a caracteres, se incrementar. su valor en (, pero si esta&a de$inido como
un puntero a enteros, se incrementar. en 12C
Comparacin
%ueden compararse punteros del mismo modo que cualquier otra varia&le,
teniendo siempre presente que se comparan direcciones , no contenidosC
int *p, *q;
...
...
if (p == q) puts ("p y q apuntan a Ia misma posicin de memoria");
...
...
*cvi
if (*p == *q) puts ("Las posiciones apuntadas por p y q aImacenan eI mismo vaIor");
En el segundo caso puede aparecer el mensaje aunque p , K apunten a direcciones
di$erentesC
,atrices unidimensionales
4on aquellas que s"lo precisan de un @ndice para acceder a cada elementoC
-am&i9n se les llama 4ectores o listasC
-odos los elementos de un vector se almacenan en posiciones de memoria
contiguas, almacen.ndose el primer elemento en la direcci"n m.s &ajaC
;n vector se declara de la siguiente $orma:
tipo nombreTnum[elemUA
donde tipo es el tipo de dato de todos los elementos del vector, nombre es cualquier
identi$icador v.lido #, , num[elem es el nKmero de elementos del vectorC %or
ejemplo,
char frase[20];
int numero[16];
fIoat vaIor[12];
declaran, por este orden, un vector de 22 caracteres, otro de 16 elementos enteros ,
otro de 12 elementos en coma $lotanteC El nKmero de &,tes ocupado por una matri1
se calcula multiplicando el nKmero de elementos por el tamaFo de cada uno de ellosC
6s@, los 3 vectores anteriores ocupan, respectivamente, 22, 32 , 48 &,tesC
En las declaraciones de matrices, el nom&re de la matri1 sin @ndices es un
puntero al primer elementoC 6s@, en las declaraciones anteriores frase es un puntero a
c&ar , almacena la direcci"n de fraseT1UC +o mismo ocurre para numero , 4alorC
En un vector de < elementos, el primero se re$erencia con el @ndice 1 , el
Kltimo con el @ndice <S1C 6s@, en el vector
int numero[16];
el primer elemento es numeroT1U , el Kltimo numeroT1#UC
Es importante tener en cuenta que # no hace compro&aci"n de l@mites en el
proceso de matricesC El control de&e hacerlo el programadorC 6s@, es posi&le escri&ir
numero[30] = 250;
manejando el elemento 32 del vector numero que se declar" para almacenar s"lo 16
elementosC +as consecuencias para el programa suelen ser desastrosasC
*cvii
En el siguiente programa se carga un vector de 12 caracteres desde el teclado,
, se muestra despu9s la direcci"n , contenido de cada elementoC
#incIude <stdio.h>
#incIude <conio.h>
void main (void)
{
register int i;
char vector[10];
for (i = 0; i <= 9; i++) vector[i] = getche ();
for (i = 0; i <= 9; i++) printf ("\nLugar: %d - Direccin: %p - VaIor: %c", i, vector + i,
vector[i]);
}
Cadenas de caracteres
;n caso particular de vector es la cadena de caracteresC ;na cadena de
caracteres se declara mediante
c&ar nombreTnum[carUA
, permite almacenar num[carS1 caracteres , el car.cter nulo ^F1^ de terminaci"nC
%or lo tanto, una declaraci"n como
char frase[21];
es apta para almacenar 22 caracteres , el nuloC
# permite la iniciali1aci"n de cadenas de caracteres en la declaraci"n, mediante
sentencias del tipo
char cadena[ ] = "Esto es una cadena de caracteres";
en la que no es necesario aFadir el nulo $inal ni indicar el tamaFo, pues lo hace
autom.ticamente el compiladorC
+as operaciones con cadenas de caracteres como copiar, comparar, concatenar,
medir, etcC, se hacen mediante $unciones de la &i&lioteca est.ndarC 4u utili1aci"n
requiere incluir el archivo de ca&ecera string.&C 0eamos alguna de ellasC
c&ar 9strcat (c&ar 9cad18 const c&ar 9cad2)A
#oncatena cad2 a cad1 devolviendo la direcci"n de cad1C Elimina el nulo de
terminaci"n de cad1 inicialC
Ejemplo:
char cad1[80], cad2[80];
...
*cviii
...
printf ("\nTecIee una frase: ");
gets (cad1);
printf ("\nTecIee otra frase: ");
gets (cad2);
strcat (cad1, cad2);
puts (cad1);
En este ejemplo, si se teclea :rimera frase para cad1 , "egunda frase para cad2, se
muestra en pantalla
:rimera frase"egunda frase
-endr@a el mismo e$ecto
puts (strcat (cad1, cad2));
Qa, que asegurarse de que el tamaFo de cad1 es su$iciente para almacenar el
resultadoC
c&ar 9strc&r (const c&ar 9cad8 int c&)A
<evuelve la direcci"n de la primera aparici"n del car.cter c& en la cadena cadC
4i no se encuentra devuelve un puntero nuloC
Ejemplo:
char *p, caracter, cadena[80];
int Iugar;
...
...
printf ("\nTecIee un carcter: ");
caracter = getche ();
printf ("\nTecIee una frase: ");
gets (cadena);
p = strchr (cadena, caracter);
if (!p) printf ("\nNo est eI carcter %c en Ia frase", caracter);
eIse {
Iugar = p - cadena;
printf ("\nEI carcter %c ocupa eI Iugar %d de Ia frase", caracter, Iugar);
}
int strcmp (const c&ar 9cad18 const c&ar 9cad2)A
%ara la comparaci"n de cadenas de caracteres no se permite la utili1aci"n de los
operadores >, =, >B, XB, etcC, sino que se de&e utili1ar la $unci"n strcmpC Esta
$unci"n compara le*icogr.$icamente cad1 , cad2 , devuelve un entero que se de&e
interpretar como sigue:
= 1 cad1 = cad2
*ci*
1 cad1 igual a cad2
> 1 cad1 > cad2
Ejemplo:
char cad1[40], cad2[40];
...
...
printf ("\nTecIee una frase: ");
gets (cad1);
printf ("\nTecIee una frase: ");
gets (cad2);
n = strcmp (cad1, cad2);
if (!n) puts ("Son iguaIes");
eIse if (n < 0) puts ("La primera es menor que Ia segunda");
eIse puts ("La primera es mayor que Ia segunda");
Es necesario insistir en que la comparaci"n no se hace en cuanto al tamaFo de
la cadena sino en cuanto al orden de los caracteres en el c"digo 64#!!C Esto quiere
decir que si cad1 es 03C;E , cad2 es (-5, la $unci"n strcmp devuelve un valor
negativo, pues se considera que cad1 = cad2 ,a que el car.cter 0 tiene un c"digo
64#!! menor que el car.cter (C
c&ar 9strcp- (c&ar 9cad18 const c&ar 9cad2)
#opia la cadena cad2 en cad1, so&reescri&i9ndolaC <evuelve la direcci"n de
cad1C Qa, que asegurarse de que el tamaFo de cad1 es su$iciente para al&ergar a
cad2C
Ejemplo:
char cadena[40];
...
...
strcpy (cadena, "Buenos das");
int strlen (const c&ar 9cad)A
<evuelve el nKmero de caracteres que almacena cad Dsin contar el nulo $inalEC
Ejemplo:
char cad[30];
...
...
printf ("\nTecIee una frase: ");
gets (cad);
printf ("\nLa frase <<<%s>>> tiene %d caracteres", cad, strIen (cad));
c
c&ar 9strl%r (c&ar 9cad)A
#onvierte cad a minKsculasC +a $unci"n no tiene e$ecto so&re los caracteres que
no sean letras ma,KsculasC -ampoco tiene e$ecto so&re el conjunto e*tendido de
caracteres 64#!! Dc"digo ma,or que 125E, por lo que no convierte las letras f, g o
vocales acentuadasC <evuelve la direcci"n de cadC
Ejemplo:
char cad[40];
...
...
printf ("\nTecIee una frase en mayscuIas: ");
gets (cad);
printf ("\nLa cadena en minscuIas es %s", strIwr (cad));
c&ar 9strre4 (c&ar 9cad)A
!nvierte la cadena cad , devuelve su direcci"nC
Ejemplo:
char cad[80];
...
...
printf ("\nTecIee una frase: ");
gets (cad);
printf ("\nFrase invertida: %s", strrev (cad));
c&ar 9strset (c&ar 9cad8 int c&)A
'eempla1a cada uno de los caracteres de cad por el car.cter c&C <evuelve la
direcci"n de cadC
Ejemplo:
char cad[80];
...
...
strcpy (cad, "12345");
strset (cad, 'X');
puts ("Se visuaIiza una cadena con 5 X");
puts (cad);
c&ar 9strupr (c&ar 9cad)A
#onvierte cad a ma,KsculasC +a $unci"n no tiene e$ecto so&re los caracteres
que no sean letras minKsculas ni so&re el conjunto e*tendido de caracteres 64#!!
Dletras F, h o vocales acentuadasEC <evuelve la direcci"n de cadC
Ejemplo:
ci
char cad[40];
...
...
printf ("\nTecIee una frase en minscuIas: ");
gets (cad);
printf ("\nLa frase en mayscuIas es %s", strupr (cad));
En el #ap@tulo 13 se muestran m.s $unciones de cadenas de caracteresC
-am&i9n e*iste un amplio conjunto de $unciones que manejan caracteres
individualesC +a ma,or@a de estas $unciones in$orman del tipo de car.cter incluido en
su argumento devolviendo un valor 1 " 2C Estas $unciones tienen su prototipo
de$inido en ct-pe.& , generalmente no consideran el conjunto 64#!! e*tendidoC
6lguna de estas $unciones se e*plican a continuaci"n:
int isalnum (int c&) <evuelve 1 si c& es al$anum9rico Dletra del al$a&eto o d@gitoE , 2
en caso contrarioC
int isalp&a (int c&) <evuelve 1 si c& es una letra del al$a&eto , 2 en caso contrarioC
int isdigit (int c&) <evuelve 1 si c& es un d@gito del 2 al , , 2 en caso contrarioC
int islo%er (int c&) <evuelve 1 si c& es un letra minKscula , 2 en caso contrarioC
int isupper (int c&) <evuelve 1 si c& es una letra ma,Kscula , 2 en caso contrarioC
int tolo%er (int c&) <evuelve el car.cter c& en minKsculaC 4i c& no es una letra
ma,Kscula la $unci"n devuelve c& sin modi$icaci"nC
int toupper (int c&) <evuelve el car.cter c& en ma,KsculaC 4i c& no es una letra
minKscula la $unci"n devuelve c& sin modi$icaci"nC
En el #ap@tulo 13 se muestran m.s $unciones de caracteresC
El programa siguiente hace uso de alguna de las $unciones anteriores para
e*aminar una cadena de caracteres , convertir las minKsculas a ma,Ksculas ,
viceversaC 6dem.s cuenta cu.ntos caracteres son d@gitos num9ricosC
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
#incIude <ctype.h>
void main (void)
{
char cadena[100];
int contador = 0;
register int i;
cIrscr ();
printf ("\nTecIee una cadena de caracteres: ");
gets (cadena);
cii
for (i = 0; i <= strIen (cadena); i++) {
if (isupper (cadena[i])) cadena[i] = toIower (cadena[i]);
eIse if (isIower (cadena[i])) cadena[i] = toupper (cadena[i]);
eIse if (isdigit (cadena[i])) contador++;
}
printf ("\nLa cadena tiene %d dgitos numricos\n", contador);
puts (cadena);
}
:unteros - matrices
%uesto que una matri1 se identi$ica mediante la direcci"n del primer
elemento, la relaci"n entre punteros , matrices es estrechaC 4ea la declaraci"n
int matriz[100];
%odemos identi$icar un elemento, digamos el 2(, de cualquiera de las dos $ormas
siguientes:
matriz[24];
*(matriz + 24);
puesto que matri5 Dsin @ndicesE es la direcci"n del primer elementoC
El uso de punteros para manejar matrices es, en general, m.s e$iciente ,
r.pido que el uso de @ndicesC +a decisi"n de qu9 m9todo utili1ar Dpunteros o
@ndicesE depende del tipo de accesoC 4i se va a acceder a los elementos de la matri1
de $orma aleatoria, es mejor utili1ar @ndicesC 4in em&argo, si el acceso va a ser
secuencial, es m.s adecuado usar punterosC Este segundo caso es el t@pico en las
cadenas de caracteresC %or ejemplo, las sentencias siguientes muestran en pantalla,
car.cter a car.cter una cadena de caracteresC
char *p, cadena[30];
register int i;
...
...
for (i = 0; cadena[i]; i++) putch (cadena[i]);
...
...
p = cadena;
for (; *p; p++) putch (*p);
...
...
p = cadena;
whiIe (*p) putch (*p++);
+as dos Kltimas son las m.s adecuadasC )tro ejemplo lo constitu,en las 3 $unciones
que se descri&en a continuaci"nC Estas $unciones comparan dos cadenas de
caracteres de modo similar a como lo hace strcmp()C
ciii
int compara1 (char *cad1, char *cad2)
{
register int i;
for (i = 0; cad1[i]; i++) if (cad1[i] - cad2[i]) return (cad1[i] - cad2[i]);
return 0;
}
int compara2 (char *cad1, char *cad2)
{
char *p1, *p2;
p1 = cad1;
p2 = cad2;
whiIe (*p1) {
if (*p1 - *p2) return (*p1 - *p2);
eIse {
p1++;
p2++;
}
}
return 0;
}
int compara3 (char *cad1, char *cad2)
{
char *p1, *p2;
p1 = cad1;
p2 = cad2;
for (; *p1; p1++, p2++) if (*p1 - *p2) return (*p1 - *p2);
return 0;
}
<e las 3 $unciones anteriores son m.s e$icientes las dos KltimasC
,atrices bidimensionales
;na matri1 &idimensional es aquella que necesita dos @ndices para identi$icar un
elementoC %uede decirse que una matri1 &idimensional es una estructura de datos
organi1ados en $ilas , columnasC 4e declaran de la siguiente $orma:
tipo nombreTne filasUTne columnasUA
%or ejemplo, para declarar una matri1 de nKmeros enteros organi1ada en 8 $ilas
, 6 columnas se escri&e
civ
int totaI[8][6];
El primer elemento de la matri1 es totalT1UT1U , se almacena en una direcci"n de
memoria identi$icada por totalC El Kltimo es totalT+UT#UC
;n caso particular de matrices &idimensionales lo constitu,en las matrices de
cadenas de caracteresC %or ejemplo, la sentencia
char cadenas[10][25];
declara una matri1 de 12 cadenas de 24 caracteres m.s el nuloC %ara acceder a una
cadena en particular &asta especi$icar el @ndice i1quierdo DnKmero de cadenaEC 6s@,
gets (cadena[6]);
lee del teclado una cadena de caracteres , la almacena en la s9ptima cadena Dla
primera es cadenaT1UE de la matri1 C Esta sentencia es equivalente a
gets (&cadena[6][0]);
%ara acceder a un car.cter concreto de una cadena ha, que especi$icar am&os
@ndicesC %or ejemplo, la sentencia
cadena[3][9] = 'X';
almacena en el 12i car.cter de la 4d cadena el car.cter RC
//Cambia en un grupo de cadenas las vocales por #
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
void main (void)
{
char cadena[10][70];
register int i, j;
cIrscr ();
for (i = 0; i <= 9; i++) {
printf ("\nCadena n %d: ", i);
gets (cadena[i]);
}
for (i = 0; i <= 9; i++) {
for (j = 0; cadena[i][j]; j++) {
if (strchr ("aeiouAEIOU", cadena[i][j])) cadena[i][j] = '#';
}
puts (cadena[i]);
}
}
En el siguiente programa se carga del teclado una matri1 de 12 cadenas de
caracteres , se &usca en ellas la primera aparici"n de la cadena O/60, in$ormando
del nKmero de cadena en que se encuentra , de la posici"n que ocupa en ellaC %ara
ello se utili1a la $unci"n strstr e*plicada en el #ap@tulo 13 Dp.gina 212EC
cv
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
void main (void)
{
char cadena[10][50];
register int i;
char *p;
cIrscr ();
for (i = 0; i <= 9; i++) {
printf ("\nCadena n %d: ", i);
gets (cadena[i]);
strupr (cadena[i]);
}
for (i = 0; i <= 9; i++) {
p = strstr (cadena[i], "HOLA");
if (p) printf ("\nCadena n %d, posicin %d", i, p - cadena[i]);
}
}
%odemos acceder a los elementos de una matri1 &idimensional mediante
punterosC 4e accede al elemento matri5TiUT7U mediante la $"rmula:
9(matri5 Q i 9 ne[de[filas Q 7)
,atrices de ms de 2 dimensiones
En # pueden manejarse matrices de m.s de 2 dimensionesC %ara declarar estas
matrices se hace
tipo nombreTtama\o 1UTtama\o 2U ... Ttama\o <UA
+a siguiente sentencia declara una matri1 tridimensional de elementos de tipo
float:
fIoat matriz3D[5][3][8];
El pro&lema de este tipo de matrices es la cantidad de memoria que pueden
llegar a ocupar, ,a que esta aumenta e*ponencialmente con el nKmero de
dimensionesC Es por ello que para estas estructuras suele utili1arse asignaci"n
din.mica de memoria, de modo que permite asignar o recortar memoria segKn se va
necesitandoC Estudiaremos esto en el #ap@tulo C
+as siguientes sentencias muestran como se puede cargar desde el teclado la
matri1 matri53;C
for (i = 0; i <= 4; i++) {
cvi
for (j = 0; j <= 5; j++) {
for (k = 0; k <= 7; k++) {
printf ("\nEIemento %d-%d-%d: ", i, j, k);
scanf ("%f", &matriz3D[i][j][k]);
}
}
}
Cmo iniciali5ar matrices
#ualquier matri1 puede ser iniciali1ada en el momento de la declaraci"nC %ara
ello se encierran entre llaves, separados por comas, los datos de la iniciali1aci"nC
0eamos algunos ejemplos:
fIoat vector[5] = {1.23, 16.9, -1.2, 2.06, 31.15};
int tabIa[2][3] = {5, 62, 34, 21, 43, 90};
%ara m.s claridad, en las matrices de dos dimensiones suele hacerse:
int tabIa[2][3] = { 5, 62, 34,
21, 43, 90};
En los dos Kltimos casos, la matri1 tabla queda iniciali1ada de la siguiente manera:
tablaT1UT1U B # tablaT1UT1U B $2 tablaT1UT2U B 3
tablaT1UT1U B 21 tablaT1UT1U B 3 tablaT1UT2U B .1
El mismo e$ecto se produce usando anidamiento de llaves:
int tabIa[2[3] = { { 5, 62, 34 },
{ 21, 43, 90 } };
+as matrices de cadenas de caracteres pueden iniciali1arse de la $orma
char frases[3][30] = { "Primera cadena", "Segunda cadena", "Tercera" };
En todas las matrices multidimensionales puede omitirse el primer @ndice
cuando se iniciali1an en la declaraci"nC %or ello, las declaraciones siguientes:
int tabIa[3][4] = { 6, 12, 25, 4, 5, 13, 7, 2, 2, 4, 9, 6};
int tabIa[ ][4] = {6, 12, 25, 4, 5, 13, 7, 2, 2, 4, 9, 6};
son id9nticasC En el segundo caso, el compilador se encarga de calcular el tamaFo
correspondienteC
,atrices como argumentos de funciones
cvii
#uando se pasa una matri1 como argumento de una $unci"n, el compilador
genera la llamada con la direcci"n del primer elementoC <e esta $orma se evita pasar
la matri1 completa, lo que consume mucha memoria , hace el proceso m.s lentoC 4ea,
por ejemplo, la matri1 unidimensional
int vector[30];
que se quiere pasar como argumento a una $unci"n ma-or() que devuelve como
valor de retorno el elemento m.s grande de la matri1C +a llamada se hace de la $orma
a = mayor (vector);
, la $unci"n ma-or() puede declararse de cualquiera de las $ormas siguientes:
int mayor (int x[30])
{
...
...
}
int mayor (int x[ ])
{
...
...
}
En cualquiera de los 2 casos el resultado es id9ntico, pues am&as declaraciones
le indican al compilador que se va a reci&ir en el argumento la direcci"n de un entero
Dla del primer elemento de la matri1EC En el primer caso, el valor 32 no se tiene en
cuentaC
El siguiente programa carga desde el teclado una matri1 de enteros , muestra el
ma,or de ellos, calcul.ndolo mediante una $unci"nC
#incIude <stdio.h>
void main (void)
{
register int i;
int vector[30];
for (i = 0; i <= 29; i++) {
printf ("\nEIemento %d: ", i);
scanf ("%d", &vector[i]);
}
printf ("\nEI mayor es %d", mayor (vector, 30));
}
int mayor (int tabIa[ ], int num_eIement)
{
register int i;
int max;
max = tabIa[0];
for (i = 0; i < num_eIement; i++) if (max < tabIa[i]) max = tabIa[i];
return max;
}
cviii
>"tese que es necesario pasar el tamaFo de la matri1 como argumento, pues de
lo contrario la $unci"n ma-or() no tendr@a ninguna in$ormaci"n so&re el nKmero de
elementos de la matri1C
%ara las matrices &idimensionales, aunque se pasa s"lo la direcci"n del primer
elemento, es necesario especi$icar el nKmero de columnas Dsegundo @ndiceE para que
el compilador sepa la longitud de cada $ilaC %or ejemplo, una $unci"n que reci&a como
argumento una matri1 declarada como
int matriz2D[10][20];
se declara de la $orma siguiente:
funcion (int x[ ][20])
{
...
}
, la llamada se hace con una sentencia como
funcion (matriz2D);
En general, para matrices multidimensionales, s"lo se puede omitir el primer
@ndice en la declaraci"nC %or ejemplo, una matri1 declarada mediante
int matriz3D[5][10][20];
se pasa como argumento de una $unci"n mediante una llamada de la $orma
funcion (matriz3D);
, la declaraci"n de la $unci"n tiene el siguiente aspecto:
funcion (int x[ ][10][20])
{
...
}
0rgumentos de la funcin main()
#uando, por ejemplo, escri&imos desde el indicador del <)4 una orden como
C2F>RC/:` 9.;0T 32 !"
estamos ejecutando un programa llamado RC/:`.ERE con 3 par.metros: 9.;0T,
32 , !"C Esos par.metros, de alguna $orma, son le@dos por el programa RC/:`C
%ara hacer esto en cualquier programa #, es necesario modi$icar la $orma en
que se llama a la $unci"n main(), inclu,endo en ella argumentos que permitan la
o&tenci"n de los par.metros introducidos en la l@nea de "rdenesC +a $orma de hacer
esto es la siguiente:
main (int argc8 c&ar 9arg4T U)
ci*
0eamos el signi$icado de las varia&les argc , arg4C
argc: Entero que indica el nKmero de par.metros tecleados Dinclu,e el
nom&re del programaEC
arg4T U: /atri1 de cadenas de caracteresC #ada uno de los elementos arg4TiU
es una cadena que almacena un argumentoC
+a varia&le argc vale 1 como m@nimo, puesto que se cuenta el nom&re del
programaC +os par.metros se identi$ican mediante arg4 de la siguiente manera:
arg4T1U cadena que almacena el nom&re del programaC
arg4T1U cadena que almacena el primer par.metroC
arg4T2U cadena que almacena el segundo par.metroC
...
...
arg4TargcU vale cero DEn realidad es un puntero nuloEC
%ara que los argumentos sean tratados como di$erentes tienen que ir separados
por uno o varios espacios &lancosC 6s@, en el ejemplo anterior la varia&le argc vale 4
Dnom&re del programa , 3 par.metrosEC 4i escri&imos, por ejemplo
C2F>:L/M :0L18:0L2
la varia&le argc valdr@a 2, puesto que la cadena :0L18:0L2 queda identi$icada
como un s"lo par.metro Dalmacenado en la cadena arg4T1UE ,a que la coma no actKa
como separadorC %ara que :0L1 , :0L2 sean tratados como dos par.metros
di$erentes, de&e ejecutarse :L/M mediante
C2F>:L/M :0L1 :0L2
El siguiente programa lista los par.metros, si los ha,, de la l@nea de "rdenesC
#incIude <stdio.h>
void main (int argc, char *argv[ ])
{
register int i;
printf ("\nNombre deI programa: %s", argv[0]);
if (argc == 1) printf ("\nNo se han introducido parmetros");
eIse {
printf ("\nParmetros en Ia Inea de rdenes: ");
for (i = 1; i < argc; i++) printf ("\n%d: %s", i, argv[i]);
}
}
+a $unci"n main() soporta una varia&le m.s, llamada en4:
en4T U: /atri1 de cadenas de caracteresC #ada uno de los elementos de la
matri1 es una cadena que almacena el nom&re , contenido de una
varia&le del entornoC
c*
#incIude <stdio.h>
void main (int argc, char *argv[ ], char *env[ ])
{
register int i;
printf ("\nNombre deI programa: %s", argv[0]);
if (argc == 1) printf ("\nNo se han introducido parmetros");
eIse {
printf ("\nParmetros en Ia Inea de rdenes: ");
for (i = 1; i < argc; i++) printf ("\n%d: %s", i, argv[i]);
}
printf ("\nVariabIes de entorno: \n");
for (i = 0; env[i]; i++) puts (env[i]);
}
4i este programa esta compilado , linGado como :L/M.ERE , se ejecuta
como
C2F>:L/M :0L1 :0L2 C2F> :L/M
proporciona la salida
<ombre del programa2 :L/M <ombre del programa2 :L/M
:armetros en la lGnea de rdenes2 <o se &an introducido parmetros
12 :0L1 ]ariables de entorno2
22 :0L2 C/,":ECBC2F;/"FC/,,0<;.C/,
]ariables de entorno2
:L/,:TBf:fM
C/,":ECBC2F;/"FC/,,0<;.C/, :0TOBC2FAC2F;/"AC2FbI<;/b"
:L/,:TBf:fM
:0TOBC2FAC2F;/"AC2FbI<;/b"
,atrices de punteros
%ueden de$inirse matrices de punteros, es decir, matrices cu,os elementos
son direccionesC %or ejemplo,
int *pint[20];
char *pchar[40];
declaran una matri1 pint de 22 punteros a enteros , otra matri1 pc&ar de 42
punteros a caracteresC
%ara asignar las direcciones se hace igual que con cualquier otro punteroC
/ediante las siguientes sentencias
int *pint[20], a;
...
...
a = 20;
pint[3] = &a;
printf ("%d", *pint[3]);
se muestra en pantalla el nKmero 22C
c*i
;n ejemplo t@pico de matri1 de punteros es la matri1 de cadenas de
caracteresC +as declaraciones siguientes son equivalentes
char dias[ ][10] = { "Domingo", "Lunes", "Martes", "MircoIes",
"Jueves", "Viernes", "Sbado" };
char *dias[ ] = { "Domingo", "Lunes", "Martes", "MircoIes",
"Jueves", "Viernes", "Sbado" };
:unteros a punteros
En la ma,or@a de los casos un puntero apunta a un datoC
p *
;ireccin
de
(
]alor
, 9p proporciona el valor de (C %ero tam&i9n se pueden de$inir punteros a
punterosC
p1 p2 *
;ireccin
de
p2
;ireccin
de
(
]alor
En este caso 9p2 proporciona el valor de (C %ero p1 proporciona la direcci"n
de p2C %ara acceder a ( mediante p1 ha, que hacer 99p1C
#incIude <stdio.h>
void main (void)
{
int x, *p, **q;
x = 10;
p = &x;
q = &p;
printf ("%d", **q);
}
c*ii
Este programa muestra en pantalla el nKmero 12 que almacena (C
:unteros a funciones
%uesto que una $unci"n ocupa una posici"n en la memoria, pueden de$inirse
punteros a $unciones, , hacer llamadas a la $unci"n por medio de la direcci"nC Esto
se aplica generalmente para tra&ajar con matrices de $uncionesC 0e.moslo con un
ejemploC El siguiente programa reali1a las operaciones &.sicas suma, resta ,
producto, por medio de llamadas a $unciones que $orman parte de una matri1C
#incIude <stdio.h>
#incIude <conio.h>
int menu (void);
int suma (int, int);
int resta (int, int);
int producto (int, int);
int (*caIcuIo[3]) (int, int) = { suma, resta, producto };
void main (void)
{
int n, x, y, resuItado;
whiIe (( n = menu()) != 3) {
printf ("\nTecIea dos nmeros: ");
scanf ("%d %d", &x, &y);
resuItado = (*caIcuIo[n]) (x, y);
printf (" = %d", resuItado);
getch ();
}
}
int menu (void)
{
int opcion;
cIrscr ();
puts ("0. Suma");
puts ("1. Resta");
puts ("2. Producto");
puts ("3. SaIir");
do {
opcion = getch ();
} whiIe (opcion < '0' || opcion > '3');
return opcion - 48;
}
int suma (int a, int b)
c*iii
{
printf ("\n%d + %d", a, b);
return a + b;
}
int resta (int a, int b)
{
printf ("\n%d - %d", a, b);
return a - b;
}
int producto (int a, int b)
{
printf ("\n%d * %d", a, b);
return a * b;
}
En general, un puntero a una $unci"n se declara de acuerdo a
tipo (9pfunc) ()A
siendo pfunc el nom&re del puntero, , tipo el tipo del valor devuelto por la
$unci"nC +os par9ntesis son necesarios, pues
tipo 9pfunc ()A
declara una $unci"n que devuelve un punteroC %ara llamar a la $unci"n de&e hacerse
(9pfunc) ()A
E7ercicios
1. #arga mediante el teclado una matri1 entera de 4 $ilas , 3 columnasC #alcula ,
muestra en pantalla la suma de cada $ila , de cada columna por medio de dos
$unciones de prototipos
int suma[fila (int fila)A
int suma[columna (int columna)A
2. #onstru,e un programa que cree , muestre en pantalla un cuadrado m.gico de
orden 3C ;n cuadrado m.gico es aqu9l en el que todas las $ilas , columnas
suman lo mismoC %ara ello, se coloca el valor 1 en el medio de la 1d $ilaC +os
siguientes valores D2, 3, 4, CCCE se sitKan en la $ila de arri&a, columna de la
derecha, salvo que est9 ocupada, en cu,o caso se coloca inmediatamente
de&ajoC 4e supone que las $ilas , columnas de los e*tremos son ad,acentesC
1 1 $ * 1 6
c*iv
3 3 # 3 ( +
2 2 4 . 2
3. #onstru,e un programa que cree , muestre en pantalla un cuadrado m.gico de
orden < impar D3 V > 1EC El valor de < se leer. de la l@nea de "rdenes
Ddeclarando adecuadamente la $unci"n mainEC Env@a a pantalla un mensaje de
error en cada uno de los siguientes casos:
El valor de < est. $uera de rangoC
>o se ha dado valor a < en la l@nea de "rdenesC
Qa, demasiados par.metros en la l@nea de "rdenesC
En cualquiera de los casos $inali1ar.s el programa despu9s de enviado el
mensajeC D>)-6: ;tili1a la $unci"n atoi() de la &i&lioteca est.ndarEC
. #onstru,e un programa que cargue del teclado dos matrices enteras 0 , 3 de
orden 3*3, , que visualice la matri1 producto : B 0 c 3C
iO
i[ [O
[
p
a b
=
=

0
3
+a carga de matrices de&es reali1arla mediante una $unci"n a la que llamar.s
dos veces: una para cargar 0 , otra para cargar 3C -am&i9n calcular.s los
elementos p
i7
mediante una $unci"nC
#. #onstru,e dos $unciones similares a strl%r() , strupr() que actKen tam&i9n
so&re los caracteres F, h, letras acentuadas, etcC 4e llamar.n strminus() ,
strma-us()C
$. <esarrolla las siguientes $unciones:
;na $unci"n llamada burbu7a() que ordene ascendentemente un
vector de 122 elementos enteros por el m9todo de la &ur&ujaC
;na $unci"n llamada seleccion() que ordene ascendentemente un
vector de 122 elementos enteros por el m9todo de selecci"nC
;na $unci"n llamada insercion() que ordene ascendentemente un
vector de 122 elementos enteros por el m9todo de inserci"nC
;na $unci"n llamada s&ell() que ordene ascendentemente un vector de
122 elementos enteros por el m9todo shellC
;na $unci"n llamada Kuic'() que ordene ascendentemente un vector
de 122 elementos enteros por el m9todo de ordenaci"n r.pida o 8uicG
4ortC
#onstru,e un programa que cargue un vector ordenado descendentemente
aT1U B .. aT1U B .* aT2U B .+ ... aT..U B 1
c*v
, que determine, mediante llamadas a las $unciones anteriores, qu9 m9todo de
ordenaci"n es m.s r.pidoC %ara medir el tiempo utili1a la $unci"n de la
&i&lioteca est.ndar biostime() cu,o prototipo est. en bios.&C
+. #onstru,e dos $unciones de prototipos
c&ar 9Copia (c&ar 9cad18 const c&ar 9cad2)A
c&ar 9Concatena (c&ar 9cad18 const c&ar 9cad2)A
que realicen las mismas operaciones, respectivamente, que las $unciones de
&i&lioteca est.ndar strcp-() , strcat()C Qa1 dos versiones de cada $unci"n:
una con @ndices , otra con punterosC
*. #onstru,e una $unci"n de prototipo
c&ar 9Insertar (c&ar 9cad8 int car8 int pos)A
que inserte el car.cter car en la posici"n "os de la cadena cadC +a $unci"n
de&e devolver la direcci"n de cadC Qa1 dos versiones de la $unci"n: una con
@ndices , otra con punterosC
.. #onstru,e una $unci"n de prototipo
c&ar 9Elimina (c&ar 9cad8 int pos)A
que elimine de cad el car.cter situado en la posici"n "osC +a $unci"n de&e
devolver la direcci"n de cadC Qa1 dos versiones de la $unci"n: una con
@ndices , otra con punterosC
11. #onstru,e una $unci"n de prototipo
c&ar 9"ubstr (c&ar 9orig8 int desde8 int n8 c&ar 9dest)A
que almacene en la cadena dest la su&cadena de cad que comien1a en la
posici"n desde , tiene n caracteresC +a $unci"n de&e devolver la direcci"n de
destC Qa1 dos versiones de la $unci"n: una con @ndices , otra con punterosC
11. #rea un vector de 1222 elementos enteros ordenados descendentemente:
(T1U (T1U (T2U ... (T..*U (T...U
... ..* ..+ ... 1 1
c*vi
, ord9nalo ascendentemente por el m9todo de la &ur&ujaC Qa1 dos versiones
del programa: una con @ndices , otra con punterosC /ide la e$iciencia de cada
m9todo utili1ando la $unci"n cloc'() de la &i&lioteca est.ndarC
12. ;tili1ando punteros carga un vector de (2 elementos enteros D=enera los
valores aleatoriamente mediante las $unciones de la &i&lioteca est.ndar
random() , randomi5e()EC %osteriormente muestra cu.l es el valor ma,or,
su posici"n en el vector , la posici"n de memoria que ocupaC
13. Qa1 un programa que cree un vector preparado para almacenar (2 datos
enteros que $uncione con estructura de pilaC El programa ejecutar. las
siguientes acciones:
1C /ostrar el contenido de la pilaC
2C !ntroducir un dato en la pilaC
3C 4acar un dato de la pilaC
4C Fin del programaC
El programa presentar. este menK , reali1ar. las acciones deseadas mediante
$unciones agrupadas en una matri1C
*
/tros tipos de datos
Introduccin
El +enguaje # permite al usuario crear nuevos tipos de datos mediante (
herramientas:
+a sentencia t-pedef, que permite dar nuevos nom&res a tipos de datos
que ,a e*istenC
+as estructuras, agrupaciones de varia&les de distinto tipo &ajo un
nom&re comKnC
+os campos de bits, que son una variante de las estructuras, , que
permiten el acceso individual a los &its de una pala&raC
+as uniones, que permiten asignar la misma 1ona de memoria para
varia&les di$erentesC
+as enumeraciones, que son listas de s@m&olosC
c*vii
Estudiaremos cada una de ellas a continuaci"nC
Tipos definidos por el usuario
/ediante la pala&ra reservada t-pedef podemos dar nuevos nom&res a tipos
de datos que ,a e*istenC +a sinta*is es la siguiente:
t-pedef ti"o nombreO
donde ti"o es un tipo de dato , nombre es el nuevo nom&re para el tipo de dato
anteriorC %or ejemplo:
typedef register int CONTADOR;
hace que # recono1ca C/<T0;/L como un tipo de dato id9ntico a register intC
6s@, despu9s de la de$inici"n anterior podemos declarar varia&les del nuevo tipo
mediante sentencias como
CONTADOR i, j;
que declara dos varia&les i, 7 del tipo C/<T0;/L, es decir, register intC
6dem.s, este tipo de de$iniciones no anulan el tipo anterior, por lo que podemos
seguir declarando varia&les del tipo register int que convivan con declaraciones
del tipo C/<T0;/LC
/ediante esta sentencia podemos usar nom&res m.s c"modos para los tipos
de datos, , hacer que el c"digo $uente sea m.s claroC
Estructuras
;na estructura es un conjunto de varia&les de igual o distinto tipo, agrupadas
&ajo un nom&re comKnC 6 esas varia&les se les denomina cam"os de la estructuraC
+as estructuras se declaran mediante la pala&ra reservada structC Qa, varias
$ormas de declarar una estructura, pero la m.s general es la siguiente:
struct nombre_estructura ?
ti"o variable1A
ti"o variable2A
...
...
ti"o variableNA
@ A
c*viii
0eamos un ejemploC +a siguiente declaraci"n
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
};
de$ine una estructura llamada )ICO0 con tres campos de distinto tipo: nombre,
edad , alturaC
Qemos de tener en cuenta que la declaraci"n anterior s"lo de$ine la $orma de
la estructura, pero no declara ninguna varia&le con dicha $ormaC %or as@, decirlo,
hemos de$inido una plantilla de 3 campos, pero no hemos aplicado dicha plantilla a
ninguna varia&leC %ara hacerlo ha, que escri&ir sentencias como
struct FICHA registro;
que declara una varia&le llamada registro con la estructura )ICO0, es decir,
registro es una varia&le compuestas por 3 campos: nombre, edad , alturaC %ara
acceder a cada uno de los campos se utili1a el operador punto D.E de la siguiente
$orma:
strcpy (registro.nombre, "Jos Garca");
registro.edad = 38;
registro.aItura = 1.82;
%or supuesto, pueden declararse varias varia&les con la misma estructura:
struct FICHA var1, var2;
que son dos varia&les con la estructura )ICO0C +os campos de cada una de ellas,
como por ejemplo 4ar1.edad , 4ar2.edad son dos varia&les distintas que ocupan
posiciones de memoria di$erentesC
-am&i9n pueden declararse las varia&les a la ve1 que se de$ine la estructura:
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
} var1, var2;
que declara dos varia&les 4ar1 , 4ar2 con la estructura )ICO0C Este tipo de
declaraciones no impide que puedan declararse m.s varia&les con esa estructura:
#incIude <...
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
} var1, var2;
void Funcion (void);
c*i*
void main (void)
{
struct FICHA var3;
...
...
}
void Funcion (void)
{
struct FICHA var4;
...
...
}
En las sentencias anteriores se declaran 4 varia&les con la estructura )ICO0:
4ar1 , 4ar2, glo&alesO 4ar3, local a main()O , 4ar, local a )uncion()C
%ueden hacerse declaraciones de una estructura sin darle nom&reC %or
ejemplo:
struct {
char nombre[40];
int edad;
fIoat aItura;
} var1, var2;
declara las varia&les 4ar1 , 4ar2 con la estructura indicadaC El pro&lema que
plantea este tipo de declaraciones es que, al no tener nom&re la estructura, no es
posi&le declarar otras varia&les con esa estructuraC
-am&i9n es ha&itual de$inir las estructuras con un nuevo tipoC %or ejemplo:
typedef struct {
char nombre[40];
int edad;
fIoat aItura;
} MIESTR;
6hora podemos hacer uso del nuevo tipo para declarar varia&les mediante
sentencias como:
MIESTR var1, var2;
Fij9monos que, de&ido a la sentencia t-pedef, ,IE"TL no es una varia&le,
sino un tipo de datoC
Iniciali5acin de estructuras
Es posi&le iniciali1ar varia&les con estructura en el momento en que son
declaradasC %or ejemplo:
#incIude <...
struct FICHA {
char nombre[40];
int edad;
c**
fIoat aItura;
};
void main (void)
{
struct FICHA registro = { "Jos Garca", 38, 1.82 };
...
que produce el mismo e$ecto que las sentencias
strcpy (registro.nombre, "Jos Garca");
registro.edad = 38;
registro.aItura = 1.82;
0nidamiento de estructuras
Es posi&le el anidamiento de estructuras, en el sentido de que un campo de
una estructura puede ser, a su ve1, una estructuraC 0e.moslo con un ejemplo:
struct FECHA {
int dia;
int mes;
int anyo;
};
struct CUMPLE {
char nombre[40];
struct FECHA nacim;
};
struct CUMPLE aniversario;
+a varia&le ani4ersario as@ de$inida tiene los siguientes campos:
ani4ersario.nombre
ani4ersario.nacim.dia
ani4ersario.nacim.mes
ani4ersario.nacim.an-o
El anidamiento de estructuras puede hacerse a m.s pro$undidad, en cu,o
caso el acceso a los campos de la varia&le se hace utili1ando sucesivamente
operadores puntoC
,atrices de estructuras
;no de los usos m.s ha&ituales de las estructuras son las matricesC %ara
declarar una matri1 de una estructura se hace como para cualquier otra varia&leC
%or ejemplo,
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
};
...
...
c**i
struct FICHA vector[100];
declara un vector de 122 elementos llamado 4ectorC #ada uno de los elementos
4ectorTiU, est. $ormado por los 3 campos de$inidos en la estructuraC +os campos
del elemento i de 4ector son:
4ectorTiU.nombre
4ectorTiU.edad
4ectorTiU.altura
4i alguno de los campos de la estructura es una matri1 Dcomo es el caso del
campo nombreE puede accederse a cada elemento de la $orma siguiente:
4ectorT11U.nombreT3U
que se re$iere al car.cter 3 del campo nombre del elemento 4ectorT11UC
:aso de estructuras a funciones
;n campo de una estructura puede pasarse como argumento de una $unci"n
del mismo modo que cualquier varia&le simpleC El siguiente pograma muestra en
pantalla, por medio de una $unci"n, un campo de una estructuraC
#incIude <stdio.h>
#incIude <conio.h>
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
};
void Funcion (int);
void main (void)
{
struct FICHA registro = { "Jos Garca", 37, 1.82 };
cIrscr ();
Funcion (registro.edad);
}
void Funcion (int n)
{
printf ("\nEdad: %d", n);
}
-am&i9n se puede pasar la direcci"n de un campo de una estructuraC ;n
programa similar al anterior, pero manejando la direcci"n del campo, es el
siguiente:
#incIude <stdio.h>
c**ii
#incIude <conio.h>
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
};
void Funcion (int *);
void main (void)
{
struct FICHA registro = { "Jos Garca", 37, 1.82 };
cIrscr ();
Funcion (&registro.edad);
}
void Funcion (int *n)
{
printf ("\nEdad: %d", *n);
}
%or Kltimo, tam&i9n podemos pasar la estructura completa como argumento
de una $unci"nC El siguiente ejemplo muestra c"mo hacerlo:
#incIude <stdio.h>
#incIude <conio.h>
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
};
void Funcion (struct FICHA);
void main (void)
{
struct FICHA registro = { "Jos Garca", 37, 1.82 };
cIrscr ();
Funcion (registro);
}
void Funcion (struct FICHA n)
{
printf ("\nFuncion3");
printf ("\nNombre: %s", n.nombre);
printf ("\nEdad: %d", n.edad);
printf ("\nAItura: %f", n.aItura);
}
:unteros a estructuras
c**iii
#uando las estructuras son complejas el paso de la estructura completa a una
$unci"n puede ralenti1ar los programas de&ido a la necesidad de introducir , sacar
cada ve1 todos los elementos de la estructura en la pilaC Es por ello por lo que es
conveniente recurrir a pasar s"lo la direcci"n de la estructura, utili1ando punterosC
;n puntero a una estructura se declara del mismo modo que un puntero a
cualquier otro tipo de varia&le, mediante el operador 9C %or ejemplo, la sentencia
struct MIESTR *p, var;
declara un puntero p a una estructura ,IE"TL , una varia&le 4ar con esa
estructuraC <espu9s de una declaraci"n como la anterior, puede hacerse una
asignaci"n como la siguiente:
p = &var;
que asigna a p la direcci"n de la varia&le 4arC
%ara acceder a los campos de la estructura mediante el puntero se hace
(9p).campo
4in em&argo esta sinta*is es antigua , est. $uera de usoC En su lugar se
utili1a el operador $lecha DAWE, $ormado por el gui"n DAE , el s@m&olo ma,or que
DWEC
p S> campo
El siguiente programa muestra en pantalla los campos de una estructura a
trav9s de un puntero que contiene su direcci"nC
#incIude <stdio.h>
#incIude <conio.h>
struct FICHA {
char nombre[40];
int edad;
fIoat aItura;
};
void main (void)
{
struct FICHA *p, registro = { "Jos Garca", 37, 1.82 };
cIrscr ();
p = &registro;
printf ("\nNombre: %s", p -> nombre);
printf ("\nEdad: %d", p -> edad);
printf ("\nAItura: %f", p -> aItura);
}
Campos de bits
c**iv
+os campos de &its son un caso particular de estructuras que permiten
acceder a los &its individuales de una pala&raC +a sinta*is que de$ine un campo de
&its es la siguiente:
struct nombre_estructura ?
ti"o variable12 ancho1A
ti"o variable22 ancho2A
...
...
ti"o variableN2anchoNA
@A
donde ti"o es uno de los tipos c&ar, unsigned c&ar, int o unsigned int, ,
anchoN es un valor de 2 a 16, que representa el ancho en &its del campo de &its
variableNC 4i no se pone nom&re al campo de &its, los &its especi$icados en ancho
se reservan, pero no son accesi&lesC
El siguiente ejemplo muestra una declaraci"n de campo de &its:
struct MIESTR {
int i: 2;
unsigned j: 5;
int : 4;
int k: 1;
unsigned m: 4;
};
struct MIESTR var;
Esta declaraci"n se corresponde con el siguiente diseFo de la pala&ra:
1# 1 13 12 11 11 . * + $ # 3 2 1 1
m ' no usados 7 i
+os campos de &its son Ktiles para almacenar varia&les l"gicas en un &,te,
para codi$icar los &its de un dispositivo, etcC El acceso a los campos de &its se
reali1a del mismo modo que a los campos de cualquier estructuraC -an s"lo ha,
que tener en cuenta un par de restricciones con los campos de &its: no se permiten
matrices , no se puede tra&ajar con direccionesC
+os campos de &its pueden presentar algKn pro&lema respecto de la
porta&ilidad de los programas de una m.quina a otraC 6qu@ se ha supuesto que los
campos $uncionan de i1quierda a derecha, pero eso puede cam&iar en otras
m.quinas, con lo que la interprestaci"n de los di$erente campos cam&iaC
c**v
Dniones
;na uni"n es una agrupaci"n de varia&les que ocupan la misma posici"n de
memoriaC 4e declaran de modo similar a las estructuras:
union nombre_unin ?
ti"o variable_1A
ti"o variable_2A
...
...
ti"o variable_NA
@A
#uando se declara una uni"n, las varia&les variable_1, variable_2, CCC,
variable_N ocupan la misma posici"n de memoriaC El compilador reserva el
tamaFo su$iciente para almacenar la varia&le m.s grandeC
Es importante advertir una di$erencia nota&le entre las estructuras DstructE ,
las uniones DunionEC En las primeras cada campo ocupa una posici"n de memoria
propia, , cuando se almacena un valor en uno de los campos, no in$lu,en en el
restoC %or el contrario, en las uniones todas las varia&les de la uni"n tienen
asignada la misma posici"n de memoria, lo cual implica que cuando se almacena un
dato en una de ellas, in$lu,e en todas las dem.sC 6claremos esto con un ejemplo
sencilloC 4ea la estructura
struct MIESTR {
char a;
int b;
fIoat c;
};
struct MIESTR mivar;
Esta declaraci"n asigna 5 &,tes de memoria para la varia&le mi4ar: uno para
el campo a, dos m.s para el campo b, , otros cuatro para el campo cC
mi4ar
$ # 3 2 1 1
c b a
4i hacemos una asignaci"n como
mivar.b = 120;
c**vi
no a$ecta a mi4ar.a ni a mi4ar.c, pues cada uno de ellos tiene asignadas
direcciones distintas de memoriaC
4in em&argo, sea la union
union MIUNION {
char a;
int b;
fIoat c;
};
union MIUNION mivar;
Esta declaraci"n asigna 4 &,tes de memoria para mi4ar Del campo m.s
grande de la uni"n es c, de 4 &,tesEC
mi4ar
3 2 1 1
a
b
c
4i ahora hacemos una asignaci"n como
mivar.b = 120;
a$ecta tanto a mi4ar.a como a mi4ar.cC
0eamos un ejemploC +as siguientes declaraciones utili1an las estructuras ,
uniones para almacenar datos de 122 alumnos , pro$esores de un #entro de
EnseFan1aC 4e almacena el tipo D6: alumno, %: pro$esorE, nom&re, edad, direcci"n
, tel9$onoC 4i es alumno se almacena, adem.s, el grupo al que pertenece, el nKmero
de asignaturas que cursa , si es o no repetidorC 4i es pro$esor se almacena el
nKmero de registro , el cargo que desempeFaC
c**vii
struct ALUMNO {
char grupo[15];
int asignat;
char repite;
};
struct PROFESOR {
char nrp[16];
char cargo[21];
};
union AL_PR {
struct ALUMNO aI;
struct PROFESOR pr;
};
struct DATOS {
char tipo;
char nombre[40];
int edad;
char direccion[40];
char teIefono[8];
union AL_PR ambos;
} personaI[100];
El siguiente segmento de progama muestra los datos de la matri1 personalC
for (i = 0; i < 100; i++) {
printf ("\nNombre: %s", personaI[i].nombre);
printf ("\nEdad: %d", personaI[i].edad);
printf ("\nDireccin: %s", personaI[i].direccion);
printf ("\nTeIfono: %s", personaI[i].teIefono);
if (personaI[i].tipo == 'A') {
printf ("\nALUMNO");
printf ("\nGrupo: %s", personaI[i].ambos.aI.grupo);
printf ("\nN de Asignaturas: %d", personaI[i].ambos.aI.asignat);
printf ("\nRepite: %d", personaI[i].ambos.aI.repite); }
eIse {
printf ("\nPROFESOR");
printf ("\nN.R.P.: %s", personaI[i].ambos.pr.nrp);
printf ("\nCargo: %s", personaI[i].ambos.pr.cargo);
}
}
#om&inando estructuras, uniones , campos de &its podemos de$inir varia&les
de 16 &its con acceso por &it, &,te o pala&raC
struct BITS {
unsigned bit0: 1;
unsigned bit1: 1;
unsigned bit2: 1;
unsigned bit3: 1;
unsigned bit4: 1;
unsigned bit5: 1;
unsigned bit6: 1;
unsigned bit7: 1;
unsigned bit8: 1;
unsigned bit9: 1;
c**viii
unsigned bit10: 1;
unsigned bit11: 1;
unsigned bit12: 1;
unsigned bit13: 1;
unsigned bit14: 1;
unsigned bit15: 1;
};
struct BYTES {
unsigned byte0: 8;
unsigned byte1: 8;
};
union PALABRA {
int x;
struct BYTES byte;
struct BITS bit;
} dato;
6hora, mediante dato podemos acceder a la pala&ra completa Ddato.(E, a
uno de los dos &,tes Ddato.b-te.b-te<E, o a &its individuales Ddato.bit.bit<EC
0amos a utili1ar la $unci"n de la &i&lioteca est.ndar bioseKuip() en un
programa quehace uso de esta capacidadC +a $unc"n bioseKuip() devuelve una
pala&ra con la siguiente in$ormaci"n:
bits 1S1# >Kmero de impresoras paralelo
bit 13 !mpresoria serie instalada
bit 12 ]o,sticG instalado
bits .S11 >Kmero de puertos #)/
bit * #hip </6 instalado D2: 4c, 1: >)E
bits $S+ >i de disqueteras Dsi bit1 B 1E
22: 1 disquetera
21: 2 disqueteras
12: 3 disqueteras
11: 4 disqueteras
bits S# /odo inicial de v@deo
22: >o usado
21: 42*2( B>, adaptador color
12: 82*2( B>, adaptador color
11: 82*2( B>, adaptador monogr.$ico
bits 2S3 '6/ en placa &ase
22: 16G
21: 32G
12: 48G
11: 64G
bit 1 #oprocesador matem.tico 82*85 instalado
bit 1 6rranque desde disquete
El siguiente programa presenta en pantalla la in$ormaci"n proporcionada por
bioseKuip()C
#incIude <stdio.h>
#incIude <conio.h>
#incIude <bios.h>
c**i*
struct BIOSEQUIP {
unsigned arranque: 1;
unsigned cop80x87: 1;
unsigned RAM_base: 2;
unsigned video: 2;
unsigned discos: 2;
unsigned DMA: 1;
unsigned puertos: 3;
unsigned juegos: 1;
unsigned serie: 1;
unsigned paraIeIo: 2;
};
union EQUIPO {
int paIabra;
struct BIOSEQUIP bits;
};
void Presentar (void);
void main (void)
{
union EQUIPO bios;
bios.paIabra = biosequip ();

cIrscr ();
Presentar ();

gotoxy (31, 1);
if (bios.bits.cop80x87) puts ("SI");
eIse puts ("NO");
gotoxy (31, 2);
printf ("%d Kb", (bios.bits.RAM_base + 1) * 16);
gotoxy (31, 3);
switch (bios.bits.video) {
case 1: puts ("40x25 BIanco y Negro, Adaptador CoIor");
break;
case 2: puts ("80x25 BIanco y Negro, Adaptador CoIor");
break;
case 3: puts ("80x25 BIanco y Negro, Adaptador Monocromo");
}
gotoxy (31, 4);
if (bios.bits.arranque) printf ("%d", bios.bits.discos + 1);
eIse puts ("0");
gotoxy (31, 5);
if (bios.bits.DMA) puts ("NO");
eIse puts ("SI");
gotoxy (31, 6);
printf ("%d", bios.bits.puertos);
gotoxy (31, 7);
if (bios.bits.juegos) puts ("SI");
eIse puts ("NO");
c***
gotoxy (31, 8);
printf ("%d", bios.bits.serie);
gotoxy (31, 9);
printf ("%d\n", bios.bits.paraIeIo);
}
void Presentar (void)
{
puts ("Coprocesador Matemtico ..... ");
puts ("RAM en pIaca base ........... ");
puts ("Modo iniciaI de vdeo ....... ");
puts ("N unidades de disquete ..... ");
puts ("Chip DMA .................... ");
puts ("N de puertos COM ........... ");
puts ("Joystick .................... ");
puts ("Impresora serie ............. ");
puts ("Impresoras paraIeIo ......... ");
}
Enumeraciones
4on grupos de constantes agrupadas de modo similar a las estructuras , que
permiten controlar el rango de una varia&leC +a sinta*is que permite de$inir una
enumeraci"n es:
enum nombre_enumeracin ?
constante1A
constante2A
...
...
constanteNA
@ variableA
siendo nombre_enumeracin el identi$icador que da nom&re a la enumeraci"n, ,
variable la varia&le que puede tomar los valores de$inidos para constante1,
constante2, CCC, constanteNC Estas constantes asumen los valores 2, 1, 2, CCC, >C %or
ejemplo:
enum COLORES {
NEGRO;
AZUL;
VERDE;
CYAN;
ROJO;
MORADO;
AMARILLO;
BLANCO;
} coIor;
%ara una enumeraci"n como la anterior, la sentencia
c***i
printf ("%d %d", AZUL, MORADO);
mostrar@a en pantalla los valores 1 , (C -am&i9n son posi&les sentencias del tipo
switch (coIor) {
case NEGRO: ...
break;
case AZUL: ...
...
...
defauIt: ...
}
Es importante no olvidar que los valores de$inidos con los identi$icadores
<EML/, 0aD6, etc9tera, no son varia&les sino constantesC
Es posi&le modi$icar el rango de valores de una enumeraci"n, iniciali1ando
las constantes en el momento de la declaraci"nC 6s@, la enumeraci"n
enum VALORES {
CTE1;
CTE2;
CTE3 = 25;
CTE4;
CTE5 = 31;
};
de$ine las constantes de la enumeraci"n con los siguientes valores
CTE1: 0
CTE2: 1
CTE3: 25
CTE4: 26
CTE5: 31
c***ii
E7ercicios
1. <eseamos hacer un listado de precios de los art@culos de la empresa
8;!EB'6,4C6C +os datos a procesar para cada art@culo son los siguientes:
Cdigo del artGculo: #adena de 3 caracteresC
;escripcin: #adena de 42 caracteresC
Componentes: /atri1 de ( elementosC #ada elemento de esta matri1
contendr. los siguientes campos:
1C Cdigo del componente: #adena de 8 caracteresC
2C Cantidad: Entero entre 1 , 122C
3C :recio unitario: Entero entre (22 , (222C
#onstru,e un programa que realice las siguientes tareas:
aE #apturar por teclado los datos de los art@culos, almacen.ndolos en una
matri1 Dm.*imo, 2( art@culosEC
&E !mprimir los datos de la matri1 con el $ormato siguiente:
dDIE3L08 ".0. 6istado de precios :gina2RRR
C/,:/<E<TE"
Cod ;escripcin Cdigo Cant :recio Importe
((( ((((((((((((((((((((((((( (((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
Total2 (((((((
((( ((((((((((((((((((((((((( (((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
(((((((( ((((( (((((( (((((((
Total2 (((((((
... ... ... ... ... ...
... ... ... ... ... ...
... ... ... ... ... ...
... ... ... ... ... ...
!mprime ( art@culos en cada p.ginaC
c***iii
2. +a $unci"n J2 de la !>- 15h devuelve el estado de un puerto paralelo
especi$icado con el registro <BC +os requerimientos previos de la $unci"n
son:
6Q M 2
<B M >i del puerto paralelo
2 A +%-1:
1 A +%-2:
CCC
CCC
+a $unci"n devuelve en 6Q el estado del puertoC +os &its de 6Q de&en
interpretarse como sigue:
bit 1 +a impresora no respondi" en el tiempo previsto
bits 1S2 >o usados
bit3 Error de E34
bit !mpresora seleccionada
bit# 4in papel
bit$ 'econocimiento de impresora D6cuse de reci&o 6#?E
bit+ !mpresora li&re
#onstru,e un programa que muestre esta in$ormaci"n para el primer puerto
paralelo D+%-1:EC
.
0signacin dinmica
de memoria
0lmacenamiento esttico - dinmico
+a $orma convencional de almacenar las varia&les en memoria se denomina
almacenamiento esttico: al principio del programa se declaran las varia&les , se
reserva la cantidad de memoria necesariaC Este es el sistema que hemos utili1ado
hasta el momento en todos los ejercicios , ejemplosC #on este m9todo cuando un
programa utili1a una matri1, previamente decidimos el tamaFo m.*imo que
necesita , declaramos la matri1 de acuerdo a ese tamaFo m.*imoC %or ejemplo, si
el programa usa una matri1 &idimensional de enteros , suponemos que el m.*imo
de $ilas , de columnas que precisar. es de 122*122, haremos una declaraci"n como
c***iv
int matriz[100][100];
con lo que estaremos reservando 122 * 122 * 2 M 22222 &,tes de memoria al inicio
del programa Den el supuesto de que est9n disponi&lesE , permanecer.n reservados
durante todo el programa, independientemente de que se usen o no para almacenar
valoresC
Este tipo de almacenamiento presenta algKn inconvenienteC Fij9monos en el
Ejercicio 3 del #ap@tulo 5 Dp.gina 118E en el que se constru,e un cuadrado m.gicoC
En ese programa se tra&aja con una matri1 cu,a dimensi"n puede ir desde 3*3
hasta 1*1C %ara el cuadrado de dimensi"n m@nima se necesitan 18 &,tes de
memoriaO cuando se usa la m.*ima dimensi"n son necesarios 522 &,tesC %ero,
independientemente del cuadrado m.gico que se desee construir, hemos de
declarar la matri1 del tamaFo m.*imo, , cuando se constru,a el cuadrado de
ordenes in$eriores a 1 estaremos malgastando cierta cantidad de memoriaC En este
programa esto no es demasiado importante, pero s@ lo es para otros que usen
matrices ma,oresC 4i el ejercicio re$erido tratase con cuadrados de "rdenes mu,
grandes, la cantidad de memoria malgastada podr@a ser mu, importanteC Basta
$ijarse en que una matri1 de enteros de orden (22*(22 necesita, apro*imadamente,
2C( /& de almacenamiento est.ticoC
+a alternativa ideal ser@a que el programa pudiese solicitar al sistema la
cantidad de memoria precisa en cada casoC %ara el cuadrado m.gico se tratar@a de
pedir al sistema 18 &,tes para el orden 3*3 , 522 &,tes cuando se constru,a el
cuadrado de orden 1*1C Esto se consigue con la asignacin dinmica de
memoria, mediante la cual el programa va requiriendo al sistema la memoria que
necesita , devolviendo la que ,a no es necesariaC %ara ello se utili1an las $unciones
malloc() , free(), que estudiaremos en el pr"*imo apartadoC
+a memoria asignada din.micamente se toma de una 1ona denominada
montn DheapE , su tamaFo es varia&le, dependiendo del modelo de memoria

usado para compilar el programaC
B.sicamente, la $orma de situar en la memoria datos , c"digo de un
programa atiende al siguiente esquema:
;irecciones altas :I60
(;atos locales)
,/<Tg<
(;atos dinmicos)
;atos globales
;irecciones ba7as
Cg;IM/
9
Los modelos de memoria se estudian en el Captulo 12.
c***v
El tamaFo para las 1onas de c"digo , de datos de vida glo&al permanece
constante durante todo el programaC +a pila crece hacia a&ajo , en ella se
almacenan las varia&les de .m&ito local utili1adas por las $uncionesC El mont"n,
tam&i9n denominado 5ona de almacenamiento libre, crece hacia arri&a, a medida
que se asigna memoria din.micamente a petici"n del programaC En algunos casos
la pila puede solapar parte del mont"nC -am&i9n puede ocurrir que el mont"n no
pueda satis$acer todas las demandas de memoria del programaC Estos pro&lemas
pueden controlarse con las $unciones de asignaci"n din.mica de #C
6as funciones malloc() - free()
4on las dos $unciones &.sicas para la asignaci"n din.mica de memoriaC #on
la $unci"n malloc() se solicita memoria del mont"nC #on la $unci"n free() se
devuelve memoria al mont"nC
El prototipo para la $unci"n malloc() es
4oid 9malloc (si5e[t tama)A
, est. de$inido en stdlib.& , alloc.&C Esta $unci"n asigna un &loque de tama &,tes
del mont"nC 4i la cantidad de memoria solicitada est. disponi&le, malloc()
devuelve un puntero a la 1ona de memoria asignadaC En caso contrario, devuelve
un puntero nuloC El tipo 4oid 9 indicado en el prototipo quiere decir que el puntero
devuelto por malloc() puede D, de&eE trans$ormarse a cualquier tipoC El siguiente
ejemplo solicita memoria para 122 datos enteros:
int *bIoque;
...
...
bIoque = maIIoc (200);
if (!bIoque) {
puts ("Memoria insuficiente");
Funcion_error ();
}
4i la $unci"n malloc() tiene 9*ito, el puntero bloue tendr. la direcci"n de
una 1ona de 222 &,tes del mont"nC En caso contrario de&emos $inali1ar el
programa o ejecutar una rutina de errorC Qa, que poner especial cuidado en no
tra&ajar con punteros nulos, puesto que ello provoca, generalmente, la caida del
sistemaC
6unque el ejemplo anterior es correcto, se recomienda hacer la llamada a
malloc() de la $orma siguiente:
int *bIoque;
...
...
bIoque = (int *) maIIoc (100 * sizeof (int));
if (!bIoque) {
c***vi
puts ("Memoria insuficiente");
Funcion_error ();
}
pues asegura la transporta&ilidad del c"digoC
+a $unci"n free() tiene como prototipo
4oid free (4oid 9bloue)A
, precisa la inclusi"n del archivo de ca&ecera alloc.&C Esta $unci"n devuelve al
mont"n el &loque de memoria apuntado por bloue, siendo bloue un puntero
proporcionado por una llamada previa a malloc()C +a memoria devuelta por free()
puede volver a ser asignada por otra llamada a malloc()C
El programa de la p.gina siguiente ilustra el uso de am&as $uncionesC En 9l se
solicita memoria para almacenar una cadena de caracteres de longitud varia&leC
4"lo se usar. la memoria necesaria dada por la longitud de la cadenaC
#incIude <stdio.h>
#incIude <conio.h>
#incIude <aIIoc.h>
#incIude <stdIib.h>
#incIude <process.h>
void main (void)
{
char *cadena;
int N;
cIrscr ();
puts ("EJEMPLO DE ASIGNACIN DINMICA DE MEMORIA");
printf ("Longitud de Ia cadena: ");
scanf ("%d", &N);
getchar ();
..Elimina el @nro de la enrada
cadena = (char *) maIIoc (N + 1); ..N E 5 para incluir el nulo final
if (!cadena) {
puts ("\nMEMORIA INSUFICIENTE");
exit (1); }
eIse printf ("\nDireccin asignada: %p", cadena);
printf ("\nTecIea %d caracteres: ", N);
gets (cadena);
printf ("\nHas tecIeado: %s", cadena);
free (cadena);
}
)tras $unciones de asignaci"n din.mica de -ur&o # son: allocmem(),
calloc(), coreleft(), farcalloc(), farmalloc() , realloc()C
,atrices asignadas dinmicamente
c***vii
El programa mencionado anteriormente del cuadrado m.gico ilustra &astante
&ien una de las situaciones en que es conveniente usar programaci"n din.mica: el
programa maneja una matri1 cu,o tamaFo no puede determinarse a prioriC
El siguiente programa resuelve el ejercicio del cuadrado m.gico utili1ando
asignaci"n din.mica de memoriaC 6unque en este caso no es necesario, se mantiene
la limitaci"n del orden m.*imo a 1*1, por ra1ones de presentaci"n en pantallaC
6dem.s se supone que las $unciones Intro() , "trdigit() se encuentran en m"dulos
o&jeto separados que se enla1ar.n posteriormente
12
C
#incIude <stdio.h>
#incIude <conio.h>
#incIude <stdIib.h>
#incIude <string.h>
#incIude <ctype.h>
#incIude <aIIoc.h>
#incIude <process.h>
void main (void)
{
int *magico, *p;
int i, j, ant_i, ant_j, orden, tope;
register int vaIor;
char N[3];
cIrscr ();
puts ("CUADRADO MGICO DE ORDEN N IMPAR (3 a 19)");
do {
do {
printf ("\nVaIor de N: ");
Intro (wherey (), wherex (), 2, N);
} whiIe (!Strdigit (N));
orden = atoi (N);
} whiIe (orden < 3 || orden > 19 || !(orden % 2));
tope = orden * orden;
magico = (int *) maIIoc (tope * sizeof (int));
if (!magico) {
puts ("\nMemoria insuficiente");
exit (1);
}
for (i = 0; i < orden; i++) {
for (j = 0; j < orden; j++) {
p = magico + i * orden + j; ..+ireccin de
ma=icoFiGFDG
*p = 0;
}
}
i = 0;
j = orden / 2;
for (vaIor = 1; vaIor <= tope; vaIor++) {
10
La compilacin y enlazado independientes del entorno integrado de programacin
de Turbo C se estudian en el Captulo 12.
c***viii
p = magico + i * orden + j; ..+ireccin de
ma=icoFiGFDG
if (*p) {
i = ant_i + 1;
j = ant_j;
if (i > orden - 1) i = 0;
}
p = magico + i * orden + j; ..+ireccin de
ma=icoFiGFDG
*p = vaIor;
ant_i = i--;
ant_j = j++;
if (i < 0) i = orden - 1;
if (j > orden - 1) j = 0;
}
cIrscr ();
for (i = 0; i < orden; i++) {
for (j = 0; j < orden; j++) {
p = magico + i * orden + j; ..+ireccin de
ma=icoFiGFDG
printf ("%3d ", *p);
}
printf ("\n");
}
free (magico);
}
Colas dinmicas
;na cola es una estructura F!F) D)irst In, )irst /utE, es decir, el primer
elemento que entra en la estructura es el primero en salirC +as colas se ajustan mu,
&ien al tipo de estructuras suscepti&les de programarse din.micamente, pues son
estructuras que crecen , se contraen a medida que la in$ormaci"n entra , sale de
ellasC
%ara programar din.micamente este tipo de estructuras Dcomo las pilas, los
.r&oles &inarios, etcCE es necesario recurrir a las estructuras autoreferenciadasC
;na estructura autore$erenciada se de$ine, &.sicamente, de la siguiente $orma:
struct nombre_estructura ?
cam"o_de_nformacin1A
cam"o_de_informacin2A
...
...
cam"o_de_informacinNA
struct nombre_estructura enlace1A
struct nombre_estructura enlace2A
...
...
struct nombre_estructura enlaceNA
c***i*
@A
es decir, ha, uno o varios campos en los que se almacena la in$ormaci"n que se
desee, , uno o varios campos de enlace con otros elementosC %ara el caso de una
cola din.mica de nKmeros enteros cada elemento de&e enla1ar con el siguiente
mediante una estructura autore$erenciada como la siguiente:
struct C/60 ?
int datoA
struct C/60 9enlaceA
@A
siendo dato el nKmero entero que se almacena en la cola, , enlace un puntero a la
estructura del siguiente elemento de la colaC
El siguiente programa gestiona una cola din.mica de nKmeros enteros
positivosC El $uncionamiento del programa se &asa en un menK de opciones , en
dos $unciones, Introducir() , "acar(), que controlan la entrada3salida de los datos
en la colaC
+a $unci"n Introducir()reali1a las siguientes operaciones:
+lama a malloc() para solicitar memoria para el nuevo elementoC En caso
de que no ha,a memoria disponi&le, la $unci"n devuelve un valor 2C
6lmacena el dato en la direcci"n asignada mediante malloc()C
'ecorre toda la cola desde el principio para locali1ar el Kltimo elemento, a
partir del cual de&e incluirse el nuevoC
Enla1a el elemento que antes era el Kltimo con el nuevo elemento
introducido en la colaC
<evuelve un valor 1C
+a $unci"n "acar() e$ectKa las siguientes operaciones:
#omprue&a si la cola est. vac@a, en cu,o caso devuelve un valor A1C
)&tiene la in$ormaci"n del primer elemento de la colaC
Qace que el segundo elemento de la cola sea el primero, apunt.ndolo con
el puntero del elemento que se sacaC
<evuelve al mont"n mediante free() la memoria ocupada por el elemento
que se sacaC
<evuelve el valor e*tra@doC
El programa completo se muestra a continuaci"n:
#incIude <stdio.h>
#incIude <conio.h>
#incIude <stdIib.h>
#incIude <aIIoc.h>
struct COLA {
int dato;
c*l
struct COLA *enIace;
};
int Menu (void);
int Introducir (int n);
int Sacar (void);
struct COLA *primero;
void main (void)
{
int vaIor, opcion, st;
primero = 0;
whiIe ((opcion = Menu ()) != 3) {
switch (opcion) {
case 1: printf ("\nVaIor a introducir en Ia coIa: ");
scanf ("%d", &vaIor);
if (!Introducir (vaIor)) {
puts ("\nMemoria agotada. PuIse una tecIa ...");
whiIe (!getch ());
}
break;
case 2: vaIor = Sacar ();
if (vaIor < 0) puts ("\nCoIa vaca");
eIse printf ("\nVaIor obtenido: %d", vaIor);
printf ("\nPuIse una tecIa ...");
whiIe (!getch ());
}
}
}
int Menu (void)
{
int n;
cIrscr ();
puts ("COLA DINMICA\n");
puts ("1. Introducir");
puts ("2. Sacar");
puts ("3. SaIir\n");
do {
n = getch ();
} whiIe (n < '1' || n > '3');
return n - 48;
}
int Introducir (int n)
{
struct COLA *nuevo, *actuaI, *anterior;
nuevo = (struct COLA *) maIIoc (sizeof (struct COLA));
if (!nuevo) return 0;
nuevo -> dato = n;
nuevo -> enIace = 0;
if (!primero) primero = nuevo;
eIse {
actuaI = primero;
c*li
whiIe (actuaI) {
anterior = actuaI;
actuaI = anterior -> enIace;
}
anterior -> enIace = nuevo;
}
return 1;
}
int Sacar (void)
{
struct COLA *antprimero;
int n;
if (!primero) return -1;
eIse {
antprimero = primero;
n = primero -> dato;
primero = primero -> enIace;
free (antprimero);
return n;
}
}
E7ercicios
1. #onstru,e un programa que gestione una pila de enteros con asignaci"n
din.mica de memoriaC El programa presentar. un menK con las opciones
1C !ntroducir
2C 4acar
3C 4alir
El programa dispondr. de $unciones Introducir() , "acar() similares a las
utili1adas en el apartado I#olas din.micasI del cap@tuloC
11
)ic&eros
Canales - fic&eros
c*lii
Ya qued" dicho que toda la E34 en # se hace mediante $unciones de &i&liotecaC
Esto, que ,a se estudi" para la E34 por consola, se estudiar. en este cap@tulo para la
E34 so&re cualquier dispositivo, en particular so&re archivos de discoC
El sistema de E34 del 6>4! # proporciona un intermediario entre el
programador , el dispositivo al que se accedeC Este intermediario se llama canal o
flu7o , es un &u$$er independiente del dispositivo al que se conecteC 6l dispositivo
real se le llama arc&i4o o fic&eroC %or tanto, programa , archivo est.n conectados
por medio de un canal , la misma $unci"n permite escri&ir en pantalla, impresora,
archivo o cualquier puertoC E*isten dos tipos de canales:
Canales de te(to: 4on secuencias de caracteresC <ependiendo del entorno
puede ha&er conversiones de caracteres D+F #' L +FEC Esto hace que el
nKmero de caracteres escritos3le@dos en un canal pueda no coincidir con el
nKmero de caracteres escritos3le@dos en el dispositivoC
Canales binarios: 4on secuencias de &,tesC 6 di$erencia de los canales de
te*to, en los canales &inarios la correspondencia de caracteres en el canal ,
en el dispositivo es 1 a 1, es decir, no ha, conversionesC
;n archivo es, por tanto, un concepto l"gico que se puede asociar a cualquier
cosa suscepti&le de reali1ar con ella operaciones de E34C %ara acceder a un archivo
ha, que relacionarlo con un canal por medio de una operaci"n de apertura que se
reali1a mediante una $unci"n de &i&liotecaC %osteriormente pueden reali1arse
operaciones de lectura3escritura que utili1an &K$ers de memoriaC %ara estas
operaciones ha, disponi&le un amplio conjunto de $uncionesC %ara desasociar un canal
de un archivo es necesario reali1ar una operaci"n de cierreC Qa, ( canales que se
a&ren siempre que comien1a un programa #C 4on:
stdin #anal est.ndar de entradaC %or de$ecto el tecladoC D6>4!E
stdout #anal est.ndar de salidaC %or de$ecto la pantallaC D6>4!E
stderr #anal est.ndar de salida de erroresC %or de$ecto la pantallaC D6>4!E
stdau( #anal au*iliar Dcanal serie #)/1EC D6 partir de -ur&o # v2C2E
stdprn #anal para la impresoraC D6 partir de -ur&o # v2C2E
0brir - cerrar fic&eros
%ara poder manejar un $ichero es necesario asociarle un canalC Esto se consigue
mediante una operaci"n de apertura que se reali1a mediante la $unci"n de &i&lioteca
fopen(), que devuelve un puntero al canal que se asociaC El prototipo de esta $unci"n
est. de$inido en stdio.& , es el siguiente:
)I6E 9fopen (const c&ar 9nombre8 const c&ar 9modo)A
Esta $unci"n a&re el $ichero nombre , le asocia un canal mediante el puntero a
)I6E que devuelveC El tipo de dato )I6E est. de$inido tam&i9n en stdio.& , es una
estructura que contiene in$ormaci"n so&re el $icheroC #onsta de los siguientes
campos:
typedef struct {
c*liii
short IeveI; ..ni&el de ocupacin del
/uffer
unsigned fIags; ..indicadores de conrol
char fd; ..descripor del
fichero 1nH *ue lo idenifica2
char hoId; ..carBcer de un=ec12
11
short bsize; ..amaIo del /uffer
unsigned char *buffer; ..punero al /uffer
unsigned char *curp; ..posicin en curso
short token; ..se usa para conrol
} FILE;
>o de&e tocarse ninguno de los campos de esta estructura a menos que se sea
un programador mu, e*pertoC #ualquier cam&io no controlado en los valores de esas
varia&les, posi&lemente daFar@a el archivoC 4i se produce cualquier error en la
apertura del $ichero, fopen() devuelve un puntero nulo , el $ichero queda sin canal
asociadoC
+os valores posi&les del par.metro modo se muestran en la ta&la siguiente:
HODO DESCRIPCIN
r Abre un 'ic?ero s6lo para lecturaB Si el 'ic?ero no eFiste 6%#!n)*
de!uel!e un puntero nulo : se *enera un errorB
\ .rea un nue!o 'ic?ero para escrituraB Si :a eFiste un 'ic?ero con
este nombreD se sobreescribeD perdiEndose el contenido anteriorB
a Abre o crea un 'ic?ero para aTadirB Si el 'ic?ero eFisteD se abre
apuntando al 'inal del mismoB Si no eFiste se crea uno nue!oB
r2 Abre un 'ic?ero para leer : escribirB Si el 'ic?ero no eFiste 6%#!n)*
de!uel!e un puntero nulo : se *enera un errorB Si eFisteD pueden
realizarse sobre El operaciones de lectura : de escrituraB
\2 .rea un nue!o 'ic?ero para leer : escribirB Si :a eFiste un 'ic?ero
con este nombreD se sobreescribeD perdiEndose el contenido
anteriorB Sobre el arc?i!o pueden realizarse operaciones de lectura
: de escrituraB
a2 Abre o crea un 'ic?ero para leer : aTadirB Si el 'ic?ero :a eFiste se
abre apuntando al 'inal del mismoB Si no eFiste se crea un 'ic?ero
nue!oB
%ara indicar si el canal asociado al $ichero es de te*to o &inario, se aFade al
modo la letra t o b, respectivamenteC 6s@, si modo es rt, se est. a&riendo el $ichero en
modo te*to s"lo para lectura, mientras que si modo es %Qb se a&rir. o crear. un
$ichero en modo &inario para lectura , para escritura
12
C
%ara cerrar un $ichero , li&erar el canal previamente asociado con fopen(), se
de&e usar la $unci"n fclose() de$inida en stdio.& , cu,o prototipo es
int fclose ()I6E 9canal)A
11
Esta $unci"n tiene como prototipo int ungetc (int car!cter8 )I6E 9canal)A , devuelve car!cter al canal de entrada canal, lo
que permite que pueda volver a ser leidoC
12
#uando no se indica ninguno de los modos b o t el modo de apertura est. go&ernado por la varia&le glo&al [fmodeC 4i est.
iniciali1ada con el valor /[3I<0L`, los $icheros se a&ren en modo &inarioC 4i est. iniciali1ada como /[TERT, se a&ren en modo te*toC
Estas constantes est.n de$inidas en fcntl.&C
c*liv
Esta $unci"n devuelve 1 si la operaci"n de cierre ha tenido 9*ito, , E/) en
caso de errorC E/) es una macro de$inida en stdio.& de la siguiente $orma:
#define EOF (-1)
El siguiente programa a&re s"lo para lectura un $ichero de nom&re
<6-)4C<6- ,, posteriormente lo cierraC
#incIude <stdio.h>
#incIude <process.h> ..Para e%i12
void main (void)
{
FILE *f;
int st;
f = fopen ("DATOS.DAT", "rt");
if (!f) {
puts ("Error aI abrir eI fichero");
exit (1);
}
..A*uJ &endrJan las operaciones so/re el fichero
st = fcIose (f);
if (st) puts ("Error aI cerrar eI fichero");
}
Es ha&itual escri&ir la sentencia de apertura del $ichero como sigue:
if (!(f = fopen ("DATOS.DAT", "rt"))) {
puts ("Error aI abrir eI fichero");
exit (1);
}
Control de errores - de fin de fic&ero
#ada ve1 que se reali1a una operaci"n de lectura o de escritura so&re un $ichero
de&emos compro&ar si se ha producido algKn errorC %ara ello disponemos de la
$unci"n ferror() cu,o prototipo, de$inido en stdio.&, es
int ferror ()I6E 9canal)A
Esta $unci"n devuelve 1 si la Kltima operaci"n so&re el $ichero se ha reali1ado
con 9*itoC Qa, que tener en cuenta que todas las operaciones so&re el $ichero a$ectan
a la condici"n de error, por lo que de&e hacerse el control de error inmediatamente
despu9s de cada operaci"n o, de lo contrario, la condici"n de error puede perderseC
+a $orma de invocar esta $unci"n puede ser
if (ferror (f)) puts ("Error de acceso aI fichero");
c*lv
siendo f un puntero a )I6EC
4e puede conseguir un mensaje asociado al Kltimo error producido mediante la
$unci"n perror() cu,o prototipo, de$inido en stdio.&, es
4oid perror (const c&ar 9cadena)A
Esta $unci"n env@a a stderr Dgeneralmente la pantallaE la cadena indicada en el
argumento, dos puntos ,, a continuaci"n, un mensaje del sistema asociado al Kltimo
error producidoC +a $orma en que se relaciona el error con el mensaje es mediante una
varia&le glo&al prede$inida llamada errno Dde$inida en errno.&E que se activa cuando
se producen erroresC %or ejemplo, dado el segmento de programa
FILE *f;
if (!(f = fopen ("DATOS.DAT", "rb"))) {
printf ("\nError %d. ", errno);
perror ("DATOS.DAT");
exit (1);
}
si no e*iste el $ichero <6-)4C<6- se env@a a pantalla el mensaje
Error 2. ;0T/".;0T2 <o suc& file or director-
#ada ve1 que se reali1a una operaci"n de lectura so&re un $ichero, el indicador
de posici"n del $ichero se actuali1aC Es necesario, pues, controlar la condici"n de $in
de $icheroC %or ello, de&emos sa&er que cuando se intentan reali1ar lecturas m.s all.
del $in de $ichero, el car.cter le@do es siempre E/)C 4in em&argo en los canales
&inarios un dato puede tener el valor E/) sin ser la marca de $in de $icheroC Es
aconseja&le, por ello, e*aminar la condici"n de $in de $ichero mediante la $unci"n
feof(), cu,o prototipo, de$inido en stdio.&, es
int feof ()I6E 9canal)A
Esta $unci"n devuelve un valor di$erente de cero cuando se detecta el $in de
$icheroC
;n algoritmo que lea todo un archivo puede ser el siguiente:
#incIude <stdio.h>
#incIude <process.h>
void main (void)
{
FILE *f;
if (!(f = fopen ("DATOS.DAT", "rt"))) {
perror ("\nDATOS.DAT");
exit (1);
}
..operacin de lecura so/re +ATO?0+AT
c*lvi
whiIe (!feof (f)) {
..raamieno
..operacin de lecura so/re +ATO?0+AT
}
fcIose (f);
if (ferror (f)) puts ("Error aI cerrar eI archivo DATOS.DAT");
}
E!" de caracteres
%ara leer caracteres individuales de un $ichero se utili1a la $unci"n
int fgetc ()I6E 9canal)A
o su macro equivalente
int getc ()I6E 9canal)A
6m&as est.n de$inidas en stdio.& , son completamente id9nticasC <evuelven el
car.cter le@do e incrementan el contador de posici"n del $ichero en 1 &,teC 4i se
detecta la condici"n de $in de $ichero, devuelven E/), pero para canales &inarios es
mejor e*aminar dicha condici"n mediante feof()C
%ara escri&ir caracteres individuales en un $ichero se utili1a la $unci"n
int fputc (int car!cter8 )I6E 9canal)A
o su macro equivalente
int putc (int car!cter8 )I6E 9canal)A
6m&as tienen el prototipo de$inido en stdio.& , son completamente id9nticasC
Escri&en el car.cter indicado en el argumento Dque puede ser tam&i9n una varia&le
c&arE en el $ichero asociado a canalC 4i no ha, error, devuelven el car.cter escritoO en
caso contrario devuelven E/)C
El siguiente programa copia car.cter a car.cter el $ichero <6-)4C<6- en
#)%!6C<6-C
#incIude <stdio.h>
#incIude <process.h>
void main (void)
{
FILE *fent, *fsaI;
char caracter;
if (!(fent = fopen ("DATOS.DAT", "rb"))) {
perror ("DATOS.DAT");
c*lvii
exit (1);
}
if (!(fsaI = fopen ("COPIA.DAT", "wb"))) {
perror ("COPIA.DAT");
exit (1);
}
caracter = getc (fent);
whiIe (!feof (fent)) {
putc (caracter, fsaI);
if (ferror (fsaI)) puts ("No se ha escrito eI carcter");
caracter = getc (fent);
}
fcIose (fent);
fcIose (fsaI);
}
+a misma operaci"n puede reali1arse en una sola l@nea mediante
whiIe (!feof (fent)) putc (getc (fent), fsaI);
E*isten dos $unciones an.logas a getc() , putc() pero para leer , escri&ir
enteros en lugar de caracteres:
int get% ()I6E 9canal)A
int put% (int entero8 )I6E 9canal)A
6m&as est.n de$inidas en stdio.& , la Knica di$erencia con getc() , putc() est.
en que se procesan dos &,tes en cada operaci"nC Estos dos &,tes de&en interpretarse
como un nKmero enteroC +a $unci"n get%() no de&e usarse con $icheros a&iertos en
modo te*toC
E!" de cadenas de caracteres
%ara leer cadenas de caracteres se utili1a la $unci"n
c&ar 9fgets (c&ar 9cadena8 int n8 )I6E 9canal)A
cu,o prototipo est. de$inido en stdio.&C Esta $unci"n lee caracteres del $ichero
asociado a canal , los almacena en cadenaC En cada operaci"n de lectura se leen
n - 1 caracteres, a menos que se encuentre primero un car.cter nueva l@nea Dque
tam&i9n se almacena en cadenaEC 4i no se produce error, la $unci"n devuelve un
puntero a cadenaO en caso contrario, devuelve un puntero nuloC
El siguiente programa muestra el contenido del $ichero 6;-)EBE#CB6-,
numerando las l@neasC 4e supone que ninguna l@nea tiene m.s de 82 caracteresC
c*lviii
#incIude <stdio.h>
#incIude <process.h>
void main (void)
{
FILE *f;
register int i = 1;
char cadena[81];
if (!(f = fopen ("AUTOEXEC.BAT", "rt"))) {
perror ("AUTOEXEC.BAT");
exit (1);
}
fgets (cadena, 80, f);
whiIe (!feof (f)) {
printf ("%d: %s", i, cadena);
i++;
fgets (cadena, 80, f);
}
fcIose (f);
}
%ara escri&ir cadenas de caracteres se utili1a la $unci"n
int fputs (const c&ar 9cadena8 )I6E 9canal)A
cu,o prototipo est. de$inido en stdio.&, , que escri&e la cadena indicada en el
argumento en el $ichero asociado a canalC Qa, que tener en cuenta que fputs() no
copia el car.cter nulo ni aFade un car.cter nueva l@nea al $inalC 4i no se produce error,
fputs() devuelve el Kltimo car.cter escritoO en caso contrario devuelve E/)C
El siguiente programa escri&e en la impresora las cadenas de caracteres que se
van tecleando, hasta que se pulsa C
#incIude <stdio.h>
#incIude <string.h>
void main (void)
{
char *cadena[85];
printf ("\nTecIee cadena: ");
gets (cadena);
whiIe (cadena[0]) {
strcat (cadena, "\n\r");
fputs (cadena, stdprn);
gets (cadena);
}
}
E!" de bloKues de datos
c*li*
+a &i&lioteca est.ndar de # dispone de $unciones que permiten leer , escri&ir
&loques de datos de cualquier tipoC +as $unciones que reali1an estas operaciones son,
respectivamente, fread() , f%rite(), cu,os prototipos, de$inidos en stdio.&, son los
siguientes:
int fread (4oid 9buffer8 int nb)tes8 int contador8 )I6E 9canal)A
int f%rite (4oid 9buffer8 int nb)tes8 int contador8 )I6E 9canal)A
+a $unci"n fread() lee contador &loques de datos del $ichero asociado a canal
, los sitKa en bufferC #ada &loque contiene nb)tes &,tesC +a $unci"n f%rite() vuelca
en el $ichero asociado a canal los contador &loques de nb)tes &,tes que se
encuentran almacenados a partir de bufferC 4i la operaci"n tiene 9*ito, fread()
devuelve el nKmero de &loques Dno de &,tesE realmente le@dosC 6n.logamente,
f%rite() devuelve el nKmero de &loques realmente escritosC +a declaraci"n
4oid 9buffer
indica que buffer es un puntero a cualquier tipo de varia&lesC
En el programa siguiente se almacenan en el $ichero /6-'!bCF+) un
conjunto de 12 nKmeros de tipo floatC +a escritura se hace con una sentencia f%rite()
para cada datoC En la operaci"n de lectura se leen los 12 datos de una sola ve1 con
una sentencia fread() ,, a continuaci"n, se muestran en pantallaC
#incIude <stdio.h>
#incIude <process.h>
#incIude <conio.h>
void main (void)
{
register int i;
FILE *f;
fIoat eIem, matriz[10];
if (!(f = fopen ("MATRIZ.FLO", "w+b"))) {
perror ("MATRIZ.FLO");
exit (1);
}
for (i = 0; i <= 9; i++) {
printf ("\nTecIee nmero: ");
scanf ("%f", &eIem);
fwrite (&eIem, sizeof (eIem), 1, f);
}
rewind (f);
fread (matriz, sizeof (matriz), 1, f);
cIrscr ();
for (i = 0; i <= 9; i++) printf ("\n%d: %f", i, matriz[i]);
fcIose (f);
cl
}
Fij9monos en algunos detalles del programa anteriorC +a sentencia
fwrite (&eIem, sizeof (eIem), 1, f);
vuelca en el $ichero, cada ve1, los 4 &,tes Asi5eof (elem)A de elemC ;na ve1 $inali1ado
el primero de los &ucles for se han ejecutado 12 operaciones f%rite() ,, por tanto, el
indicador de posici"n del $ichero apunta al $inal del mismoC %ara poder reali1ar la
lectura de los datos hemos de recolocar este indicador al principio del $icheroC Esto
puede hacerse de dos $ormas:
#errando el $ichero , volvi9ndolo a a&rir para lecturaC
/ediante la $unci"n re%ind()C
En el ejemplo se utili1a el segundo m9todoC +a $unci"n re%ind() reposiciona el
indicador de posici"n del $ichero al principio del mismoC 4u prototipo, de$inido en
stdio.&, es el siguiente:
4oid re%ind ()I6E 9canal)A
4iguiendo con el programa anterior, la sentencia
fread (matriz, sizeof (matriz), 1, f);
lee del $ichero 42 &,tes Asi5eof (matri5)A , los sitKa en matri5C Fij9monos que ahora
no es necesario escri&ir Jmatri5 en el primer par.metro, pues matri5 ,a es un
punteroC
Qa&itualmente fread() , f%rite() se utili1an para leer o escri&ir estructurasC
0e.moslo con un programa que crea un archivo de list@n tele$"nicoC El registro de ese
archivo constar. de los siguientes campos:
<ombre 1 caracteres
;omicilio 1 caracteres
:oblacin2# caracteres
:ro4incia 1# caracteres
TelWfono 11 caracteres
El siguiente programa crea ese $ichero, llamado +!4-!>C-E+C
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
typedef struct {
char nom[41];
char dom[41];
char pob[26];
char pro[16];
char teI[11];
} REG;
cli
void main (void)
{
FILE *f;
REG var;
if (!(f = fopen ("LISTIN.TEL", "wb"))) {
perror ("LISTIN.TEL");
exit (1);
}
cIrscr ();
printf ("Nombre: ");
gets (var.nom);
whiIe (var.nom[0]) {
printf ("\nDomiciIio: ");
gets (var.dom);
printf ("\nPobIacin: ");
gets (var.pob);
printf ("\nProvincia: ");
gets (var.pro);
printf ("\nTeIfono: ");
gets (var.teI);
fwrite (&var, sizeof (var), 1, f);
if (ferror (f)) {
puts ("No se ha aImacenado Ia informacin");
getch ();
}
cIrscr ();
printf ("Nombre: ");
gets (var.nom);
}
fcIose (f);
}
El siguiente programa ilustra como se pueden leer &loques de registros de un
$icheroC #oncretamente lee los registros del $ichero +!4-!>C-E+ en grupos de 4,
mostrando en pantalla los campos <ombre , TelWfonoC
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
typedef struct {
char nom[41];
char dom[41];
char pob[26];
char pro[16];
char teI[11];
} REG;
void main (void)
{
FILE *f;
REG var[4];
clii
int i, n;
if (!(f = fopen ("LISTIN.TEL", "rb"))) {
perror ("LISTIN.TEL");
exit (1);
}
do {
cIrscr ();
n = fread (var, sizeof (REG), 4, f);
for (i = 0; i < n; i++) printf ("\n%-41s %s", var[i].nom, var[i].teI);
puts ("\nPuIse una tecIa ...");
getch ();
} whiIe (!feof (f));
fcIose (f);
}
4i nos $ijamos en la sentencia fread() de este programa, se leen en cada
operaci"n 4 &loques de si5eof (LEM) &,tes D13(, tamaFo de cada registroEC +a
misma cantidad de &,tes se leer@a mediante la sentencia
fread (var, sizeof (var), 1, f);
sin em&argo, as@ no tendr@amos un control adecuado so&re la varia&le nC
E!" con formato
+a $unci"n que permite escri&ir con $ormato en un $ichero es
int fprintf ()I6E 9canal8 const c&ar9formato8 lista de argumentos)A
que escri&e los argumentos de la lista, con el $ormato indicado, en el $ichero asociado
a canalC Esta $unci"n es id9ntica a printf() salvo en que permite escri&ir en cualquier
dispositivo , no s"lo en stdoutC ;n uso de fprintf() se estudi" en el #ap@tulo 4 para
salida por impresoraC
%ara leer con $ormato e*iste la $unci"n
int fscanf ()I6E 9canal8 const c&ar9formato8 lista de argumentos)A
que es id9ntica a scanf() salvo en que puede leer de cualquier dispositivo, no
necesariamente de stdinC
6unque estas $unciones pueden ser de gran utilidad en ciertas aplicaciones, en
general es m.s recomenda&le usar fread() , f%rite()C
cliii
0cceso directo
El acceso directo Dtanto en lectura como en escrituraE a un archivo, se reali1a
con la a,uda de la $unci"n fsee'() que permite situar el indicador de posici"n del
archivo en cualquier lugar del mismoC El prototipo de esta $unci"n es:
int fsee' ()I6E 9canal8 long nb)tes8 int origen)A
Esta $unci"n sitKa el indicador de posici"n del $ichero nb)tes contados a partir
de origenC +os valores posi&les del par.metro origen , sus macros asociadas se
muestran en la siguiente ta&la:
ORIGEN GAFOR HACRO
(rincipio del
'ic?ero
0 SJJLZSJT
(osici6n actual 1 SJJLZ.MR
$in del 'ic?ero & SJJLZJ1
+a $unci"n devuelve 2 cuando ha tenido 9*itoC En caso contrario devuelve un
valor di$erente de 2C
Esta $unci"n simplemente maneja el indicador de posici"n del $ichero, pero no
reali1a ninguna operaci"n de lectura o escrituraC %or ello, despu9s de usar fsee'()
de&e ejecutarse una $unci"n de lectura o escrituraC
El siguiente programa crea un archivo llamado F'64EC-B- con una cadena de
caracteresC %osteriormente lee un car.cter de la cadena cu,a posici"n se tecleaC
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
#incIude <process.h>
void main (void)
{
FILE *f;
int nbyte, st;
char frase[80], caracter;
if (!(f = fopen ("FRASE.TXT", "w+t"))) {
perror ("FRASE.TXT");
exit (1);
}
cIrscr ();
printf ("TecIee frase: ");
gets (frase);
fwrite (frase, strIen (frase) + 1, 1, f);
printf ("\nLeer carcter n: ");
cliv
scanf ("%d", &nbyte);
st = fseek (f, (Iong) nbyte, SEEK_SET);
if (st) puts ("Error de posicionamiento");
eIse {
caracter = getc (f);
if (caracter != EOF) printf ("\nEI carcter es: %c", caracter);
eIse puts ("Se sobrepas eI fin de fichero");
}
fcIose (f);
}
%uede usarse fsee'() para acceder a registrosC %ara ello de&e calcularse
previamente en qu9 &,te del $ichero comien1a el registro &uscadoC El siguiente
programa escri&e registros a,ud.ndose de fsee'()C
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
typedef struct {
char nombre[40];
int edad;
fIoat aItura;
} REGISTRO;
void main (void)
{
FILE *f1;
REGISTRO mireg;
int num;
Iong int puntero;
if (!(f1 = fopen ("REGISTRO.DAT", "r+b"))) {
puts ("Error de apertura");
exit (1);
}
cIrscr ();
printf ("Escribir registro n: ");
scanf ("%d", &num);
whiIe (num > 0) {
getchar ();
printf ("Nombre: ");
gets (mireg.nombre);
printf ("Edad: ");
scanf ("%d", &mireg.edad);
printf ("AItura: ");
scanf ("%f", &mireg.aItura);
puntero = (num - 1) * sizeof (REGISTRO);
if (fseek (f1, puntero, SEEK_SET)) puts ("Error de posicionamiento");
eIse {
fwrite (&mireg, sizeof (mireg), 1, f1);
if (ferror (f1)) {
puts ("ERROR de escritura");
getch ();
}
}
clv
cIrscr ();
printf ("Escribir registro n: ");
scanf ("%d", &num);
}
fcIose (f1);
}
clvi
E7ercicios
1. Escri&e un programa que va,a almacenando en un archivo todos los
caracteres que se tecleen hasta que se pulse #-'+AbC El nom&re del archivo
se pasar. como par.metro en la l@nea de "rdenesC
2. Escri&e un programa que lea un archivo de te*to , cam&ie todas las
apariciones de una pala&ra determinada, por otraC El programa se ejecutar.
con la orden
:L/M fic&ero palabra1 palabra2
siendo palabra1 la pala&ra sustituida por palabra2C El programa de&e
in$ormar del nKmero de sustituciones e$ectuadasC
<ota2 4e supondr. que las l@neas del $ichero no tienen m.s de 82 caracteresC
3. En el clu& de &aloncesto B6QEE-)P4 B64?E- #+;B se est.
reali1ando una campaFa de captaci"n de jugadores altosC 4e dispone de un
$ichero con datos de aspirantes, llamado 6+-)4C<6-, que se descri&e a
continuaci"n
06T/".;0T 0spirantes a 7ugadores del club
Campo ;escripcin Tipo
nom >om&re del aspirante charD41E
alt 6ltura del aspirante Den metrosE $loat
pro %rovincia de nacimiento charD26E
+os campos de tipo c&ar inclu,en el nulo $inal
El $ichero almacena un m.*imo de (22 registrosC
+a provincia se almacena en ma,KsculasC
El $ichero no est. ordenadoC
#onstru,e un programa que realice las siguientes operaciones:
4olicitar por teclado una provincia , almacenar en sendas matrices los
nom&res , las alturas de los aspirantes nacidos en la provincia indicadaC
#alcular la altura media de todos los aspirantes de dicha provinciaC
Emitir un in$orme impreso con los nom&res , alturas de los aspirantes de
la provincia cu,a altura supere la mediaC El $ormato del listado de&e ser el
siguiente:
:ro4incia2 (((((((((((((((((((((((((
0ltura ,edia2 (.((
<ombre
0ltura
(((((((((((((((((((((((((((((((((((((((( (.((
clvii
*** 5+ l,neas de detalle "or "!gina
. 4e tienen dos archivos de datos 0LTIC.;0T , </,:L/.;0T, que se
descri&en a continuaci"n:
0LTIC.;0T ,aestro de 0rtGculos
Campo ;escripcin Tipo
cod #"digo del art@culo charD5E
des <escripci"n charD31E
e(i E*istencia unsigned
pco %recio de compra unsigned
p4p %recio de 0enta unsigned
pro #"digo del proveedor charD(E
+os campos de tipo c&ar inclu,en el nulo $inal
+os campos cod , pro almacenan s"lo d@gitos num9ricos , est.n
completados a la i1quierda con cerosC %or ejemplo, el art@culo de c"digo
6( se almacena como 22226(C
El $ichero est. ordenado ascendentemente por el campo codC
>o est.n todos los valores de codC
</,:L/.;0T <ombres de pro4eedores
Campo ;escripcin Tipo
nom >om&re del proveedor charD41E
#ada nom&re de proveedor est. almacenado en el registro cu,o nKmero
coincide con su c"digoC 6s@, el nom&re del proveedor de c"digo 222241
se almacena en el registro 41C
Escri&e un programa que emita un in$orme impreso con el $ormato de la
p.gina siguienteC
6l inicio del programa se solicitar.n por teclado los c"digos de art@culo
inicial , $inal que limitar.n los registros que se de&en listarC
clviii
11
)ic&eros inde(ados2
la interfase 3trie4e
Introduccin
El +enguaje # no incorpora instrucciones ni $unciones de manejo de $icheros
inde*adosC %ara disponer de este tipo de acceso en un programa # de&emos
recurrir a una gesti"n propia, lo que resulta e*cesivamente complejo, o a algKn
programa comercial que proporcione una inter$ase adecuadaC ;no de los
programas m.s e$icientes de gesti"n de archivos inde*ados es el programa Btrieve,
desarrollado por >ovellC En el presente cap@tulo se descri&ir. una parte importante
de Btrieve, pero no se reali1ar. un estudio e*ahustivo, pues ello merecer@a un li&ro
monogr.$icoC
+as e*plicaciones del cap@tulo se re$ieren a la versi"n (C2, aunque gran parte
de lo que se diga es v.lido para otras versionesC
;escripcin de 3trie4e
Btrieve es un programa residente en memoria que gestiona, lee, inserta ,
actuali1a registros en los $icheros de datos de las aplicaciones, utili1ando para ello
los recursos del sistema operativoC En principio, Btrieve $ue diseFado para tra&ajar
en entornos monousuario, pero las Kltimas versiones incorporan operaciones de
&loqueo de registros que permiten tra&ajar en entornos de redC El estudio de este
cap@tulo se circunscri&e a entornos monousuarioC %ara otros tra&ajos de&e
consultarse el /anual de )peraciones BtrieveC
+os requerimientos m@nimos de Btrieve son los siguientes:
)rdenador personal !B/ o compati&leC
128 ?& de memoriaC
;na unidad de discoC
4istema operativo /4A<)4 2C2 o posteriorC
+a rutina que queda residente en memoria ocupa un m@nimo de 3( G&C
cli*
Entre las caracter@sticas de Btrieve que ca&e destacar est.n las siguientes:
4oporta hasta 24 claves para cada $icheroC
%ueden aFadirse o eliminarse claves despu9s de creado el $icheroC
6dmite 14 tipos de clavesC
%ermite claves duplicadas Dm.s de un registro con el mismo valor para la
claveE, modi$ica&les, segmentadas D$ormadas por dos segmentos disjuntos
del registroE, nulas , descendentesC
/aneja $icheros de hasta 4 /& con un nKmero ilimitado de registrosC
%uede tra&ajar con $icheros almacenados en dos dispositivos di$erentesC
%roporciona 36 operaciones distintas que pueden ejecutarse desde el
programa de aplicaci"nC
El $lujo de control entre el programa de aplicaci"n , el gestor Brieve es,
&.sicamente, el siguiente:
El programa emite una llamada a Btrieve por medio de una $unci"n a la
que se pasa un &loque de par.metrosC +a $orma de estas llamadas cam&ia
ligeramente de un lenguaje a otroC /.s adelante estudiaremos c"mo se
hace para -ur&o #C
;na pequeFa rutina de inter$ase incluida en el programa guarda el &loque
de par.metros en memoria , llama a la parte residente de BtrieveC
Btrieve reci&e el &loque de par.metros, los valida, , ejecuta la operaci"n
que se ha,a indicado, por ejemplo la lectura o escritura de un registro en
el $icheroC
Btrieve devuelve los datos apropiados, entre ellos un c"digo que indica si
la operaci"n ha tenido 9*ito o noC
Btrieve devuelve el control al programa de aplicaci"nC
Mestin de fic&eros 3trie4e
+os $icheros Btrieve se crean mediante el programa B;-!+CEBE Dse e*plica
m.s adelanteE , se gestionan mediante el =estor de <atos B-'!E0ECEBEC
;n $ichero Btrieve est. $ormado por una serie de p.ginasC +a p.gina es la
unidad de trans$erencia utili1ada por Btrieve entre memoria , disco en una
operaci"n de E34C El tamaFo de la p.gina se especi$ica cuando se crea el $ichero, ,
ha de ser un mKltiplo de (12 &,tes, hasta un m.*imo de 426C El tamaFo "ptimo
de la p.gina depende de las caracter@sticas del registroC /.s adelante veremos
c"mo determinar ese valorC
+.s p.ginas de un $ichero Btrieve son de tres tipos:
:gina de cabecera, tam&i9n llamada registro de control del fic&ero
DF#'EC #ontiene in$ormaci"n so&re las caracter@sticas del $icheroC
cl*
:ginas de datos, en donde se almacenan los registros de datosC
:ginas de Gndices, que contienen los valores de las clavesC
Btrieve almacena en la p.gina de datos tantos registros como le es posi&leC
Es conveniente determinar el tamaFo "ptimo de la p.gina de datos para aumentar
la e$iciencia de BtrieveC %ara calcular este tamaFo "ptimo ha, que tener en cuenta
lo siguiente:
%or cada clave duplicada Btrieve almacena 8 &,tes e*tra de in$ormaci"n
en cada registroC
4i el $ichero admite registros de longitud varia&le Btrieve aFade 4 &,tes
por registroC
4i se admite truncamiento de &lancos se aFaden 6 &,tes por registroC
#ada p.gina requiere 6 &,tes para in$ormaci"n de ca&eceraC
#on estos datos es posi&le determinar el tamaFo de p.gina que hace mejor
utili1aci"n del discoC 0eamos un ejemploC 4ea un $ichero cu,a longitud de registro
l"gico es 115 &,tes, , que utili1a dos claves que admiten duplicadosC +a longitud
del registro $@sico es:
115 L 2 R 8 M 133 &,tes
+a siguiente ta&la muestra el porcentaje de ocupaci"n para cada p.gina:
TAHAIO
DE
PGINA
WTIF
NWHERO
DE
REGISTROS
OCUPADO
NO
UTIFIXAD
O
9 DE
PGINA
OCUPADA
@1& @0A + ,0@ 107 79B1
10&, 1018 7 9+7 87 91B@
1@+A 1@+0 11 1,A9 A7 9@BA
&0,8 &0,& 1@ &001 ,7 97B7
&@A0 &@@, 19 &@++ &7 98B9
+07& +0AA &+ +0A@ 7 99B8
+@8, +@78 &A +,A, 1&0 9AB7
,09A ,090 +0 +99A 100 97BA
En este ejemplo vemos que un tamaFo de p.gina de (12 &,tes es inadecuado,
pues por cada (12 &,tes se malgastan 125C -am&i9n vemos que en una p.gina de
426 &,tes se almacenan 32 registros, pero se desperdician 122 &,tes, lo que
signi$ica que si el nKmero de registros del $ichero es elevado, se pierde mucho
espacioC El tamaFo "ptimo parece ser el de 3252 &,tes, pues tan solo se pierden 5
&,tes cada 23 registrosC
;na caracter@stica importante de Btrieve es el control que reali1a de la
consistencia de los datosC 4i se produce un $allo en el sistema mientras Btrieve hace
actuali1aciones en las p.ginas pueden producirse inconsistencias en el $icheroC %ara
protegerse contra ello Btrieve reali1a un proceso llamado preimagen, mediante el
cual se restaura autom.ticamente el $ichero a la situaci"n inmediatamente anterior
a la operaci"n no completadaC %ara ello Btrieve utili1a un $ichero temporal,
cl*i
llamado fic&ero preimagen, en el que registra los cam&ios en el $ichero mientras
dura la operaci"nC El $ichero preimagen tiene el mismo nom&re que el $ichero de
datos Btrieve, pero con e*tensi"n C%'E, por lo que de&e evitarse esta e*tensi"n
para los $icheros de datosC
)tro metodo proporcionado por Btrieve para proteger la consistencia de los
$icheros es la de$inici"n de transaccionesC Entre las operaciones aportadas por
Btrieve ha, dos, denominadas Inicio , )in de TransaccinC +as operaciones
Btrieve reali1adas entre el inicio , el $inal de una transacci"n s"lo se actuali1ar.n
en el $ichero si la transacci"n tiene 9*itoC 4i el sistema $alla antes de completar la
transacci"n, las operaciones Btrieve solicitadas desde el inicio de la transacci"n no
se actuali1an en el $icheroC Btrieve utili1a un fic&ero de control de transaccin
para seguir la pista de los $icheros involucradosC
)tra particularidad de Btrieve es que permite a&rir $icheros en modo
acelerado para mejorar el rendimiento en operaciones de inserci"n, actuali1aci"n ,
eliminaci"nC #uando se a&re un $ichero en modo acelerado Btrieve no escri&e
p.ginas en disco hasta que la memoria intermedia est. llena , el algoritmo +';
D6ast Lecientl, DsedE selecciona un .rea para ser rellenadaC
%or Kltimo, Btrieve permite restringir el acceso a $icheros especi$icando un
nom&re de propietario o pala&ra de paso, evitando accesos no autori1ados a los
datosC
El Mestor de ;atos 3trie4e
%ara que un programa pueda hacer llamadas a Btrieve ha de cargarse
previamente en memoria el =estor de <atos 3TLIE]E.ERE, que es qui9n ejecuta
todas las operaciones de gesti"n de registros , $icherosC %ara ello, desde el
indicador del <)4 de&e ejecutarse el programa B-'!E0ECEBE mediante
3TLIE]E _o"ciones`
;na ve1 cargado correctamente en memoria aparecer. un mensaje similar a
3trie4e Lecord ,anager ]ersion #.((
Cop-rig&t (c) 1.*28 1.**8 no4ell8 Inc. 0ll Lig&ts Leser4ed
4i en la carga se produce algKn error, Btrieve env@a un mensaje descri&iendo las
caracter@sticas del pro&lemaC 4i no ha, error, Btrieve permanece residente en
memoria hasta que se interrumpe la corriente, se recarga el <)4, se descarga
mediante el utilitario 3DTI6 Dha&laremos de 9l m.s adelanteE o desde el programa
de aplicaci"n se emite una orden de paradaC
+a ta&la siguiente descri&e algunas de las opciones de arranque del =estor de
<atosC
cl*ii
OPCIN DESCRIPCIN
8HD TamaTo de memoria Js un !alor comprendido entre 9 : A,
;ue determina el tamaTo de memoria
en Lb de las )reas de Btrie!eB Jl !alor
por de'ecto es +& LbB
8PD TamaTo de p)*ina Jspeci'ica el tamaTo de la p)*inaB Ha de
ser un mUltiplo de @1& ?asta un m)Fimo
de ,09AB Si se especi'ica un tamaTo de
p)*ina de ,09AD debe asi*narseD al
menosD +A [b para la opci6n 8HB
8TD $ic?ero de transacci6n Jspeci'ica el 'ic?ero de control de
transaccionesB
8ID 1ispositi!o del 'ic?ero
preima*en
Jspeci'ica el dispositi!o en el ;ue se
ubicar) el 'ic?ero preima*enB
8FD $ic?eros abiertos Jspeci'ica el m)Fimo nUmero de
'ic?eros Btrie!e ;ue pueden permanecer
abiertos simult)neamenteB Jl !alor por
de'ecto es &0B Jl m)Fimo es &@@B
El utilitario 3DTI6
El utilitario 3DTI6.ERE es un programa que reali1a ciertas operaciones
so&re $icheros Btrieve Dcrear, copiar, CCCE, permite descargar de memoria el =estor
de <atos, o in$ormar so&re la versi"n de Btrieve que se est. utili1andoC
6ntes de ejecutar B;-!+ de&e cargarse en memoria el =estor de <atosC +a
sinta*is de B;-!+ es la siguiente:
3DTI6 Smandato _"ar!metros` _S/ V"ro"ietarioW`
6 continuaci"n se descri&en algunos de los mandatos de B;-!+C
C6/<E
#rea un $ichero Btrieve vac@o con las mismas caracter@sticas que uno
e*istenteC +a sinta*is para #+)>E es:
butil SC6/<E Vfichero e&istenteW Vfichero nuevoW _S/ V"ro"ietarioW`
C/:`
#opia el contenido de un $ichero Btrieve en otroC 6m&os de&en e*istirC +a
sinta*is es:
butil SC/:` Vfich* entradaW Vfich* salidaW _S/ V"ro"* entW _S/ V"ro"* SalW``
CLE0TE
cl*iii
+os $icheros Btrieve se crean con esta orden del utilitario B;-!+C /ediante
#'E6-E se crea un $ichero Btrieve vac@o con ciertas propiedadesC ^stas se
especi$ican en un $ichero de te*to que contiene una lista de par.metros que de$inen
las caracter@sticas del $icheroC El $ichero que contiene los par.metros se crea con
cualquier editor de te*to, , contiene sentencias del tipo
"alabra_reservadaBvalor
en donde "alabra_reservada se re$iere a una caracter@stica del $ichero o de
sus claves, , valor es el valor asignado a dicha caracter@sticaC +a ta&la siguiente
muestra algunas de las pala&ras reservadas utili1adas para $ijar caracter@sticas
generales del $icheroC

$!c%$">R Jspeci'ica la lon*itud del re*istro l6*icoB Jl !alor R debe
estar comprendido entre , : ,090
va$iabl!>=Y]n8 Jspeci'ica si el 'ic?ero contiene o no re*istros de
lon*itud !ariableB
Z!Y>R Jspeci'ica el nUmero de cla!es del 'ic?eroB Se admite
cual;uier !alor entre 1 : &,B
#a!>R Jspeci'ica el tamaTo de p)*inaB 1ebe ser un mUltiplo
de @1& ?asta un m)Fimo de ,09AB
$!#lac!>=Y]n8 Se utiliza para indicar si se desea ;ue Btrie!e cree un
nue!o 'ic?ero si :a eFiste uno con el mismo nombreD
ad!irtiendo de su eFistenciaB
#%&i3i%n>R Jspeci'ica la posici6nD dentro del re*istro l6*icoD en ;ue
comienza la cla!e ;ue se describeB
l!n3P>R Jspeci'ica la lon*itud de la cla!eB
"u#lica3!&>=Y]
n8
1etermina si se permite o no duplicados en las cla!esB
O%"i6iabl!>=Y]
n8
3ndica si el pro*rama puede modi'icar el !alor de la
cla!eB
3Y#!>tipo 3ndica el tipo de cla!eB Al*unos de los tipos de cla!e
permitidos se muestran en una tabla posteriorB
"!&c!n"in>Y Se especi'ica cuando se ;uiere mantener el 'ic?ero
ordenado descendentemente respecto de la cla!e
de'inidaB
al3!$na3!>=Y]n8 Se especi'ica Y cuando se desea un criterio de
clasi'icaci6n di'erente al AS.33 est)ndarB Jn ese casoD el
nue!o criterio se almacena en un 'ic?ero cu:a
estructura se eFplica m)s adelanteB
&!O!n3>=Y]n8 3ndica si la cla!e tiene o no al*Un se*mento m)sB
naO!>'ic?ero Jspeci'ica el 'ic?ero ;ue contiene el nue!o criterio de
clasi'icaci6n si se ?a indicado al3!$na3!>YB
+a siguiente ta&la muestra alguno de los tipos de clave que se pueden
especi$icar con el par.metro t-pe
TIPO DESCRIPCIN
strin* .adenas de caracteres
inte*er Jnteros almacenados en binario (& b:tes)
'loat Umeros en punto 'lotante (,08 b:tes)
numeric Umeros almacenados como cadenas de
cl*iv
caracteres
lstrin* .omo &3$inD especi'icando la lon*itus en el b:te
0
zstrin* .adenas tipo .X 'inalizadas con el AS.33 nulo
4i en alguna clave se ha especi$icado la sentencia alternateB-, la Kltima
sentencia del $ichero de&e ser del tipo nameBfichero, siendo fichero el archivo que
almacena el nuevo criterio de clasi$icaci"nC Este archivo de&e tener la siguiente
estructura:
b-te 1
Es un &,te de control que de&e almacenar siempre el valor
6# he*C
b-tes 1S*
6lmacenan un nom&re que identi$ica la secuencia de
intercalaci"n alternativa ante BtrieveC
2#$ b-tes
6lmacenan la nueva clasi$icaci"nC
#uando se crea el $ichero de par.metros de&en tenerse en cuenta las
siguientes normas:
-odos los elementos de&en estar en minKsculasC
<e&en presentarse en el mismo orden en que se han e*puesto en las ta&las
anterioresC
+as sentencias han de ser consistentesC %or ejemplo, si se ha indicado para
alguna clave alternateB-, el Kltimo elemento del $ichero de par.metros
de&e ser una sentencia nameC
0eamos un ejemploC 4ea el siguiente $ichero, de nom&re <6-)4C%6':
recordB113
4ariableBn
'e-B2
pageB31+2
replaceBn
positionB1 lengt&B# duplicatesBn modifiableBn t-peB5string alternateBn segmentBn
positionB$ lengt&B31 duplicatesB- modifiableB- t-peB5string alternateBn segmentB-
positionB$ lengt&B3 duplicatesB- modifiableB- t-peB5string alternateBn segmentBn
/ediante la orden
3DTI6 SCLE0TE ;0T/".3TL ;0T/".:0L
se crea un $ichero llamado <6-)4CB-' con las siguientes especi$icaciones:
'egistros de longitud $ija de 113 &,tes
%.ginas de 3252 &,tes
<os claves de acceso de$inidas de la siguiente manera
1C #lave no segmentada de ( &,tes, contados desde el primer &,te del
registro, de tipo 5string, no duplicada , no modi$ica&leC
cl*v
2C #lave de tipo 5string, duplicada , modi$ica&le con dos segmentos: uno
de 32 &,tes contados a partir del 6i, , otro de 3 &,tes a partir del 46iC
6/0;
%ermite insertar registros de un $ichero secuencial en un $ichero BtrieveC +a
sinta*is es
butil S6/0; Vfichero secuencialW Vfichero -trieveW _S/ V"ro"ietarioW`
+a estructura de los registros del $ichero secuencial de&e ser
#8reg=CLQ6)>
siendo # la longitud del registro, reg el registro a insertar en el $ichero Btrieve, ,
CLQ6) los caracteres retorno de carro , salto de l@neaC %or ejemplo, si con un
editor de te*to creamos un archivo <6-)4C4E# que contenga
20,ABCDEFGHIJKLMNOPQRST
20,abcdefgh!"#$%&'()*+
, tenemos un $ichero Btrieve llamado <6-)4CB-', la orden
3DTI6 S6/0; ;0T/"."EC ;0T/".3TL
inserta los 2 registros de <6-)4C4E# en <6-)4CB-'C
Es importante asegurarse de que cada l@nea escrita en el $ichero secuencial
$inali1a con los caracteres 'etorno de #arro , 4alto de +@nea, , de que la longitud
de registro especi$icada es la misma que se indic" al crear el $ichero BtrieveC
"0]E
0uelca el contenido de un $ichero Btrieve en un $ichero secuencialC Es la
operaci"n inversa a +)6<C +a sinta*is es
butil S"0]E Vfich*-trieveW Vfich*secuencialW VN. claveW _S/ V"ro"ietarioW`
+os registros creados con 460E tienen la misma estructura e*plicada para el
mandato +)6<C 4i no se especi$ica lo contrario, el $ichero se vuelca ordenado por
la clave 2C 4i se quiere otro orden se indica en el par.metro N. claveC
"T0T
/uestra en pantalla in$ormaci"n con las caracter@sticas de un $ichero BtrieveC
+a sinta*is es
cl*vi
butil S"T0T Vfichero -trieveW _S/ V"ro"ietarioW`
"T/:
Elimina el =estor de <atos de memoriaC +a sinta*is es
butil S"T/:
]EL
!n$orma de la versi"n del =estor de <atos con que se est. tra&ajandoC +a
sinta*is es:
butil S]EL
Interfase de 3trie4e con Turbo C
+as operaciones Btrieve en # no utili1an ninguna de las $unciones estudiadas
en el #ap@tulo 12C -odas las operaciones so&re $icheros Btrieve se hacen mediante
llamadas a una $unci"n 3TL], de prototipo
int 3TL] (int o"8 c&ar 9bloue8 4oid 9datos8 int 9lonreg8 c&ar 9/e)val8 c&ar 9n/e))A
6 continuaci"n se descri&e cada uno de los par.metros:
o"
Es un valor entero que indica la operaci"n a reali1ar so&re el
$icheroC +as m.s ha&ituales se descri&en en el siguiente apartado
del cap@tuloC
bloue
Es un .rea de 128 &,tes, denominado bloKue de posicin del
$ichero, que Btrieve utili1a para un correcto manejo del mismo,
iniciali1.ndolo en la aperturaC <e&e asignarse un &loque de
posici"n di$erente para cada $ichero Btrieve que se a&raC
datos
Es la direcci"n de una varia&le, generalmente de tipo struct, en
donde se almacena el registro que va a ser escrito en el $ichero ,
donde se reci&e el registro le@do del $icheroC
lonreg
#on este par.metro se pasa la direcci"n de una varia&le que
contiene la longitud del registroC
/e)val
6lmacena el valor de la clave por la que se est. accediendoC
n/e)
Es el nKmero de clave con que se accede al $icheroC
+a $unci"n B-'0 devuelve un valor enteroC 4i la operaci"n ha tenido 9*ito,
devuelve 2C En caso contrario devuelve un c"digo de errorC +os c"digos de error
se muestran m.s adelante en el cap@tuloC %ara poder utili1ar la $unci"n B-'0 de&e
incluirse el archivo turcbtr4.c mediante una sentencia #include como
cl*vii
#incIude <c:\btr\turcbtrv.c>
suponiendo que el $ichero turcbtr4.c se encuentra en el directorio c2FbtrC -am&i9n
puede compilarse este $ichero , o&tener un m"dulo o&jeto que se enlace m.s tarde
con el programa Dse estudia c"mo hacerlo en el #ap@tulo 12EC 0eremos m.s
adelante algunos ejemplos de programas que manejan $icheros BtrieveC 6ntes es
necesario conocer las operaciones que se pueden reali1ar so&re ellosC
/peraciones 3trie4e
0amos a estudiar algunas de las operaciones Btrieve m.s comKnmente
usadasC 4e muestran en orden al$a&9ticoC
03/LT0L TL0<"0CCIg< 21
<eshace todas las operaciones reali1adas desde el comien1o de una transacci"n
activa , termina la transacci"nC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B
<evuelve
03LIL 1
6&re un $ichero Btrieve cu,o nom&re se especi$ica en 'e-4alC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B
4i ha, pala&ra de paso se pone en datos, , en longitud se pone su longitudC
En n'e- se indica el modo de aperturaC +os modos ha&ituales son:
aE S1 6celeradoC
&E 1 6pertura normalC
03LIL TL0<"0CCIg< 1.
4eFala el comien1o de una transacci"nC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B
<evuelve
0CTD06Ia0L 3
6ctuali1a un registro e*istente en un $ichero BtrieveC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B
%reviamente de&e ha&erse reali1ado con 9*ito una operaci"n de lectura del
cl*viii
registro que se desea actuali1arC
0"IM<0L :0603L0 ;E :0"/ 2.
6signa una pala&ra de paso a un $ichero Btrieve para prevenir el acceso al mismo
a usuarios no autori1adosC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B B
<evuelve B
El $ichero de&e estar a&ierto , no tener asignada una pala&ra de pasoC
+a pala&ra de paso de&e colocarse en el par.metro datos , en el par.metro
'e-4alC <e&e ser una cadena de hasta 8 caracteres aca&ada con un nuloC
El par.metro n'e- se iniciali1a a un valor que indica el tipo de restricci"n de
acceso asociada al $icheroC +os valores posi&les son:
aE 1 %ala&ra de paso requerida para cualquier accesoC
>o se criptogra$@an datosC
&E 1 %ermiso de lectura sin pala&ra de pasoC
>o se criptogra$@an datosC
cE 2 %ala&ra de paso requerida para cualquier accesoC
4e criptogra$@an datosC
dE 3 %ermiso de lectura sin pala&ra de pasoC
4e criptogra$@an datosC
3/LL0L
6ctuali1a un registro e*istente en un $ichero BtrieveC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B
<evuelve B B
%reviamente de&e ha&erse reali1ado con 9*ito una operaci"n de lectura del
registro que se desea &orrarC
CELL0L 1
#ierra un $ichero BtrieveC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B
<evuelve
E6I,I<0L :0603L0 ;E :0"/ 31
Elimina la pala&ra de paso previamente asignada a un $ichero BtrieveC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B
<evuelve B
I<"ELT0L 2
cl*i*
!nserta un nuevo registro en un $ichero BtrieveC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B
El par.metro datos de&e almacenar el registro a insertarC
6EEL 0<TELI/L +
6ccede al registro inmediatamente anterior al Iregistro actualIC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B B B
6nteriormente de&e ha&erse reali1ado con 9*ito una operaci"n de lecturaC El
par.metro 'e-4al de&e pasarse tal como $ue devuelto en dicha operaci"nC
6EEL IMD06 #
6ccede al 1
er
registro cu,o valor de clave es el mismo que el que se indica en
'e-4alC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B B
6EEL I<)ELI/L 12
6ccede al registro correspondiente a la clave m.s &aja de la v@a n'e-C
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B
<evuelve B B B B
6EEL ,0`/L *
6ccede al 1
er
registro cu,o valor de clave es ma,or que el especi$icado en 'e-4alC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B B B
6EEL ,0`/L / IMD06 .
6ccede al 1
er
registro con valor de clave ma,or o igual que el indicado en 'e-4alC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B B B
6EEL ,E</L 11
6ccede al 1
er
registro cu,o valor de clave es menor que el especi$icado en 'e-4alC
op bloKue datos lonreg 'e-4al n'e-
cl**
6 pasar B B B B B
<evuelve B B B B
6EEL ,E</L / IMD06 11
6ccede al 1
er
registro con valor de clave menor o igual que el indicado en 'e-4alC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B B B
6EEL "IMDIE<TE $
6ccede al registro siguiente al Iregistro actualIC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B B
<evuelve B B B B
6nteriormente de&e ha&erse reali1ado con 9*ito una operaci"n de lecturaC El
par.metro 'e-4al de&e pasarse tal como $ue devuelto en dicha operaci"nC
6EEL "D:ELI/L 13
6ccede al registro correspondiente a la clave m.s alta para la v@a n'e-C
op bloKue datos lonreg 'e-4al n'e-
6 pasar B B B B
<evuelve B B B B
:0L0L 2#
<escarga el =estor de <atos de memoria , cierra todos los $icherosC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B
<evuelve
TEL,I<0L TL0<"0CCIg< 21
#ompleta una transacci"n , con$irma las operaciones reali1adas desde su inicioC
op bloKue datos lonreg 'e-4al n'e-
6 pasar B
<evuelve
E7emplos
cl**i
0eremos ahora algunos ejemplos de programas # que utili1an archivos
BtrieveC El primero es un programa que reali1a algunas operaciones &.sicas que se
seleccionan desde un menKC
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
#incIude "c:\btr\turcbtrv.c"
#define ABRIR 0
#define CERRAR 1
#define INSERTAR 2
#define ACTUALIZAR 3
#define BORRAR 4
#define IGUAL 5
#define SIGUIENTE 6
#define ANTERIOR 7
#define INFERIOR 12
#define SUPERIOR 13
struct REG {
char nombre[26]; .. -ampo -la&e6 no dup6 no modifica/le
char direcc[31];
char teIef[8];
};
void ErrorBtr (int, int);
void PantaIIa (void);
int Opcion (void);
void Presentar (struct REG);
char *Intro (int, int, int, char *);
void main (void)
{
int st;
char bIoque[128];
struct REG datos;
int Ionreg = sizeof (datos);
char keyvaI[26];
char opc;
st = BTRV (ABRIR, bIoque, &datos, &Ionreg, "DATOS.BTR", -1);
if (st) {
ErrorBtr (st, ABRIR);
exit (1);
}
PantaIIa ();
whiIe ((opc = Opcion ()) != 'X') {
switch (opc) {
case 'A': Intro (15, 9, 25, datos.nombre);
strupr (datos.nombre);
Intro (16, 9, 30, datos.direcc);
Intro (17, 9, 7, datos.teIef);
st = BTRV (INSERTAR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, INSERTAR);
eIse {
cl**ii
printf ("\nRegistro insertado. PuIse una tecIa");
getch ();
deIIine ();
}
break;
case 'B': Intro (15, 9, 25, datos.nombre);
strcpy (keyvaI, strupr (datos.nombre));
st = BTRV (IGUAL, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, IGUAL);
eIse Presentar (datos);
break;
case 'C': st = BTRV (INFERIOR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, INFERIOR);
eIse Presentar (datos);
break;
case 'D': st = BTRV (SUPERIOR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, SUPERIOR);
eIse Presentar (datos);
break;
case 'E': st = BTRV (ANTERIOR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, ANTERIOR);
eIse Presentar (datos);
break;
case 'F': st = BTRV (SIGUIENTE, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, SIGUIENTE);
eIse Presentar (datos);
break;
case 'G': st = BTRV (BORRAR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, BORRAR);
eIse {
gotoxy (1, 20);
printf ("Registro borrado. PuIse una tecIa ...");
getch ();
deIIine ();
}
break;
case 'H': Intro (16, 9, 30, datos.direcc);
Intro (17, 9, 7, datos.teIef);
st = BTRV (ACTUALIZAR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, ACTUALIZAR);
eIse {
gotoxy (1, 20);
printf ("Registro actuaIizado. PuIse una tecIa ...");
getch ();
deIIine ();
}
}
}
cIrscr ();
st = BTRV (CERRAR, bIoque, &datos, &Ionreg, keyvaI, 0);
if (st) ErrorBtr (st, CERRAR);
}
void ErrorBtr (int st, int op)
{
gotoxy (1, 20);
printf ("Error %d en operacin %d", st, op);
printf ("\nPuIse una tecIa ...");
getch ();
gotoxy (1, 20);
cl**iii
deIIine ();
deIIine ();
}
void PantaIIa (void)
{
cIrscr ();
printf ("A: Insertar\n");
printf ("B: Leer registro\n");
printf ("C: Leer inferior\n");
printf ("D: Leer superior\n");
printf ("E: Leer anterior\n");
printf ("F: Leer siguiente\n");
printf ("G: Borrar\n");
printf ("H: Modificar\n");
printf ("X: SaIir");
gotoxy (1, 15);
printf ("Nombre: ");
printf ("\nDirecc: ");
printf ("\nTeIef.: ");
}
int Opcion (void)
{
int tecIa;
do {
gotoxy (1, 11);
printf ("==> TecIee opcin: ");
gotoxy (20, 11);
tecIa = toupper (getche ());
} whiIe (!strchr ("ABCDEFGHX", tecIa));

return tecIa;
}
void Presentar (struct REG x)
{
gotoxy (9, 15);
printf ("%-25s", x.nombre);
gotoxy (9, 16);
printf ("%-30s", x.direcc);
gotoxy (9, 17);
printf ("%-7s", x.teIef);
}
char *Intro (int f, int c, int tam, char *cad)
{
char aux[50];
register int i;
textattr (WHITE | BLUE * 16);
gotoxy (c, f);
for (i = 0; i < tam; i++) putch (' ');
gotoxy (c, f);
aux[0] = tam + 1;
strcpy (cad, cgets (aux));

textattr (LIGHTGRAY | BLACK * 16);
cl**iv
return cad;
}
%uesto que en la ma,or@a de las llamadas a B-'0 el Knico par.metro que
cam&ia de una a otra es el c"digo de operaci"n, suele simpli$icarse la llamada
mediante una $unci"n que invoque a B-'0 de la $orma siguiente:
int Btr (int codop)
{
return BTRV (codop, ... );
}
Esto implica declarar como glo&ales las varia&les Btrieve que se pasan a B-'0C
%ara el programa anterior la $unci"n es
int Btr (int codop)
{
return BTRV (codop, bIoque, &datos, &Ionreg, keyvaI, 0);
}
,, por ejemplo, la operaci"n !>4E'-6' se ejecuta del modo
st = Btr (INSERTAR);
ha&iendo declarado como glo&ales las varia&le bloKue, datos, lonreg , 'e-4alC
Esta nomenclatura simpli$ica la escritura de programas que usan $icheros
BtrieveC Qa&itualmente se tendr.n que manejar varios $icheros Btrieve en un
mismo programaC %uede utili1arse una sola $unci"n 3tr para hacer las llamadas
Btrieve de todos los $icheros, sin m.s que hacer una cuidadosa declaraci"n de
varia&lesC 0eamos un ejemplo con un programa que usa dos $icheros Btrieve
llamados 6'-!#CB-' , %E<!<)4CB-' cu,a descripci"n es la siguiente:
0LTIC.3TL ,aestro de 0rtGculos :E;I;/".3TL :edidos a pro4eedor
Inde(ado 3trie4e Inde(ado 3trie4e
Campo ;escripcin Tipo Campo ;escripcin Tipo
cod #"digo del 6rt@culo charD5E pro #"digo %roveedor charD5E
des <escripci"n
charD41E
art #"digo del 6rt@culo charD5E
e(i E*istencia int can #antidad a pedir int
min /@nimo int pre %recio de compra int
opt Zptimo int
pco %recio de compra int
p4p %recio de 0enta int
pro #"digo %roveedor charD5E
El campo cod es la Knica clave de
acceso al $icheroC >o se admiten
duplicados ni modi$icaciones de clavesC
+os campos de tipo char inclu,en el
nulo $inalC
+a Knica clave est. $ormada por los
campos pro , artC >o se admiten dupliA
cados ni modi$icaciones de clavesC +os
campos de tipo char inclu,en el nulo
$inal
cl**v
El programa inserta un registro en %E<!<)4CB-' por cada registro de
6'-!#CB-' cu,a e*istencia est. &ajo m@nimosC En ese caso genera un registro en
el que la cantidad a pedir Dcampo can de %E<!<)4CB-'E se o&tiene como la
di$erencia opt S e(i de 6'-!#CB-'C
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
#incIude "c:\btr\turcbtrv.c"
#define ABRIR 0
#define CERRAR 1
#define INSERTAR 2
#define SIGUIENTE 6
#define INFERIOR 12
#define AR 0
#define PD 1
#define NF 2
struct REGART {
char cod[7];
char des[41];
unsigned exi;
unsigned min;
unsigned opt;
unsigned pco;
unsigned pvp;
char pro[7];
};
struct REGPED {
char pro[7];
char art[7];
unsigned can;
unsigned pre;
};
union REGTOT {
struct REGART ar;
struct REGPED pd;
};
int Btr (int op, int fich);
void BtrError (int st, int op, int fich);
void Cerrar (int fich);
char fichero[NF][13] = { "ARTIC.BTR", "PEDIDOS.BTR" };
union REGTOT reg[NF];
char bIoque[NF][128];
int Iongitud[NF] = { sizeof (struct REGART), sizeof (struct REGPED) };
char keyvaI[NF][14];
void main (void)
{
int st, i;
cl**vi
for (i = 0; i < NF; i++) {
strcpy (keyvaI[i], fichero[i]);
st = Btr (ABRIR, i);
if (st) {
BtrError (st, ABRIR, i);
Cerrar (i);
exit (1);
}
}
st = Btr (INFERIOR, AR);
whiIe (!st) {
if (reg[AR].ar.exi < reg[AR].ar.min) {
strcpy (reg[PD].pd.pro, reg[AR].ar.pro);
strcpy (reg[PD].pd.art, reg[AR].ar.cod);
reg[PD].pd.can = reg[AR].ar.opt - reg[AR].ar.exi;
reg[PD].pd.pre = reg[AR].ar.pco;
st = Btr (INSERTAR, PD);
if (st) BtrError (st, INSERTAR, PD);
}
st = Btr (SIGUIENTE, AR);
}
if (st != 9) BtrError (st, SIGUIENTE, AR);
Cerrar (NF);
}
int Btr (int op, int fich)
{
return BTRV (op, bIoque[fich], &reg[fich], &Iongitud[fich], keyvaI[fich], 0);
}
void BtrError (int st, int op, int fich)
{
printf ("\n%s: Error %d en operacin %d", fichero[fich], st, op);
printf ("\nPuIse una tecIa ...");
whiIe (!getch ()) getch ();
}
void Cerrar (int fich)
{
register int i;
int st;
for (i = 0; i < fich; i++) {
st = Btr (CERRAR, i);
if (st) BtrError (st, CERRAR, i);
}
}
Cdigos de error 3trie4e
+a siguiente ta&la muestra los valores de retorno posi&les devueltos por
B-'0 si la operaci"n no tiene 9*ito:
cl**vii
&3 DESCRIPCIN &3 DESCRIPCIN
1 .6di*o de operaci6n in!)lido 1& $ic?ero no encontrado
& Jrror de J5S 1+ Jrror de eFtensi6n
+ $ic?ero no abierto 1, Jrror de preapertura
, .la!e no encontrada 1@ Jrror de preima*en
@ o se admiten cla!es
duplicadas
1A Jrror de eFpansi6n
A Umero de cla!e incorrecto 17 Jrror de cierre
7 Umero de cla!e cambiado 18 1isco lleno
8 (osicionamiento in!)lido 19 Jrror irrecuperable
9 $in de 'ic?ero &0 o est) car*ado BTR3J%J
10 o se permite modi'icar la
cla!e
&1 Jrror en )rea de cla!e
11 ombre de 'ic?ero in!)lido && Jrror en tamaTo de re*istro
&3 DESCRIPCIN &3 DESCRIPCIN
&+ Blo;ue de posici6n = 1&8 b:tes ,8 Jrror en secuencia alternati!a
&, Jrror de tamaTo de p)*ina ,9 Jrror en tipo de cla!e
&@ Jrror de J5S en creaci6n @0 (alabra de paso :a asi*nada
&A Umero de cla!es incorrecto @1 (alabra de paso in!)lida
&7 (osici6n de la cla!e incorrecta @& Jrror al *rabar desde memoria
&8 "on*itud del re*istro incorrecta @+ 3nter'ase in!)lida (%ersi6n)
&9 "on*itud de cla!e incorrecta @, o se puede leer p)*ina
!ariable
+0 o es un 'ic?ero Btrie!e @@ Jrror de autoincremento
+1 Jrror en eFtensi6n @A ^ndice incompleto
+& Jrror de J5S en eFtensi6n @7 Jrror de memoria eFpandida
+, ombre in!)lido par eFtensi6n @8 Yrea de compresi6n pe;ueTa
+@ Jrror de directorio @9 $ic?ero eFistente
+A Jrror en transacci6n 80 .on'licto
+7 Transacci6n :a acti!a 81 Blo;ueo in!)lido
+8 Jrror de J5S en 'ic?ero de
transB
8& (osicionamiento perdido
+9 Jrror de 'in5aborto de transacB 8+ "ectura 'uera de transacci6n
,0 1emasiados 'ic?eros en
transacB
8, Re*istro blo;ueado
,1 Pperaci6n no permitida 8@ $ic?ero blo;ueado
,& Acceso acelerado incompleto 8A Tabla de 'ic?eros llena
,+ 1irecci6n in!)lida (Pperaci6n
&+)
87 Tabla de identi'icadores llena
,, %#a de acceso con cla!e nula 88 Jrror en modo de apertura
,@ Jrror en indicadores de cla!e 9+ Tipo de blo;ueo incompatible
,A Acceso dene*ado 9, Jrror de alto ni!el
,7 1emasiados 'ic?eros abiertos
E7ercicios
cl**viii
1. En un #entro de EnseFan1a se dispone de una Base de <atos con
in$ormaci"n so&re las $altas de asistencia a clase de sus alumnosC <os de los
$icheros de dicha Base de <atos se descri&en a continuaci"n:
ALUMNOS.BTR a!os de "lumnos
#nde$ado %!rieve
Campo Descripcin Tipo CIave
gru Clave del grupo char(&) '() '*
nom "pellidos + nombre del alumno char(,*) '*) '2
faI -al!as mes/asigna!ura in! *2$.
/a clave K0 es el campo gru0"dmi!e duplicados0
/a clave K1 es!1 formada por los campos gru + nom0 2o admi!e duplicados0
/a clave K2 es!1 formada por el campo nom0 2o admi!e duplicados0
/as !res claves son de !ipo srin=0
3l campo gru slo puede almacenar los valores4 *-52%) 2-52") 2-52%)
2-52C) ,-52" + ,-52%0
3l campo faI es una ma!riz en!era de *2 filas por . columnas 6ue debe
in!erpre!arse como sigue4 3l elemen!o faI[i][j] se refiere al n7mero de fal!as
del mes i en la asigna!ura j0
GRUPO.BTR a!os del 8rupo
#nde$ado %!rieve
Campo Descripcin Tipo CIave
gru Clave del grupo char(&) '(
asg "brevia!ura de las asigna!uras char .$&
/a clave K0 es el campo gru0 2o admi!e duplicados0 3s de !ipo srin=0
3l campo gru slo puede almacenar los valores4 *-52%) 2-52") 2-52%)
2-52C) ,-52" + ,-52%0
3l campo asg es una ma!riz de . cadenas de & carac!eres 6ue almacenan las
abrevia!uras de los nombres de las asigna!uras del grupo0 5or ejemplo)
59"C: para 5r1c!icas0
Escri&e un programa que solicite por teclado un grupo , un mes, , realice un
in$orme impreso de las $altas de todos los alumnos del grupo durante ese
mes, por orden al$a&9tico , totali1ando por alumno , asignaturaC El $ormato
de dicho in$orme de&e ser el siguiente:
GRUPO: XXXXX
FALTAS DEL MES DE: XXXXXXXXXX
ApeIIidos y Nombre abr1 abr2 abr3 abr4 abr5 abr6 abr7 abr8 TOT
$$$$$$$$$$$$$$$$$$$$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$
000 000 000 000 000 000 000 000 000 000
000 000 000 000 000 000 000 000 000 000
$$$$$$$$$$$$$$$$$$$$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$
:;:"/3<4 $$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$ $$$
D+os t@tulos abr1, CCC, abr* son los nom&res a&reviados de las asignaturasEC
2. En la &i&lioteca de un !nstituto se controla el pr9stamo de li&ros mediante
una Base de <atos $ormada por los siguientes $icheros Btrieve:
cl**i*
PRESTAMO.BTR /ibros pres!ados
#nde$ado %!rieve
Campo Descripcin Tipo CIave
fec -echa del pr=s!amo char(>) '(
isbn #<%2 char(**)
exp 2? de e$pedien!e del alumno char(&)
dev evuel!o </2 char k*
/a clave K0 es el campo fec0 "dmi!e duplicados0 :ipo srin=0
/a clave K1 es el campo dev0 "dmi!e duplicados0 :ipo srin=0
3l campo fec almacena la fecha del pr=s!amo en forma!o """"@@0
3l campo exp almacena slo dAgi!os num=ricos + es!1 comple!ado con ceros a
la iz6uierda0 5or ejemplo) el e$pedien!e &B se almacena como (((&B0
3l campo dev almacena el car1c!er S si el libro ha sido devuel!o) + el car1c!er
N en caso con!rario0
LIBROS.BTR @aes!ro de libros
#nde$ado %!rieve
Campo Descripcin Tipo CIave
isbn #<%2 char(**) '(
tit :A!ulo char(B*)
aut "u!or char(,*)
edi 3di!orial char(,*)
/a clave K0 es el campo isbn0 2o admi!e duplicados0 3s de !ipo srin=0
ALUMNOS.BTR a!os de alumnos
#nde$ado %!rieve
Campo Descripcin Tipo CIave
exp 2? de e$pedien!e del alumno char(&) '(
nom 2ombre char(,*)
gru 8rupo char(**)
/a clave K0 es el campo exp0 2o admi!e duplicados0 3s de !ipo srin=0
3l campo exp almacena slo dAgi!os num=ricos) + es!1 comple!ado a la
iz6uierda con ceros0
-eniendo en cuenta que los li&ros pueden estar prestados un m.*imo de 5
d@as, constru,e un programa que realice un listado de aquellos li&ros que no
han sido devueltos en el pla1o indicadoC %ara ello se asumir. como $echa del
d@a la del sistemaC El listado imprimir. 6 $ichas por p.gina con el siguiente
$ormato para cada $icha:
"lumno4 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 8rupo4 $$$$$$$$$$
:A!ulo4
"u!or4
3di!orial4
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
-echa del pr=s!amo4 $$ de $$$$$$$$$$ de $$$$
cl***
3. <isponemos de un $ichero secuencial llamado /)0!/C-/% en el que se
registran todos los movimientos de art@culos en los almacenes de una
empresaC +a descripci"n de este $ichero es la siguiente:
MOVIM.TMP 3/< de ar!Aculos
<ecuencial
Campo Descripcin Tipo CIave
aIm Cdigo de almac=n char(,)
art Cdigo de ar!Aculo char(C)
can Can!idad unsigned
ope ;peracin 3/</% char
3l campo aIm con!iene dos digi!os num=ricos0 "sA) el almac=n * se codifica
como D(*D0
3l campo ope almacena una E si es una en!rada de ma!erial) una S si es una
salida) + una B si el ar!Aculo debe darse de baja en su almac=n0
3l archivo no es!1 ordenado bajo ning7n cri!erio0
6 partir de este archivo se desea actuali1ar las e*istencias en el /aestro de
6rt@culos, 6'-!#CB-', cu,a descripci"n es la siguiente:
ARTIC.BTR @aes!ro de "r!Aculos
#nde$ado %!rieve
Campo Descripcin Tipo CIave
aIm Cdigo de almac=n char(,) '(
art Cdigo de ar!Aculo char(C) '() '*
des escripcin del ar!Aculo char(4*)
exi 3$is!encia in!
min @Animo unsigned
opt Ep!imo unsigned
pvp 5recio de ven!a unsigned
pco 5recio de compra unsigned
/a clave K0 es!1 formada por los campos aIm + art0 2o se admi!en duplicados
ni modificaciones0 3s de !ipo srin=0
/a clave K1 coincide con el campo art0 "dmi!e duplicados0 3s de !ipo srin=0
3l campo aIm con!iene dos digi!os num=ricos0 "sA) el almac=n * se codifica
como D(*D0
Escri&e un programa que e$ectKe dicha actuali1aci"n de e*istenciasC %ara ello
has de tener en cuenta:
"i el campo ope de ,/]I,.T,:
almacena...
6a operacin a reali5ar en
0LTIC.3TL es2
E e*i M e*i L can
4 e*i M e*i A can
B Borrar el registro correspondiente
12
Compilacin - enla5ado
cl***i
Introduccin
-ur&o # proporciona un entorno integrado de desarrollo de aplicaciones
D!<E: Integrated ;evelopment EnvironmentE que permite, mediante un sencillo
sistema de menKs, editar, compilar, enla1ar, ejecutar , depurar un programa sin
a&andonar dicho entornoC %ero, adem.s, puede usarse cualquier editor de te*to
para crear nuestros programas, , reali1ar la compilaci"n , enla1ado desde la l@nea
de "rdenes del <)4C En este cap@tulo se muestra c"mo hacerloC
,odelos de memoria
#uando un programa # se carga en memoria de&emos distinguir en 9l cuatro
partes:
Cdigo del programaC
;atos estticos: <atos con tiempo de vida glo&al a los que se asigna
memoria en los segmentos de datos del programaC
;atos dinmicos: <atos a los que se les asigna memoria en tiempo de
ejecuci"n, a medida que se necesitaC Esta memoria no se toma de los
segmentos de datos, sino de una 1ona aparte denominada montn DheapEC
;atos automticos: <atos localesC 4e les asigna memoria en la pila
cuando se ejecuta el &loque del programa en que est.n de$inidosC
En # ha, 6 $ormas posi&les de organi1ar estas partes del programa en la
memoriaC Estos 6 modelos de memoria se denominan:
<iminuto D-in,E
%equeFo D4mallE
/ediano D/ediumE
#ompacto D#ompactE
=rande D+argeE
Enorme DQugeE
,odelo ;iminuto (Tin-)
-anto el c"digo como los datos ocupan el mismo segmento, que es KnicoC
%or tanto, un programa compilado , enla1ado &ajo este modelo no puede superar
los 64 ?&C Estos programas no asignan memoria para su pila, sino que utili1an la
del <)4C %or ello, en el enla1ado se muestra la advertencia 0arning1 no stac/C
+os registros #4, <4, E4 , 44 no cam&ian durante el programa , tienen todos el
cl***ii
mismo valorC +os programas CEBE generados as@ pueden convertirse a C#)/
mediante la utilidad del <)4 EBE2B!>, cu,a sinta*is es
e(e2bin prog.e(e prog.com
,odelo :eKue\o ("mall)
Es el modelo usado por de$ectoC %uede contener 64 ?& de c"digo , otros
64 ?& para todos los datosC <urante la ejecuci"n del programa los valores de #4,
<4, E4 , 44 no cam&ian, pero a di$erencia con el modelo diminuto, #4 , <4
contienen valores di$erentesC
,odelo ,ediano (,edium)
-odos los datos se almacenan en el mismo segmento, por lo que no pueden
superar los 64 ?&C %or el contrario, el c"digo puede ocupar hasta 1 /& D16
segmentos de 64 ?&EC
,odelo Compacto (Compact)
El c"digo est. limitado a un segmento de 64 ?&, pero los datos pueden
ocupar 1 /&C <e los 16 segmentos de datos, s"lo uno D64 ?&E puede ser utili1ado
para los datos est.ticosC
,odelo Mrande (6arge)
-anto el c"digo como los datos pueden ocupar 1 /& cada uno, pero los
datos est.ticos est.n limitados a 64 ?&C
,odelo Enorme (Ouge)
/antiene las capacidades del modelo =rande, pero sin la limitaci"n de 64 ?&
para datos est.ticosC
%ara decidir qu9 modelo de memoria se de&e utili1ar, ha, que tener en cuenta
los siguientes aspectos:
#antidad de c"digo , datos del programaC
+os programas generados con los modelos de memoria m.s pequeFos se
ejecutan m.s r.pidamente, por lo que ha, que elegir el modelo de
memoria m.s pequeFo posi&leC
#ualquier archivo C)B] resultante de compilar un m"dulo simple no
puede so&repasar los 64 ?& de c"digo ni los 64 ?& de datos, puesto que
cl***iii
cada m"dulo compilado ha de encajar en un segmento de memoriaC
#uando se utili1an los modelos /ediano, =rande , Enorme los programas
pueden llegar hasta 1 /&, pero a &ase de m"dulos no superiores a 64 ?&C
4i el c"digo de algKn m"dulo supera este l@mite, se genera un mensaje
2oo much code defined in file
4i los datos est.ticos superan los 64 ?&, se genera el mensaje
2o much global data defined in file
En am&os casos ha, que dividir los m"dulos en $icheros m.s pequeFosC
El compilador TCC
El programa -##CEBE es el compilador independiente del entornoC
/ediante -## podemos o&tener directamente programas CEBE, o &ien
archivos C)B] para ser enla1ados posteriormenteC +a sinta*is de -## es
tcc 3o"ciones4 fichero5s6
+a siguiente ta&la muestra las opciones posi&les
OPCIN SIGNIFICADO
0A
0a
0a0
0B
0.
0c
01n%O
01n%O<ca"
0d
0en%O
0'
0'0
0'87
0K
0*N
03$u3a
0iN
0ON
0L
0L0
0"$u3a
09
S6lo reconoce palabras cla!e AS3B
Alinea los datos en 'rontera de palabraB
Alinea los datos en 'rontera de b:teB
Acepta c6di*o ensamblador : llama a 9AS9 para procesarloB
Acepta comentarios anidadosB
.ompila a BPBV (sin enlazar)B
1e'ine el nombre (n%O) de una constanteD como si 'uera una
directi!a N"!6in! dentro del pro*ramaD para ser usada con la
directi!a Ni6 "!6in!"B
Hace lo mismo ;ue una directi!a N"!6in! n%O ca"B
Asi*na la misma posici6n de memoria a cadenas idEnticas
del c6di*o 'uenteB
Jstablece el nombre del 'ic?ero BJGJ resultanteB
Msa la emulaci6n de coma 'lotanteB
(one en o'' la emulaci6n de coma 'lotanteB
Msa el coprocesador matem)tico sin *enerar c6di*o de
emulaci6nB
Pptimiza el c6di*o para !elocidad en lu*ar de para tamaToB
1etiene la compilaci6n tras N ad!ertencias (Qarnin*s)B
Jstablece la $u3a para los arc?i!os Ninclu"!B
Jspeci'ica la lon*itud de los identi'icadoresB
1etiene la compilaci6n tras N erroresB
Jstablece por de'ecto para el tipo cPa$ el modi'icador
un&in!"B
Jstablece por de'ecto para el tipo cPa$ el modi'icador
cl***iv
0mU
0
0n$u3a
0P
0on%O
0p
0p0
0r
0r0
0S
0Mn%O
0\
0\0
0\UUU
0\UUU0
0N
0:
0_
0z
01
010
0&
&in!"B
Jstablece la $u3a para las bibliotecasB
.rea arc?i!o de mapa de memoriaB
Jstablece un modelo de memoria se*Un el car)cter U (()*B
198)B
.omprueba el desbordamiento de pilaB
Jstablece el directorio para los 'ic?eros de salida (BPBV :
BJGJ)B
Pptimiza el c6di*o para tamaTo en lu*ar de para !elocidadB
Jspeci'ica el nombre del arc?i!o BPBVD sin llamar al enlazadorB
Msa el con!enio de llamada de (ascalB
Msa el con!enio de llamada de .B
(ermite a las !ariables $!i&3!$ usar los re*istros S3 : 13B
(one a o'' la opci6n anteriorB
Kenera como salida un 'ic?ero 'uente en ensamblador
(BAS9)B
1eOa sin de'inir las de'iniciones pre!ias dadas por la opci6n
01B
9uestra mensaOes de ad!ertenciaB
o muestra mensaOes de ad!ertenciaB
(one en on las ad!ertencias de error UUUD c6di*o de + letras
;ue especi'ica el tipo (!er Ku#a del (ro*ramador)B
(one en o'' las ad!ertencias de error UUUB
$abrica la pila est)ndarB
3nclu:e nUmeros de l#nea en el c6di*oB
Acti!a la optimizaci6n de re*istroB Jl pro*rama recuerda el
contenido de los re*istros :D si es posibleD !uel!e a utilizarlos
en lu*ar de !ol!er a car*ar el !alor de memoriaB
Jspeci'ica los nombres de los se*mentos (Ku#a de
Re'erencia)B
Kenera instrucciones 8018A580&8AB
o *enera instrucciones 8018A580&8AB
Kenera instrucciones 80&8A en modo prote*idoB
%or ejemplo, la orden
tcc SIc2FtcFinclude Smc Seprog fic&1 fic&2 fic&3.ob7
contiene las opciones
SI indica que los archivos #include se &uscar.n en c2FtcFincludeC
Sm especi$ica el modelo de memoria a usarC En este caso, Smc selecciona
el modelo #ompactoC
Se especi$ica que el $ichero resultante de la compilaci"n ser. :L/M.EREC
+a orden anterior compila los archivos F!#Q1C# , F!#Q2C# , o&tiene los
archivos F!#Q1C)B] , F!#Q2C)B] correspondientes que enla1a despu9s con
F!#Q3C)B] para o&tener %')=CEBEC
En los procesos de compilaci"n ha, opciones que se repiten en la ma,or@a de
las ocasiones , que de&emos teclear cada ve1C %ara evitar esto puede crearse un
archivo de con$iguraci"n denominado -;'B)#C#F= con las opciones m.s
comunesC -## &usca siempre este archivo en el directorio actual, , si no lo
encuentra lo &usca en el directorio en que est. u&icado -##, generalmente el
cl***v
directotio c2FtcFbinC %or ejemplo, el archivo -;'B)#C#F= puede tener las
siguientes l@neas:
SIc2FtcFinclude
S6c2FtcFlib
Sms
SM
con lo que -## &uscar. los archivos #include en c2FtcFinclude DA!E, las &i&liotecas
en c2FtcFlib DA+E, seleccionar. el modelo #ompacto de memoria DAmcE , optimi1ar.
el c"digo para velocidad DA=EC
El enla5ador T6I<h
#uando ejecutamos -## sin la opci"n Sc, los archivos son compilados ,
enla1ados para o&tener el ejecuta&leC %ero puede usarse -## de $orma que s"lo
compile, sin enla1ar, usando la opci"n ScC %or ejemplo
tcc SIc2FtcFinclude Smc SM Sc fuentes
compila los archivos de la lista fuentes a C)B] sin enla1arlos despu9sC
%osteriormente de&e usarse el enla1ador independiente -+!>?, cu,a sinta*is es
tlin' 3o"ciones4 archivos_7-89 archivo_:;:9 archivo_<$P9 bibliotecas
+as opciones de -+!>? se muestran a continuaci"n:
OPCI
N
SIGNIFICADO
5c
5d
5e
5i
5l
5m
5n
5s
5t
5!
5F
5+
"os s#mbolos (MB"3. : JGTJR distin*uen ma:Usculas :
minUsculasB
9ostrar una ad!ertencia si ?a: s#mbolos duplicados en las
bibliotecasB
o usar palabras cla!e eFtendidasB
3nicializar todos los se*mentos
3ncluir los nUmeros de l#nea de la 'uente para la depuraci6nB Js
necesario usar la opci6n .Y con T..B
3ncluir los s#mbolos pUblicos en el arc?i!o de mapaB
3*norar las bibliotecas por de'ectoB
3ncluir un mapa detallado de los se*mentos en el arc?i!o de mapaB
.rear un arc?i!o B.P9 (s6lo para el modelo 1iminuto de memoria)B
3ncluir toda la in'ormaci6n completa de depuraci6nB
o crear un arc?i!o de mapaB
Msar procesamiento completo de +& bitsB
archivos_7-8 es el nom&re de todos los archivos C)B] que se quieren
enla1ar Dseparados por &lancosEC El primero de ellos ha de ser un m"dulo de
iniciaci"n de -ur&o #C Estos m"dulos est.n normalmente en el directorio c2FtcFlib
, ha, uno para cada modelo de memoriaC El nom&re de estos archivos es #2(C)B],
cl***vi
siendo ( un car.cter que especi$ica el modelo de memoria usadoC +os valores
posi&les de * se especi$ican en la ta&la siguiente:
U HODEFO
t 1iminuto (Tin:)
s (e;ueTo (Small)
m 9ediano (9edium)
c .ompacto
(.ompact)
l Krande ("ar*e)
? Jnorme (Hu*e)
6s@, el archivo c2FtcFlibFc1l.ob7 es el m"dulo de iniciaci"n de -ur&o # para el
modelo =rande de memoriaC
archivo_:;: es el nom&re del programa ejecuta&le a generarC 4i no se
especi$ica, se asume el nom&re del primer archivo C)B] que no sea un m"dulo de
iniciaci"n de -ur&o #C
archivo_<$P es el nom&re de un archivo que contiene un mapa de memoria
del programaC -iene e*tensi"n C/6% ,, si no se especi$ica, asume como nom&re el
del archivo CEBEC El $ichero de mapa no se crea -+!>? lleva la opci"n !(C
bibliotecas es una lista de &i&liotecas a enla1arC 6parte de las &i&liotecas de
usuario, de&e enla1arse el correspondiente archivo de &i&lioteca est.ndarC E*iste
uno para cada modelo de memoria , se almacenan en c2FtcFlibC El nom&re de estos
archivos es #(C+!B, siendo ( un car.cter de la ta&la anterior que especi$ica el
modelo de memoriaC 6dem.s de estas &i&liotecas, si el programa usa operaciones
en coma $lotante de&e enla1arse el archivo F%85C+!B si se dispone de
coprocesador matem.ticoC En caso contrario se enla1ar. el archivo E/;C+!BC
6m&os archivos se encuentran, normalmente, en c2FtcFlibC %or Kltimo est.n los
archivos que almacenan las rutinas matem.ticas, que se llaman /6-Q(C+!B,
siendo ( el car.cter que identi$ica el modelo de memoriaC
#on las siguientes "rdenes se compila el archivo %')=C# Dque usa
operaciones en coma $lotanteE a %')=C)B] , posteriormente se enla1a a
%')=CEBE sin generar $ichero de mapaC 4e usa el modelo %equeFo de memoriaC
tcc SIc2FtcFinclude Sms SM Sc prog
tlin' !( c2FtcFlibFc1s prog8 8 8 c2FtcFlibFemu c2FtcFlibFcs
El enla1ador -+!>? tam&i9n permite la sinta*is
tlin' ifichero_res"uesta
siendo fichero_res"uesta un archivo de te*to con todas las "rdenesC %or ejemplo,
un $ichero de respuesta puede ser
!( Q
c2FtcFlibFc1s prog1 prog28 Q
prog38 Q
cl***vii
8 Q
c2FtcFlibFcs
donde los signos L indican continuaci"n en la l@nea siguienteC
El bibliotecario T6I3
;na &i&lioteca es un archivo C+!B que almacena m"dulos C)B]C ;n
programa puede hacer llamadas a $unciones que han sido compilados
individualmente e incluidos en una &i&liotecaC %ara ello se enla1a el programa con
la &i&lioteca , en este proceso de enla1ado s"lo se tomar.n de la &i&lioteca los
m"dulos o&jeto que se usenC El &i&liotecario de -ur&o # se llama -+!B , la
sinta*is de su uso es
tlib nombre_biblioteca =o">modulo_7-8
donde nombre_biblioteca es el nom&re del archivo C+!B, , modulo_7-8 es el
m"dulo so&re el que se reali1a la operaci"n indicada por o", que puede ser una de
las siguientes:
OPERADOR ACCIN
2
0
4
02 6 20
04 6 40
ATade un m6dulo a la biblioteca
Jlimina un m6dulo de la biblioteca
JFtrae un arc?i!o BPBV de la biblioteca
Reemplaza el m6dulo especi'icado con una nue!a
copia
JFtrae el m6dulo especi'icado : lo elimina de la
biblioteca
%or ejemplo, la orden
tlib mibiblio Qfuncion1 Sfuncion2
aFade el archivo F;>#!)>1C)B] a la &i&lioteca /!B!B+!)C+!B , elimina de la
misma el archivo F;>#!)>2C)B]C
6n.logamente a -+!>?, -+!B admite un $ichero de respuestas, en cu,o
caso la sinta*is es
tlib nombre_biblioteca ifichero_res"uestas
6a utilidad ,0hE
El programa /6?E automati1a la recompilaci"n de programas $ormados
por varios m"dulosC B.sicamente, /6?E comprue&a si alguno de los m"dulos de
que est. compuesto el programa ha sido modi$icado , reali1a las acciones de
cl***viii
compilaci"n, enla1ado u otras necesarias para la actuali1aci"n del programaC %ara
ello, /6?E parte de un archivo de construccin, que est. compuesto por
sentencias como las siguientes:
archivo_ob?etivo11 lista_de_archivos_de"endientes
secuencia de rdenes
archivo_ob?etivo21 lista_de_archivos_de"endientes
secuencia de rdenes
...
...
archivo_ob?etivoN1 lista_de_archivos_de"endientes
secuencia de rdenes
+a l@nea que contiene archivo_ob?etivo de&e empe1ar en la primera columna,
, la secuencia de rdenes de&e comen1ar por una ta&uladorC Entre cada &loque
de&e ha&er, al menos, una l@nea en &lancoC
;n archivo ob?etivo es aqu9l que se o&tiene a partir de los archivos
de"endientesC %or ejemplo, %')=C# es un archivo dependiente de %')=C)B]
pues para crear %')=C)B] ha, que compilar %')=C#C
%or ejemplo, si el programa %')= est. $ormado por los m"dulos /)<1 ,
/)<2, el archivo de construcci"n de /6?E podr@a tener el siguiente aspecto:
:L/M.ERE2 ,/;1./3P ,/;2./3P
tlin' !( c1s mod1 mod28 prog88 cs
,/;1./3P2 ,/;1.C
tcc SIc2FtcFinclude SM Sc Sms mod1
,/;2./3P2 ,/;2.C
tcc SIc2FtcFinclude SM Sc Sms mod2
El programa /6?E &usca un archivo de construcci"n llamado /6?EF!+EC
Basta entonces con teclear desde la l@nea de "rdenes del <)4
ma'e
4i el archivo tiene un nom&re di$erente, digamos %')=C/6?, de&e usarse la
opci"n Sf como sigue:
ma'e Sf:L/M.,0h
/6?E tiene varias opciones disponi&les, que se pueden consultar mediante
la opci"n SI Dma'e SIEC
cl***i*
Dn e7emplo sencillo
0amos a aplicar lo e*plicado en los apartados del cap@tulo con un ejemplo
sencilloC En primer lugar, supondremos que nuestro directorio de tra&ajo es
#:N-'6B6]) , que en 9l tenemos el archivo -;'B)#C#F= siguiente:
SIc2FtcFinclude
S6c2FtcFlib
SM
, el archivo E]E/%+)C# siguiente:
., Pro=rama EKEMPLO0- ,.
#incIude <stdio.h>
#inIcude <conio.h>
fIoat suma (fIoat, fIoat);
fIoat producto (fIoat, fIoat);
void main (void)
{
fIoat a, b;
cIrscr ();
printf ("TecIea dos nmeros: ");
scanf ("%f %f", &a, &b);
printf ("\nSuma: %f", suma (a, b));
printf ("\nProducto: %f", producto (a, b));
}
fIoat suma (fIoat x, fIoat y);
{
return x + y;
}
fIoat (producto (fIoat x, fIoat y)
{
return x * y;
}
%ara o&tener el programa E]E/%+)CEBE &asta con hacer:
C2FTL030P/> tcc Sms e7emplo
Turbo CQQ ]ersion 1.11 Cop-rig&t (c) 1..1 3orland International
e7emplo.c2
Turbo 6in' ]ersion 3.1 Cop-rig&t (c) 1.*+8 1..1 3orland International
04ailable memor- &&&&&&
C2FTL030P/>
c*c
<espu9s de esto, el directorio tendr. los archivos
e7emplo.c
turboc.cfg
e7emplo.ob7
e7emplo.e(e
El archivo E]E/%+)C)B] es el o&jeto resultante de la compilaci"n, ,
E]E/%+)CEBE es el ejecuta&le que se o&tiene despu9s del enla1ado con los
modulos de iniciaci"n , &i&liotecas de -ur&o #C
;n inconveniente que podemos encontrar en este m9todo es que las
$unciones suma() , producto() s"lo sirven para el programa E]E/%+)C#C 4i
quisieramos usar estas $unciones en otros programas, tendr@amos que teclearlas de
nuevo al editarlosC Esto no es demasiado pro&lema en $unciones como las del
ejemplo, pero resulta mu, inc"modo para $unciones con m.s c"digo o que usemos
ha&itualmente en nuestros programasC +a soluci"n consiste en guardar en archivos
di$erentes el programa E]E/%+)C# Dla parte que contiene las declaraciones , la
$unci"n main()E , las $unciones suma() , producto(), por ejemplo, en archivos
4;/6C# , %')<C#C
., Pro=rama EKEMPLO0- ,.
#incIude <stdio.h>
#inIcude <conio.h>
fIoat suma (fIoat, fIoat);
fIoat producto (fIoat, fIoat);
void main (void)
{
fIoat a, b;
cIrscr ();
printf ("TecIea dos nmeros: ");
scanf ("%f %f", &a, &b);
printf ("\nSuma: %f", suma (a, b));
printf ("\nProducto: %f", producto (a, b));
}
., Archi&o ?UMA0-A Funcin suma ,.
fIoat suma (fIoat x, fIoat y);
{
return x + y;
}
., Archi&o PRO+0-A Funcin produco ,.
fIoat (producto (fIoat x, fIoat y)
{
return x * y;
}
c*ci
6hora compilaremos por separado cada uno de estos m"dulos ,, posteriormente,
haremos el enla1adoC
C2FTL030P/> tcc Sc Sms e7emplo
Turbo CQQ ]ersion 1.11 Cop-rig&t (c) 1..1 3orland International
e7emplo.c2
04ailable memor- &&&&&&
C2FTL030P/> tcc Sc Sms prod
Turbo CQQ ]ersion 1.11 Cop-rig&t (c) 1..1 3orland International
prod.c2
04ailable memor- &&&&&&
C2FTL030P/> tcc Sc Sms suma
Turbo CQQ ]ersion 1.11 Cop-rig&t (c) 1..1 3orland International
suma.c2
04ailable memor- &&&&&&
C2FTL030P/> tlin' !( c1s e7emplo prod suma8 e7emplo88 emu mat&s
cs
13
Turbo 6in' ]ersion 3.1 Cop-rig&t (c) 1.*+8 1..1 3orland International
C2FTL030P/>
<espu9s de esto, en el directorio #:N-'6B6]) tendremos los siguientes
archivos:
e7emplo.c
prod.c
suma.c
turboc.cfg
e7emplo.ob7
prod.ob7
suma.ob7
e7emplo.e(e
+os RC)B] son los resultantes de las compilaciones de los RC#, ,
E]E/%+)CEBE es el ejecuta&le $inalC
Este m9todo de tra&ajo permite tener por separado nuestras $unciones
compiladas Den $ormato C)B]E, disponi&les para ser enla1adas con cualquier
programaC 6dem.s, si modi$icamos uno de los m"dulos &asta con recompilarlo ,,
posteriormente, hacer el enla1ado, sin recompilar los m"dulos que no han sido
13
Para no tener que indicar en los archivos c0s, emu, maths y cs el camino de
bsqueda c:\tc\lib (lo que puede dar problemas, al ser la lnea de rdenes demasiado
larga) es conveniente ejecutar previamente la orden APPEND c:\tc\lib (o bien incluirla
en el archivo AUTOEXEC.BAT). Esta orden es similar a la orden PATH, en el sentido que
indica a las aplicaciones dnde buscar los archivos que no se encuentren en el directorio
actual.
c*cii
modi$icadosC %or ejemplo, si hacemos algKn cam&io en E]E/%+)C#, &astar. con
hacer:
C2FTL030P/> tcc Sc Sms e7emplo
Turbo CQQ ]ersion 1.11 Cop-rig&t (c) 1..1 3orland International
e7emplo.c2
04ailable memor- &&&&&&
C2FTL030P/> tlin' !( c1s e7emplo prod suma8 e7emplo88 emu mat&s cs
Turbo 6in' ]ersion 3.1 Cop-rig&t (c) 1.*+8 1..1 3orland International
C2FTL030P/>
%ero para estos casos es mu, Ktil el programa /6?EC #reamos el siguiente
archivo de construcci"n /6?E, al que llamaremos E]E/%+)C/6?:
e7emplo.e(e2 e7emplo.ob7 prod.ob7 suma.ob7
tlin' !( c1s e7emplo prod suma8 e7emplo88 emu mat&s cs
e7emplo.ob72 e7emplo.c
tcc Sc Sms e7emplo
prog.ob72 prod.c
tcc Sc Sms prod
suma.ob72 suma.c
tcc Sc Sms suma
4uponiendo que tenemos en el directorio #:N-'6B6]) los siguientes archivos
e7emplo.c
prod.c
suma.c
turboc.cfg
e7emplo.ma'
despu9s de
C2FTL030P/> ma'e Sfe7emplo.ma'
tendremos, adem.s, los archivos
e7emplo.ob7
prod.ob7
suma.ob7
e7emplo.e(e
4i se modi$ica alguno de los m"dulos, digamos 4;/6C#, , repetimos la orden
c*ciii
C2FTL030P/> ma'e Sfe7emplo.ma'
o&servaremos que /6?E se encarga de recompilar 4;/6C# , enla1ar el
4;/6C)B] resultante con el resto de m"dulos o&jeto , &i&liotecas, sin recompilar
E]E/%+)C# ni %')<C#C
)tra posi&ilidad consiste en tener almacenados nuestros m"dulos o&jeto en
una &i&liotecaC 4upongamos que tenemos en #:N-'6B6]) los archivos
e7emplo.c
prod.c
suma.c
turboc.cfg
e7emplo.ob7
prod.ob7
suma.ob7
, hacemos
C2FTL030P/> tlib milib Qsuma Qprod
T6I3 3.1 Cop-rig&t (c) 1.*+8 1..1 3orland International
C2FTL030P/> del suma.ob7 5no es necesario6
C2FTL030P/> del suma.ob7 5no es necesario6
+os archivos en #:N-'6B6]) ser.n
e7emplo.c
prod.c
suma.c
turboc.cfg
e7emplo.ob7
milib.lib
El enla1ado se hace ahora
C2FTL030P/> tlin' !( c1s e7emplo8 e7emplo88 emu mat&s cs milib
Turbo 6in' ]ersion 3.1 Cop-rig&t (c) 1.*+8 1..1 3orland International
C2FTL030P/>
<e este modo podemos tener una colecci"n de m"dulos o&jeto disponi&le para
cualquier programa mediante la &i&lioteca /!+!BC+!BC
13
6a biblioteca
c*civ
de funciones de Turbo C
Introduccin
6 continuaci"n se descri&en algunas de las $unciones de la &i&lioteca de
-ur&o #, agrupadas por categor@asC 6lgunas ,a han sido e*plicadas en cap@tulos
precedentes, por lo que no se volver.n a tratar aqu@C >o se recogen en este
cap@tulo todas las $unciones, sino s"lo algunas m.s comKnmente usadasC ;n
conocimiento pormenori1ado de todas ellas se encuentra en el +i&rar, 'e$erence
de -ur&o #C
)unciones de E!"
Ya se han estudiado las siguientes $unciones en el #ap@tulo 4:
fprintf getc& getc&e gets printf putc&ar
puts scanf
, en el #ap@tulo 11:
fclose feof ferror fgetc fgets fopen
fprintf fputc fputs fread fscanf fsee'
f%rite getc get% perror putc put%
re%ind
6 continuaci"n se e*plican otras $unciones de E34:
cgets
:rototipo2 char Rcgets Dchar RcadEO
Include2 conioCh
:ropsito2 Esta $unci"n lee una cadena de caracteres del teclado,
almacenando dicha cadena D, su longitudE en la posici"n
apuntada por cadC
cgets lee caracteres hasta que se teclea o hasta un nKmero
m.*imo permitido de caracteresC El se reempla1a por un
terminador nulo PN2PC
6ntes de llamar a cgets ha, que guardar en cad=+> la longitud
m.*ima permitida para la cadena cadC <espu9s de aca&ar,
c*cv
cgets almacena en cad=1> el nKmero de caracteres tecleadosC
+a cadena tecleada se almacena a partir de cad=2>C -odo esto
implica que para cad de&en reservarse 2 &,tes m.s que el
nKmero m.*imo de caracteresC
;e4uel4e2 ;n puntero a cad=2>C
:ortabilidad2 4"lo !B/A%#s , compati&lesC
remo4e
:rototipo2 int remove Dconst char RficheroEO
Include2 stdioCh
:ropsito2 Borra el $ichero especi$icado mediante ficheroC El $ichero
de&e estar cerradoC
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 , la
varia&le glo&al errno asume alguno de los valores siguientes:
E>)E>- >o e*iste el $ichero
E6##E4 %ermiso denegado
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
rename
:rototipo2 int rename Dconst char Rvie?ofich, const char RnuevofichEO
Include2 stdioCh
:ropsito2 #am&ia el nom&re del $ichero vie?ofich a nuevofichC 6m&os
de&en estar almacenados en la misma unidadC 4i el directorio
de am&os no coincide, rename mueve el $ichero de un
directorio a otroC >o se permiten comodinesC
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 , la
varia&le glo&al errno asume uno de los valores siguientes:
E>)E>- >o e*iste el $ichero
E6##E4 %ermiso denegado
E>)-46/ <ispositivo no coincide
:ortabilidad2 Es compati&le con 6>4!C#
c*cvi
sprintf
:rototipo2 int sprint$ Dchar Rcad, const char Rformat _, argumento, CCC`EO
Include2 stdioCh
:ropsito2 Esta $unci"n es id9ntica a printf pero en lugar de reali1ar la
salida a pantalla, la reali1a so&re la cadena cadC
;e4uel4e2 El nKmero de caracteres almacenados en cad Dsin contar el
terminador nuloEC 4i ocurre un error, devuelve E)FC
:ortabilidad2 Esta disponi&le para ;>!B , est. de$inida en 6>4! #C Es
compati&le con ?j'C
sscanf
:rototipo2 int sscan$ Dconst char Rcad, const char Rformat _,direcc, CCC`EO
Include2 stdioCh
:ropsito2 Funciona igual que scanf pero no lee los datos del teclado
sino de la cadena cadC
;e4uel4e2 El nKmero de campos le@dos, convertidos , almacenados en
sus varia&lesC 4i se intenta leer un $in de cadena, devuelve
E)FC
:ortabilidad2 Esta disponi&le para ;>!B , est. de$inida en 6>4! #C Es
compati&le con ?j'C
tmpfile
:rototipo2 F!+E Rtmp$ile DvoidEO
Include2 stdioCh
:ropsito2 6&re un $ichero temporal en modo %QbC El $ichero se &orra
cuando se cierra o aca&a el programaC
;e4uel4e2 4i no ha, error devuelve un puntero al canal asociado al
$icheroC En caso contrario devuelve un puntero nuloC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
tmpnam
:rototipo2 char Rtmpnam Dchar RnombreEO
Include2 stdioCh
:ropsito2 =enera un nom&re no e*istente para un $ichero temporal , lo
almacena en nombreC Es responsa&ilidad del programador
a&rir, cerrar o &orrar el $icheroC
;e4uel4e2 4i nombre es la cadena nula, devuelve un puntero a una
varia&le est.tica internaC En caso contrario devuelve un
puntero a nombreC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
)unciones de cadenas de caracteres
c*cvii
Funciones estudiadas en el #ap@tulo 5:
strcat strc&r strcmp strcp- strlen strl%r
strre4 strset strupr
)tras $unciones se e*plican a continuaci"nC
strerror
:rototipo2 char Rstrerror Dint nerrorEO
Include2 stdioCh, stringCh
:ropsito2 <evuelve un puntero a una cadena que almacena un mensaje
de error asociado a nerrorC
;e4uel4e2 ;n puntero a una cadena con un mensaje de errorC +a cadena
se almacena en un &u$$er est.tico que se so&reescri&e en cada
llamada a la $unci"nC
:ortabilidad2 Es compati&le con 6>4! #C
stricmp
:rototipo2 int stricmp Dconst char Rcad1, const char Rcad2EO
Include2 stringCh
:ropsito2 Es una $unci"n id9ntica a strcmp salvo en que no di$erencia
ma,Ksculas , minKsculasC
;e4uel4e2 V 2 si cad1 V cad2
M 2 si cad1 M cad2
W 2 si cad1 W cad2
:ortabilidad2 4"lo <)4C
strncat
:rototipo2 char Rstrncat Dchar Rdest, const char Rorig, si1eXt ma&EO
Include2 stringCh
:ropsito2 #opia un m.*imo de ma& caracteres de la cadena orig en la
cadena dest , aFade el terminador nuloC
;e4uel4e2 ;n puntero a destC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
c*cviii
strncmp
:rototipo2 int strncmp Dconst char Rcad1, const char Rcad2, si1eXt ma&EO
Include2 stringCh
:ropsito2 Es id9ntica a strcmp pero no compara cadenas completas,
sino s"lo los primeros ma& caracteresC
;e4uel4e2 V 2 si cad1 V cad2
M 2 si cad1 M cad2
W 2 si cad1 W cad2
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
strncp-
:rototipo2 char strncp, Dconst char Rdest, const char Rorig, si1eXt ma&EO
Include2 stringCh
:ropsito2 #opia hasta ma& caracteres de orig en destC +a cadena dest
podr@a no tener un terminador nulo si el tamaFo de orig es
ma& o ma,orC
;e4uel4e2 ;n puntero a destC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
strnset
:rototipo2 char Rstrnset Dchar Rcad, int carac, si1eXt nEO
Include2 stringCh
:ropsito2 %one el car.cter carac en los primeros n &,tes de cadC +a
operaci"n $inali1a cuando se han escrito n caracteres o se
encuentra el terminador nuloC
;e4uel4e2 ;n puntero a cadC
:ortabilidad2 4"lo <)4C
strrc&r
:rototipo2 char Rstrrchr Dconst char Rcad, int caracEO
Include2 stringCh
:ropsito2 Busca en direcci"n inversa el car.cter carac en la cadena cad,
considerando el terminador nulo como parte de cadC
;e4uel4e2 4i encuentra carac devuelve un puntero a esa direcci"nC En
caso contrario devuelve un puntero nuloC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
c*ci*
strstr
:rototipo2 char Rstrstr Dconst char Rcad, const char RsubcadEO
Include2 stringCh
:ropsito2 Busca la primera aparici"n de subcad en cadC
;e4uel4e2 4i subcad est. en cad devuelve un puntero al lugar de cad en
que comien1a subcadC En caso contrario devuelve un puntero
nuloC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
)unciones de memoria
memc&r
:rototipo2 void Rmemchr Dconst void Rbloue, int carac, si1eXt nEO
Include2 stringCh, memCh
:ropsito2 Busca la primera aparici"n del car.cter carac en los primeros
n &,tes del &loque de memoria apuntado por bloueC
;e4uel4e2 ;n puntero a la primera aparici"n de carac en bloueC 4i no
lo encuentra devuelve un puntero nuloC
:ortabilidad2 Est. disponi&le para ;>!B 4,stem 0 , es compati&le con
6>4! #C
memcmp
:rototipo2 int memcmp Dconst void Rbloue1, const void Rbloue2, si1eXt nEO
Include2 stringCh, memCh
:ropsito2 #ompara dos &loques de memoria de n &,tes de longitudC
;e4uel4e2 V 2 si bloue1 V bloue2
M 2 si bloue1 M bloue2
W 2 si bloue1 W bloue2
:ortabilidad2 Est. disponi&le para ;>!B 4,stem 0 , es compati&le con
6>4! #C
memcp-
:rototipo2 void Rmemcp, Dvoid Rdest, const void Rorig, si1eXt nEO
Include2 stringCh, memCh
:ropsito2 #opia un &loque de n &,tes desde orig hasta destC Es misi"n
del programador controlar que orig , dest no se superponenC
;e4uel4e2 ;n puntero a destC
:ortabilidad2 Est. disponi&le para ;>!B 4,stem 0 , es compati&le con
6>4! #C
cc
memicmp
:rototipo2 int memicp Dconst void Rbloue1, const void Rbloue2, si1eXt nEO
Include2 stringCh, memCh
:ropsito2 #ompara los primeros n &,tes de bloue1 , bloue2, sin
di$erenciar ma,Ksculas , minKsculasC
;e4uel4e2 V 2 si bloue1 V bloue2
M 2 si bloue1 M bloue2
W 2 si bloue1 W bloue2
:ortabilidad2 Est. disponi&le para ;>!B 4,stem 0C
memmo4e
:rototipo2 void Rmemmove Dvoid Rdest, const void Rorig, si1eXt nEO
Include2 stringCh, memCh
:ropsito2 #opia un &loque de n &,tes desde orig hasta destC !ncluso
cuando los &loques se superponen, los &,tes en las posiciones
superpuestas se copian correctamenteC
;e4uel4e2 ;n puntero a destC
:ortabilidad2 Est. disponi&le para ;>!B 4,stem 0 , es compati&le con
6>4! #C
memset
:rototipo2 void Rmemset Dvoid Rbloue, int carac, si1eXt nEO
Include2 stringCh, memCh
:ropsito2 %one en los n primeros &,tes de bloue el car.cter caracC
;e4uel4e2 ;n puntero a bloueC
:ortabilidad2 Est. disponi&le para ;>!B 4,stem 0 , es compati&le con
6>4! #C
mo4edata
:rototipo2 void movedata Dunsigned seg1, unsigned off1, unsigned seg2, unsigned off2, si1eXt nEO
Include2 memCh, stringCh
:ropsito2 #opia n &,tes desde la direcci"n seg11off1 hasta la direcci"n
seg21off2C
;e4uel4e2
:ortabilidad2 4"lo <)4C
mo4mem
:rototipo2 void movmem Dvoid Rorig, void Rdest, unsigned nEO
Include2 memCh
cci
:ropsito2 /ueve un &loque de n &,tes desde orig hasta destC !ncluso si
orig , dest se superponen los &,tes se mueven correctamenteC
;e4uel4e2
:ortabilidad2 4"lo -ur&o #LLC
)unciones de caracteres
Funciones estudiadas en el #ap@tulo 5:
isalnum isalp&a isdigit islo%er isupper tolo%er toupper
)tras $unciones
isascii
:rototipo2 int isascii Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un car.cter perteneciente al
conjunto de caracteres 64#!! no e*tendido, de 2 a 125C
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrarioC
:ortabilidad2 Est. disponi&le para ;>!BC
iscntrl
:rototipo2 int iscntrl Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un car.cter de control, es decir,
de c"digo 64#!! de 2 a 31 " 125C
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrarioC
:ortabilidad2 Est. disponi&le para ;>!B , es compati&le con 6>4! #C
isgrap&
:rototipo2 int isgraph Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un car.cter imprimi&le distinto
del espacio Dc"digo 64#!! de 33 a 126EC
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrarioC
:ortabilidad2 Est. disponi&le para ;>!B , es compati&le con 6>4! #C
isprint
ccii
:rototipo2 int isprint Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un car.cter imprimi&le
inclu,endo el espacio Dc"digo 64#!! de 32 a 126EC
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrarioC
:ortabilidad2 Est. disponi&le para ;>!B , es compati&le con 6>4! #C
ispunct
:rototipo2 int ispunct Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un car.cter de puntuaci"n, es
decir, un car.cter de control inclu,endo el espacioC
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrario
:ortabilidad2 Est. disponi&le para ;>!B , es compati&le con 6>4! #C
isspace
:rototipo2 int isspace Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un espacio, retorno de carro,
ta&ulador vertical, ta&ulador hori1ontal, salto de p.gina o
salto de l@neaC
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrarioC
:ortabilidad2 Est. disponi&le para ;>!B , es compati&le con 6>4! #C Es
compati&le con ?j'C
is(digit
:rototipo2 int is*digit Dint caracEO
Include2 ct,peCh
:ropsito2 !n$orma acerca de si carac es un d@gito he*adecimal D2A, aA$,
6AFEC
;e4uel4e2 1 en caso a$irmativo, 2 en caso contrarioC
:ortabilidad2 Est. disponi&le para ;>!B , es compati&le con 6>4! #C
)unciones matemticas
6parte de las $unciones que se muestran en este apartado, -ur&o #
proporciona un grupo importante de $unciones trigonom9tricas, logar@tmicas,
e*ponenciales, hiper&"licas , complejasC
e(p
:rototipo2 dou&le e*p Ddou&le &EO
cciii
Include2 mathCh
:ropsito2 #alcula e
&
C
;e4uel4e2 El valor calculadoC 4i este valor es demasiado grande para
representarse como double devuelve Q;=EX06+C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
fabs
:rototipo2 dou&le $a&s Ddou&le &EO
Include2 mathCh
:ropsito2 #alcula el valor a&soluto de &C
;e4uel4e2 El valor a&soluto de &C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
floor
:rototipo2 dou&le $loor Ddou&le &EO
Include2 mathCh
:ropsito2 'edondea & hacia a&ajoC
;e4uel4e2 El ma,or entero que no es ma,or que &C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4!C#
modf
:rototipo2 dou&le mod$ Ddou&le &, dou&le RenteraEO
Include2 mathCh
:ropsito2 <escompone & en parte entera Dque se almacena en enteraE ,
parte $raccionariaC
;e4uel4e2 +a parte $raccionariaC
:ortabilidad2 4"lo <)4C
po%
:rototipo2 dou&le poH Ddou&le &, dou&le )EO
Include2 mathCh
:ropsito2 #alcula &
)
C
;e4uel4e2 4i tiene 9*ito, el valor calculadoC 4i ha, des&ordamiento
devuelve Q;=EX06+ , asigna a la varia&le glo&al errno el
valor E'6>=EC 4i & vale 2 e ) es menor o igual a 2 se
produce un error de dominio , asigna a errno el valor
E<)/C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
sKrt
cciv
:rototipo2 dou&le sqrt Ddou&le &EO
Include2 mathCh
:ropsito2 #alcula la ra@1 cuadrada positiva de &C
;e4uel4e2 4i tiene 9*ito devuelve el valor calculadoC 4i & es negativo se
produce un error de dominio , se asigna a la varia&le glo&al
errno el valor E<)/C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
)unciones de sistema
absread
:rototipo2 int a&sread Dint unidad, int nsec, int desde, void RbufferEO
Include2 dosCh
:ropsito2 +ee nsec sectores de la unidad especi$icada con unidad D6M2,
BM1, CCCE a partir del sector desde , los almacena en bufferC
;tili1a para la lectura la interrupci"n <)4 2*2(C El nKmero
de sectores a leer est. limitado a 64 ?&C
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 ,
asigna a la varia&le glo&al errno el valor devuelto por el
sistema en el registro 6BC
:ortabilidad2 4"lo <)4C
abs%rite
:rototipo2 int a&sHrite Dint unidad, int nsec, int desde, void RbufferEO
Include2 dosCh
:ropsito2 Escri&e en la unidad especi$icada con unidad D6M2, BM1, CCCE
nsec sectores a partir del sector desdeC +a in$ormaci"n de&e
estar almacenada en bufferC ;tili1a la interrupci"n <)4 2*26C
El nKmero de sectores a escri&ir est. limitado a 64 ?&C
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 ,
asigna a la varia&le glo&al errno el valor devuelto por el
sistema en el registro 6BC
:ortabilidad2 4"lo <)4C
bioseKuip
:rototipo2 int &iosequip DvoidEO
Include2 &iosCh
:ropsito2 ;sa la interrupci"n 2*11 para devolver un entero con
in$ormaci"n so&re el equipamiento del sistemaC
ccv
;e4uel4e2 ;na pala&ra cu,os &its de&en interpretarse segKn se e*plica a
continuaci"n:
14A1(: >Kmero de impresoras paralelo instaladasC
13: !mpresora serieC
12: 6daptador de juegosC
A11: >Kmero de puertos #)/C
8: #hip de acceso directo a memoria D</6E
instaladoC 4i vale 2 indica que s@C
6A5: >Kmero de unidades de disquette, si el &itA2 es 1C
22 M 1 unidadC
21 M 2 unidadesC
12 M 3 unidadesC
11 M 4 unidadesC
4A(: /odo de v@deo inicial:
22 M >o usadoC
21 M 42*2( B> con adaptador colorC
12 M 82*2( B> con adaptador colorC
11 M 82*2( B> con adaptador monocromoC
2A3: '6/ en placa &ase:
22 M 16 ?&C
21 M 32 ?&C
12 M 48 ?&C
11 M 64 ?&C
1: #oprocesador matem.ticoC
2: 6rranque desde disquetteC
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
bios'e-
:rototipo2 int &iosGe, Dint o"EO
Include2 &iosCh
:ropsito2 'eali1a varias operaciones so&re el teclado usando la
interrupci"n 2*16C +a operaci"n a reali1ar depende del valor
de o"C
;e4uel4e2 El valor devuelto depende de o":
2: Espera a que se pulse una tecla , devuelve su valor en
2 &,tes: el &,te &ajo contiene el c"gigo 64#!!C 4i este
es 2 Dtecla especialE, en el &,te alto devuelve el c"digo
e*tendidoC
1: 'evisa si se pulsa una teclaC <evuelve 2 si no se ha
pulsado ninguna, , di$erente de 2 en caso contrarioC
2: <evuelve un &,te con el estado de alguna de las teclas,
representando cada &it el estado de una tecla di$erente:
2: /6Yk4#;+64 <#Q6 pulsadaC
1: /6Yk4#;+64 !b8<6 pulsadaC
2: -ecla #)>-')+ pulsadaC
3: -ecla 6+- pulsadaC
4: -ecla B+)8 <E4%+ activadaC
(: -ecla B+)8 >;/ activadaC
6: -ecla B+)8 /6Yk4 activadaC
ccvi
5: -ecla !>4E'- activadaC
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
biosmemor-
:rototipo2 int &iosmemor, DvoidEO
Include2 &iosCh
:ropsito2 )&tiene la cantidad de '6/ mediante la interrupci"n 2*12
del B!)4C >o inclu,e memoria de v@deo, e*tendida ni
e*pandidaC
;e4uel4e2 +a cantidad de '6/ en &loques de 1 ?&C
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
biosprint
:rototipo2 int &iosprint Dint o", int b)te, int "uertoEO
Include2 &iosCh
:ropsito2 'eali1a varias operaciones so&re el puerto paralelo de la
impresora usando la interrupci"n 2*15 del B!)4C El valor de
"uerto es 2 para +%-1, 1 para +%-2, etcC +as operaciones
reali1adas dependen del valor de o":
2: Env@a a la impresora el &,te b)teC
1: !niciali1a el puertoC
2: )&tiene el estado de la impresoraC
;e4uel4e2 ;n &,te de estado de la impresoraC #ada &it de&e interpretarse
como sigue:
2: Error de timeAoutC
1A2: 4in usarC
3: Error de E34C
4: !mpresora conctadaC
(: >o ha, papelC
6: 'econocimiento D6#?EC
5: >o ocupadaC
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
biostime
:rototipo2 long &iostime Dint o", long nuevotEO
Include2 &iosCh
:ropsito2 +ee o asigna un valor al reloj del sistemaC Este reloj se
iniciali1a a medianoche , se incrementa a ra1"n de 18C2 ticGs
por segundoC 4i o" vale 2 lee el relojO si vale 1, asigna al
sistema el valor nuevotC
;e4uel4e2 4i o" vale 2 devuelve el valor actual del reloj del sistemaC
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
ccvii
cloc'
:rototipo2 clocGXt clocG DvoidEO
Include2 timeCh
:ropsito2 <etermina el tiempo de procesoC %uede usarse para calcular el
tiempo transcurrido entre dos sucesosC %ara determinar el
tiempo en segundos, el valor devuelto por cloc' de&e
dividirse por la macro #+?X-#?C
;e4uel4e2 El tiempo de proceso desde el comien1o del programaC 4i ha,
error, devuelve A1C
:ortabilidad2 Es compati&le con 6>4! #C
dela-
:rototipo2 void dela, Dunsigned msEO
Include2 dosCh
:ropsito2 <etiene la ejecuci"n del programa durante ms milisegundosC
;e4uel4e2
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
):[/))
:rototipo2 unsigned F%X)FF Dvoid $ar R"EO
Include2 dosCh
:ropsito2 Es una macro que o&tiene el valor de despla1amiento del
puntero "C
;e4uel4e2 El valor del despla1amientoC
:ortabilidad2 4"lo <)4C
):["EM
:rototipo2 unsigned F%X4E= Dvoid $ar R"EO
Include2 dosCh
:ropsito2 Es una macro que o&tiene el valor de segmento del puntero "C
;e4uel4e2 El valor de segmentoC
:ortabilidad2 4"lo <)4C
getdate
:rototipo2 void getdate Dstruct date RfechaEO
Include2 dosCh
:ropsito2 )&tiene la $echa del sistema mediante una estructura date
apuntada por fechaC +a estructura date esta de$inida como
sigue:
struct date ?
ccviii
int da[-earA 33aFo
int da[da-A 33d@a
int da[monA 33mes
@A
;e4uel4e2
:ortabilidad2 4"lo <)4C
gettime
:rototipo2 void gettime Dstruct time RhoraEO
Include2 dosCh
:ropsito2 )&tiene la hora del sistema mediante una estructura time
apuntada por horaC +a estructura time est. de$inida como
sigue:
struct time ?
unsigned c&ar ti[minA 33minutos
unsigned c&ar ti[&ourA 33horas
unsigned c&ar ti[&undA 33cent9simas de segC
unsigned c&ar ti[secA 33segundos
@A
;e4uel4e2
:ortabilidad2 4"lo <)4C
int*$
:rototipo2 int int86 Dint nint, union 'E=4 Rregin, union 'E=4 RregoutEO
Include2 dosCh
:ropsito2 Ejecuta la interrupci"n especi$icada por nintC 6ntes de llamar
a la $unci"n de&en ponerse en la estructura apuntada por
regin los valores adecuados en los registros del procesadorC
+a estructura 'E=4 est. de$inida como sigue:
struct b/L;LEM" ?
unsigned int a(8 b(8 c(8 d(8 si8 di8 cflagA
@A
struct 3`TELEM" ?
unsigned c&ar al8 a&8 bl8 b&8 cl8 c&8 dl8 d&A
@A
union LEM" ?
struct b/L;LEM" (A
struct 3`TELEM" &A
@A
<espu9s de ejecutada la $unci"n, la estructura apuntada por
regout contiene los valores de los registros del procesador
devueltosC
;e4uel4e2 El valor dejado en 6B por la rutina de interrupci"nC 4i el
indicador de acarreo Drepresentado por (.cflagE est. activado
indicando un error, la $unci"n asigna a la varia&le glo&al
[doserrno el c"digo de errorC
cci*
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
int*$(
:rototipo2 int int86* Dint nint, union 'E=4 Rregin, union 'E=4 Rregout, struct 4'E=4 RregsegEO
Include2 dosCh
:ropsito2 Es id9ntica a la anterior, pero utili1a la estructura "LEM" que
est. de$inida como sigue:
struct "LEM" ?
unsigned int esA
unsigned int csA
unsigned int ssA
unsigned int dsA
@A
Esta $unci"n copia antes de ejecutar la interrupci"n, los
valores de ds , es en los correspondientes registrosC Esto
permite a los programas usar punteros lejanos o el modelo
grande de memoria para especi$icar qu9 segmento de memoria
de&e usarse en la interrupci"nC
;e4uel4e2 El valor dejado en 6B por la rutina de interrupci"nC 4i el
indicador de acarreo Drepresentado por (.cflagE est. activado
indicando un error, la $unci"n asigna a la varia&le glo&al
[doserrno el c"digo de errorC
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
intdos
:rototipo2 int intdos Dunion 'E=4 Rregin, union 'E=4 RregoutEO
Include2 dosCh
:ropsito2 Es id9ntica a int*$ pero s"lo para la interrupci"n 2*21C
;e4uel4e2 El valor dejado en 6B por la rutina de interrupci"nC 4i ha,
error se activa el indicador de acarreo (.cflag, , se asigna a la
varia&le glo&al [doserrno el c"digo de errorC +a estructura
LEM" se muestra en la p.gina 222 Dint*$EC
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
intdos(
:rototipo2 int intdos* Dunion 'E=4 Rregin, union 'E=4 Rregout, struct 4'E=4 RregsegEO
Include2 dosCh
:ropsito2 Es id9ntica a int*$( pero s"lo para la interrupci"n 2*21C
;e4uel4e2 El valor dejado en 6B por la interrupci"nC 4i ha, error se
activa el indicador de acarreo (.cflag, , se asigna a la varia&le
glo&al [doserrno el c"digo de errorC +as estructuras LEM" ,
"LEM" se muestran en la p.gina 222 Dint*$ e int*$(EC
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
cc*
pee'
:rototipo2 int peeG Dunsigned segmento, unsigned des"lEO
Include2 dosCh
:ropsito2 +ee la pala&ra situada en la direcci"n segmento:des"lC
;e4uel4e2 El valor le@doC
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
pee'b
:rototipo2 char peeG& Dunsigned segmento, unsigned des"lEO
Include2 dosCh
:ropsito2 +ee el &,te situado en la direcci"n segmento:des"lC
;e4uel4e2 El valor le@doC
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
po'e
:rototipo2 void poGe Dunsigned segmento, unsigned des"l, int valorEO
Include2 dosCh
:ropsito2 6lmacena el entero valor en la direcci"n segmento:des"lC
;e4uel4e2
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
po'eb
:rototipo2 void poGe& Dunsigned segmento, unsigned des"l, char valorEO
Include2 dosCh
:ropsito2 6lmacena el &,te valor en la direcci"n segmento:des"lC
;e4uel4e2
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
segread
:rototipo2 void segread Dstruct 4'E=4 RregsegEO
Include2 dosCh
:ropsito2 )&tiene los valores de los registros de segmentoC +a
estructura "LEM" est. de$inida en la p.gina 221 Dint*$(EC
;e4uel4e2
:ortabilidad2 4"lo para la $amilia de procesadores 8286C
setdate
:rototipo2 void setdate Dstruct date RfechaEO
Include2 dosCh
cc*i
:ropsito2 Esta&lece la $echa del sistemaC +a estructura date est.
de$inida en la p.gina 221 DgetdateEC
;e4uel4e2
:ortabilidad2 4"lo <)4C
settime
:rototipo2 void settime Dstruct time RhoraEO
Include2 dosCh
:ropsito2 Esta&lece la hora del sistemaC +a estructura time est. de$inida
en la p.gina 221 DgettimeEC
;e4uel4e2
:ortabilidad2 4"lo <)4C
sleep
:rototipo2 void sleep Dunsigned segEO
Include2 dosCh
:ropsito2 4uspende la ejecuci"n del programa durante seg segundosC
;e4uel4e2
:ortabilidad2 Esta disponi&le para ;>!BC
)unciones de asignacin dinmica de memoria
Ya se han estudiado en el #ap@tulo las $unciones:
free malloc
)tras $unciones se e*plican a continuaci"nC
calloc
:rototipo2 void Rcalloc Dsi1eXt n, si1eXt tamEO
Include2 stdli&Ch, allocCh
:ropsito2 6signa un &loque de n elementos de tam &,tes del mot"n,
iniciali1.ndolo a 2C
;e4uel4e2 4i tiene 9*ito, un puntero al &loque asignadoC En caso
contrario devuelve un puntero nuloC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C Es
compati&le con ?j'C
coreleft
cc*ii
:rototipo2 unsigned corele$t DvoidEO
14
unsined long corele$t DvoidEO
1(
Include2 allocCh
:ropsito2 )&tiene una medida de la cantidad de memoria li&re en el
mont"nC
;e4uel4e2 El nKmero de &,tes li&res del mont"nC
:ortabilidad2 4"lo <)4C
realloc
:rototipo2 void Rrealloc Dvoid R", si1eXt tamEO
Include2 stdli&Ch, allocCh
:ropsito2 #am&ia el tamaFo de memoria asignada apuntada por " al
nuevo tamaFo dado por tamC
;e4uel4e2 ;n puntero al &loque asignadoC Este puede ser di$erente del
anteriorC 4i no tiene 9*ito, devuelve un puntero nuloC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inido en 6>4! #C
)unciones de directorio
c&dir
:rototipo2 int chdir Dconst char RnuevodirEO
Include2 dirCh
:ropsito2 Esta&lece como directorio actual nuevodirC
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 ,
asigna a la varia&le glo&al errno el valor E>)E>-C
:ortabilidad2 Est. disponi&le para ;>!BC
findfirst
:rototipo2 int $ind$irst Dconst char R"ath, struct $$&lG Rbloue, int atribEO
Include2 dirCh, dosCh
:ropsito2 Busca el primer nom&re de archivo que coincida con "athC El
nom&re de archivo puede contener comodines R , :C 4i el
archivo se encuentra, llena la in$ormaci"n de la estructura
ffbl' apuntada por bloueC Esta estructura est. de$inida como
sigue:
struct ffbl' ?
c&ar ff[reser4edT21UA 33'eservado por <)4
c&ar ff[attribA 336tri&utos de archivo
14
Para los modelos de memoria diminuto (tiny), pequeo (small) y mediano (medium),
explicados en el Captulo 12.
15
Para los modelos de memoria compacto (compact), grande (large) y enorme (huge),
explicados en el Captulo 12.
cc*iii
int ff[ftimeA 33Qora D#ampo de &itsE
int ff[dateA 33Fecha D#ampo de &itsE
long ff[fsi5eA 33-amaFo
c&ar ff[nameT13UA 33>om&re
@A
En el par.metro atrib se selecciona el tipo de archivo que se
&uscar.C %uede tener alguno de los siguientes valores:
F6X'<)>+Y 6rchivo de s"loAlectura
F6XQ!<<E> 6rchivo oculto
F6X4Y4-E/ 6rchivo de sistema
F6X+6BE+ Etiqueta de volumen
F6X<!'E# <irectorio
F6X6'#Q 6rchivo
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 ,
asigna a la varia&le glo&al errno alguno de los siguientes
valores:
E>)E>- 6rchivo no encontrado
E>/F!+E >o m.s $icheros
:ortabilidad2 4"lo <)4
findne(t
:rototipo2 int $indne*t Dstruct $$&lG RbloueEO
Include2 dirCh
:ropsito2 #ontinKa la &Ksqueda iniciada por findfirstC
;e4uel4e2 +os mismos valores que findfirstC
:ortabilidad2 4"lo <)4C
getcurdir
:rototipo2 int getcurdir Dint unidad, char RdirectorioEO
Include2 dirCh
:ropsito2 %one en la cadena directorio el directorio actual de tra&ajo
para el disco unidad D2: de$ecto, 1: 6, 2: B, CCCEC+a cadena
directorio de&e tener como m.*imo /6B<!' caracteresC +a
macro /6B<!' est. de$inida en dir.&C
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario, A1C
:ortabilidad2 4"lo <)4C
getc%d
:rototipo2 char RgetcHd Dchar Rbuffer, int longbufEO
Include2 dirCh
:ropsito2 #opia el directorio actual de tra&ajo , lo sitKa en la cadena
bufferC 4i el nom&re del directorio tiene m.s de longbuf
caracteres, se produce un errorC 4i buffer es nulo, la $unci"n
cc*iv
asigna memoria para buffer con una llamada a mallocC En ese
caso, puede li&erarse la memoria asignada mediante freeC
;e4uel4e2 ;n puntero a buffer si tiene 9*itoC En caso contrario devuelve
un puntero nuloC 4i ocurre un error, asigna a la varia&le glo&al
errno uno de los valores siguientes:
E>)<E0 >o e*iste el dispositivo
E>)/E/ >o ha, su$iciente memoria
E'6>=E 'esultado $uera de rango
:ortabilidad2 4"lo <)4
getdis'
:rototipo2 int getdisG DvoidEO
Include2 dirCh
:ropsito2 )&tiene el nKmero de la unidad actualC
;e4uel4e2 2 para 6:, 1 para B:, etcC
:ortabilidad2 4"lo <)4C
m'dir
:rototipo2 int mGdir Dconst char RdirectorioEO
Include2 dirCh
:ropsito2 #rea el directorio indicado en la cadena directorioC
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1, ,
asigna a la varia&le glo&al errno alguno de los valores
siguientes:
E6##E4 6cceso denegado
E>)E>- Encaminamiento no v.lido
:ortabilidad2
m'temp
:rototipo2 char RmGtemp Dchar RnombreEO
Include2 dirCh
:ropsito2 #rea un nom&re de archivo Knico , lo pone en nombreC +a
cadena nombre de&e estar iniciali1ada como IBBBBBBIC
Esta $unci"n no a&re el $icheroC
;e4uel4e2 4i tiene 9*ito, un puntero a nom&reC En caso contrario, un
puntero nuloC
:ortabilidad2 Est. disponi&le para sistemas ;>!BC
rmdir
:rototipo2 int rmdir Dconst char RdirectorioEO
Include2 dirCh
cc*v
:ropsito2 Borra el directorio cu,o nom&re se indica en directorioC %ara
poder &orrar el directorio de&e cumplirse que:
Est. vac@o
>o es el directorio de tra&ajo
>o es el directorio ra@1
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1 ,
asigna a la varia&le glo&al errno alguno de los valores
siguientes:
E6##E4 6cceso denegado
E>)E>- Encaminamiento no v.lido
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
searc&pat&
:rototipo2 char Rsearchpath Dconst char RnombreEO
Include2 dirCh
:ropsito2 Busca el archivo nombre usando la varia&le de entorno
%6-QC
;e4uel4e2 4i tiene 9*ito devuelve un puntero al encaminamiento
completoC En caso contrario, devuelve un puntero nuloC
:ortabilidad2 4"lo <)4C
setdis'
:rototipo2 int setdisG Dint unidadEO
Include2 dirCh
:ropsito2 Esta&lece como unidad activa la especi$icada mediante unidad
D2M6, 1MB, CCCEC
;e4uel4e2 El nKmero de unidades disponi&leC
:ortabilidad2 4"lo <)4C
)unciones de control de procesos
abort
:rototipo2 void a&ort DvoidEO
Include2 stdli&Ch, processCh
:ropsito2 /uestra el mensaje $bnormal "rogram termination en stderr
, $inali1a el programa, enviando al proceso padre un c"digo
de retorno 3C >o cierra ningKn archivoC
;e4uel4e2
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
cc*vi
Funciones e(ec
:rototipos2 int e*ecl Dchar Rnom, char Rarg+, CCC, char RargN, >;++EO
int e*ecle Dchar Rnom, char Rarg+, CCC, char RargN, >;++, char Rentorno= >EO
int e*eclp Dchar Rnom, char Rarg+, CCC, char RargN, >;++EO
int e*eclpe Dchar Rnom, char Rarg+, CCC, char RargN, >;++, char Rentorno= >EO
int e*ecv Dchar Rnom, char Rarg= >EO
int e*ecve Dchar Rnom, char Rarg= >, char Rentorno= >EO
int e*ecvp Dchar Rnom, char Rarg= >EO
int e*ecvpe Dchar Rnom, char Rarg= >, char Rentorno= >EO
Include2 processCh
:ropsito2 +as $unciones e(ec ejecutan otros programas, llamados
"rocesos hi?oC <espu9s de la llamada el proceso hijo sustitu,e
al "roceso "adre en memoria, siempre que ha,a su$icienteC El
nom&re del proceso hijo se especi$ica con el par.metro nomC
6l proceso hijo se le pasan los argumentos individualmente
mediante arg+, CCC, argN, o &ien en el vector arg= >C -am&i9n
se puede pasar una matri1 de cadenas de entorno mediante el
par.metro entorno= >C
El proceso hijo es &uscado siguiendo las siguientes normas:
4i nom no tiene incluida una e*tensi"n, se &uscar. un
archivo con ese nom&reC 4i no se encuentra, se &uscar.
el mismo archivo con e*tensi"n C#)/C 4i tampoco se
encuentra, se &uscar. un archivo con e*tensi"n CEBEC
4i nom lleva incluida una e*tensi"n, s"lo se &uscar. ese
archivoC
+a manera en que se ejecutan estas $unciones dependen de
qu9 versi"n de $unci"n e(ec se utiliceC +as versiones se
di$erencian por los su$ijos p, l, 4 , e que se pueden aFadir al
nom&reC El signi$icado de estos su$ijos es el siguiente:
p 4i la $unci"n tiene este su$ijo, el proceso hijo se &usca
usando la varia&le de entorno %6-Q del <)4C En caso
contrario la &Ksqueda se reali1a s"lo en el directorio de
tra&ajoC
l +os argumentos se pasan individualmente mediante los
par.metros arg+, CCC, argNC El Kltimo argumento de&e
ser un <D66 Dde$inido en stdioChEC
4 +os argumentos se pasar.n en una matri1 arg= >C
e 4e pasar. una o varias cadenas de entorno mediante la
matri1 entorno= >C El Kltimo elemento de la matri1 de&e
ser un <D66C
+as $unciones e(ec de&en pasar al proceso hijo al menos un
argumentoC Este argumento es, por convenio, nom, aunque
cualquier otro no produce errorC
#uando se usa el su$ijo l, arg+ apunta a nom, , arg1, CCC, argN
apuntan a la lista de argumentos que se pasanC
#uando se usa el su$ijo e, +as cadenas de la matri1 entorno= >
de&en tener la $orma
variable de entorno @ valor
+a suma de longitudes de los argumentos que se pasan no
de&e superar los 128 &,tes Dsin contar los nulosEC
+as $unciones e(ec no cierran $icherosC
cc*vii
;e4uel4e2 En caso de error devuelve A1 , asigna a la varia&le glo&al
errno alguno de los valores siguientes:
E2B!= <emasiados argumentos
E6##E4 6cceso denegado al proceso hijo
E/F!+E <emasiados $icheros a&iertos
E>)E>- 6rchivo no encontrado
E>)EBE# Error de $ormato en la $unci"n e(ec
E>)/E/ /emoria insu$iciente
:ortabilidad2 4"lo <)4C
e(it
:rototipo2 void e*it Dint stEO
Include2 processCh, stdli&Ch
:ropsito2 %rovoca la terminaci"n del programaC #ierra todos los
$icheros a&iertos , descarga todos los &u$$ers de salidaC Env@a
al proceso padre un c"digo de retorno stC >ormalmente se
env@a un valor 2 para la terminaci"n normal, , un valor
di$erente de 2 si se ha producido un errorC
;e4uel4e2
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
Funciones spa%n
:rototipos2 int spaHnl Dint modo, char Rnom, char Rarg+, CCC, char RargN, >;++EO
int spaHnle Dint modo, char Rnom, char Rarg+, CCC, char RargN, >;++, char Rentorno= >EO
int spaHnlp Dint modo, char Rnom, char Rarg+, CCC, char RargN, >;++EO
int spaHnlpe Dint modo, char Rnom, char Rarg+, CCC, char RargN, >;++, char Rentorno= >EO
int spaHnv Dint modo, char Rnom, char Rarg= >EO
int spaHnve Dint modo, char Rnom, char Rarg= >, char Rentorno= >EO
int spaHnvp Dint modo, char Rnom, char Rarg= >EO
int spaHnvpe Dint modo, char Rnom, char Rarg= >, char Rentorno= >EO
Include2 processCh
:ropsito2 Estas $unciones son id9nticas a las $unciones e(ec, salvo en
tres detalles:
En primer lugar, en las $unciones spa%n el proceso hijo no
sustitu,e necesariamente al proceso padre en memoriaC
En segundo lugar, se aFade un nuevo par.metro, modo, que
puede tener los siguientes valores:
%X[6!- <eja suspendida la ejecuci"n del proceso
padre hasta que termine el proceso hijoC
%X>)[6!- Ejecuta concurrentemente el padre , el
hijoC >o est. disponi&le en -ur&o #C
%X)0E'+6Y El proceso hijo sustitu,e al proceso
padre en memoriaC
+a tercera di$erencia est. en c"mo el proceso hijo es &uscadoC
4e siguen las siguientes normas:
4i nom no tiene incluida una e*tensi"n ni un punto, se
&uscar. un archivo con ese nom&reC 4i no se encuentra,
se &uscar. el mismo archivo con e*tensi"n C#)/C 4i
cc*viii
tampoco se encuentra, se &uscar. un archivo con
e*tensi"n CEBEC
4i nom lleva incluida una e*tensi"n, s"lo se &uscar. ese
archivoC
4i nom tiene un punto se &uscar. s"lo un $ichero con
ese nom&re , sin e*tensi"nC
;e4uel4e2 En caso de error devuelve A1 , asigna a la varia&le glo&al
errno alguno de los valores siguientes:
E2B!= <emasiados argumentos
E/F!+E <emasiados $icheros a&iertos
E>)E>- 6rchivo no encontrado
E>)EBE# Error de $ormato en la $unci"n e(ec
E>)/E/ /emoria insu$iciente
:ortabilidad2 4"lo <)4C
)unciones de pantalla de te(to
Ya se han estudiado las siguientes $unciones en el #ap@tulo 4:
clreol clrscr delline goto(- &ig&4ideo insline
lo%4ideo mo4et(t norm4ideo te(tattr te(tbac'ground te(tcolor
te(tmode %&ere( %&ere-
)tras $unciones de pantalla de te*to se muestran a continuaci"n:
cprintf
:rototipo2 int cprint$ Dconst char Rformat _, argumento, CCC`EO
Include2 conioCh
:ropsito2 Es pr.cticamente id9ntica a printfC +as di$erencias son:
Escri&e en la ventana activa , no en stdoutC
!mpide que se superen los l@mites de la ventanaC
>o se puede redireccionar la salidaC
'espeta los atri&utos de color actualC
>o convierte la nueva l@nea DFnE en salto de l@nea L
retorno de carroC Es preciso aFadir FrC
;e4uel4e2 El nKmero de caracteres escritosC
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
cputs
:rototipo2 int cputs Dconst char RcadenaEO
Include2 conioCh
:ropsito2 Es pr.cticamente id9ntica a putsC +as di$erencias entre puts ,
cputs son las mismas que entre printf , cprintfC
cc*i*
;e4uel4e2 4i tiene 9*ito devuelve el Kltimo car.cter escritoC En caso
contrario, devuelve E)FC
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
cscanf
:rototipo2 int cscan$ Dconst char Rformat _, direcc, CCC`EO
Include2 conioCh
:ropsito2 Es id9ntica a scanf salvo que lee la in$ormaci"n de la consola
en lugar de stdinC 'espeta los atri&utos de color actualC >o se
puede redirigirC
;e4uel4e2 El nKmero de argumentos a los que realmente se les ha
asignado valoresC
:ortabilidad2 4"lo <)4C
gette(t
:rototipo2 int gette*t Dint i(, int arriba, int dcha, int aba?o, void RdestEO
Include2 conioCh
:ropsito2 6lmacena en dest un rect.ngulo de la pantalla de te*to
de$inido por las coordenadas i(, arriba, dcha , aba?oC +as
coordenadas son a&solutas, no relativas a la ventanaC +a
esquina superior i1quierda est. en D1,1EC +a copia se hace
secuencialmente, es decir, de i1quierda a derecha , de arri&a
hacia a&ajoC #ada posici"n en la pantalla ocupa 2 &,tes en la
memoria: el primero almacena el car.cter , el segundo el
atri&utoC
;e4uel4e2 4i tiene 9*ito, devuelve 1C En caso contrario, devuelve 2C
:ortabilidad2 4"lo en !B/A%#Ps , en sistemas con B!)4 compati&leC
putte(t
:rototipo2 int putte*t Dint i(, int arriba, int dcha, int aba?o, void RfuenteEO
Include2 conioCh
:ropsito2 Escri&e el contenido del .rea apuntada por fuente en el
rect.ngulo de pantalla de$inido por las coordenadas i(,
arriba, dcha , aba?oC =eneralmente el .rea fuente se ha
llenado con una llamada a gette(tC
;e4uel4e2 4i tiene 9*ito, devuelve un valor di$erente de 2C En caso
contrario, devuelve 2C
:ortabilidad2 4"lo en !B/A%#Ps , en sistemas con B!)4 compati&leC
%indo%
:rototipo2 void HindoH Dint i(, int arriba, int dcha, int aba?oEO
Include2 conioCh
cc**
:ropsito2 <e$ine la ventana de te*to activaC +as coordenadas i(, arriba
son las de la esquina superior i1quierdaC +as coordenadas
dcha, aba?o son las de la esquina in$erior derechaC
;e4uel4e2
:ortabilidad2 4"lo en !B/A%#Ps , compati&lesC
/tras funciones
abs
:rototipo2 int a&s Dint &EO
Include2 mathCh, stdli&Ch
:ropsito2 )&tiene el valor a&soluto del entero &C
;e4uel4e2 El valor calculadoC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
atof
:rototipo2 dou&le ato$ Dconst char RcadEO
Include2 mathCh, stdli&Ch
:ropsito2 #onvierte la cadena apuntada por cad en un doubleC Esta
$unci"n reconoce la representaci"n de un nKmero en coma
$lotante con la siguiente estructura:
_&lancos`_signo`_ddd`_C`_elE_signo`ddd`
#ualquier car.cter no admisi&le corta la entradaC
;e4uel4e2 El valor calculadoC 4i se produce des&ordamiento devuelve
L3A Q;=EX06+ , asigna a la varia&le glo&al errno el valor
E'6>=EC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
cc**i
atoi
:rototipo2 int atoi Dconst char RcadEO
Include2 stdli&Ch
:ropsito2 #onvierte la cadena cad en un nKmero enteroC Esta $unci"n
reconoce el $ormato:
_&lancos`_signo`_ddd`
+a entrada $inali1a si se encuentra un car.cter no v.lidoC
;e4uel4e2 El valor convertidoC 4i la conversi"n no es posi&le devuelve 2C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
atol
:rototipo2 long atol Dconst char RcadEO
Include2 stdli&Ch
:ropsito2 #onvierte la cadena cad en un nKmero longC Esta $unci"n
reconoce el $ormato
_&lancos`_signo`_ddd`
+a entrada $inali1a si se encuentra un car.cter no v.lidoC
;e4uel4e2 El valor convertidoC 4i la conversi"n no es posi&le devuelve 2C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
itoa
:rototipo2 char Ritoa Dint valor, char Rcad, int baseEO
Include2 stdli&Ch
:ropsito2 #onvierte el entero valor en una cadena, , lo almacena en
cadC El par.metro base especi$ica en qu9 &ase se reali1ar. la
conversi"nC <e&e estar entre 2 , 36C 4i valor es negativo ,
base es 12, el primer car.cter de cad es el signo menos DAEC El
espacio asignado para cad de&e ser su$icientemente grande
para almacenar el resultadoC +a $unci"n itoa puede devolver
hasta 15 caracteresC
;e4uel4e2 ;n puntero a cadC
:ortabilidad2 4"lo <)4C
'b&it
:rototipo2 int G&hit DvoidEO
Include2 conioCh
:ropsito2 <etecta si una tecla ha sido pulsada, sin retirar el car.cter del
&u$$er , sin detener el programaC
;e4uel4e2 4i se ha pulsado una tecla devuelve un valor di$erente de 2C
En caso contrario devuelve 2C
:ortabilidad2 4"lo <)4C
cc**ii
labs
:rototipo2 long int la&s Dlong int &EO
Include2 mathCh, stdli&Ch
:ropsito2 #alcula el valor a&soluto de &C
;e4uel4e2 El valor calculadoC
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C
ltoa
:rototipo2 char Rltoa Dlong valor, char Rcad, int baseEO
Include2 stdli&Ch
:ropsito2 #onvierte el entero largo valor en una cadena, , lo almacena
en cadC El par.metro base especi$ica en qu9 &ase se reali1ar.
la conversi"nC <e&e estar entre 2 , 36C 4i valor es negativo ,
base es 12, el primer car.cter de cad es el signo menos DAEC El
espacio asignado para cad de&e ser su$icientemente grande
para almacenar el resultadoC +a $unci"n ltoa puede devolver
hasta 33 caracteresC
;e4uel4e2 ;n puntero a cadC
:ortabilidad2 4"lo <)4C
nosound
:rototipo2 void nosound DvoidEO
Include2 dosCh
:ropsito2 6paga el altavo1 despu9s de una llamada a soundC
;e4uel4e2
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
random
:rototipo2 int random Dint numEO
Include2 stdli&Ch
:ropsito2 =enera un nKmero aleatorio entero entre 2 , num A 1C
;e4uel4e2 El valor generadoC
:ortabilidad2
cc**iii
randomi5e
:rototipo2 void randomi1e DvoidEO
Include2 stdli&Ch, timeCh
:ropsito2 !niciali1a el generador de nKmeros aleatoriosC
;e4uel4e2
:ortabilidad2
[setcursort-pe
:rototipo2 void Xsetcursort,pe Dint ti"ocursorEO
Include2 conioCh
:ropsito2 Esta&lece el aspecto del cursorC +os valores posi&les para
ti"ocursor son:
X>)#;'4)' <esaparece el cursor
X4)+!<#;'4)' #ursor de &loque D E
X>)'/6+#;'4)' #ursor normal D [ E
;e4uel4e2
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
sound
:rototipo2 void sound Dunsigned ciclosEO
Include2 dosCh
:ropsito2 6ctiva el altavo1 a una $recuencia de sonido de ciclos hert1
Dciclos por segundoEC
;e4uel4e2
:ortabilidad2 4"lo !B/A%#Ps , compati&lesC
s-stem
:rototipo2 int s,stem Dconst char RordenEO
Include2 stdli&Ch, processCh
:ropsito2 +lama al int9rprete de comandos D#)//6><C#)/E del
<)4 para ejecutar la orden especi$icada mediante ordenC Esta
orden puede ser una orden <)4, un $ichero CB6- o cualquier
programaC
;e4uel4e2 4i tiene 9*ito devuelve 2C En caso contrario devuelve A1C
:ortabilidad2 Est. disponi&le para ;>!B , est. de$inida en 6>4! #C Es
compati&le con ?j'C
cc**iv
ultoa
:rototipo2 char Rultoa Dunsigned long valor, char Rcad, int baseEO
Include2 stdli&Ch
:ropsito2 #onvierte el unsigned long valor en una cadena, , lo
almacena en cadC El par.metro base especi$ica en qu9 &ase se
reali1ar. la conversi"nC <e&e estar entre 2 , 36C 4i valor es
negativo , base es 12, el primer car.cter de cad es el signo
menos DAEC El espacio asignado para cad de&e ser
su$icientemente grande para almacenar el resultadoC +a
$unci"n ultoa puede devolver hasta 33 caracteresC
;e4uel4e2 ;n puntero a cadC
:ortabilidad2 4"lo <)4C
1
"oluciones a los
e7ercicios
1. Introduccin
AB Ca",tulo 1* :?ercicio 1 BA
LNEA PONE DEBE PONER
1
include s!udio0h #include Fs!dio0hG
2
000 semana /H 000 semana H/
3
main IJ main ()
4
( I
(
in! d in! dK
6
d 4L CK d L CK
5
prin! (Ma+ d dAas en una semana)K prin!f (DMa+ Nd dAas en una semanaD) d)K
8 T
AB Ca",tulo 1* :?ercicio 2 BA
aE Qistorias de cronopios , $amasC6utor: ]ulio #ort.1ar
&E 7#u.ntas l@neas
ocupa esto:
cc**v
cE Estamos
aprendiendo 3naprogramar en #
dE 2 L 2 M 4
., -apJulo 50 EDercicio : ,.
#incIude <stdio.h>
main ()
{
int R;
fIoat S, L;
printf ("\nCIcuIo deI rea de un crcuIo y Iongitud de su circunferencia");
printf ("\nRadio: ");
scanf ("%d", &R);
S = 3.14 * R * R;
L = 2 * 3.14 * R;
printf ("\nAREA: %f", S);
printf ("\nCIRCUNFERENCIA: %f", L);
}
., -apJulo 50 EDercicio L ,.
#incIude <stdio.h>
main ()
{
int L1, L2, S1, S2, S;
printf ("\nLongitud deI cuadrado mayor: ");
scanf ("%d", &L1);
printf ("\nLongitud deI cuadrado menor: ");
scanf ("%d", &L2);
S1 = AreaCuadrado (L1);
S2 = AreaCuadrado (L2);
S = S1 - S2;
printf ("\nSoIucin: %d", S);
}
AreaCuadrado (int x)
{
return x * x;
}
2. Elementos de un programa C
AB Ca",tulo 2* :?ercicio 1 BA
cc**vi
#omo car.cter de escape PNnP
#"digo 64#!! en octal PN212P
#"digo 64#!! en he* PN*6P
cc**vii
AB Ca",tulo 2* :?ercicio 2 BA
aE Es una constante entera decimal: 12
&E Es una constante entera octal: 212 D12 decimalE
cE Es una constante entera he*adecimal: 2*12 D18 decimalE
dE Es una constante entera he*adecimal: 2B12 D18 decimalE
eE Es el car.cter >
$E Es el car.cter de c"digo 64#!! he*adecimal 12 D18 decimalE
gE Es el car.cter de c"digo 64#!! he*adecimal 1B D25 decimalE: E4#6%E
hE Es el car.cter de c"digo octal 34 D28 decimalE
AB Ca",tulo 2* :?ercicio 3 BA
$E 2dias comien1a por un nKmero
hE 4umaA-otal no se permite el gui"n A
AB Ca",tulo 2* :?ercicio D BA
( - 5 u 4 t
valores iniciales
2 3 4 ( 6 5
(QQA 3
- B QQ5A ( (
t B SS4A ( (
4 B ( Q (- QB 3) ! 2A 1( 12
u B ( Q - ! 2A 12
AB Ca",tulo 2* :?ercicio 5 BA
El car.cter PNaP es el car.cter de escape correspondiente al 64#!! 5 D&eepE, mientras
que el car.cter PN6P es lo mismo que P6PC
+a di$erencia entre P6P , I6I estri&a en que el primero es un car.cter simple
Dcomillas simplesE mientras que el segundo es una cadena de caracteres Dcomillas
do&lesE ,, por tanto, consta de dos caracteres: el car.cter P6P , el car.cter nuloC
AB Ca",tulo 2* :?ercicio E BA
aE * W , jj 1 W t ] jj 1 W t ] jj ] ]
&E * V , jj 1 W t ) jj 1 W t ) jj ] )
cE * V , ll 1 W t ) ll 1 W t ) ll ] ]
dE e2 e) ]
eE e1 e] )
$E 2 eM 1 ]
gE 2 eM e1 ) eM e] ) eM ) )
hE 2 MM e1 ) MM e] ) MM ) ]
iE 222 ll * ] ll ] ]
cc**viii
jE * R 2 2 )
GE * R , 222 ]
lE ee2 ee) e] )
mEeD2 MM 2E e] )
nE 12 W ( jj eD12 V E ll 3 VM 4 12 W ( jj e) ll 3 VM 4
12 W ( jj ] ll 3 VM 4 ] jj ] ll 3 VM 4 ] jj ] ll ]
] ll ] ]
FE 1 jj e2 ll 1 ] jj e) ll ] ] jj ] ll ] ] ll ] ]
oE 1 jj eD2 ll 1E ] jj eD) ll ]E ] jj e] ] jj ) )
AB Ca",tulo 2* :?ercicio F BA
"i ( B 11 "i ( B *
- B (( > . I QQ( 2 SS()A , M 11, * M 11 , M 5, * M 5
- B (( > . I (QQ2 (SS)A , M 12, * M 11 , M 8, * M 5
., -apJulo 90 EDercicio M ,.
#incIude <stdio.h>
main ()
{
int C;
fIoat F;
printf ("\nGrados centgrados: ");
scanf ("%d", &C);
F = ((fIoat) 9 / 5) * C + 32;
printf ("\n%d grados Centgrados equivaIen a %f grados Fahrenheit", C, F);
}
., -apJulo 90 EDercicio N ,.
#incIude <stdio.h>
main ()
{
unsigned int nhex, aIto, bajo;
printf ("\nTecIee un nmero hexadecimaI: ");
scanf ("%x", &nhex);
bajo = (nhex & 0x00FF) << 8;
aIto = (nhex & 0xFF00) >> 8;
nhex = aIto | bajo;
printf ("\nResuItado: %x", nhex);
}
., -apJulo 90 EDercicio 58 ,.
#incIude <stdio.h>
cc**i*
main ()
{
unsigned int nhex;
printf ("\nTecIee un nmero hex: ");
scanf ("%x", &nhex);
nhex &= 0xFDB6; .. mBscara 4
5555 5585 5855 8558
nhex |= 0x0924; .. mBscara 4
8888 5885 8858 8588
nhex ^= 0xF492; .. mBscara 4
5555 8588 5885 8858
printf ("\nResuItado: %x", nhex);
}
., -apJulo 90 EDercicio 55 ,.
#incIude <stdio.h>
main ()
{
int num1, num2, dif;
printf ("\nTecIee 2 nmeros enteros: ");
scanf ("%d %d", &num1, &num2);
dif = (num1 > num2 ? num1 - num2 : num2 - num1);
dif *= 3;
printf ("\nResuItado: %d", dif);
}
., -apJulo 90 EDercicio 59 ,.
#incIude <stdio.h>
main ()
{
int num, cociente, resto, soIucion;
printf ("\nTecIee un nmero entero de 4 cifras: ");
scanf ("%d", &num);
cociente = num / 100;
resto = num % 100;
soIucion = (resto >= 50 ? cociente + 1 : cociente);
soIucion *= 100;
printf ("\nResuItado: %d", soIucion);
}
3. Tipos bsicos de datos
cc***
AB Ca",tulo 3* :?ercicio 1 BA
aE unsigned long int
&E unsigned char
cE $loat
dE char
eE $loat
$E unsigned int
gE unsigned char
hE $loat
iE $loat
AB Ca",tulo 3* :?ercicio 2 BA
4e admite por teclado un car.cter Dsentencia scanEC 4i el c"digo 64#!! de este
car.cter es ma,or que 125 Des decir, si es un car.cter del conjunto 64#!!
e*tendidoE se incrementa su c"digo en 1C En caso contrario se decrementa en 1C
%or tanto, si se teclea un car.cter del conjunto 64#!! e*tendido, se visuali1a el
siguiente de la ta&laO en caso contrario se visuali1a el anteriorC
AB Ca",tulo 3* :?ercicio 3 BA
N,3IT/ TIE,:/ ;E ]I;0
a -odo el programa, pues es una
varia&le glo&alC
<urante todo el programaC
b +a $unci"n main() pues es local a
ellaC
/ientras se ejecuta main()C
c +a $unci"n ,i)uncion(), pues es
local a ellaC
/ientras se ejecuta ,i)uncion()C
d +a $unci"n ,i)uncion(), pues es
local a ellaC
<urante todo el programa, pues es
una varia&le est.ticaC
. E!" bsica
., -apJulo L0 EDercicio 5 ,.
#incIude <stdio.h>
#define CLS printf ("\033[2J") .. Oorra panalla
main ()
{
unsigned char caracter;
CLS;
printf ("\033[7m"); .. 3Jdeo in&erso
printf ("TecIee un cdigo ASCII (0-255): ");
cc***i
scanf ("%d", &caracter);
printf ("\033[5;1;37;41m"); .. Olanco inenso parpadeane so/re roDo
printf ("\nEI carcter correspondientes es %c", caracter);
printf ("\033[0m"); .. Ari/uos normales
}
., -apJulo L0 EDercicio 9 ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
unsigned int caracter;
cIrscr ();
textcoIor (YELLOW);
textbackground (BLUE);
cprintf ("TecIee un carcter: ");
caracter = getche ();
textcoIor (WHITE);
textbackground (RED);
cprintf ("\n\rCODIGO ASCII DecimaI ........... %u", caracter);
cprintf ("\n\r OctaI ............... %o",
caracter);
cprintf ("\n\r HexadecimaI ... %X",
caracter);
textattr (LIGHTGRAY | BLACK * 16);
}
., -apJulo L0 EDercicio : ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
fIoat n1, n2;
textattr (YELLOW | BLUE * 16);
cIrscr ();
cprintf ("\n\rA continuacin debe tecIear dos nmeros de tipo fIoat");
cprintf ("\n\rLa parte entera no debe tener ms de 3 dgitos");
cprintf ("\n\rLa parte decimaI se redondear a 2 dgitos");
cprintf ("\n\r==> ");
cscanf ("%f %f", &n1, &n2);
textcoIor (YELLOW);
textbackground (RED);
gotoxy (35, 10); cprintf ("%6.2f", n1);
gotoxy (35, 11); cprintf ("%6.2f", n2);
gotoxy (35, 12); cprintf ("------");
gotoxy (35, 13); cprintf ("%6.2f", n1 + n2);
cc***ii
textcoIor (LIGHTGRAY);
textbackground (BLACK);
}
., -apJulo L0 EDercicio L ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
int n1, n2, unidad, decena, centena, resto;
textattr (YELLOW | BLUE * 16);
cIrscr ();
cprintf ("\n\rTecIee dos nmeros enteros de 3 dgitos: ");
cscanf ("%d %d", &n1, &n2);
centena = n2 / 100;
resto = n2 % 100;
decena = resto / 10;
unidad = resto % 10;
cprintf ("\n\r%6d", n1);
cprintf ("\n\r x %3d", n2);
cprintf ("\n\r------");
cprintf ("\n\r%6d", n1 * unidad);
cprintf ("\n\r%5d", n1 * decena);
cprintf ("\n\r%4d", n1 * centena);
cprintf ("\n\r------");
cprintf ("\n\r%6Id", (Iong) n1 * n2);
textattr (LIGHTGRAY | BLACK * 16);
}
., -apJulo L0 EDercicio P ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
int anyo, A, B, C, D, E, N, mes, dia;
printf ("\033[2J"); .. Oorra panalla
printf ("\033[12;36H"); .. -ursor a fila 596 columna :Q
printf ("Ao: ");
scanf ("%d", &anyo);
A = anyo % 19;
B = anyo % 4;
C = anyo % 7;
D = (19 * A + 24) % 30;
E = (2 * B + 4 * C + 6 * D + 5) % 7;
N = 22 + D + E;
mes = (N > 31 ? 4 : 3);
cc***iii
dia = (mes == 3 ? N : N - 31);
printf ("\033[1;5m"); .. Ala inensidad 7 parpadeo
printf ("\033[14;19H"); .. -ursor a fila 5L6 columna 5N
printf ("Primer Domingo de Pascua: %02d/%02d/%02d", dia, mes, anyo % 100);
printf ("\033[0m"); .. +esaci&a ari/uos
}
., -apJulo L0 EDercicio Q ,.
#incIude <stdio.h>
#incIude <conio.h>
#define LF fprintf (stdprn, "\n\r");
#define FF fprintf (stdprn, "\f");
main ()
{
char nombre1[21], nombre2[21];
int edad1, edad2;
fIoat aItura1, peso1, aItura2, peso2;
fIoat edad_m, aItura_m, peso_m;
cIrscr ();
textcoIor (WHITE);
textbackground (BLUE);
Presentar ();
gotoxy (14, 3); gets (nombre1);
gotoxy (14, 4); scanf ("%d", &edad1);
gotoxy (14, 5); scanf ("%f", &aItura1);
gotoxy (14, 6); scanf ("%f", &peso1);
getchar ();
textcoIor (BLUE);
textbackground (WHITE);
Presentar ();
gotoxy (14, 9); gets (nombre2);
gotoxy (14, 10); scanf ("%d", &edad2);
gotoxy (14,11); scanf ("%f", &aItura2);
gotoxy (14, 12); scanf ("%f", &peso2);
getchar ();
edad_m = (fIoat) (edad1 + edad2) / 2;
aItura_m = (aItura1 + aItura2) / 2;
peso_m = (peso1 + peso2) / 2;
LF; fprintf (stdprn, "NOMBRE EDAD ALTURA PESO");
LF; fprintf (stdprn, "=======================================");
LF; fprintf (stdprn, "%-20s %2d %4.1f %6.2f", nombre1, edad1, aItura1, peso1);
LF; fprintf (stdprn, "%-20s %2d %4.1f %6.2f", nombre2, edad2, aItura2, peso2);
LF;
LF; fprintf (stdprn, "%20s %5.2f %5.2f %6.2f", "Media:", edad_m, aItura_m, peso_m);
FF;
textcoIor (LIGHTGRAY);
textbackground (BLACK);
}
Presentar ()
cc***iv
{
cprintf ("\n\rINTRODUZCA LOS SIGUIENTES DATOS:");
cprintf ("\n\rNombre ..... ");
cprintf ("\n\rEdad .......... ");
cprintf ("\n\rAItura ........ ");
cprintf ("\n\rPeso .......... ");
}
#. "entencias de control
., -apJulo P0 EDercicio 5 ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
fIoat nota;
cIrscr ();
do {
printf ("Nota: ");
scanf ("%f", &nota);
} whiIe (nota < 0 || nota > 10);
if (nota >= 8.5) {
textattr (YELLOW | BLUE * 16);
cprintf ("SOBRESALIENTE"); }
eIse if (nota >= 7) {
textattr (BLACK | GREEN * 16);
cprintf ("NOTABLE"); }
eIse if (nota >= 6) {
textattr (BLACK | GREEN * 16);
cprintf ("BIEN"); }
eIse if (nota >= 5) {
textattr (BLACK | GREEN * 16);
cprintf ("SUFICIENTE"); }
eIse if (nota >= 3.5) {
textattr (YELLOW | BLINK | RED * 16);
cprintf ("INSUFICIENTE"); }
eIse {
textattr (YELLOW | BLINK | RED * 16);
cprintf ("MUY DEFICIENTE");
}
textattr (LIGHTGRAY | BLACK * 16);
}
., -apJulo P0 EDercicio 9 ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
cc***v
{
char sexo;
int edad, t_caIificacion, t_anterior;
cIrscr ();
puts ("MARATN");
do {
printf ("\n(H)ombre / (M)ujer: ");
sexo = getche ();
} whiIe (sexo != 'H' && sexo != 'M');
if (sexo == 'M') t_caIificacion = 180;
eIse {
printf ("\nEdad: ");
scanf ("%d", &edad);
if (edad < 40) t_caIificacion = 150;
eIse t_caIificacion = 175;
}
printf ("\nTiempo de anterior Maratn: ");
scanf ("%d", &t_anterior);
if (t_anterior <= t_caIificacion) puts ("SELECCIONADO");
eIse puts ("NO SELECCIONADO");
}
., -apJulo P0 EDercicio : ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
char turno, domingo;
int vaIor_hora, incremento, trabajadas;
cIrscr ();
puts ("CLCULO DEL JORNAL");
do {
printf ("\n(D)iurno / (N)octurno: ");
turno = getche ();
} whiIe (turno != 'D' && turno != 'N');
if (turno == 'D') {
vaIor_hora = 1000;
incremento = 400; }
eIse {
vaIor_hora = 1600;
incremento = 600;
}
do {
printf ("\nDomingo (S/N): ");
domingo = getche ();
} whiIe (domingo != 'S' && domingo != 'N');
if (domingo == 'S') vaIor_hora += incremento;
printf ("\nHoras trabajadas: ");
scanf ("%d", &trabajadas);
cc***vi
printf ("\nJORNAL: %d pts.", vaIor_hora * trabajadas);
}
., -apJulo P0 EDercicio L ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
register int i;
int A, B, pares, impares;
cIrscr ();
puts ("Suma de pares e impares comprendidos entre A y B");
do {
printf ("\nTecIee vaIores de A y B (A < B): ");
scanf ("%d %d", &A, &B);
} whiIe (A >= B);
pares = impares = 0;
for (i = A; i <= B; i++) {
if (i % 2) impares += i;
eIse pares += i;
}
printf ("\nSUMA PARES: %d", pares);
printf ("\nSUMA IMPARES: %d", impares);
}
., -apJulo P0 EDercicio P ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
register int i;
int x, n;
Iong int totaI = 1;
cIrscr ();
puts ("CLCULO DE x
n
");
printf ("\nVaIor de x: ");
scanf ("%d", &x);
do {
printf ("\nVaIor de n (n 0): ");
scanf ("%d", &n);
} whiIe (n < 0);
for (i = 1; i <= n; i++) totaI *= x;
printf ("\nResuItado: %Id", totaI);
}
cc***vii
., -apJulo P0 EDercicio Q ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
register int i;
int n;
Iong int totaI = 1;
cIrscr ();
puts ("CLCULO DE n!");
do {
printf ("\nVaIor de n (n 0): ");
scanf ("%d", &n);
} whiIe (n < 0);
for (i = 1; i <= n; i++) totaI *= i;
printf ("\n%d! = %Id", n, totaI);
}
cc***viii
., -apJulo P0 EDercicio R ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
register int i;
int M;
Iong int suma = 0;
cIrscr ();
puts ("CIcuIo deI primer vaIor N para eI que 1 + 2 + 3 + ... + N > M");
do {
printf ("\nM = ");
scanf ("%d", &M);
} whiIe (M < 0);
for (i = 1; ; i++) {
if (suma > M) break;
suma += i;
}
printf ("\nPara %d Ia suma vaIe %d", i - 1, suma);
}
., -apJulo P0 EDercicio M ,.
#incIude <stdio.h>
#incIude <conio.h>
main ()
{
int a_2, a_1, a, N;
cIrscr ();
puts ("Primer eIemento de Ia serie de Fibonacci mayor que N");
do {
printf ("\nVaIor de N (N > 1): ");
scanf ("%d", &N);
} whiIe (N <= 1);
a_2 = a_1 = 1;
a = a_2 + a_1;
whiIe (a <= N) {
a_2 = a_1;
a_1 = a;
a = a_1 + a_2;
}
printf ("\nEI primer eIemento mayor que %d es %d", N, a);
}
., -apJulo P0 EDercicio N ,.
#incIude <stdio.h>
cc***i*
#incIude <conio.h>
doubIe VaIor_absoIuto (doubIe x);
main ()
{
register int i;
int signo;
doubIe termino, mi_pi, pi_reaI;
cIrscr ();
puts ("CALCULO DE ");
pi_reaI = 3.141592;
mi_pi = 0;
termino = 0;
signo = 1;
for (i = 1; ; i += 2) {
if (VaIor_absoIuto (pi_reaI - mi_pi) < 0.001) break;
termino += (doubIe) signo / i;
mi_pi = 4 * termino;
signo = -signo;
gotoxy (1, 4);
printf ("Iteracin: %5d - VaIor estimado de : %6.4f", i, mi_pi);
}
}
doubIe VaIor_absoIuto (doubIe x)
{
if (x < 0) return -x;
eIse return x;
}
$. )unciones
., -apJulo Q0 EDercicio 5 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
#incIude <stdIib.h>
doubIe potencia (doubIe base, int exponente);
doubIe factoriaI (int numero);
void main (void)
{
register int i;
int x, signo;
doubIe radianes, seno, termino;
cIrscr ();
do {
printf ("\nnguIo (0-360): ");
cc*l
scanf ("%d", &x);
} whiIe (x < 0 || x > 360);
radianes = x * 3.1416 / 180;
seno = 0;
signo = 1;
for (i = 1; ; i += 2) {
if (termino <= 0.001 && i != 1) break;
termino = potencia (radianes, i) / factoriaI (i);
seno += signo * termino;
signo = -signo;
gotoxy (1, 3);
printf ("\nTrmino: %6.4f - seno (%3d) = %6.4f", termino, x, seno);
}
}
doubIe potencia (doubIe base, int exponente)
{
register int i;
doubIe totaI = 1;
for (i = 1; i <= exponente; i++) totaI *= base;
return totaI;
}
doubIe factoriaI (int numero)
{
register int i;
doubIe totaI = 1;
for (i = 1; i <= numero; i++) totaI *= (doubIe) i;
return totaI;
}
., -apJulo Q0 EDercicio 9 ,.
#incIude <stdio.h>
#incIude <conio.h>
Iong potencia (int base, int exponente);
void main (void)
{
int x, n;
cIrscr ();
puts ("CLCULO DE x
n
MEDIANTE UNA FUNCIN RECURSIVA");
do {
printf ("\nVaIor de x (x > 0): ");
scanf ("%d", &x);
} whiIe (x <= 0);
do {
printf ("\nVaIor de n (n > 0): ");
scanf ("%d", &n);
} whiIe (n <= 0);
cc*li
printf ("\nResuItado: %Id", potencia (x, n));
}
Iong potencia (int base, int exponente)
{
if (!exponente) return 1;
return base * potencia (base, exponente - 1);
}
., -apJulo Q0 EDercicio : ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
#incIude <stdIib.h>
int Fibonacci (int eIemento);
void main (void)
{
register int i;
int N;
cIrscr ();
puts ("SUCESIN DE FIBONACCI");
printf ("\nMostrar Ios N primeros trminos");
do {
printf ("\nVaIor de N (N > 0): ");
scanf ("%d", &N);
} whiIe (N <= 0);
for (i = 1; i <= N; i++) printf ("\n%d", Fibonacci (i));
}
int Fibonacci (int eIemento)
{
if (eIemento <= 2) return 1;
eIse return Fibonacci (eIemento - 1) + Fibonacci (eIemento - 2);
}
., -apJulo Q0 EDercicio L ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <bios.h>
void Presentar (void);
void main (void)
{
int equipo, a;
cIrscr ();
Presentar ();
equipo = biosequip ();
gotoxy (37, 4);
a = equipo & 0x0002;
cc*lii
if (a) puts ("SI");
eIse puts ("NO");
gotoxy (37, 5);
a = (equipo & 0x000C) >> 2;
printf ("%d Kb.", (a + 1) * 16);
gotoxy (37, 7);
a = (equipo & 0x0030) >> 4;
switch (a) {
case 1: puts ("40x25 BIanco y Negro, Adaptador CoIor");
break;
case 2: puts ("80x25 BIanco y Negro, Adaptador CoIor");
break;
case 3: puts ("80x25 Adaptador Monocromo");
}
gotoxy (37, 8);
a = equipo & 0x0001;
if (!a) puts ("0");
eIse {
a = (equipo & 0x00C0) >> 6;
printf ("%d", a + 1);
}
gotoxy (37, 9);
a = equipo & 0x0100;
if (a) puts ("NO");
eIse puts ("SI");
gotoxy (37, 10);
a = (equipo & 0x0E00) >> 9;
printf ("%d", a);
gotoxy (37, 11);
a = equipo & 0x2000;
if (a) puts ("SI");
eIse puts ("NO");
gotoxy (37, 12);
a = (equipo & 0xC000) >> 14;
printf ("%d", a);
gotoxy (37, 6);
a = biosmemory ();
printf ("%d Kb.", a);
}
void Presentar (void)
{
puts ("EQUIPAMIENTO");
puts ("-----------------------\n");
puts ("Procesador matemtico instaIado ...");
puts ("RAM en pIaca base ...........................");
puts ("RAM convencionaI ...........................");
puts ("Modo iniciaI de vdeo .......................");
puts ("Unidades de disquete ......................");
puts ("Chip DMA instaIado .........................");
puts ("Puertos serie ....................................");
puts ("Adaptador de juegos instaIado .......");
puts ("Impresoras .......................................");
cc*liii
}
., -apJulo Q0 EDercicio P ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <bios.h>
void Presentar (void);
void main (void)
{
register int i;
unsigned int tecIado, bit, saIir = 0;
_setcursortype (_NOCURSOR);
cIrscr ();
Presentar ();
for (;;) {
tecIado = bioskey (2);
for (i = 0; i < 8; i++) {
bit = tecIado & 1;
gotoxy (26, i + 1);
if (bit) puts ("SI");
eIse puts ("NO");
tecIado >>= 1;
}
if (kbhit()) saIir = getch ();
if (saIir == 27) break;
}
_setcursortype (_NORMALCURSOR);
}
void Presentar (void)
{
puts ("MayscuIas derecha ");
puts ("MayscuIas izquierda ");
puts ("TecIa ControI ");
puts ("TecIa AIt ");
puts ("TecIa BIoq DespI ");
puts ("TecIa BIoq Num ");
puts ("TecIa BIoq Mays ");
puts ("TecIa Ins ");
puts ("\nPuIse Ia tecIa Esc para finaIizar");
}
., -apJulo Q0 EDercicio Q ,.
char *Intro (int f, int c, int tam, char *cad)
{
register int i;
char aux[100];
gotoxy (c, f);
for (i = 0; i < tam; i++) putch (' ');
gotoxy (c, f);
cc*liv
aux[0] = tam + 1;
strcpy (cad, cgets (aux));
return cad;
}
., -apJulo Q0 EDercicio R ,.
int Strdigit (char *cad)
{
register int i;
for (i = 0; cad[i]; i++) if (!isdigit (cad[i])) return 0;
return 1;
}
., -apJulo Q0 EDercicio M ,.
char *Format_fecha (char *fecha, int tipo, char *format)
{
int diasemana;
char dia[3], mes[3], anyo[5], aux[9];
char meses[12][12] = { "Enero", "Febrero", "Marzo", "AbriI", "Mayo", "Junio",
"JuIio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };
char dias[7][12] = { "Domingo", "Lunes", "Martes", "MircoIes", "Jueves",
"Viernes", "Sbado" };
diasemana = VaIida_fecha (fecha);
if (diasemana == -1 || tipo < 0 || tipo > 3) {
format = 0;
return format;
}
dia[2] = mes[2] = 0;
strncpy (dia, fecha, 2);
strncpy (mes, fecha + 2, 2);
strcpy (anyo, fecha + 4);
switch (tipo) {
case 0: sprintf (format, "%s/%s/%s", dia, mes, anyo + 2);
break;
case 1: sprintf (format, "%s/%s/%s", dia, mes, anyo);
break;
case 2: sprintf (format, "%d de %s de %s", atoi (dia), meses[atoi(mes) - 1], anyo);
break;
case 3: sprintf (format, "%s, %s", dias[diasemana], Format_fecha (fecha, 2,
aux));
}
return format;
}
., -apJulo Q0 EDercicio N ,.
#incIude <dos.h>
int VaIida_fecha (char *fecha)
{
union REGS ent, saI;
cc*lv
char dia[3], mes[3], anyo[5];
int sysdia, sysmes, sysanyo, diasemana;
int i;
if (strIen (fecha) != 8) return -1;
for (i = 0; fecha[i]; i++) if (!isdigit (fecha[i])) return -1;
dia[2] = mes[2] = 0;
strncpy (dia, fecha, 2);
strncpy (mes, fecha + 2, 2);
strcpy (anyo, fecha + 4);
ent.h.ah =0x2A;
intdos (&ent, &saI);
sysanyo = saI.x.cx;
sysmes = saI.h.dh;
sysdia = saI.h.dI;
ent.h.ah = 0x2B;
ent.x.cx = atoi (anyo);
ent.h.dh = atoi (mes);
ent.h.dI = atoi (dia);
intdos (&ent, &saI);
if (saI.h.aI) return -1;
ent.h.ah = 0x2A;
intdos (&ent, &saI);
diasemana = saI.h.aI;
ent.h.ah = 0x2B;
ent.x.cx = sysanyo;
ent.h.dh = sysmes;
ent.h.dI = sysdia;
intdos (&ent, &saI);
return diasemana;
}
., -apJulo Q0 EDercicio 58 ,.
int TecIa (int *scan)
{
unsigned paIabra;
paIabra = bioskey (0);
*scan = paIabra >> 8;
return paIabra & 0x00FF;
}
., -apJulo Q0 EDercicio 55 ,.
int Mensaje (int st, int fiI, int coI, char *cad)
{
int ascii, scan;
gotoxy (coI, fiI);
cprintf (cad);
if (!st) return 0;
ascii = TecIa (&scan);
if (ascii) return ascii;
cc*lvi
eIse return scan + 1000;
}
+. ,atrices - punteros
., -apJulo R0 EDercicio 5 ,.
#incIude <stdio.h>
#incIude <conio.h>
int Suma_fiIa (int fiIa);
int Suma_coIumna (int coIumna);
int matriz[4][3];
void main (void)
{
register int i, j;
cIrscr ();
puts ("Carga de Ios eIementos de Ia matriz");
for (i = 0; i < 4; i++) {
for (j = 0; j < 3; j++) {
printf ("\nMATRIZ[%d][%d] = ", i, j);
scanf ("%d", &matriz[i][j]);
}
}
for (i = 0; i < 4; i++) printf ("\nLa fiIa %d suma %d", i, Suma_fiIa (i));
for (i = 0; i < 3; i++) printf ("\nLa coIumna %d suma %d", i, Suma_coIumna (i));
}
int Suma_fiIa (int fiIa)
{
register int i;
int totaI = 0;
for (i = 0; i < 3; i++) totaI += matriz[fiIa][i];
return totaI;
}
int Suma_coIumna (int coIumna)
{
register int i;
int totaI = 0;
for (i = 0; i < 4; i++) totaI += matriz[i][coIumna];
return totaI;
}
., -apJulo R0 EDercicio 9 ,.
cc*lvii
#incIude <stdio.h>
#incIude <conio.h>
void main (void)
{
int magico[3][3];
int i, j, ant_i, ant_j;
register int vaIor;
cIrscr ();
puts ("CUADRADO MGICO DE ORDEN 3");
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
magico[i][j] = 0;
}
}
i = 0;
j = 1;
for (vaIor = 1; vaIor <= 9; vaIor++) {
if (magico[i][j]) {
i = ant_i + 1;
j = ant_j;
if (i > 2) i = 0;
}
magico[i][j] = vaIor;
ant_i = i--;
ant_j = j++;
if (i < 0) i = 2;
if (j > 2) j = 0;
}
cIrscr ();
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf ("%3d ", magico[i][j]);
}
printf ("\n");
}
}
., -apJulo R0 EDercicio :
?e supone *ue en el direcorio C)*+I,IB se encuenran las funciones In'ro()
7 S'rdi-i'() diseIadas en el capJulo anerior ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <stdIib.h>
#incIude <string.h>
#incIude <ctype.h>
#incIude <process.h>
#incIude "C:\MILIB\INTRO.C"
#incIude "C:\MILIB\STRDIGIT.C"
void main (int argc, char *argv[ ])
{
int magico[19][19];
cc*lviii
int i, j, ant_i, ant_j, orden, tope;
register int vaIor;
cIrscr ();
puts ("CUADRADO MGICO DE ORDEN N IMPAR (3 N 19)");
switch (argc) {
case 1: puts ("FaIta parmetro");
exit (1);
case 2: orden = atoi (argv[1]);
if (orden < 3 || orden > 19 || !(orden % 2)) {
puts ("Parmetro no vIido");
exit (1);
}
break;
defauIt: puts ("Demasiados parmetros");
exit (1);
}
tope = orden * orden;
for (i = 0; i < orden; i++) {
for (j = 0; j < orden; j++) {
magico[i][j] = 0;
}
}
i = 0;
j = orden / 2;
for (vaIor = 1; vaIor <= tope; vaIor++) {
if (magico[i][j]) {
i = ant_i + 1;
j = ant_j;
if (i > orden - 1) i = 0;
}
magico[i][j] = vaIor;
ant_i = i--;
ant_j = j++;
if (i < 0) i = orden - 1;
if (j > orden - 1) j = 0;
}
cIrscr ();
for (i = 0; i < orden; i++) {
for (j = 0; j < orden; j++) {
printf ("%3d ", magico[i][j]);
}
printf ("\n");
}
}
., -apJulo R0 EDercicio L ,.
., ?olucin declarando las marices como =lo/ales ,.
#incIude <stdio.h>
#incIude <conio.h>
void Carga (int x[3][3]);
int Producto (int fiIa, int coIumna);
int A[3][3], B[3][3];
cc*li*
void main (void)
{
register int i, j;
int P[3][3];
cIrscr ();
puts ("Carga de Ia Matriz A");
Carga (A);
puts ("Carga de Ia Matriz B");
Carga (B);
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
P[i][j] = Producto (i, j);
}
}
puts ("Matriz producto: \n");
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf ("%3d ", P[i][j]);
}
printf ("\n");
}
}
void Carga (int x[3][3])
{
register int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf ("\n[%d][%d]: ", i, j);
scanf ("%d", &x[i][j]);
}
}
}
int Producto (int fiIa, int coIumna)
{
register int k;
int totaI = 0;
for (k = 0; k < 3; k++) totaI += A[fiIa][k] * B[k][coIumna];
return totaI;
}
., -apJulo R0 EDercicio L ,.
., ?olucin declarando las marices como locales ,.
#incIude <stdio.h>
#incIude <conio.h>
void Carga (int x[3][3]);
int Producto (int fiIa, int coIumna, int x[3][3], int y[3][3]);
void main (void)
{
register int i, j;
ccl
int A[3][3], B[3][3], P[3][3];
cIrscr ();
puts ("Carga de Ia Matriz A");
Carga (A);
puts ("Carga de Ia Matriz B");
Carga (B);
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
P[i][j] = Producto (i, j, A, B);
}
}
puts ("Matriz producto: \n");
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf ("%3d ", P[i][j]);
}
printf ("\n");
}
}
void Carga (int x[3][3])
{
register int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf ("\n[%d][%d]: ", i, j);
scanf ("%d", &x[i][j]);
}
}
}
int Producto (int fiIa, int coIumna, int x[3][3], int y[3][3])
{
register int k;
int totaI = 0;
for (k = 0; k < 3; k++) totaI += x[fiIa][k] * y[k][coIumna];
return totaI;
}
., -apJulo R0 EDercicio P ,.
char *Strminus (char *cad)
{
char mayus[ ] = "";
char minus[ ] = "";
char *p;
register int i;
strIwr (cad);
for (i = 0; cad[i]; i++) {
p = strchr (mayus, cad[i]);
if (p) cad[i] = minus[p - mayus];
}
return cad;
ccli
}
char *Strmayus (char *cad)
{
char mayus[ ] = "";
char minus[ ] = "";
char *p;
register int i;
strupr (cad);
for (i = 0; cad[i]; i++) {
p = strchr (minus, cad[i]);
if (p) cad[i] = mayus[p - minus];
}
return cad;
}
., -apJulo R0 EDercicio Q ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <bios.h>
#incIude <time.h>
void Presentar (void);
void Iniciar (int vector[ ], int n);
void Burbuja (int vector[ ], int n);
void SeIeccion (int vector[ ], int n);
void Insercion (int vector[ ], int n);
void SheII (int vector[ ], int n);
void Quick (int vector[ ], int primero, int uItimo);
void main (void)
{
int fiIa, x[5000];
register int i;
unsigned Iong int inicio, finaI;
cIrscr ();
Presentar ();
fiIa = 6;
for (i = 500; i <= 5000; i += 500) {
Iniciar (x, i);
inicio = biostime (0, 0);
Burbuja (x, i);
finaI = biostime (0, 0);
gotoxy (9, fiIa);
printf ("%12Iu ", finaI - inicio);
Iniciar (x, i);
inicio = biostime (0, 0);
SeIeccion (x, i);
finaI = biostime (0, 0);
gotoxy (23, fiIa);
printf ("%12Iu ", finaI - inicio);
Iniciar (x, i);
inicio = biostime (0, 0);
cclii
Insercion (x, i);
finaI = biostime (0, 0);
gotoxy (37, fiIa);
printf ("%12Iu ", finaI - inicio);
Iniciar (x, i);
inicio = biostime (0, 0);
SheII (x, i);
finaI = biostime (0, 0);
gotoxy (51, fiIa);
printf ("%12Iu ", finaI - inicio);
Iniciar (x, i);
inicio = biostime (0, 0);
Quick (x, 0, i - 1);
finaI = biostime (0, 0);
gotoxy (65, fiIa);
printf ("%12Iu ", finaI - inicio);
fiIa += 2;
}
}
void Presentar (void)
{
register int i, j;
char tituIos[ ][15] = { "BURBUJA", "SELECCIN", "INSERCIN", "SHELL", "QUICK" };
puts ("TICKS EMPLEADOS EN LAS DIFERENTES ORDENACIONES");
printf ("\n ");
for (i = 1; i <= 5; i++) printf (" ");
putch (' ');
printf ("\n ");
for (i = 1; i <= 5; i++) printf (" %12s ", tituIos[i - 1]);
putch ('');
for (j = 500; j <= 5000; j += 500) {
printf ("\n ");
for (i = 1; i <= 5; i++) printf (" ");
putch (' ');
printf ("\n %4d ", j);
for (i = 1; i <= 5; i++) printf (" ");
putch ('');
}
printf ("\n ");
for (i = 1; i <= 5; i++) printf (" ");
putch (' ');
}
void Iniciar (int vector[ ], int tope)
{
register int i;
for (i = 0; i < tope; i++) vector[i] = tope - i;
}
void Burbuja (int vector[ ], int tope)
{
int i, ordenado, aux;
ordenado = 0;
ccliii
whiIe (!ordenado) {
ordenado = 1;
for (i = 0; i < tope - 1; i++) {
if (vector[i] > vector[i + 1]) {
aux = vector[i];
vector[i] = vector[i + 1];
vector[i + 1] = aux;
ordenado = 0;
}
}
tope--;
}
}
void SeIeccion (int vector[ ], int tope)
{
register int i, inicio;
int aux, menor;
for (inicio = 0; inicio < tope - 1; inicio++) {
menor = inicio;
for (i = inicio + 1; i < tope; i++) if (vector[i] < vector[menor]) menor = i;
aux = vector[inicio];
vector[inicio] = vector[menor];
vector[menor] = aux;
}
}
void Insercion (int vector[ ], int n)
{
register int i, j;
int aux;
for (i = 1; i < n; i++) {
aux = vector[i];
for (j = i - 1; j >= 0; j--) {
if (aux < vector[j]) vector[j + 1] = vector[j];
eIse break;
}
vector[j + 1] = aux;
}
}
void SheII (int vector[ ], int n)
{
register int i, separador;
int aux;
for (separador = n / 2; separador > 0; separador /= 2) {
if (!(separador % 2)) separador++;
for (i = 0; i < n - separador; i++) {
if (vector[i] > vector[i + separador]) {
aux = vector[i];
vector[i] = vector[i + separador];
vector[i + separador] = aux;
}
}
}
}
void Quick (int vector[ ], int primero, int uItimo)
ccliv
{
register int i, j;
int aux, centro;
centro = vector[ (primero + uItimo) / 2];
i = primero;
j = uItimo;
do {
whiIe (centro > vector[i]) i++;
whiIe (vector[j] > centro) j--;
if (i < j) {
aux = vector[i];
vector[i] = vector[j];
vector[j] = aux;
i++;
j--; }
eIse if (i == j) i++;
} whiIe (i <= j);
if (primero < j) Quick (vector, primero, j);
if (i < uItimo) Quick (vector, i, uItimo);
}
+os valores proporcionados son:
BURBURA SEFECCIN INSERCIN SSEFF [UIC\
@00 10 , A 0 0
1000 +8 17 && 1 0
1@00 87 ,1 @, 1 1
&000 1@, A8 88 1 0
&@00 &,& 109 1+9 1 1
+000 +@0 1@7 &01 & 1
+@00 ,77 &1+ &7, & &
,000 A&+ &77 +@8 & 1
,@00 789 +,A ,@+ + &
@000 97, ,&7 @@9 + &
+a primera columna indica el nKmero de elementos a ordenarC En el interior se
muestra los ticGs transcurridosC +os m9todos m.s e$icientes son 4hell , 8uicG , el
peor es de la Bur&ujaC 4i el vector est. ordenado aleatoriamente el m9todo de
!nserci"n supera al de 4elecci"nC +as modi$icaciones que ha, que hacer en el
programa para que el vector est9 ordenado aleatoriamente son:
6Fadir las l@neas que inclu,en los archivos de ca&ecera stdIib.h , mem.hC
Eliminar la $unci"n Iniciar() , su prototipoC
6Fadir las declaraciones int y[5000]; , register int j;C
<espu9s de la l@nea for (i = 500; i <= 5000; i += 500) {, aFadir:
randomize ();
for (j = 0; j < i; j++) y[j] = random (10000);
4ustituir todas las llamadas a Iniciar() por sentencias memcpy (x, y, 2 * i);
cclv
+os resultados proporcionados por este programa son los siguientes:
BURBURA SEFECCIN INSERCIN SSEFF [UIC\
@00 7 @ + 0 0
1000 +, 18 11 1 0
1@00 A, ,1 &@ 1 1
&000 11, 7@ ,+ & 1
&@00 180 11A 70 & 1
+000 &A0 1AA 101 & 1
+@00 +@1 &&@ 1+, + &
,000 ,A0 &9+ 17A + +
,@00 @8+ +70 &&@ + +
@000 719 ,@7 &77 + +
., -apJulo R0 EDercicio RA Funcin Co(ia() con Jndices ,.
char *Copia (char *cad1, const char *cad2)
{
register int i;
for (i = 0; cad2[i]; i++) cad1[i] = cad2[i];
cad1[i] = 0;
return cad1;
}
., -apJulo R0 EDercicio RA Funcin Co(ia() con puneros ,.
char *Copia (char *cad1, const char *cad2)
{
char *p1;
const char *p2;
for (p1 = cad1, p2 = cad2; *p2; p1++, p2++) *p1 = *p2;
*p1 = 0;
return cad1;
}
., -apJulo R0 EDercicio RA Funcin Conca'#na() con Jndices ,.
char *Concatena (char *cad1, const char *cad2)
{
register int i, j;
for (i = 0, j = strIen (cad1); cad2[i]; i++, j++) cad1[j] = cad2[i];
cad1[j] = 0;
return cad1;
}
., -apJulo R0 EDercicio RA Funcin Conca'#na() con puneros ,.
cclvi
char *Concatena (char *cad1, const char *cad2)
{
char *p1;
const char *p2;
p1 = cad1 + strIen (cad1);
p2 = cad2;
for (; *p2; p1++, p2++) *p1 = *p2;
*p1 = 0;
return cad1;
}
., -apJulo R0 EDercicio MA Funcin In.#r'ar() con Jndices ,.
char *Insertar (char *cad, int car, int pos)
{
register int i;
for (i = strIen (cad); i >= pos; i--) cad[i + 1] = cad[i];
cad[pos] = car;
return cad;
}
., -apJulo R0 EDercicio MA Funcin In.#r'ar() con puneros ,.
char *Insertar (char *cad, int car, int pos)
{
char *p;
p = cad + strIen (cad);
for (; p >= cad + pos; p--) *(p + 1) = *p;
*(cad + pos) = car;
return cad;
}
., -apJulo R0 EDercicio NA Funcin E&imina() con Jndices ,.
char *EIimina (char *cad, int pos)
{
register int i;
for (i = pos + 1; cad[i]; i++) cad[i - 1] = cad[i];
cad[i - 1] = 0;
return cad;
}
., -apJulo R0 EDercicio NA Funcin E&imina() con puneros ,.
char *EIimina (char *cad, int pos)
{
char *p;
cclvii
p = cad + pos + 1;
for (; *p; p++) *(p - 1) = *p;
*(p - 1) = 0;
return cad;
}
., -apJulo R0 EDercicio 580 Funcin Su".'r() con Jndices ,.
char *Substr (char *orig, int desde, int n, char *dest)
{
register int i, j;
for (i = desde, j = 0; i < desde + n && orig[i]; i++, j++) dest[j] = orig[i];
dest[j] = 0;
return dest;
}
., -apJulo R0 EDercicio 58A Funcin ?u/sr12 con puneros ,.
char *Substr (char *orig, int desde, int n, char *dest)
{
char *po, *pd;
po = orig + desde;
pd = dest;
whiIe (po < orig + desde + n && *po) {
*pd = *po;
pd++;
po++;
}
*pd = 0;
return dest;
}
., -apJulo R0 EDercicio 55 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <time.h>
#define SI 1
#define NO 0
void main (void)
{
int x[1000], desorden, aux, *p, tope, i;
cIock_t inicio, fin;
cIrscr ();
puts ("ORDENACION MEDIANTE INDICES");
for (i = 0; i < 1000; i++) x[i] = 1000 - i;
puts ("Matriz cargada. Comienza ordenacin");
inicio = cIock ();
cclviii
tope = 1000;
desorden = SI;
whiIe (desorden) {
desorden = NO;
for (i = 0; i < tope - 1; i++) {
if (x[i] > x[i + 1]) {
aux = x[i];
x[i] = x[i + 1];
x[i + 1] = aux;
desorden = SI;
}
}
tope--;
}
fin = cIock ();
printf ("Ordenacin finaIizada. Tiempo medido: %7.4f\n", (fin - inicio) / CLK_TCK);
puts ("\nORDENACION MEDIANTE PUNTEROS");
for (i = 0; i < 1000; i++) x[i] = 1000 - i;
puts ("Matriz cargada. Comienza ordenacin");
inicio = cIock ();
tope = 1000;
desorden = SI;
whiIe (desorden) {
desorden = NO;
for (p = x; p < x + tope - 1; p++) {
if (*p > *(p + 1)) {
aux = *p;
*p = *(p + 1);
*(p + 1) = aux;
desorden = SI;
}
}
tope--;
}
fin = cIock ();
printf ("Ordenacin finaIizada. Tiempo caIcuIado: %7.4f", (fin - inicio) / CLK_TCK);
}
., -apJulo R0 EDercicio 59 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <stdIib.h>
#incIude <time.h>
void main (void)
{
int vector[50], *p, mayor, Iugar, *direccion, i;
cIrscr ();
randomize ();
puts ("Carga aIeatoria deI vector");
for (p = vector; p < vector + 50; p++) *p = random (1000);
for (i = 0; i < 50; i++) {
if (i == 4 * (i / 4)) printf ("\n");
eIse printf (" ");
printf ("%2d - %3d [%ph]", i, vector[i], &vector[i]);
}
ccli*
mayor = *vector;
Iugar = 0;
direccion = vector;
for (p = vector + 1; p < vector + 50; p++) {
if (*p > mayor) {
mayor = *p;
Iugar = p - vector;
direccion = p;
}
}
printf ("\n\nEI mayor es %d", mayor);
printf ("\nOcupa eI Iugar %d", Iugar);
printf ("\nSe aImacena en Ia direccin %p", direccion);
}
., -apJulo R0 EDercicio 5: ,.
#incIude <stdio.h>
#incIude <conio.h>
#define TOPE 50
int Menu (void);
int Mostrar (int);
int Introducir (int);
int Sacar (int);
int (*F_piIa[ ]) (int) = { Mostrar, Introducir, Sacar };
int piIa[TOPE], indice;
void main (void)
{
int n, dato, st;
whiIe ((n = Menu ()) != 4) {
if (n == 2) {
printf ("\nDato a introducir en Ia piIa: ");
scanf ("%d", &dato);
}
st = (*F_piIa[n - 1]) (dato);
switch (n) {
case 2: if (st) puts ("\nPILA LLENA: EI dato no se ha introducido");
case 1: break;
case 3: if (st < 0) puts ("\nPILA VACIA");
eIse printf ("\nDato sacado de Ia piIa: %d", st);
}
printf ("\nPuIse una tecIa ...");
getch ();
}
}
int Menu (void)
{
int opcion;
cIrscr ();
puts ("1. Mostrar eI contenido de Ia piIa");
puts ("2. Introducir un dato en Ia piIa");
puts ("3. Sacar un dato de Ia piIa");
ccl*
puts ("4. Fin deI programa");
do {
opcion = getch ();
} whiIe (opcion < '1' || opcion > '4');
return opcion - 48;
}
int Mostrar (int x)
{
register int i;
for (i = 0; i < indice; i++) {
if (i == 5 * (i / 5)) printf ("\n");
eIse printf (" ");
printf ("%2d: %4d", i, piIa[i]);
}
return 0;
}
int Introducir (int x)
{
if (indice == TOPE) return 1;
piIa[indice++] = x;
return 0;
}
int Sacar (int x)
{
if (!indice) return -1;
return piIa[--indice];
}
*. /tros tipos de datos
., -apJulo M0 EDercicio 5
Las funciones In'ro() 7 S'rdi-i'() se suponen almacenadas en mdulos apare6
compiladas separadamene 7 enla(adas con ese pro=rama ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
#incIude <math.h>
#define LF fprintf (stdprn, "\n\r");
#define FF fprintf (stdprn, "\f");
struct COMPO {
char codigo[9];
char cantidad;
int precio;
};
struct ARTIC {
char codigo[6];
char descri[41];
struct COMPO co[5];
};
ccl*i
char *Intro (int, int, int, char *);
int Strdigit (char *);
void Cabecera (void);
void main (void)
{
register int i, j, k;
struct ARTIC ar[25];
char cant[4], prec[5];
int articuIos;
Iong totaI, parciaI;
cIrscr ();
textcoIor (YELLOW);
textbackground (BLUE);
for (i = 0; i < 10; i++) {
printf ("\nARTICULO n %d", i);
printf ("\nCdigo: (000 para acabar) ");
Intro (wherey (), wherex (), 5, ar[i].codigo);
if (!strcmp (ar[i].codigo, "000")) break;
printf ("\nDescripcin: ");
Intro (wherey (), wherex (), 40, ar[i].descri);
for (j = 0; j < 5; j++) {
printf ("\nComponente n %d", j);
printf ("\nCdigo: ");
Intro (wherey (), wherex (), 8, ar[i].co[j].codigo);
do {
do {
printf ("\nCantidad (1-100): ");
Intro (wherey (), wherex (), 3, cant);
} whiIe (!Strdigit (cant));
} whiIe (atoi (cant) < 1 || atoi (cant) > 100);
ar[i].co[j].cantidad = atoi (cant);
do {
do {
printf ("\nPrecio (500-5000): ");
Intro (wherey (), wherex (), 4, prec);
} whiIe (!Strdigit (prec));
} whiIe (atoi (prec) < 500 || atoi (prec) > 5000);
ar[i].co[j].precio = atoi (prec);
}
printf ("\n--------------------------------------------");
}
printf ("\nIMPRESIN DE DATOS. Prepare Ia impresora y puIse <Intro>");
whiIe (getch () != 13);
articuIos = 0;
for (k = 0; k < i; k++) {
if (!articuIos) Cabecera ();
totaI = 0;
for (j = 0; j < 5; j++) {
parciaI = (Iong) ar[k].co[j].cantidad * ar[k].co[j].precio;
totaI += parciaI;
LF;
if (!j) fprintf (stdprn, "%-5s %-40s ", ar[k].codigo, ar[k].descri);
eIse fprintf (stdprn, "%5s %40s ", " ", " ");
fprintf (stdprn, "%-8s %3d %5d %6Id", ar[k].co[j].codigo, ar[k].co[j].cantidad, ar[k].co[j].precio, parciaI);
}
ccl*ii
LF; fprintf (stdprn, "%75s", "-------");
LF; fprintf (stdprn, "%50s TotaI .......... %7Id", " ", totaI);
LF;
LF;
articuIos++;
if (articuIos == 5) articuIos = 0;
}
FF;
}
void Cabecera (void)
{
static int pagina;
register int i;
if (pagina) FF;
pagina++;
fprintf (stdprn, "%-64s Pgina:%3d", "QUIEBRA, S.A. Listado de precios", pagina);

LF;
LF; fprintf (stdprn, "%67s", "COMPONENTES");
LF; fprintf (stdprn, "%75s", "----------------------------");
LF; fprintf (stdprn, " COD %-40s CODIGO CANT PRECIO IMPORTE", "DESCRIPCION");
LF; for (i = 0; i < 75; i++) fprintf (stdprn, "-");
}
., -apJulo M0 EDercicio 9 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <dos.h>
struct IMPRESORA {
unsigned timeout: 1;
unsigned :2;
unsigned error_ES: 1;
unsigned conectada: 1;
unsigned sin_papeI: 1;
unsigned ack: 1;
unsigned Iibre: 1;
};
union IMPR {
char x;
struct IMPRESORA im;
};
void main (void)
{
union REGS ent, saI;
union IMPR int17;
cIrscr ();
puts ("DETERMINACIN DEL ESTADO DE LA IMPRESORA (LPT1:)");
ent.h.ah = 2;
ent.x.dx = 0;
int86 (0x17, &ent, &saI);
int17.x = saI.h.ah;
if (int17.im.timeout) puts ("La impresora no respondi en eI tiempo previsto");
if (int17.im.error_ES) puts ("Error de E/S");
ccl*iii
if (int17.im.conectada) puts ("Impresora seIeccionada");
if (int17.im.sin_papeI) puts ("No hay papeI");
if (int17.im.ack) puts ("Reconocimiento de impresora (Acuse de recibo ACK)");
if (int17.im.Iibre) puts ("Impresora Iibre");
}
.. 0signacin dinmica de memoria
., -apJulo N0 EDercicio 5 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <stdIib.h>
#incIude <aIIoc.h>
struct PILA {
int dato;
struct PILA *enIace;
};
int Menu (void);
int Introducir (int n);
int Sacar (void);
struct PILA *primero;
void main (void)
{
int vaIor, opcion, st;
primero = 0;
whiIe ((opcion = Menu ()) != 3) {
switch (opcion) {
case 1: printf ("\nVaIor a introducir en Ia piIa: ");
scanf ("%d", &vaIor);
if (!Introducir (vaIor)) {
puts ("\nMemoria agotada. PuIse una tecIa ...");
whiIe (!getch ());
}
break;
case 2: vaIor = Sacar ();
if (vaIor < 0) puts ("\nPiIa vaca");
eIse printf ("\nVaIor obtenido: %d", vaIor);
printf ("\nPuIse una tecIa ...");
whiIe (!getch ());
}
}
}
int Menu (void)
{
int n;
cIrscr ();
puts ("PILA DINMICA\n");
ccl*iv
puts ("1. Introducir");
puts ("2. Sacar");
puts ("3. SaIir\n");
do {
n = getch ();
} whiIe (n < '1' || n > '3');
return n - 48;
}
int Introducir (int n)
{
struct PILA *nuevo, *actuaI, *anterior;
nuevo = (struct PILA *) maIIoc (sizeof (struct PILA));
if (!nuevo) return 0;
nuevo -> dato = n;
nuevo -> enIace = 0;
if (!primero) primero = nuevo;
eIse {
actuaI = primero;
whiIe (actuaI) {
anterior = actuaI;
actuaI = anterior -> enIace;
}
anterior -> enIace = nuevo;
}
return 1;
}
int Sacar (void)
{
struct PILA *actuaI, *anterior;
int n;
if (!primero) return -1;
actuaI = primero;
whiIe (actuaI -> enIace) {
anterior = actuaI;
actuaI = anterior -> enIace;
}
n = actuaI -> dato;
if (primero -> enIace) anterior -> enIace = 0;
eIse primero = 0;
free (actuaI);
return n;
}
11. )ic&eros
., -apJulo 580 EDercicio 5 ,.
ccl*v
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
void main (int argc, char *argv[ ])
{
FILE *f;
char caracter;
switch (argc) {
case 1: puts ("FaIta eI nombre deI fichero");
exit (1);
case 2: if (!(f = fopen (argv[1], "wt"))) {
perror (argv[1]);
exit (1);
}
break;
defauIt: puts ("Demasiados parmetros");
exit (1);
}
caracter = getche ();
whiIe (caracter != 26) {
..9Q es el cdi=o A?-@@ de -TRLST
fputc (caracter, f);
if (ferror (f)) {
printf ("\nError de escritura en %s", argv[1]);
exit (1);
}
if (caracter == 13) {
putch ('\n');
fputc ('\12', f);
}
caracter = getche ();
}
fcIose (f);
}
., -apJulo 580 EDercicio 9
?e uili(a la funcin r#nam# 1renom/ra ficheros2 7 la funcin r#mo/# 1/orra ficheros2 ,.
#incIude <stdio.h>
#incIude <process.h>
#incIude <string.h>
#define CTRLZ 26
void main (int argc, char *argv[ ])
{
FILE *fe, *fs;
char reg[81], tmp[100], char *p;
int i, cambios = 0;
switch (argc) {
case 1:
case 2:
case 3: puts ("FaIta aIgn parmetro");
exit (1);
ccl*vi
case 4: if (!(fe = fopen (argv[1], "rt"))) {
perror (argv[1]);
exit (1);
}
break;
defauIt: puts ("Demasiados parmetros");
exit (1);
}
if (!(fs = fopen ("tmp.tmp", "wt"))) {
puts ("Error aI crear eI fichero temporaI");
exit (1);
}
fgets (reg, 80, fe);
whiIe (!feof (fe)) {
p = strstr (reg, argv[2]);
whiIe (p) {
cambios++;
for (i = 0; i < p - reg; i++) tmp[i] = reg[i];
tmp[i] = 0;
strcat (tmp, argv[3]);
strcat (tmp, p + strIen (argv[2]));
strcpy (reg, tmp);
p = strstr (reg, argv[2]);
}
fputs (reg, fs);
fgets (reg, 80, fe);
}
fcIose (fe);
fcIose (fs);
if (remove (argv[1]) == -1) puts ("No se pueden aImacenar Ios cambios");
eIse if(rename ("tmp.tmp", argv[1])) puts ("Cambios se han aImacenado en
TMP.TMP");
printf ("\nCambios: %d", cambios);
}
., -apJulo 580 EDercicio : ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
#incIude <string.h>
#define LF fprintf (stdprn, "\n\r");
#define FF fprintf (stdprn, "\f");
struct REG {
char nom[41];
fIoat aIt;
char pro[26];
};
void Cabecera (char *, fIoat);
char *Intro (int, int, int, char *);
void main (void)
{
FILE *f;
ccl*vii
struct REG aI;
char provincia[26];
char nombre[500][41];
fIoat aItura[500], totaI = 0, media;
register int i;
int Iinea = 0, contador = 0;
if (!(f = fopen ("B:ALTOS.DAT", "rb"))) {
perror ("ALTOS.DAT");
exit (1);
}
printf ("\nProvincia: ");
Intro (wherey (), wherex (), 25, provincia);
strupr (provincia);
fread (&aI, sizeof (aI), 1, f);
whiIe (!feof (f)) {
if (!strcmp (provincia, aI.pro)) {
strcpy (nombre[contador], aI.nom);
aItura[contador] = aI.aIt;
contador++;
totaI += aI.aIt;
}
fread (&aI, sizeof (aI), 1, f);
}
if (contador) {
media = totaI / contador;
for (i = 0; i < contador; i++) {
if (aItura[i] > media) {
if (!Iinea) Cabecera (provincia, media);
LF; fprintf (stdprn, "%-40s %4.2f", nombre[i], aItura[i]);
Iinea++;
if (Iinea == 50) Iinea = 0;
}
}
FF; }
eIse puts ("\nNo hay datos de esta provincia");
fcIose (f);
}
void Cabecera (char *prov, fIoat med)
{
static int pagina;
if (pagina) FF;
pagina++;
LF; fprintf (stdprn, "Provincia: %s", prov);
LF; fprintf (stdprn, "AItura Media: %4.2f", med);
LF;
LF; fprintf (stdprn, "Nombre
AItura");
LF; fprintf (stdprn, "
");
}
ccl*viii
., -apJulo 580 EDercicio L ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
#incIude <stdIib.h>
#incIude <dos.h>
#define LF fprintf (stdprn, "\n\r")
#define FF fprintf (stdprn, "\f")
struct ARTIC {
char cod[7];
char des[31];
unsigned exi;
unsigned pco;
unsigned pvp;
char pro[5];
};
char *Intro (int, int, int, char *);
int Strdigit (char *);
void Cabecera (void);
void Linea (void);
void Fecha ();
char fec[20];
void main (void)
{
FILE *fart, *fnp;
struct ARTIC ar;
char nompro[41];
char articuIo[7], arini[7], arfin[7];
int Iinea = 0, sw = 0;
Iong nreg;
unsigned Iong coste, venta, difer, t_coste = 0, t_venta = 0;
if (!(fart = fopen ("B:ARTIC.DAT", "rb"))) {
perror ("ARTIC.DAT");
exit (1);
}
if (!(fnp = fopen ("B:NOMPRO.DAT", "rb"))) {
perror ("NOMPRO.DAT");
exit (1);
}
Fecha ();
do {
do {
printf ("\nArtcuIo IniciaI: ");
Intro (wherey (), wherex (), 6, articuIo);
} whiIe (!Strdigit (articuIo));
sprintf (arini, "%06d", atoi (articuIo));
do {
printf ("\nArtcuIo FinaI: ");
Intro (wherey (), wherex (), 6, articuIo);
} whiIe (!Strdigit (articuIo));
sprintf (arfin, "%06d", atoi (articuIo));
} whiIe (strcmp (arini, arfin) > 0);
ccl*i*
do {
fread (&ar, sizeof (ar), 1, fart);
} whiIe (!feof (fart) && strcmp (ar.cod, arini) < 0);
whiIe (!feof (fart) && strcmp (ar.cod, arfin) <= 0) {
if (!Iinea) Cabecera ();
nreg = (atoi (ar.pro) - 1) * sizeof (nompro);
fseek (fnp, nreg, SEEK_SET);
fread (&nompro, sizeof (nompro), 1, fnp);
if (ferror (fnp)) strcpy (nompro, "Desconocido");
coste = (unsigned Iong) ar.exi * ar.pco;
venta = (unsigned Iong) ar.exi * ar.pvp;
difer = venta - coste;
t_coste += coste;
t_venta += venta;
LF; fprintf (stdprn, "%6s-%-30s %5u %5u %9Iu %5u %9Iu %9Iu %5s-%-
40s", /
ar.cod, ar.des, ar.exi, ar.pco, coste, ar.pvp, venta, difer, ar.pro,
nompro);
sw = 1;
Iinea++;
if (Iinea == 50) Iinea = 0;

fread (&ar, sizeof (ar), 1, fart);
}
if (sw) {
LF; fprintf (stdprn, "%85s", "--------- --------- ---------");
difer = t_venta - t_coste;
LF; fprintf (stdprn, "%49s %9Iu %9Iu %9Iu", "TotaIes .....", t_coste, t_venta,
difer);
FF;
}
fcIose (fart);
fcIose (fnp);
}
void Cabecera (void)
{
static int pagina;
if (pagina) FF;
pagina++;
LF; fprintf (stdprn, "%-84s Fecha: %-18s Pgina:%3d",
"INVENTARIO /
VALORADO A PRECIO DE COSTE Y DE
VENTA", fec, pagina);
LF;
LF; Linea ();
LF; fprintf (stdprn, "%-37s Exist VaIor a P.Coste VaIor a P.Venta
Diferenc. /
Proveedor", "ArtcuIo");
LF; Linea ();
}
ccl**
void Linea (void)
{
register int i;
for (i = 0; i < 132; i++) fprintf (stdprn, "=");
}
void Fecha (void)
{
char meses[12][11] = { "Enero", "Febrero", "Marzo", "AbriI", "Mayo",
"Junio",
"JuIio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };
struct date f;
getdate (&f);
sprintf (fec, "%d-%s-%d", f.da_day, meses[f.da_mon - 1], f.da_year);
}
11. )ic&eros inde(ados2 la interfase 3trie4e
.,-apJulo 550 EDercicio 5
?e uili(an las funciones In'ro 7 S'rdi-i' diseIadas en el -apJulo Q
?e supone *ue se compilan por separado 7 se enla(an poseriormene ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <string.h>
#incIude <process.h>
#incIude <c:\btr\turcbtrv.c>
#define ABRIR 0
#define CERRAR 1
#define IGUAL 5
#define SIGUIENTE 6
#define MAY_IGUAL 9
#define AL 0
#define GR 1
#define NF 2
#define LF fprintf (stdprn, "\n\r")
#define FF fprintf (stdprn, "\f")
struct REG_AL {
char gru[6];
char nom[31];
int faI[12][8];
};
struct REG_GR {
char gru[6];
char asg[8][6];
};
union REG_TOT {
struct REG_AL aI;
struct REG_GR gr;
};
char bIoque[NF][128];
union REG_TOT area[NF];
ccl**i
int Iongitud[NF] = { sizeof (struct REG_AL), sizeof (struct REG_GR) };
char cIave[NF][37];
int ncIave[NF] = { 1, 0 };
char fichero[NF][13] = { "ALUMNOS.BTR", "GRUPO.BTR" };
int faItasig[8];
char *Intro (int, int, int, char *);
int Strdigit (char *);
int Btr (int, int);
void BtrError (int, int, int);
void Cerrar (int);
void Cabecera (char *, char *);
void DetaIIe (int);
void Pie (void);
void Linea (void);
void main (void)
{
int i, p, nmes, st, impresion = 0, Iinea = 0;
char grupo[6], mes[3];
char grupos[6][6] = { "1FP2B", "2FP2A", "2FP2B", "2FP2C", "3FP2A", "3FP2B" };
char meses[12][12] = { "ENERO", "FEBRERO", "MARZO", "ABRIL", "MAYO", "JUNIO",
"JULIO", "AGOSTO", "SEPTIEMBRE", "OCTUBRE", "NOVIEMBRE",
"DICIEMBRE" };
for (i = 0; i < NF; i++) {
strcpy (cIave[i], fichero[i]);
st = Btr (ABRIR, i);
if (st) {
BtrError (i, st, ABRIR);
Cerrar (i);
exit (1);
}
}
cIrscr ();
do {
printf ("\nGRUPOS: 1FP2B - 2FP2A - 2FP2B - 2FP2C - 3FP2A - 3FP2B ");
printf ("\nSeIeccione grupo: ");
Intro (wherey (), wherex (), 5, grupo);
strupr (grupo);
for (i = 0; i < 6; i++) {
p = strcmp (grupo, grupos[i]);
if (!p) break;
}
} whiIe (p);
do {
do {
printf ("\nMes: ");
Intro (wherey (), wherex (), 2, mes);
} whiIe (!Strdigit (mes));
nmes = atoi (mes);
} whiIe (nmes < 0 || nmes > 12);
printf (" - %s", meses[nmes - 1]);
strcpy (cIave[GR], grupo);
st = Btr (IGUAL, GR);
if (st) {
printf ("\nNo hay datos de asignaturas");
whiIe (!getch ());
ccl**ii
for (i = 0; i < 6; i++) sprintf (area[GR].gr.asg[i], "ASG-%d", i + 1);
}
for (i = 0; i < 8; i++) faItasig[i] = 0;
sprintf (cIave[AL], "%s%c%30s", grupo, 0, " ");
st = Btr (MAY_IGUAL, AL);
whiIe (!st && !strcmp (grupo, area[AL].aI.gru)) {
impresion = 1;
if (!Iinea) Cabecera (grupo, meses[nmes - 1]);
DetaIIe (nmes);
Iinea++;
if (Iinea > 55) Iinea = 0;
st = Btr (SIGUIENTE, AL);
if (st) st += 1000;
}
if (st && st != 9 && st < 1000) BtrError (AL, st, MAY_IGUAL);
eIse if (st && st != 1009) BtrError (AL, st - 1000, SIGUIENTE);
if (impresion) Pie ();
Cerrar (NF);
}
.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, F U N - @ O N E ? ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.
.. Uace las llamadas a Orie&e
int Btr (int op, int nf)
{
return BTRV (op, bIoque[nf], &area[nf], &Iongitud[nf], cIave[nf], ncIave[nf]);
}
.. Muesra mensaDes de error Orie&e
void BtrError (int nf, int st, int op)
{
printf ("\n%s: Error %d - Operacin %d", fichero[nf], st, op);
whiIe (!getch ());
}
.. -ierra ficheros
void Cerrar (int nf)
{
int i, st;
for (i = 0; i < nf; i++) {
st = Btr (CERRAR, i);
if (st) BtrError (i, st, CERRAR);
}
}
.. @mprime la ca/ecera del lisado
void Cabecera (char *gr, char *month)
{
static int pagina;
int i;
if (pagina) FF;
pagina++;
LF; fprintf (stdprn, "CAPTULO 12. Ejercicio 1. Pgina:%2d", pagina);
LF; fprintf (stdprn, "
");
LF;
LF; fprintf (stdprn, "GRUPO: %s", gr);
ccl**iii
LF; fprintf (stdprn, "FALTAS DEL MES DE %s", month);
LF;
LF; fprintf (stdprn, "%-30s", "ApeIIidos y nombre");
for (i = 0; i < 8; i++) fprintf (stdprn, "%6s", area[GR].gr.asg[i]);
fprintf (stdprn, " TOTAL");
LF; Linea ();
}
.. @mprime la lJnea de dealle
void DetaIIe (int n)
{
int i, faItaIum = 0;
LF; fprintf (stdprn, "%-30s", area[AL].aI.nom);
for (i = 0; i < 8; i++) {
fprintf (stdprn, "%5d ", area[AL].aI.faI[n - 1][i]);
faItaIum += area[AL].aI.faI[n - 1][i];
faItasig[i] += area[AL].aI.faI[n - 1][i];
}
fprintf (stdprn, "%5d", faItaIum);
}
.. @mprime el pie del lisado
void Pie (void)
{
int i, totaI = 0;
LF; Linea ();
LF; fprintf (stdprn, "%30s", "TOTALES:");
for (i = 0; i < 8; i++) {
fprintf (stdprn, "%5d ", faItasig[i]);
totaI += faItasig[i];
}
fprintf (stdprn, "%5d", totaI);
FF;
}
.. @mprime una lJnea con el carBcer 4
void Linea (void)
{
int i;
for (i = 0; i < 84; i++) fprintf (stdprn, "=");
}
.,-apJulo 550 EDercicio 9 ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
#incIude <string.h>
#incIude <dos.h>
#incIude <c:\btr\turcbtrv.c>
#define ABRIR 0
#define CERRAR 1
#define IGUAL 5
#define SIGUIENTE 6
#define MAY_IGUAL 9
ccl**iv
#define PR 0
#define LI 1
#define AL 2
#define NF 3
#define LF fprintf (stdprn, "\n\r")
#define FF fprintf (stdprn, "\f")
struct REG_PR {
char fec[9];
char isbn[11];
char exp[6];
char dev;
};
struct REG_LI {
char isbn[11];
char tit[51];
char aut[31];
char edi[31];
};
struct REG_AL {
char exp[6];
char nom[31];
char gru[11];
};
union REG_TOT {
struct REG_PR pr;
struct REG_LI Ii;
struct REG_AL aI;
};
char bIoque[NF][128];
union REG_TOT area[NF];
int Iongitud[NF] = {sizeof (struct REG_PR), sizeof (struct REG_LI), sizeof (struct
REG_AL) };
char cIave[NF][13];
int ncIave[NF] = { 1, 0, 0 };
char fichero[NF][13] = { "PRESTAMO.BTR", "LIBROS.BTR", "ALUMNOS.BTR" };
int ndia, nmes, nanyo;
int Btr (int, int);
void BtrError (int, int, int);
void Cerrar (int);
void Fecha (char *);
void FechaTope (char *, char *);
void DatosLibro (void);
void DatosAIumno (void);
void Imprimir (void);
void Formatea (char *);
void Linea (int);
void main (void)
{
int st, i, Iinea = 0, impresion = 0;
char tope[9], hoy[9];
for (i = 0; i < NF; i++) {
strcpy (cIave[i], fichero[i]);
st = Btr (ABRIR, i);
ccl**v
if (st) {
BtrError (i, st, ABRIR);
Cerrar (i);
exit (1);
}
}
Fecha (hoy);
cIave[PR][0] = 'N';
st = Btr (MAY_IGUAL, PR);
whiIe (!st && area[PR].pr.dev == 'N') {
FechaTope (area[PR].pr.fec, tope);
if (strcmp (tope, hoy) < 0) {
DatosLibro ();
DatosAIumno ();
Imprimir ();
Iinea++;
if (Iinea > 5) {
Iinea = 0;
FF;
}
}
st = Btr (SIGUIENTE, PR);
if (st) st += 1000;
}
switch (st) {
case 0:
case 9:
case 1009: break;
defauIt: if (st > 1000) BtrError (PR, st - 1000, SIGUIENTE);
eIse BtrError (PR, st, MAY_IGUAL);
}
if (!impresion) FF;
eIse printf ("\nNo hay devoIuciones pendientes");
Cerrar (NF);
}
.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, F U N - @ O N E ? ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.
.. Uace las llamadas a Orie&e
int Btr (int op, int nf)
{
return BTRV (op, bIoque[nf], &area[nf], &Iongitud[nf], cIave[nf], ncIave[nf]);
}
.. Muesra los mensaDes de error Orie&e
void BtrError (int nf, int st, int op)
{
printf ("\n%s: Error %d - Operacin %d", fichero[nf], st, op);
whiIe (!getch ());
}
.. -ierra ficheros
void Cerrar (int nf)
{
int i, st;
for (i = 0; i < nf; i++) {
st = Btr (CERRAR, i);
if (st) BtrError (i, st, CERRAR);
ccl**vi
}
}
.. O/iene la fecha del dJa en formao AAAAMM++
void Fecha (char *cad)
{
struct date f;
getdate (&f);
sprintf (cad, "%d%02d%02d", f.da_year, f.da_mon, f.da_day);
}
.. -alcula la fecha ope hasa la *ue se puede ener el li/ro presado
void FechaTope (char *desde, char *hasta)
{
int dia, mes, anyo;
char xdia[3], xmes[3], xanyo[5];
int dias[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
xmes[2] = xanyo[4] = 0;
strcpy (xdia, desde + 6);
strncpy (xmes, desde +4, 2);
strncpy (xanyo, desde, 4);
ndia = dia = atoi (xdia);
nmes = mes = atoi (xmes);
nanyo = anyo = atoi (xanyo);
dia += 7;
if (dia > dias[mes - 1]) {
dia -= dias[mes - 1];
mes++;
if (mes > 12) {
mes = 1;
anyo++;
}
}
sprintf (hasta, "%d%02d%02d", anyo, mes, dia);
}
.. O/iene los daos del fichero L@ORO?0OTR
void DatosLibro (void)
{
int st;
strcpy (cIave[LI], area[PR].pr.isbn);
st = Btr (IGUAL, LI);
if (st) {
strcpy (area[LI].Ii.tit, "Sin datos");
strcpy (area[LI].Ii.aut, "Sin datos");
strcpy (area[LI].Ii.edi, "Sin datos");
}
}
.. O/iene los daos del fichero ALUMNO?0OTR
void DatosAIumno (void)
{
int st;
strcpy (cIave[AL], area[PR].pr.exp);
st = Btr (IGUAL, AL);
if (st) {
strcpy (area[AL].aI.nom, "Sin datos");
ccl**vii
strcpy (area[AL].aI.gru, "Sin datos");
}
}
.. @mprime una ficha
void Imprimir (void)
{
char fecformat[30];
Formatea (fecformat);
LF; Linea ('=');
LF; fprintf (stdprn, "ALUMNO: %-30s GRUPO: %s", area[AL].aI.nom, area[AL].aI.gru);
LF; Linea ('-');
LF; fprintf (stdprn, "TTULO: %s", area[LI].Ii.tit);
LF; fprintf (stdprn, "AUTOR: %s", area[LI].Ii.aut);
LF; fprintf (stdprn, "EDITORIAL: %s", area[LI].Ii.edi);
LF; Linea ('-');
LF; fprintf (stdprn, "FECHA DEL PRSTAMO: %s", fecformat);
LF;
}
.. Formaea la fecha del prVsamo a ++ de MMMMMMMMMM de AAAA
void Formatea (char *cad)
{
char meses[12][12] = { "Enero", "Febrero", "Marzo", "AbriI", "Mayo", "Junio",
"JuIio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" };
sprintf (cad, "%d de %s de %d", ndia, meses[nmes - 1], nanyo);
}
.. @mprime una lJnea
void Linea (int trazo)
{
int i;
for (i = 0; i < 56; i++) fprintf (stdprn, "%c", trazo);
}
., -apJulo 550 EDercicio : ,.
#incIude <stdio.h>
#incIude <conio.h>
#incIude <process.h>
#incIude <string.h>
#incIude <c:\btr\turcbtrv.c>
#define ABRIR 0
#define CERRAR 1
#define ACTUALIZAR 3
#define BORRAR 4
#define IGUAL 5
struct REG_MV {
char aIm[3];
char art[7];
unsigned can;
char ope;
};
struct REG_AR {
ccl**viii
char aIm[3];
char art[7];
char des[41];
int exi;
unsigned min;
unsigned opt;
unsigned pvp;
unsigned pco;
};
char bIoque[128];
struct REG_AR ar;
int Iongitud = sizeof (ar);
char cIave[13];
int Btr (int);
void BtrError (int, int);
void main (void)
{
FILE *MV;
struct REG_MV mv;
int st, op;
MV = fopen ("MOVIM.TMP", "rb");
if (!MV) {
perror ("MOVIM.TMP");
exit (1);
}
strcpy (cIave, "ARTIC.BTR");
st = Btr (ABRIR);
if (st) {
BtrError (st, ABRIR);
exit (1);
}
cIrscr ();
fread (&mv, sizeof (mv), 1, MV);
whiIe (!feof (MV) && !ferror (MV)) {
printf ("\n%s %s %u %c", mv.aIm, mv.art, mv.can, mv.ope);
strcpy (cIave, mv.aIm);
strcpy (cIave + 3, mv.art);
st = Btr (IGUAL);
if (st) BtrError (st, IGUAL);
eIse {
switch (mv.ope) {
case 'E': ar.exi += mv.can;
op = ACTUALIZAR;
break;
case 'S': ar.exi -= mv.can;
op = ACTUALIZAR;
break;
case 'B': op = BORRAR;
}
st = Btr (op);
if (st) BtrError (st, op);
eIse printf (" Ok");
}
fread (&mv, sizeof (mv), 1, MV);
}
ccl**i*
if (ferror (MV)) perror ("MOVIM.TMP");
fcIose (MV);
st = Btr (CERRAR);
if (st) BtrError (st, CERRAR);
}
/************************************** F U N C I O N E S **************************************/
.. Efec>a las operaciones Orie&e
int Btr (int op)
{
return BTRV (op, bIoque, &ar, &Iongitud, cIave, 0);
}
.. Muesra los mensaDes de error Orie&e
void BtrError (int st, int op)
{
printf ("\nARTIC.BTR: Error %d - Operacin %d", st, op);
whiIe (!getch ());
}
ccl***

Vous aimerez peut-être aussi