Está en la página 1de 240

CURSO

DE
LENGUAJ E " C"
Angel Salas
Centr o de Clculo
Univer sidad de Zar agoza
Ener o - 1991
SALAS, Angel
Curso de Lenguaje "C" / Angel Salas . - Zaragoza :
Secretariado de Publicaciones de la Universidad ,
1991 . - 238 p. ( pag. var. ) ; 30 cm . - (C.C.U.Z. ; 28)
ISBN 84-7733-232-0
CURSO DE LENGUAJ E " C"
Angel Salas
Centro de Clculo
de la Universidad de Zaragoza, 1991.
Edificio de Matemticas
Ciudad Universitaria
50009 - ZARAGOZA
Tfno: 354100
Edita: Secretariado de Publicaciones
de la Universidad de Zaragoza
Depsito Legal: Z-416-91
I.S.B.N.: 84-7733-232-0
PRESENTACION
Esta publicacin recoge la documentacin que se entrega en el Curso de Lenguaje "C"
impartido por el Centro de Clculo de la Universidad de Zaragoza.
Contiene una reproduccin de todas las transparencias que usa el profesor en sus
exposiciones.
No es un manual de referencia, sino un material didctico dirigido a facilitar la
comprensin de los conceptos, elementos y reglas de la construccin de programas con
lenguaje "C".
En el curso, se explica el lenguaje desde el principio, en trminos que presuponen
conocimientos bsicos sobre la progamacin de computadores. Se estudian, presentando
abundantes ejemplos, todos los aspectos del lenguaje: tipos de datos, clases de
almacenamiento, operadores, expresiones, sentencias de control, funciones, bibliotecas
estndar.
Hay una Introduccin donde se exponen algunos datos histricos y caractersticas
generales del lenguaje.
En la leccin 1, se presenta un panorama general de la estructura de un programa
escrito en C sin profundizar, con el fin de adquirir desde el principio familiaridad con
algunos aspectos importantes. Se habla del formato de escritura, de los comentarios, de las
sentencias para el preprocesador, de la definicin de funciones, de las reglas de alcance, de
las expresiones, de la sentencias "if-else" y "for", de las funciones "scanf" y "printf".
En la leccin 2 se tratan los elementos que forman el programa desde el punto de
vista lxico: caracteres, identificadores, palabras reservadas, constantes, cadenas,
operadores, separadores.
La leccin 3 es muy breve. Se trata nicamente el operador de asignacin para explicar
la semntica de las expresiones de asignacin.
En la leccin 4 se presentan los tipos de datos predefinidos sin entrar a fondo.
Tambin se trata de las clases de almacenamiento y de la inicializacin de variables en las
declaraciones.
En la leccin 5 se estudian los tipos fundamentales a fondo y los operadores ms
afines.
La leccin 6 se dedica a mostrar todas las sentencias de control.
La leccin 7 est dedicada a las funciones. Se estudian todos los aspectos relacionados
con la definicin y uso de las funciones. Se explican las reglas de alcance, las clases de
almacenamiento.
En la leccin 8 se muestra un panorama general de los tipos estructurados
predefinidos sin entrar a fondo.
En la leccin 9 se estudian a fondo el tipo "array", las cadenas y la relacin con los
punteros. Se presentan algunas funciones de biblioteca para manejar cadenas de caracteres.
La leccin 10 se dedica explicar el tipo "struct", los campos de "bits", las uniones y
los tipos definidos por el usuario.
En la leccin 11 se presentan algunas funciones de biblioteca para leer y escribir en
ficheros: abrir y cerrar fichero, posicionar, leer y escribir un carcter, leer y escribir una
cadena, leer y escribir en binario, leer y escribir con formato.
En la leccin 12 se explican las bases para construir y manejar estructuras de datos
dinmicas. Se estudia el caso de una lista encadenada con disciplina FIFO.
C.00.01
CONTENIDO
INTRODUCCION
ESTRUCTURA Y FORMATO DEL PROGRAMA.
PANORAMA GENERAL.
ELEMENTOS LEXICOS.
EXPRESIONES Y SENTENCIAS. EXPRESIONES DE
ASIGNACION.
LOS TIPOS DE DATOS. VISION GENERAL.
LOS TIPOS DE DATOS FUNDAMENTALES.
LAS SENTENCIAS DE CONTROL.
LAS FUNCIONES.
LOS TIPOS DE DATOS ESTRUCTURADOS. VISION
GENERAL.
" ARRAYS" , CADENAS Y PUNTEROS.
ESTRUCTURAS, UNIONES Y TIPOS DEFINIDOS POR
EL USUARIO.
FUNCIONES PARA MANEJ O DE FICHEROS.
ESTRUCTURAS DINAMICAS DE DATOS.
C.00.02
El lenguaje C fue diseado por Dennis Ritchie, de los Labor ator ios Bell,
y se instal en un PDP-11 en 1972.
Se dise par a ser el lenguaje de los sistemas oper ativos UNIX.
Se cr e par a super ar las limitaciones del lenguaje B, utilizado por Ken
Thompson par a pr oducir la ver sin or iginal de UNIX en 1970.
El lenguaje B se bas en BCPL, lenguaje sin tipos desar r ollado por
Mar tin Richar ds, en 1967, par a pr ogr amacin de sistemas.
Su definicin apar eci en 1978:
apndice " C Refer ence Manual"
del libr o " The C pr ogr amming Language"
de Br ian W. Ker nighan y Dennis M. Ritchie
(Ed. Pr entice-Hall)
En 1983, se public otr o estndar :
" The C Pr ogr amming Language-Refer ence Manual"
(Lab.Bell)
escr ito por Dennis M. Ritchie
C.00.03
ES UN LENGUAJ E DE NIVEL MEDIO
Combina elementos de lenguajes de alto nivel (tipos, bloques, ...) con la
funcionalidad de los ensamblador es.
Per mite manejar los elementos tpicos de la pr ogr amacin de sistemas:
bits
bytes
dir ecciones
NO ESTA FUERTEMENTE ORIENTADO A TIPOS
Tiene cinco tipos de datos bsicos, tipos estr uctur ados y admite
definicin de tipos por el usuar io.
Per o per mite casi todas las conver siones (p.ej. se pueden mezclar los tipos
" int" y " char " en casi todas las expr esiones).
No hace compr obaciones de er r or en tiempo de ejecucin
(desbor damiento de ar r ays, ...)
" Deja hacer " al pr ogr amador .
C.00.04
ES UN LENGUAJ E SEMI-ESTRUCTURADO
No es completamente estr uctur ado en bloques por que no per mite
declar ar pr ocedimientos o funciones dentr o de otr os pr ocedimientos o
funciones.
Per o tiene algunas car acter sticas pr opias de los lenguajes estr uctur ados:
Dos for mas de estr uctur acin del cdigo:
Con funciones independientes
Con bloques
Dispone de las sentencias tpicas par a constr uir
estr uctur as de contr ol:
while
do-while
for
C.00.05
ES UN LENGUAJ E PARA PROGRAMADORES
Algunos otr os lenguajes estn hechos par a no-pr ogr amador es (BASIC,
COBOL, ...)
El lenguaje C est influenciado, diseado y pr obado por pr ogr amador es
pr ofesionales.
Pr opor ciona:
Una visin pr xima a la mquina
Pocas r estr icciones
Pocas pegas
Conjunto r educido de palabr as clave
Estr uctur acin en bloques
Funciones independientes
Recur sos par a el encapsulamiento de datos
Per mite alcanzar casi la eficiencia del cdigo ensamblador , junto con la
estr uctur acin pr opia de lenguajes como ALGOL, MODULA-2.
Se dise par a la pr ogr amacin de sistemas
Los pr ogr amas son muy tr anspor tables
Actualmente se usa par a otr os pr opsitos
C.00.06
BIBLIOGRAFIA
"The C programming language"
Brian W Kernighan y Dennis M. Ritchie
Ed. Prentice-Hall, segunda edicin, 1988.
"Lenguaje C. Introduccin a la programacin"
Al Kelley e Ira Pohl
Ed. Addison-Wesley, 1987 (edicin original, en 1984).
"C estndar. Gua de referencia para programadores"
P.J. Plauger y Jim Brodie
Ed. Anaya Multimedia, 1990 (primera edicin en 1989)
"C. Manual de referencia. Segunda edicin"
Herbert Schildt
Ed. McGraw-Hill, 1990.
Manual de Referencia de la implementacin
que se use.
C.01.00
- 1 -
ESTRUCTURA Y FORMATO DEL PROGRAMA.
PANORAMA GENERAL.
El for mato de escr itur a
Ejemplo de un pr ogr ama completo
Los comentar ios
Las sentencias par a el pr e-pr ocesador
Las funciones. Definicin de una funcin
Las declar aciones
Reglas de alcance
Las expr esiones
Las sentencias
La sentencia " if-else"
La sentencia " for "
La funcin " pr intf"
La funcin " scanf"
C.01.01
#include <stdio.h>
main ( )
{
saludo( );
primer_mensaje( );
}
saludo()
{
printf ("Buenos dias\n");
}
primer_mensaje()
{
printf("Un programa esta formado ");
printf("por funciones\n");
}
C.01.02
Los pr ogr amas se constr uyen con:
Comentar ios.
Or denes par a el pr epr ocesador
de macr os.
Definiciones de funciones.
Expr esiones for madas con constantes, var iables,
funciones y oper ador es.
Sentencias.
C.01.03
EL FORMATO DE ESCRITURA ES MUY FLEXIBLE:
Las constantes, identificadores y palabras clave deben separarse; pero
ello puede hacerse con :
- espacios en blanco
- marcas de tabulador
- marcas de salto de linea
- comentarios
/*
ej1.c
Indica el menor de dos enteros leidos
*/
#include <stdio.h>
void main ( )
{
int n1, n2, menor (int, int);
printf ("Introducir dos enteros:\n");
scanf ("%d%d", &n1, &n2);
if ( n1 == n2 )
printf ("Son iguales \n");
else
printf ("El menor es: %d\n",menor(n1,n2));
}
int menor (int a, int b)
{
if ( a < b ) return (a );
else return ( b );
}
C.01.04
LOS COMENTARIOS
Son lineas que ignor a el compilador per o sir ven par a documentar los
pr ogr amas:
Empiezan con: /*
ter minan con: */
pueden abar car var ias lineas
no se pueden anidar
/*
ej1.c
Indica el menor de dos enter os leidos
*/
...
...
...
scanf(" %d%d" , &n1, &n2); /* aqui se leen dos
valor es enter os */
...
...
C.01.05
LAS SENTENCIAS PARA EL PREPROCESADOR
Son r denes que el pr epr ocesador inter pr eta antes de que el cdigo
fuente sea compilado.
El pr epr ocesador pr oduce un pr ogr ama escr ito en C que es lo que se
compila despus.
Deben empezar con el smbolo " # " en la
pr imer a columna.
# define PI 3.1416
# define EQ ==
----------
# define cuadr ado(x) ( (x) * (x) )
----------
# include <stdio.h>
# include <math.h>
----------
# define PRUEBA 1
...
...
# if PRUEBA
pr intf(" pr ueba: x = %d\n" , x);
# endif
----------
# ifdef UNO
...
...
# else
...
...
# endif
( cc -DUNO fn.c )
----------
# ifndef
----------
C.01.06
LAS FUNCIONES
Un programa esta formado por funciones.
No se pueden definir anidadas.
Desde una funcin se puede llamar a cualquier otra.
Est permitida la recursividad.
Si no se indica otro tipo, las funciones son de tipo "int" por
defecto
El mecanismo de paso es por valor.
DEVUELVEN UN VALOR.
La funcin "main"
Todo programa debe contener una funcin llamada "main".
Es la invocada desde el sistema operativo cuando comienza la
ejecucin del programa.
Tambin devuelve un valor al medio de llamada.
C.01.07
DEFINICION DE UNA FUNCION
Encabezamiento . . . . . . . . . . . . tipo nombr e (p1, p2, p3)
Declar acin de par metr os . . . . . tipo p1, p2, p3;
{
Cuer po con: Declar aciones . . . . . . tipo v1, v2, v3;
Sentencias . . . . . . sentencia
...
sentencia
}
int menor (a, b)
int a, b;
{
if ( a<b ) r etur n( a );
else r etur n( b );
}
C.01.08
/*
ej1.c
Indica el menor de dos enteros leidos
*/
#include <stdio.h>
main ( )
{
int n1, n2, menor ( );
printf("Introducir dos enteros: \n");
scanf("%d%d", &n1, &n2);
if ( n1 == n2 )
printf("Son iguales \n");
else
printf("El menor es: %d\n", menor (n1, n2));
}
int menor ( a, b )
int a, b;
{
if ( a < b ) return ( a );
else return ( b );
}
COMENTARIOS
SENTENCIA PARA
EL PRE-PROCESADOR
DEFINICION DE LA
FUNCION "main"
Encabezamiento. No hay
parmetros
Declaraciones de objetos
locales
Cuerpo de la funcin
Sentencias
DEFINICION DE LA
FUNCION "menor"
Encabezamiento. Los
parmetros son "a" y "b"
Declaracin de los parmetros
Cuerpo de la funcin.
No contiene declaraciones
C.01.09
DEFINICIONES DE DATOS. DECLARACIONES
Todas las var iables deben declar ar se antes de usuar las:
Indicar el tipo de datos al que per tenece.
Ello deter mina : Su r epr esentacin en memor ia.
El conjunto de valor es posibles.
Las oper aciones per mitidas.
La for ma de r ealizar las oper aciones.
Tambin se puede indicar :
La clase de localizacin en memor ia.
El mbito de existencia.
Un valor inicial.
El usuar io puede definir tipos nuevos, combinando tipos pr edefinidos
per o...
C no est or ientado a los tipos
estr ictamente
REGLAS DE ALCANCE
Los objetos declar ados fuer a de la funcin son globales.
Al pr incipio de cualquier bloque ( pr oposiciones entr e { y } )
se pueden poner declar aciones.
Los objetos slo son conocidos dentr o del bloque en que
han sido declar ados, y en los bloques anidados dentr o.
C.01.10
Ejemplos de declar aciones
int n, m, *p, v[100];
float r , a[10][10], *pf[100];
char c, *s, lin[80];
float super ficie();
str uct naipe {
int valor ;
char palo;
} car ta ;
enum color es{ r ojo, azul,
amar illo } color ;
typedef str uct {
float r eal;
float imaginar ia;
} complejo;
complejo c1, c2;
C.01.11
Reglas de alcance
int g; /* " g" es var iable global */
main( )
{
int a, b;
. . .
. . .
{
float b, x, y;
. . . /* se conoce a " int a" , per o no
. . . a " int b" , que ha quedado
enmascar ada. */
}
{
unsigned a;
char c, d;
. . . /* se conoce a " int b" , per o no a
. . . " int a" .
No se conoce a " x" ni a " y" */
}
...
... /* se conoce a " int a" y a " int b" .
... No se conoce a " x" , " y" , " c" */
...
}
La var iable " g" es conocida en todos los bloques.
C.01.12
EXPRESIONES
Una expr esion se for ma combinando constantes, var iables, oper ador es y
llamadas a funciones.
s = s + i
n == 0
++i
Una expr esin r epr esenta un valor que es el r esultado de r ealizar las
oper aciones indicadas siguiendo las r eglas de evaluacin establecidas en
el lenguaje.
Con expr esiones se for man sentencias, con
sentencias se for man funciones y con funciones se
constr uye un pr ogr ama completo.
Algunos oper ador es
De r elacin: menor que: < Ar itmticos: suma: +
mayor que: > resta: -
menor o igual que: <= multiplicacin: *
mayor o igual que: >= divisin: /
resto divisin entera: %
De igualdad: igual a: == (unario) incremento: ++
distinto de: != (unario) decremento: --
asignacin: =
Lgicos: (unario) negacin: !
y (AND) lgico: &&
o (OR) lgico: | |
C.01.13
SENTENCIAS
Una sentencia se for ma con expr esiones:
Puede contener una, var ias o ninguna
expr esin
Un bloque empieza con " { " y ter mina con " } " , pudiendo contener
cualquier nmer o de sentencias y declar aciones.
Todas las sentencias, excepto los bloques, ter minan con el smbolo " ; " .
s = s + n ;
if ( letr a == ' .' ) ter minar ( );
pr intf ( " mensaje\n" );
En los bloques, las declar aciones de datos deben estar al pr incipio del
bloque delante de cualquier sentencia que los utilice.
. . .
. . .
{
int j;
j = i-1;
while ( j >= 0 ) pr intf(" %c" , s[j--]);
pr intf (" \n" );
}
. . .
. . .
C.01.14
LA SENTENCIA " if - else"
if ( expr esi n ) sentenci a_1 else sentenci a_2
La expr esin debe escr ibir se entr e par ntesis.
Las sentencias ter minan con " ;" .
Si la expresin no es cero (verdadero), se ejecuta la "sentencia_1", en caso
contrario, si es cero (falso), se ejecuta la "sentencia_2"
cero es falso
distinto de cer o es ver dader o
expr esin
ver dader o falso
sentencia_1
sentencia_2

if ( a < b ) r etur n (a);
else r etur n ( b );
C.01.15
LA SENTENCIA " for "
for ( expr esi n_1 ; expr esi n_2 ; expr esi n_3 ) sentenci a
Se evala la "expresin_1", se evala la "expresin_2" y si produce el
valor "verdadero" (distinto de cero) se ejecuta la "sentencia". Despus se
evala la "expresin_3" y el control pasa al principio del ciclo y se salta la
evaluacin de la "expresin_1". El proceso se repite hasta que la
"expresin_2" tome el valor "falso" (cero).
expr esin_1
expr esin_2
expr esin_3
MIENTRAS QUE
sentencia
potencia = 1.0;
for (i=1 ; i<=exponente ; i++)
potencia=potencia*base;
MIENTRAS QUE
i = 1
i <= exponente
potencia = potencia * bas e
i = i + 1
C.01.16
/*
ej2.c
Calcula potencias de base real positiva y exponente entero
*/
#include <stdio.h>
void main ( )
{
int exponente;
float base, potencia (float, int);
printf ("Introducir BASE y EXPONENTE: \n");
scanf ("%f%d", &base, &exponente);
if ( base <= 0.0 ) printf ("Solo admito bases positivas \n");
else { if ( exponente > 0 )
printf ("Potencia: %f \n", potencia(base, exponente));
else
printf ("Potencia: %f \n",
1.0/potencia(base, -exponente));
}
}
float potencia (float b, int e)
{
if ( b == 1.0 ) return (1.0);
else {
if ( e == 1 ) return ( b );
else {
int i; float p=1.0;
for ( i=1; i<=e; i++ ) p=p*b;
return ( p );
}
}
}
C.01.17
La funcin " pr intf"
Per mite escr ibir con for mato por el dispositivo de salida estndar .
Admite dos tipos de par metr os:
Especificaciones de for mato
Lista de valor es
Se indican los valor es que hay que escr ibir y el for mato de escr itur a. La
funcin " pr intf" convier te, for matea y escr ibe.
las sentencias:
float x1, x2;
x1=3.1416; x2=2.5;
pr intf(" Resultados: \nx1=%f \nx2=%f \n" , x1,x2);
pr intf(" Otr o for mato: \nx1=%7.2f \nx2=%4.2f \n" , x1,x2);
producen una salida as:
Resultados:
x1=3.141600
x2=2.500000
Otro formato:
x1= 3.14
x2=2.50
C.01.18
Especificaciones de for mato
Se escr iben entr e comillas.
Pueden contener :
-Car acter es y secuencias de escape como " \n" (salto de linea)
"INDICE\n"
-Especificaciones de conver sin:
Empiezan con " %" y lleva un cdigo de conver sin y un
modificador opcional:
%d %4d %7.4f
Con el modificador se deter mina la pr esentacin (longitud
del campo, nmer o de dgitos decimales, etc...)
Con el cdigo de conver sin se indica el tipo de
tr ansfor macin:
d se convierte a notacin decimal
o se convierte a formato octal sin signo
x se convierte a formato hexadecimal sin signo
f se considera que el argumento es de tipo "float" y
se convierte a notacin decimal
e se considera que el argumento es de tipo "float" y
se convierte a notacin exponencial
c se considera que el argumento es un simple
carcter
s se considera que el argumento es una cadena de
caracteres
C.01.19
Lista de valor es
Pueden poner se constantes, var iables, llamadas a funciones y expr esiones
pr intf ( " El numer o %d es impar .\n" , n );
for ( r =3.1416; r >= 0.0; r =r -0.001) pr intf ( " %7.4f\n" , r );
pr intf ( " Atencion!! %c \n" , 7 );
pr intf ( " Potencia:%f\n" , potencia(base, exponente));
C.01.20
La funcin " scanf"
Per mite leer datos con for mato por el dispositivo de
entr ada estndar .
Lee car acter es y los convier te a r epr esentaciones
inter nas de var iables segn las especificaciones de
for mato.
Admite par metr os de dos clases:
Especificaciones de for mato
Apuntador es a var iables
scanf ( " %d%d" , &n1, &n2 );
Las especificaciones de for mato:
-se escr iben en tr e comillas
-empiezan con el smbolo " % "
-pueden contener cdigos de conver sin y
modificador es de conver sin
Algunos cdigos de conver sin:
d a enter o decimal (int)
f a coma flotante (float)
c a car cter (char )
s a cadena de car acter es
C.01.21
La lista de apuntador es:
Contiene expr esiones que apuntan (son dir ecciones) a las
var iables que r ecibir n los valor es leidos segn las
especificaciones de for mato cor r espondientes.
Pueden ser nombr es de var iables de tipo punter o o
expr esiones for madas con el smbolo " & " seguido
de un nombr e de var iable:
int n1, n2;
scanf (" %d %d" , &n1, &n2);
...
char letr a; int n; float r ;
scanf (" %c %d %f" , &letr a, &n, &r );
...
char cad[80];
scanf (" %s" , cad);
& es el oper ador de dir eccin
En C, el mecanismo de paso de valor es a las funciones es por valor
siempr e. Por eso, cuando se quier e pr oducir el efecto later al de modificar
el valor de una var iable, hay que pasar su dir eccin usando el oper ador
de dir eccin " & " .
C.01.22
/*
ej3.c
Lee un numero entero y determina si es par o impar
*/
#include <stdio.h>
#define MOD % /* %, es el operador que obtiene el resto
de la divisin entera */
#define EQ ==
#define NE !=
#define SI 1
#define NO 0
void main ( )
{
int n, es_impar(int);
printf ("Introduzca un entero: \n");
scanf ("%d", &n);
if ( es_impar (n) EQ SI )
printf ("El numero %d es impar. \n", n);
else
printf ("El numero %d no es impar. \n", n);
}
int es_impar (int x)
{
int respuesta;
if ( x MOD 2 NE 0 ) respuesta=SI;
else respuesta=NO;
return (respuesta);
}
C.02.01
- 2 -
ELEMENTOS LEXICOS
Car acter es
Smbolos:
Identificador es
Palabr as r eser vadas
Constantes
Cadenas
Oper ador es
Separ ador es
C.02.02
Los car acter es
Un pr ogr ama escr ito en " C" es una secuencia de
car acter es agr upados, for mando smbolos que
componen cadenas sintcticas vlidas.
letr as minsculas: a b c d . . . z
letr as maysculas: A B C D . . . Z
cifr as: 0 1 2 3 4 5 6 7 8 9
caracteres
especiales: + = _ - ( ) * & % $ # !
| < > . , ; : " ' / ?
{ } ~ \ [ ] ^
caracteres
no impr imibles: espacio en blanco,
salto de linea,
marca de tabulador
C.02.03
LOS SIMBOLOS
Son secuencias de uno o ms caracteres, que
se usan para representar entidades de distinta
naturaleza:
identificador es:
n, suma, main, scanf, ...
palabr as r eser vadas
int, float, while, if, else,
return, ...
constantes: 3.1416, 27, 'a', ...
cadenas: "palabra", ...
oper ador es: +, -, *, /, ++, ...
separ ador es: {, }, ...
Los espacios en blanco, las marcas de tabulador, los saltos
de linea y los comentarios sirven como separadores, pero
se ignoran a otros efectos por el compilador.
C.02.04
LOS IDENTIFICADORES
Son secuencias de car acter es que se pueden for mar usando letr as,
cifr as y el car cter de subr ayado " _" .
Se usan par a dar nombr e a los objetos que se manejan en un
pr ogr ama: tipos, var iables, funciones, ...
Deben comenzar por letra o por "_".
Se distingue entre maysculas y minsculas.
Se deben definir en sentencias de declar acin antes de ser usados.
int i, j, k;
float largo, ancho, alto;
enum colores {rojo, azul, verde}
color1, color2;
C.02.05
LAS PALABRAS RESERVADAS
Son algunos smbolos cuyo significado est pr edefinido
y no se pueden usar par a otr o fin:
auto br eak case char
continue default do double
else enum exter n float
for goto if int
long register r etur n shor t
sizeof static str uct switch
typedef union unsigned void
while
C.02.06
LAS CONSTANTES
Son entidades cuyo valor no se modifica dur ante la
ejecucin del pr ogr ama.
Hay constantes de var ios tipos.
Ejemplos:
numr icas: -7 3.1416 -2.5e-3
caracteres: 'a' '\n' '\0'
cadenas: "indice general"
CONSTANTES SIMBOLICAS
Se definen con sentencias par a el pr epr ocesador .
Se define un identificador y se le asigna un valor
constante. Despus se puede usar el identificador .
Favor ecen la r ealizacin de modificaciones en los
pr ogr amas.
#define PI 3.1416
C.02.07
LAS CADENAS
Una cadena de car acter es (str ing) en " C" es una secuencia de
car acter es, almacenados en posiciones de memor ia contiguas, que
ter mina con el car cter nulo.
Una cadena se r epr esenta escr ibiendo una secuencia de car acter es
encer r ada entr e comillas:
" buenos dias"
" asi: \" se pueden incluir las comillas"
Una cadena es un valor constante de una estr uctur a de tipo " ar r ay de
char " .
char titulo[24];
str cpy(titulo, " Cur so de C" );
pr intf(" %s" , titulo);
Par a r ealizar oper aciones con cadenas hay que usar funciones de
biblioteca. El lenguaje no dispone de oper ador es par a cadenas.
C.02.08
LOS OPERADORES
Sir ven par a indicar la aplicacin de oper aciones sobr e
los datos:
oper aciones ar itmticas, de compar acin, de
desplazamiento de bits, de indir eccin, etc...
Casi todos se r epr esentan con smbolos especiales:
+ - / % & * etc...
Algunos tienen significados difer entes segn el
contexto:
pr intf(" %d" , a) aqu se usa par a especificacin
de for mato
n % 5 aqu es el oper ador mdulo
p = n * m aqu es par a multiplicar
n = *punter o aqu es la indir eccin
c.02.09
LOS OPERADORES
Puestos en orden de prioridad descendente
Oper ador es Asociatividad
( ) [ ] -> . (miembr o) izquier da a der echa
~ ! ++ -- sizeof (tipo) der echa a izquier da
-(unar io) *(indir eccin) &(dir eccin)
* / % izquier da a der echa
+ - izquier da a der echa
<< >> izquier da a der echa
< <= > >= izquier da a der echa
== != izquier da a der echa
& izquier da a der echa
^ izquier da a der echa
| izquier da a der echa
&& izquier da a der echa
|| izquier da a der echa
?: der echa a izquier da
= += -= *= ... der echa a izquier da
, (oper ador coma) izquier da a der echa
C.02.10
LOS SEPARADORES
Los caracteres especiales actan como separadores en
general.
Hay algunos caracteres que slo sirven para actuar de
separadores:
El espacio en blanco
La marca de tabulador
El salto de linea
Los comentarios (se trata el conjunto como
un espacio en blanco)
Hay que separar con espacios en blanco:
Las palabras reservadas
Las constantes
Algunos identificadores adyacentes
Si la secuencia que lee el compilador ha sido analizada
hasta un car cter deter minado:
el siguiente elemento se toma incluyendo la
cadena de car acter es ms lar ga que pueda
constituir un elemento sintctico vlido.
C.03.01
- 3 -
EXPRESIONES Y SENTENCIAS.
EXPRESIONES DE ASIGNACION.
C.03.02
LAS EXPRESIONES
Son combinaciones de constantes, var iables, oper ador es y llamadas a
funciones:
i++
a + b
3.1416*r *r
densidad*volumen(a, b, c)
En gener al, toda expr esin tiene un valor que es el r esultado de aplicar
las oper aciones indicadas a los valor es de las var iables siguiendo unas
r eglas de pr ior idad y asociatividad pr opias del lenguaje.
Una expr esin seguida de un punto y coma es una
sentencia.
3.1416;
n=0;
++n;
s=s+n;
C.03.03
LAS EXPRESIONES DE ASIGNACION
Se for man con el oper ador " = " .
var iable = expr esion
Cuando se ejecuta, se evala la expr esin que est a la der echa y el
r esultado se asigna a la var iable del lado izquier do haciendo
conver sin de tipo si es necesar io. Ese valor es el que toma la
expr esin en su conjunto tambin.
n=5 la expr esin toma el valor 5
x=(y=5)+(z=7) y toma el valor 5
z toma el valor 7
x toma el valor 12
la expr esin toma el valor 12
El oper ador de asignacin " = " es asociativo de der echa a
izquier da:
x=y=z=0 es equivalente a x=(y=(z=0))
C.04.01
- 4 -
LOS TIPOS DE DATOS.
VISION GENERAL.
El concepto de tipo de datos.
Los tipos fundamentales. Esquema. Descr ipcin br eve.
Declar aciones: tipo - clase - valor inicial.
Las clases de almacenamiento.
Ejemplo de declar aciones e inicializacin.
El oper ador " sizeof" .
C.04.02
LOS TIPOS DE DATOS
PROGRAMA = ESTRUCTURAS + ALGORITMOS
DE DATOS
Las for mas de or ganizar datos estn deter minadas por los TIPOS DE
DATOS definidos en el lenguaje.
Todo objeto de datos per tenece a un tipo.
Un tipo de datos deter mina el r ango de valor es
que puede tomar el objeto, las oper aciones a
que puede ser sometido y el for mato de
almacenamiento en memor ia.
En " C" :
Existen tipos pr edefinidos
El usuar io puede definir otr os tipos,
a par tir de los bsicos.
per o...
No es un lenguaje or ientado a tipos
estr ictamente
C.04.03
LOS TIPOS DE DATOS
ESCALARES:
Numr icos: Enter os: int
long
shor t
unsigned
unsigned long
unsigned shor t
char
Reales: float
double
pointer (punter os)
enum (enumer ativos)
ESTRUCTURADOS: ar r ay
str ing
str uct
campos de bits
union
C.04.04
int, long, short, unsigned, ...:
Par a manejar nmer os enter os.
int n; n=27;
float, double: Par a manejar nmer os r eales.
float r; r=3.1416;
char: Repr esenta a un car cter de la tabla
de codificacin.
char c; c='a';
pointer: Apuntador es par a manejar estr uctur as
dinmicas. Es fundamental en " C" .
Se per mite la ar itmtica de punter os.
Se usan par a conseguir el paso por
r efer encia en la comunicacin entr e
funciones.
int n, m, *p; p=&x;
m=*p;
leer(&n);
enum : Enumer ativos.El usuar io define cual
es el conjunto de valor es posibles.
enum colores
{rojo,azul,verde}color;
color=verde;
C.04.05
array : Ar r eglos homogneos. Pueden ser de una o
var ias dimensiones. Per miten el acceso dir ecto
a cualquier a de sus elementos.
int n[100]; n[1]=0;
float r[10][20][30];
float a[100][100];
int i,j;
a[1][2]=2.5;
a[i][j]=0.0;
string : Cadenas. Secuencias de car acter es ter minando
con el car cter nulo.
Se manejan con funciones de biblioteca.
Son ar r eglos de " char " .
char *c, s[24];
strcpy(c,"abc"); 'a' 'b' 'c' '\0'
strcpy(s,"indice general");
struct : Estr uctur as. Son ar r eglos heter ogneos.
struct naipe {
int valor;
char palo;
} c1, c2;
c1.valor=3;
c1.palo='e';
C.04.06
union : Uniones. Par a compar tir memor ia.
union numerico {
int n;
float x;
} numero;
numero.x=5.3;
C.04.07
DECLARACION DE VARIABLES
Todos los identificador es de var iables deben ser declar ados antes de
usar se.
En la declar acin de una var iable se establece:
la clase de almacenamiento
el tipo al que per tenece
el valor inicial (opcionalmente)
int n, m;
static char s[24]=" cadena" ;
static float a[3][3] ={ 1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0 };
CLASES DE ALMACENAMIENTO
automatic
static
exter nal
register
C.04.08
CLASES DE ALMACENAMIENTO
automatic : son var iables locales de cada llamada a un bloque.
Desapar ecen al ter minar la ejecucin del bloque.
static : locales de un bloque. Conser van su valor entr e
ejecuciones sucesivas del bloque.
exter nal : existen y mantienen sus valor es dur ante toda la
ejecucin del pr gr ama. Pueden usar se par a la
comunicacin entr e funciones, incluso si han sido
compiladas por separ ado.
r egister : se almacenan, si es posible, en r egistr os de alta
velocidad de acceso. Son locales al bloque y
desapar ecen al ter minar su ejecucin.
C.04.09
INICIALIZACION DE VARIABLES
POR DEFECTO:
exter nal, static se inicializan a cer o
automatic, r egister quedan indefinidas
(valor es aleator ios)
PARA VARIABLES ESCALARES:
Se pueden asignar valor es iniciales en la declar acin:
tipo var iable = valor ;
con exter nal y static:
se hace una vez, en tiempo de compilacin
se deben usar valor es constantes
con automatic y register:
se hace cada vez que se entr a en el bloque
se pueden usar var iables y llamadas a funciones
C.04.10
INICIALIZACION DE ARRAYS
Los automatic no se pueden inicializar .
Los exter nal y los static se pueden inicializar escr ibiendo una lista de
valor es separ ados por comas y encer r ada entr e llaves:
static float a[5]={1.0,1.0,1.0,1.0,1.0};
si se ponen menos valor es, el r esto de los elementos
se inicializa a cero
si no se declar tamao, se toma el nmer o de
elementos de la lista de inicializacin
con los ar r ay de char, se per mite una constr uccin
especial:
static char s[24]="los tipos de datos"
C.04.11
/*
ej4.c
Inicializacion y manejo de "arrays", cadenas y estructuras.
*/
# include <stdio.h>
void main()
{
int i, j;
static int enteros [5] = { 3, 7, 1, 5, 2 };
static char cadena1 [16] = "cadena";
static char cadena2 [16] = { 'c','a','d','e','n','a','\0' };
static int a[2][5] = {
{ 1, 22, 333, 4444, 55555 },
{ 5, 4, 3, 2, 1 }
};
static int b[2][5] = { 1,22,333,4444,55555,5,4,3,2,1 };
static char *c = "cadena";
static struct {
int i;
float x;
} sta = { 1, 3.1415e4}, stb = { 2, 1.5e4 };
static struct {
char c;
int i;
float s;
} st [2][3] = {
{{ 'a', 1, 3e3 }, { 'b', 2, 4e2 }, { 'c', 3, 5e3 }},
{ { 'd', 4, 6e2 }, }
};
printf ("enteros:\n");
for ( i=0; i<5; ++i ) printf ("%d ", enteros[i]);
printf ("\n\n");
printf ("cadena1:\n");
printf ("%s\n\n", cadena1);
printf ("cadena2:\n");
printf ("%s\n\n", cadena2);
printf ("a:\n");
for (i=0; i<2; ++i) for (j=0; j<5; ++j) printf ("%d ", a[i][j]);
printf("\n\n");
printf ("b:\n");
for (i=0; i<2; ++i) for (j=0; j<5; ++j) printf ("%d ", b[i][j]);
C.04.11.a
pr intf (" \n\n" );
pr intf (" c:\n" );
pr intf (" %s\n\n" , c);
pr intf (" sta:\n" );
pr intf (" %d %f \n\n" , sta.i, sta.x);
pr intf (" st:\n" );
for (i=0; i<2; ++i) for (j=0; j<3; ++j)
pr intf (" %c %d %f\n" , st[i][j].c, st[i][j].i, st[i][j].s);
}
ent eros:
3 7 1 5 2
cadena1:
cadena
cadena2:
cadena
a:
1 22 333 4444 55555 5 4 3 2 1
b:
1 22 333 4444 55555 5 4 3 2 1
c:
cadena
st a:
1 31415.000000
st :
a 1 3000.000000
b 2 400.000000
c 3 5000.000000
d 4 600.000000
0 0.000000
0 0.000000
C.04.12
EL OPERADOR " sizeof "
Devuelve un entero que indica el nmero de bytes usados
para almacenar un objeto.
int n;
printf("%d", sizeof(n));
printf("%d", sizeof( (int) ));
/*
ej5.c
Se indican los tamanios de las representaciones internas de
algunos tipos de datos fundamentales.
*/
# include <stdio.h>
void main()
{
char c;
short s;
int i;
long l;
float f;
double d;
printf ("Tipo char: %d bytes\n", sizeof(c));
printf ("Tipo short: %d bytes\n", sizeof(s));
printf ("Tipo int: %d bytes\n", sizeof(i));
printf ("Tipo long: %d bytes\n", sizeof(l));
printf ("Tipo float: %d bytes\n", sizeof(f));
printf ("Tipo double: %d bytes\n", sizeof(d));
}
C.04.12.a
/*
ej5a.c
Aplicacion del operador "sizeof" a los tipos fundamentales.
*/
# include <stdio.h>
void main()
{
printf ("\n char: %d bytes", sizeof(char));
printf ("\n short: %d bytes", sizeof(short));
printf ("\n unsigned short: %d bytes", sizeof(unsigned short));
printf ("\n int: %d bytes", sizeof(int));
printf ("\n unsigned: %d bytes", sizeof(unsigned));
printf ("\n long: %d bytes", sizeof(long));
printf ("\n unsigned long: %d bytes", sizeof(unsigned long));
printf ("\n float: %d bytes", sizeof(float));
printf ("\n double: %d bytes", sizeof(double));
printf ("\n\n");
}
C.05.01
- 5 -
LOS TIPOS DE DATOS FUNDAMENTALES
Los tipos numr icos enter os
Los tipos numr icos de coma flotante
Oper ador es unar ios
Oper ador es ar itmticos
Funciones matemticas
El tipo char
Las funciones " getchar " y " putchar " par a leer y escr ibir un
carcter
Oper ador es de asignacin
Conver siones y " casts"
El tipo " pointer "
Ar itmtica de punter os
Inter pr etacin de las declar aciones complejas
Los oper ador es de " bits"
Mscar as
Empaquetamiento
Los tipos enumer ativos
C.05.02
LOS TIPOS NUMERICOS ENTEROS
int long shor t
unsigned unsigned long unsigned shor t
char
El tipo " int" es el ms usado par a tr abajar con enter os.
Los dems se utilizan cuando se desea algn efecto especial como
ahor r ar memor ia o poder oper ar con valor es mayor es.
shor t : r ango de valor es menor par a
poder usar un nmer o menor de
bits
unsigned : slo valor es positivos, per o con
mayor lmite super ior por que no
se gasta un bit par a el signo.
La cantidad de memor ia que ocupa cada tipo depende de la
implementacin per o deter mina, en todo caso, el r ango de valor es
posibles.
El caso tpico de las ar quitectur as de 32 bits como la del VAX y la del
HP-9000 se r esume en la tabla siguiente.
C.05.03
Implementacin de los tipos numr icos enter os en
ar quitectur as de 32 bits.
Bits Mnimo Mximo
int 32 -2
31
2
31
-1
(-2.147.483.648) (+2.147.483.647)
unsigned 32 0 2
32
-1
(+4.294.967.295)
shor t 16 -2
15
2
15
-1
(-32.768) (+32.767)
unsigned 16 0

2
16
-1
shor t
(+65.535)
long 32 -2
31
2
31
-1
(-2.147.483.648) (+2.147.483.647)
unsigned 32 0 2
32
-1
long (+4.294.967.295)
char 8 ' \0' ( 0 ) ' \377' (255)
C.05.04
El tipo " int "
Es el tipo ms impor tante:
Es el tipo que toman las funciones por defecto
En la evaluacin de expr esiones ar itmticas mixtas, los valor es
" char " y " shor t" se convier ten a " int"
Los dir ecciones de memor ia se r epr esentan con enter os
etc...
Las var iables de tipo " int" se usan:
Par a r ealizar oper aciones ar itmticas
Como contador es de bucles r epetitivos
Como subndices de ar r ays
etc...
Constantes enter as
0 - 7
0 - 9
1 - 9
0
0 - 9
a - f
A - F
0x
0X
octal
decimal
hexadecimal
Ejemplos: 0
25
32767
0777
0x1A
C.05.05
Los enter os negativos son expr esiones
Oper ador unar io " menos" aplicado a
constante enter a
Rango de valor es en ar quitectur a de 32 bits
Valor mnimo Valor mximo
-2
31
2
31
- 1
-2.147.483.648 2.147.483.647
Con 32 bits se pueden r epr esentar 2
32
estados:
La mitad, son enter os positivos: 0, 1, 2, ..., 2
31
-1
La mitad, son enter os negativos: -1, -2, . . ., -2
31
Se maneja la r epr esentacin de complemento a 2 de 32 bits con
" bytes" de 8 bits y codificacin ASCII.
0 00000000000000000000000000000000
1 00000000000000000000000000000001
2 00000000000000000000000000000010
5 00000000000000000000000000000101
2.147.483.647 01111111111111111111111111111111
-2.147.483.648 10000000000000000000000000000000
-5 11111111111111111111111111111011
-2 11111111111111111111111111111110
-1 11111111111111111111111111111111
C.05.06
Los oper ador es ar itmticos
+ - * / %
Cor r esponden a las oper aciones matemticas de suma, r esta,
multiplicacin, divisin y mdulo.
Son binar ios por que cada uno tiene dos oper andos.
Hay un oper ador unar io menos " -" , per o no hay oper ador unar io
ms " +" :
-3 es una expr esin cor r ecta
+3 NO es una expr esin cor r ecta
La divisin de enter os devuelve el cociente enter o y desecha la
fr accin r estante:
1/2 tiene el valor 0
3/2 tiene el valor 1
-7/3 tiene el valor -2
El oper ador mdulo se aplica as:
con dos enter os positivos, devuelve el r esto de la divisin
12%3 tiene el valor 0
12%5 tiene el valor 2
si un oper ando o los dos son negativos, el r esultado depende de la
mquina.
En HP-UX:
pr intf (" %d\n" , -12%5); escr ibe -2
pr intf (" %d\n" , 12%-5); escr ibe 2
pr intf (" %d\n" , -12%-5); escr ibe -2
C.05.07
Los operadores de incremento y decremento
Son unarios.
Tienen la misma prioridad que el menos "-" unario.
Se asocian de derecha a izquierda.
Pueden aplicarse a variables, pero no a constantes ni a expresiones.
Se pueden presentar como prefijo o como sufijo.
Aplicados a variables enteras, su efecto es incrementar o
decrementar el valor de la variable en una unidad:
++i; es equivalente a i=i+1;
--i; es equivalente a i=i-1;
Cuando se usan en una expresin, se produce un efecto secundario
sobre la variable:
El valor de la variable se incrementa antes
o despues de ser usado.
con ++a el valor de "a" se incrementa antes de evaluar la
expresin.
con a++ el valor de "a" se incrementa despus de evaluar
la expresin.
con a el valor de "a" no se modifica antes ni despus de
evaluar la expresin.
C.05.08
Ejemplos
a=2*(++c) se incr ementa el valor de " c" y se evala la
expr esin despus.
Es equivalente a: c=c+1; a=2*c;
a[++i]=0 se incr ementa el valor de " i" y se r ealiza
la asignacin despus.
Es equivalente a: i=i+1; a[i]=0;
a[i++] se r ealiza la asignacin con el valor actual
de " i" , y se incr ementa el valor de " i"
despus.
Es equivalente a: a[i]=0; i=i+1;
Hay que evitar expr esiones como sta: a=++c+c
por que el r esultado depende de la mquina
C.05.09
Los tipos enter os " shor t" " long" " unsigned"
Se utilizan par a obtener algn efecto especial: ahor r ar espacio en
memor ia, disponer de un r ango de valor es mayor .
La implementacin depende de la mquina.
shor t: la r epr esentacin inter na ocupa un nmer o
menor de bytes.
Si son 2 bytes (16 bits):
valor menor : -2
15
= -32768
valor mayor : 2
15
-1= 32767
long: la r epr esentacin inter na ocupa un nmer o
mayor de bytes.
En ar quitectur as de 32 bits, suele ser igual
que " int" .
unsigned: se pr escinde del signo par a disponer de un
bit ms y poder oper ar en un r ango de valor es
mayor .
Par a una implementacin de " int" en 32 bits,
" unsigned" pr opor ciona el r ango:
valor mnimo: 0
valor mximo: 2
31
-1= 4.294.967.295
C.05.10
El operador " sizeof "
Est incorporado al lenguaje para proporcionar el
nmero de bytes usados para almacenar un objeto.
sizeof(int)
sizeof(short)
sizeof(long)
sizeof(unsigned)
Lo que C garantiza:
sizeof(char) = 1
sizeof(short) <= sizeof(int) <= sizeof(lon)
sizeof(unsigned) = sizeof(int)
sizeof(float) <= sizeof(double)
/*
ej5.c
Se indican los tamanios de las representaciones internas de
algunos tipos de datos fundamentales.
*/
# include <stdio.h>
void main()
{
char c;
short s;
int i;
long l;
float f;
double d;
printf ("Tipo char: %d bytes\n", sizeof(c));
printf ("Tipo short: %d bytes\n", sizeof(s));
printf ("Tipo int: %d bytes\n", sizeof(i));
printf ("Tipo long: %d bytes\n", sizeof(l));
printf ("Tipo float: %d bytes\n", sizeof(f));
printf ("Tipo double: %d bytes\n", sizeof(d));
}
C.05.11
For matos de lectur a y escr itur a par a enter os
d enter o decimal.
o enter o octal que no empieza con 0.
x enter o hexadecimal que no empieza con x.
u enter o decimal sin signo.
main( )
{
int n;
pr intf(" Intr oducir una constante enter a:\n" );
scanf(" %d" , &n);
pr intf(" El valor leido es: %d\n" , n);
}
C.05.12
Los tipos numr icos de coma flotante
float double
Se usan par a oper ar con nmer os r eales.
float r , v[100], a[10][10], *p;
double r , v[100], a[10][10], *p;
La pr ecisin simple (float) se suele implementar con 32 bits (4
bytes), y la doble pr ecisin con 64 bits (8 bytes).
Constantes r eales
e
E
+
-
0 - 9
0 - 9
0 - 9 0 - 9
0 - 9
Ejemplos: 27.
3.14
3.14e10
.612e-5
47e-3
En esta constante: 888.7777e-22
888 es la par te enter a
7777 es la par te fr accionar ia
e-22 es la par te exponencial
C.05.13
Rango de valores y precisin
Son dependientes de la mquina. Unos valores tpicos:
float double
============ =============
precisin 6 cifras 16 cifras
rango 10
-38
a 10
38
10
-38
a 10
38
representacin +/-.d
1
d
2
...d
6
x10
n
+/-.d
1
d
2
...d
16
x10
n
-38<=n<=+38 -38<=n<=+38
Los operadores aritmticos que se aplican a tipos de coma flotante son:
+ - * /
con el significado habitual.
/*
ej6.c
Precisin en el clculo
*/
# include <stdio.h>
void main()
{
float x=1.0;
long i=1;
x=x*(float)0.99937;
while ( 1.0 != (1.0+x) ) {
++i;
x=x*(float)0.99937;
}
printf ("%ld %20.12f\n", i, x);
}
C.05.14
Las funciones matemticas no estn incor por adas en el
lenguaje.
Se pr opor cionan en una biblioteca, que contiene
funciones de uso fr ecuente:
sqr t( )
exp( )
log( )
sin( )
cos( )
tan( )
etc...
En la seccin 3 del manual de Refer encia de UNIX se descr iben las
funciones de las bibliotecas.
Casi todas usan el tipo " double" par a los par metr os.
Los pr ogr amas que utilizan funciones de la biblioteca matemtica, en el
entor no UNIX, deben incluir cier tas declar aciones con la or den :
# include <math.h>
y deben ser compilados invocando a la libr er a:
cc fn.c -lm
{
double x;
scanf(" %f" , &x);
pr intf(" %20.12e\n" , exp(x));
}
C.05.15
For matos par a lectur a y escr itur a
For matos par a lectur a con " scanf"
e nmer o en coma flotante
f equivalente a " e"
For matos par a escr itur a con " pr intf"
e coma flotante en for ma exponencial
f coma flotante sin exponente
g se elige el ms cor to entr e " e" y " f"
{
float r ;
pr intf(" Un nmer o en coma flotante ?\n" );
scanf(" %f" , &r );
pr intf(" El valor leido es: %f\n" , r );
}
C.05.16
El tipo " char "
Se usa par a manejar car acter es aislados.
char c, s[10], *p;
Un " char " se almacena en un byte y lleva asociado un valor enter o (el
or dinal que indica su posicin en la tabla de codificacin ASCII, o la
codificacin en uso).
0 0 0 0 0 0 1 1
6 5 4 3 2 1 0 7
' A'
65
pr intf (" %d" , ' a' + ' b' + ' c' );
Los car acter es no impr imibles se pueden r epr esentar mediante
secuencias de escape expr esadas con car acter es alfabticos o con
valor es numr icos en sistema octal.
Nombr e Valor
del carcter Escr itur a en C enter o
============= ============ =====
nulo ' \0' ' \0' 0
retroceso ' \b' ' \10' 8
tabulador ' \t' ' \11' 9
salto de linea ' \n' ' \12' 10
salto de pgina ' \f' ' \14' 12
r etor no de car r o ' \r' ' \15' 13
comillas ' \" ' ' \42' 34
apstr ofo ' \' ' ' \47' 39
bar r a inver tida ' \\' ' \134' 92
C.05.17
La tabla de codificacin ASCII
Der echa
0 1 2 3 4 5 6 7 8 9
Izda.
0 nul soh stx etx eot enq ack bel bs ht
1 nl vt np cr so si dle dc1 dc2 dc3
2 dc4 nak syn etb can em sub esc fs gs
3 r s us sp ! " # $ % & '
4 ( ) * + , - . / 0 1
5 2 3 4 5 6 7 8 9 : ;
6 < = > ? @ A B C D E
7 F G H I J K L M N O
8 P Q R S T U V W X Y
9 Z [ \ ] ^ _ ` a b c
10 d e f g h i j k l m
11 n o p q r s t u v w
12 x y z { | } ~ del
Significado de algunas abr eviatur as
nul nulo nl salto de linea
ht tabulador hor izontal esc escape
cr r etor no de car r o bs retroceso
bel campana vs tabulador ver tical
Obser vaciones:
Los cdigos de los car acter es 0 a 31 y 127 no son impr imibles
Los cdigos de las letr as maysculas, los de las minsculas y los de
las cifr as son contiguos entr e s.
La difer encia entr e una letr a mayscula y su cor r espondiente
minscula es 32.
C.05.18
Ejemplos
pr intf(" Resultados\n" );
{
char s[80]; int lon;
lon=0;
while ( s[lon] != ' \0' ) lon++;
}
Notar la difer encia entr e el valor numr ico que
r epr esenta una cifr a y el enter o asociado al car cter :
el valor del car cter ' 3' no es 3
Distinguir entr e ' a' y " a"
' a' es una constante de tipo char
" a" es una cadena constante,de dos car acter es:
' a' ' \0'
(El car cter nulo indica siempr e el final
de una cadena)
C.05.19
Lectur a y escr itur a de car acter es
getchar ( ) putchar ( )
scanf( ) pr intf( )
Son funciones de la biblioteca estndar .
En los pr ogr amas que usan estas funciones y constantes tiles como
EOF, se deben incluir cier tas definiciones y declar aciones poniendo la
or den:
# include <stdio.h>
getchar ( ) se obtiene el siguiente car cter del ficher o de
entr ada estndar (el teclado, por defecto).
El valor del car cter se devuelve como " int" .
Si se encuentr a el fin de ficher o o si se
pr oduce er r or , se devuelve EOF.
#include <stdio.h>
main( )
{ int c;
c=getchar ( );
pr intf(" El car cter leido es: %c\n" , c); }
putchar (c) escr ibe el valor " char " de " c" en el ficher o de
salida estndar .
Devuelve el valor " int" del car cter escr ito.
#include <stdio.h>
main( )
{ int c;
while ( (c=getchar ( )) != EOF )
putchar (c); }
C.05.20
Para la lectura y escritura de caracteres con formato
por los dispositivos estndar, con
scanf( ) y printf( )
se usa el formato " %c ".
/*
ej7.c
*/
# include <stdio.h>
void main( )
{
int c;
printf("Introducir un caracter:\n");
scanf("%c", &c);
printf("El caracter leido es: %c\n", c);
}
...
printf("%d", 'A');
printf("%c", 65);
printf("%c", 7);
C.05.21
Los oper ador es de asignacin
= += -= *= /= %=
>>= <<= &= ^= |=
>> desplazamiento de bits a la der echa
<< desplazamiento de bits a la izquier da
& AND binar io
^ OR exclusivo binar io
| OR inclusivo binar io
Abr eviatur as
En C se admiten abr eviatur as par a simplificar la escr itur a de algunas
sentencias de asignacin:
x = x + 10; se puede escr ibir como x += 10;
Esta for ma de abr eviatur a acta con todos los oper ador es binar ios.
For ma gener al:
var iable = var iable oper ador expr esin
es lo mismo que
var iable oper ador = expr esin
k *= 3 + x es equivalente a k = k*(3 + x)
a[] /= x + y es equivalente a a[i] = a[i] / (x + y)
Una expr esin a la izquier da de un oper ador de
asignacin, se evala una sola vez:
a[++i] += 3;
no es equivalente a
a[++i] = a[++i]+3; (codificacin indeseable por que el
r esultado depende del compilador )
C.05.22
Conver siones de tipo en las expr esiones ar itmticas
Cuando en una expr esin se mezclan constantes y var iables de distinto
tipo, se convier ten a un tipo nico par a evaluar la expr esin.
Los valor es de las var iables almacenados en memor ia no cambian. Se
hacen copias tempor ales par a evaluar la expr esin.
shor t x;
int y;
...
par a evaluar la expr esin " x+y" :
el valor de " x" se convier te a un " int"
el valor de la expr esin ser un " int"
Reglas par a la conver sin automtica en expr esiones
ar itmticas como " x op y " :
1.
Todos los " char " y " shor t" se convier ten a " int" .
Todos los " unsigned char " o " unsigned shor t" se convier ten a
" unsigned" .
2.
Si la expr esin es de tipo mixto despus del pr imer paso, el
oper ando de menor r ango se pr omueve al tipo del oper ando de
mayor r ango y se convier te toda la expr esin en ese tipo.
int < unsigned < long < unsigned long < float < double
A este pr oceso se le llama pr omocin.
C.05.23
Ejemplos
char c; double d; float f; int i;
long l; shor t s; unsigned u;
expr esin tipo
c - s / i int
u * 3 - i unsigned
u * 3.0 -i double
f * 3 - i float
c + 1 int
c + 1.0 double
3 * s * l long
Los tipos de las constantes
El tipo de datos asociado a una constante depende de la mquina. Se
asignan segn la for ma en que se escr ibe.
Lo nor mal es que no existan constantes de los tipos shor t, unsigned y
float.
int: 0 77 5013
long: 0L 77L 5013L
double: 0.003 1.0 0.5013e-2
char : ' a' ' b' ' c'
cadena: " esta es una constante de cadena"
Cuando una constante enter a es demasiado gr ande par a " int" , se le
asigna el tipo " long" .
Las expr esiones constantes se evalan en tiempo de compilacin.
C.05.24
Conver siones implcitas a tr avs del signo " = "
Con el oper ador de asignacin " = " tambin se pr oducen conver siones
de tipo implcitas.
El oper ando de la der echa se convier te al tipo del oper ando de la
izquier da al hacer se la evaluacin.
Supongamos: int i; double d; char c;
Al evaluar se la expr esin: d = i
se convier te el valor de " i" a
" double" y se asigna a " d" , y ste
ser el valor de la expr esin.
Si se tr ata de una
degr adacin : i = d
se puede per der infor macin
por que se desecha la par te
fr accionar ia.
En los casos de degr adacin, el r esultado depende de la
mquina.
Al evaluar se: c = i
se descar tan los bytes ms
significativos en " i" .
Al evaluar se: i = c
si el valor ASCII de c es cer o o
mayor que cer o, se llenan con
cer os los bits de los bytes ms
significativos de " i" .
C.05.25
Conver siones explcitas con el oper ador " casts "
Con el oper ador " casts" se pueden for zar conver siones de tipos
indicndolas explcitamente.
(t i po ) expr esi n
Ejemplo: int;
...
.. (double) i ... hace que se convier ta el valor
de " i" en uno de tipo " double"
par a la evaluacin de la
expr esin.
Estas conver siones no afectan al valor de la var iable almacenado en
memor ia, que no se alter a.
Los " casts" pueden aplicar se a cualquer expr esin.
El oper ador " casts" es unar io.
Tiene la misma pr ior idad que otr os unar ios y asociatividad de
der echa a izquier da.
(float) i + 3 es equivalente a ( (float) i ) + 3
por que el oper ador " casts" tiene pr ior idad super ior
al oper ador " +"
Ejemplos:
(char ) (3 - 3.14 * x)
k = (int)((int) x + (double) i + j )
(float) (x = 77)
Aqu se usa una var iable enter a (" i" ) par a contr olar un bucle y par a
r ealizar un cociente con par te fr accionar ia:
int i;
for ( i=1; i<100; ++i )
pr intf(" %d / 2 es: %f\n" , i, (float)i/2);
C.05.26
El tipo " pointer " . Los punter os.
En C, siempr e se pueden manejar :
el valor asignado
la dir eccin en memor ia

de cualquier var iable
El oper ador " & " (dir eccin) pr opor ciona la dir eccin de una
var iable
int n; " n" r epr esenta al valor almacenado (un enter o)
" &n" r epr esenta la dir eccin de memor ia
donde se almacena el valor
Par a manejar dir ecciones se usan los punter os (var iables de tipo
" pointer " ).
Los valor es que toman las var iables punter o son:
Dir ecciones de memor ia.
" Apuntan" a dir eccin de memor ia donde se
almacena un valor del tipo base.
Par a declar ar un punter o se escr ibe:
ti po_base *var i abl e
por ejemplo: int *n;
" n" es un punter o a valor es de tipo " int"
los valor es de " n" son dir ecciones
los valor es de la expr esin " *n " son
enter os
C.05.27
Asignacin de valor es a punter os:
int *p, i;
p = 0
p = NULL /* equivalente a p=0 */
p = &i
p = ( int * ) 1501
El oper ador de indir eccin " * "
Pr opor ciona el valor de la var iable apuntada:
Si " p" es un punter o, " *p " r epr esenta al valor
almacenado en la dir eccin " p " .
El oper ador " * " es unar io y tiene asociatividad de der echa a
izquier da.
con la declar acin: int a, b, *p;
son equivalentes: p = &a; b = *&a; b = a;
b = *p;
main( )
{
float i=3.1416, *p;
p=&i;
pr intf(" el valor de i es %f\n" , *p);
pr intf(" la dir eccin de i es %d\n" , p); }
Asignacin de un valor inicial: int i=7, *p=&i;
int n;
pr intf(" Intr oducir un enter o\n" );
scanf(" %d" , &n);
pr intf(" El valor leido es: %d\n" , n);
C.05.28
Se puede apuntar a:
var iables: int n;
&n
elementos de " ar r ay" : int v[10], n;
&v[0] &v[1]
&v[n]
No se puede apuntar a:
constantes: &7 ERROR
" ar r ays" : int v[10];
&v ERROR
El nombr e de un " ar r ay" es una
constante
expr esiones: &(n+1) ERROR
var iables de clase " r egister " : r egister x;
&x ERROR
C.05.29
La ar itmtica de punter os
Es una de las car acter sticas ms eficaces del lenguaje.
Si la var iable " p" es un punter o a un tipo deter minado, la expr esin "
p+1 " da la dir eccin de mquina cor r espondiente a la siguiente
var iable de ese tipo.
Son vlidas: p + 1
++p
p += i
La unidad de desplazamiento es pr opia del tipo base y depende de la
mquina:
1 byte par a char
4 bytes par a int
8 bytes par a double
int *p;
al evaluar se " ++p " el punter o pasa a apuntar al
valor almacenado 4 bytes ms adelante
Esta tcnica se usa mucho par a acceder a los elementos de las
estr uctur as " ar r ay" .
C.05.30
Inter pr etacin de las declar aciones complejas
char *( *x( ) )[ ]
A)
Hay que tener en cuenta las r eglas de pr ior idad y asociatividad de los
oper ador es: ( ) [ ] *
1) ( ) funcin y [ ] ar r ay izquier da a der echa
2) * punter o der echa a izquier da
B)
Se busca la var iable y se aplican los oper ador es siguiendo las r eglas de
pr ecedencia y asociatividad.
C)
Se hace la siguiente lectur a:
( ) funcin que devuelve ...
[ ] ar r ay de ...
* punter o a ...
Ejemplo:
char *( *x( ) ) [ ]; x es una funcon que devuelve punter os
1 a " ar r ays" de punter os a car acter es.
2
3
4
5
6
C.05.31
Ejemplos
int i, *i, f( ), *f( ), (*p)( ), *p[ ];
int i i es un enter o
int *p p es un punter o a enter o
2 1
int f( ) f es funcin que devuelve enter o
2 1
int *f( ) f es funcin que devuelve apuntador a enter o
3 2 1
int ( *p )( ) p es punter o a funcin que devuelve enter o
4 1 2 3
int *p[ ] p es ar r ay de punter os a enter o
3 2 1
No estn per mitidas todas las combinaciones posibles:
En algunas implementaciones, las funciones no pueden devolver
" ar r ays" , estr uctur as, uniones ni funciones. (Pueden devolver
punter os a esos tipos).
No se per miten " ar r ays" de funciones. (Se per miten " ar r ays" de
punter os a funciones).
Las estr uctur as y las uniones no pueden contener a una funcin.
(Pueden contener punter os a funciones).
C.05.32
Los oper ador es de " bits"
Actan sobr e expr esiones enter as r epr esentadas como cadenas de
dgitos binar ios.
El r esultado de las oper aciones depende de la mquina.
Aqu se supone una r epr esentacin de enter os en complemento a 2, de
32 bits, con bytes de 8 " bits" y codificacin ASCII.
0 00000000000000000000000000000000
1 00000000000000000000000000000001
2 00000000000000000000000000000010
3 00000000000000000000000000000011
4 00000000000000000000000000000100
5 00000000000000000000000000000101
2147483647 01111111111111111111111111111111
-2147483648 10000000000000000000000000000000
-5 11111111111111111111111111111011
-4 11111111111111111111111111111100
-3 11111111111111111111111111111101
-2 11111111111111111111111111111110
-1 11111111111111111111111111111111
En complemento a 2, una cadena binar ia y su complementar ia
suman -1.
Los oper ador es de " bits"
Op. lgicos: (unar io) complemento de " bits" ~
oper ador AND de " bits" &
OR exclusivo de " bits" ^
OR de " bits" |
Op. de
desplazamiento: desp. hacia la izquier da <<
desp. hacia la der echa >>
c.05.33
LOS OPERADORES
Puestos en orden de prioridad descendente
Oper ador es Asociatividad
( ) [ ] -> . (miembr o) izquier da a der echa
~ ! ++ -- sizeof (tipo) der echa a izquier da
- (unar io) *(indir eccin) &(dir eccin)
* / % izquier da a der echa
+ - izquier da a der echa
<< >> izquier da a der echa
< <= > >= izquier da a der echa
== != izquier da a der echa
& izquier da a der echa
^ izquier da a der echa
| izquier da a der echa
&& izquier da a der echa
|| izquier da a der echa
?: der echa a izquier da
= += -= *= ... der echa a izquier da
, (oper ador coma) izquier da a der echa
C.05.34
El oper ador de complemento " ~" es unar io, los dems
son binar ios.
Todos oper an con var iables enter as.
El oper ador complemento de " bits"
Invier te la r epr esentacin de la cadena de " bits" de su ar gumento,
convir tiendo los cer os en unos y los unos en cer os.
Si x, tiene la r epr esentacin: 000...1100001
entonces, ~x tiene la r epr esentacin: 111...0011110
Oper ador es binar ios lgicos de " bits"
Oper an de " bit" en " bit" con todos los " bits" de los oper andos.
Semntica oper ando sobr e un " bit"
x y x&y x^y x|y
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 0 1
C.05.35
Oper ador es de desplazamiento de " bits" << >>
Son oper ador es binar ios.
Los oper andos deben ser expr esiones enter as.
El oper ando der echo se convier te a " int" .
El oper ando der echo no puede ser negativo. Su valor no puede ser
mayor que el nmer o de " bits" de la r epr esentacin del oper ando
izquier do.
El tipo de la expr esin es el del oper ando izquier do.
Desplazamiento hacia la izquier da: <<
La r epr esentacin de " bits" del oper ando izquier do se mueve
hacia la izquier da el nmer o de lugar es que indica el
oper ando de la der echa.
Los " bits" de or den menor se sustituyen por cer os.
char x=' Z' ;
expr esin r epr esentacin
x 01011010
x<<1 10110100
x<<4 10100000
Desplazamiento hacia la der echa: >>
La r epr esentacin de " bits" del oper ando izquier do se mueve
hacia la der echa el nmer o de lugar es que indica el oper ando
de la der echa.
Con expr esiones enter as " unsigned" , se intr oducen cer os.
Con expr esiones " char " , " shor t" , " int" y " long" , el r esultado
depende de la mquina. En algunas se intr oducen cer os, en
otr as se intr oducen bits de signo.
C.05.36
Mscar as
Una mscar a es una expr esin que se utiliza par a extr aer " bits" de
otr a var iable o expr esin.
La constante 1 tiene esta r epr esentacin:
00000000000000000000000000000001
y se puede utilizar par a conocer como es el " bit" de or den
menor en una expr esin de tipo " int" :
int n; . . .; pr intf ( " %d" , n&1 );
Par a saber como est un " bit" deter minado de un valor enter o, se
puede usar una mscar a que tenga un 1 en esa posicin y 0 en las
dems.
La constante 0x10 sir ve como mscar a par a el quinto
" bit" contando desde la der echa:
0x10 se r epr esenta como 0...00010000
Si " x" tiene tipo " int" ,
la expr esin ( x&0x10) ? 1 : 0
vale 0 si el quinto " bit" en " x" es 0
vale 1 si el quinto " bit" en " x" es 1
La constante 0xff sir ve como mscar a par a el " byte"
de or den menor :
0xff se r epr esenta como 0...011111111
Si " x" tiene tipo " int" ,
la expr esin x&0xff
tiene un valor con todos los " bytes" de or den mayor
a cer o y con el " byte" de or den menor igual que el
cor r espondiente de " x" .
C.05.37
Ejemplos
/*
Funcin par a escr ibir la r epr esentacin binar ia
de un valor " int"
*/
bitpr int ( n )
int n;
{
int i, mascar a;
mascar a=1; /* 0...001 */
mascar a=mascar a << 31; /* se desplaza el " bit" 1 hacia
el extr emo ms significativo */
for ( i=1; i<=32; ++i ) {
putchar ( ((n&mascar a)==0) ? ' 0' : ' 1' );
n=n<<1;
}
}
/*
Esta funcin cuenta los " bits" que tienen valor 1
*/
cuenta_bits ( n )
unsigned n;
{
int unos;
for ( unos=0; n!=0; n>>1 ) if ( n&01 ) unos++;
r etur n (unos)
}
C.05.38
Empaquetamiento
Los oper ador es de " bits" per miten empaquetar datos en los lmites de
los " bytes" par a ahor r ar espacio en memor ia y tiempo de ejecucin.
Ejemplo:
En una mquina con ar quitectur a de 32 " bits" se puede hacer que se
pr ocesen 4 car acter es en un ciclo.
Esta funcin los empaqueta:
pack ( a, b, c, d )
char a, b, c, d;
{
int p;
p=a;
p=(p<<8)|b;
p=(p<<8)|c;
p=(p<<8)|d;
r etur n(p); }
Esta funcin los desempaqueta:
unpack ( p )
int p;
{
exter n a, b, c, d;
d=p&0xff;
c=(p&0xff00)>>8;
b=(p&0xff0000)>>16;
a=(p&0xff000000)>>24; }
C.05.39
Los tipos enumer ativos
En la definicin se establece un conjunto de valor es posibles
r epr esentados por identificador es.
enum color es { r ojo, azul, amar illo } color ;
La var iable " color " es de tipo " enum color es" .
Los valor es posibles son 3 y estn identificados por esos
nombr es que se llaman enumer ador es: r ojo, azul, amar illo
color =azul;
. . .
if ( color ==amar illo ) . . .
El compilador asigna un valor " int" a cada enumer ador , empezando
en cer o.
enum labor ables { lunes,mar tes,mier coles,jueves,vier nes } dia;
enumer ador valor
lunes 0
mar tes 1
miercoles 2
jueves 3
vier nes 4
Se puede establecer otr a asignacin indicndola explcitamente:
enum {pino=7, chopo, alamo=3, abeto, abedul} ar bol;
enumer ador valor
pino 7
chopo 8
alamo 3
abeto 4
abedul 5
C.05.40
Ejemplo
...
enum dia { lun, mar , mie, jue, vie, sab, dom };
...
/*
Esta funcion devuelve el dia siguiente
*/
enum dia dia_siguiente ( d )
enum dia d;
{
r etur n ( (enum dia) ( (( int)d+1 ) % 7 );
}
La utilidad de los tipos enumer ativos se basa en dos aspectos:
Mejor an la clar idad del pr ogr ama, por su car cter
autodocumentador
Obligan al compilador a hacer test de consistencia de tipo.
C.06.01
- 6 -
LAS SENTENCIAS DE CONTROL
Oper ador es de r elacin, igualdad y lgica.
La sentencia vaca.
La sentencia compuesta.
Las sentencias " if" , " if-else" . El oper ador condicional " ?"
La sentencia " while"
La sentencia " for " . El oper ador coma " ;" .
La sentencia " do-while"
La sentencia " switch"
La sentencia " br eak"
La sentencia " continue"
La sentencia " goto"
C.06.02
OPERADORES DE RELACION, IGUALDAD Y LOGICA
Se usan par a modificar el flujo de la ejecucin.
Op. de Relacin: < menor que
> mayor que
<= menor o igual que
>= mayor o igual que
Op de Igualdad: == igual a
!= distinto de
Op. de Lgica: ! negacin
&& AND lgico
|| OR lgico
El oper ador " ! " es unar io, los dems son binar ios.
Todos oper an sobr e expr esiones dando como r esultado uno de dos:
0 FALSO
1 VERDADERO
En C: FALSO es 0 0.0
VERDADERO es distinto de 0,
o distinto de 0.0
C.06.03
Pr ior idad (or den descendente) y asociatividad de oper ador es de
r elacin y algunos otr os
! -(unar io) ++ -- sizeof(tipo) der echa a izquier da
* / % izquier da a der echa
+ - izquier da a der echa
< <= > >= izquier da a der echa
== != izquier da a der echa
&& izquier da a der echa
|| izquier da a der echa
= += -= *= ... der echa a izquier da
, (coma) izquier da a der echa
Tabla semntica de los oper ador es de r elacin
valor de e1-e2 e1<e2 e1>e2 e1<=e2 e1>=e2
positivo 0 1 0 1
cero 0 0 1 1
negativo 1 0 1 0
Analizar el valor de la expr esin: 3<j<5
si j tiene el valor 7
( 3<j )<5 ---> 1<5 ---> 1
j=7;
pr intf(" %d\n" , 3<j<5); se escr ibir : 1
Si se tr ata de chequear si el valor de " j" est compr endido entr e 3 y 5,
hay que escr ibir :
3<j && j<5
C.06.04
Los oper ador es de igualdad: == !=
son binar ios
actan sobr e expr esiones
pr oducen un valor lgico: int 0 FALSO
int 1 VERDADERO
Semntica:
valor de e1-e2 e1==e2 e1!=e2
cero 1 0
no cer o 0 1
Par a la expr esin a==b,
a nivel de mquina se r ealiza: a-b==0
Hay que distinguir entr e: == y =
if ( i=1 ) .... la expr esin " i=1" siempr e devuelve
el valor VERDADERO
if ( i==1 ) ..... la expr esin " i==1" devuelve el valor
VERDADERO si la var iable " i" tiene
el valor 1.
C.06.05
Los oper ador es lgicos: ! && ||
Se aplican a expr esiones
El oper ador " !" es unar io, los dems son binar ios
Pr oducen uno de estos valor es: int 0 FALSO
int 1 VERDADERO
Semntica del oper ador " ! "
expr esin ! expr esin
cero 1
no cer o 0
Difer encia con el oper ador de negacin en Lgica:
no ( no x ) es x
! ( ! 5 ) es 1
Semntica de los oper ador es " &&" y " ||"
valor es de
exp1 exp2 exp1 && exp2 exp1 || exp2
cero cero 0 0
cero no cer o 0 1
no cer o cero 0 1
no cer o no cer o 1 1
C.06.06
Al evaluar expresiones que son operandos de "&&" o de "||", el
proceso de evaluacin se detiene tan pronto como se conoce el
resultado (verdadero o falso) final de la expresin:
en exp1 && exp2
si exp1 tiene el valor 0, no se evala exp2
en exp1 || exp2
si exp1 tiene el valor 1, no se evala exp2.
Ejemplo
i=0;
while (i++<3 && (c=getchar()) != EOF) accin...
la accin se ejecuta para los tres primeros caracteres del fichero,
mientras que no se alcance EOF.
Cuando "i" toma el valor 3, la expresin "i++<3" toma el valor
FALSO y deja de evaluarse la siguiente. Por tanto, en otra sentencia
de lectura posterior, se obtendra el cuarto caracter, no el quinto.
C.06.07
La sentencia vaca
" ; "
for ( n=0; getchar () != EOF; ++n) ;
Sentencia compuesta
Una ser ie de sentencias encer r adas entr e llaves.
Si hay declar aciones al pr incipio, entonces se llama
BLOQUE.
Una sentencia compuesta se puede poner en cualquier
lugar donde pueda ir una simple
{
int i;
float p;
p=1.0;
for (i=1; i<=e; ++i) p=p*b;
r etur n(p);
}
C.06.08
Las sentencias " if " " if - else "
if ( expr esi on ) sentenci a1 else sentenci a2
if ( expr esi on ) sentenci a
Se evala la expr esin. Si tiene un valor distinto de cer o se ejecuta la
" sentencia1" y se salta la " sentencia2" . Si tiene el valor cer o, se salta la
" sentencia1" y se ejecuta la " sentencia2" .
expr esin
ver dader o falso
sentencia_1
sentencia_2
La expr esin puede ser de cualquier tipo.
if ( x<min ) min=x;
------
if ( c==' ' ) {
++contador ;
pr intf(" hallado otr o espacio en blanco\n" );
}
------
i=0;
if ( (c=getchar ()) != EOF ) s[i++]=c;
else s[i]=' \0' ;
C.06.09
int n;
if ( n%2 == 0 ) printf("%d es par\n", n);
else printf("%d es impar\n", n);
------
/*
ej8.c
*/
# include <stdio.h>
void main( )
{
char c;
c=getchar( );
if ( ( c>=65 ) && ( c<=90 ) )
printf("Es letra mayuscula\n");
else {
if ( (c>=97) && (c<=122) )
printf("Es letra minuscula\n");
else
printf("No es un caracter alfabetico\n");
}
}
C.06.10
Cuando el compilador lee var ias sentencias " if " anidadas:
asocia cada " else " con el " if " ms
pr ximo.
if ( c == ' ' )
++blancos;
else if ( ' 0' <=c && c<=' 9' )
++cifr as;
else if (' a' <=c && c<=' z' || ' A' <=c && c<=' Z' )
++letr as;
else if (c ==' \n' )
++saltos;
else
++otr os;
C.06.11
El oper ador condicional " ? "
Es un oper ador ter nar io.
exp1 ? exp2 : exp3
Se evala la expr esin " exp1" . Si tiene valor distinto de cer o, se evala
la expr esin " exp2" y su r esultado ser el valor de la expr esin.
Si " exp1" tiene valor cer o, se evala " exp3" y su r esultado ser el
valor de la expr esin.
La sentencia: x = ( y<z ) ? y : z ;
Tiene un efecto equivalente a: if ( y < z )
x=y;
else
x=z;
Ejemplo:
Escr ibir los elementos de un " ar r ay" de " int" poniendo cinco en
cada linea :
#define TAM 100
...
int a[TAM];
...
for ( i=0; i<TAM; ++i )
pr intf(" %c%12d" , ( i%5 == 0 ) ? ' \n' : ' \0' , a[i] );
C.06.12
La sentencia " while "
while ( expr esi on ) sentenci a
Se evala la " exper sion" . Si tiene valor distinto de cer o (ver dader o), se
ejecuta la " sentencia" y el contr ol vuelve al pr incipio del ciclo. Cuando
la " expr esin" tiene el valor cer o, ter mina la ejecucin del bucle y se
pasa a la sentencia siguiente.
expr esion
es
cer o
sentencia
NO
SI
salida
entr ada
La " sentencia" se puede ejecutar cer o o ms veces.
while ( (c=getchar () ) == ' ' )
; /* sentencia vacia */
int i=2, max=100;
while ( i<max) {
pr intf(" %d\n" , i);
i=i+2;
}
C.06.13
/* contar el numer o de car acter es almacenados en un
ficher o, incluyendo los saltos de linea
*/
int n=0;
while ( getchar () != EOF ) ++n;
# define TOTAL 100
. . .
float v[TOTAL];
int n;
n=0;
while ( n<TOTAL ) {
v[n]=0.0;
++n;
}
while ( scanf(" %d" , &enter o) != EOF )
pr intf(" El valor leido es: %d\n" , enter o);
C.06.14
La sentencia " for "
for ( expr esi on1 ; expr esi on2 ; expr esi on3 ) sentenci a
Su semntica es equivalente a la de:
expr esion1;
while ( expr esion2 ) {
sentencia
expr esion3;
}
factor ial=1;
for (i=1; i<=n; ++i) factor ial *= i;
Pueden faltar alguna o todas las expr esiones, per o deben per manecer los
signos de punto y coma:
i=1; suma=0;
for ( ; i<=10; ++i) suma += i;
es equivalente a:
i=1; suma=0;
for ( ; i<=10 ; ) suma += i++;
Cuando falta la " expr esion2" , se le supone valor ver dader o siempr e,
for mandose un ciclo sin salida:
i=1; suma=0;
for ( ; ; ) {
suma += i++;
pr intf(" %d\n" , suma);
}
C.06.15
{
float v[100];
int num=25, i;
for ( i=0; i<num; ++i ) v[i]=0.0;
}
/*
ej9.c
escribir una tabla de verdad
*/
# include <stdio.h>
# define EXPRESION a&&b
# define T 1
# define F 0
void main( )
{
int a, b;
for ( a=F; a<=T; ++a) {
for ( b=F; b<=T; ++b) {
if ( EXPRESION) printf("T ");
else printf("F ");
}
printf("\n");
}
}
C.06.16
El oper ador coma " , "
Es un oper ador binar io par a expr esiones :
expr esi on1 , expr esi on2
Se evala pr imer o " expr esion1" y despus se evala " expr esion2" . La
expr esin coma tiene el valor y tipo de su oper ando der echo.
suma=0 , i=1
Se suele usar en las sentencias " for " por que per mite hacer asignacin
mltiple de valor es iniciales y pr ocesamiento mltiple de ndices.
for ( suma=0, i=1; i<=n; ++i ) suma += i;
pr intf(" %d\n" , suma);
for ( suma=0, i=1; i<=n; suma += i, ++i) ;
pr intf(" %d\n" , suma);
Par a impr imir la suma de los pr imer os " n" enter os par es y la de los
pr imer os " n" enter os impar es, puede escr ibir se:
for (cont=0, j=2, k=1; cont<n; ++cont, j += 2, k += 2) {
suma_par += j;
suma_impar += k;
}
pr intf(" %7d %7d\n" , suma_par , suma_impar );
C.06.17
La sentencia " do "
Es una var iante de " while" . En " do" , el test se hace al final del bucle.
do sentenci a while ( expr esi n );
expr esion
es
cer o
sentencia
NO
SI
salida
entr ada
/*
Se r epite la or den de lectur a mientr as
el valor intr oducido sea menor o igual
que cer o
*/
{
int n;
do {
pr intf(" Enter o positivo ? " );
scanf(" %d" , &n);
} while ( n<=0 );
}
int i=o, exponente;
float base, potencia;
. . .
potencia=1.0;
do { potencia *= base; ++i } while ( i<exponente );
C.06.18
/*
ej10.c
Calculo del numero "e" . ( x
n
= ( 1+ 1/n)
n
)
Contiene funciones para obtener el valor absoluto de un
numero y para obtener potencias de exponente entero
positivo.
*/
# include <stdio.h>
void main()
{
int n=1;
float eant, e=2, precision;
float abs(float), potencia(float, int);
printf("Que precision?\n");
scanf("%f", &precision);
do {
eant=e;
++n;
e = potencia (1.0+1.0/ (float) n, n );
}
while ( abs(e-eant) >= precision );
printf("e= %f\n",e);
printf("precision= %f\n", precision);
}
/* Devuelve el valor absoluto de un numero real. */
float abs(float r)
{
if ( r < 0.0 ) return (-r);
else return (r);
}
/* Calcula potencias de exponente entero positivo */
float potencia (float b, int e)
{
int i;
float p;
p=1.0;
for (i=1; i<=e; ++i) p=p*b;
return(p);
}
C.06.19
La sentencia " switch "
Es una sentencia condicional mltiple que gener aliza a la sentencia " if-
else" .
switch ( expr esi on_enter a ) {
case expr esi on_constante_enter a : sentenci a
br eak;
case expr esi on_constante_enter a : sentenci a
br eak;
. . .
default : sentenci a
}
1. Se evala la " expr esion_enter a"
2. Se ejecuta la clasula " case" que se cor r esponda con el valor
obtenido en el paso 1. Si no se encuentr a cor r espondencia, se
ejecuta el caso " default" ; y si no lo hay, ter mina la ejecucin de
" switch" .
3. Ter mina cuando se encuentr a una sentencia " br eak" o por cada al
vaco.
c=getchar ( );
while ( c != ' .' && c != EOF ) do {
switch ( c ) {
case ' c' : consultas( );
br eak;
case ' a' : altas( );
br eak;
case ' b' : bajas( );
br eak;
case ' m' : modificaciones( );
br eak;
default : error( );
}
c=getchar ( );
}
c.06.19.a
/*
ej11.c
Se leen caracteres por STDIN contando la cantidad de
cifras, espacios (tabulador o salto de linea) y otros.
*/
#include <stdio.h>
void main()
{
int c, i;
int blancos=0;
int otros=0;
static int cifs[10]={0,0,0,0,0,0,0,0,0,0};
while ( (c=getchar()) != EOF )
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
cifs[c-'0']++;
break;
case ' ':
case '\n':
case '\t':
blancos++;
break;
default:
otros++;
break;
}
printf ("cifras: ");
for (i=0; i<10; i++) printf("%d",cifs[i]);
printf("\nblancos: %d, otros: %d\n", blancos, otros);
}
C.06.20
La sentencia " br eak "
Par a for zar la salida inmediata de un bucle, saltando la evaluacin
condicional nor mal.
Par a ter minar una clasula " case" de sentencia " switch" y
finalizar su ejecucin.
# include <math.h>
...
while ( 1 ) {
scanf(" %lf" , &x);
if ( x<0.0 ) br eak;
pr intf(" %f\n" , sqr t(x));
}
switch ( c ) {
case ' .' : mensaje(" fin" );
br eak;
case ' ?' : ayuda( );
br eak;
default : pr ocesar (c);
}
C.06.21
La sentencia " continue "
Se detiene la iteracin actual de un bucle y se inicia la siguiente de
inmediato.
for ( i=0; i<TOTAL ;++i ) {
c=getchar( );
if ( '0'<=c && c<'9' ) continue;
procesar(c);
}
El caso: Es equivalente a:
for ( exp1; exp2; exp3 ) { exp1;
. . . while ( exp2 ) {
continue . . .
. . . goto siguiente
} siguiente: exp3;
}
/* ej12.c */
# include <stdio.h>
void main ( )
{
char fin, c;
fin=0;
while ( !fin ) {
c=getchar( );
if ( c == '$') { fin=1;
continue;
}
putchar(c+1);
}
}
C.06.22
La sentencia " goto "
Bifur cacin incondicional a una sentencia etiquetada ar bitr ar iamente
dentr o de la funcin.
La sentencia " goto" y su sentencia etiquetada cor r espondiente deben
estar en el cuer po de la misma funcin.
. . .
{
. . .
goto er r or ;
. . .
}
error: mensaje( );
Su uso est desaconsejado por que suele r omper la estr uctur acin de
los algor itmos.
CONVIENE NO USARLA MUCHO
C.07.01
- 7 -
LAS FUNCIONES
El diseo descendente. Las funciones. La funcin " main" .
Definicin o declar acin de funciones.
El tipo " void" .
Valor de r etor no.
Llamada a una funcin.
La tr ansmisin de valor es. Paso por valor .
Reglas de alcance. Clases de almacenamiento.
Recur sividad.
C.07.02
Las funciones
Un programa escrito en C est formado por una o varias funciones.
Cada funcin expresa la realizacin del algoritmo que resuelve una de las
partes en que se ha descompuesto el problema completo en cuestin.
En el mtodo de anlisis descendente, un problema complejo se
descompone sucesivamente en partes cada vez ms simples hasta que
resulta trivial su programacin.
Con el lenguaje C, cada una de esas partes se resuelve con una
funcin.
Formalmente, una funcin tiene un nombre y est formada por un conjunto de
sentencias que se ejecutan devolviendo un valor al medio que la invoca.
Todo programa debe contener la funcin "main", que es la invocada desde el
sistema operativo cuando comienza la ejecucin del programa.
La funcin "main" controla la ejecucin del resto del programa.
La funcin "main" devuelve un valor entero al sistema cuando
termina la ejecucin. Dicho valor se puede controlar con la funcin de
biblioteca "exit".
# include <stdio.h>
# include <stdlib.h>
/* ej13.c */
void main()
{ int b, e, p, i;
printf("Calculo de potencias de exponente entero > 0\n");
printf("Introducir base y exponente\n");
scanf("%d %d", &b, &e);
if ( e<=0 ) exit(-1);
else { for ( p=1, i=1; i<=e; ++i ) p *=b;
printf("%d elevado a %d es %d\n", b, e, p);
exit(0);
}
}
C.07.03
Las funciones: se definen
se asocian a un tipo de datos
se invocan
se ejecutan
devuelven un valor
Definicin de una funcin
Las funciones que componen un pr ogr ama pueden definir se en
ficher os difer entes o en el mismo ficher o.
ti po nombr e ( l i sta_de_par metr os )
{
cuer po
}
Sus elementos, con ms detalle:
Encabezamiento . . . . . . . . . ti po nombr e ( p1, p2, p3,...)
Declar acin de par metr os . . ti po p1, p2, p3...;
{
Cuer po con: Declar aciones . . . . . ti po v1,v2,v3,...;
Sentencias . . . . . . . . sentenci a
sentenci a
. . .
r etur n (expr esi n)
}
Si no se declar a tipo, adquier e tipo " int" .
La lista de par metr os per mite la tr ansmisin de valor es entr e
funciones.
Hay que declar ar el tipo de cada par metr o. Si no se hace,
adquier en el tipo " int" .
El cuer po puede contener declar aciones que deben estar al pr incipio
de los bloques.
No se pueden definir otr as funciones dentr o de una funcin
C.07.04
/*
ej14.c
Captura el primer argumento, se convierte a entero ("int")
y se multiplica por 2.
Uso: a.out cifras
*/
# include <stdio.h>
void main(int argc, char *argv[ ])
{
int num(char *);
if (argc == 1)
printf("Uso: a.out cifras\n");
else printf("El doble es: %d\n", 2*num(argv[1]));
}
int num (char s[ ])
{
int i,n;
n=0;
for (i=0; s[i] >= '0' && s[i] <= '9'; ++i)
n=10*n+s[i]-'0';
return(n);
}
C.07.05
/*
ej1.c
Indica el menor de dos enteros leidos
*/
#include <stdio.h>
main ( )
{
int n1, n2, menor ( );
printf("Introducir dos enteros: \n");
scanf("%d%d", &n1, &n2);
if ( n1 == n2 )
printf("Son iguales \n");
else
printf("El menor es: %d\n", menor (n1, n2));
}
int menor ( a, b )
int a, b;
{
if ( a < b ) return ( a );
else return ( b );
}
COMENTARIOS
SENTENCIA PARA
EL PRE-PROCESADOR
DEFINICION DE LA
FUNCION "main"
Encabezamiento. No hay
parmetros
Declaraciones de objetos
locales
Cuerpo de la funcin
Sentencias
DEFINICION DE LA
FUNCION "menor"
Encabezamiento. Los
parmetros son "a" y "b"
Declaracin de los parmetros
Cuerpo de la funcin.
No contiene declaraciones
C.07.05.a
En el standard ANSI, se pueden declarar los tipos de los argumentos.
Ello permite que el compilador realice tests de consistencia entre los
parmetros actuales y los formales.
main( )
{
int i, n;
float r, a[10];
int funcion(int, float, float[ ]);
n=5;
r=3.14;
for ( i=0; i<n; ++i ) a[i]=(float)i+r;
funcion(n, r, a);
}
int funcion ( int n, float x, float v[ ] )
{
int i;
printf("primer parametro: %d\n", n);
printf("segundo parametro: %12.4f\n", x);
for (i=0; i<n; ++i) printf("v[%d]: %12.4f\n", i, v[i]);
}
C.07.06
El tipo " void "
Se usa en los casos en que no se pr etende que la funcin devuelva un
valor .
void saltar _lineas ( n )
int n;
{
int i;
for ( i=1; i<=n; ++i ) pr intf(" \n" );
}
Cuando se declar a tipo " void" :
Se puede invocar a la funcin como si fuer a una sentencia
satar _lineas (10);
No se puede poner la funcin en una expr esin donde se
r equier a un valor .
Cuando no se declar a tipo explcitamente:
El sistema asigna el tipo " int"
La funcin devuelve un valor aleator io aunque no contenga una
sentencia " r etur n"
C.07.07
El valor de r etor no
El valor que devuelve una funcin al medio de llamada se puede
deter minar con la sentencia " r etur n" .
r etur n;
r etur n ( expr esi n );
Semntica:
concluye la ejecucin de la funcin y se devuelve el
contr ol al medio que la invoc. El valor de la expr esin se
convier te al tipo de la funcin y se devuelve como valor
de la funcin.
Se puede omitir la sentencia " r etur n" . Entonces:
el contr ol se devuelve cuando se alcanza la llave " }" que
delimita el cuer po de la funcin.
El valor devuelto queda indefinido si falta la sentencia " r etur n" o si
apar ece sin indicacin de expr esin.
C.07.07.a
En algunas implementaciones las funciones no
pueden devolver
ar r ays
str ucts
unions
funciones
per o pueden devolver apuntador es a esos objetos
No se per miten los " ar r ays" de funciones,
per o s los " ar r ays" de apuntador es a funcion.
Una estr uctur a (str uct) no puede contener una
funcin,
per o si puede contener apuntador es a funciones.
int i, *ip, f(), *fip(), ( *pfi )();
i enter o
ip punter o a enter o
f funcion que devuelve un enter o
fip funcin que devuelve punter o a un enter o
pfi punter o a funcin que devuelve enter o (la
indir eccin r especto a un punter o a
funcin, es una funcin que devuelve un
enter o).
C.07.08
Llamada a una funcin
Una funcin se puede usar de dos for mas.
Invocndola nor malmente:
escr ibiendo su nombr e seguido de una lista de par metr os
escr itos entr e par ntesis.
c = getchar ( );
m = r aiz ( m );
s = menor ( lista, num );
peso = volumen ( a, b, c) * densidad (mater ial);
Tomando su dir eccin:
Cuando el nombr e de una funcin apar ece dentr o de una
expr esin en un lugar que no es el que le cor r esponde segn
el for mato nor mal indicado antes, se gener a un punter o a la
funcin.
Esto per mite pasar una funcin a otr a.
main()
{
int f( ), g( );
...
...
g ( f );
...
}
int g(funcion)
int (*funcion) ( );
{
...
(*funcion) ( );
...
}
C.07.09
Semntica de la llamada a una funcin
1. Se evala cada expr esin de la lista de ar gumentos.
2. Al pr incipio del cuer po de la funcin, se asigna el valor de cada
expr esin a su par metr o for mal cor r espondiente.
3. Se ejecuta el cuer po de la funcin.
4. Si se ejecuta una sentencia " r etur n" , el contr ol r egr esa al medio que
hizo la llamada.
5. Si la sentencia " r etur n" incluye una expr esin, el valor de la
expr esin se convier te (si es necesar io) al tipo de la funcin, y ese
valor se devuelve al medio que hizo la llamada.
6. Si no hay una sentencia " r etur n" , el contr ol r egr esa al medio que
hizo la llamada cuando se llega al final del cuer po de la funcin.
7. Si se ejecuta una sentencia " r etur n" que no tiene expr esin o si no
hay sentencia " r etur n" , entonces no se devuelve ningn valor
deter minado al medio de llamada (el valor de r etor no queda
indefinido).
8. Todos los ar gumentos pasan con una " llamada por valor " .
C.07.10
/*
ej15.c
Paso de funcion por lista de parametros
*/
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
void main ( )
{
float r, rad;
float raiz(float (*f)(float), float);
float estandar(float), aprox(float);
char opcion;
printf("Introducir radicando y opcion(1/2)\n");
scanf("%f %c", &rad, &opcion);
switch ( opcion ) {
case '1' : r=raiz(estandar, rad);
break;
case '2' : r=raiz(aprox, rad);
break;
default : printf("opcion incorrecta\n");
exit(-1);
}
printf("radicando: %f opcion: %c raiz: %f\n",
rad, opcion, r);
}
float raiz( float (*f)(float), float v )
{ return( (*f)(v) ); }
float estandar(float rad)
{ return( sqrt(rad) ); }
float aprox(float rad)
{
float r1, r2=1.0;
do {
r1=r2;
r2=( rad/r1 + r1 )/(float)(2);
} while ( abs(r2-r1) > 1e-3*r1 ); return(r2);
}
C.07.11
La tr ansmisin de valor es. El paso por valor .
Al llamar a una funcin se le pueden pasar pasar valor es por la lista de
par metr os.
Los par metr os se pasan " por valor " :
Se evalan las expr esiones de la lista de par metr os de paso y los
valor es r esultantes se asignan a sus par metr os for males
cor r espondientes.
Las modificaciones en los valor es de los par metr os for males de la
funcin, no afectan a las var iables del medio que hizo la llamada.
Si se quier e conseguir el efecto later al de afectar a las var iables del
medio de llamada, hay que inducir el paso por r efer encia, pasando
dir ecciones de var iables en vez de sus valor es:
Entonces, se usan los par metr os for males desr efer enciados
dentr o de la funcin.
Paso por valor Paso por r efer encia
{ {
int n,m; int n,m;
n=5; n=5;
pr intf(" %d\n" , n); pr intf(" %d\n" , n);
m=doble( n ); m=doble( &n );
pr intf (" %d\n" , n); pr intf (" %d\n" , n);
} }
int doble(i) int doble(i)
int i; int *i;
{ {
i *= 2; *i *= 2;
r etur n ( i ); r etur n( *i );
} }
C.07.12
Var iables locales
Todas las var iables declar adas en el cuer po de una funcin son
" locales" a esa funcin:
Slo existen dur ante la ejecucin del bloque en el que se han
declar ado.
Var iables globales
Las var iables que no han sido declar adas ni como ar gumentos, ni en el
cuer po de una funcin son " globales" a la funcin y deben estar
definidas exter namente:
Existen dur ante la ejecucin de todo el pr ogr ama.
C.07.13
int g; /* " g" es var iable global */
main( )
{
int a, b;
. . .
. . .
{
float b, x, y;
. . . /* se conoce a " int a" , per o no
. . . a " int b" , que ha quedado
enmascar ada. */
}
{
unsigned a;
char c, d;
. . . /* se conoce a " int b" , per o no a
. . . " int a" .
No se conoce a " x" ni a " y" */
}
...
... /* se conoce a " int a" y a " int b" .
... No se conoce a " x" , " y" , " c" */
...
}
La var iable " g" es conocida en todos los bloques.
C.07.14
Clases de almacenamiento
Las var iables y las funciones tienen dos atr ibutos:
tipo
clase de almacenamiento
Hay cuatr o clases de almacenamiento:
auto
exter n
register
static
Var iables de clase " auto"
Las var iables declar adas dentr o del cuer po de las funciones son
automticas por omisin.
Son equivalentes estas dos for mas:
{ {
char c; auto char c;
int i, j, k; auto int i, j, k;
... ...
} }
Tienen almacenamiento dinmico:
Cuando se entr a en el bloque, se r eser va memor ia
automticamente y se liber a al abandonar lo.
Slo existen mientr as dur a la ejecucin del bloque donde han
sido declar adas.
C.07.15
Var iables de clase " exter n"
A las var iables declar adas fuer a de una funcin se les asigna
almacenamiento per manente. Son de clase " exter n" .
Se consider an globales par a todas las funciones declar adas despus de
ellas.
Existen dur ante toda la vida del pr ogr ama.
Se pueden usar par a compar tir valor es entr e funciones, per o se
r ecomienda no hacer lo. Es pr efer ible canalizar la tr ansmisin de
valor es por la lista de par metr os siempr e par a evitar efectos later ales.
La especificacin " exter n" se puede utilizar par a indicar que la
var iable se esper a de otr o contexto, aunque la declar acin no est
contenida en el mismo ficher o.
Var iables de clase " r egister "
Se almacenan en r egistr os de memor ia de alta velocidad si es posible
fsica y semnticamente.
Se utiliza par a las var iables de uso muy fr ecuente (contr ol de bucles,
por ejemplo).
Su uso es muy limitado por que suele haber muy pocos r egistr os de alta
velocidad.
Su declar acin es una suger encia par a el compilador .
C.07.16
Var iables de clase " static"
Locales estticas
El almacenamiento " static" per mite que una var iable local r etenga su
valor pr evio cuando se entr a de nuevo en el bloque donde r eside.
Globales estticas
Las var iables exter nas estticas pr opor cionan una pr opiedad de
pr ivacidad muy inter esante par a la pr ogr amacin modular :
Son de alcance r estr ingido al r esto del ficher o fuente en el
que se han declar ado.
Se puede conseguir que sean pr ivadas a un conjunto de
funciones
Funciones estticas
El almacenamiento " static" se puede aplicar a funciones.
Las funciones estticas son visibles slo dentr o del ficher o en el que se
han declar ado (til par a desar r ollar mdulos pr ivados).
C.07.17
La recursividad
En C, las funciones tienen la propiedad de poderse invocar a s mismas.
/*
ej16.c
Calculo de potencias con algoritmo recursivo.
*/
potencia(int b, int e)
{
if (e == 0) return(1);
else return(b*potencia(b, e-1));
}
/*
ej17.c
Calculo del factorial con algoritmo recursivo
*/
factorial ( int n )
{
if ( (n==1) || ( n==0) ) return(1);
else return ( n*factorial(n-1) );
}
C.08.01
- 8 -
LOS TIPOS DE DATOS ESTRUCTURADOS.
VISION GENERAL.
ar r ay
str ing
str uct
bits
union
C.08.02
Los tipos de datos estr uctur ados
Pueden contener ms de un componente simple o estr uctur ado a la
vez.
Se car acter izan por :
El tipo o los los tipos de los componentes
La for ma de la or ganizacin
La for ma de acceso a los componentes
ar r ay ( ar r eglo homogneo de acceso dir ecto)
str ing ( cadena de car acter es )
str uct ( estr uctur a heter ognea )
bits ( campos de bits )
union ( compar tir memor ia )
C.08.03
El tipo " ar r ay "
Una or ganizacin de datos car acter izada por :
Todos los componentes son del mismo tipo (homogneo).
Acceso dir ecto a sus componentes. Todos sus componentes
se pueden selecionar ar bitr ar iamente y son igualmente
accesibles
int v[100], a[100][100];
v[10]=5; v[i]=0; v[i++]=3;
for ( i=0; i<100; i++ ) v[i]=0;
for ( i=0; i<100; i++ )
for ( j=0; j<100; j++ ) a[i][j]=0;
C.08.04
El tipo str ing (cadena de car acter es)
Una cadena de car acter es es:
Un " ar r ay" unidimensional de tipo " char "
que ter mina con el car acter nulo ( ' \0' ).
char lin[80];
' c' ' a' ' d' ' e' ' n' ' a' ' \0'

El lenguaje no tiene oper ador es par a
manejar cadenas de car actes.

Se manejan con funciones de biblioteca
C.08.05
El tipo " str uct"
Las estr uctur as (" str uct" ) son or ganizaciones de datos cuyos
miembr os pueden ser de tipos difer entes.
str uct naipe {
int valor ;
char palo;
};
str uct naipe car ta, c;
...
car ta.valor =10;
car ta.palo=' e' ;
c=car ta;
enum palos {or os, copas, espadas, bastos};
str uct naipe {
int valor ;
enum palos palo;
};
car ta.palo=espadas;
C.08.06
Campos de bits
Son miembr os consecutivos de una estr uctur a ( " str uct" ) que
contienen un nmer o constante no negativo de bits.
str uct byte {
unsigned bit0: 1,
bit1: 1,
bit2: 1,
bit3: 1,
bit4: 1,
bit5: 1,
bit6: 1,
bit7: 1;
};
byte c;
c.bit0=1;
c.bit1=0;
c.bit2=0;
str uct naipe {
unsigned valor : 4;
unsigned palo : 2;
}
str uct naipe car ta;
car ta.valor =9;
car ta.palo=2;
C.08.07
El tipo " union "
Las uniones son estr uctur as (" str uct" ) cuyos miembr os compar ten
memor ia.
str uct octetos {
unsigned byte0: 8, byte1: 8, byte2: 8, byte3: 8;
};
str uct bits {
unsigned
bit0 :1, bit1 :1, bit2 :1, bit3 :1,
bit4 :1, bit5 :1, bit6 :1, bit7 :1,
bit8 :1, bit9 :1, bit10 :1, bit11 :1,
bit12 :1, bit13 :1, bit14 :1, bit15 :1,
bit16 :1, bit17 :1, bit18 :1, bit19 :1,
bit20 :1, bit21 :1, bit22 :1, bit23 :1,
bit24 :1, bit25 :1, bit26 :1, bit27 :1,
bit28 :1, bit29 :1, bit30 :1, bit31 :1;
};
union palabr a {
int x;
str uct octetos y;
str uct bits z;
} w;
w.x=7;
w.y.byte3=' a' ;
w.z.bit5=1;
union equivalencia {
int i;
char c;
};
union equivalencia x;
x.i=5;
x.c=' A' ;
C.09.01
- 9 -
" ARRAYS" , CADENAS Y PUNTEROS.
El tipo " ar r ay" . " Ar r ays" unidimensionales. Declar acin. Descr iptor
de elemento.
Inicializacin de " ar r ays" .
El ndice.
Punter os y " ar r ays" . La ar itmtica de punter os.
Ar r ays multidimensionales.
Paso de " ar r ays" a funciones.
Cadenas de car acter es.
Funciones de biblioteca par a manejar cadenas.
" Ar r ays" de punter os. Pr ogr ama par a or denas palabr as . Paso de
ar gumentos a la funcin " main" .
" Ar r ays" no unifor mes.
C.09.02
El tipo " ar r ay "
Or ganizacin de datos que se car acter iza por que todos los
componentes:
Son del mismo tipo (homognea).
Se pueden acceder ar bitr ar iamente y son igualmente
accesibles (acceso dir ecto).
Declar acin: ti po i denti fi cador [ tamao ];
int v[10];
El " tamao" tiene que ser una expr esin enter a positiva que
indica el nmer o de elementos del ar r eglo.
Los elementos se identifican escr ibiendo el nombr e de la
var iable y un ndice escr ito entr e cor chetes:
v[0] v[1] v[2] . . . v[8] v[9]
lmite infer ior del ndice = 0
lmite super ior del ndice = tamao-1
El uso de constantes simblicas facilita la modificacin de los
pr ogr amas:
#define TAM 10
int a[TAM];
Pueden tener clase de almacenamiento: automtica
esttica
exter na
No est per mitida la clase : register
C.09.03
Inicializacin de " ar r ays"
Asignacin de valor en la sentencia de declar acin.
Se pueden inicializar los de clase " static" o " exter n" .
No se pueden inicializar los de clase " auto" .
Sintaxis:
cl ase ti po i denti fi cador [tamao] = {l i sta de val or es };
static float v[5]={0.1, 0.2, -1.7, 0.0, 3.14};
Si se escr iben menos valor es, el r esto de elementos se inicializan a
cero.
static int a[20] = { 1,2,3,4,5,6 };
Si no se declar tamao, se deduce de la inicializacin.
static int a[ ] = { 0,0,0 };
C.09.04
El ndice
Los elementos de un " ar r ay" r esponden a un nombr e de var iable
comun y se identifican por el valor de una expr esin enter a, escr ita
entr e cor chetes, llamada ndice.
Modificando el valor del ndice se puede r ecor r er toda la estr uctur a.
# define TAM 100
int i, a[TAM], suma;
suma=0;
for ( i=0; i<TAM; ++i ) suma += a[i];
El ndice debe tomar valor es positivos e infer ior es al indicado en la
declar acin.
Si el ndice sobr epasa el lmite super ior , se obtiene un valor incor r ecto
por que se est haciendo r efer encia a una posicin de memor ia ajena al
" ar r ay" .
Los desbor damientos no se suelen avisar dur ante la
ejecucin.
C.09.05
Punter os y " ar r ays"
Los punter os y los " ar r ays" se usan de for ma par ecida par a acceder a
las dir ecciones de memor ia.
El nombr e de un " ar r ay" es un punter o constante.
(Repr esenta una dir eccin constante).
Es la posicin en memor ia donde comienza el " ar r ay"
(la que ocupa el pr imer elemento).
La declar acin de un " ar r ay" pr oduce:
La asignacin de una dir eccin base
La r eser va de un espacio suficiente par a almacenar los valor es
de todos los elementos.
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
v [0] v [1]
v [2]
# define TAM 3
int v [TAM]
Un valor de tipo " int" ocupa 4 bytes en
ar quitectur as de 32 bits
El nombr e del " ar r ay" ( " v" ) r epr esenta la dir eccin
base.
Un descr iptor de elemento r epr esenta un valor de tipo
" int" (v[1]).
C.09.06
Segn el ejemplo anter ior :
Si: int *p;
Son equivalentes: p = v; p = &v[0];
asignan 1024 a " p"
Son equivalentes: p = v+1; p = &v[1];
asignan 1028 a " p"
Ar itmtica de punter os
Si " p" es un punter o a un tipo deter minado, entonces la expr esin
" p+1" r epr esenta la dir eccin en memor ia del siguiente valor del
mismo tipo. El desplazamiento depende del tipo:
es 1 byte par a char
es 4 bytes par a int
for ( p=v; p<&v[TAM]; ++p ) *p=0;
for ( i=0; i<TAM; ++i ) *(v+i) = 0;
for ( p=v; p<&v[TAM]; ++p ) suma=suma+ *p;
for ( suma=0, i=0; i<TAM; ++i ) suma += *(v+i);
Como el nombr e de " ar r ay" es una constante, las expr esiones
siguientes son incor r ectas:
v=p ++v v += 2
C.09.07
" ar r ays" multidimensionales
Son " ar r ays" de " ar r ays" .
int a[3][5];
int b[3][3][3];
Los elementos se almacenan en posiciones de memor ia contiguas desde
la dir eccin base (pr imer elemento).
La tr ansfor macin entr e el punter o y los ndices del
ar r eglo se llama funcin de tr ansfor macin del
almacenamiento.
Par a el " ar r ay a" la funcin de tr ansfor macin se especifica
consider ando que:
a[i][j] es equivalente a *(&a[0][0]+5*i+j)
a[1][2] es equivalente a *(&a[0][0]+5+2) *(&a[0][0]+7)
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[1][0] a[1][1] a[1][2] ...
Se puede pensar que el ndice que var a ms depr isa es el que est ms a
la der echa; o que las matr ices se almacenan por filas.
a+3 (dir eccin del cuar to elemento) equivale a &a[0][3]
Es ms r pido el acceso a un elemento si se utiliza la
ar itmtica de punter os, por que se evita el clculo de la
funcin de tr ansfor macin.
C.09.08
Paso de " ar r ays" a funciones
Cuando se pasa un " ar r ay" , pasa su dir eccin base por
valor . Los elementos del " ar r ay" no se copian.
int sumar ( v, n ) int sumar (v, n )
int v[ ]; int *v;
int n; . . .
{ {
int i, s=0; . . .
for ( i=0; i<n; ++i ) . . .
s += v[i]; . . .
r etur n (s); . . .
} }
llamada lo que se calcula
=============== =================
sumar (a, 100); a[0]+a[1]+...+a[99]
sumar (a, 40); a[0]+a[1]+...+a[39]
sumar (a, m); a[0]+a[1]+...+a[m-1]
sumar (&a[5], m-5); a[5]+a[6]+...+a[m-1]
sumar (v+7, 2*k); a[7]+a[8]+...+a[2*k+6]
Otr a for ma de escr ibir la funcin:
int sumar (v, n)
int v[ ], n;
{
int i, s;
for ( i=0, s=0; i<n; ++i ) s += *(v+i);
}
C.09.09
Si un " ar r ay" multidimensional es par metr o for mal
de una funcin, deben declar ar se los tamaos de todas
sus dimensiones excepto el de la pr imer a, par a que se
pueda calcular la funcin de tr ansfor macin de
almacenamiento.
int a[3][5], n, m;
. . .
. . .
sumar (b, n, m)
int b[ ][5], n, m;
{
etc...
}
En el encabezamiento de una funcin, son
equivalentes:
int b[ ][5]; int (*b)[5];
apuntador a " ar r ays" de
5 enter os
C.09.10
Las cadenas de car acter es (" str ings" )
Una cadena es un " ar r ay" unidimensional de tipo " char " .
Con el car cter nulo ( ' \0' ) se indica el final de la cadena.
Una cadena es una secuencia de car acter es
almacenados en posiciones contiguas, que ter mina con
el car cter nulo.
char s[36];
Se declar a la longitud mxima.
El car cter nulo ( ' \0' ) consume una posicin siempr e.
Se pueden almacenar cadenas de longitud var iable sobr e el
tamao mximo declar ado.
El pr ogr amador tiene que pr eocupar se de evitar el
desbor damiento.
Las constantes de cadenas se escr iben entr e comillas:
" ejemplo de cadena"
Se puede asignar valor inicial en la declar acin:
static char cad[40]=" valor inicial" ;
static char cad[40]={ ' c' , ' a' , ' d' , ' e' , ' n' , ' a' , ' \0' };
No hay oper ador es par a manejar cadenas.
Las cadenas se manejan con funciones de biblioteca
incluyendo, en el pr ogr ama, la cabecer a:
<str ing.h>
C.09.11
Funciones de biblioteca par a manejar cadenas
Estn descr itas en la seccin 3 del manual de r efer encia.
Necesitan incluir el ficher o " str ing.h" en el pr ogr ama:
# include <str ing.h>
Funciones que devuelven un " int" :
str cmp compar ar
str ncmp compar ar " n" elementos
str len longitud
etc...
Funciones que devuelven un punter o a " char " :
str cat encadenar
str ncat encadenar " n" elementos
str cpy copiar
str ncpy copiar " n" elementos
str chr localizar un elemento
etc...
C.09.12
int strcmp(char *s1, char *s2)
Compara elementos sucesivos de dos cadenas, s1 y s2, hasta que se
encuentran elementos diferentes. Si todos los elementos son iguales, la
funcin devuelve cero. Si el elemento diferente de s1 es mayor que el de
s2, la funcin devuelve un valor positivo, en caso contrario devuelve un
valor negativo.
/*
ej18.c
*/
# define TAM 40
# include <stdio.h>
# include <string.h>
void main()
{
char s1[TAM], s2[TAM];
int n;
printf("Introducir dos cadenas: ");
scanf("%s %s", s1, s2);
n = strcmp(s1, s2);
if ( n == 0 ) printf("\nSon iguales");
else if ( n<0 ) printf("\ns1 es menor que s2");
else printf("\ns1 es mayor que s2\n");
}
int strncmp(char *s1, char *s2, int n)
Es semejante a "strcmp", pero no se comparan ms de "n"
caracteres.
C.09.13
int str len(char *s)
Devuelve el nmer o de car acter es de la cadena s, sin incluir su car cter
nulo de ter minacin.
Una ver sin posible:
/*
ej19.c
*/
int str len(s)
char *s;
{
int i;
for ( i=0; *s != ' \0' ; s++ ) ++i;
r etur n( i );
}
char *str cat(char *s1, char *s2)
Copia la cadena s2, incluyendo el car cter nulo, en los elementos de la
cadena s1, empezando en el elemento de s1 que contiene el car cter
nulo. Devuelve s1.
char *str ncat(char *s1, char *s2, int n)
Es semejante a " str cat" , per o se agr egan no ms de " n" elementos no
nulos seguidos opr ' \0' . Devuelve s1.
C.09.14
char *str cpy(char *s1, char *s2)
La funcin copia la cadena s2, incluyendo su car cter nulo , en
elementos sucesivos del " ar r ay" de " char " cuyo pr imer elemento tiene
la dir eccin s1. Devuelve s1.
{
char s[24];
str cpy(s, " valor asignado" );
pr intf(" %s\n" , s);
}
char *str ncpy(char *s1, char *s2, int n)
La funcion copia la cadena s2, sin incluir el car cter nulo,en elementos
sucesivos del " ar r ay" de " char " cuyo pr imer elemento tiene la
dir eccin s1. Se copian " n" car acter es de s2 como mximo. Despus la
funcin almacena cer o o ms car acter es nulos en los siguientes
elementos de s1 hasta almacenar un total de " n" car acter es. Devuelve
s1.
char *str chr (char *s, char c)
La funcin busca el pr imer elemento de la cadena s que sea igual a
" (char )c" . Consider a el car cter nulo de ter minacin como par te de la
cadena. En caso de encontr ar lo, se devuelve la dir eccin del elemento;
en caso contr ar io, se devuelve un punter o nulo.
C.09.15
" ar r ays" de punter os
Ejemplo donde se usa un " ar r ay" de punter os a " char " en un
pr ogr ama par a or denar palabr as en sentido cr eciente.
Se utiliza una tcnica par a almacenar cadenas de car acter es de for ma
compacta:
Se declar a un " ar r ay" de " char " de tamao suficiente par a
almacenar todas las palabr as como cadenas de car acter es
contiguas:
char s[1024];
Se usa un " ar r ay" de punter os auxiliar donde se almacenan las
dir ecciones base de las cadenas en el " ar r ay" anter ior :
char *d[128];
\0 g a t
o
\0 m o s c a
s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9] s[10] s[11] . . . . . . . . . . . . . . s[1024]
d[0] d[1] d[2]
o
c a \0
C.09.16
\0 g a t
o
\0 m o s c a
s[0] s[1] s[2] s[3] s[4] s[5] s[6] s[7] s[8] s[9] s[10] s[11] . . . . . . . . . . . . . . s[1024]
d[0] d[1] d[2]
o
c a \0
char s[1024]; s[0] ='m'
char *p; s[1] ='o'
char *d[128]; s[2] ='s'
s[3] ='c'
p=s; p=&s[0] s[4] ='a'
s[5] ='\0'
scanf(" %s" , p); s[6] ='g'
s[7] ='a'
s[0]='m' s[8] ='t'
s[1]='o' s[9] ='o'
s[2]='s' s[10]='\0'
s[3]='c' s[11]='o'
s[4]='a' s[12]='c'
s[5]='\0' s[13]='a'
s[14]='\0'
d[0]=p; d[0]=&s[0] s[15]
etc....
p=p+str len(p)+1; p=&s[0]+5+1 p=&s[6]
scanf(" %s" , p);
s[6] ='g'
s[7] ='a'
s[8] ='t'
s[9] ='o'
s[10]='\0'
d[1]=p; d[1]=&s[6]
p=p+str len(p)+1 p=&s[6]+4+1 p=&s[11]
etc....
C.09.17
La funcin principal
/*
ej20.c
*/
# include <stdio.h>
# include <string.h>
# define BUFFER 1024
# define MAXPAL 128
void main( )
{
int leer_palabras(int max, char s[ ], char *d[ ]);
void escribir_palabras(char s[ ], char *d[ ], int n);
void ordenar(char s[ ], char *d[ ], int n);
char s[BUFFER], *d[MAXPAL];
int n;
if ( n=leer_palabras(MAXPAL, s, d) ) {
ordenar(s, d, n);
escribir_palabras(s, d, n);
}
}
C.09.18
La funcin "leer_palabras"
int leer_palabras(int max, char s[ ], char *d[ ])
{
char *p;
int i, num;
p=s;
printf("Cuantas palabras se van a ordenar? \n");
scanf("%d", &num);
if ( num <= max ) {
printf("Introducir %d palabras:\n", num);
for ( i=0; i<num; ++i ) {
scanf("%s", p);
d[i]=p;
p += strlen(p)+1;
}
return(num);
}
else {
printf("ERROR. Valor maximo: %d\n", max);
return(0);
}
}
La funcin "escribir_palabras"
void escribir_palabras(char s[ ], char *d[ ], int n)
{
int i;
printf("Lista ordenada:\n");
for ( i=0; i<n; ++i ) printf("%s\n", d[i]);
}
C.09.19
La funcin "ordenar"
void ordenar(char s[ ], char *d[ ], int n)
{
char *aux;
int i, j;
for ( i=0; i<n-1; ++i ) for ( j=n-1; i<j; --j)
if ( strcmp(d[j-1], d[j]) > 0 ) {
aux=d[j-1];
d[j-1]=d[j];
d[j]=aux;
}
}
C.09.20
Paso de ar gumentos a " main"
En el medio UNIX, se pueden pasar valor es a un pr ogr ama en la or den
de llamada.
$ factor ial 4
Esos valor es se pueden r ecuper ar desde la funcin " main" mediante
par metr os.
main(ar gc, ar gv)
ar gc : es el nmer o de ar gumentos que se pasan,
contando el nombr e del pr ogr ama
ar gv: es un " ar r ay" de punter os a cada uno de los
par metr os tomado como cadena de car acter es
main(ar gc, ar gv)
int ar gc;
char *ar gv[ ];
...
C.09.21
/*
ej21.c
uso: $ a.out 4
factorial de 4 = 24
*/
# include <stdio.h>
void main(argc, argv)
int argc;
char *argv[ ];
{
int num(char *), factorial(int);
int n;
if ( argc == 1 ) {
printf("Introducir un entero\n");
scanf("%d", &n);
}
else n=num(argv[1]);
printf("factorial de %d = %d\n", n, factorial(n));
}
int num(char *s)
{
int i, n;
n=0;
for ( i=0; s[i]>='0' && s[i]<='9'; ++i )
n=10*n+s[i]-'0';
return(n);
}
int factorial(int n)
{
int i, f;
if ( n == 0 || n == 1 ) return(1);
else for (i=1, f=1; i<=n; ++i) f *= i;
return(f);
}
C.09.22
" ar r ays" no unifor mes
" ar r ays" de punter os que apuntan a otr os " ar r ays" de tamaos
difer ent es.
static char *p[3] = {" Jose Per ez" , " Coso, 25" , " 252423" };
Otr a for ma menos eficaz:
static char a[3][20] = {" Jose Per ez" , " Coso, 25" , " 252423" };
El " ar r ay a" :
Es bidimensional
Puede almacenar hasta 60 car acter es
Contiene 3 " ar r ays" de " ar r ays" de 20 car acter es
El " ar r ay p" :
Es un " ar r ay" de punter os a " char "
Puede almacenar 3 punter os (3x4=12 bytes)
p[0] contiene la dir eccin base de la cadena " Jose Per ez"
p[1] contiene la dir eccin base de la cadena " Coso, 25"
p[2] contiene la dir eccin base de la cadena " 252423"
Es mejor usar el punter o " p" :
Se ocupa menos memor ia (slo la estr ictamente necesar ia).
El acceso es ms r pido por que el compilador no tiene que
gener ar cdigo par a la funcin de tr ansfor macin de
almacenamiento, como se hace par a acceder a los elementos
a[i][j]
C.10.01
- 10 -
ESTRUCTURAS, UNIONES Y TIPOS DEFINIDOS
POR EL USUARIO.
Estr uctur as. El tipo " str uct" .
Inicializacin de estr uctur as.
El oper ador " miembr o de estr uctur a" .
El oper ador punter o a estr uctur a.
Estr uctur as y funciones.
Campos de bits.
Uniones.
Tipos definidos por el usuar io.
C.10.02
Declar acin de estr uctur as
Una estr uctur a (" str uct" ) es una or ganizacin de datos heter ognea
donde sus miembr os pueden ser de tipos difer entes.
str uct naipe {
int valor ;
char palo;
} c1, c2;
aqu han quedado definidos un tipo y dos var iables:
el tipo es " str uct naipe"
las var iables son " c1" y " c2"
los miembr os de la estr uctur a son " valor " y " palo"
str uct {
int valor ;
char palo;
} car ta, bar aja[40];
aqu, no se ha definido identificador
par a el tipo.
C.10.03
Inicializacin
Las estr uctur as exter nas (" exter n" ) y estticas (" static" ) pueden
r ecibir valor es en la declar acin misma, de for ma anloga a los
" ar r ays" .
static str uct naipe {
int valor ;
char palo[8];
} car ta = { 3, " bastos" };
static str uct complejo {
float r e;
float im;
};
static str uct complejo x[3][3] = {
{ {1.0, -0.5}, {3.5, 7.3}, {0.2, 0.2} },
{ {6.0, -2.3}, {-0.7, 2.4}, {23.1, 7.2} }
}; /* a x[2][ ] se le asignan cer os */
static str uct {
char c;
int i;
float s;
} x[2][3]= { { ' a' , 1, 3e3 },
{ ' b' , 2, 4e2 },
{ ' c' , 3, 5e3 },
{ ' d' , 4, 6e2 }
};
C.10.04
El oper ador miembr o de estr uctur a " ."
El descr iptor de un miembr o de estr uctur a tiene la for ma:
var i abl e_estr uctur a.nombr e_mi embr o
Un nombr e de miembr o no se puede r epetir en una estr uctur a
Puede haber estr uctur as difer entes que tengan miembr os del
mismo nombr e
str uct complejo {
float r eal;
float imaginar ia;
} x, y, z, a[10][10];
x.r eal=2.7;
x.imaginar ia=-0.5;
y.r eal=x.r eal;
z=x;
a[2][4].r eal=x.r eal;
C.10.05
El oper ador punter o a estr uctur a " -> "
Es fr ecuente usar punter os a estr uctur as.
Por ejemplo, en las implementaciones donde no se per mite
que las funciones devuelvan valor de tipo " str uct" .
Por eso existe un smbolo especial par a los punter os a estr uctur as:
-> (" menos" seguido de " mayor que" )
La descr ipcin de un miembr o tiene la for ma:
var i abl e_punter o_a_estr uctur a ->var i abl e_mi embr o
Recor dar que los oper ador es
apuntador a estr uctur a ->
miembr o de estr uctur a .
par ntesis ( )
cor chetes [ ]
tienen la pr ior idad ms alta
asociatividad de izquier da a der echa
C.10.06
Ejemplo
str uct alumno {
int cur so;
char gr upo;
char nombr e[40];
float notas[10];
};
str uct alumno buf, *p=&buf;
buf.cur so=2;
buf.gr upo=' A' ;
str cpy( buf.nombr e, " Pedr o Per ez" );
buf.notas[5]=7.5;
expr esin
expr esin equivalente valor
============ ======================
buf.cur so p->cur so 2
buf.gr upo p->gr upo A
buf.nombr e p->nombr e Pedr o Per ez
*(p->nombr e+2) p->nombr e[2] d
*p->nombr e+2 *(p->nombr e)+2 R
C.10.07
Estr uctur as y funciones
Las estr uctur as se pueden pasar a las funciones por valor .
Las funciones pueden devolver un valor de tipo " str uct" (depende
de la implementacin).
Aunque la implementacin no per mita declar ar funciones de tipo
" str uct" , siempr e se pueden declar ar como apuntador es a " str uct" .
str uct complejo {
float r e;
float im;
};
main( )
{
str uct complejo x, y, z;
x.r e=2.5; x.im=-5.4;
y.r e=0.4; y.im=12.1;
z = *sumar (x, y);
. . .
}
str uct complejo *sumar (a, b)
str uct complejo a, b;
{
str uct complejo *z;
z->r e = a.r e + b.r e;
z->im = a.im + b.im;
r etur n(z);
}
C.10.08
Campos de bits
Son miembr os consecutivos de una estr uctur a (" str uct" ) que
contienen un nmer o constante no negativo de bits:
ti po i denti fi cador : expr esi n_constante ;
str uct wor d {
unsigned byte0 : 8,
byte1 : 8,
byte2 : 8,
byte3 : 8;
};
str uct wor d w;
w.byte0=' A' ;
w.byte1=' B' ;
Los campos per miten: Acceso cmodo al bit
Ahor r ar espacio en memor ia
Un campo no puede ser mayor que una palabr a (32 bits).
Los campos deben ser de tipo " int" o " unsigned" .
No estn per mitidos los " ar r ays" de campos.
No puede haber punter os a campos.
A un campo no se le puede aplicar el oper ador dir eccin.
Se pueden usar campos sin nombr e, a efectos de r elleno.
C.10.09
Ejemplos
str uct naipe {
unsigned valor : 4; /* para representar el entero 12
necesito ms de 3 bits */
unsigned palo : 2; /* con 2 bits puedo representar
4 valores diferentes */
};
str uct naipe car ta;
car ta.valor =3;
car ta.palo=1;
str uct r s232c {
unsigned pin1: 1,
tr ansmision_datos: 1,
r ecepcion_datos: 1,
r ts: 1,
cts: 1,
dsr : 1,
sg: 1,
: 12,
dtr : 1,
: 5;
};
str uct r s232c estado;
. . .
if (estado.cts) pr intf(" listo par a enviar " );
. . .
C.10.10
Las uniones
Son organizaciones de datos semejantes a las estructuras, que se
caracterizan porque sus miembros comparten memoria.
Permiten ahorrar memoria.
El compilador asigna una cantidad de memoria suficiente para
poder almacenar al miembro mayor.
Se accede a los miembros como en las estructuras.
/*
ej22.c
*/
# include <stdio.h>
void main( )
{
union numero {
int i;
float f;
} x;
x.i=222;
printf("i: %15d f: %15.8e\n", x.i, x.f);
x.f=222.0;
printf("i: %15d f: %15.8e\n", x.i, x.f);
}
C.10.11
/*
ej23.c
*/
# include <stdio.h>
typedef struct {
unsigned b0:1, b1:1, b2:1, b3:1,
b4:1, b5:1, b6:1, b7:1,
b8:1, b9:1, b10:1, b11:1,
b12:1, b13:1, b14:1, b15:1;
} word;
void main()
{
void escribir(word);
union equivalencia {
int n;
char c;
word bits;
} x;
scanf("%d", &x.n);
while ( x.n != 0 ){
escribir(x.bits);
scanf("%d", &x.n);
}
x.n=0;
x.c='A';
escribir(x.bits);
}
void escribir (word b)
{
printf("%1d%1d%1d%1d%1d%1d%1d%1d",
b.b0,b.b1,b.b2,b.b3,b.b4,b.b5,b.b6,b.b7);
printf("%1d%1d%1d%1d%1d%1d%1d%1d",
b.b8,b.b9,b.b10,b.b11,b.b12,b.b13,b.b14,b.b15);
printf("\n");
}
C.10.12
Tipos definidos por el usuar io
Con la declar acin " typedef" se puede asociar explcitamente un
identificador a un tipo.
typedef int enter o;
typedef int vector [10];
typedef char *cadena;
typedef float matr iz[100][100];
Despus, los identificador es se pueden usar par a declar ar var iables y
funciones:
vector v;
matr iz a, b, c;
Se pueden constr uir jer ar quas de tipos:
typedef double escalar ;
typedef escalar vector [N];
typedef vector matr iz[N];
El uso de " typedef" tiene algunas ventajas:
Per mite abr eviar expr esiones lar gas.
Facilita la documentacin del pr ogr ama.
Facilita la modificacin del pr ogr ama y, por tanto, su tr anspor te
entr e mquinas difer entes.
Per mite al pr ogr amador pensar en tr minos de la
aplicacin (alto nivel) y no en tr minos de la
r epr esentacin inter na.
C.10.13
Las definiciones de tipos se suelen almacenar en ficheros
independientes que se incorporan a los programas con rdenes
"include":
# include <stdio.h>
Con "typedef", el usuario puede ampliar el lenguaje de manera
natural incorporando tipos nuevos como dominio. Despus, se pueden
definir funciones que proporcionen operaciones sobre estos dominios.
/*
ej24.c
*/
#define N 100
typedef double escalar;
typedef escalar matriz[N][N];
void mat_producto(matriz a, matriz b, matriz c)
{
int i, j, k;
for ( i=0; i<N; ++i )
for ( j=0; j<N; ++j )
for ( c[i][j]=0, k=0; k<N; ++k )
c[i][j] += a[i][k] * b[k][j];
}
C.10.14
/*
ej25.c
Se maneja un tipo definido por el usuario para implementar
operaciones con numeros complejos.
Caso en que las funciones pueden devolver "struct".
*/
#include <math.h>
#include <stdio.h>
typedef float tipo_componente;
typedef struct {
tipo_componente re;
tipo_componente im;
} complex;
complex cpxasig(tipo_componente, tipo_componente);
complex cpxsuma(complex, complex);
complex cpxprod(complex, complex);
complex cpxconj(complex);
tipo_componente cpxlon(complex *, int);
tipo_componente cpxabs(complex);
void cpxprint(complex);
#define N 5
void main()
{
static tipo_componente a[N]={1.0, 2.0, 3.0, 4.0, 5.0};
static tipo_componente b[N]={1.0, 2.0, 3.0, 4.0, 5.0};
complex c[N];
int i;
for (i=0; i<N; ++i) c[i] = cpxasig(a[i], b[i]);
for (i=0; i<N; ++i) {
printf("%d: ", i);
cpxprint(c[i]);
}
printf("Suma c[1]+c[2]: ");
cpxprint(cpxsuma(c[1],c[2]));
printf("Producto c[1]*c[2]: ");
cpxprint(cpxprod(c[1], c[2]));
printf("Conjugado de c[1]: ");
cpxprint(cpxconj(c[1]));
printf("Val.absoluto de c[1]: %f\n", cpxabs(c[1]));
printf("Longitud del vector: %f\n", cpxlon(c, N));
C.10.14.a
complex cpxasig( tipo_componente parte_real,
tipo_componente parte_imaginaria)
{
complex x;
x.re=parte_real;
x.im=parte_imaginaria;
return(x);
}
void cpxprint(complex x)
{
printf("%f + %f i\n", x.re, x.im);
}
complex cpxsuma(complex x, complex y)
{
complex z;
z.re=x.re+y.re;
z.im=x.im+y.im;
return(z);
}
complex cpxprod(complex x, complex y)
{
complex z;
z.re=x.re*y.re-x.im*y.im;
z.im=x.re*y.im+x.im*y.re;
return(z);
}
C.10.14.b
complex cpxconj(complex x)
{
complex z;
z.re= x.re;
z.im= -x.im;
return(z);
}
tipo_componente cpxabs(complex x)
{
complex z;
z=cpxprod(x, cpxconj(x));
return(sqrt(z.re));
}
tipo_componente cpxlon(complex *v, int n)
{
int i;
tipo_componente s;
complex z;
for (s=0.0, i=0; i<n; ++i) {
z=cpxprod(v[i], cpxconj(v[i]));
s += z.re;
}
return(sqrt(s));
}
C.10.15
/* ej26.c
Se maneja un tipo definido por el usuario para
implementar operaciones con numeros complejos.
Caso en que las funciones no pueden devolver "struct"
y se usan funciones del tipo "int". */
#include <math.h>
#include <stdio.h>
typedef float tipo_componente;
typedef struct {
tipo_componente re;
tipo_componente im;
} complex;
void cpxasig(tipo_componente, tipo_componente, complex *);
void cpxsuma(complex, complex, complex *);
void cpxprod(complex, complex, complex *);
void cpxconj(complex, complex *);
void cpxprint(complex);
tipo_componente cpxlon(complex *, int);
tipo_componente cpxabs(complex);
#define N 5
void main()
{
static tipo_componente a[N]={1.0, 2.0, 3.0, 4.0, 5.0};
static tipo_componente b[N]={1.0, 2.0, 3.0, 4.0, 5.0};
complex c[N], x;
int i;
for (i=0; i<N; ++i) cpxasig(a[i], b[i], &c[i]);
for (i=0; i<N; ++i) {
printf("%d: ", i);
cpxprint(c[i]);
}
cpxsuma(c[1],c[2], &x);
printf("Suma de c[1]+c[2]: "); cpxprint(x);
cpxprod(c[1],c[2], &x);
printf("Producto de c[1]*c[2]: "); cpxprint(x);
cpxconj(c[1], &x);
printf("Conjugado de c[1]: "); cpxprint(x);
printf("Val.absoluto de c[1]: %f\n", cpxabs(c[1]));
printf("Longitud del vector: %f\n", cpxlon(c, N));
}
C.10.15.a
void cpxasig(tipo_componente a, tipo_componente b,
complex *x)
{
x->re=a;
x->im=b;
}
void cpxprint(complex x)
{
printf("(%f + %f i)\n", x.re, x.im);
}
void cpxsuma(complex x, complex y, complex *s)
{
s->re=x.re+y.re;
s->im=x.im+y.im;
}
void cpxprod(complex x, complex y, complex *p)
{
p->re=x.re*y.re-x.im*y.im;
p->im=x.re*y.im+x.im*y.re;
}
void cpxconj(complex x, complex *c)
{
c->re=x.re;
c->im=-x.im;
}
C.10.15.b
tipo_componente cpxabs(complex x)
{
complex c, p;
cpxconj(x, &c);
cpxprod(x, c, &p);
return(sqrt(p.re));
}
tipo_componente cpxlon(complex *v, int n)
{
int i;
tipo_componente s;
complex c, p;
for (s=0.0, i=0; i<n; ++i) {
cpxconj(v[i], &c);
cpxprod(v[i], c, &p);
s += p.re;
}
return(sqrt(s));
}
C.10.16
/*
ej27.c
Se maneja un tipo definido por el usuar io par a implementar
oper aciones con numer os complejos.
Se manejan funciones que devuelven punter os a estr uctur as
*/
#include <math.h>
#include <stdio.h>
typedef float tipo_componente;
typedef str uct {
tipo_componente r e;
tipo_componente im;
} complex;
complex *cpxasig(), *cpxsuma(), *cpxpr od(), *cpxconj();
tipo_componente cpxabs(), cpxlon();
#define N 5
main()
{
static tipo_componente a[N]={1.0, 2.0, 3.0, 4.0, 5.0};
static tipo_componente b[N]={1.0, 2.0, 3.0, 4.0, 5.0};
complex c[N];
int i;
for (i=0; i<N; ++i) c[i] = *cpxasig(a[i], b[i]);
for (i=0; i<N; ++i) {
pr intf(" %d: " , i);
cpxpr int(c[i]);
}
pr intf(" Suma c[1]+c[2]: " ); cpxpr int(*cpxsuma(c[1],c[2]));
pr intf(" Pr oducto c[1]*c[2]: " ); cpxpr int(*cpxpr od(c[1], c[2]));
pr intf(" Conjugado de c[1]: " ); cpxpr int(*cpxconj(c[1]));
pr intf(" Val.absoluto de c[1]: %f\n" , cpxabs(c[1]));
pr intf(" Longitud del vector : %f\n" , cpxlon(c, N));
}
C.10.16.a
complex *cpxasig(par te_r eal, par te_imaginar ia)
tipo_componente par te_r eal, par te_imaginar ia;
{
complex x;
x.r e=par te_r eal;
x.im=par te_imaginar ia;
r etur n(&x);
}
cpxpr int(x)
complex x;
{
pr intf(" %f + %f i\n" , x.r e, x.im);
}
complex *cpxsuma(x, y)
complex x, y;
{
complex z;
z.r e=x.r e+y.r e;
z.im=x.im+y.im;
r etur n(&z);
}
complex *cpxpr od(x, y)
complex x, y;
{
complex z;
z.r e=x.r e*y.r e-x.im*y.im;
z.im=x.r e*y.im+x.im*y.r e;
r etur n(&z);
}
C.10.16.b
complex *cpxconj(x)
complex x;
{
complex z;
z.r e= x.r e;
z.im= -x.im;
r etur n(&z);
}
tipo_componente cpxabs(x)
complex x;
{
complex z;
z= *cpxpr od(x, *cpxconj(x));
r etur n(sqr t(z.r e));
}
tipo_componente cpxlon(v, n)
complex v[];
int n;
{
int i;
tipo_componente s;
complex z;
for (s=0.0, i=0; i<n; ++i) {
z= *cpxpr od(v[i], *cpxconj(v[i]));
s += z.r e;
}
r etur n(sqr t(s));
}
C.11.01
- 11 -
FUNCIONES PARA MANEJ O DE FICHEROS
Ficher o, flujo de datos y punter o a flujo.
Resumen de funciones de la biblioteca estndar .
Abr ir ficher o con " fopen" .
Cer r ar ficher o con " fclose" .
Posicionar en ficher o con " fseek" , " r ewind" .
Leer un car cter con " fget" , " getc" , " getchar " .
Escr ibir un car cter con " fput" , " putc" , " putchar " .
Leer una cadena con " fgets" , " gets" .
Escr ibir una cadena con " fputs" , " puts" .
Leer en binar io usando " buffer " con " fr ead" .
Escr ibir en binar io usando " buffer " con " fwr ite" .
Leer con for mato usando " fscanf" , " scanf" , " sscanf"
Escr ibir con for mato usando " fpr intf" , " pr intf" , " spr intf"
C.11.02
Los pr ogr amas se comunican con el entor no leyendo y escr ibiendo
ficher os.
Un ficher o se consider a como flujo de datos que se pr ocesan
secuencialmente.
El concepto de ficher o es amplio:
Ficher o de disco: conjunto de datos que se puede leer
y escr ibir r epetidamente.
Tuber a, canal: flujo de bytes gener ados por un pr ogr ama.
Dispositivos: flujo de " bytes" r ecibidos desde o enviados
hacia un dispositivo per ifr ico (teclado,
monitor , ...).
Todas las clases de ficher os se manejan casi de la misma for ma.
Los ficher os se manejan con funciones de biblioteca cuyas
declar aciones se incor por an al pr ogr ama con la or den:
# include <stdio.h>
Las funciones par a manejo de ficher os usan el sopor te que
pr opor ciona el sistema oper ativo.
C.11.03
Antes de r ealizar cualquier oper acin sobr e un ficher o, hay que
abr ir lo.
En el entor no se dispone siempr e de tr es ficher os abier tos:
asignacin
identificador nombr e inicial
========= ======================= ========
stdin ficher o estndar de entr ada teclado
stdout ficher o estndar de salida pantalla
stder r ficher o estndar par a mensajes pantalla
de error
Al abr ir un ficher o, la funcin " fopen" lo asocia con un flujo de datos
y devuelve un punter o a un objeto de tipo FILE que se usa par a
mantener el estado del flujo.
Despus ese punter o se utiliza par a las oper aciones sobr e el ficher o.
Todas las entr adas se pr oducen como si cada car cter fuer a leido
llamando a " fgetc" .
Todas las salidas se pr oducen como si cada car cter fuer a escr ito
llamando a " fputc" .
El ficher o se puede cer r ar con " fclose" .
C.11.04
El punter o a FILE mantiene infor macin sobr e el estado del flujo de
datos:
Un indicador de er r or , que toma valor distinto de cer o cuando la
funcin encuentr a un er r or de lectur a o de escr itur a.
Un indicador de fin de ficher o, que r esulta distinto de cer o
cuando la funcin encuentr a el final de ficher o cuando est
leyendo.
Un indicador de posicin, que indica el siguiente " byte" que se
lee o se escr ibe en el flujo de datos, si el ficher o puede sopor tar
pr eguntas sobr e la posicin.
Un " buffer " de ficher o, que indica la dir eccin y tamao de un
" ar r ay" que utilizan las funciones par a leer y escr ibir .
# include <stdio.h>
main( )
{
FILE *fp;
. . .
fp = fopen ( " datos" , " r " );
. . .
fclose ( fp );
. . .
}
C.11.05
Algunas de las funciones estndar
Control: fopen fclose
fseek r ewind
Leer y escribir un carcter: fgetc getc getchar
fputc putc putchar
Leer y escribir una cadena: fgets gets
fputs puts
Leer y escribir con "buffer": fr ead fwr ite
Leer y escribir con formato: fpr intf pr intf spr intf
fscanf scanf sscanf
Los entor nos oper ativos tambin pr opor cionan bibliotecas de
funciones que implementan diver sos modos de acceso.
C.11.06
Abr ir ficher o con " fopen"
FILE *fopen ( char *nombr e, char *modo);
Abr e un ficher o, lo asocia con un flujo de datos y devuelve un punter o
a FILE. Si el ficher o no es accesible, se devuelve el punter o de valor
NULL.
Los modos " r " , " w" y " a" cor r esponden a leer , escr ibir y aadir .
Si el modo es " r " o " w" , el punter o de ficher o se coloca al pr incipio. Si
el modo es " a" , el punter o se coloca al final.
Si el modo es " w" o " a" , se cr ea el ficher o si no existe.
# include <stdio.h>
main()
{
FILE *fp;
char nombr e[36];
pr intf(" nombr e de ficher o ? " );
scanf(" %s" ,nombr e);
if ( ! (fp=fopen(nombr e," r " )) )
pr intf(" er r or \n" );
else
pr ocesar (fp);
. . .
. . .
}
C.11.07
Cer r ar ficher o con " fclose"
int fclose (FILE *fp );
Si el punter o no est asociado a un ficher o, se devuelve EOF.
En caso de xito, se devuelve cer o (0).
Posicionar con " fseek"
int fseek ( FILE *fp, long desplaz, int posicion );
Se establece la posicin par a la siguiente oper acin de lectur a o
escr itur a.
El par metr o " posicion" puede tomar los valor es 0, 1, 2.
Con " posicion" se identifica una posicin en el ficher o: 0 par a el
pr incipio, 1 par a la posicin actual y 2 par a el final de ficher o.
El punter o se desplaza un nmer o de bytes indicado por " desplaz" a
par tir de " posicin" .
En caso de er r or , devuelve un valor distinto de cer o.
Posicionar al pr incipio con " r ewind"
void r ewind ( FILE *fp )
Tiene el mismo efecto que " fseek ( fp, 0L, 0 ) " ;
C.11.08
Leer un car cter con " fgetc" , " getc" , " getchar "
int fgetc ( FILE *fp );
Se obtiene el siguiente car cter en el flujo de entr ada al que apunta
" fp" , avanza el indicador de posicin y se devuelve el car cter leido
como un " int" .
Si se pr oduce er r or o se alcanza el fin de ficher o, se devuelve EOF.
int getc ( FILE *fp );
Es una macr o que tiene el mismo efecto que " fgetc" .
La funcin " fgetc" es ms lenta que la macr o " getc" , per o ocupa
menos espacio por llamada y su nombr e se puede pasar como
ar gumento a otr a funcin.
int getchar ( );
Es una macr o que se define como " getc(stdin)" .
C.11.09
Uso de "fopen()", "fclose()", "getc()", "putchar()"
/*
ej28.c
Se leen caracteres en un fichero y se escriben
por "stdout"
*/
# include <stdio.h>
void main()
{
FILE *fp;
char nombre[36], c;
printf("nombre de fichero ? ");
scanf("%s",nombre);
if ( ! (fp=fopen(nombre,"r")) ) printf("error\n");
else {
c = getc(fp);
while ( c != EOF ) {
putchar(c);
c = getc(fp);
}
fclose(fp);
}
}
C.11.10
Escr ibir un car cter con " fput" , " putc" , " putchar "
int fputc ( int c , FILE *fp );
Escr ibe el car cter " c" en el flujo de salida " fp" , avanza la posicin y
devuelve el car cter escr ito como " int" .
Si se pr oduce er r or , devuelve EOF.
int putc ( int c, FILE *fp );
Es una macr o con el mismo efecto que " fputc" .
La funcin " fputc" es ms lenta, per o ocupa menos espacio y se puede
pasar como ar gumento a otr a funcin.
int putchar ( int c );
Es una macr o equivalente a " putc(stdout)" .
C.11.11
Uso de "fopen()", "fclose()", "getc()", "putc()"
/*
ej29.c
Se copia el contenido de un fichero a otro, operando
sobre caracteres con "getc()" y "putc()".
*/
# include <stdio.h>
void main()
{
FILE *in, *out;
char nomin[36], nomout[36], c;
printf("Fichero de entrada ? "); scanf("%s",nomin);
in=fopen(nomin, "r");
if ( ! in )
printf("error al abrir fichero de entrada\n");
else {
printf("Fichero de salida ? "); scanf("%s",nomout);
out=fopen(nomout, "w");
if ( ! out ) {
printf("error al abrir fichero de salida\n");
fclose(in);
}
else {
c=getc(in);
while ( c != EOF ) {
putc(c, out);
c = getc(in);
}
fclose(in); fclose(out);
}
}
}
C.11.12
Uso de "fseek()", "getc()", "putchar()"
/* ej30.c
Se lee un nmero de caracteres a partir de una posicin
del fichero que se determina con "fseek()" y se escriben
por pantalla. */
# include <stdio.h>
int leer_posicion(void);
int leer_num(void);
int test(int);
void main()
{
FILE *fp;
char nombre[36], c;
int pos, num; long desp;
printf("Nombre de Fichero ? "); scanf("%s",nombre);
fp=fopen(nombre, "rb");
if ( ! fp )
printf("error al abrir fichero de entrada\n");
else {
while ( 1 ) {
pos = leer_posicion();
printf("Desplazamiento (num. de bytes) ? ");
scanf("%ld", &desp);
num = leer_num();
if ( fseek(fp, desp, pos) != 0 )
printf("error en posicionamiento\n");
else {
int i=0;
c = getc(fp);
while ( i<=num && c!=EOF ) {
putchar(c);
i=i+1;
c = getc(fp);
}
putchar('\n'); putchar('\n');
}
}
}
C.11.13
int leer_posicion()
{
int n;
printf("Posicion (0:principio, 1:actual, 2:EOF) ? ");
scanf("%d", &n);
while ( ! test(n) ) {
printf("Posicion (0:principio, 1:actual, 2:EOF) ?");
scanf("%d", &n);
}
return(n);
}
int test ( int n )
{
if ( n<0 || n>2 ) return(0);
else return(1);
}
int leer_num()
{
int n;
printf("Numero de bytes ( mayor que cero ) ? ");
scanf ("%d", &n);
while ( n<0 ) {
printf("Numero de bytes ( mayor que cero ) ? ");
scanf ("%d", &n);
}
return(n);
}
C.11.14
Leer una cadena con " fgets()" y " gets()"
char *fgets ( char *s, int n, FILE *fp);
Lee car acter es por el flujo al que apunta " fp" y los coloca en el
" ar r ay" al que apunta " s" , hasta que se han leido " n-1" car acter es o
se lee el car cter " nueva_lnea" o se alcanza la condicin de fin de
ficher o. Despus se pone el car cter nulo (' \0' ) como mar ca de fin de
cadena.
El car cter " nueva_lnea" leido tambin entr a en la cadena.
En caso de er r or se devuelve el punter o nulo.
En caso de alcanzar fin de ficher o sin haber leido car acter es, se
devuelve el punter o nulo.
En otr o caso, se devuelve " s" .
char *gets ( char *s );
Lee car acter es por el flujo de entr ada estndar (stdin) y los coloca en el
" ar r ay" apuntado por " s" , hasta que se alcance el car cter de
" nueva_lnea" o la condicin de fin de ficher o.
El car cter " nueva_lnea" se descar ta y se pone el car cter nulo (' \0' ).
Se compor ta igual que " fgets" en cuanto al valor que devuelve.
C.11.15
Escr ibir una cadena con " fputs()" y " puts()"
int fputs ( char *s, FILE *fp);
Escr ibe la cadena apuntada por " s" en el flujo de salida " fp" .
No se escr ibe el car cter nulo que mar ca el fin de cadena.
Devuelve EOF en caso de er r or .
int puts ( char *s );
Escr ibe la cadena apuntada por " s" y un car cter de " nueva_lnea"
por el flujo de salida estndar (stdout).
No se escr ibe el car cter nulo que mar ca el fin de cadena.
Devuelve EOF en caso de er r or .
C.11.16
Leer en binar io usando " buffer " , con " fr ead"
int fr ead(char *buf, int tam, int num, FILE *fp);
Se lee un nmer o " num" de items por el flujo " fp" y se almacenan en
el " ar r ay" apuntado por " buf" .
Cada item es una secuencia de " bytes" de longitud dada por " tam" .
Ter mina cuando se alcanza la condicin de fin de ficher o o cuando se
ha leido un nmer o " num" de items. El punter o del flujo de entr ada
queda apuntando al " byte" que sigue al ltimo leido.
No se modifica el contenido del flujo de entr ada.
Se devuelve en nmer o de items leidos.
Escr ibir en binar io usando " buffer " con " fwr ite"
int fwr ite ( char *buf, int tam, int num, FILE *fp);
Aade al menos un nmer o " num" de items de datos del " ar r ay"
apuntado por " buf" , en el flujo de salida " fp" . Se ter mina de aadir
cuando ya se ha aadido un nmer o " num" de items o cuando se
pr oduce condicin de er r or en el flujo de salida.
No se modifica el contenido del " ar r ay" apuntado por " buf" .
Se devuelve el nmer o de items escr itos.
C.11.17
Uso de "fread()", "fwrite()"
/*
ej31.c
Se copia el contenido de un fichero, operando
en binario con buffer de 512 bytes
*/
# define LON 512
# include <stdio.h>
void main()
{
FILE *in, *out;
char nomin[36], nomout[36], buf[LON];
int n;
printf("Fichero de entrada ? ");
scanf("%s", nomin);
in=fopen(nomin, "r");
if ( ! in )
printf("error al abrir fichero de lectura\n");
else{
printf("Fichero de salida ? ");
scanf("%s", nomout);
out=fopen(nomout, "w");
if ( ! out ) {
printf("error al abrir fichero de salida\n");
fclose(in);
}
else {
while ( (n=fread(buf, 1, LON, in)) > 0 )
fwrite(buf, 1, n, out);
fclose(in); fclose(out);
}
}
}
C.11.18
Leer con for mato usando " fscanf" , " scanf" , " sscanf" .
int fscanf ( FILE *fp, char *for mato, lista . . . );
Se leen car acter es por el flujo de entr ada " fp" , se convier ten en valor es
de acuer do con las especificaciones de " for mato" y se almacenan en la
dir eccin dada por el punter o cor r espondiente de la lista de
ar gumentos.
Se devuelve el nmer o de conver siones conseguidas. Se devuelve EOF
si se alcanza la condicin de fin de ficher o.
En caso de er r or , si el for mato no es numr ico, devuelve el nmer o de
ar gumentos leidos cor r ectamente antes de pr oducir se el er r or . Si el
for mato es numr ico, devuelve cer o.
La cadena de contr ol " for mato" puede contener :
Espacios en blanco, que se cor r esponden con el espacio en blanco
opcional del flujo de entr ada.
Un car cter or dinar io, que no sea ' %' ni espacio en blanco y que se
cor r esponda con el siguiente car cter en el flujo de entr ada.
Especificaciones de conver sin conteniendo:
-El car cter ' %' , el car cter opcional ' *' par a supr imir la
conver sin.
-Un enter o opcional que indica la anchur a mxima del campo.
-Uno de los modificador es ' l' o ' h' par a indicar tamao " long" . -
Un cdigo de conver sin.
C.11.19
Car cter de
Conver sin Inter pr etacin del flujo de entr ada
========= ==========================
d Enter o decimal
o Enter o octal
x Enter o hexadecimal
u Enter o decimal sin signo
e Nmer o de coma flotante
f Equivalente a " e"
c Un car cter
s Cadena de car acter es
[cadena] Cadena especial
Los car acter es ' d' , ' o' , ' x' , ' e' y ' f' pueden ir pr ecedidos por ' l' par a
indicar conver sin a " long" o a " double" .
Los car acter es ' d' , ' o' , ' x' pueden ir pr ecedidos por ' h' par a conver tir a
" shor t" .
Un campo de entr ada es una secuencia de car acter es distintos del
espacio en blanco.
Par a todos los descr iptor es, excepto " [" y " c" , se ignor an los
espacios en blanco que pr eceden a un campo.
El campo de entr ada ter mina cuando se alcanza un car cter
inapr opiado o cuando acaba la anchur a del campo.
Cuando se leen car acter es, el espacio en blanco no se salta.
El for mato " %1s" puede usar se par a leer el siguiente car cter
distinto de espacio en blanco.
C.11.20
La especificacin "%[cadena]" se usa para leer una cadena
especial.
Si el primer carcter de la cadena es '^', entonces la cadna leida
estar formada por caracteres diferentes de los que forman la
especificacin:
Con "%[^abc], la lectura termina al encontrar 'a', 'b' 'c';
pero no un espacio en blanco.
Si el primer carcter es distinto de '^', la cadena leida slo puede
contener los caracteres de la especificacin.
scanf ( "%[ab \n\t]", s )
Leer una cadena que contenga nicamente los caracteres 'a', 'b',
espacio en blanco, nueva linea, tabulador.
scanf ( "%5s", s )
Se ignoran espacios en blanco y se leen los cinco caracteres siguientes.
scanf ( "%s", s )
Se lee una cadena arbitraria hasta encontrar espacio en blanco.
C.11.21
int n, a, b, c;
float x;
char nombr e[50];
n=scanf(" %d%f%s" , &a, &x, nombr e);
25 54.32E-1 eugenio
var iable valor asignado
====== ===========
n 3
a 25
x 5.432
nombr e eugenio
scanf(" %d,%d,%d" , &a, &b, &c);
12,5,7
var iable valor asignado
====== ===========
a 12
b 5
c 7
scanf(" %2d%f%*d%[0-9]" , &a, &x, nombr e);
56789 0123 56a72
var iable valor asignado
====== ===========
a 56
x 789.0
nombr e 56
C.11.22
int scanf ( char *formato, lista . . .);
Se lee por el flujo de entrada "stdin", con el mismo efecto que "fscanf".
int sscanf ( char *s, char *formato, lista . . .);
Se lee en la cadena apuntada por "s", con el mismo efecto que
"fscanf".
/*
ej32.c
Se calculan las raices cuadradas de los valores
pasados en la orden de llamada.
Uso: $ raices 4 5.6 7 8
*/
# include <stdio.h>
# include <math.h>
void main(argc, argv)
int argc;
char *argv[];
{
int i;
float x;
if ( argc == 1 )
printf("Error. Hay que pasar valores en la llamada\n");
else {
for ( i=1; i<argc; ++i ) {
sscanf(argv[i], "%f", &x); /* la entrada se toma de
una cadena */
printf("La raiz cuadrada de %f es %lf\n",
x, sqrt(x) );
}
}
}
C.11.23
Escr ibir con for mato usando " fpr intf" , " pr intf" ,
" spr intf" .
int fpr intf ( FILE *fp, char *for mato, lista . . . );
Esta funcin convier te, for matea y escr ibe por un flujo de salida.
Las expr esiones que for man la " lista" de ar gumentos se evalan, se
convier ten de acuer do con los for matos de la cadena de contr ol
" for mato" , y se escr iben por el flujo de salida " fp" .
Se devuelve el nmer o de car acter es escr itos o un valor negativo en
caso de er r or .
El for mato se indica con una cadena de car acter es que puede contener
especificaciones de conver sin y car acter es nor males.
C.11.24
Las especificaciones de conversin empiezan po '%' o por "%n$",
donde "n" es un entero que indica la posicin del argumento al que se
aplicar. Despus se puede poner:
Ninguno o ms modificadores: - + blanco #
Una secuencia de cifras para indicar la anchura del campo.
Una secuencia de cifras para indicar la precisin:
nmero mnimo de dgitos para las conversiones "d, i, o, u, x,
X"
nmero de cifras decimales para las conversiones "e, f"
mximo nmero de cifras significativas para la
conversin "g"
mximo nmero de "bytes" que se escriben para la conversin
"s"
La anchura del campo y la precisin se separan con un punto.
Si se pone "*", el valor se calcula usando los siguientes
argumentos:
printf("%*.*d\n", ancho, precision, valor)
Una "l" o "h" opcionales para convertir a "long" o "short" los
tipos enteros.
Un carcter que indica el tipo de conversin que se solicita.
Ejemplos: %6d %8.4f %2$4d
Modificadores
- ajustar a la izquierda
+ escribir el signo siempre
etc...
C.11.25
Car acter es de conver sin
d, i se convier te a decimal con signo.
o se convier te a octal sin signo.
u se convier te a decimal sin signo
x, X se convier te a hexadecimal sin signo
f se supone ar gumento " float" o " double y se
convier te a notacin decimal.
e, E se supone ar gumento " float" o " double" y se
convier te a notacin exponencial.
g, G se supone ar gumento " float" o " double" y se
elige el ms br eve entr e entr e " f" o " e" .
c un car cter .
s se toma el ar gumento como cadena de
caracteres
int pr intf ( char *for mato, lista . . . );
Escr ibe por el flujo de salida " stdout" , con el mismo efecto que
" fpr intf" .
int spr intf ( char *s, char *for mato, lista . . .);
Escr ibe en la cadena apuntada por " s" , con el mismo efecto que
" fpr intf" .
C.11.26
/*
ej33.c
Escribir con formato definido en tiempo de ejecucion,
que se introduce como dato.
*/
# include <stdio.h>
void main()
{
int n=12;
float x=3.1416;
static char s[18]="25-ENE-91";
char formato[80];
printf("Introducir un formato para: ");
printf("entero float cadena\n");
while ( gets(formato) ) {
printf ( formato, n, x, s );
printf("\nIntroducir un formato para: ");
printf("entero float cadena\n");
}
}
C.12.01
- 12 -
ESTRUCTURAS DINAMICAS DE DATOS
Estr uctur as estticas y dinmicas.
Definicin r ecur siva de datos.
Estr uctur as dinmicas tpicas.
Asignar memor ia con " malloc( )"
Liber ar memor ia con " fr ee( )" .
Constr uccin de una lista encadenada en for ma lineal.
Pr ogr ama par a manejar una cola.
C.12.02
Estr uctur as estticas
Se les asigna memor ia en tiempo de compilacin
Ocupan un nmer o fijo de posiciones de memor ia.
Existen dur ante toda la ejecucin del bloque.
Estr uctur as dinmicas
Se les asigna memor ia en tiempo de ejecucin.
Pueden expandir se y contr aer se.
Se cr ean dur ante la ejecucin invocando a la funcin
" malloc" .
Las estr uctur as dinmicas se constr uyen con punter os
Existe una funcin que cr ea una r ealizacin del objeto.
Un componente del objeto es un punter o que " apunta" a otr o
objeto del mismo tipo.
Se consigue tener un conjunto de objetos r elacionados que puede
aumentar y disminuir en tiempo de ejecucin.
C.12.03
Ejemplo
Un texto se puede r epr esentar con una lista de car acter es encadenados.
As, las oper aciones de inser cin y eliminacin son muy econmicas.
m o
s
c
a
Si se r epr esenta el texto con un " ar r ay" , entonces las oper aciones de
inser cin y eliminacin son ms costosas por que obligan a r easignar
muchos elementos.
C.12.04
Las estr uctur as dinmicas se manejan con definiciones
de datos r ecur sivas.
str uct lista {
char dato;
str uct lista *siguiente;
} nodo;
La flecha r epr esenta
" estar apuntando a . . ."
dato puntero
El compilador no r eser va memor ia par a ese tipo de objetos.
La cr eacin del objeto y asigacin de memor ia se hace en tiempo de
ejecucin, invocando la funcin de biblioteca " malloc" :
malloc ( tamao )
Los valor es de ese tipo que se cr ean dur ante la ejecucin no se
pueden identificar por el nombr e de var iable, que es slo un
identificador genr ico.

Se asigna memor ia con " malloc()"

Se liber a memor ia con " fr ee( )"
C.12.05
Estr uctur as dinmicas tpicas
COLA. Lista encadenada, con disciplina FIFO
NULL
pr incipio
fin
1
2
3
4
5
PILA. Lista encadenada, con disciplina LIFO
cima
NULL
3
2
1
C.12.06
LISTA CON ENCADENAMIENTO DOBLE
NULL
NULL
fin
pr incipio
ARBOL BINARIO
r aiz
C.12.07
La funcin " malloc"
void *malloc ( tipo_size longitud );
La funcin asigna una r egin de memor ia par a un objeto de datos de
tamao " longitud" , y devuelve la dir eccin del pr imer " byte" de esa
r egin (" tipo_size" es el tipo del valor que devuelve el oper ador
" sizeof" ).
Los valor es almacenados en el objeto de datos quedan indefinidos.
En caso de er r or (no hay memor ia suficiente, ...) devuelve el punter o
nulo.
str uct lista {
char dato;
str uct lista *siguiente;
} nodo, *p;
. . .
p = malloc ( sizeof(lista) );
. . .
p = (str uct lista *) malloc (sizeof(lista) );
. . .
if ( p=malloc(sizeof(lista)) ) pr ocesar ( );
else pr intf(" er r or \n" );
C.12.08
La funcin " fr ee"
void fr ee ( void *punter o );
Se liber a la asignacin de memor ia cor r espondiente al objeto de datos
cuya dir eccin indica " punter o" .
Si el punter o tiene valor nulo, no hace nada.
Se puede liber ar asignacin de memor ia de cualquier objeto de datos
al que se haya asignado pr eviamente con " malloc" , " calloc" o
" r ealloc" .
str uct lista {
char dato;
str uct lista *siguiente;
} nodo, *p;
. . .
p = malloc ( sizeof(lista) );
. . .
fr ee ( p );
. . .
C.12.09
Encadenamiento de datos
str uct lista {
char dato;
str uct lista *siguiente;
} x, y, z, *p;
x, y, z son var iables de tipo " str uct lista"
p es un punter o a datos de tipo " str uct lista"
Hay un campo par a almacenar datos y otr o par a hacer
conexiones.
Asignacin de valor es:
x.dato=' A' ;
y.dato=' B' ;
z.dato=' C' ;
x.siguiente = y.siguiente = z.siguiente = NULL;
x
y
z
A
B C NULL NULL NULL
Encadenamiento:
x.siguiente = &y;
y.siguiente = &z;
x
y
z
A
B C NULL
El campo de enlace per mite acceder al siguiente elemento hasta llegar a
una mar ca de final convenida.
x.siguiente -> dato es ' B'
x.siguiente -> siguiente -> dato es ' C'
Per o ser a muy poco til usar var iables difer entes par a manejar
estr uctur as dinmicas.
C.12.10
Constr uccin de una lista encadenada en for ma lineal
B C D
E
NULL A
pr incipio
fin
El final de la lista se mar ca asignando el valor nulo al campo
punter o del ltimo elemento.
Se manejan dos punter os auxiliar es par a poder acceder al pr imer
elemento y al ltimo.
Se usa una var iable genr ica par a r epr esentar los elementos de la
lista.
Definicin de datos:
# define NULL 0
typedef char TIPO_DATOS;
str uct lista {
TIPO_DATOS dato;
str uct lista *siguiente;
};
typedef str uct lista ELEMENTO;
typedef ELEMENTO *ENLACE;
ENLACE nodo, pr incipio, fin;
C.12.11
nodo = malloc( sizeof(ELEMENTO) ); (1)
nodo -> dato = 'A'; (2)
nodo = NULL; (3)
principio = fin = nodo; (4)
A
principio
fin
NULL
A
A NULL
(1) (2) (3)
(4)
nodo = malloc ( sizeof(ELEMENTO) );
nodo -> dato = 'B';
nodo -> siguiente = NULL; (5)
fin -> siguiente = nodo; (6)
fin = fin -> siguiente; (7)
principio
fin
NULL A NULL B
principio
fin
NULL A B
principio
fin
NULL A B
(5)
(6)
(7)
C.12.12
Ejemplo
Se pr opone un pr ogr ama par a manejar una Cola (Lista encadenada
con disciplina FIFO).
NULL
pr incipio
fin
1
2
3
4
5
El campo de datos de cada elemento es de tipo " char " .
Los datos se intr oducen por pantalla en for ma de cadena de
caracteres.
Desde el teclado se pueden ejecutar en or den ar bitr ar io las
oper aciones de adicin , eliminacin y listado de elementos.
La adicin de un elemento nuevo se hace por el final de cola.
La eliminacin de un elemento se hace por el pr incipio de cola.
El listado se hace r ecor r iendo la cola desde el pr incipio hasta el final.
C.12.13
/*
ej34.c
Manejo de una estructura dinamica con disciplina de
cola (FIFO).
*/
# include <stdio.h>
# include <stdlib.h>
typedef char TIPO_DATO;
struct lista {
TIPO_DATO dato ;
struct lista *sig;
};
typedef struct lista ELEMENTO;
typedef ELEMENTO *ENLACE;
void Opcion_1(ENLACE *, ENLACE *);
void aniadir(ENLACE *, ENLACE *, ENLACE);
void Opcion_2(ENLACE *, ENLACE *);
ENLACE retirar(ENLACE *, ENLACE *);
void Opcion_3(ENLACE);
void listar(ENLACE);
void leer_cadena(char *, int);
void mensaje(void), preguntar(void);
# define NULL 0
# define LONCAD 80
C.12.13.a
void main()
{
ENLACE principio, fin;
int seguir=1; char c;
mensaje();
principio=(ENLACE)malloc(sizeof(ELEMENTO));
fin=(ENLACE)malloc(sizeof(ELEMENTO));
principio=fin=NULL;
while ( seguir ) {
preguntar();
while ( (c=getchar()) == '\n' ) ; getchar();
switch ( c ) {
case '1' : Opcion_1 ( &principio, &fin );
break;
case '2' : Opcion_2 ( &principio, &fin );
break;
case '3' : Opcion_3 ( principio );
break;
case '4' : seguir=0;
break;
default : printf("Elija una opcion correcta %c\n",
7);
}
}
printf("FIN DE LA EJECUCION\n");
}
C.12.14
/*
Opcion_1
Se lee una cadena de caracteres y se aaden a la cola
por el final con algoritmo iterativo.
*/
void Opcion_1 (ENLACE *principio, ENLACE *fin)
{
ENLACE nuevo;
int i;
char s[80];
printf("Introducir una cadena: ");
leer_cadena(s, LONCAD);
for (i=0; s[i] != '\0'; ++i) {
nuevo=(ENLACE)malloc(sizeof(ELEMENTO));
nuevo->dato=s[i];
nuevo->sig=NULL;
aniadir(principio, fin, nuevo);
}
}
void aniadir( ENLACE *principio, ENLACE *fin,
ENLACE nuevo )
{
if ( *fin ) {
(*fin)->sig=nuevo;
*fin = (*fin)->sig;
}
else *principio = *fin = nuevo;
}
C.12.15
/*
Opcion_2
Eliminar un elemento por el principio de cola.
*/
void Opcion_2 (ENLACE *principio, ENLACE *fin)
{
ENLACE nodo;
if ( *principio ) {
nodo = retirar (principio, fin);
printf ("Elemento retirado: %c\n", nodo->dato);
free(nodo);
}
else printf("No hay elementos en cola\n");
}
ENLACE retirar ( ENLACE *principio, ENLACE *fin )
{
ENLACE tope;
tope= *principio;
*principio= (*principio)->sig;
if (*principio) tope->sig=NULL;
else *fin=NULL;
return (tope);
}
C.12.16
Retirar un elemento
NULL
principio
fin
principio
fin
nodo
nodo
nodo
principio
fin
NULL
NULL
NULL
nodo = pr incipio;
pr incipio = pr incipio -> sig;
nodo -> siguiente = NULL;
C.12.17
void Opcion_3 (ENLACE p)
{
if ( p==NULL ) printf("No hay elementos en cola\n");
else listar(p);
}
void listar (ENLACE p)
{
while ( p->sig != NULL ) {
printf("%c", p->dato);
p=p->sig;
}
printf("%c", p->dato);
printf("\n");
}
C.12.18
void leer_cadena(char *s, int lon)
{
int i=0;
while ( (s[i]=getchar()) != '\n' ) if ( i<(lon-1) ) i++;
s[i]='\0';
}
void mensaje()
{
printf("Programa COLA\n");
printf("Este programa permite manejar una Cola: ");
printf("Lista encadenada\n");
printf("con disciplina FIFO (primero en entrar, ");
printf("primero en salir)\n");
}
void preguntar()
{
printf("\nQue opcion ( 1-Aniadir, 2-Retirar, ");
printf("3-Listar, 4- Terminar) ? \n");
}
C.12.19
Ejemplo de algoritmo recursivo para manejar listas
encadenadas.
Es la forma natural de manejar datos definidos recursivamente.
En el siguiente programa se construye una lista encadenada con los
caracteres de una cadena que se lee por pantalla, y se recorre dos veces
escribiendo los campos de de datos.
/*
ej35.c
Creacion y recorrido de una lista encadenada con
algoritmo recursivo.
*/
# include <stdio.h>
# include <stdlib.h>
# define NULL 0
struct lista {
char dato;
struct lista *siguiente;
};
typedef struct lista ELEMENTO;
typedef ELEMENTO *ENLACE;
ENLACE cadena(char *);
void listar(ENLACE);
void main()
{
ENLACE principio;
char s[80];
printf("Introducir una cadena: \n");
scanf("%s", s);
principio=cadena(s);
listar(principio);
printf("\n");
listar(principio);
printf("\n");
}
C.12.20
/*
Creacion de lista encadenada con algoritmo recursivo
*/
ENLACE cadena(char s[ ])
{
ENLACE principio;
if ( s[0] == '\0' ) return(NULL);
else {
principio=(ENLACE)malloc(sizeof(ELEMENTO));
principio->dato=s[0];
principio->siguiente=cadena(s+1);
return(principio);
}
}
/*
Se recorre una lista con algoritmo recursivo escribiendo
los campos de datos.
*/
void listar(ENLACE principio)
{
if ( principio == NULL ) printf("NULL");
else {
printf("%c --> ", principio->dato);
listar(principio->siguiente);
}
}

También podría gustarte