El lenguaje de programación C (Transparencias)

Anuncio
El lenguaje de programación C
(Transparencias)
(C) Javier Miranda 1996-2004
Reservados todos los derechos
Esta colección de transparencias forma parte del contenido
del libro “Diseño de Software con C y UNIX (Volumen 1)”,
J.Miranda (1996), con ISBN 84-87526-45-4.
18 de febrero de 2004
18 de febrero de 2004
Transp. 1
Historia
1965: Multics (MIT, General Electric, Laboratorios Bell).
1968: Thompson desarrolla Unix para DEC PDP-7 (8k, sin software).
1969: Thompson crea B.
1970: Thompson continua desarrollo de Unix sobre DEC PDP-11 (24k).
1971: Unix comienza a tener usuarios. Thompson desarrolla de NB.
1973: Creación de C. Thompson reescribe Unix en C. Instala C en otras
arquitecturas.
1978: The C programming language. Kernighan, Ritchie. Johnson
desarrolla pcc.
1979: Johnson desarrolla lint.
1983: Creación comite para creación del estándar de C.
1989: C se convierte en estándar ISO/IEC 9899-1990
1986: Stroustrup crea C++.
18 de febrero de 2004
Transp. 2
El compilador de C
Fichero
fuente
Preprocesador
Otros ficheros
(include)
Compilador
Ensamblador
Fichero
objeto
Bibliotecas
del sistema
Enlazador
Fichero
ejecutable
Ficheros
objeto del
usuario
18 de febrero de 2004
Transp. 3
El preprocesador de C
#define
* Macros simples
#define NUM 15
/* Numero de elementos */
#define TOTAL 2*NUM/4
#define MENSAJE "El lenguaje C"
* Macros con parámetros
#define INTERCAMBIA(X,Y) {\\
int tmp = X;\\
X=Y;\\
Y=X;}
* Operador #
#define ESCRIBE(X) printf(#X "=%d",X)
#undef
#define NUM 15
.
.
.
#undef NUM
#define NUM 34
18 de febrero de 2004
Transp. 4
El preprocesador de C
Compilación condicional
(#if #ifdef #ifndef #else #elif #endif)
#define DEBUG 1
#define
INTEL
...
...
int OUT(...)
{
#ifdef INTEL
...
#endif
#ifdef VAX
...
#endif
...
}
int distancia(...)
{
...
#if DEBUG
printf(...);
#endif
...
}
#include
#include "fichero.h"
#include <fichero.h>
#line
#line 300 "PRUEBA.PAS"
...
...
#line 301
18 de febrero de 2004
Transp. 5
Introducción
/* Ejemplo de introduccion a la programacion en C */
#include <stdio.h>
int Suma (a,b)
int a,b;
{ int tmp;
tmp = a + b;
return tmp;
}
void Resta(a,b,Resultado)
int a,b;
int *Resultado;
{
*Resultado = a - b;
}
int main()
{ int a,b = 0;
int Respuesta;
scanf("%d %d", &a, &b);
Respuesta = Suma(a,b);
printf("La suma de %d y %d es %d ", a, b, Respuesta);
Resta(a, b, &Respuesta);
printf("y la resta es %d\n", Respuesta);
exit (0);
}
18 de febrero de 2004
Transp. 6
Tipos de datos y constantes
char
Tipos de datos
int
cualificadores
float
short
long
unsigned
double
char
ascii
octal
Salto de línea (LF)
\n
Tabulador horizontal
\t
Tabulador vertical
\v
Retorno de carro (CR)
\r
decimal
Salto de página (FF)
\f
octal
Alarma
\a
hexadecimal
Barra invertida
\\
Interrogación
\?
Apóstrofo
\’
Comillas
\"
hexadecimal
string
Constantes
int
float
Secuencias de escape
18 de febrero de 2004
Transp. 7
Operadores
Operadores
Aritméticos
+ − * / %
Relacionales
< <= > >= == !=
Lógicos
&& || !
nivel bits
& | ^ << >> ~
Autoincremento, autodecremento
Asignación
Múltiple
Operador coma
Precedencia de operadores
( ) [ ] −> .
! ~ ++ −− + − * & (tipo) sizeof()
* / %
+ −
<< >>
< <= > >=
== !=
&
^
|
&&
||
?:
= += −= etc.
,
a=b=c=d
Compuesta
Expresión condicional
++ −−
a op= b
e1 ? e2 : e3
e1 , e2
Asociatividad
18 de febrero de 2004
Transp. 8
Ejemplo con operadores
main()
{
int a,b,c,d,e,max,abs;
char c;
}
a = - b + c * d / (e % f);
/* Aritmeticos */
a = ((b > c) == (d <= e));
/* Relacionales */
a = ! ( (a && b) || c );
/* Logicos */
a = ~ ( (a & b) | c);
/* Logicos nivel bit */
a++;
b = ++a;
c = a++;
d = a--;
/* Autoincremento */
/* Autodecremento */
a = b = c = d+e;
a += 2;
a /= b + c;
/* Asignacion multiple */
/* Asignacion compuesta */
max = (b>c) ? b : c ;
abs = (a>0) ? a : -a ;
/* Expresion condicional*/
a = (b=2,c=3);
/* Operador coma */
a = sizeof(b);
/* Operador "sizeof()" */
c = (char) a;
d = (int) c + d;
d = (int) (c+d);
/* Conversion de tipos */
18 de febrero de 2004
Transp. 9
Control de flujo
Control
de flujo
*
if (expresión)
sentencia
[else
sentencia]
*
switch (expresión) {
{ case expresión−constante: sentencia }
[ default: sentencia ]
}
*
while (expresión)
sentencia
*
do
*
for (expresión−1; expresión−2; expresión−3)
sentencia
*
break
*
continue
*
goto
sentencia
while (expresión)
18 de febrero de 2004
Transp. 10
Funciones
int f1(s)
char s[];
{
float f2(int,float);
/* Formato K&R */
...
if (...)
return(0);
...
}
float f2(int a, float b)
{
...
if (a>0)
f2(a,b);
...
}
main()
{
...
}
/* Formato ANSI-C */
18 de febrero de 2004
Transp. 11
Variables
Fichero 1:
int a,b;
extern char c;
static char d;
/* Externa */
/* Externa definida en otro fichero */
/* Estatica externa */
int f1()
{
int c;
static char d;
extern float e;
/* Externa */
/* Automatica */
/* Interna estatica */
/* Externa definida en otro fichero */
...
}
Fichero 2:
char c;
float e;
/* Externa */
/* Externa */
static int f2()
{
register i;
/* Externa estatica */
...
{
int i;
...
}
...
}
/* Registro */
/* Automatica */
18 de febrero de 2004
Transp. 12
EJEMPLO.ADA
package ejemplo is
a,b,c:integer;
function f1(x,y:integer)
return integer;
...
end ejemplo;
package body ejemplo is
d,e:integer;
function f1(x,y:integer)
return integer is
aux:integer;
begin
...
end;
procedure p1(z:character) is
begin
...
for i in 1..N loop
...
end loop;
...
end;
end;
EJEMPLO.C
int a,b,c;
static int d,e;
int f1(int x,y)
{
int aux;
...
}
static void p1(char z)
{
...
{
register i;
for (i=1;i<n;i++) {
...
}
}
...
}
18 de febrero de 2004
Transp. 13
Entrada/Salida
#include <stdio.h>
main()
{
char ch = \’{A}’;
char *p = &ch;
int
n = 1234;
int
m = 0;
float f = 3.1416;
char s1[50],s2[50],s3[50];
/* Entrada/Salida basica */
putchar(’\n’);
ch=getchar();
/* Entrada/Salida formateada */
printf("Entero %d, Octal %o, Hexadecimal %x, ",n,n,n);
printf("Caracter \’%c\’, ",ch);
printf("Doble %f, Puntero %p\n",f,p);
printf("Introduce un numero: ");
scanf("%d",&n);
ch=getchar();
printf("Correcto (S/N) ?");
ch=getchar();
sprintf(s1,"Pongo %d en la string",n);
sscanf(s1,"%s %d %s",s2,&n,s3);
printf("%s %d %s\n",s2,n,s3);
}
18 de febrero de 2004
Transp. 14
Estructuras de datos
Sinónimo (alias)
typedef int longitud;
typedef char string;
...
longitud maxlen,auxlen;
string nombre[20];
int maxlen,auxlen;
char nombre[20];
Enumerado
Declaración
enum boolean {FALSE,TRUE};
enum meses
{ENE = 1, FEB, MAR, ABR, MAY, JUN,
JUL, AGO, SEP, OCT, NOV, DIC };
enum escapes {NEWLINE = ’\n’, BACKSPACE = ’\b’};
boolean b;
meses tabla[23];
Acceso
b = FALSE;
tabla[12] = OCT;
18 de febrero de 2004
Transp. 15
Estructuras de datos
Array
Declaración
int a[25]
char s[]="123";
int lista[3]
/*char s[]={’1’,’2’,’3’,’\0’}*/
= {12,4,-2};
int tabla[2][4] = { {1,2,3,4},
{5,6,7,8} };
Acceso
s[0]
lista[2]
tabla[i][j]
18 de febrero de 2004
Transp. 16
Estructuras de datos
Estructura (Registro)
Declaración
struct {
int id;
char nombre[20];
struct {
int dia;
int mes;
int anyo;
} fecha_ingreso;
} x,empleados[30];
struct fecha {
int dia;
int mes;
int anyo;
}
struct info {
int id;
char nombre[20];
struct fecha fecha_ingreso;
}
struct info x,empleados[30];
Acceso
x.id
empleados[i].nombre;
empleados[i].fecha_ingreso.dia
18 de febrero de 2004
Transp. 17
Estructuras de datos
Union
union u_tag
int
float
char
}
{
i;
f;
c;
Campos de bit
#define INTERRUPCION 1
#define DMA
2
#define MOTOR_ON
4
main() {
int control;
flags |= INTERRUPCION;
flags &= ~DMA);
}
struct {
unsigned interrupcion :1;
unsigned dma
:1;
unsigned motor_on
:1;
} control;
main()
{
control.interrupcion = 1;
control.dma
= 0;
}
18 de febrero de 2004
Transp. 18
Punteros
void swap(px,py)
int *px,*py;
{
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
main()
{
int x,y;
int *p1;
int *p2 = 0;
int **p3;
void swap();
x
/* NULL */
= 27;
p1 = &x;
y = *p1;
y = *p1 + 1;
printf("%d\n", *p1);
*p1 = 0;
*p1 += 1;
(*p1)++;
if (p2 != p1)
p2 = p1;
*p3 = p1;
swap(&y,*p3);
}
18 de febrero de 2004
Transp. 19
Punteros: arrays y funciones
struct registro_persona {
char nombre[15];
int dia,mes,anyo;
}
void f(tabla);
int tabla[2][4];
{
...
}
/* int tabla[][4] o int(*tabla)[4] */
main()
{
struct registro_persona tabla[18];
struct registro_persona *ptr, aux;
int matriz[2][4];
int i;
int (*fnc)();
ptr = &tabla;
aux = *ptr;
aux = *(ptr+3);
ptr++;
i = ptr->dia;
f(matriz);
fnc = &f;
(*fnc)(matriz);
}
/* Cuidado con (*ptr+3) */
/* (*ptr).dia
*/
18 de febrero de 2004
Transp. 20
Punteros: strlen()
strlen(s)
char s[];
{
int n;
/* VERSION 1 */
for (n=0; s[n] != ’\0’; n++);
return(n);
}
strlen(s)
char *s;
{
int n;
/* VERSION 2 */
for (n=0; *s != ’\0’; s++, n++);
return(n);
}
strlen(s)
/* VERSION 3 */
char *s;
{
char *p = s;
while (*p != ’\0’) p++;
return(p-s);
}
strlen(s)
/* VERSION 4 */
char *s;
{
char *p = s;
while (*p) p++;
return(p-s);
}
18 de febrero de 2004
Transp. 21
Parámetros lı́nea comandos
main(argc, argv)
int argc;
char *argv[];
{
int i;
/* Version 1 */
for (i=1;i<argc;i++)
/* Procesar argv[i] */
}
main(argc, argv)
/* Version 2 */
int argc;
char **argv;
{
while (--argc) {
/* Procesar *argv */
/* argv++ */
}
}
18 de febrero de 2004
Transp. 22
Tratamiento de ficheros
#include <stdio.h>
main(int argc, char *argv[])
{
FILE *f1,*f2;
int c;
if (argc != 3) {
fprintf(stderr,"Sintaxis: copy
exit(1);
}
if ( (f1 = fopen(argv[1],"r")) ==
fprintf(stderr,"ERROR: Fichero
exit(2);
}
if ( (f2 = fopen(argv[2],"w")) ==
fprintf(stderr,"ERROR:No puedo
exit(2);
}
while ( (c= getc(f1)) != EOF )
putc(c,f2);
fclose(f1);
fclose(f2);
}
origen destino\n");
NULL) {
’%s’ inexistente.",argv[1]);
NULL) {
crear ’%s’.",argv[1]);
18 de febrero de 2004
Transp. 23
Errores frecuentes de los
programadores de C
1. Realizar una comparación con =.
if (i=3) return 1;
else return 0;
2. Anidar comentarios.
/* Comento este fragmento de codigo
if (a==4)
/* Si elijo la opcion 4 */
f(a);
*/
3. Añadir ; al final de una sentencia de control de flujo.
while (i<100);
s=s+a[i];
4. Indentar mal el programa.
if (a)
if (b)
f();
else
g();
if (a)
j = 1;
k = 0;
int* ptr1, ptr2;
5. Utilizar mal los operadores de autoincremento/autodecremento.
a[i++] = i++;
6. Equivocar el orden de evaluación de expresiones.
if (fp=fopen(fichero,"r") == NULL)
return (NULL);
18 de febrero de 2004
Transp. 24
Errores frecuentes de los
programadores de C
7. Pasar el valor de una variable en vez de su dirección.
scanf("%d",i);
8. Sobrepasar el lı́mite de un array.
9. Confundir “\n” con’\n’.
10. Declarar mal los parámetros de una función.
invertir(str)
{
char *str;
...
}
11. Especificar un directorio mediante .̃
fopen("~/datos.dat","r");
12. Utilizar un puntero sin haberle asignado memoria.
char *respuesta;
...
gets(respuesta);
18 de febrero de 2004
Transp. 25
¿ Dónde está el error ?
Programa 1:
#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
for (i=0;i<10;i=i+1);
printf("i vale %d\n",i);
}
Programa 2:
#include <stdio.h>
#include <stdlib.h>
main()
{
int i,numeros[10];
for (i=1;i<=10;i++)
numeros[i]=i;
for (i=1;i<=10;i++)
printf("numeros[%d]=%d\n", i, numeros[i]);
}
18 de febrero de 2004
Transp. 26
¿ Dónde está el error ?
Programa 3:
#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
for (i=0;i<10;i=i+1)
if (i=2)
printf("i vale 2\n");
else
printf("i no vale 2\n");
}
Programa 4:
#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
for (i=0;i<10;i=i+1)
switch (i) {
case 0: printf("i vale 0\n");
case 1: printf("i vale 1\n");
default: printf("i es mayor que 1\n");
}
}
18 de febrero de 2004
Transp. 27
Programación de estructuras de datos
dinámicas con C
Existen dos formas de declarar el nodo:
• Método 1:
struct nodo {
int info;
struct nodo *siguiente;
}
• Método 2:
typedef struct nodo Nodo;
typedef Nodo *PtrNodo;
struct nodo {
int
info;
PtrNodo siguiente;
};
Debe utilizarse la biblioteca stdlib (#include<stdlib>) para tener
acceso a:
void *malloc(int Numero_bytes)
void free(void *p)
18 de febrero de 2004
Transp. 28
Pila (LIFO)
#define PILA_VACIA -99999
PtrNodo top = NULL;
void Push(int n)
{ PtrNodo p;
p = (PtrNodo) malloc (sizeof(Nodo));
p->info = n;
p->siguiente = top;
top = p;
}
int Pop()
{ int aux_n;
PtrNodo aux_p;
if (top) {
aux_n = top->info;
aux_p = top;
top = top->siguiente;
free(aux_p);
return(aux_n);
}
return(PILA_VACIA);
}
18 de febrero de 2004
Transp. 29
Cola (FIFO)
#define COLA_VACIA -99999
PtrNodo primero, ultimo = NULL;
void Insertar(int n)
{
PtrNodo p;
p = (PtrNodo) malloc
p->info = n;
p->siguiente = NULL;
if (!primero)
ultimo = primero
else {
ultimo->siguiente
ultimo
}
(sizeof(Nodo));
= p;
= p;
= p;
}
int Extraer()
{ int
n;
PtrNodo p_aux;
if (!primero)
return(COLA_VACIA);
else {
n
= primero->info;
p_aux = primero->siguiente;
free(primero);
primero = p_aux;
if (!primero)
ultimo=NULL; /* La cola queda vacia */
return(n);
}
}
18 de febrero de 2004
Transp. 30
Lista simplemente encadenada
PtrNodo primero=NULL;
void Insertar(int n)
{
PtrNodo aux_p, anterior, nuevo;
nuevo = (PtrNodo) malloc (sizeof(Nodo));
nuevo->info = n;
if (!primero) {
/*Lista vacia*/
nuevo->siguiente=NULL;
primero = nuevo;
return;
} else {
anterior = NULL;
aux_p
= primero;
while (aux_p) {
if (aux_p->info < n) {
/*Busqueda*/
anterior
= aux_p;
aux_p
= aux_p->siguiente;
} else
if (!anterior) { /*Ins. principio*/
nuevo->siguiente = primero;
primero
= nuevo;
return;
} else {
anterior->siguiente = nuevo; /*Ins. medio*/
nuevo->siguiente = aux_p;
return;
}
}
anterior->siguiente = nuevo;
/* Ins. final */
nuevo->siguiente
= NULL;
return;
}
}
18 de febrero de 2004
Transp. 31
Lista simplemente encadenada
PtrNodo Buscar(int n,PtrNodo *anterior)
{ PtrNodo aux_p;
*anterior=NULL;
if (!primero) return(NULL);
aux_p = primero;
while (aux_p->info != n) {
*anterior = aux_p;
aux_p = aux_p->siguiente;
if (!aux_p) return(NULL);
}
return(aux_p);
}
int Borrar(int n)
{
PtrNodo aux_p,anterior;
aux_p = Buscar(n, &anterior);
if (!aux_p) return (0);
if (!anterior) {
/*Era el primero*/
primero = aux_p->siguiente;
free(aux_p);
} else {
/*No era el primero*/
anterior->siguiente = aux_p->siguiente;
free(aux_p);
}
return(1);
}
18 de febrero de 2004
Transp. 32
Lista doblemente encadenada
PtrNodo primero, ultimo = NULL;
Insertar(int n)
{ PtrNodo aux_p, anterior, nuevo;
nuevo = (PtrNodo) malloc (sizeof(Nodo));
nuevo->info = n;
if (!primero) {
/* Lista vacia /*
nuevo->izquierda = NULL;
nuevo->derecha = NULL;
primero
= nuevo;
ultimo
= nuevo;
return;
}
aux_p = primero;
while(aux_p)
if (aux_p->info < n)
aux_p = aux_p->next;
else
if (aux_p == primero) { /* Ins. al principio */
nuevo->izquierda = NULL;
nuevo->derecha
= primero;
primero->izquierda = nuevo;
primero
= nuevo;
return;
} else {
/* Ins. en medio */
nuevo->izquierda
= aux_p->izquierda;
nuevo->derecha
= aux_p;
aux_p->izquierda
= nuevo;
nuevo->izquierda->derecha=nuevo;
return;
}
ultimo->derecha = nuevo;
/* Ins. al final */
nuevo->izquierda = ultimo;
nuevo->derecha = NULL;
ultimo
= nuevo;
return;
}
18 de febrero de 2004
Transp. 33
Arbol binario
Recorrido in order iterativo
void r_in_order (PtrNodo p)
{
PtrNodo PILA[MAX_NODOS];
do {
while (p) {
Push(p);
p=p->left;
}
p=Pop;
visitar(p);
p=p->right;
} while (PILA<>{0});
}
Recorrido in order recursivo
void r_in_order (PtrNodo p)
{
if (p->left)
r_in_order(p->left);
printf("%d ",p->info);
if (p->right)
r_in_order(p->right);
}
/*Visitar(p)*/
18 de febrero de 2004
Transp. 34
Arbol binario
int Insertar(int n)
{ PtrNodo padre,nuevo,aux_p;
int dir;
nuevo = (PtrNodo) malloc (sizeof(Nodo));
nuevo->info
= n;
nuevo->izquierda = NULL;
nuevo->derecha = NULL;
if (!raiz) {
/*Arbol vacio*/
raiz = nuevo;
return(1);
}
aux_p = raiz;
do {
if (n == aux_p->info)
free(nuevo);
return(0);
/*clave duplicada*/
else {
padre=aux_p;
if (n < aux_p->info) {
aux_p = aux_p->izquierda;
dir=0;
} else {
aux_p = aux_p->derecha;
dir=1;
}
}
} while (aux_p);
if (dir == 0)
padre->izquierda=nuevo;
else
padre->derecha=nuevo;
return(1);
}
Descargar