A Lenguaje C PDF
A Lenguaje C PDF
A Lenguaje C PDF
DE
LENGUAJE "C"
Angel Salas
Centro de Cálculo
Universidad de Zaragoza
Enero - 1991
SALAS, Angel
ISBN 84-7733-232-0
Centro de Cálculo
de la Universidad de Zaragoza, 1991.
Edificio de Matemáticas
Ciudad Universitaria
50009 - ZARAGOZA
Tfno: 354100
Contiene una reproducción de todas las transparencias que usa el profesor en sus
exposiciones.
En la lección 9 se estudian a fondo el tipo "array", las cadenas y la relación con los
punteros. Se presentan algunas funciones de biblioteca para manejar cadenas de caracteres.
La lección 10 se dedica explicar el tipo "struct", los campos de "bits", las uniones y
los tipos definidos por el usuario.
CONTENIDO
INTRODUCCION
ELEMENTOS LEXICOS.
LAS FUNCIONES.
Se creó para superar las limitaciones del lenguaje B, utilizado por Ken
Thompson para producir la versión original de UNIX en 1970.
Pero permite casi todas las conversiones (p.ej. se pueden mezclar los tipos
"int" y "char" en casi todas las expresiones).
ES UN LENGUAJE SEMI-ESTRUCTURADO
while
do-while
for
C.00.05
Proporciona:
BIBLIOGRAFIA
-1-
• El formato de escritura
• Ejemplo de un programa completo
• Los comentarios
• Las sentencias para el pre-procesador
• Las funciones. Definición de una función
• Las declaraciones
• Reglas de alcance
• Las expresiones
• Las sentencias
• La sentencia "if-else"
• La sentencia "for"
• La función "printf"
• La función "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
Comentarios.
Definiciones de funciones.
Sentencias.
C.01.03
- 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));
}
LOS COMENTARIOS
Son lineas que ignora el compilador pero sirven para documentar los
programas:
Empiezan con: /*
terminan con: */
no se pueden anidar
/*
ej1.c
Indica el menor de dos enteros leidos
*/
...
...
...
scanf("%d%d", &n1, &n2); /* aqui se leen dos
valores enteros */
...
...
C.01.05
# define PI 3.1416
# define EQ ==
----------
# define cuadrado(x) ( (x) * (x) )
----------
# include <stdio.h>
# include <math.h>
----------
# define PRUEBA 1
...
...
# if PRUEBA
printf("prueba: x = %d\n", x);
# endif
----------
# ifdef UNO
...
...
# else
...
...
# endif
( cc -DUNO fn.c )
----------
# ifndef
----------
C.01.06
LAS FUNCIONES
La función "main"
{
Cuerpo con: Declaraciones . . . . . . tipo v1, v2, v3;
Sentencias . . . . . . sentencia
...
sentencia
int menor(a, b)
int a, b;
{
if ( a<b ) return( a );
else return( b );
}
C.01.08
/*
ej1.c COMENTARIOS
Indica el menor de dos enteros leidos
*/
SENTENCIA PARA
#include <stdio.h> EL PRE-PROCESADOR
DEFINICION DE LA
FUNCION "main"
Encabezamiento. No hay
main ( ) parámetros
{ Cuerpo de la función
int n1, n2, menor ( ); Declaraciones de objetos
locales
DEFINICION DE LA
int menor ( a, b ) FUNCION "menor"
Encabezamiento. Los
int a, b; parámetros son "a" y "b"
pero...
REGLAS DE ALCANCE
Ejemplos de declaraciones
float superficie();
struct naipe {
int valor;
char palo;
} carta ;
typedef struct {
float real;
float imaginaria;
} complejo;
Reglas de alcance
main( )
{
int a, b;
...
...
{
float b, x, y;
... /* se conoce a "int a", pero no
... a "int b", que ha quedado
enmascarada. */
}
{
unsigned a;
char c, d;
... /* se conoce a "int b", pero 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" */
...
}
EXPRESIONES
s=s+i
n == 0
++i
Algunos operadores
SENTENCIAS
Un bloque empieza con " { " y termina con " } ", pudiendo contener
cualquier número de sentencias y declaraciones.
Todas las sentencias, excepto los bloques, terminan con el símbolo " ; ".
s=s+n;
if ( letra == '.' ) terminar( );
printf ( "mensaje\n" );
...
...
{
int j;
j = i-1;
while ( j >= 0 ) printf("%c", s[j--]);
printf ("\n");
}
...
...
C.01.14
cero es falso
distinto de cero es verdadero
expresión
verdadero falso
sentencia_1 sentencia_2
LA SENTENCIA "for"
expresión_1
sentencia
expresión_3
potencia = 1.0;
for (i=1 ; i<=exponente ; i++)
potencia=potencia*base;
i=1
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));
}
}
La función "printf"
Especificaciones de formato
Lista de valores
las sentencias:
Resultados:
x1=3.141600
x2=2.500000
Otro formato:
x1= 3.14
x2=2.50
C.01.18
Especificaciones de formato
"INDICE\n"
-Especificaciones de conversión:
%d %4d %7.4f
Lista de valores
La función "scanf"
Especificaciones de formato
Apuntadores a variables
La lista de apuntadores:
...
char letra; int n; float r ;
scanf ("%c %d %f", &letra, &n, &r);
...
char cad[80];
scanf ("%s", cad);
/*
ej3.c
Lee un numero entero y determina si es par o impar
*/
#include <stdio.h>
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);
}
-2-
ELEMENTOS LEXICOS
• Caracteres
• Símbolos:
Identificadores
Palabras reservadas
Constantes
Cadenas
Operadores
Separadores
C.02.02
Los caracteres
letras minúsculas: a b c d . . . z
letras mayúsculas: A B C D . . . Z
cifras: 0 1 2 3 4 5 6 7 8 9
caracteres
especiales: + = _ - ( ) * & % $ # !
| < > . , ; : " ' / ?
{ } ~ \ [ ] ^
caracteres
no imprimibles: espacio en blanco,
salto de linea,
marca de tabulador
C.02.03
LOS SIMBOLOS
identificadores:
palabras reservadas
separadores: {, }, ...
LOS IDENTIFICADORES
int i, j, k;
LAS CONSTANTES
Ejemplos:
CONSTANTES SIMBOLICAS
#define PI 3.1416
C.02.07
LAS CADENAS
"buenos dias"
"asi: \" se pueden incluir las comillas"
char titulo[24];
strcpy(titulo, "Curso de C");
printf("%s", titulo);
LOS OPERADORES
+ - / % & * etc...
LOS OPERADORES
Operadores Asociatividad
( ) [ ] -> . (miembro) izquierda a derecha
~ ! ++ -- sizeof (tipo) derecha a izquierda
-(unario) *(indirección) &(dirección)
* / % izquierda a derecha
+ - izquierda a derecha
<< >> izquierda a derecha
< <= > >= izquierda a derecha
== != izquierda a derecha
& izquierda a derecha
^ izquierda a derecha
| izquierda a derecha
&& izquierda a derecha
|| izquierda a derecha
?: derecha a izquierda
= += -= *= ... derecha a izquierda
, (operador coma) izquierda a derecha
C.02.10
LOS SEPARADORES
• El espacio en blanco
• La marca de tabulador
• El salto de linea
• Los comentarios (se trata el conjunto como
un espacio en blanco)
-3-
EXPRESIONES Y SENTENCIAS.
EXPRESIONES DE ASIGNACION.
C.03.02
LAS EXPRESIONES
i++
a+b
3.1416*r*r
densidad*volumen(a, b, c)
3.1416;
n=0;
++n;
s=s+n;
C.03.03
variable = expresion
Cuando se ejecuta, se evalúa la expresión que está a la derecha y el
resultado se asigna a la variable del lado izquierdo haciendo
conversión de tipo si es necesario. Ese valor es el que toma la
expresión en su conjunto también.
-4-
VISION GENERAL.
En "C":
pero...
ESCALARES:
Reales: float
double
pointer (punteros)
enum (enumerativos)
ESTRUCTURADOS: array
string
struct
campos de bits
union
C.04.04
int n; n=27;
float r; r=3.1416;
char c; c='a';
enum colores
{rojo,azul,verde}color;
color=verde;
C.04.05
float r[10][20][30];
float a[100][100];
int i,j;
a[1][2]=2.5;
a[i][j]=0.0;
struct naipe {
int valor;
char palo;
} c1, c2;
c1.valor=3;
c1.palo='e';
C.04.06
union numerico {
int n;
float x;
} numero;
numero.x=5.3;
C.04.07
DECLARACION DE VARIABLES
• la clase de almacenamiento
• el tipo al que pertenece
• 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
external
register
C.04.08
CLASES DE ALMACENAMIENTO
INICIALIZACION DE VARIABLES
POR DEFECTO:
INICIALIZACION DE ARRAYS
/*
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
printf ("\n\n");
printf ("c:\n");
printf ("%s\n\n", c);
printf ("sta:\n");
printf ("%d %f \n\n", sta.i, sta.x);
printf ("st:\n");
for (i=0; i<2; ++i) for (j=0; j<3; ++j)
printf ("%c %d %f\n", st[i][j].c, st[i][j].i, st[i][j].s);
}
enteros:
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
sta:
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
int n;
printf("%d", sizeof(n));
/*
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-
unsigned 32 0 232-1
(+4.294.967.295)
unsigned 16 0 216-1
short (+65.535)
unsigned 32 0 232-1
long (+4.294.967.295)
Constantes enteras
octal 0
0-7
decimal
1-9
0-9
0-9
0x a-f
0X A-F
hexadecimal
Ejemplos: 0
25
32767
0777
0x1A
C.05.05
-231 231 - 1
-2.147.483.648 2.147.483.647
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
+ - * / %
En HP-UX:
Son unarios.
Ejemplos
valor mínimo: 0
valor máximo: 231-1= 4.294.967.295
C.05.11
d entero decimal.
o entero octal que no empieza con 0.
x entero hexadecimal que no empieza con x.
u entero decimal sin signo.
main( )
{
int n;
printf("Introducir una constante entera:\n");
scanf("%d", &n);
printf("El valor leido es: %d\n", n);
}
C.05.12
float double
Constantes reales
0-9
0-9
0-9
e
0-9 0-9
E
+
-
Ejemplos: 27.
3.14
3.14e10
.612e-5
47e-3
float double
============ =============
precisión 6 cifras 16 cifras
-38<=n<=+38 -38<=n<=+38
+ - * /
/*
ej6.c
Precisión en el cálculo
*/
# 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
sqrt( )
exp( )
log( )
sin( )
cos( )
tan( )
etc...
# include <math.h>
cc fn.c -lm
{
double x;
scanf("%f", &x);
printf("%20.12e\n", exp(x));
}
C.05.15
{
float r;
printf("Un número en coma flotante ?\n");
scanf("%f", &r);
printf("El valor leido es: %f\n", r);
}
C.05.16
'A'
7 6 5 4 3 2 1 0
0 1 0 0 0 0 0 1
65
Nombre Valor
del carácter Escritura en C entero
============= ============ =====
nulo '\0' '\0' 0
retroceso '\b' '\10' 8
tabulador '\t' '\11' 9
salto de linea '\n' '\12' 10
salto de página '\f' '\14' 12
retorno de carro '\r' '\15' 13
comillas '\"' '\42' 34
apóstrofo '\'' '\47' 39
barra invertida '\\' '\134' 92
C.05.17
Derecha
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 rs 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
Observaciones:
• Los códigos de los caracteres 0 a 31 y 127 no son imprimibles
• Los códigos de las letras mayúsculas, los de las minúsculas y los de
las cifras son contiguos entre sí.
• La diferencia entre una letra mayúscula y su correspondiente
minúscula es 32.
C.05.18
Ejemplos
printf("Resultados\n");
{
char s[80]; int lon;
lon=0;
while ( s[lon] != '\0' ) lon++;
}
'a' '\0'
getchar( ) putchar( )
scanf( ) printf( )
#include <stdio.h>
main( )
{ int c;
c=getchar( );
printf("El carácter leido es: %c\n", c); }
#include <stdio.h>
main( )
{ int c;
while ( (c=getchar( )) != EOF )
putchar(c); }
C.05.20
scanf( ) y printf( )
/*
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
= += -= *= /= %=
>>= <<= &= ^= |=
Abreviaturas
En C se admiten abreviaturas para simplificar la escritura de algunas
sentencias de asignación:
Forma general:
Ejemplos
expresión 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
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"
Ejemplos
expresión 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
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"
Si se trata de una
degradación : i=d
se puede perder información
porque se desecha la parte
fraccionaria.
Al evaluarse: i=c
(t ipo ) expresión
Ejemplo: int;
...
.. (double) i ... hace que se convierta el valor
de "i" en uno de tipo "double"
para la evaluación de la
expresión.
Ejemplos:
(char) (3 - 3.14 * x)
k = (int)((int) x + (double) i + j )
(float) (x = 77)
Aquí se usa una variable entera ("i") para controlar un bucle y para
realizar un cociente con parte fraccionaria:
int i;
for ( i=1; i<100; ++i )
printf("%d / 2 es: %f\n", i, (float)i/2);
C.05.26
• el valor asignado
• la dirección en memoria
de cualquier variable
Direcciones de memoria.
"Apuntan" a dirección de memoria donde se
almacena un valor del tipo base.
tipo_base *variable
int *p, i;
p=0
p = NULL /* equivalente a p=0 */
p = &i
p = ( int * ) 1501
main( )
{
float i=3.1416, *p;
p=&i;
printf("el valor de i es %f\n", *p);
printf("la dirección de i es %d\n", p); }
int n;
printf("Introducir un entero\n");
scanf("%d", &n);
printf("El valor leido es: %d\n", n);
C.05.28
Se puede apuntar a:
• variables: int n;
&n
No se puede apuntar a:
La aritmética de punteros
int *p;
al evaluarse " ++p " el puntero pasa a apuntar al
valor almacenado 4 bytes más adelante
char *( *x( ) )[ ]
A)
Hay que tener en cuenta las reglas de prioridad y asociatividad de los
operadores: ( ) [ ] *
B)
Se busca la variable y se aplican los operadores siguiendo las reglas de
precedencia y asociatividad.
C)
Se hace la siguiente lectura:
Ejemplo:
Ejemplos
int i i es un entero
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
Op. de
desplazamiento: desp. hacia la izquierda <<
desp. hacia la derecha >>
c.05.33
LOS OPERADORES
Operadores Asociatividad
( ) [ ] -> . (miembro) izquierda a derecha
~ ! ++ -- sizeof (tipo) derecha a izquierda
- (unario) *(indirección) &(dirección)
* / % izquierda a derecha
+ - izquierda a derecha
<< >> izquierda a derecha
< <= > >= izquierda a derecha
== != izquierda a derecha
& izquierda a derecha
^ izquierda a derecha
| izquierda a derecha
&& izquierda a derecha
|| izquierda a derecha
?: derecha a izquierda
= += -= *= ... derecha a izquierda
, (operador coma) izquierda a derecha
C.05.34
x y x&y
C.05.37
Ejemplos
/*
Función para escribir la representación binaria
de un valor "int"
*/
bitprint ( n )
int n;
{
int i, mascara;
mascara=1; /* 0...001 */
mascara=mascara << 31; /* se desplaza el "bit" 1 hacia
el extremo más significativo */
for ( i=1; i<=32; ++i ) {
putchar( ((n&mascara)==0) ? '0' : '1' );
n=n<<1;
}
}
/*
Esta función 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++;
return (unos)
}
C.05.36
Máscaras
00000000000000000000000000000001
Ejemplos
/*
Función para escribir la representación binaria
de un valor "int"
*/
bitprint ( n )
int n;
{
int i, mascara;
mascara=1; /* 0...001 */
mascara=mascara << 31; /* se desplaza el "bit" 1 hacia
el extremo más significativo */
for ( i=1; i<=32; ++i ) {
putchar( ((n&mascara)==0) ? '0' : '1' );
n=n<<1;
}
}
/*
Esta función 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++;
return (unos)
}
C.05.38
Empaquetamiento
Ejemplo:
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;
return(p); }
unpack ( p )
int p;
{
extern a, b, c, d;
d=p&0xff;
c=(p&0xff00)>>8;
b=(p&0xff0000)>>16;
a=(p&0xff000000)>>24; }
C.05.39
color=azul;
...
if ( color==amarillo ) . . .
enumerador valor
lunes 0
martes 1
miercoles 2
jueves 3
viernes 4
enumerador 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;
{
return ( (enum dia) ( (( int)d+1 ) % 7 );
}
-6-
Op de Igualdad: == igual a
!= distinto de
En C: FALSO es 0 ó 0.0
VERDADERO es distinto de 0,
o distinto de 0.0
C.06.03
positivo 0 1 0 1
cero 0 0 1 1
negativo 1 0 1 0
j=7;
printf("%d\n", 3<j<5); se escribirá: 1
• son binarios
• actúan sobre expresiones
• producen un valor lógico: int 0 FALSO
int 1 VERDADERO
Semántica:
cero 1 0
no cero 0 1
• Se aplican a expresiones
• El operador "!" es unario, los demás son binarios
• Producen uno de estos valores: int 0 FALSO
int 1 VERDADERO
cero 1
no cero 0
no ( no x ) es x
! ( ! 5 ) es 1
cero cero 0 0
cero no cero 0 1
no cero cero 0 1
no cero no cero 1 1
C.06.06
en exp1 || exp2
si exp1 tiene el valor 1, no se evalúa exp2.
Ejemplo
i=0;
while (i++<3 && (c=getchar()) != EOF) acción...
La sentencia vacía
";"
Sentencia compuesta
{
int i;
float p;
p=1.0;
for (i=1; i<=e; ++i) p=p*b;
return(p);
}
C.06.08
if ( expresion ) sentencia
Se evalúa la expresión. Si tiene un valor distinto de cero se ejecuta la
"sentencia1" y se salta la "sentencia2". Si tiene el valor cero, se salta la
"sentencia1" y se ejecuta la "sentencia2".
expresión
verdadero falso
sentencia_1 sentencia_2
if ( x<min ) min=x;
------
if ( c==' ' ) {
++contador;
printf("hallado otro 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.11
Es un operador ternario.
La sentencia: x = ( y<z ) ? y : z ;
Ejemplo:
entrada SI
expresion
es salida
cero
sentencia NO
expresion1;
while ( expresion2 ) {
sentencia
expresion3;
}
factorial=1;
for (i=1; i<=n; ++i) factorial *= i;
Pueden faltar alguna o todas las expresiones, pero deben permanecer 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++;
i=1; suma=0;
for ( ; ; ) {
suma += i++;
printf("%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
expresion1 , expresion2
suma=0 , i=1
Se suele usar en las sentencias " for " porque permite hacer asignación
múltiple de valores iniciales y procesamiento múltiple de índices.
NO
entrada SI
sentencia expresion
es salida
cero
/*
Se repite la orden de lectura mientras
el valor introducido sea menor o igual
que cero
*/
{
int n;
do {
printf("Entero positivo ? ");
scanf("%d", &n);
} while ( n<=0 );
}
/*
ej10.c
Calculo del numero "e" . ( xn = ( 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);
}
switch ( expresion_entera ) {
1. Se evalúa la "expresion_entera"
2. Se ejecuta la claúsula "case" que se corresponda con el valor
obtenido en el paso 1. Si no se encuentra correspondencia, se
ejecuta el caso "default"; y si no lo hay, termina la ejecución de
"switch".
3. Termina cuando se encuentra una sentencia "break" o por caída al
vacío.
c=getchar( );
while ( c != '.' && c != EOF ) do {
switch ( c ) {
case 'c' : consultas( );
break;
case 'a' : altas( );
break;
case 'b' : bajas( );
break;
case 'm' : modificaciones( );
break;
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
# include <math.h>
...
while ( 1 ) {
scanf("%lf", &x);
if ( x<0.0 ) break;
printf("%f\n", sqrt(x));
}
switch ( c ) {
case '.' : mensaje("fin");
break;
case '?' : ayuda( );
break;
default : procesar (c);
}
C.06.21
El caso: Es equivalente a:
/* 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
...
{
...
goto error;
...
}
error: mensaje( );
-7-
LAS FUNCIONES
Las funciones
Cada función expresa la realización del algoritmo que resuelve una de las
partes en que se ha descompuesto el problema completo en cuestión.
# 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
/*
ej14.c
Captura el primer argumento, se convierte a entero ("int")
y se multiplica por 2.
# 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]));
}
/*
ej1.c COMENTARIOS
Indica el menor de dos enteros leidos
*/
SENTENCIA PARA
#include <stdio.h> EL PRE-PROCESADOR
DEFINICION DE LA
FUNCION "main"
Encabezamiento. No hay
main ( ) parámetros
{ Cuerpo de la función
int n1, n2, menor ( ); Declaraciones de objetos
locales
DEFINICION DE LA
int menor ( a, b ) FUNCION "menor"
Encabezamiento. Los
int a, b; parámetros son "a" y "b"
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);
}
void saltar_lineas ( n )
int n;
{
int i;
for ( i=1; i<=n; ++i ) printf("\n");
}
satar_lineas (10);
El valor de retorno
return;
return ( expresión );
Semántica:
concluye la ejecución de la función y se devuelve el
control al medio que la invocó. El valor de la expresión se
convierte al tipo de la función y se devuelve como valor
de la función.
arrays
structs
unions
funciones
i entero
ip puntero a entero
f funcion que devuelve un entero
fip función que devuelve puntero a un entero
pfi puntero a función que devuelve entero (la
indirección respecto a un puntero a
función, es una función que devuelve un
entero).
C.07.08
• Invocándola normalmente:
escribiendo su nombre seguido de una lista de parámetros
escritos entre paréntesis.
c = getchar ( );
m = raiz ( m );
s = menor ( lista, num );
peso = volumen ( a, b, c) * densidad (material);
• Tomando su dirección:
Cuando el nombre de una función aparece dentro de una
expresión en un lugar que no es el que le corresponde según
el formato normal indicado antes, se genera un puntero a la
función.
main()
{
int f( ), g( );
...
...
g ( f );
...
}
int g(funcion)
int (*funcion) ( );
{
...
(*funcion) ( );
...
}
C.07.09
/*
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);
}
{ {
int n,m; int n,m;
n=5; n=5;
printf("%d\n", n); printf("%d\n", n);
m=doble( n ); m=doble( &n );
printf ("%d\n", n); printf ("%d\n", n);
} }
Variables locales
Variables globales
main( )
{
int a, b;
...
...
{
float b, x, y;
... /* se conoce a "int a", pero no
... a "int b", que ha quedado
enmascarada. */
}
{
unsigned a;
char c, d;
... /* se conoce a "int b", pero 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" */
...
}
Clases de almacenamiento
• tipo
• clase de almacenamiento
• auto
• extern
• register
• static
{ {
char c; auto char c;
int i, j, k; auto int i, j, k;
... ...
} }
Su uso es muy limitado porque suele haber muy pocos registros de alta
velocidad.
Locales estáticas
Globales estáticas
Funciones estáticas
Las funciones estáticas son visibles sólo dentro del fichero en el que se
han declarado (útil para desarrollar módulos privados).
C.07.17
La recursividad
/*
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-
VISION GENERAL.
• array
• string
• struct
• bits
• union
C.08.02
Se caracterizan por:
char lin[80];
El tipo "struct"
struct naipe {
int valor;
char palo;
};
struct naipe carta, c;
...
carta.valor=10;
carta.palo='e';
c=carta;
Campos de bits
struct 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;
struct naipe {
unsigned valor : 4;
unsigned palo : 2;
}
struct naipe carta;
carta.valor=9;
carta.palo=2;
C.08.07
struct octetos {
unsigned byte0: 8, byte1: 8, byte2: 8, byte3: 8;
};
struct 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 palabra {
int x;
struct octetos y;
struct 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-
int v[10];
#define TAM 10
int a[TAM];
Inicialización de "arrays"
Sintaxis:
El índice
Punteros y "arrays"
Los punteros y los "arrays" se usan de forma parecida para acceder a
las direcciones de memoria.
# define TAM 3
int v [TAM]
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
Aritmética de punteros
v=p ++v v += 2
C.09.07
"arrays" multidimensionales
int a[3][5];
int b[3][3][3];
Se puede pensar que el índice que varía más deprisa es el que está más a
la derecha; o que las matrices se almacenan por filas.
int a[3][5], n, m;
...
...
sumar (b, n, m)
int b[ ][5], n, m;
{
etc...
}
apuntador a "arrays" de
5 enteros
C.09.10
"ejemplo de cadena"
<string.h>
C.09.11
# include <string.h>
strcmp comparar
strncmp comparar "n" elementos
strlen longitud
etc...
strcat encadenar
strncat encadenar "n" elementos
strcpy copiar
strncpy copiar "n" elementos
strchr localizar un elemento
etc...
C.09.12
/*
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");
}
/*
ej19.c
*/
int strlen(s)
char *s;
{
int i;
for ( i=0; *s != '\0'; s++ ) ++i;
return( i );
}
{
char s[24];
strcpy(s, "valor asignado");
printf("%s\n", s);
}
"arrays" de punteros
char s[1024];
char *d[128];
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]
m o s c a \0 g a t o \0 o c a \0
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]
m o s c a \0 g a t o \0 o c a \0
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]
etc....
C.09.17
La función 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 función "leer_palabras"
La función "escribir_palabras"
La función "ordenar"
$ factorial 4
main(argc, argv)
main(argc, argv)
int argc;
char *argv[ ];
...
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 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
"arrays" no uniformes
El "array a":
• Es bidimensional
• Puede almacenar hasta 60 caracteres
• Contiene 3 "arrays" de "arrays" de 20 caracteres
El "array p":
- 10 -
Declaración de estructuras
struct naipe {
int valor;
char palo;
} c1, c2;
struct {
int valor;
char palo;
} carta, baraja[40];
Inicialización
static struct {
char c;
int i;
float s;
} x[2][3]= { { 'a', 1, 3e3 },
{ 'b', 2, 4e2 },
{ 'c', 3, 5e3 },
{ 'd', 4, 6e2 }
};
C.10.04
.
variable_estructura nombre_miembro
struct complejo {
float real;
float imaginaria;
} x, y, z, a[10][10];
x.real=2.7;
x.imaginaria=-0.5;
y.real=x.real;
z=x;
a[2][4].real=x.real;
C.10.05
variable_puntero_a_estructura ->variable_miembro
Ejemplo
struct alumno {
int curso;
char grupo;
char nombre[40];
float notas[10];
};
struct alumno buf, *p=&buf;
buf.curso=2;
buf.grupo='A';
strcpy( buf.nombre, "Pedro Perez");
buf.notas[5]=7.5;
expresión
expresión equivalente valor
============ ======================
buf.curso p->curso 2
buf.grupo p->grupo A
buf.nombre p->nombre Pedro Perez
*(p->nombre+2) p->nombre[2] d
*p->nombre+2 *(p->nombre)+2 R
C.10.07
Estructuras y funciones
struct complejo {
float re;
float im;
};
main( )
{
struct complejo x, y, z;
x.re=2.5; x.im=-5.4;
y.re=0.4; y.im=12.1;
z = *sumar(x, y);
...
}
Campos de bits
struct word {
unsigned byte0 : 8,
byte1 : 8,
byte2 : 8,
byte3 : 8;
};
struct word w;
w.byte0='A';
w.byte1='B';
Ejemplos
struct naipe {
unsigned valor : 4; /* para representar el entero 12
necesito más de 3 bits */
unsigned palo : 2; /* con 2 bits puedo representar
4 valores diferentes */
};
struct naipe carta;
carta.valor=3;
carta.palo=1;
struct rs232c {
unsigned pin1: 1,
transmision_datos: 1,
recepcion_datos: 1,
rts: 1,
cts: 1,
dsr: 1,
sg: 1,
: 12,
dtr: 1,
: 5;
};
struct rs232c estado;
...
if (estado.cts) printf("listo para enviar");
...
C.10.10
Las uniones
/*
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);
}
vector v;
matriz a, b, c;
# include <stdio.h>
/*
ej24.c
*/
#define N 100
typedef double escalar;
typedef escalar matriz[N][N];
/*
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;
#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
void cpxprint(complex x)
{
printf("%f + %f i\n", x.re, x.im);
}
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));
}
/* 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;
#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 cpxprint(complex x)
{
printf("(%f + %f i)\n", x.re, x.im);
}
tipo_componente cpxabs(complex x)
{
complex c, p;
cpxconj(x, &c);
cpxprod(x, c, &p);
return(sqrt(p.re));
}
/*
ej27.c
Se maneja un tipo definido por el usuario para implementar
operaciones con numeros complejos.
Se manejan funciones que devuelven punteros a estructuras
*/
#include <math.h>
#include <stdio.h>
typedef float tipo_componente;
typedef struct {
tipo_componente re;
tipo_componente im;
} complex;
complex *cpxasig(), *cpxsuma(), *cpxprod(), *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) {
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.16.a
cpxprint(x)
complex x;
{
printf("%f + %f i\n", x.re, x.im);
}
complex *cpxsuma(x, y)
complex x, y;
{
complex z;
z.re=x.re+y.re;
z.im=x.im+y.im;
return(&z);
}
complex *cpxprod(x, y)
complex x, 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.16.b
complex *cpxconj(x)
complex x;
{
complex z;
z.re= x.re;
z.im= -x.im;
return(&z);
}
tipo_componente cpxabs(x)
complex x;
{
complex z;
z= *cpxprod(x, *cpxconj(x));
return(sqrt(z.re));
}
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= *cpxprod(v[i], *cpxconj(v[i]));
s += z.re;
}
return(sqrt(s));
}
C.11.01
- 11 -
# include <stdio.h>
asignación
identificador nombre inicial
========= ======================= ========
stdin fichero estándar de entrada teclado
stdout fichero estándar de salida pantalla
stderr fichero estándar para mensajes pantalla
de error
# include <stdio.h>
main( )
{
FILE *fp;
...
fp = fopen ( "datos", "r" );
...
fclose ( fp );
...
}
C.11.05
# include <stdio.h>
main()
{
FILE *fp;
char nombre[36];
printf("nombre de fichero ? ");
scanf("%s",nombre);
if ( ! (fp=fopen(nombre,"r")) )
printf("error\n");
else
procesar(fp);
...
...
}
C.11.07
int getchar ( );
/*
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
/*
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
/* ej30.c
Se lee un número de caracteres a partir de una posición
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 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
int fwrite ( char *buf, int tam, int num, FILE *fp);
/*
ej31.c
Se copia el contenido de un fichero, operando
en binario con buffer de 512 bytes
*/
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
Carácter de
Conversión Interpretación del flujo de entrada
========= ==========================
d Entero decimal
o Entero octal
x Entero hexadecimal
u Entero decimal sin signo
e Número de coma flotante
f Equivalente a "e"
c Un carácter
s Cadena de caracteres
[cadena] Cadena especial
Los caracteres 'd', 'o', 'x', 'e' y 'f' pueden ir precedidos por 'l' para
indicar conversión a "long" o a "double".
Los caracteres 'd', 'o', 'x' pueden ir precedidos por 'h' para convertir a
"short".
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 nombre[50];
25 54.32E-1 eugenio
12,5,7
/*
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 */
Modificadores
- ajustar a la izquierda
+ escribir el signo siempre
etc...
C.11.25
Caracteres de conversión
/*
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 estáticas
Estructuras dinámicas
Ejemplo
m o c a
struct lista {
char dato;
struct lista *siguiente;
} nodo;
La flecha representa
"estar apuntando a . . ."
dato puntero
malloc ( tamaño )
1 2 3 4 5
NULL
principio fin
cima
NULL
C.12.06
fin
NULL
NULL
principio
ARBOL BINARIO
raiz
C.12.07
La función "malloc"
struct lista {
char dato;
struct lista *siguiente;
} nodo, *p;
...
p = malloc ( sizeof(lista) );
...
p = (struct lista *) malloc (sizeof(lista) );
...
if ( p=malloc(sizeof(lista)) ) procesar( );
else printf("error\n");
C.12.08
La función "free"
struct lista {
char dato;
struct lista *siguiente;
} nodo, *p;
...
p = malloc ( sizeof(lista) );
...
free ( p );
...
C.12.09
Encadenamiento de datos
struct lista {
char dato;
struct lista *siguiente;
} x, y, z, *p;
x y z
A NULL B NULL C NULL
Encadenamiento:
x.siguiente = &y;
y.siguiente = &z;
x y z
A B C NULL
Pero sería muy poco útil usar variables diferentes para manejar
estructuras dinámicas.
C.12.10
A B C D E NULL
principio
fin
Definición de datos:
# define NULL 0
A A NULL
(4)
A NULL
principio
fin
(5)
A NULL B NULL
principio
fin
(6)
A B NULL
principio
fin
(7)
A B NULL
principio
fin
C.12.12
Ejemplo
1 2 3 4 5
NULL
principio fin
/*
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;
# 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 añaden 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);
}
}
/*
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");
}
Retirar un elemento
principio
NULL
nodo fin
nodo = principio;
principio
NULL
fin
nodo
principio
NULL NULL
nodo fin
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
/*
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;
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);
}
}