PERTENECE
COLEGIO:
A
AUTORES:
Julio Roberto Duque Muñoz Licenciado Matemáticas Universidad Pedagógica Nacional Especialista Computación para la Docencia Universidad Antonio Nariño
Manuel Antonio Montero Gaona Licenciado Matemáticas Universidad Pedagógica Nacional Especialista Computación para la Docencia Universidad Antonio Nariño Magíster en Evaluación de la Educación Universidad Santo Tomás de Aquino
PORTADA: Javier Alejandro Duque Castro Diseñador Industrial Universidad Javeriana
2
1. INTRODUCCION LOGROS: Estudiaremos en esta unidad la forma de declarar los objetos que vamos a utilizar en este nuevo lenguaje. Diferenciar y comprender cada tipo de datos y su rango de variación. Definir los términos constantes, variables y sus formas de almacenamiento. Realizar un programa que nos muestre en pantalla los diferentes tipos de datos y las diferentes formas de presentación.
1.1 DECLARACIONES Las variables y las constantes son los objetos que manipulan un programa. Por lo tanto deben definirse antes de usarlos. Forma general: Identificador
Lista de Variables;
Los elementos de la lista están separados por comas
1.2 TIPOS DE DATOS C proporciona los siguientes tipos de datos:
TIPO CHAR
EXPLICACION Este tipo de dato es utilizado para representar un código ASCCII, su longitud es un byte, y siempre los char van encerrados en comillas simples.
RANGO 0 a 255 -128 a 128
INT
Es un número sin punto decimal. Su longitud es de 2 bytes. Es un número con punto decimal y tiene una longitud de 4 bytes. Es un tipo de dato real de doble precisión con una longitud de 8 bytes y una precisión de 15 dígitos. Se utiliza para declarar funciones que no retornan un valor, o para declarar un puntero a un tipo de datos no específico.
-32678 a 32768
FLOAT DOUBLE VOID
3
-3.40*1038 a 3.40* 1038 -1.79*10324 a 1.79*10 324
1.3 MODIFICADORES Los modificadores se pueden aplicar a los tipos de datos char, int, flota y double. Estos modificadores son:
UNSIGNED
Entero en el rango 0 a 65535
SHORT
Entero corto -32768 a 32767
LONG
Entero en formato largo en el rango ± 2147883648
1.4. CONSTANTES Una constante es un valor fijo que permanece sin ninguna alteración durante la ejecución del programa. Las constantes en C se definen mediante la instrucción del coprocesador #DEFINE. Su declaración general es:
#define
Identificador
Operando expresión
Ejemplos: #define car #define begin #define longitude
22 { 300
La palabra define va en minúscula
1.5. CADENAS Una cadena es un conjunto de caracteres que se encierran entre comillas dobles ( “ ). Ejemplo:
“Este lenguaje es muy fácil y nos permite crear lo que queremos” “Recuerde las palabras reservadas de C siempre se escriben en minúsculas”
Las constantes de caracteres son todos los caracteres imprimibles encerrados entre comillas simples.
4
1.6. CODIGOS DE BARRA INVERTIDAS
CODIGO \b
FUNCION Retroceso
CODIGO \f
FUNCION Alimentación de hoja
\n
Retorno de carro o línea en blanco Tabulador
\0
Nulo
\v
Tabulador vertical
\t
1.7. VARIABLES Es el nombre que le damos a un almacenamiento de memoria. Su formato general es:
Clase
Representa
la
Tipo
clase
Identificador
de
Es el nombre que le damos al
almacenamiento de memoria
Determina el tipo de
almacenamiento
que
dato de la variable.
para su identificación.
puede
ser
estática,
de
memoria
automática, registro o externa.
Ejemplos
static int x,y; auto float p,r; register int R; extern char e;
El nombre con el cual se identifica la variable es único; es decir float r es diferente a float R, ya que estas dos letras son diferentes una es mayúscula y la otra minúscula, y para C esta ya es una diferencia. Para la asignación de variables se usa el signo igual (=). R=5; asignamos a R el valor de 5. Las variables se pueden almacenar en una de las siguientes partes de un programa: Fuera de todas las funciones, incluyendo la función main(). A este tipo de variables se le conoce con el nombre de VARIABLES GLOBALES, y se puede usar en cualquier parte del programa. Dentro de una función o un bloque. A estas variables se le conoce con el nombre de VARIABLES LOCALES. y únicamente son conocidas en la función o bloque donde fueron definidas. (se construyen al entrar y se destruyen al salir de ahí), y es desconocida fuera de la función o del bloque. El último lugar es en la declaración de parámetros formales de una función. Se usan los parámetros formales para recibir los argumentos de una función cuando se llama. 5
1.8. CLASES DE ALMACENAMIENTO. Las variables se pueden almacenar en:
CLASE
EXPLICACION Las variables declaradas dentro del cuerpo general de la función principal son automáticas por defecto. Se puede colocarle la clase de almacenamiento sin ningún problema.
AUTO
EXTERN
Este especificador le dice al compilador que las variables ya han sido declaradas. Una variable declarada como extern se puede acceder antes de su declaración o en otro archivo.
STATIC INTERNAS STATIC EXTERNAS
Permite que una variable local retenga su valor entre llamadas de funciones. Se crea un almacenamiento permanente. Son definidas como variables globales pero únicamente son conocidas en el archivo en que se definen.
REGISTER
Se aplica únicamente a variables locales de tipo char e int. Hace que C mantenga el valor en un registro de la CPU en lugar de la memoria.
Como ya hemos definido los objetos que necesitamos en el lenguaje C y estamos familiarizados con ellos; es hora de declarar la forma general o el formato general de un programa en este lenguaje. La siguiente forma nos indica que en el lenguaje de programación en C es una secuencia de funciones, las cuales siempre contiene la función principal main(). Veamos su formato:
Declaraciones y Directivas
main ( lista de parámetros) { secuencia de sentencias ; } Tipo devuelto funcion1 (parámetros ) { secuencia de sentencias; } Tipo devuelto funcion2 (parámetros ) { secuencia de sentencias; 6
}
1.9 ENTRADA Y SALIDA DE DATOS Las siguientes funciones son utilizadas para el ingreso y salida de datos. Para poderlas utilizar debemos cargarlas a la memoria con la directiva #include , su formato es: < archivo .h> o “archivo.c”
#include
Los archivos que incluimos deben llevar la extensión h o c. y están ubicados en el subdirectorio Include. Los archivos que tienen la extensión c, son los archivos definidos por el usuario.
Ejemplos:
#include <stdio.h> #include “ventanas.c”
No olvide los signos <> o “”
Para las funciones de entrada y salida utilizaremos los archivos stdio.h y conio.h
FUNCION Getchar() Getch() Getche() Gets()
Scanf()
Puts()
Printf()
EXPLICACION Lee un carácter del teclado y se lo asigna a una variable: Ejemplo: a=getchar(); Espera a que se pulse una tecla e inmediatamente devuelve un valor. No imprime el carácter en pantalla. Igual que getch (). Pero esta función muestra el carácter en pantalla. Lee una cadena de caracteres desde el teclado y la sitúa en la dirección apuntada por el argumento. Por ejemplo char *gets(char *cad); Función que nos permite ingresar un dato en el computador: Scanf (“%d “,&var); Donde %d es una cadena de caracteres que indica el tipo de dato &var es la lista de variables. El & indica dirección de memoria. Nos permite escribir una cadena de caracteres en la pantalla. Nos permite imprimir resultados y mensajes en la pantalla: Printf(“su edad es : %+- -+ 0 12 d \n”, var); Donde: % especificador de tipo +justificación derecha + o izquierda -. -+ signo positivo o negativo 0 llenar los campos de cero 12 amplitud.
7
CLASE DE TIPOS
d
Formato entero
c
Carácter
x
Entero hexadecimal
f
Float
g
Notación e
e
Punto flotante
l
Long
L
double
n
Puntero a entero
u
Unsigned
i
entero
P
puntero
s
string
o
Entero octal
G
Notacion E
Cuando queremos escribir un mensaje que nos recuerde que hace cada sentencia o función en nuestro programa, el cual este mensaje no se imprime al ejecutar el programa lo escribimos entre /*
Mensaje
*/
Ejemplos: Los siguientes ejemplos nos permiten ver el uso de las funciones de entrada y salida y el uso de las variables locales y globales. 1. /* GET1.C INTRODUCCION E IMPRESION DE UN CARACTER ******/ #include<stdio.h> main() { char ch1,ch2,ch3; clrscr(); /* borra pantalla */ printf("introduce un carácter y lo escribe tecleando [intro] \n"); ch1=getchar();putchar(ch1); putchar('\n'); /* cambio de linea */ printf("introduce un carácter y produce eco sin utilizar [intro] \n"); ch2=getche();putchar(ch2); putchar('\n'); printf("espera el tecleo de un carácter y lo escribe sin usar[intro] \n"); ch3=getch();putchar(ch3); printf("\n comp s de espera .....(teclee!) \n"); getch();}
2. /*GLOBAL1 *******************************/ /* declaración de variables globales o externas int exter1; int exter2; main() { int i=7; /* variable local */ clrscr(); /* borrado de pantalla */ printf("la variable local en main() es i=%d\n",i); exter1=8*3; /* variable global */ exter2=10*2;/* inicializacion */ muestra(); /* llama a función /
*/
8
printf("fin del programa principal \n"); } /*---funciรณn muestra()--------*/ muestra() /* zona para definir los parรกmetros formales(si los hay)*/ {char sip; int i=27; extern exter1,exter2; /* declaraciรณn opcional de variable global*/ printf("la variable global es= %d y = %d\n",exter1,exter2); printf("la variable local i =%d es distinta en main()\n",i); scanf("%c",&sip); }
1.10 OPERADORES Nuestro objetivo de esta unidad es dar a conocer los diferentes operadores que se utilizan en lenguaje C y su importancia a nivel de programaciรณn. 1.10.1 ARITMETICOS Son todos los operadores que utilizamos en la representaciรณn simbรณlica de las operaciones aritmรฉticas, los cuales son: + * /
suma producto divisiรณn
A+B A*B A/B
% -++
La precedencia de estos operadores es la siguiente: MAYOR ++ -- Estos son evaluados de izquierda */% MENOR + en el mismo nivel de procedencia
modulo A%B decremento incremento
main() { int x=3,y=7; printf ("%d"y/x); /* mostrara 2 */ printf ("%d"y%x);/*mostrara 1 elresiduo */ printf (" % d",x*y); /* mostrara 21 */ }
1.10.2 INCREMENTO Y DECREMENTO Estos operadores no existen generalmente en otros lenguajes de programaciรณn, la operaciรณn x++ agrega 1 a su operando y la operaciรณn x-- quita 1 a su operando; es decir x=x+1 es lo mismo que x++ x=x-1 es lo mismo que x-su posiciรณn cambia el sentido de asignaciรณn. ejemplo.
A. y=7; z=y++; printf ("%d",z);/* en este caso se imprime el valor*/ printf ("%d",y); /* z=7,y=8 */
9
B. y=7; z=++y; printf ("%d",z);/* imprime z=8 */ printf("%d",y); /* imprime y=8*/
De aquí podemos concluir: Cuando el operador de incremento o decremento precede a su operando, C hace la operación antes de utilizar el valor del operando (ejemplo b) y cuando el operador sigue al operando C utiliza su valor y luego lo incrementa o decrementa (ejemplo a)
1.10.3 RELACIONALES Y LOGICOS Son los operadores que se refieren a la relación que existe entre unos valores y otros , y las formas en que estas relaciones se conectan. Estos operadores son: RELACIONALES
LOGICOS
> mayor que < menor que >= mayor o igual que <= menor o igual que != no igual
&& AND (y) || OR (o) ! NOT (no) == igual
El valor falso es igual a cero y verdadero a uno. Estos operadores tienen un nivel de precedencia menor que los aritméticos: 7-2 > -4+13
se evalúa (7-2)>(-4+13)
lo cual es falso y nos da como resultado 0. La precedencia de estos operadores es la siguiente: MAYOR ! >>=<<= && MENOR ||
1.10.4 OPERADOR INTERROGACION (?)
Este operador funciona como una decisión de la forma if-then- else, y tiene la forma general:
expresión1 ? expresión2: expresión3
Y actúa así: si expresión1 es verdadera evalúa expresión2 y toma ese valor para expresión1 en caso 10
contrario evalúa expresión3 y toma ese valor para espresión1. Ejemplo: z=15; h=z>5 ? 100 : 1000; Ejemplo: A>B ? printf("esto es menor"): printf ("no entendio") 1.10.5 OPERADOR SIZEOF Es un operador de tiempo de compilación que devuelve la longitud en bytes de la variable o del especificador de tipo que esta entre paréntesis al que precede. printf ("%d",sizeof z); /*muestra 4*/ printf ("%d",sizeof(int)); /*muestra 2*/ Uno de sus más importantes usos de este operador es para ayudar a generar código portable que dependa del tamaño de los datos en C.
1.10.6 OPERADOR COMA (,) Este operador encadena varias expresiones. Donde la parte izquierda se evalúa como tipo VOID. Es decir la parte derecha del operador coma se convierte en el valor total de la expresión separada por comas. main() { int z; z=10; w=(z=z*2,z/5);printf("%d",w);/*imprime el valor de 4*/ }
1.11 OPERADORES A NIVEL DE BITS Como el lenguaje C se diseño en un principio para sustituir el lenguaje de maquina (ensamblador) en muchas tareas de programación. Las operaciones a nivel de bits se refieren a la comprobación, asignación o desplazamiento de los bits reales que componen un byte o una palabra. Bytes o palabras que corresponden a los tipos estándar de datos en C, char e int. No se PUEDEN efectuar operaciones a nivel de bits con los tipos de datos float, void, double, y otros tipos de datos más complejos. Los operadores a nivel de bits son: OPERADORES & AND | OR ^ XOR ~ COMPLEMENTO A UNO >> DESPLAZAMIENTO DERECHA << DESPLAZAMIENTO IZQUIERDA 11
PRECEDENCIA MAYOR ~ & ^ | MENOR >> <<
1.11.1 OPERADOR AND (&) : Se utiliza para apagar bits.
main() { int a,b,c; a=17; /* 0000000000010001 */ b=117; /* 0000000001110101 */ c=a&b; /* 0000000000010001 */ printf("%d",c); } c=
1.11.2 OPERADOR OR (|):
Se utiliza para encender bits. main() { int a,b,c; a=17; /* 0000000000010001 */ b=117; /* 0000000001110101 */ c=a|b; /* 0000000001110101 */ printf("%d",c);} c=
1.11.3 OPERADOR XOR (^): Este operador enciende bits si al compararlos uno por uno estos son diferente.
main() { int a,b,c; a=17; /* 0000000000010001 */ b=117; /* 0000000001110101 */ c=a^b; /* 0000000001100100 */ printf("%d",c); } c=
1.11.4 OPERADOR COMPLEMENTO (~): Se utiliza para recuperar el complemento de un dato.
main() { int a,b; a=17; /* 0000000000010001 */ b=~a; /* 1111111111101110 =-18 */ printf("%d",b); } b=
1.11.5 OPERADOR DE DESPLAZAMIENTO- DERECHA (>>): Este operador desplaza n bits a la derecha del contenido de los bits de un dato. 12
variable >> # de posiciones en bits main() { int a,b; a=17;/*0000000000010001 */ b=a>>1; /* 0000000000001000 */ printf("%d",b); } b=
1.11.6 OPERADOR DE DESPLAZAMINETO- IZQUIERDA (<<): Este operador desplaza n bits a la izquierda del contenido de los bits de un dato. variable << # de posiciones en bits
main(){ int a,b; a=17; /* 0000000000010001 */ b=a<<1; /* 0000000000100010 */ printf("%d",b); } b=
Ejemplos: Veamos algunos ejemplos de macros que se utilizaran más adelante:
1. #define resto(x,y) (x%y)/* residuo de x entre y */ 2. #define cuadrado(x) x*x /* cuadrado del valor x */ 3. #define truncar(x) ((int(x)) /* transforma x a int */ 4. #define es_binario(x) ((x=='0'||x=='1')?1:0) 5. #define es_hexa(x) ((es_dígito(x)||(x>'A'&&x<='F'))?1:0) 6. #define es_octal(x) ((x >='0' && x<=7)? 1:0) 7. #define es_dígito(x) ((x>= '0' && x<= '9')?1:0
1.12 EJERCICIOS a) main() { int a,b; a=getchar(); b=(~a)& 135 printf("%d",b);}
main() { int a,b; a=getchar(); b=a--; a=(a|(~b))|~b ; printf("%d",a);}
13
b=
a=
c) defina las siguientes macros: es_mayúscula(x)
es_ascii(x)
a_minúscula(x)
es_decimal(x)
es_minúscula(x)
es_par(x)
a_mayúscula(x)
es_impar(x)
d) Programa que lee 6 números y los suma
Programa que lee nombre, edad, fecha de nacimiento y lugar.
EJEMPLOS 1.
Una tienda ofrece un descuento del 15% sobre el total de la compra y un cliente desea saber cuanto deberá pagar finalmente por su compra.
#include<stdio.h> main() { float compra, comprat; clrscr(); printf ("deme el valor de la compra \n"); scanf ("%f", &compra); 14
comprat=compra-(compra*0.15); printf ("el valor de la compra con el 15 por ciento de descuento es %f \n", comprat);getche (); } 2) Un alumno desea saber cual será su calificación final en la materia de Algoritmos. Dicha calificación se compone de los siguientes porcentajes: 55% del promedio de sus tres calificaciones parciales. 30% de la calificación del examen final. 15% de la calificación de un trabajo final. #include<stdio.h> main() { int cal1, cal2, cal3, pdecalific, exafinal, trabajo, materia; clrscr(); printf ("deme la primera calificacion \n");scanf ("%d", &cal1); printf ("deme la segunda calificacion \n");scanf ("%d", &cal2); printf ("deme la tercera calificacion \n");scanf ("%d", &cal3); pdecalific=(cal1+cal2+cal3)/3*0.55; printf ("el promedio de las calificaciones es %d \n", pdecalific); printf ("deme el examen \n");scanf ("%d", &exafinal); exafinal=exafinal*0.30; printf ("el valor del examen final es %d \n", exafinal); printf ("deme el valor del trabajo \n");scanf ("%d", &trabajo); trabajo=trabajo*0.15; printf ("el valor del trabajo final es %d \n", trabajo); materia=pdecalific+exafinal+trabajo; printf ("la nota en la materia de algoritmos es %d \n", materia); getche ();} 3) Un maestro desea saber qué porcentaje de hombres y qué porcentaje de mujeres hay en un grupo de estudiantes. #include<stdio.h> main() {float tpersonas, nhombres, nmujeres, pnhombres, pnmujeres;clrscr(); printf ("deme el numero de personas \n");scanf ("%f", &tpersonas); printf ("deme el numero de hombres \n");scanf ("%f", &nhombres); pnhombres=(nhombres*100)/tpersonas; printf ("el porciento de hombres es %f \n", pnhombres); printf ("deme el numero de mujeres \n");scanf ("%f", &nmujeres); pnmujeres=(nmujeres*100)/tpersonas; printf ("el porciento de mujeres es %f \n", pnmujeres); getche (); } 4) Realizar un programa que calcule la edad de una persona.
#include<stdio.h> main() { int nacimiento, edad; clrscr(); printf ("deme el año en que nació \n");
15
scanf ("%d", &nacimiento); edad=2008-nacimiento; printf ("usted tiene %d", edad);printf (" años");getche(); } TRABAJO
1. El dueño de una tienda compra un artículo a un precio determinado. Obtener el precio en que lo debe vender para obtener una ganancia del 30%.
2. Todos los lunes, miércoles y viernes, una persona corre la misma ruta y cronometra los tiempos obtenidos. Determinar el tiempo promedio que la persona tarda en recorrer la ruta en una semana cualquiera.
16
3. Tres personas deciden invertir su dinero para fundar una empresa. Cada una de ellas invierte una cantidad distinta. Obtener el porcentaje que cada quien invierte con respecto a la cantidad total invertida.
Actividades 1. Dado el radio R de una esfera, calcular e imprimir su área y su volumen. 2. Leer la base y la altura de un rectángulo, calcular el perímetro y la área. 3. Dada una cantidad en pesos, obtener la equivalencia en dólares, asumiendo que la cantidad cambiaría es un dato desconocido.
17
18
2. CICLOS LOGROS Conocer y aplicar las diferentes funciones de control y de ciclos. Aplicar los diferentes clases de ciclos en la elaboración de programas en C. Diferenciar los ciclos repetitivos de las funciones de control de flujo y de decisiones.
2.1 SENTENCIAS DE CONDICION Las sentencias de control en Turbo C son los bucles y las sentencias condicionales.
2.2 SENTENCIA IF: Se utiliza esta sentencia para controlar una condición si esta es verdadera o falsa. Su formato es: if (condición) sentencia1; else sentencia2;
if (condición) {bloque de sentencias1;} else {bloque de sentencias2;}
Se evalúa de la siguiente forma: Si condición es verdadera se realiza la sentencia1 o el bloque de sentencias1, si la condición es falsa se realiza la sentencia2 o el bloque de sentencias2 que están después del else. Ejemplo:
main() { int a,b,c;printf("déme un numero entero"); scanf("%d",&a);printf("déme otro numero entero"); scanf("%d",&b);if(a>b) { c=a+b; printf("la suma de los dos números es %d y el mayor es %d",c,a);} else { c=b-a; printf("la resta de los dos números es %d y el mayor es %d",c,b);}getch();}
2.3 IF ANIDADOS: La regla principal en Turbo C para if anidados es simple; tenemos que cada else esta asociado al if mas próximo que no tenga una sentencia else asociada. if(b) if(c) printf("bloque1"); else printf("bloque2"); getch();
19
2.4 ESCALA IF-ELSE-IF
if(condición) sentencia; else if(condición1) sentencia1; else if(condicion2) sentencia2; . : else sentencia3; sentencian;
Leer tres números diferentes e imprimir el número mayor de los tres. #include < stdio. h> #include < conio. h> main() { clrscr(); int num1 , num2, num3,mayor; printf( ”Ingrese un número”); scanf(“%d\n”, num1 ); printf( ”Ingrese un número”); scanf(“%d\n”, num1) ; printf( ”Ingrese un número”); scanf(“%d\n”, num1) ; if ((num1 > num2)&&(num1> num3)) { mayor=num1 ; } else{ if ((num2> num1 )&&(num2> num3)) { mayor=num2; } else{ mayor=num3; } } printf( ”El número mayor es %d\n ”,mayor) ; getch();}
Estas condiciones se evalúan de arriba hacia abajo. tan pronto se encuentre una condición verdadera se realiza la sentencia asociada con ella y las demás se pasan por alto. si todas las sentencias son falsas se realiza la sentencia3.
2.4.1 Ejercicios 1. Leer tres números calcular el menor y la media aritmética.
2. muestre el valor absoluto de un numero entero introducido por teclado.
3. Un empresario ofrece, por Navidad, un bono del 15% del sueldo a los trabajadores que ganen menos de $1000000. Elabore el programa para hallar el valor del bono.
4. Un empresario ofrece, por Navidad, un bono del 15% del sueldo a los trabajadores que ganen menos de $1000000 y 10% en caso contrario. Elabore el programa para hallar el valor del bono. 5. Un empresario ofrece, por Navidad, un bono del 15% del sueldo a los trabajadores que ganen menos de $1000000 , 10% si el sueldo es mayor o igual a 1000000 pero menos de 2500000 y 8% a los demás trabajadores. Elabore el programa para hallar el valor del bono.
20
2.5 SENTENCIA SWITCH: Es una sentencia de decisión múltiple. Una variable es sucesivamente comparada con una lista de enteros o caracteres, cuando se encuentra la correspondencia, se ejecuta la sentencia o bloque de sentencias. Su formato general es: * Se utiliza únicamente con tipo entero si existe un char este se convierte en entero.
switch(expresión) { case constante1: secuencia de instrucciones; break; case constante2:secuencia de sentencias, break; case constante3:secuencias de sentencias; break default :secuencia de sentencias: }
* No pueden existir mas de un case con la misma constante. * Únicamente la expresión evalúa igualdad. *Podemos anidar switch en la misma forma que anidamos IF.
2.6 SENTENCIA BREAK : Se utiliza para finalizar el flujo de la sentencia asociada. 2.7 SENTENCIA DEFAULT : Esta sentencia se ejecuta si no se ha encontrado ninguna correspondencia en un switch.
2.8 CICLOS REPETITIVOS: Lo mismo que en el lenguaje pascal C maneja 3 tipos de ciclos:el ciclo while,el ciclo do-while y el ciclo for.
2.9 CICLO WHILE :
El ciclo while evalúa la condición si esta es verdadera se realiza sentencia o bloque de sentencias, esta condición puede ser cualquier expresión siendo verdadera para cualquier valor diferente de cero. La forma general es: main() { /*ejemplo de suma */ int i=0,s=0; while(i<=100) { s+=i; printf("numero %d suma %d\n",i,s); i++; } getch(); }
while(condición) { sentencias; }
s=
2.10 CICLO FOR: Este ciclo se utiliza cuando el # de repeticiones de la sentencia esta definido. Su formato general es: for(inicio; condición; incremento) { sentencia; }
21
INICIO:Es una sentencia de asignación generalmente,se utiliza como variable de control. CONDICION: Esa una expresión relacional que determina cuando finaliza el ciclo. INCREMENTO: Define como cambia la variable de control cada vez que se repite el ciclo. Estas tres secciones deben estar separadas por un punto y coma. El ciclo for se ejecuta mientras la condición es verdadera, sino continua con la sentencia.
Utilizando el operador coma podemos utilizar dos o mas variables de control.
main(){ int i,t=0; for(i=0 ;i<100;i++) { t+=i; printf("El número es %d la suma es %d\n",i,t); } getch(); }
for(z=1,w=2;z+w<100;++z){ z=getchar(); z=z+"i";}
t=
Podemos utilizar un ciclo infinito escribiendo for (;;) o un ciclo sin cuerpo como en el caso de contadores: for(k=0;k<valor ;k++);
2.11 CICLO DO-WHILE. Este ciclo se diferencia de los demás porque el primero realiza el bloque de sentencias y después analiza su condición; si esta es verdadera se vuelve a ejecutar el ciclo y en caso contrario continua con el programa. Su forma general es:
do { sentencias;} while (condición)
Su uso más común es en el de funciones de menú. MENU () { char op; printf ("1 programa suma\n"); printf ("2 programa resta\n"); printf ("3 programa encender\n"); printf (" introduzca opción\n"); do{ op=getchar();/*tomala opción del teclado*/ switch (op){ case '1':suma(); break; case '2':resta(); break; case '3':encender(); break; case '4' :exit(0)} } while (op!='1'&& op!='2'&& op!='3'&& op!=4); } 22
2.12 SENTENCIA EXIT(): Esta función permite la terminación automática y nos envía al sistema operativo. Esta función se llama normalmente con un argumento 0.
2.13 SENTENCIA CONTINUE Actúa en forma similar a la sentencia break, con la diferencia de que en lugar de forzar su terminación, continué forza una nueva interacción del ciclo y salta cualquier código que exista entre medios.
2.14 SENTENCIA GOTO: Esta sentencia transfiere el control del programa a otra sentencia, en otra parte del programa. Su formato general es: goto etiqueta; etiqueta:
2.15 Ejercicios: Hallar todos los números pares que se encuentran entre dos números diferentes incluyéndolos a ellos.
Elaborar un programa con menú. Este programa debe realizar todas las operaciones de operadores con bits en las bases decimal, octal y hexadecimal con dos números y dos caracteres de entrada.
23
Realizar un programa que resuelva la ecuaci贸n : AX2+BX+C=0
Resolver un sistema de ecuaciones dos por dos
24
3. FUNCIONES LOGROS Capacitar al estudiante en el manejo de funciones Adquirir destreza en la construcción de programas con funciones. Por medio de ejercicios prácticos ver la aplicación del lenguaje Turbo C en la vida practica.
3.1 FUNCIONES La función es el bloque constructor de C, y la base de toda actividad del programa. Un programa realizado en Turbo C es una secuencia de funciones. Su forma general es: <static> Especificador_de_Tipo Nombre (Lista de Parámetros) Declaración de los parámetros; { Cuerpo de la función; }
Especificador del tipo: Especifica el tipo de valor que devuelve la sentencia return de la función. si no se especifica ningún tipo esta retorna un valor entero. -Stactic : Nos indica que la función tiene alcance de fichero y no de programa. Es decir estas funciones son invisibles para las funciones que están en otros archivos. -Lista de parámetros: Es una lista de nombres de variables separados por comas que reciben los valores de los argumentos. Cuando llamamos una función esta puede no tener argumentos. -Declaración de parámetros : Es opcional y nos especifica el tipo de datos de cada uno de los argumentos y del cuerpo de la función. Nombre : es un nombre que le damos a la función.
3.2 SENTENCIA RETURN: Esta sentencia tiene dos usos importantes. 1. Fuerza a una salida inmediata de la función en que se encuentra.
25
2. Ejemplos:
Se utiliza para devolver un valor.
CONVERT(ch) int ch; { if (ch>='0' && ch<= '9') return (ch- '0');
Crear una función que lea un carácter numérico y lo convierta al número entero que representa.
else return(-1); }
Ahora colocamos la función en el programa principal :
#include <stdio.h> main() { char b; printf("teclee un carácter \n"); b=getchar(); if (CONVERT(b)<0) printf("no es un numero \n"); else printf("si es un numero \n");getch();}
NOTA: -Siempre debemos definir una función fuera de la función principal (main).
las funciones
no se pueden anidar.
Del ejemplo anterior vemos dos tipos de parámetros: Uno que son los datos que el programador manda del programa principal a la función y que se denominan PARAMETROS ACTUALES. en nuestro caso el char b. Dos Los datos que recibe la función, y que se denominan PARAMETROS FORMALES. en el ejemplo el char ch. ejemplo: Programa para multiplicar dos numeros enteros. main() {int w,v,res; printf("déme el primer numero\n);scanf("%d",&w; printf ("déme el segundo numero\n"); scanf("%d",&v); res= pro(w,v);/* parametros actuales */ printf (" %d * %d = %d \n",w,v,res);getch();}
pro(int x, int y)/* x,y parametros formales */ { int z; z=x*y; return (z);}
w=
26
v=
res=
3.3 LLAMADAS POR VALOR Y POR REFERENCIA.
Se pueden pasar argumentos a las funciones de dos formas: Por valor : copia el valor de un argumento en el parámetro formal. Es decir que se evalúa cada argumento y su valor se utiliza de forma local en lugar del parámetro formal. Así si una variable pasa a una función, el valor almacenado de ese variable no cambiara en el medio que la llama. La llamada por referencia es la segunda forma de pasar argumentos a una función. Aquí la dirección de un argumento se copia en el parámetro; dentro de la función la dirección se usa para acceder al argumento que se uso en la llamada. Es decir que los cambios hechos a los parámetros afectan a la variable usada para llamar a la función. Ejemplos: main() { int k=0; printf("%d %d\n",sqr(k),k);/*llamada por valor */} sqrt(k)=
sqr(int x) { x=x*x;return(x);}
k=
3.4 LLAMADAS A FUNCIONES CON ARRAYS: Cuando se usa un array como un argumento a una función, solo se pasa la dirección del array, no una copia entera de este. Cuando se llama a una función con un nombre de array se pasa a la función un puntero al primer elemento del array.
Formas de declarar un parámetro que va a recibir un puntero a un array. 1. Se puede declarar como un array. main() { int k[10],i; for(i=0;i<10;++i) k[i]=i; muestra(k);}
muestra (num) int num[10]; { int i; for (i=0;i<10;i++) printf("%d",num[i]);}
Aunque el parámetro num se declara como un array de enteros el compilador de C automáticamente lo convierte en un puntero a entero.
27
Esto es necesario porque ningún parámetro puede recibir un array de enteros. De esta forma, solo se pasa un puntero a un array. Así debe haber en las funciones un parámetro de tipo puntero para recibirlo. 2. Especificar el array sin tamaño. muestra(num) int num[]; { int i; for(i=0;i<10;++i) printf("%d",num[i]);}
3. Declarar el array como puntero. Esto es permitido porque cualquier puntero se puede indexar usando [].
muestra(num) int *num; { int i; for(i=0;i<10;i++) printf("%d",num[i]);}
3.5 RECURSIVIDAD Las funciones en C pueden llamarse así mismas, es decir es recursiva ya que recursividad es el proceso de definir algo en términos de si mismo. fact(x) /* recursividad */ int x; { int re; if(x==1) return(1); re=fact(x-1)*x; return(re); }
fact(x) int x; { int re,i; re=1; for(i=1;i<=x;i++) re=re*i; return(re); }
Estas son dos formas de usar una función de forma recursiva o directa. Ejemplos: 1. Diseñemos un programa que calcule el máximo común divisor de dos números mediante el algoritmo de Euclides. Solución: Sean los dos números X,Y. El método para hallar el máximo común divisor (mcd) de dos números X,Y por el método de Euclides es: 1. Dividir el número mayor X entre el menor Y. Si el resto de la división es cero, el número Y es el mcd. 2. Si la división no es exacta, se divide el número menor Y por el resto de la división anterior. 3. Se siguen los pasos anteriores hasta obtener un resto 0. el ultimo divisor es el mcd buscado. mcd(a,b) int a,b; {while(a!=b){ (a>b) a=a-b else; } return(a); }
if
main() { int X,Y,m; scanf("%d",&X);scanf("%d",&Y); n=mcd(X,Y); printf(" el mcd de %d y %d es %d",X,Y,n);}
28
2. Diseñar un programa que cambie dos numeros utilizando parametros por referencia. Solución:Diseñamos la función de intercambio de valores, la cual llamaremos inter.
inter(int *x,int *y) {int tem; tem=*x; /*guarda la dirección de x */ *x=*y; /* pone y en x */ *y=tem;} /* pone x en y */
main(){int a,b; printf(""déme el primer numero ");scanf("%d",&a); printf("déme el segundo numero");scanf("%d",&b); inter(&a,&b); printf("%d %d ",a,b);}
Aquí hemos utilizado dos operadores nuevos para nosotros. Estos son el operador de indirección (*) que nos devuelve el valor almacenado en la variable y el operador de dirección (&) que nos devuelve la dirección de su operando. ACTIVIDADES
2. Para cada trabajador, de un grupo de n trabajadores, se conoce: cédula, nombre, horas semanales trabajadas, valor de la hora. Las horas que superen las 40 horas se pagarán como extras con un salario hora 1.5 veces el salario ordinario. Encontrar el pago semanal. 3. Escribir un programa que permita deducir si un número n es primo, apoyándose en una función Primo.
29
4. Diseñar un programa que maneje un menú con barrido del cursor y que maneje las teclas de las flechas. #include<stdio.h> #include<conio.h> #include<string.h> char ch,ch1,salir; int op; main() { op=1;salir=0; bloquemenu();} sumar() {int a,b,c; char esp;clrscr(); printf("déme los dos numeros"); gets(a);gets(b); c=a+b;printf("la suma es %d\n",c); esp=getch();op=1; }
multiplicar() { int a,b,m; char esp;clrscr(); printf("déme los dos numeros"); scanf("%d%d\n",&a,&b); m=a*b;printf("el producto es %d\n",m); esp=getch();op=3; } división() {int d,f,g; char esp;clrscr(); printf("déme los dos numeros"); scanf("%d%d\n",&d,&f); g=d/f;printf("la división es %d\n",g); esp=getch();op=4; }
restar() { int a,b,r; char esp;clrscr(); printf("déme los dos numeros"); scanf("%d%d\n",&a,&b); r=a-b;printf("la resta es %d\n",r); esp=getch();op=2; }
bloquemenu() { clrscr(); textcolor(BLUE); gotoxy(15,3);cprintf("MENU"); gotoxy(15,5);cprintf("suma"); gotoxy(15,6);cprintf("resta"); gotoxy(15,7);cprintf("multiplicar"); gotoxy(15,8);cprintf("dividir"); gotoxy(15,9);cprintf("salir");textcolor(RED); if(op==1){gotoxy(15,5);cprintf("sumar"); } if(op==2){gotoxy(15,6);cprintf("restar"); } if(op==3){gotoxy(15,7);cprintf("multiplicar");} if(op==4){gotoxy(15,8);cprintf("división");} if(op==5){gotoxy(15,9);cprintf("salir");} ch1=getch(); switch(ch1) { case 72:if (op==1){op==5;} else op--; break; case 80:if (op==5){op==1;} else op++;break; case 13:if(op==1){sumar();break;} if(op==2){restar();break; } if(op==3){multiplicar();break;} if(op==4){división();break;} if(op==5){salir=1;break;} case 27:salir=1; break;} if(salir !=1){bloquemenu();} else exit(); }
En este programa utilizamos las funciones de cprintf y de textcolor. 3.6 EJERCICIOS: 1. Realizar un programa que nos calcule xy.
30
2. diseñar un programa que lea : -nombre del empleado -código del empleado -número de horas trabajadas en la semana -valor de la hora
3. diseñar un programa que halle un número determinado de términos de la serie de fibonaci.
debe calcular: el valor neto del sueldo de cada empleado, sabiendo que si trabaja más de 45 horas el excedente son horas extras y tienen un reajuste del 25% sobre el valor de la hora. el programa se hará con el uso de funciones.
31
4. GRAFICAS LOGROS Aplicar los comandos de gráficas y de texto en la presentación de los trabajos. Realizar trabajos dinámicos con movimiento y música. Descubrir la importancia de los comandos gráficos y de texto en la realización de trabajos prácticos en el lenguaje Turbo C.
Para la realización de texto tenemos que invocar un archivo de cabecera conio.h y aplicar las funciones de salida de datos en modo texto. los cuales son: cputs, cprintf, putch. La función que nos permite inicializar el modo texto es textmode(modo), donde el argumento de modo puede ser: constante simbólica LAST BW40 C40 BW80 C80 MONO
constante numérica -1 0 1 2 3 4
modo texto texto previo blanco y negro 40 columnas color 40 columnas blanco y negro 80 columnas color 80 columnas monocromatico, 80 columnas
La funcion cprintf es igual que la función printf. textcolor(BLUE);cprintf("texto en color azul\n"); cputs devuelve una cadena en el color indicado; s="Turbo c"; textcolor(BLUE); cputs(s); putch es lo mismo que putchar si no la diferencia radica que la salida la da en el color indicado. textcolor(BLUE); putch('\5'); 4.1 FUNCIONES PARA ESTABLECER LOS ATRIBUTOS PARA TEXTO. textcolor(valor): establece el color del primer plano. textbackground(valor):establece el color del fondo del texto mostrado a través de las funciones de salida,donde el argumento es cualquiera de los de bajo intensidad. El argumento para estas funciones es alguno de los siguientes:
32
BAJA INTENSIDAD VALOR CONSTANTE 0 BLACK 1 BLUE 2 GREEN 3 CYAN 4 RED 5 MAGENTA 6 BROWN 7 LIGHTGRAY
ALTA INTENSIDAD VALOR CONSTANTE 8 DARKGRAY 9 LIGHTBLUE 10 LIGHTGREEN 11 LIGHTCYAN 12 LIGHTRED 13 LIGHTMAGENTA 14 YELLOW 15 WHITE 128 BLINK
textattr(atributo): Establece el atributo de texto. Donde el atributos es un valor del byte en el que: 0-2 bits especifican el color del primer plano. 3 especifica la intensidad 4-6 especifican el fondo 7 especifica el modo de parpadeo.
highvideo(): Establece el texto en alta intensidad colocando el bit 3 en on. lowvideo(): Establece el texto en baja intensidad colocando el bit 3 en off. normvideo(): establece el texto normal después de utilizar highvideo o lowvideo. cuando usted utiliza una pantalla monocromatica debe utilizar los siguientes atributos para las funciones de textcolor, textbackground, textattr, highvideo, lowvideo y normvideo, MODO VIDEO PRIMER PLANO Normal LIGHTGRAY(7) Subrayado BLUE(1) Negrilla WHITE(1) Inverso BLACK(0) Parpadeo +BLINK(128) Negrita y Subrayado LIGHTBLUE BLACK(1)
SEGUNDO PLANO BLACK(0) BLACK(1) BLACK(0) LIGHTGRAY(7) BLACK(0)
4.2 FUNCIONES PARA EL MANEJO DE PANTALLA Y VENTANA clrscr(): Función que nos permite limpiar la pantalla texto. clreol(): Función que borra desde la posición del cursor hasta el final de la línea. delline(): Borra la línea donde esta el cursor. inslinea(): Inserta una línea en blanco debajo de la posición del cursor. gotoxy(int x,int y): ubica el cursor en la columna x y en la fila y. la pantalla texto tiene 80 columnas y 40 filas. 33
wherex() y wherey(): Funciones que nos devuelven la posición del cursor según su coordenada en x o en y. movetext(izq,sup,der,inf,nueiz,nueinf): Mueve el texto desde un área de la pantalla a otra pantalla, y donde izq, sup, significa la esquina izquierda superior, der,inf, significa esquina derecha inferior del rectángulo donde encierra el texto a mover y nueiz, nueinf, indican la esquina inferior izquierda del nuevo rectángulo. window(izq,sup,der,inf):Define una ventana de texto en las coordenadas especificas. gettext(izq,sup,der,inf,memoria):Graba el texto de la pantalla en memoria. Se utiliza esta función para guardar una porción de texto que va ha ser cubierta por una ventana. puttext(izq,sup,der,inf,memoria):Recupera el texto que esta en la memoria sacandolo en la pantalla . Se utiliza esta función para recuperar una porción de texto que ha sido cubierta por una ventana. 4.3 GRAFICAS Para realizar una gráfica en Turbo c, se debe tener en cuenta el tipo de hardware que se posee. El lenguaje proporciona una serie de funciones que nos permite realizar cualquier tipo de gráfica y sus respectivos movimientos; con los cuales se desarrolla todo el diseño de software animado. Al realizar una gráfica debemos tener una secuencia de instrucciones las cuales son: 1. Incluir el archivo de cabecera: graphics.h. #include <graphics.h> 2. Definir dos variables enteras para mantener los drivers ( controlador) de gráficos, el modo gráfico. Por ejemplo: int gdriver,gmodo; 3. Invocar la función initgraph() para inicializar el sistema de gráficas y poner la pantalla en modo gráfico. initgraph(&gdriver,&gmodo,"");
4.4 CONTROLADORES Y MODOS GRAFICOS Cuando no queremos utilizar el modo gráfico superior de los posibles que tiene el hardware debemos utilizar cualquiera de los siguientes e insertar las siguientes líneas: int gdriver=MCGA,gmodo=MCGAMED;/* modo 4 */0 initgraph(&gdriver,&gmodo,""); Definimos los driver gráficos DETECT,CGA, MCGA, EGA, EGA64, EGAMONO, IBM8514,/* 1 - 6 */ HERCMONO, ATT400, VGA, PC3270/* 7 - 10 34 */
Modos grรกficos para cada driver: MCGA MCGAC0 = 0, /* 320x200 palette 0; 1 page*/ MCGAC1 = 1, /* 320x200 palette 1; 1 page*/ MCGAC2 = 2, /* 320x200 palette 2; 1 page*/ MCGAC3 = 3, /* 320x200 palette 3; 1 page*/ MCGAME = 4, /* 640x200 1 page*/ MCGAHI = 5, /* 640x480 1 page*/
CGA CGAC0 = 0, /* 320x200 palette 0; 1 page*/ CGAC1 = 1, /* 320x200 palette 1; 1 page*/ CGAC2 = 2, /* 320x200 palette 2: 1 page*/ CGAC3 = 3, /* 320x200 palette 3; 1 page*/ CGAHI = 4, /* 640x200 1 page*/
EGA EGALO = 0, /* 640x200 16 color 4 pages*/ EGAHI = 1, /* 640x350 16 color 2 pages*/ EGA64LO =0, /* 640x200 16 color 1 page*/ EGA64HI =1, /* 640x350 4 color 1 page*/ EGAMONOHI = 3,/* 640x350 64K on card, 1 page - 256K on card, 4 pages */ HERCMONO HERCMONOHI = 0, /* 720x348 2 pages*/
ATT400 ATT400C0 = 0,/* 320x200 palette 0; 1 page*/ ATT400C1 = 1,/* 320x200 palette 1; 1 page*/ ATT400C2 = 2,/* 320x200 palette 2; 1 page*/ ATT400C3 = 3,/* 320x200 palette 3; 1 page*/ ATT400MED = 4,/* 640x200 1 page*/ ATT400HI = 5,/* 640x400 1 page*/
VGA VGALO = 0, /* 640x200 16 color 4 pages*/ VGAMED = 1, /* 640x350 16 color 2 pages*/ VGAHI = 2, /* 640x480 16 color 1 page*/
PC3270 PC3270HI = 0, /* 720x350 1 page*/ IBM8514LO = 0, /* 640x480 256 colors*/ IBM8514HI = 1 /*1024x768 256 colors*/
DETECT Cuando usted use este modo grรกfico, initgraph() automรกticamente detecta el tipo de video que posee el hardware y selecciona el modo de video.
4.5 PANTALLA Y VENTANA DE GRAFICOS El Turbo C contiene funciones para el manejo de pantalla y ventanas grรกficas (viewport), los cuales son:
En el directorio de tc, debe tenr los archivos *.bgi y *.chr
setviewport(izq,sup,der,inf,banderacorte): Establece una nueva Ventana estilo window, pero en el modo grรกfico. La banderacorte nos permite controlar el grรกfico dentro de los limites de la ventana, esto es: si banderacorte esta en 0 (cero) banderacorte esta en off y los grรกficos que van mรกs allรก de los limites es totalmente ignorada y no se muestra ningรบn dibujo si por el contrario es uno la salida de grรกficos que van mas allรก de los limites de la ventana son truncados y se muestra la parte interior del dibujo. getviewsettings(puntero a estructura): limpia el viewport de grรกficos. clearviewport(): Limpia la ventana de dibujo dejando la pantalla en el color del fondo.
35
getimage(izq,sup,der,inf,matrix):Copia la imagen que esta dentro del rectángulo definido. Donde matriz es un puntero a array y matriz es definido como un array de tipo unsigned char. putimage(izq,sup,matriz,parámetro): Dibuja un modelado del mapa de bits en la pantalla de gráficos, donde matriz es la matriz definida en getimage y parámetro es cualquiera de los siguientes: COPY_PUT XOR_PUT OR_PUT AND_PUT NOT_PUT
0 1 2 3 4
copia directa o esclusiva (borra) o inclusiva (une) y -cubrecopia inversa
setcolpalette(paleta): fija el color de la paleta. setcolors(fondo,paleta):Establece el fondo y el color de las paletas. setcolor(número): Establece el color de los gráficos en el color correspondiente a número. setbkcolor(número): Establece el color del fondo de la pantalla de gráficos. Color para las Paletas 0: LightGreen, LightRed, Yellow 1: LightCyan, LightMagenta, White 2: Green, Red, Brown 3: Cyan, Magenta, LightGray Colores para setpalette y setallpalette BLACK0/* dark colors */ BLUE 1 /* dark colors */ GREEN 2 CYAN 3 BROWN 6 LIGHTGRAY 7 LIGHTBLUE 9 LIGHTGREEN 10 LIGHTRED 12 YELLOW 14
RED 4 MAGENTA 5 DARKGRAY 8/* light colors */ LIGHTCYAN 11 WHITE 15
putpixel(x,y,color):Establece un pixel de gráficos en las coordenadas especificadas y en el color especificado. getpixel(x,y): Devuelve el color en la posición especificada. arc(x,y,angulo_ini,angulo_fin,radio): Dibuja un arco de circulo con centro en x,y, y radio especificado. Los angulos se expresan en grados sexagesimales en el sentido contrario de las manecillas del reloj. circle(x,y,radio): dibuja un circulo con centro en x,y, con el radio fijado ellipse(x,y,angulo_ini,angulo_fin,x_radio,y_radio):Dibuja un arco eliptico con centro en x,y. line(x0,y0,x1,y1): Dibuja una línea entre dos puntos: lineto(x,y):Dibuja un punto desde la última posición hasta el punto x,y.
36
Estilos de líneas para las funciones get/setlinestyle SOLID_LINE = 0, DOTTED_LINE = 1, CENTER_LINE = 2, DASHED_LINE = 3, USERBIT_LINE = 4,*/Usar estilo de línea definida*/
Ancho de líneas para las funciones get/setlinestyle NORM_WIDTH = 1, THICK_WIDTH = 3, .
rectangle(x0,y0,x1,y1): Dibuja un rectángulo con esquinas en los puntos (x0,y0),(x1,y1). drawpoly(num_lados,matriz): Dibuja un poligono de num lados , donde las coordenadas se definen en matriz. floodfill(x,y,color): Rellena una zona de la pantalla de gráficos. setfillstyle(modelo,color): Establece el estilo de relleno. setfillpattern(pattern,color): Establece el relleno definido por el usuario. Formas de llenado para las funciones get/setfillstyle */ EMPTY_FILL LTSLASH_FILL, /* /// */ LTBKSLASH_FILL, /* \\\ */ INTERLEAVE_FILL,
SOLID_FILL, SLASH_FILL /* /// */ HATCH_FILL, WIDE_DOT_FILL,
LINE_FILL, /*--- */ BKSLASH_FILL, /* \\\ */ XHATCH_FILL, CLOSE_DOT_FILL,USER_FILL,
settextstyle(fuente,dirección,tamaño): Especifica la fuente de texto (tipo de letra ) en la dirección y tamaño deseado. outtext(cadena): Muestra una cadena en pantalla de gráficos. outtextxy(x,y,cadena):Muestra una cadena en pantalla gráfico en las coordenadas especificadas por x,y Fuentes y direcciones de Textos en gráficos dirección DEFAULT_FONT= 0,/* 8x8 bit mapas de bits */ TRIPLEX_FONT= 1,/* "tipo triple */ HORIZ_DIR 0/* izquierda a derecha--horizontal*/ SMALL_FONT= 2, VERT_DIR 1/* de abajo a arriba--vertical */ SANS_SERIF_FONT= 3, GOTHIC_FONT= 4 closegraph(): cierra el sistema de gráficas. getgraphmode(): Obtiene el modo gráfico actual. cleardevice(): Limpia la pantalla de gráficos. restorecrtmode() Retorna al modo texto original.
Ejemplos: Construyamos los siguientes dibujos
37
4.6 Ejercicios 2. Realizar un proyecto en graficas de la reproducci贸n humana. 3. Hacer un programa que nos ayude a conocer cada capital y pa铆s del mundo, y donde este ubique el pais correspondiente en el mapamundi.
38
MAPA DE COLOMBIA
#include<graphics.h> #include <conio.h>
line (150,186,157,189);line(157,189,170,191); line(170,191,178,196);line (178,196,180,198); line(180,198,182,196);line (182,196,195,207); main() line (195,207,198,206);line(198,206,205,207); {int i;install();portada(); line(205,207,205,206);line (205,206,210,208); mapa();getch(); line (210,208,218,207);line (218,207,232,215); restorecrtmode();} line (232,215,218,230);line(218,230,228,231); line (228,231,230,238);line (230,238,237,232); mapa(){cleardevice (); line (237,232,241,212);line (241,212,245,210); rectangle line (245,210,243,208);line (243,208,238,200); (1,1,700,345);rectangle(2,2,699,344); line(238,200,240,188);line (240,188,244,186); line(211,30,202,38);line(202,38,190,4 line(244,186,242,184);line(242,184,247,181); 5); line(211,30,217,33);line (217,33,219,38); line (190,45,180,46);line line (219,38,212,42);line (212,42,206,45); (180,46,177,54); line (206,45,198,57); line (198,57,200,72); line (177,54,174,49);line line (200,72,203,75);line (203,75,206,78); (174,49,170,49); line (206,78,204,80);line (204,80,202,83); line (170,49,172,60);line line(135,93,132,98);line(132,98,140,1 line (202,83,208,87);line(208,87,212,100); line (212,100,235,100);line(235,100,245,114); 07); line(140,107,142,118);line(142,118,1 line (245,114,275,114);line (275,114,270,129); line (270,129,276,140);line (276,140,276,143); 38,117); line(138,117,140,132);line(140,132,1 line (276,143,278,145);line(278,145,277,149); line (277,149,270,155);line (270,155,280,160); 38,137); line(138,137,144,142);line(144,142,1 line (280,160,281,164);line (281,164,284,172); line(284,172,284,175);line (284,175,280,177); 35,154); line (280,177,277,173);line (277,173,280,177); line (135,154,128,157);line(128,157,124, line (280,177,275,165);line (275,165,268,170); line (268,170,264,165);line(264,165,264,167); 163); line(124,163,125,166);line(125,166,1 line (264,167,245,166);line (245,166,243,169); (172,60,162,70); 19,170); line (162,70,156,70);line (156,70,146,82); line(119,170,145,187);line(145,187,1 line (146,82,147,86);line (147,86,140,80); 50,186); line(140,80,137,85);line (137,85,142,88); line (142,88,137,95); line(137,95,135,93);
line (243,169,244,171);line (244,171,250,173); line (250,173,250,178);line (250,178,247,181); line (147,80,160,90);line (160,90,167,100); line (167,100,183,101);line(183,101,191,91); line (191,91,196,86); line(196,86,202,83); line(160,90,154,100);line (154,100,160,108); line(160,108,161,125);line(161,125,156,135); line (156,135,158,145); line(158,145,143,167); line(143,167,137,182);line (220,101,215,120); line(215,120,210,122); line(210,122,200,140); line (200,140,195,143);line (195,143,175,168); line(175,168,174,178);line (174,178,169,192); line(185,157,197,155);line (197,155,215,159); line (215,159,235,155);line(235,155,253,159); line (253,159,276,149);getch(); restorecrtmode();} install() {int gm,gd; gd=DETECT; gm=2; initgraph(&gd,&gm,'');} portada() { setgraphmode(0); setbkcolor(15); setcolor(1); rectangle(0,0,319,199); settextstyle(4,0,1); outtextxy(10,20,"ELABORADO POR : "); settextstyle(3,0,1); outtextxy(15,50,"MANUEL MONTERO"); outtextxy(100,170," 1 9 9 2 "); setgraphmode(0);}
5. MATRICES LOGROS o
Dar a conocer la importanciasw de trabajo con las direcciones de memoria y las formas de accesarlas.
o
Capacitar al estudiante en el manejo de matrices y de cadenas con uso de apuntadores.
o
Realizar programas de aplicación en las diferentes ramas del conocimiento.
5.1 MATRICES
Un array es una colección de datos y variables del mismo tipo que se referencia por un nombre común. En el medio matematico un array unidimencional es un vector de a i hasta an y se referencia por un indice i=0...n y si el array es bidimensional es una matriz de dimensión dos, y todas las operaciones que podemos realizar en el ambito matemático la podemos realizar en el ámbito del Turbo C. Un array en C consta de posiciones de memoria contiguas las cuales siempre se inicializan en la posición cero hasta la posición n-1. Gráficamente tenemos: array M [10] 0
1 2
3 4
5 6
7 8
9
Su forma general es: Especificador_de_Tipo Nombre_variable [tamaño] -Especificador de tipo: Declara el tipo base del array que es el tipo de datos de cada elemento del array. -Nombre_variable: Es el nombre que identifica el array dentro del programa. -Tamaño : Nos indica cuantos elementos tendrá el arreglo y los indice siempre comienzan en cero hasta n-1. El tamaño del array en bytes lo podemos calcular como: sizeof(tipo)*longitud del array= total de Bytes. Ejemplo 1: main(){ int x,y[10]; /* reserva 10 elementos enteros */ for(x=0;x<=9;x++) { y[x]=x; printf(" los elementos del array son %d ",y[x]);} getch();}
40
Ejemplo 2. main(){ int i,k[5],n[5],j[5]; /******** DATOS DE LA MATRIZ K *******/ printf ("déme los elementos de la matriz k"); for(i=0;i<=4;i++) { printf("déme el elemento %d\n",i); scanf("%d",&k[i]);}getch(); printf (" los elementos de la matriz k son :\n"); for(i=0;i<=4;i++) {printf(" %d\n",k[i]);}getch(); /* **DATOS DEL MATRIZ UNIDIMENSIONAL N****/ printf ("déme los elementos de la matriz n"); for(i=0;i<=4;i++) { printf("déme el elemento %d\n",i); scanf("%d",&n[i]); }getch();
printf ("los elementos de la matriz n son :\n"); for(i=0;i<=4;i++) { printf(" %d\n",n[i]);}getch(); /* ******SUMA DE LAS MATRICES ********/ for(i=0;i<=4;i++) j[i]=k[i]+n[i]; printf("\n"); printf (" los elementos de la matriz k+n es:\n"); for(i=0;i<=4;i++) printf("%d\n",j[i]);getch(); }
5.2 ARREGLOS MULTIDIMENSIONALES El lenguaje Turbo C permite definir arreglos de mas de una dimensión y de cualquier tipo de datos incluyendo arreglo de arreglos, para definir los arreglos multidimensionales únicamente necesitamos colocar un par de paréntesis más, ya que en Turbo C al colocar un par de paréntesis definimos una nueva dimensión del array si colocamos dos pares es un array bidimensional y así sucesivamente hasta colocar n pares de paréntesis. Su forma general es:
Tipo Nombre [tamaño 1][tamaño 2]...[tamaño n] El número de bytes que ocupa en memoria un arreglo dimensional se determina por la formula: sizeof(tipo)*filas*columnas=número de Bytes. Como todos los arreglos se almacenan en forma contigua (uno después de otro) con frecuencia es útil imaginarnos el arreglo de la siguiente manera: int h[2][3];
Fila 0 Fila 1
Col 0 h[0][0] h[1][0]
Col 1 h[0][1] h[1][1]
Col 2 h[0][2] h[1][2]
Para acceder a un elemento de una matriz debemos indicar la fila y la columna donde esta ubicado el elemento. Por ejemplo: h[i][j]
41
Ejemplo 3 main() /* ***** suma de matrices ****/ {int m[5][6],n[5][6],l[5][6]; int i,j;
/****** IMPRESION DE DATOS ******* */ printf(" matriz m\n"); for (i=0;i<=4;i++) for(j=0;j<=5;j++) printf("%d\n",m[i][j]);printf(" matriz n\n"); for (i=0;i<=4;i++) for(j=0;j<=5;j++) printf("%d\n",n[i][j]); /****** SUMA DE LOS DATOS ******* */ for (i=0;i<=4;i++) for(j=0;j<=5;j++) l[i][j]=m[i][j[]+n[i]j[]; /****** IMPRESION DE LA SUMA ******* */ printf(" matriz l\n"); for (i=0;i<=4;i++) for(j=0;j<=5;j++) printf("%d\n",l[i][j]);}
/* ***** ingreso de datos de la matriz m ****/ for (i=0;i<=4;i++) for(j=0;j<=5;j++) { printf("ingrese el termino %d %d de la matriz m\n",i,j); scanf("%d\n",&m[i][j]);} } /* ***** ingreso de datos de la matriz n ****/ for (i=0;i<=4;i++) for(j=0;j<=5;j++) { printf("ingrese el termino %d %d de la matriz n\n",i,j);scanf("%d\n",&n[i][j]);} }
5.3 ASIGNACIONES DE VALORES: Los arreglos pueden tener clase de almacenamiento automatico, externo o estático, pero no de registro. Los arreglos externos y estáticos pueden obtener valores iniciales con un indicador de arreglos: Especificador_Tipo Nombre[tamaño]...[tamaño]={Lista de valores} La lista de elementos es una lista de constantes compatibles con el tipo de datos del array y están separadas por comas. La primera constante se asigna con la primera posición del array y así sucesivamente. Cuando una lista de elementos es menor que el numero de elementos del array que se iniciará, los elementos restantes se inician con el valor de cero. La lista de elementos al cerrar el corchete se le coloca el punto y coma (;). Ejemplo: static float h[3]={1.2,2.3,4.5}; Si un arreglo externo o estático se declara sin tamaño y recibe una serie de valores iniciales, obtiene de manera implícita el tamaño del número de elementos, por tanto: int a[]={1,2,3,4}; y int a[4]={1,2,3,4} Son declaraciones externas equivalentes. 5.4 CADENAS Las cadenas son arreglos unidimensionales de tipo char. por convención, una cadena en Turbo C, termina con el carácter nulo, \0 (\cero). Las constantes de cadena se escriben entre comillas dobles, por ejemplo "malo" es una cadena de caracteres con cinco elementos con el ultimo elemento el carácter nulo. Los cuales podemos representar de la siguiente forma: 42
array M [5]="malo"
m
a
l
o
\0
Por tanto una constante de cadena como "u" no es igual a la constante 'u'. El arreglo "u" tiene dos elementos el carácter 'u' y el carácter nulo, \0. array M [1]="u"
u
\0
Ejemplos: 1. Construir una función que nos cuente el número de elementos de una cadena. longitud(s) register char *s; {register int n; for(n=0;*s!='\0';++s);return(n);} La biblioteca estándar contiene funciones para el manejo de cadenas como la anterior las cuales no necesitan definirse sino únicamente llamarse. Para usar estas funciones necesitamos incluir el archivo de cabecera string.h. #include <string.h> 5.5 FUNCIONES QUE DEVUELVEN UN ENTERO: Debemos definir dos variables de tipo char: s1 y s2, los cuales son apuntadores a char. strcmp(s1,s2):compara n caracteres de s1 con s2. Se devuelve: 0 si s1=s2 un entero negativo si s1<s2 un entero positivo si s1>s2. strncmp(s1,s2,n): Compara un máximo de n caracteres. strlen(s1): Devuelve la longitud de la cadena en s1, sin contar el carácter nulo. 5.6 FUNCIONES QUE DEVUELVEN UN APUNTADOR A CHAR.
strcat(s1,s2): Se anexa la cadena s2 al final de la cadena s1, sobreescribiendo en lo que hubiese en los espacios de memoria, el carácter nulo de s1 se remplaza por el primer carácter de s2. strncat(s1,s2,n): Concatena n caracteres de s2 con s1. si n es mayor que la longitud de s2, el proceso se termina con el carácter nulo. strcpy(s1,s2):s2 se copia en s1 hasta que se llegue al carácter nulo, se sobrescribe todo lo que existe en s1, se supone que s1 tiene espacio suficiente para contener a s2. strncpy(s1,s2,n): Se copia s2 en s1, con la diferencia que únicamente se mueven n caracteres de 43
s2, se trunca o se llenan con caracteres nulos dependiendo de la longitud de la cadena s2. strrchr(s1,n): Devuelve un puntero a la ultima ocurrencia del byte menos significativo de n en la cadena apuntada por s1. Si no lo encuentra devuelve un puntero nulo. strchr(s1,n): devuelve un puntero a la primera ocurrencia del byte menos significativo de n en la cadena apuntada por s1, si no lo encuentra devuelve un puntero nulo.
5.7 FUNCIONES DE MANEJO DE CARACTERES
Para el uso de funciones de trabajo con caracteres debemos incluir el archivo de cabecera ctype.h el cual nos permite manejar las siguientes funciones que pueden tomar como parámetro una variable de tipo char evaluandose en la misma forma que un entero. isalnum(int c):Indica si un caràcter es alfanumèrico. Devuelve un valor diferente de cero si el parámetro es alfanumérico en caso contrario, un cero. isalpha(int c):Indica si un caràcter es una letra del alfabeto. Devuelve un valor diferente de cero si el parámetro es alfabético en caso contrario, un cero. iscntrl(int c):Indica si un carácter es de control o de borrado, (0 a 31 en decimal y 127). Devuelve un valor diferente de cero si el parámetro es un carácter de control en caso contrario, un cero. isdigit(int c):Indica si un carácter es un dígito (0-9). Devuelve un valor diferente de cero si el parámetro es un dígito en caso contrario, un cero. isgraph(int c):Indica si un carácter es imprimible, con excepción del carácter de espacio. Devuelve un valor diferente de cero si el parámetro es imprimible en caso contrario, un cero. islower(int c):Indica si un carácter es una letra minúscula. Devuelve un valor diferente de cero si el parámetro es una letra minúscula en caso contrario, un cero. isprint(int c):Indica si un carácter es imprimible (0-126). Devuelve un valor diferente de cero si el parámetro es imprimible en caso contrario, un cero. ispunct(int c):Indica si un carácter es de puntuación, esto significa que no sea un carácter de control ni alfanumérico imprimible, (32-47, 58-63,91-96,123-126).Devuelve un valor diferente de cero si el parámetro es puntuación en caso contrario, un cero. isspace(int c):Indica si un carácter es un "espacio en blanco". Devuelve un valor diferente de cero si el parámetro es un espacio en blanco (espacio, retorno de carro,línea nueva o de salto de forma), en caso contrario, un cero. isupper(int c):Indica si un carácter es una letra mayúscula. Devuelve un valor diferente de cero si el parámetro es una letra mayúscula; en caso contrario, un cero. isxdigit(int c):Indica si un carácter es un dígito hexadecimal. Devuelve un valor diferente de cero si el parámetro es un número hexadecimal en caso contrario, un cero. tolower(int c):Convierte un carácter en su equivalente en minúscula. Devuelve el carácter en
44
minúscula o el carácter sin modificar cuando este es numerico. toupper(int c):Convierte un carácter en su equivalente en mayúscula. Devuelve el carácter en mayúscula o el carácter sin modificar cuando este es numérico.
Ejemplo Realizamos el siguiente ejemplo con el cual hacemos uso de las funciones de texto y de matrices. El programa consiste en pedir el nombre y las notas de n estudiantes.
#include "stdio.h" #include "conio.h" char nombre[5][35]; float notas [13][3][5]; double defin [13][5]; main() { menú();} menú(){char x; int pos; textmode (C80); textbackground (0); window (0,0,80,25); clrscr(); cuadro (1,1,80,5,4); cuadro (1,6,80,24,2); textbackground (15); window (2,2,79,4); clrscr(); textcolor(1);gotoxy(4,2);cprintf("* ACCESAR *"); gotoxy(25,2);cprintf("*MODIFICAR*");gotoxy(46,2); cprintf("*CONSULTAR*");gotoxy(67,2); cprintf("* SALIDA *"); pos=4; gotoxy (pos,2); textcolor (4); putch ('*');gotoxy (pos+10,2); putch ('*'); do { x=getch(); gotoxy (pos,2); textcolor (1); putch ('*'); gotoxy (pos+10,2); putch ('*'); switch (x) { case 75: {pos=pos-21;break;} case 77: {pos=pos+21;break;} } if (pos==-17) {pos=67;} if (pos==88) {pos=4;} textcolor (4); gotoxy (pos,2); putch ('*'); gotoxy (pos+10,2); putch ('*'); }while (x!=13); switch (pos) { case 4:{leer();break;} case 25:{modif();break;} case 46:{menu1();break;} case 67:{window (1,1,80,25); textbackground (0);clrscr();exit (1);} } menú();} cuadro (int x,int y,int x1,int y1,int col){ int i; textcolor (col); i=x+1; gotoxy (i,y); while (i<x1){ putch ('M'); i++;} gotoxy (x,y); putch ('I'); gotoxy (x1,y);putch (';'); i=x+1; gotoxy (i,y1); while (i<x1){ putch ('M'); i++;} gotoxy(x,y1);putch('H'); gotoxy(x1,y1); putch('<');i=y+1; while (i<y1) {gotoxy(x,i);putch(':');gotoxy(x1,i); putch(':'); i++;}} leer(){ char tec; int j,n,x; char nom[35]; 45
float not1,not2,not3,not4; double def; j=0; while (((strcmp (nombre[j],"\0"))!=0)&&(j<5)) j++; if (j<5) { do {formato(); gotoxy(13,2); textcolor(1); gets(nombre[j]); x=5; for (n=0;n<12;n++) { do{ gotoxy (26,x);printf (" "); gotoxy (26,x); scanf ("%f",&not1); }while ((not1<1.0)||(not1>10.0)); do{ gotoxy (36,x);printf (" "); gotoxy (36,x);scanf("%f",&not2);}while ((not2<1.0)||(not2>10.0)); do{ gotoxy (46,x);printf(" "); gotoxy(46,x);scanf("%f",&not3);}while ((not3<1.0)||(not3>10.0)); notas[n][1][j]=not1;notas[n][2][j]=not2;notas[n][3][j]=not3; def=not1+not2+not3;def=def/3;defin[n][j]=def; gotoxy (56,x); cprintf ("%4.1f",def);x++; } window (1,1,7,24);cuadro (55,17,78,23,5); textbackground (0);window(56,18,77,22); clrscr(); window(1,1,79,24);textcolor (12); gotoxy (57,19);if (j+1<5) {cprintf ("Desea otro alumno?");gotoxy (57,20);cprintf ("(S/N)"); do{ gotoxy (57,21);putchar (' ');gotoxy (57,21); tec=toupper(getch());}while ((tec!='S')&&(tec!='N'));} gets (nom);j++; }while ((tec=='S')&&(j<5));} textbackground (0); window (56,18,77,22); clrscr();window(1,1,79,24);gotoxy(59,20); cprintf("Presione [ENTER]"); gotoxy (59,21); cprintf ("para continuar"); gets (nom);} modif(){ char nom[35]; int j,k,n,x,val; float not1,not2,not3; double def; window(1,1,79,24);textcolor(4);textbackground(0); gotoxy (10,15); cprintf ("TECLEE EL NOMBRE DEL ALUMNO A MODIFICAR \n"); gotoxy (10,17);gets (nom);val=0; for (j=0;j<5;j++) if (strcmp (nombre[j],nom)==0) {k=j;j=5;val=1;} if (val==0) error(); else { formato(); gotoxy (13,2); textcolor (4); cprintf ("%s",nombre[k]); x=5; for (n=0;n<12;n++) { gotoxy (26,x);cprintf ("%4.1f",notas[n][1][k]); gotoxy (36,x);cprintf ("%4.1f",notas[n][2][k]); gotoxy (46,x);cprintf ("%4.1f",notas[n][3][k]); gotoxy (56,x);cprintf ("%4.1f",defin[n][k]); x++; } j=k;gotoxy (13,2); printf (" "); gotoxy(13,2);textcolor (1);gets (nombre[j]);x=5; for (n=0;n<12;n++) { do{ gotoxy (26,x); printf (" "); gotoxy (26,x); scanf ("%f",&not1); }while ((not1<1.0)||(not1>10.0)); do{gotoxy (36,x);printf (" ");gotoxy (36,x);scanf ("%f",&not2); } while ((not2<1.0)||(not2>10.0)); do{gotoxy (46,x);printf (" ");gotoxy (46,x);scanf ("%f",&not3); } while((not3<1.0)||(not3>10.0)); notas[n][1][j]=not1;notas[n][2][j]=not2; notas[n][3][j]=not3;def=not1+not2+not3; def=def/3;defin[n][j]=def;textcolor (2);gotoxy (56,x);cprintf ("%4.1f",def);x++;} window (1,1,79,24);window (0,0,80,25);textcolor(2); gotoxy (25,17); cprintf ("Presione una tecla para continuar"); getch(); gets (nom); }} menu1() { char z; int y,n,x; window (1,1,79,24); textbackground (5);window (46,4,58,7);clrscr();cuadro(1,1,12,4,1);gotoxy(3,2); cprintf("TODOS ");gotoxy(3,3);cprintf("INDIVID.");y=2; textcolor(2);gotoxy(2,2); 46
putch('*');gotoxy(11,2);putch ('*'); do{ z=getch(); textcolor(5);gotoxy(2,y);putch('*'); gotoxy (11,y); putch ('*');textcolor (2); switch (z){ case 72: {y=y+1;break;} case 80: {y=y-1;break;} case 27: {men煤();} } if(y==4)y=2;if(y==1)y=3; gotoxy(2,y);putch('*'); gotoxy(11,y); putch ('*');} while (z!=13); switch (y){ case 2: {tod();break;} case 3: {uno();break;}}} tod() { int i=0,x,n; window (1,1,79,24); while (((strcmp (nombre[i],"\0"))!=0)&&(i<5)) {formato();gotoxy (13,2);textcolor (4); cprintf ("%s",nombre[i]);x=5; for (n=0;n<12;n++) {gotoxy (26,x);cprintf ("%4.1f",notas[n][1][i]); gotoxy (36,x);cprintf ("%4.1f",notas[n][2][i]);gotoxy (46,x);cprintf ("%4.1f",notas[n][3][i]); gotoxy (56,x);cprintf ("%4.1f",defin[n][i]);x++; } textcolor (2);gotoxy (25,17); cprintf ("Presione una tecla para continuar");getch();i++;}} uno() { char nom[35]; int i,j,k,x,n,val; window(1,1,79,24);textcolor(4);textbackground(0);gotoxy(10,15); cprintf("TECLEE EL NOMBRE DEL ALUMNO A CONSULTAR\n"); gotoxy (10,17);gets (nom); val=0; for (j=0;j<5;j++) if (strcmp(nombre[j],nom)==0) {k=j;j=5;val=1;} if (val==0) error(); else {formato();gotoxy(13,2); textcolor (4); cprintf ("%s",nombre[k]); x=5; for(n=0;n<12;n++){gotoxy(26,x);cprintf("%4.1f",notas[n][1][k]); gotoxy (36,x); cprintf ("%4.1f",notas[n][2][k]); gotoxy (46,x); cprintf ("%4.1f",notas[n][3][k]); gotoxy (56,x); cprintf ("%4.1f",defin[n][k]); x++; } textcolor (2); gotoxy (25,17); cprintf ("Presione una tecla para continuar"); getch(); }} formato() {window (0,0,80,25);textbackground(0);window (2,7,79,23); clrscr();textcolor (14);gotoxy (5,2); cprintf ("NOMBRE: ");gotoxy (25,4);cprintf ("NOTA 1");gotoxy (35,4); cprintf("NOTA 2:");gotoxy(45,4);cprintf("NOTA 3:"); gotoxy(55,4);cprintf ("DEFINI: ");gotoxy (5,5); cprintf ("Ingles ");gotoxy (5,6);cprintf ("C.Naturales"); gotoxy (5,7);cprintf ("Matematicas");gotoxy (5,8); cprintf ("Dibujo.Tec");gotoxy (5,9);cprintf ("Historia"); gotoxy (5,10);cprintf ("Area Tec.Pract");gotoxy (5,11); cprintf ("Geografia");gotoxy (5,12);cprintf ("Espa$ol");gotoxy (5,13);cprintf ("Tecnologia");gotoxy (5,14); cprintf ("Educ.Fisica");gotoxy (5,15);cprintf ("Sistemas"); gotoxy(5,16);cprintf("Administraci贸n");cuadro(54,3,62,17,4);} error() {window(1,1,79,24);window(20,15,60,17);cuadro(1,1,39,3,15);textbackground (4); window (21,16,57,16); clrscr(); textcolor (15); gotoxy (4,1); cprintf ("!ERROR! : Alumno no encontrado"); getch();}
47
5.7.1 Ejercicios 1. Realizar un programa que multiplique dos 2. Hacer un programa que nos resuelva un matrices. sistema de ecuaciones 2x2 por el metodo de eliminaci贸n de Gauss.
48
5.8 APUNTADORES Un apuntador es una variable que contiene la dirección de otra variable. si definimos : int n,m; Memoria
m
Del
n
Computador
Entonces n y m quedaron en una posición de la memoria del computador, y la cual podemos acceder a dicha posición de memoria a través de su dirección. Utilizando un apuntador podemos guardar la dirección donde se encuentra n y m, y esta nueva variable apunta a la variable m ó n. Sea q la variable que guarda la dirección de n, entonces q apunta a n, y sea r la variable que guarda la dirección de m, entonces r apunta a m. Gráficamente tenemos: r
m
Memoria Del
n q
Computador
Un apuntador puede guardar la dirección de un objeto de cualquier tipo, incluyendo estructuras, funciones, listas, árboles, etc. La forma general para declarar un puntador es: tipo *nombre; tipo : tipo de dato del apuntador al cual va apuntar. * : operador de indirección nombre: nombre de la variable que identifica el apuntador. Utilizamos dos operadores uno de dirección &, el cual nos devuelve la dirección de la variable a la cual se apunta. Y el operador de indirección *, el cual nos devuelve el valor que se encuentra en dicha dirección. Para asignar al puntero una dirección de una posición de memoria utilizamos el operador & de la siguiente forma: int *r; /* se declara el apuntador */ r=&a; /* asigna la dirección de a */
49
Al definir un apuntador no implica que este quede apuntando a alguna variable, porque en este momento no se ha asignado a ninguna dirección. Ejemplo: 1.int q,*u; /* estas variables están en algún sitio de la memoria*/ char r,*w; Para asignar una dirección al apuntador se procede así: u=&q; w=&r;
u
q
w
r
2. main() { int i=10,*q; q=&i; printf("\n el valor de i es %d",*q); printf("\n la dirección de i es %d",&p);getch();}
5.9 PARAMETROS POR REFERENCIA Se denomina parámetro por referencia a una variable que se pasa a una función, la función modifica su valor y devuelve el nuevo valor. ordena(p,q) int *p,*q; {int tem; if (*p>*q) {tem=*p;*p=*q;*q=tem;}} En el programa principal se debe llamar de la siguiente forma:
ordena(&i,&j);
Las direcciones de i y j no pueden ser cambiadas en el medio en que se les llama. Sin embargo si pueden ser desreferenciadas, y esto proporciona el mecanismo mediante el cual la función ordena() puede cambiar los valores almacenados en i y j, en el medio en que se les llama. Podemos definir un apuntador a otro apuntador de la siguiente forma: tipo **variable /* int **pq */
Puntero
Variabl e Valor
Dirección
Puntero Dirección
Indirección
Puntero Dirección Indirección Múltiple
Ejemplo: main() {int y,*p,**q; y=100; p=&y; /* se asigna la dirección de y a p */ q=&p: /* se asigna la dirección de p a q */ printf("%d",**q);} /*imprime el valor de y */ 50
Variabl e Valor
5.10 OPERACIONES CON APUNTADORES Únicamente podemos realizar dos operaciones basicas con los auntadores: suma y resta. ejemplo:
c c+1 c+2 c+3 c+4 c+5
3000 3001 3002 3003 3004 3005
i i+1 i+2
Cada i se incrementa en 2 bytes
Cada c se incrementa en 1byte
char *c=3000; int *i=3000;
Cuando sumamos o restamos apuntadores nos desplazamos o retrocedemos el sizeof(tipo) del tipo de dato del apuntador.
5.11 APUNTADORES Y ARREGLOS Los apuntadores pueden estructurarsen en arrays como cualquier otro tipo de datos. por ejemplo: int *p[10],v; p[0]=&v; printf("%d",*p[0]);
Definimos un array de 10 elementos que son punteros a datos de tipo int y una variable v, asignamos a p[0] la dirección de v y escribimos su contenido.
Ahora si tenemos : char nombre[40],*q; q=nombre; Aquí q ha sido asignado a la dirección del primer elemento del array nombre. Luego si queremos acceder al elemento 7 del array procedemos de la siguiente forma. nombre[6] ó *(q+6)
/* porque apunta al primer elemento de nombre. */
Esto lo podemos realizar porque sabemos que el primer elemento del array es nombre[0] luego el séptimo elemento del array es 0+6, y como q apunta al primer elemento es decir a nombre[0]; podemos acceder a este elemento así. *(q+6), es decir nombre[6] es equivalente a *(q+6).
51
6. ESTRUCTURAS
LOGROS 1. Capacitar al estudiante para el desarrollo de aplicaciones de negocios, utilizando funciones, matrices y estructuras. 2. comprender la relaci贸n existente apuntadores, matrices y estructuras. 3. Desarrollar un proyecto que utilice los diferentes tipos de gr谩ficas, matrices, apuntadores, estructuras, funciones y archivos. 4. Crear diferentes aplicaciones con la estructura de archivos en ambiente DOS y UNIX. 6.1 ESTRUCTURAS Una estructura la podemos definir como un nuevo tipo de datos el cual re煤ne a su vez variables de diferentes tipos de datos; bajo un mismo nombre. El formato general de una estructura es: struct nombre { tipo variable1; tipo variable2; : : tipo variablen; } Variables; En este formato podemos suprimir el nombre de la estructura o las variables pero no ambos al mismo tiempo. Por ejemplo necesitamos analizar un alumno de un curso de la especialidad n, debemos crear una estructura de la siguiente forma: struct alumno{ char nombre[40]; char apellido[40]; unsigned int c贸digo; int curso; char especialidad[40]; }; Como una estructura es un nuevo tipo de datos esta debe terminar con un punto y coma(;). Ahora definimos las variables con respecto a este tipo de datos: struct alumno persona;
52
También lo podemos definir de la siguiente forma: struct alumno{ char nombre[40]; char apellido[40]; unsigned int código; int curso; char especialidad[40]; }persona;
6.2 ACCESO A UN ELEMENTO Para referenciar un elemento de la estructura alumno lo podemos hacer así: persona.nombre persona.código
Cuando queremos referenciar un elemento de una estructura lo haremos mediante la orden: nombre_variable.variable n; Si queremos imprimir por ejemplo la especialidad de un alumno , utilizamos la función printf. printf("%s",persona.especialidad);
6.3 ARREGLOS DE ESTRUCTURAS Podemos definir un arreglo de estructura, en nuestro ejemplo anterior la estructura la diseñamos para un solo alumno, pero si deseamos todos los alumnos del colegio, debemos utilizar un array de tamaño el total de los alumnos matriculados. En este caso definimos nuestra variable persona como un array de tamaño n. struct alumno{ char nombre[40]; char apellido[40]; unsigned int código; int curso; char especialidad[40]; }persona[1000];
Para acceder un elemento de esta nueva estructura debemos indicar el subíndice del elemento al cual referenciamos. printf("%s",persona[i].especialidad); Nos imprime la especialidad del alumno i.
53
6.4 FUNCIONES Y ESTRUCTURAS Una estructura puede estar como argumento de una función o como valor que devuelve una función. Cuando se pasa un elemento de una estructura a una función se pasa es el valor del elemento. Ejemplo: struct nn{ int k;char y;char m[90]; }ejemplo; Esta es la forma de pasarlos a una función determinada: funA(ejemplo.y); /* pasa el valor del entero k */ funB(ejemplo.m); /* pasa el valor de la cadena */ funB(ejemplo.m[34]); /*pasa el valor del funA(&ejemplo.y); /* pasa la dirección de x */
carácter m[34] */
Si queremos pasar la dirección de un elemento especifico a una función este debe estar precedido por el amperson (&). Podemos pasar una estructura como un argumento de la función, en este caso la estructura se pasa como un parámetro por valor, es decir se pasa la copia de la estructura. Ejemplo: main() { struct nn{ int k; char y; char m[90]; }ejemplo; ejemplo.k=200; eje(ejemplo); } eje(par) struct{ int x; char z,n[90]; }par; { gets(par.z); printf("%d",par.z);/* imprime el valor ingresado en gets */ printf("%d",par.x);} /* imprime el valor de 200 */ Podemos definir la estructura globalmente para obtener un resultado más eficiente. struct nn{ int k; char y; char m[90];}; main(){ struct nn ejemplo; /* definimos la variable ejemplo */ ejemplo.k=200;eje(ejemplo);} eje(par) struct nn par;{ gets(par.z); printf("%d",par.z); /* imprime el valor ingresado en gets */ printf("%d",par.x);/* imprime el valor de 200 */} 54
6.5 PUNTEROS A ESTRUCTURAS Como una estructura es un nuevo tipo de dato podemos definir un puntero a una estructura. lo hacemos de la siguiente forma: struct nn{ int k; char y, m[90]; }ejemplo,*p; ó struct nn *puntero; struct nn *p; luego p=&ejemplo; coloca la dirección de la estructura ejemplo en el puntero p. Cuando pasamos un puntero a una estructura a una función el computador solo pone la dirección de la estructura en la pila. Para encontrar la dirección de una variable de una estructura anteponemos el & al nombre de la variable. Para acceder a un elemento de una estructura usando apuntadores, se utiliza la flecha (->) un guión con el símbolo mayor.
ó
p->m[i]=23; (*p).m[i]=23;
Se colocan los paréntesis ya que el operador punto es mayor que el asterisco. 6.6 ESTRUCTURAS ANIDADAS Podemos definir los elementos de la estructura como arrays, y como estructuras. struct w{ int b[3][4]; float e; } y; Para referenciarnos a un elemento de la matriz procedemos así: y.b[i][j]=45; Cuando definimos una estructura como campo de otra estructura; tenemos las estructuras anidadas. struct curso{ char nombre[40]; char apellido[40]; int semes[2]; int año[2]; }semestre; struct alum{ struct curso semestre; int código; }alumno; Para referenciarnos a un elemento de una estructura anidada se procede: alumno.semestre.semes=2; Se accede desde la parte más interna a la externa; es decir de izquierda a derecha.
55
Ejemplo 1: #include <math.h> #include <stdio.h> #include "string.h" struct { char mes[40]; char cta[40]; float debe[10]; float habe[10]; float sal[10]; }matriz[50]; int j,i,op;/*Definición de variables globales */ float d,c; char ban,con,opc; main(){ menú(); } menú(){clrscr();con =1;opc=' ';ban='s'; while (ban=='s') { cuadro();cuadromayor();textcolor(0);textbackground(7|128); gotoxy(33,3);cprintf("LENGUAJE C '"); textcolor(7); textbackground(14);textcolor(0); textbackground(7|128); gotoxy(31,8);cprintf("GESTION DE MATRICES"); textcolor(7); textbackground(14); do { do {switch (con){ case 1 :textcolor(0);textbackground(7|128);gotoxy(33,12);cprintf("INGRESO DATOS"); Textcolor(7);textbackground(14); gotoxy(33,13);cprintf("REPORTE DATOS"); gotoxy(33,14); cprintf("TERMINAR ");break; case 2 :gotoxy(33,12);cprintf("INGRESO DATOS"); textcolor(0);textbackground(7|128);gotoxy(33,13); cprintf("REPORTE DATOS"); textcolor(7);textbackground(14);gotoxy(33,14);cprintf("TERMINAR ");break; case 3 :gotoxy(33,12);cprintf("INGRESO DATOS ");gotoxy(33,13); cprintf("REPORTE DATOS"); textcolor(0);textbackground(7|128);gotoxy(33,14);cprintf("TERMINAR "); textcolor(7);textbackground(14);break; } gotoxy(33,11+con);opc=getch(); }while (((opc==80) ||(opc==50)) && ((opc==72)||(opc==56))); if ((opc==80) || (opc==50)){if (con != 3 ){con += 1;} else {con = 1;}} else {if ((opc==72) || (opc==56)){if (con != 1 ) {con -= 1 ;} else { con = 3; } }} } while (opc!=13); switch (con){ case 1 : captura();break; case 2 : reportes();break; case 3 :terminar();break; } clrscr();} } terminar(){ char seguir; clrscr();cuadromayor();textcolor(0);textbackground(7|128); gotoxy(35,6);cprintf(" TERMINAR "); textcolor(7); textbackground(14);gotoxy(34,10);printf("DESEA SEGUIR "); gotoxy(34,11);printf("TRABAJANDO ?.");gotoxy(34,13); printf(" [ S / N ] "); gotoxy(37,16); cprintf("-----"); gotoxy(39,15); scanf("%s",&seguir); if((seguir=='s') || (seguir=='S')) {gotoxy(24,20);puts("DIGITE UNA TECLA PARA CONTINUAR"); } else { if ((seguir=='n') || (seguir=='N')) {ban='n'; gotoxy(24,20);puts("DIGITE UNA TECLA PARA TERMINAR"); getch();clrscr();exit(1); }} } 56
cuadro(){int i; for (i=0;i<=30;i++){ gotoxy(i+25,6);printf("%c",205);gotoxy(i+25,19); printf("%c",205);} for (i=0;i<=11;i++){gotoxy(24,i+7);printf("%c",186);gotoxy(56,i+7); printf("%c",186);} gotoxy(24,6);printf("%c",201);gotoxy(24,19); printf("%c",200);gotoxy(56,6);printf("%c",187); gotoxy(56,19); printf("%c",188);} cuadromayor(){ int i; textcolor(14);textbackground(0|128); for (i=0;i<=79;i++){ gotoxy(i+1,1);cprintf("%c",205);gotoxy(i+1,24); cprintf("%c",205);}for (i=0;i<=23;i++){ gotoxy(1,i+1);cprintf("%c",186);gotoxy(80,i+1); cprintf("%c",186);}gotoxy(1,1);cprintf("%c",201); gotoxy(1,24); cprintf("%c",200);gotoxy(80,1);cprintf("%c",187);gotoxy(80,24); cprintf("%c",188);} cuadrobal(){int i; textcolor(14);textbackground(0|128);for (i=0;i<=79;i++){ gotoxy(i+1,1);cprintf("%c",205);gotoxy(i+1,5); cprintf("%c",205);gotoxy(i+1,8);cprintf("%c",205); gotoxy(i+1,22); cprintf("%c",205);gotoxy(i+1,24); cprintf("%c",205);}for (i=0;i<=23;i++){ gotoxy(1,i+1);cprintf("%c",186);gotoxy(80,i+1); cprintf("%c",186);}gotoxy(1,1);cprintf("%c",201); gotoxy(1,24); cprintf("%c",200);gotoxy(80,1);cprintf("%c",187);gotoxy(80,24); cprintf("%c",188);} capturabal(){ int i; textcolor(14);textbackground(0|128);for (i=0;i<=79;i++) {gotoxy(i+1,1);cprintf("%c",205);gotoxy(i+1,5); cprintf("%c",205);gotoxy(i+1,8);cprintf("%c",205); gotoxy(i+1,22); cprintf("%c",205);gotoxy(i+1,24);cprintf("%c",205);} for (i=0;i<=23;i++){gotoxy(1,i+1);cprintf("%c",186);gotoxy(80,i+1); cprintf("%c",186);} for (i=0;i<=13;i++){gotoxy(23,9+i);cprintf("%c",186);gotoxy(58,9+i); cprintf("%c",186); } for (i=0;i<=11;i++) { gotoxy(40,11+i);cprintf("%c",186); } for (i=0;i<=34;i++) { gotoxy(24+i,11);cprintf("%c",205); } gotoxy(23,8);cprintf("%c",203);gotoxy(23,22); cprintf("%c",202);gotoxy(58,8);cprintf("%c",203); gotoxy(58,22); cprintf("%c",202);gotoxy(40,22);cprintf("%c",202);gotoxy(40,11); cprintf("%c",203); gotoxy(58,11);cprintf("%c",185);gotoxy(23,11); cprintf("%c",204);gotoxy(1,1);cprintf("%c",201); gotoxy(1,24);cprintf("%c",200);gotoxy(80,1);cprintf("%c",187);gotoxy(80,24); cprintf("%c",188);} lineabal(){int i; for (i=0;i<=12;i++) {gotoxy(20,9+i);cprintf("%c",186);gotoxy(32,9+i); cprintf("%c",186);gotoxy(44,9+i);cprintf("%c",186); gotoxy(56,9+i); cprintf("%c",186);gotoxy(68,9+i); cprintf("%c",186); } gotoxy(20,8);cprintf("%c",203);gotoxy(20,22); cprintf("%c",202);gotoxy(32,8);cprintf("%c",203); gotoxy(32,22); cprintf("%c",202);gotoxy(56,8);cprintf("%c",203);gotoxy(56,22); cprintf("%c",202); gotoxy(68,8);cprintf("%c",203);gotoxy(68,22); cprintf("%c",202);} captura(){ int fil,col,a,k; char cade; clrscr();k=0; ingreso(); capturabal(); for (i=0;i<5;i++) {j=0;gotoxy(5,23);printf("DIGITE MES :"); do { gotoxy(20+j,23);cade=toupper(getche()); matriz[i].mes[j]=cade;gotoxy(5+k+j,7); putch(matriz[i].mes[j]);j++;}while(cade != 13 ); k+=15; gotoxy(20,23);printf(" "); }k=0; for (i=0;i<3;i++){ j=0;gotoxy(5,23);printf("DIGITE CUENTA:"); do {gotoxy(23+j,23); cade=toupper(getche()); matriz[i].cta[j]=cade;gotoxy(3+j,15+k); putch(matriz[i].cta[j]);j++; } while(cade != 13 ); k+=2;gotoxy(20,23);printf(" "); } d=c=0; fil=15;col=a=27;for (j=0;j<5;j++) { gotoxy(36,10);puts(matriz[j].mes); for (i=0;i<3;i++) { d=c=0; gotoxy(col,fil);scanf("%f",&d);matriz[j].debe[i]=d;col+=15;gotoxy(col,fil);scanf("%f",&c); matriz[j].habe[i]=c;matriz[j].sal[i]=0.0; col=a;fil=fil+2; } fil=15; gotoxy(36,10);printf(" "); gotoxy(27,15);printf(" ");gotoxy(41,15);printf(" "); gotoxy(27,17); printf(" ");gotoxy(41,17);printf(" "); gotoxy(27,19);printf(" ");gotoxy(41,19);printf(" "); } } 57
reportes(){ int fil,col,k,l; clrscr();k=l=0; salida(); cuadrobal();lineabal();fil=13;col=22; for (j=0;j<5;j++) { gotoxy(23+k,7);puts(matriz[j].mes); gotoxy(3,13+l);;puts(matriz[j].cta); for (i=0;i<3;i++) { matriz[j].sal[i]=matriz[j].debe[i]-matriz[j]. habe[i];gotoxy(col,fil); printf("%-8.1f",matriz[j].sal[i]); fil=fil+2; } col=col+12; fil=13;k+=12;l+=2; } getch(); } ingreso(){ clrscr(); gotoxy(36,2);printf("BALANCE");gotoxy(33,4); printf("INGRESO DATOS"); gotoxy(28,12);printf("DEBE HABER "); } salida(){ clrscr(); gotoxy(36,2);printf("BALANCE");gotoxy(33,4);printf("REPORTE DATOS"); gotoxy(22,10);printf("SALDO SALDO SALDO SALDO SALDO"); }
Ejemplo 2: #include <stdio.h> #include <conio.h> #define ESC 0x1B #define MAXLINES 24 #define MAX_LIBROS 10 int xc,yc,i,x,m,j,Ultimo_Libro=0; int CodInt; int Acci贸n; int Listado; char *ptr; char c; char msg; char Str[20]; struct LibrosType{ char Autor [20]; char Materia [20]; char Titulo [20]; int Estado; CodInt;}; struct LibrosType Libros[MAX_LIBROS]; void Cuadro(xci,xcf,yci,ycf,tipo,color) int xci, xcf, yci, ycf,tipo,color; {int xcw, ycw, bsi, bsd, bii, bid, bsr, bir, bli, bld; bsi=201;bsd=187; bii=200; bid=188; bsr=bir=205; bli=bld=186; if (tipo==1){bsi=218;bsd=191;bii=192;bid=217;bsr=bir=196;bli=bld=179;}else if (tipo==2) { bsi=bsd=bii=bid=bli=bld=219; bsr=223; bir=220;} textcolor(color);gotoxy(xci,yci);cprintf("%c",bsi);gotoxy(xcf,yci);cprintf("%c",bsd);gotoxy(xci,ycf); cprintf("%c",bii);gotoxy(xcf,ycf);cprintf("%c",bid); for(xcw=xci+1;xcw<=xcf-1;xcw++){gotoxy(xcw,yci); cprintf("%c",bsr);gotoxy(xcw,ycf);cprintf("%c",bir);}for(ycw=yci+1;ycw<=ycf-1;ycw++){ gotoxy(xci,ycw);cprintf("%c",bli); gotoxy(xcf,ycw);cprintf("%c",bld);}} void MessageLine(xci,yci,msg01,msg02) int xci, yci; char *msg01[]; char *msg02[];{textbackground(7);textcolor(4);gotoxy(xci,yci);cprintf("%s",msg01);textcolor(0); 58
cprintf("%s",msg02);textbackground(0);} void Limpiar(yi, yf) int yi, yf; { int ii;for (ii=yi;ii<=yf;ii++){gotoxy(2,ii); printf(" ");printf(" "); }} Numero (X, Y, Msg, T) int X,Y,Y;char *Msg; {register int ii, exp;int ci; ci=1; while(ci==1){gotoxy(X,Y); cprintf(Msg);ii=1; exp=0; while((ii<=T)&&(((c=getch())!=ESC)&&c!=13)){ if ((c>='0')&&(c<='9')){putchar(c);exp= exp * 10 + c - '0';ii++;}}if (ii==T){ gotoxy(25,23); cprintf("Campo lleno. Presione ENTER o ESC");while((c=getch())!=ESC&&c!=13); if (c==13)break;} else if (c!=ESC) break;}return exp;} Leer (int X, int Y, char *Msg, char *D,int T) {int ii, ci; char p[20]; ci=1; while(ci==1){gotoxy(X,Y); cprintf(Msg);ii=0;while(((c=toupper(getch()))!=ESC&&c!=13)&&ii<T){ if (((c>='A')&&(c<='Z'))||(c==' ')){putchar(c);p[ii++]=c;}}if (ii==T){gotoxy(10,18); cprintf("Campo lleno. Presione ENTER o ESC");while((c=getch())!=ESC&&c!=13);if (c==13) break;} else if (c!=ESC) break;}p[ii]='\0'; strcpy(D,p);} void Continuar (Msg) char *Msg; {textcolor(10); gotoxy(20,23);cprintf("%s Presione cualquier tecla", Msg);getch();
Limpiar(2,23);}
Crear(){struct Libros *info, *Insert();Cuadro(3,50,3,20,0,11);gotoxy(20,5); cprintf("Creacion Archivo"); Ultimo_Libro++;leer(5,7,"Nombre Autor ",Libros [Ultimo_Libro].Autor,20); Leer(5,9,"Materia ",Libros[Ultimo_Libro].Materia,20); Leer(5,11,"Titulo Libro ",Libros[Ultimo_Libro].Titulo,20);CodInt=Numero(5,13,"Cod. Interno ",5); for(i=1;i<=Ultimo_Libro;i++)if(Libros[i].CodInt==CodInt) {gotoxy(12,19); textcolor(13|128); cprintf("C贸digo Interno ya fue asignado");Ultimo_Libro--;Continuar (" ");return 0;} Libros[Ultimo_Libro].CodInt=CodInt;Libros[Ultimo_Libro].Estado=0;Limpiar(2,23);} void Imprimir(d1,d2) int d1;char *d2; { register int ii=1; while(*d2){fprintf(stdprn,"%c",*d2++);ii++;}for(ii=ii-1;ii<d1;ii++)fprintf(stdprn," ");} void Mostrar(X, Y, d1, d2, d3) int X,Y,d1; char *d2,*d3; {int x;Accion=1; gotoxy(X, Y);cprintf("%5i",Libros[d1].CodInt); x=X+7;gotoxy(x, Y);cprintf("%s",d2);x+=23;gotoxy(x, Y);cprintf("%s",d3); x+=22;gotoxy(x,Y); if (Libros[d1].Estado==0)cprintf("DISPONIBLE"); else cprintf("PRESTADO");} void Listar(d1, d2, d3) int d1; char *d2,*d3; {fprintf(stdprn, "%6i ", Libros[d1].CodInt);Imprimir(23,d2); Imprimir(22,d3);if (Libros[d1].Estado==0) fprintf(stdprn, "DISPONIBLE\n");else fprintf(stdprn, "PRESTADO\n");} void Autor(){Cuadro(3,50,3,11,0,15);gotoxy(15,5);cprintf("Consulta por Autor");textcolor(11); Leer(5,7,"Nombre ",Str,20);gotoxy(15,9); cprintf("Desea imprimir consulta ? S/N "); while((c=toupper(getch()))!='S' && c!='N');if (c=='S'){ Listado=1; fprintf(stdprn," CONSULTA POR AUTOR : %s \n\n\n",Str); fprintf(stdprn,"CODIGO ----- MATERIA ------ ------ TITULO ------ ESTADO\n\n"); }else Listado=0;gotoxy(5,13);cprintf("CODIGO ----- MATERIA ------ ------ TITULO ------ ESTADO"); textcolor(7);yc=14;Accion=0;for(i=1;i<=Ultimo_Libro;i++){if(strcmp(Str,Libros[i].Autor)==0){if (Listado==1) 59
Listar(i,Libros[i].Materia,Libros[i].Titulo);Mostrar(5,yc,i,Libros[i].Materia,Libros[i].Titulo);yc++; if (yc>21){gotoxy(20,23);printf("Hay mas libros para consultar. Presione cualquier tecla");getch(); Limpiar(9,23); yc=9;}}} if (Accion==0)Continuar("No encontre registros."); Else Continuar("Fin de la Consulta.");} void Materia(){Cuadro(3,50,3,11,0,15);gotoxy(15,5); cprintf("Consulta por Materia"); textcolor(11); Leer(5,7,"Nombre ",&Str,20);gotoxy(15,9); cprintf("Desea imprimir consulta ? S/N "); while((c=toupper(getch()))!='S' && c!='N'); if (c=='S'){Listado=1;fprintf(stdprn," CONSULTA POR MATERIA : %s \n\n\n",Str); fprintf(stdprn,"CODIGO ------ TITULO ------ ------- AUTOR ------ ESTADO\n\n");} else Listado=0;gotoxy(5,13); cprintf("CODIGO ------ TITULO ------ ------- AUTOR ------ ESTADO");textcolor(7);Accion=0;yc=14; for(i=1;i<=Ultimo_Libro;i++) {if (strcmp(Str,Libros[i].Materia)==0) {if (Listado==1)Listar(i,Libros[i].Titulo,Libros[i].Autor);Mostrar(5,yc,i,Libros[i].Titulo,Libros[i].Autor); yc++;if (yc>21){gotoxy(20,23);Continuar("Hay mas libros para consultar. ");Limpiar(9,23);yc=9;}}} if (Accion==0)Continuar("No encontre registros. ");else Continuar("Fin de la Consulta.");} void Titulo() {Cuadro(3,50,3,11,0,15);gotoxy(15,5); cprintf("Consulta por Titulo");textcolor(11); Leer(5,7,"Nombre ",&Str,20);gotoxy(15,9); cprintf("Desea imprimir consulta ? S/N "); while((c=toupper(getch()))!='S' && c!='N'); if (c=='S'){Listado=1;fprintf(stdprn," CONSULTA POR TITULO : %s \n\n\n",Str);fprintf(stdprn,"CODIGO ------ AUTOR ------- ------ MATERIA ----- ESTADO\n\n");}else Listado=0; cprintf ("%c",c); gotoxy(5,13); cprintf("CODIGO ------ AUTOR ------- ------ MATERIA ----- ESTADO");textcolor(7);yc=14;Accion=0; for(i=1;i<=Ultimo_Libro;i++){if (strcmp(Str,Libros[i].Titulo)==0){if (Listado==1) Listar (i,Libros[i].Autor,Libros[i].Materia);Mostrar(5,yc,i,Libros[i].Autor,Libros[i].Materia);yc++; if (yc>21){ gotoxy(20,23);Continuar("Hay mas libros para consultar. ");Limpiar(9,23);yc=14;}}} if(Accion==0)Continuar("No encontre registros. ");else Continuar("Fin de la Consulta.");} void Prestamo(){Cuadro(3,50,3,9,0,15);gotoxy(18,5);cprintf("Prestamo Libro");textcolor(11); CodInt=Numero(5,7,"C贸digo ",20);Accion=0; for(i=1;i<=Ultimo_Libro;i++){ if (CodInt==Libros[i].CodInt){ accion=1;gotoxy(5,12);cprintf("Titulo %s ",Libros[i].Titulo);gotoxy(5,14); cprintf("Materia %s ",Libros[i].Materia);gotoxy(5,16);cprintf("Autor %s ",Libros[i].Autor); gotoxy(5,18);if (Libros[i].Estado){textcolor(13|128);cprintf("LIBRO PRESTADO GRACIAS");} else {cprintf("Desea prestarlo ? S/N ");while(((c=toupper(getch()))!='S')&&(c!='N')); if (c=='S'){Libros[i].Estado=1;gotoxy(5,18);textcolor(12|128);cprintf("LIBRO TOMADO EN PRESTAMO GRACIAS!!! ");}}}}if (Accion==0) Continuar("No encontre registro. ");else Continuar(" ");} void Devolucion(){ Cuadro(3,50,3,9,0,15); gotoxy(18,5); cprintf("Devolucion Libro");textcolor(11); CodInt=Numero(5,7,"C贸digo ",20);Accion=0; for(i=1;i<=Ultimo_Libro;i++){if (CodInt==Libros[i].CodInt){ Accion=1;gotoxy(5,12); cprintf("Titulo %s ",Libros[i].Titulo);gotoxy(5,14) ;cprintf("Materia %s ",Libros[i].Materia);gotoxy(5,16);cprintf("Autor %s ",Libros[i].Autor); gotoxy(5,18);if (!Libros[i].Estado){ textcolor(13|128);cprintf("LIBRO NO HA SIDO PRESTADO"); } else {cprintf("Desea devolverlo ? S/N ");while(((c=toupper(getch()))!='S')&&(c!='N')); if (c=='S'){Libros[i].Estado=0;gotoxy(5,18);textcolor(12|128);cprintf("LIBRO DEVUELTO GRACIAS!!! ");}}}} if (Accion==0) Continuar("No encontre registro. ");else Continuar(" ");} main(){ clrscr();textbackground(WHITE); textcolor(BLACK); gotoxy(15,1);cprintf("ESTE PROGRAMA ES ELABORADO POR MANUEL MONTERO"); gotoxy(20,6);cprintf("SIN DERECHO A SU REPRODUCCION"); gotoxy(26,15);cprintf("INSTITUTO SANTANDER "); gotoxy(27,9);cprintf("TURBO 'C' VER 20"); gotoxy(30,19);cprintf("** 1.992 **"); gotoxy (5,24); cprintf("pulse cualquier tecla para continuar . . . \a"); getch();clrscr();Cuadro(1,80,1,24,1,10);c=' '; while(c!=ESC){textbackground(0); MessageLine(1,25,"C","reacion Archivo "); 60
MessageLine(19,25,"A","utor "); MessageLine(26,25,"M","ateria ");MessageLine(35,25,"T","itulo "); MessageLine(42,25,"P","restamo Libro ");MessageLine(58,25,"D","evolucion Libro "); MessageLine(76,25,"ESC"," "); while((c=toupper(getch()))!='C'&&c!='A'&&c!='M'&&c!='T'&&c!='P'&&c!='D'&&c!=ESC);if (c!=ESC){ textbackground(7); textcolor(10 | 128);switch(c){ case 'C': gotoxy(1,25); break; case 'A': gotoxy(19,25);break; case 'M': gotoxy(26,25);break;case 'T': gotoxy(35,25);break; case 'P': gotoxy(42,25);break; case 'D': gotoxy(58,25);}cprintf ("%c",c);textbackground(0);switch(c){ case 'C': Crear();break;case 'A': Autor();break;case 'M': Materia();break;case 'T': Titulo();break; case 'P': Prestamo(); break;case 'D': Devolucion();}}} clrscr();}
6.7 UNIONES Una unión al igual que una estructura es un nuevo tipo de dato, las uniones tienen la misma sintaxis de una estructura, pero algunos de sus miembros comparten el almacenamiento. Una variable unión define un conjunto de valores alternos que pueden almacenarse en una parte compartida de la memoria. unión ejemplo { int a; float b; }eje; En este momento se definió la variable eje que ocupara el tipo de dato más grande que pueda guardar el otro tipo de dato. Gráficamente podemos verlo así: ┌─── a ────┐ Byte0
Byte1
Byte2
Byte3
└───────── b ──────────┘ Para acceder a un elemento de una unión lo hacemos de la misma forma que a un elemento de una estructura. eje.a=56; 6.8 CAMPOS Un campo es un miembro con longitud en bits especificada por una expresión constante no negativa seguida de dos puntos. Generalmente los campos se declaran como miembros consecutivos de una estructura. struct nombre { tipo nombre1:longitud; tipo nombre2:longitud; tipo nombre3:longitud; : . tipo nombren:longitud; }nombre_var; Los tipos de datos que se pueden utilizar en los campos son: unsigned, int o signed; 61
Las restricciones con los campos son: - No se puede tomar la dirección de una variable de campo de bit. - No se pueden poner en arrays variables de campos de bits. 6.9 ENUMERACIONES Usamos la palabra reservada enum ,para declarar tipos de enumeración. esto nos proporciona el medio para nombrar un conjunto finito y para declarar variables que adopten valores que son elementos del conjunto. enum {lun,mar,mier,jue,vier,sab,dom} dias1,dias2; Estamos definiendo un conjunto con los elementos que son los días de la semana y al mismo tiempo definimos dos variables de este nuevo tipo de datos. Podemos emplear las siguientes sentencias sin ningún problema: dias2=lunes; if(dias1==dias2) printf(" hoy llueve"); Su formato general es: enum nombre {lista de elementos} variables; 6.10 TYPEDEF Podemos definir nuevos nombres de los tipos de datos usando el comando typedef. lo hacemos de la siguiente forma: typedef tipo nombre; tipo: Es cualquier tipo de dato proporcionado por Turbo C. Nombre: Es el nuevo nombre que le damos a este tipo de dato. Ejemplo: typedef int integer; typedef float real; 6.11 EJERCICIOS 1. Realizar un programa que nos calcule los numeros primos, con un arreglo de estructuras dividido en campos de bit.(utilizando la criba de Erastóstenes). Realizar un programa de notas (ejemplo de matrices) utilizando estructuras y apuntadores. 7. ARCHIVOS
62
7.1 ARCHIVOS Un archivo es accesible a través de un apuntador a una estructura definida como FILE en el archivo estándar de cabecera stdio.h. En esta estructura se encuentra los miembros que describen el estado actual del archivo. Un archivo se define como un flujo de caracteres que se procesa secuencialmente. 7.2 FUNCIONES DE ARCHIVOS EN AMBIENTE DOS. fopen(nombre_archivo,modo_archivo): Esta función se utiliza para abrir un archivo con buffers y devuelve un apuntador a FILE. Si nombre _archivo no es accesible, entonces se devuelve el valor al apuntador NULL. Nombre_archivo, como modo_archivo son cadenas. Modo_archivo Acceso
Descripción Abrir archivo para leer, si no existe error Abrir fichero para escribir si no existe se crea. Abrir archivo para añadir al de este. Abrir archivo para leer y escribir el archivo debe existir. Abrir archivo para leer y escribir el archivo si existe se borra o si no se crea. Abrir el archivo para leer y añadir , el archivo debe existir.
r w a r+ w+ a+
caracteres: b t
escribe el archivo en forma de binario escribe el archivo en forma texto.
Ejemplo: FILE *ma; ma=fopen("datos.dat","wb"); abre un archivo para escritura en modo binario. fclose (apuntador_archivo): esta función nos permite efectuar las labores necesarias para vaciar los buffers y terminar todas las conexiones con el archivo indicado. si el Apuntador_archivo no esta asociado con un archivo se devuelve EOF. fcloseall(): Esta función cierra todos los archivos que se encuentren abiertos. fprintf(puntero_archivo,cadena): Esta función es lo mismo que la función fprintf, la diferencia radica en que su salida se realiza hacia un archivo . fscanf(apuntador_archivo,cadena de control,lista de variables): corresponde a la función scanf(), pero tiene como primer argumento un apuntador de archivo que indica el archivo que se leerá. getc(apuntador_archivo): Con esta función obtenemos el siguiente carácter del archivo al que 63
apunta apuntador_archivo. El valor del carácter se devuelve como tipo int. si se encuentra un error o un fin de archivo se devuelve un EOF.
getchar(): equivalente a getc(). gets(s): s es una variable de cadena (apuntador a char); gets(s) lee una cadena del teclado. se colocan caracteres en s hasta que se lee un carácter de nueva línea, el cual se reemplaza por un carácter nulo que le indica la terminación de la cadena. fgetc(apuntador_archivo): Actúa en forma similar a getc() pero con la diferencia que es una función y no una macro. ungetc(c,apuntador_archivo): Esta función devuelve el valor char de c al archivo que apunta y devuelve el valor int de c. putc(c,apuntador_archivo): coloca el valor char de c en el archivo de salida hacia el que apunta apuntador_archivo. Devuelve el valor int del carácter escrito; fput(c,apuntador archivo):es similar a putc(). fgets(s,n,apuntador_archivo): Se leen los caracteres del archivo al que apunta apuntador_archivo y se colocan dentro de la cadena s hasta que hayan leído n-1 caracteres o un carácter de retorno. fputs(s,apuntador_archivo):La cadena s terminada en un carácter nulo se copia en el archivo en el que se apunta apuntador_archivo a menos que no se copie el carácter nulo de terminación . fseek(apuntador_archivo,desplazamiento,lugar):se establece la posición de la siguiente operación de entrada o salida. desplazamiento: es una variable de tipo long. lugar: es una variable de tipo int que puede tomar uno de los tres valores: 0 1 2
principio del archivo posición actual del archivo fin de archivo
SEEK_SET SEEK_CUR SEEK_END
El apuntador de archivo se desplaza en bytes a partir de lugar y destruye todos los efectos de ungetc(). rewind(apuntador_archivo): es equivalente a fseek(). ftell(apuntador_archivo): El desplazamiento actual, desde el principio del archivo que se apunta , se devuelve como long. unlike(nombre_archivo): El archivo nombrado se elimina del disco. exit(stado): Cuando se invoca esta función se termina el programa. Se descargan todos los buffers y se cierran los archivos. fread(*buffer,numero_bytes,cantidad,FILE):Se utiliza esta función para los datos que ocupan más
64
de un byte, es decir para matrices y estructuras, y donde *buffer es un puntero a una región de memoria donde escribir los datos leídos del archivo, número_bytes es el número de bytes a leer, cantidad determina cuantos elementos del mismo numero de bytes se van a leer, FILE es un apuntador al un archivo abierto previamente. fwrite(*buffer,numero_bytes,cantidad,FILE): Se utiliza esta función para los datos que ocupan más de un byte, es decir para matrices y estructuras, y donde *buffer es un puntero a una región de memoria donde leer los datos para ser escritos al archivo, número_bytes es el número de bytes a escribir, cantidad determina cuantos elementos del mismo numero de bytes se van a escribir, FILE es un apuntador al un archivo abierto previamente. EJEMPLO #1: #include<stdio.h> #include<ctype.h> #define tama 7 struct dire{ char nombre[40]; char calle[40]; char ciudad[30]; char barrio[20]; char código[10]; }info[tama]; void introduccir(), init_list(),mostrar(), guarda(), lee(); /*definicion de las funciones utilizadas en el programa */ main(){ char opc;clrscr(); init_list();for (;;){opc=menú(); switch(opc) { case 'i':introduccir();break; case 'm':mostrar(); break; case 'g' :guarda(); break; case 'l':lee(); break; case 'b':buscar(); break; case 's':salir(1); }}} /*inicializar la matriz de la estructura info */ void init_list(){register int t;clrscr(); for(t=0;t<tama;t++) *info[t].nombre='\0'; /* un nombre de longitud cero significa vacio */ } /*coger una opción del menú */ menú(){char s[80]; do {gotoxy (5,2);printf("(I)ntroduccir");gotoxy (15,2);printf("(M)ostrar"); gotoxy (25,2);printf("(L)leer");gotoxy (35,2);printf("(G)rabar"); gotoxy (45,2);printf("(B)uscar");gotoxy (55,2);printf("(S)alir"); gotoxy(24,20);printf(" ESCOJA SU OPCION");gets(s);clrscr();}while (!strrchr("imlgs",tolower(*s))); return tolower(*s);} void introduccir()/*coloca los nombres en info */{ register int i;clrscr();for(i=0;i<tama;i++)if(!*info[i].nombre) break; if (i==tama){printf("info completa\n"); return; }printf("nombre: ");gets(info[i].nombre);printf("calle: "); 65
gets(info[i].calle);printf("ciudad: ");gets(info[i].ciudad);printf("barrio: ");gets(info[i].barrio);printf("código: "); gets(info[i].código);} void mostrar(){register int t; clrscr();for(t=0;t<tama;t++) {if(*info[t].nombre) {gotoxy (5,5);printf("NOMBRE : %s\n",info[t].nombre);gotoxy (5,6); printf("DIRECCION : %s\n",info[t].calle);gotoxy (5,7);printf("CIUDAD :%s\n",info[t].ciudad); gotoxy (5,8);printf("BARRIO: %s\n",info[t].barrio); gotoxy (5,9);printf("CODIGO:%s\n",info[t].código);}gotoxy(5,20);printf("oprimaENTER ");getch();clrscr();}} void guarda(){ FILE *ma; register int i;clrscr(); if((ma=fopen("mam.dat","ab"))==NULL){printf("no se puede abrir el archivo\n"); return; } for(i=0;i<tama;i++)if(*info[i].nombre)if (fwrite(&info[i],sizeof(struct dire),1,ma)!=1) printf("error de escritura en archivo\n");fclose(ma); } void lee(){ FILE *ma;register int i;clrscr();if((ma=fopen("mam.dat","rb"))==NULL){ printf("no se puede abrir el archivo\n"); return; } init_list();for(i=0;i<tama;i++)if (fread(&info[i],sizeof(struct dire),1,ma)!=1){ if(feof(ma)){ fclose(ma); return;} printf("error de lectura en archivo\n");}} salir(){ exit();} EJEMPLO #2 #include <string.h> #include <stdio.h> #include <conio.h> #define numestru 100 struct DATOS{ char nombre[35]; char barrio[15]; char telefono[7]; char dirección[40]; char edad[2]; char fechac[8]; }alumno[numestru]; FILE *infodat; char op,ch; int i,j,c=0; anadir(){ register i=0; clrscr(); textbackground(WHITE);textcolor(BLACK); textbackground(WHITE); textcolor(BLACK); if ((infodat = fopen("info.dat","a+")) != NULL) { i=0;do { clrscr(); gotoxy(5,2); cprintf("Esta opsion adiciona un registro");gotoxy(10,4); cprintf("Por favor introduzca estos datos");gotoxy(20,10); cprintf("Nombre : ");gets(alumno[i].nombre);if (strlen(alumno[i].nombre) == 0) { gotoxy(42,10);gets(alumno[i].nombre);} gotoxy(20,11);cprintf("Barrio : ");gets(alumno[i].barrio); gotoxy(20,12); cprintf("Telefono :"); gets(alumno[i].telefono); gotoxy(20,13);cprintf("Dirección : "); gets(alumno[i].dirección);gotoxy(20,14);cprintf("Edad : "); gets(alumno[i].edad); 66
gotoxy(20,15);cprintf("Fecha de Nacimiento : ");gets(alumno[i].fechac); fprintf(infodat,"%s \n",alumno[i].nombre);fprintf(infodat,"%s \n",alumno[i].barrio); fprintf(infodat,"%s \n",alumno[i].telefono);printf(infodat,"%s \n",alumno[i].dirección); fprintf(infodat,"%s \n",alumno[i].edad);fprintf(infodat,"%s \n",alumno[i].fechac); gotoxy(10,20); cprintf("Desea continuar (s/n)? ***> "); op=getch();op=toupper(op);if (op == 'S'){i++;}} while (op == 'S'); fcloseall(); } else {clrscr();puts("No se puede abrir el fichero INFO.DAT\a") ; getch(); } menú();} visualizar(){int g,x; register i=0; clrscr(); textbackground(WHITE); textcolor(BLACK);textbackground(WHITE);textcolor(BLACK); if ((infodat =fopen("info.dat","a+"))!=NULL){ fseek(infodat,SEEK_SET,SEEK_SET); for (i=0;i<numestru;++i){fscanf(infodat,"%s \n",&alumno[i].nombre); fscanf(infodat,"%s \n",&alumno[i].barrio);fscanf(infodat,"%s \n",&alumno[i].telefono); fscanf(infodat,"%s \n",&alumno[i].dirección);fscanf(infodat,"%s \n",&alumno[i].edad); fscanf(infodat,"%s \n",&alumno[i].fechac); }i=0;clrscr(); gotoxy(10,12); cprintf("Esta opción visualiza todos los registros.");x=1; do { clrscr(); gotoxy(5,5); cprintf("Registro : %d",x); gotoxy(20,10);cprintf("Nombre : ");puts(alumno[i].nombre); gotoxy(20,11); cprintf("Barrio :"); puts(alumno[i].barrio);gotoxy(20,12);cprintf("Telefono : "); puts(alumno[i].telefono); gotoxy(20,13); cprintf("Dirección : "); puts(alumno[i].dirección);gotoxy(20,14);cprintf("Edad :"); puts(alumno[i].edad);gotoxy(20,15); cprintf("Fechade Nacimiento:"); puts(alumno[i].fechac); gotoxy(10,20);cprintf("Desea continuar? (s/n) ***>"); op=getch();op=toupper(op);if (op == 'S'){x++;i++;}} while (op == 'S');fcloseall();} else {clrscr();puts("No se puede abrir o no existe el fichero INFO.DAT\a"); getch(); } menú();} modificar(){char nom[35];int g; register i=0; clrscr(); textbackground(WHITE); textcolor(BLACK); textbackground(WHITE); textcolor(BLACK); if ((infodat = fopen("info.dat","a+"))!=NULL) { fseek(infodat,SEEK_SET,SEEK_SET); for (i=0;i<numestru;++i) { fscanf(infodat,"%s \n",&alumno[i].nombre); fscanf(infodat,"%s \n",&alumno[i].barrio); fscanf(infodat,"%s \n",&alumno[i].telefono); fscanf(infodat,"%s \n",&alumno[i].dirección); fscanf(infodat,"%s \n",&alumno[i].edad); fscanf(infodat,"%s \n",&alumno[i].fechac); } i=0; clrscr(); gotoxy(10,12);cprintf("Digite el nombre de la persona del registro a modificar *>"); gets(nom); for (i=0;i<101;i++) { if (strcmp(nom,alumno[i].nombre)==0) { clrscr(); gotoxy(10,5); cprintf("Introduzca los nuevos datos del registro de %s",alumno[i].nombre);gotoxy(20,10); cprintf("Nombre : "); gets(alumno[i].nombre); if (strlen(alumno[i].nombre) == 0){ gotoxy(42,10);gets(alumno[i].nombre); } gotoxy(20,11);cprintf("Barrio : ");gets(alumno[i].barrio);gotoxy(20,12); cprintf("Telefono : "); gets(alumno[i].telefono); gotoxy(20,13);cprintf("Dirección : ");gets(alumno[i].dirección); gotoxy(20,14); cprintf("Edad : "); gets(alumno[i].edad);gotoxy(20,15);cprintf("Fecha de Nacimiento : "); gets(alumno[i].fechac);fprintf(infodat,"%s\n",alumno[i].nombre); fprintf(infodat,"%s \n",alumno[i].barrio); fprintf(infodat,"%s \n",alumno[i].telefono);fprintf(infodat,"%s \n",alumno[i].dirección); 67
fprintf(infodat,"%s \n",alumno[i].edad);fprintf(infodat,"%s \n",alumno[i].fechac); gotoxy(10,20);cprintf("Desea modificar otro registro? (s/n) ***>");op=getch(); op=toupper(op); if(op == 'S'){modificar();}else{fcloseall();menú(); }}}} else { clrscr();puts("No se puede abrir o no existe el fichero INFO.DAT\a");getch();menú(); }} menú(){clrscr(); textbackground(BLACK); textcolor(WHITE);textbackground(BLACK); textcolor(WHITE); gotoxy(27,8);cprintf("M E N U");gotoxy(18,12);cprintf("1) A$adir Registro"); gotoxy(18,14);cprintf("2) Modificar un Registro");gotoxy(18,16);cprintf("3) Visualizar todos lo Registros"); gotoxy(18,18);cprintf("4) Salida");gotoxy(5,23);cprintf("Elija en numero de la opción deseada ***> "); i=1; ch=getch(); switch(ch) { case '4':clrscr();salida();exit(); case '3':clrscr();visualizar();break; case '2':clrscr();modificar();break; case '1':clrscr();anadir();break; } menú();} main() { nosound(); entrada(); menú(); fcloseall(); exit();} entrada() {clrscr();textbackground(WHITE);textcolor(BLACK);clrscr();textbackground(WHITE);textcolor(BLACK); gotoxy(27,1);cprintf("INSTITUTO TECNICO CENTRAL"); gotoxy(36,2); cprintf("LA SALLE"); gotoxy(36,5);cprintf("Archivos"); gotoxy(33,8); cprintf("Presentado A:"); gotoxy(31,9); cprintf("Manuel A.Montero");gotoxy(30,12);cprintf("Numero de Lista: 30"); gotoxy(37,15);cprintf("Curso:");gotoxy(36,16); cprintf("Noveno F"); gotoxy(36,19); cprintf("Alumno:");gotoxy(23,20);cprintf("ESPECIALIDAD DE SISTEMAS");gotoxy(16,23); cprintf("Santafe de Bogota D.C., 15 de Septiembre de 1992"); printf("\a"); getch(); clrscr(); textcolor(RED);textbackground(GREEN); clrscr(); gotoxy(36,9); cprintf("ARCHIVOS");gotoxy(10,13); cprintf("Este programa archiva en el disco datos de una persona.");gotoxy(5,24); textcolor(BLUE+BLINK);cprintf("Pulse cualquier tecla para continuar . . . \a");getch(); clrscr();} salida(){clrscr();window (1,1,80,25); textbackground (MAGENTA);clrscr();highvideo();textcolor(BLUE);gotoxy(1,5); cprintf ("adios ");sound(300);sound(9000);sound(8000);sound(7000); sound(6000);sound(5000);sound(4000);sound(3000); sound(2000);sound(100);sound(500);sound(400); sound(300);sound(300);sound(5000);sound(300); sound(9000);sound(8000);sound(7000);sound(6000); sound(5000);sound(4000);sound(3000);sound(2000); sound(100);sound(500);sound(400);sound(300); sound(300);sound(5000);nosound();getch();} 7.3 ARCHIVOS A NIVEL DE UNIX (BAJO NIVEL) Las funciones que se utilizan para la entrada y salida de datos en bajo nivel no utilizan buffers y no dan formato a los datos. se utiliza un descriptor de archivos el cual es un entero positivo asociado a un archivo. Nombre del archivo Descriptor stdin 0 entrada estandar (teclado) stdout 1 salida estandar (pantalla) stderr 2 error estandar (pantalla) stdprn impresion estandar (paralelo) stdaux auxiliar esstandar (serie) Los dos ultimos archivos depende de la maquina si esta en serie o en paralelo, por lo tanto pueden o no estar presentes. 68
7.4 FUNCIONES PARA EL MANEJO DE ARCHIVOS Creat (nombre_archivo,protección) : devuelve un descritor de archivo, si falla, devuelve -1. si ya existe el archivo nombrado, se trunca a la longitud cero; de lo contrario, se crea un nuevo archivo con la protección especificada; esta protección se define con codigos octales de tres digitos. Open(nombre_archivo,acceso,[pmodo]): Devuelve un descriptor de archivo, o -1 si falla, el acceso es 0 para leer, 1 para escribir y 2 para ambas acciones. Todas las referencia al archivo se deben hacer al traves del descriptor de archivos. El argumento acceso, es una expresión entera formada por una o mas constantes separadas por el operador |. Estas constantes definidas en fcntl.h son las siguientes. CONSTANTE O_APPEND O_BINARY O_CREAT O_EXCL O_RDONLY O_RDW O_TEXT O_TRUNC O_WRONLY
SIGNIFICADO Abre un fichero para añadir información al final del mismo. Abre un fichero en modo binario. Crea un nuevo archivo para escribir. si el archivo existe esto no tiene efecto. Solamente se utiliza con O_CREAT. Devuelve un número de error si el Archivo existe. Abre un archivo solo para leer. No se puede utilizar con O_RDWR o O_WRONLY. Abre un archivo para leer y escribir. No se puede utilizar con O_RDONLY o O_WRONLY. Abre un archivo en modo texto. Abre un archivo existente, destruyendo su contenido. El archivo debe tener permiso de escritura. Abre un archivo solo para escribir
El argumento pmodo, solamente es necesario con la constante O_CREAT para indicar el permiso dado al archivo, si el archivo existe este argumento es ignorado. PERMISO S_IWRITE S_IREAD S_IREAD|S_IWRITE
SIGNIFICADO Permiso de escritura Permiso de lectura Permiso de lectura y escritura
Close (fd): cierra el archivo abierto, fd es un descritor de archivo. Si un archivo esta cerrado, se devuelve 0; de lo contrario, se devuelve -1 como muestra del falló. Read(fd,buffer,n): Se utiliza para leer n bytes, almacenados en el buffer, que por lo general es un arreglo de caracteres cuyo tamaño es suficiente para contener n bytes, en el archivo cuyo descriptor es fd. Write (fd,buffer,n): Se utiliza para escribir n bytes en el buffers, en archivo cuyo descriptor es fd. Lseek(fd,desplazamiento,lugar): Mueve el puntero de L/E asociado con el archivo abierto con el descriptor fd, a una nueva localización dada por desplazamiento que es un entero (bytes), puede ser negativo, cero o positivo, lugar es un entero que puede ser uno, dos o cero, según la posición del archivo actual. 69
Ahora veamos un ejemplo muy simple que es el ingreso de pacientes en una clinica nn, y el sistema de historias clinicas. Ejemplo #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <ctype.h> #include <io.h> #include <fcntl.h> #define SEEK_END 2 #define SEEK_CUR 1 struct x { char nom[30],dir[30],sexo[15],tra[30],fec[15]; char enfer[20],tipo[15],tel[15],fecha[15]; char cedu[20],ape[15]; float abo,sal,tot; int con,ed,res,anes;};struct x reg; struct y {char nomm[30],dirr[30],sexoo[15],traa[30]; char fecc[15];char enferr[20],tipoo[15],tell[15],fechaa[15]; char ceduu[20], apee[15]; float aboo,sall,tott; int conn,edd,ress,aness;}; struct y reg1; char sw1; int opci,opc,cont,j,fd,conta,c,sw,op,i,da,cont;mas, cad, vl, char arti[30],nn[30],d[30],cn[30],n[30]; char *nb, *mayusculas(char *); char t[15],f[15],fech[15]; float total;
tl,encon;
recuadro(){ int i; textcolor(14);textbackground(0);textcolor(0); textbackground(7); gotoxy(1,1);cprintf("╔"); gotoxy(80,1);cprintf("╗");gotoxy(1,24);cprintf("╚");gotoxy(80,24);cprintf("╝");textcolor(14); textbackground(0); for(i=2;i<=79;i++){ textcolor(0);textbackground(7); gotoxy(i,1);cprintf("═"); gotoxy(i,24);cprintf("═");} textcolor(14);textbackground(0); for(i=2;i<=23;i++){ textcolor(0);textbackground(7);gotoxy(1,i);cprintf("║");gotoxy(80,i);cprintf("║");}textcolor(14); textbackground(0);} cre(){ opc=1; while (opc<=2) { clrscr();recuadro(); textcolor(0);textbackground(7);gotoxy(25,4); cprintf("*** M E N U M E N S A J E ***"); textcolor(14);textbackground(0);gotoxy(20,7); printf("1. CREAR");gotoxy(20,9);printf("2. ADICIONAR"); gotoxy(20,11);printf("3. REGRESAR AL MENU"); textcolor(0);textbackground(7);gotoxy(22,23); cprintf("Digite su opción: "); scanf("%d",&opc); textcolor(14);textbackground(0); switch (opc) { case 1:crear(); break; case 2:adi();break; } } } crear(){ clrscr();recuadro();if ( (da=_creat("a:droga.dat",0))==-1)
70
{ puts("ERROR EN CREACION DE ARCHIVO"); exit(1);getche(); } else {i=1;cont=0; while(i==1) { clrscr();recuadro();textcolor(0); textbackground(7); gotoxy(22,5);cprintf("H I S T O R I A C L I N I C A"); textcolor(14);textbackground(0); cont++; gotoxy(40,7);printf("N. DE HISTORIA -->%d",cont); reg.con=cont;gotoxy(20,9);printf("NOMBRE: "); scanf("\n");gets(n);strcpy(reg.nom,mayusculas(n)); gotoxy(20,10);printf("APELLIDO: ");scanf("\n"); gets(reg.ape);gotoxy(20,11);printf("CEDULA O TARJETA: "); scanf("\n");gets(reg.cedu);gotoxy(20,12);printf("EDAD: "); scanf("%d",&reg.ed);gotoxy(20,13);printf("ENFERMEDAD: "); scanf("\n");gets(reg.enfer);gotoxy(20,14);printf("DIRECCION : "); scanf("\n"); gets(reg.dir); gotoxy(20,15); printf("TELEFONO : "); scanf("\n");gets(reg.tel);gotoxy(20,16);printf("OPERADO (SI=1/NO=2): "); scanf("%d",&reg.res); gotoxy(20,17);printf("ANESTECIA (SI=1/NO=2): "); scanf("%d",&reg.anes);gotoxy(20,18);printf("TIPO DE SANGRE: "); scanf("\n");gets(reg.tipo); gotoxy(20,19);printf("SEXO: "); scanf("\n");gets(reg.sexo); gotoxy(23,23);printf("Pulse una <<tecla>> para continuar");getche(); clrscr();recuadro(); gotoxy(20,12);printf("Desea continuar S=1 / N=2 : "); scanf("%d",&i);gotoxy(23,20);printf("Pulse una <<tecla>> para continuar");getche(); if( (_write(da,(char*)&reg,sizeof(reg))) != sizeof(reg)) { puts("ERROR EN GRABACION");exit(1);getche();}}} close(da); } char *mayusculas(char alis[30]) { char henry[30]; int y,x,h,cont; for (i=0;i<=strlen(alis);i++) { alis[i] =toupper(alis[i]);} strcpy(henry,alis); return(henry); } adi() { sw1='S'; encon=0; while (sw1=='S') { if ((da=_open("a:droga.dat",4))==-1) { clrscr();recuadro();gotoxy(32,12);printf("ERROR EN APERTURA");gotoxy(80,24);delay(3000);exit(1); } sw=0;clrscr();recuadro(); textcolor(0);textbackground(7); gotoxy(30,5);cprintf("ADICION");textcolor(14); textbackground(0);gotoxy(10,10);printf("Digite nombre -->"); scanf("\n");gets(cn); mayusculas(cn); encon=0; while ( (_read(da,(char*)&reg,sizeof(reg))!=0)) {sw++; cont=reg.con;cont++; if ( (strcmp(reg.nom,cn) == 0) ){encon=1;clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("REGISTRO YA EXISTENTE"); textcolor(14);textbackground(0); getche(); } } if(encon==0){clrscr();recuadro();textcolor(0); textbackground(7);gotoxy(22,5);cprintf("AD I C I O N D E D A T O S");textcolor(14);textbackground(0); strcpy(reg.nom,mayusculas(cn));gotoxy(40,7);printf("N. DE HISTORIA -->%d",cont); reg.con=cont;gotoxy(20,10);printf("APELLIDO:");scanf("\n"); gets(reg.ape);gotoxy(20,11);printf("CEDULA O TARJETA:"); scanf("\n");gets(reg.cedu); gotoxy(20,12);printf("EDAD:"); scanf("%d",&reg.ed);gotoxy(20,13);printf("ENFERMEDAD:");scanf("\n"); gets(reg.enfer);gotoxy(20,14);printf("DIRECCION : "); scanf("\n");gets(reg.dir);gotoxy(20,15); printf("TELEFONO:");scanf("\n");gets(reg.tel);gotoxy(20,16);printf("OPERADO (SI=1/NO=2):"); scanf("%d",&reg.res);gotoxy(20,17);printf("ANESTECIA (SI=1/NO=2): ");scanf("%d",&reg.anes); gotoxy(20,18);printf("TIPO DE SANGRE: "); scanf("\n");gets(reg.tipo);gotoxy(20,19);printf("SEXO:"); scanf("\n");gets(reg.sexo);gotoxy(23,23);printf("Pulse una <<tecla>> para continuar");getche(); if(lseek(da,(long)sizeof(reg)*(sw),0)==-1){clrscr();recuadro();gotoxy(32,12);printf("ERROR EN BUSQUEDA");gotoxy(80,24);delay(3000);exit(1);}if(write(da,(char*)&reg,sizeof(reg))==-1){clrscr();recuadro ();gotoxy(32,12);printf("ERROR EN ESCRITURA");gotoxy(80,24);getche();exit(1); }gotoxy(30,21); cprintf(" "); } do {gotoxy(15,20);printf("Desea adicionar mรกs datos S/N -->"); gotoxy(55,20);sw1=toupper(getche());}while((sw1!='S') && (sw1!='N'));close(da); } } buscar() { mas=1; while (mas==1) { if ((da=_open("a:droga.dat",1))==-1) {clrscr();recuadro();gotoxy(32,12); 71
printf("ERROR EN APERTURA");gotoxy(80,24);exit(1);getche(); }else {clrscr();recuadro(); textcolor(0);textbackground(7);gotoxy(30,5);cprintf("BUSQUEDA");textcolor(14);textbackground(0); gotoxy(10,10);printf("Digite nombre -->"); scanf("\n");gets(cn); mayusculas(cn); encon=0; while ( (_read(da,(char*)&reg,sizeof(reg))!=0)){if (strcmp(reg.nom,cn) == 0){clrscr();recuadro(); gotoxy(30,3);printf("BUSQUEDA");gotoxy(22,8);printf("NOMBRE");gotoxy(22,9);printf("APELLIDO"); gotoxy(22,10);printf("CEDULA O TARJETA");gotoxy(22,11);printf("EDAD");gotoxy(22,12); printf("ENFERMEDAD");gotoxy(22,13);printf("DIRECCION");gotoxy(22,14);printf("TELEFONO");gotoxy(22, 15);printf("OPERADO");gotoxy(22,16);printf("ANESTECIA");gotoxy(22,17);printf("TIPO DE SANGRE"); gotoxy(22,18);printf("SEXO");textcolor(0);textbackground(7); gotoxy(37,8);cprintf("%s",reg.nom);gotoxy(37,9);cprintf("%s",reg.ape);gotoxy(37,10);cprintf("%s",reg.cedu); gotoxy(37,11);cprintf("%d",reg.ed);gotoxy(37,12);cprintf("%s",reg.enfer);gotoxy(37,13);cprintf("%s",reg.dir); gotoxy(37,14);cprintf("%s",reg.tel);gotoxy(37,15);cprintf("%d",reg.res);gotoxy(37,16);cprintf("%d",reg.anes); gotoxy(37,17);cprintf("%s",reg.tipo);gotoxy(37,18);cprintf("%s",reg.sexo);textcolor(14);textbackground(0);g otoxy(80,24);getche(); encon=1;} }if (encon==0){ clrscr();recuadro();textcolor(0); textbackground(7);gotoxy(32,12);cprintf("REGISTRO NO ENCONTRADO");textcolor(14); textbackground(0);getche();}clrscr();recuadro(); gotoxy(30,5);printf("BUSQUEDA"); do{gotoxy(15,12); printf("Desea realizar mas busquedas si(1)/no(2) -->"); gotoxy(60,12); scanf("%d",&mas); }while((mas<1) && (mas>2));} close(da); }} modificar(){mas=1;sw=0;while(mas==1){if((da=_open("a:droga.dat",4))==-1){ clrscr();recuadro();gotoxy(32,12);printf("ERROR EN APERTURA"); gotoxy(80,24); exit(1); getche(); } clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(30,5);cprintf("MODIFICACION");textcolor(14); textbackground(0); gotoxy(10,10);printf("Digite nombre-->"); scanf("\n");gets(cn);mayusculas(cn); encon=0;sw=0; while((_read(da,(char*)&reg,sizeof(reg))!=0)){sw++; if( strcmp(reg.nom,cn) == 0){clrscr(); recuadro();gotoxy(30,3);printf("MODIFICACION");gotoxy(22,8);printf("NOMBRE");gotoxy(22,9);printf("APE LLIDO");gotoxy(22,10);printf("CEDULA O TARJETA");gotoxy(22,11); printf("EDAD");gotoxy(22,12); printf("ENFERMEDAD");gotoxy(22,13);printf("DIRECCION");gotoxy(22,14);printf("TELEFONO"); gotoxy(22,15);printf("OPERADO"); gotoxy(22,16);printf("ANESTECIA");gotoxy(22,17); printf("TIPO DE SANGRE");gotoxy(22,18);printf("SEXO");textcolor(0); textbackground(7); gotoxy(37,8);cprintf("%s",reg.nom);gotoxy(37,9);cprintf("%s",reg.ape);gotoxy(37,10);cprintf("%s",reg.cedu); gotoxy(37,11);cprintf("%d",reg.ed);gotoxy(37,12);cprintf("%s",reg.enfer);gotoxy(37,13);cprintf("%s",reg.dir); gotoxy(37,14);cprintf("%s",reg.tel);gotoxy(37,15);cprintf("%d",reg.res);gotoxy(37,16);cprintf("%d",reg.anes); gotoxy(37,17);cprintf("%s",reg.tipo);gotoxy(37,18);cprintf("%s",reg.sexo);textcolor(14); textbackground(0);gotoxy(25,20);printf("PULSE <ENTER> PARA CONTINUAR.... "); getche(); gotoxy(25,20);printf(" ");encon=1; j=1; while (j==1) { gotoxy(5,20);printf("1.Nombre 2.Apellido 3.C.C. tarj 4.Edad 5. Enfermedad" ) ; gotoxy(3,21);printf("6.Direcci贸n 7.Telefono 8.Operado 9.Anestecia 10.T.sangre 11.Sexo");gotoxy(25,22);printf("Digite campo a modificar: ");scanf("%d",&c); getche();if (c==1) {gotoxy(10,21);printf(" ");gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite nuevo nombre : ");gotoxy(37,6);printf(" "); gotoxy(37,8);scanf("\n");gets(n);strcpy(reg.nom,mayusculas(n));gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... ");getche(); if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1){ clrscr();recuadro();textcolor(0);textbackground(7);gotoxy(32,12);cprintf("ERROR EN BUSQUEDA"); textcolor(14);textbackground(0);getche(); } if (_write(da,(char*)&reg,sizeof(reg)) == -1){ clrscr();recuadro();textcolor(0);textbackground(7);gotoxy(32,12);cprintf("ERROR EN ESCRITURA"); textcolor(14);textbackground(0);exit(1);gotoxy(25,23);printf("PULSE<ENTER> PARA CONTINUAR.... "); getche();} }if (c==2) { gotoxy(10,21);printf(" "); gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite nuevo apellido "); gotoxy(37,8);printf(" "); gotoxy(37,9);scanf("\n"); gets(reg.ape);gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... "); getche();if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1) { clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0);getche(); } if (_write(da,(char*)&reg,sizeof(reg)) == -1){clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0);exit(1);getche();}} 72
if (c==3) {gotoxy(10,21);printf(" ");gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" ");gotoxy(20,21); printf("Digite nuevo C.C o tarj.: ");gotoxy(37,10);printf(" ");gotoxy(37,10);scanf("\n");gets(reg.cedu); gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... ");getche();if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1){clrscr();recuadro();textcolor(0); textbackground(7);gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0); getche();}if (_write(da,(char*)&reg,sizeof(reg)) == -1) {clrscr();recuadro();textcolor(0); textbackground(7);gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0); exit(1);getche();}}if (c==4) {gotoxy(10,21);printf(" ");gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite nuevo edad: ");gotoxy(37,12);printf(" ");gotoxy(37,11);scanf("%d",&reg.ed); gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... "); getche();if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1) {clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0);getche(); } if (_write(da,(char*)&reg,sizeof(reg)) == -1) {clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0);exit(1);getche();} } if (c==5) {gotoxy(10,21);printf(" ");gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite Enfermedad: ");gotoxy(37,14);printf(" ");gotoxy(37,12);scanf("\n"); gets(reg.enfer);gotoxy(25,23);printf("PULSE<ENTER>PARACONTINUAR.... ")getche(); if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1){ clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14); textbackground(0);getche(); } if (_write(da,(char*)&reg,sizeof(reg)) == -1){clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0); exit(1);getche();} } if (c==6) {gotoxy(10,21);printf(" "); gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" ");gotoxy(20,21); printf("Digite nueva Direcci贸n: ");gotoxy(37,16);printf(" ");gotoxy(37,13);scanf("\n");gets(reg.dir); gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... "); getche(); if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1) {clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14); textbackground(0);getche();} if(_write(da,(char*)&reg,sizeof(reg)) == -1) {clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0);exit(1);getche();} } f (c==7) {gotoxy(10,21);printf(" ");gotoxy(40,21);printf(" "); gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite nuevo Telefono: ");gotoxy(37,16);printf(" "); gotoxy(37,13);scanf("\n"); gets(reg.tel);gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... ");getche(); if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1){clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0);getche(); } if (_write(da,(char*)&reg,sizeof(reg)) == -1) {clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0);exit(1);getche(); } } if (c==8) {gotoxy(10,21);printf(" "); gotoxy(40,21);printf(" );gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite Operado: ");gotoxy(37,16);printf(" ");gotoxy(37,13);scanf("%d",&reg.res); gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... "); getche();if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1){clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0);getche(); } if (_write(da,(char*)&reg,sizeof(reg)) == -1){clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA");textcolor(14);textbackground(0);exit(1);getche(); } } if (c==9) {gotoxy(10,21);printf(" ");gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite Anestecia:");gotoxy(37,16);printf(" ");gotoxy(37,13);scanf("%d",&reg.anes); gotoxy(25,23);printf("PULSE <ENTER> PARA CONTINUAR.... "); getche(); if ( lseek (da, (long) sizeof (reg)*(sw-1),0)==-1){clrscr();recuadro();textcolor(0);textbackground(7);gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0);getche();}If (_write(da,(char*)&reg,sizeof(reg)) == -1){ clrscr();recuadro();textcolor(0);textbackground(7);gotoxy(32,12);cprintf("ERROR EN ESCRITURA"); textcolor(14);textbackground(0);exit(1);getche(); } }if (c==10) {gotoxy(10,21);printf(" "); gotoxy(40,21);printf(" ");gotoxy(25,22);printf(" ");gotoxy(20,21);printf("Digite Tipo de sangre: "); gotoxy(37,16);printf(" ");gotoxy(37,13);scanf("\n");gets(reg.tipo);gotoxy(25,23); printf("PULSE <ENTER> PARA CONTINUAR...") getche();if(lseek(da,(long)sizeof(reg * (sw-1), 0)== -1 ) 73
{clrscr();recuadro();textcolor(0);textbackground(7);gotoxy(32,12);cprintf("ERROR EN BUSQUEDA"); textcolor(14);textbackground(0);getche();}if (_write(da,(char*)&reg,sizeof(reg)) == -1){clrscr();recuadro(); textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA"); textcolor(14); textbackground(0); exit(1);getche();} } if (c==11) { gotoxy(10,21);printf(" "); gotoxy(40,21);printf(" "); gotoxy(25,22);printf(" "); gotoxy(20,21);printf("Digite Tipo de sangre: "); gotoxy(37,16);printf(" "); gotoxy(37,13);scanf("\n");gets(reg.tipo);gotoxy(25,23);printf("PULSE<ENTER PARA CONTINUAR.... "); getche(); if (lseek(da,(long)sizeof(reg)*(sw-1),0)==-1){clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN BUSQUEDA");textcolor(14);textbackground(0);getche();} if (_write(da,(char*)&reg,sizeof(reg)) == -1) {clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(32,12);cprintf("ERROR EN ESCRITURA"); textcolor(14);textbackground(0); exit(1);getche();}} gotoxy(10,21);printf(" "); gotoxy(40,21);printf(" "); gotoxy(25,22);printf(" ");gotoxy(25,22); printf("Desea modificar mas campos S=1/N=2: ");scanf("%d",&j); } } }if (encon==0) {clrscr();recuadro(); textcolor(0);textbackground(7);gotoxy(32,12);cprintf("REGISTRO NO ENCONTRADO");textcolor(14); textbackground(0);getche();}clrscr();recuadro();gotoxy(20,5);printf("MODIFICACION DEL PACIENTE"); do {gotoxy(18,12);printf("Desea modificar mas registros si(1)/no(2) -->"); gotoxy(62,12); scanf("%d",&mas);} while ((mas<1) || (mas>2)); }close(da);} /*fin e modificacion*/ reporte(){clrscr();recuadro();if((da=_open("a:droga.dat",1))==-1){puts("ERROR EN CREACION DE ARCHIVO"); exit(1); getche(); } else {while ( (_read(da,(char*)&reg,sizeof(reg)))!=0){clrscr(); recuadro(); textcolor(0);textbackground(7);gotoxy(15,5);printf("R E P O R T E D E R E G I S T R O S ");textcolor(14);textbackground(0);gotoxy(20,8);printf("NOMBRE");puts(reg.nom);gotoxy(20,10);printf(" APELLIDO:");puts(reg.ape);gotoxy(20,11);printf("CEDULA O TERJETA: "); puts(reg.cedu); gotoxy(20,12); printf("EDAD: %d",reg.ed);gotoxy(20,13);printf("ENFERMEDAD: "); puts(reg.enfer);gotoxy(20,14); printf("DIRECCION : "); puts(reg.dir);gotoxy(20,15);printf("TELEFONO : "); puts(reg.tel);gotoxy(20,16); printf("OPERADO: %d",reg.res);gotoxy(20,17);printf("ANESTECIA: %d",reg.anes);gotoxy(20,18); printf("TIPO DE SANGRE: "); puts(reg.tipo);gotoxy(20,19);printf("SEXO: ");puts(reg.sexo); gotoxy(25,23);printf("Pulse una <<tecla>> para continuar");getche();}} close(da); } costo(){ mas=1; while (mas==1) {if ( (fd=_creat("a:droga1.dat",0))==-1) {puts("ERROR EN CREACION DE ARCHIVO"); exit(1);getche(); }if((da=_open("a:droga.dat",1))==-1) {clrscr(); recuadro(); gotoxy(32,12); printf("ERROR EN APERTURA");gotoxy(80,24);exit(1);getche(); }else {clrscr();recuadro();textcolor(0); textbackground(7);gotoxy(30,5);cprintf("LIQUIDACION DE TRATAMIENTO");textcolor(14); textbackground(0); gotoxy(10,10); printf("Digite nombre -->"); scanf("\n"); gets(cn);mayusculas(cn); encon=0;while ( (_read(da,(char*)&reg,sizeof(reg))!=0)){if (strcmp(reg.nom,cn) == 0){ clrscr(); recuadro(); textcolor(0); textbackground(7); gotoxy(32,8); cprintf("LIQUIDACION DE TRATAMIENTO"); textcolor(14);textbackground(0); gotoxy(20,10); printf("TRATAMIENTO:");scanf("\n");gets(reg1.traa);gotoxy(20,11); printf("VALOR DE CONSULTA: "); scanf("%f",&reg1.tott);gotoxy(20,12);printf("ABONO: "); scanf("%f",&reg1.aboo)gotoxy(20,13); printf("FECHA: "); scanf("\n"); gets(reg1.fecc); total=(reg1.tott-reg1.aboo);gotoxy(20,14);printf("SALDO: %.2f",total);reg1.sall=total;gotoxy(20,23);printf("Pulse una tecla para continuar ");getche(); if (lseek(fd,(long)sizeof (reg1)*(sw),0)==-1){clrscr();recuadro();gotoxy(32,12);printf("ERROR EN BUSQUEDA");gotoxy(80,24);delay(3000);exit(1); }if (write(fd,(char*)&reg1,sizeof(reg1))==-1) { clrscr();recuadro();gotoxy(32,12);printf("ERROR EN ESCRITURA");gotoxy(80,24);getche();exit(1); } gotoxy(30,21);cprintf("");gotoxy(80,24);encon=1;} }if (encon==0) {clrscr(); recuadro(); textcolor(0); textbackground(7);gotoxy(32,12);cprintf("REGISTRO NO ENCONTRADO");textcolor(14); textbackground(0);getche(); } clrscr();recuadro(); gotoxy(30,5); printf("COSTO"); do{gotoxy(15,12); printf("Desea realizar mas liquidaciones si(1)/no(2) -->");gotoxy(63,12);scanf("%d",&mas);}while ((mas<1) && (mas>2)); } } close(fd);} factura() {opci=1;while(opci<=2) {clrscr();recuadro();textcolor(0);textbackground(7);gotoxy(25,4); 74
printf(" *** M E N U F A C T U R A ***");textcolor(14); textbackground(0); gotoxy(20,7); printf("1.PANTALLA");gotoxy(20,9);printf("2.IMPRESORA");gotoxy(20,11);printf("3.REGRESAR AL MENU"); textcolor(0);textbackground(7);gotoxy(22,23);cprintf("Digite su opci贸n: "); scanf("%d",&opci); textcolor(14);textbackground(0); switch(opci) { case 1: pant();break; case 2:impre(); break; } }} pant() { mas=1; while(mas==1) {if ((da=_open("a:droga.dat",1))==-1) {clrscr();recuadro(); gotoxy(32,12); printf("ERROR DE APERTURA"); gotoxy(80,24);exit(1); } if ((fd=_open ("a:droga1.dat",1))==-1){ clrscr();recuadro();gotoxy(32,12);printf("ERROR DE APERTURA"); gotoxy(80,24);exit(1); }else {clrscr(); recuadro();textcolor(0);textbackground(7); gotoxy(23,5);cprintf("R E P O R T E P O R P A N T A L L A");textcolor(14);textbackground(0); gotoxy(10,10);printf("Digite nombre -->"); scanf("\n"); gets(cn);mayusculas(cn); encon=0; while((_read(da,(char*)&reg,sizeof(reg))!=0)){if(strcmp(reg.nom,cn)==0){ clrscr();recuadro(); textcolor(0); textbackground(7);gotoxy(25,3);cprintf("R E P O R T E P O R P A N T A L L A");textcolor(14); textbackground(0);gotoxy(60,5);printf("FECHA %s",reg1.fecc);gotoxy(15,7);printf("NOMBRE: "); puts(reg.nom);gotoxy(45,7);printf("APELLIDO: "); puts(reg.ape);gotoxy(15,9);printf("CEDULA: %s",reg.cedu);gotoxy(45,9);printf("EDAD: %d",reg.ed);gotoxy(15,11);printf("DIRECCION %s",reg.dir); gotoxy(45,11);printf("TELEFONO: %s",reg.tel);gotoxy(15,13);printf("TRATAMIENTO: "); puts(reg1.traa); gotoxy(15,15);printf("COSTO %.2f",reg1.tott);gotoxy(45,15);printf("ABONO %.2f",reg1.aboo); gotoxy(15,17);printf("SALDO %.2f",reg1.sall);gotoxy(23,20);printf("Pulse una <<tecla>> para continuar"); getche();encon=1;}}if(encon==0){clrscr();recuadro();gotoxy(20,23);printf("REGISTRONOENCONTRADO"); getche();}clrscr();recuadro();gotoxy(20,12);printf("Desea verificar mas reportes (SI=1/NO=2):"); do{gotoxy(63,12);scanf("%d",&mas);}while((mas<1)&& (mas>2)); } } close(da);close(fd); } impre(){ mas=1; while(mas==1) {if ((da=_open ("a:droga.dat",1))==-1){ clrscr();recuadro(); gotoxy(32,12);printf("ERROR DE APERTURA");gotoxy(80,24); exit(1);} if ((fd=_open ("a:droga1.dat",1))==-1) { clrscr();recuadro();gotoxy(32,12);printf("ERROR DE APERTURA"); gotoxy(80,24); exit(1);} else { clrscr();recuadro();textcolor(0);textbackground(7); gotoxy(23,5);cprintf("R E P O R T E POR I M P R E S O R A"); textcolor(14); textbackground(0); gotoxy(10,10);printf("Digitenombre-->"); scanf("\n"); gets(cn);mayusculas(cn);encon=0;while((_read(da,(char*)&reg,sizeof(reg))!=0)){if(strcmp(reg.nom,cn)==0) {clrscr();recuadro();gotoxy(23,12);printf("POR FAVOR CONECTE LA IMPRESORA"); gotoxy(23,20); printf("Pulse una <<tecla>> para continuar"); getche(); fprintf(stdprn,"%s\n\r",reg1.fecc); fprintf(stdprn,"%s\n\r",reg.nom);fprintf(stdprn,"%s/n/r",reg.ape);fprintf(stdprn,"%s/n/r",reg.cedu);fprintf(stdpr n,"%d/n/r",reg.ed);fprintf(stdprn,"%s/n/r",reg.dir);fprintf(stdprn,"%s/n/r",reg.tel);fprintf(stdprn,"%s/n/r",reg1.tr aa);fprintf(stdprn,"%.2f/n/r",reg1.tott);fprintf(stdprn,"%.2f/n/r",reg1.aboo);fprintf(stdprn,"%.2f/n/r",reg1.sall);g otoxy(23,20);printf("Pulse una <<tecla>> para continuar"); getche();encon=1;} }if (encon==0) {clrscr(); recuadro();gotoxy(20,23);printf("REGISTRO NO ENCONTRADO"); getche();}clrscr();recuadro(); gotoxy(20,12);printf("Desea imprimir mas reportes(SI=1/NO=2): "); do{gotoxy(63,12); scanf("%d",&mas); } while ((mas<1) &&(mas>2)) ;}}close(da); close(fd); } main() { op=1; while (op<=5) { clrscr();recuadro();textcolor(0); textbackground(7); gotoxy(25,4); cprintf("*** M E N U P R I N C I P A L ***"); gotoxy(26,5); cprintf("C L I N I C A L O S D O L O R E S"); textcolor(7);textbackground(0);gotoxy(20,7);printf("1. CREAR");gotoxy(20,9); printf("2. COSTO");gotoxy(20,11); printf("3. BUSCAR");gotoxy(20,13);printf("4. MODIFICAR"); gotoxy(20,15);printf("5. FACTURA");gotoxy(20,17); printf("6.TERMINAR."); textcolor(0); textbackground(7); gotoxy(22,23);cprintf("Digite su opci贸n: "); scanf("%d",&op);textcolor(7); textbackground(0);switch (op) { case 1: cre();break; case 2: costo();break;case 3: buscar();break;case 4: modificar(); break;case 5:factura();break;}} }
8. ESTRUCTURAS DINAMICAS 75
LOGROS - Capacitar al estudiante para la manipulación de rutinas de ordenamiento y busqueda de elementos en un archivo y en matrices ya que el trabajo en aplicaciones tanto comerciales y educativas lo requiere. 8.1 METODOS DE ORDENACION Ordenar es el proceso de colocar los elementos de un arreglo o de un archivo en una secuencia dependiendo de un parámetro el cual puede ser que se ordene en orden ascendente o descendente. Algunos métodos de ordenación son: 8.1.1 METODO DE BURBUJA: Este método es el más conocido por todos y el más tedioso de los métodos de ordenamiento. Se le llama así porque con cada interacción el valor se desplaza de forma similar a como lo hace una burbuja, a la parte superior del array . Este método consiste en lo siguiente: Queremos ordenar los numeros 7 4 8 5 3 En la primera interacción de la ordenación realizaran cuatro evaluaciones. 7 4 8 5 3
7 4 8 5 3
7 4 8 5 3
7 4 8 5 3
El valor mas grande en el array (en orden ascendente) esta en la posición correcta después de la primera interacción, solamente se deben examinar los siguientes elementos del array. 4 7 5 3 8
4 5 7 8 3
4 5 7 3 8
En el tercer paso se cambian los siguientes elementos: ┌─┬─┬─┬─┬─┐ ┌──┬─┬─┬─┬─┐ │4│5│3│7│8│ │ 4│5│3│7│8│ └─┴─┴─┴─┴─┘ └──┴─┴─┴─┴─┘ y por ultimo tenemos: ┌─┬─┬─┬─┬─┐ ┌──┬─┬─┬─┬─┐ │4│3│5│7│8│ │ 3│4│5│7│8│ └─┴─┴─┴─┴─┘ └──┴─┴─┴─┴─┘ En esta forma llegamos al ordenamiento que queremos. Ahora procedemos a escribir el programa en Turbo C: burbuja(char *matriz, int cont) { register char k; register int x,y; for (x=1;x<cont;++x) for(y=cont-1;y>=x;k--y){ if(matriz[y-1]>matriz[y]){/*intercambio de elementos */ k=matriz[y-1]; matriz[y-1]=matriz[y]; matriz[y]=k; }}} 8.1.2 METODO SHELL
76
Este método se desarrollo por Donald Shell para llenar los vacíos que se presentan con el método de la burbuja en el ordenamiento de array. En este método se comparan elementos que están separados y luego elementos contiguos. ejemplo: Sea el array a[8]={1011,1088,1022,1077,1033,1066,0144,1055}; Utilizamos la variable mit=num_elementos/2 mit=8/2=4 luego los elementos se separaran inicialmente por un mit de 4. la primera interacción de la matriz compara todos los elementos separados en esta distancia. este proceso se repite hasta que no se produzca ningún cambio. 0 1 2 3 4 5 6 7 ┌──────┬────┬────┬─────┬─────┬─────┬─────┬─────┬ │ 1201 │1207│1231│1235 │1236 │1238 │1239 │1240 │ └──────┴────┴────┴─────┴─────┴─────┴─────┴─────┴ Una vez que no se produzcan intercambios con el mit debemos tomar otro mit que seria : mit=mit/2 y repetir el proceso hasta que no se produzca un nuevo cambio. El programa es: shell(matriz,numero,orden) array_tipo matriz[]; int numero; int(*orden)(); / puntero a la función de orden */ { int i; int cambio; */ FALSO si no se realizo ningún cambio */ int mit=numero/2; do{ do { cambio=FALSO; for (i=0;i<numero-mit;i++) if((*orden)(matriz[i],matriz[i+mit])) { ordena(&matriz[i],&matriz[i+mit]); cambio=VERDADERO; } } while(cambio);}while((mit/=2)>0);} Realizaremos la función de ordenamiento por orden creciente y decreciente, esta función devuelve el valor de VERDADERO si el contenido en x es mayor que el valor de y, en caso contrario proporciona el valor de FALSO. ascendente(x,y) array_tipo x,y;{return((x>y)?verdadero :falso);} descendente(x,y) array_tipo x,y; { return((x<y)?verdadero :falso);} 8.1.3 ORDENACION RAPIDA 77
La ordenación rápida es un procedimiento recursivo que aumenta la velocidad cuando el array se aproxime en 150 a 200 elementos. Este método de ordenación es el mas utilizado en el momento y es el más rápido debido que el divide el array en una lista de array más pequeños y ordenados. por ejemplo si tenemos el arrary a[9]={60,20,10,30,40,50,80,70,0};
Se selecciona el valor con la referencia del array[((comienzo+final)/2)] o en este caso el array[4], como su separador de lista. Cualquier valor en el array que sea menor que o igual al valor contenido dentro del separador de lista, se colocara en una lista y los valores que sean mayores se colocaran en una segunda lista.
La variable bajo se asigna al primer elemento en la lista. la variable alto esta asignada al último elemento de la lista, la variable bajo se incrementa hasta que array[bajo] contenga un valor que sea mayor que o igual al separador de lista ( el valor debe ser <= porque se trata de una ordenación en orden ascendente). while (array[bajo]<separador_lista)
Este proceso se realizara en cada sublista hasta que estas tengan un solo elemento. en ese punto se ordena el array. Realizamos la función de ordenamiento rápido : void rápida(char *matriz,int cont) { ord(matriz,0,cont-1); } void ord(char *matriz,int izq,int der) { register int i,j; char x,y; i=izq;j=der; x=matriz[(izq+der)/2]; do { while(matriz[i]<x && j<der) i++; while(x<matriz[j] && j>izq) j--; if (i<=j) {y=matriz[i]; matriz[i]=matriz[j]; matriz[j]=y; i++,j++;}} while(i<=j); if(izq<j) ord(matriz,izq,j); if(i<der) ord(matriz,i,der);} 8.2 BUSQUEDAD BINARIA
78
Una Busqueda Binaria es el algoritmo más simple de búsqueda. Se llama búsqueda binaria, la cual se realiza dividiendo cada array en su mitad y ese nuevo array en la mitad y así sucesivamaente hasta que se encuentre el registro. Para aplicar el algoritmo de Búsqueda binaria este debe estar ordenado en orden creciente. Ejemplo: Necesitamos conocer la especialidad de un estudiante con código 123.
Para encontrar secuencialmente el código del alumno 1231 debemos hacer 7 iteraciones o podemos utilizar el algoritmo de búsqueda binaria. Para este caso utilizaremos las siguientes variables: NE : FALSE cuando se encuentra el valor deseado. bajo: el elemento inferir del array. alto: el elemento mayor del array. valor : el valor que se esta buscando. medio : el elemento que se compara con el valor. El array entero se examina en la primera iteración de BB.(Búsqueda Binaria). Para esto tomamos el primer valor 0 del array y se lo asignamos a la variable bajo . (bajo=0), y la variable alto se le asigna el valor N-1. (10-1=9), podemos ahora calcular medio de la siguiente forma: medio=(bajo + alto)/2; Como esto es un valor entero ya que tenemos: medio=(9-0)/2=4
Si el valor contenido en medio es el valor buscado entonces le colocamos NE a FALSO. Esto es: f(array[medio]==valor) E=FALSO; Si el valor contenido en el array[medio] es mayor que 123, debemos entonces modificar el contenido de alto puesto que no hay motivo para buscar pasado ese punto en el array. Por ejemplo si se tiene el siguiente array:
79
Código 0 1 2 3 4 5 6 7 8 9 ┌────┬────┬────┬───┬───┬─────┬───┬───┬─────┬────┐ │121 │127 │123 │125│126│128 │129│140│145 │ 155│ └────┴────┴────┴───┴───┴─────┴───┴───┴─────┴────┘ bajo medio alto En este caso no es conveniente examinar los elementos contenidos desde medio hasta alto por que el valor no existe en ese rango. Luego debemos modificar alto para tener el nuevo rango de la siguiente forma: alto=medio-1; Esto nos da el rango : 0 1 2 3 ┌────┬──────┬─────┬─────┐ código │121 │ 127 │ 123 │125 │ └────┴──────┴─────┴─────┘ bajo medio alto además debemos preguntar de nuevo por quien es medio? medio=(alto + bajo)/2; Pero si el valor a buscar esta en la siguiente situación: código 0 1 2 3 4 5 6 7 8 9 ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │121│127│112│125│126│128│123│140│145│155│ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ bajo medio alto Entonces debemos ahora modificar el valor de bajo de la siguiente forma: if(array[medio]<valor ) bajo=medio+1; y obtendremos el siguiente rango: 5 6 7 8 9 ┌────┬──────┬─────┬─────┬────┐ código │128 │ 123 │ 140 │145 │155 │ └────┴──────┴─────┴─────┴────┘ bajo medio alto y de nuevo el valor del medio se modifica: medio=(alto + bajo)/2 Estas tres condiciones las podemos colocar así: if(array[medio]==valor) NE=FALSO; else if(array[medio]>valor) alto=medio-1; else if(array[medio]<=valor) bajo=medio+1; medio=(alto + bajo)/2;
80
Una vez que se encuentra el valor la variable NE le permite salir del bucle. Además debemos utilizar un procedimiento secundario para cuando el valor que estamos buscando no existe, por ejemplo: Si el array es:
código
0 1 2 ┌────┬──────┬─────┐ │128 │ 140 │ 145 │ └────┴──────┴─────┘ bajo medio alto
Y estamos buscando el número 123, la primera interacción produce:
Código
0 1 2 ┌────┬──────┬─────┐ │128 │ 140 │ 145 │ └────┴──────┴─────┘ bajo medio alto
La segunda produce:
Código
0 1 2 ┌────┬──────┬─────┐ │128 │ 140 │ 145 │ └────┴──────┴─────┘ bajo medio alto
La tercera produce:
código
0 1 2 ┌────┬──────┬─────┐ │128 │ 140 │ 145 │ └────┴──────┴─────┘ bajo medio alto
Y en esta parte se obtendrá un error que ya ha examinado 128. La rutina secundaria es: while(NE && alto >= bajo) { if (array[medio]==valor) NE=FALSO; else if(array[medio]>valor) alto=medio-1; else bajo =medio+1; medio=(alto+bajo)/2; } La función en general queda de la siguiente forma: búsqueda(matriz,numero,valor) int matriz[],numero,valor; {int alto=numero-1,bajo=0,medio=(alto+bajo)/2; int NE=TRUE; while(NE && alto >= bajo){if(matriz[medio]==valor) NE=FALSO; /*valor encontrado en la matriz */ else if(matriz[medio]>valor) alto=medio-1; else /* matriz[medio]<valor */ bajo =medio+1; medio=(alto+bajo)/2;}if (NE) return (-1);else return(medio);}
81
8.3 EJERCICIOS: 1. Ordenar un vector con 10 nombres en orden alfabético. 2. hallar la suma de un vector y su media aritmética. 3. hallar la varianza y la desviación estándar de
una población.
8.4 ESTRUCTURAS AUTOREFERENCIABLES En esta unidad estudiaremos un nuevo tipo de estructuras las cualese son referenciables a si mismo, recibiendo el nombre de autoreferenciables, en este tipo de estructuras encontramos las lista, pilas y arboles. las cuales estudiaremos a continuación. 8.5 LISTAS Una lista es una secuencia de elementos los cuales tienen la siguiente propiedad: Una estructura con un campo miembro que apunte al mismo tipo de estructura.
struct lista { int valor; struct lista *siguiente; } Esta lista nos permite definir un elemento de la siguiente forma: ┌───────┬─────────────┐ │ valor │*siguiente───┼──> └───────┴─────────────┘ La variable apuntadora siguiente contiene una dirección que puede ser: 1. El elemento subsiguiente que esta en memoria 2. El valor NULL ó 0. El valor NULL se utiliza para indicar el final de la lista. Si definimos dos elementos de tipo de la estructura tenemos: struct list *n, *m ;
De acuerdo con esta declaración tenemos: n=m; indica que n y m apuntan al mismo elemento, es decir al elemento apuntado por m. y la relación: *n = *m ; copia el contenido de la estructura apuntada por m en la estructura apuntada por n, y para imprimir
82
un dato contenido en algunas de las dos estructuras empleamos la siguiente sentencia: printf("%d",m-->valor); printf("%d",n-->valor); Ejemplo: struct lista m, n,r; Se realizarán algunas asignaciones en estas estructuras. m.valor = 3; n.valor = 4; r.valor = 5; m.siguiente = n.siguiente = r.siguiente = NULL Graficamente tenemos: Asignación m ┌───┬────┐ │ 3 │NULL│ └───┴────┘
n ┌───┬────┐ │ 4│NULL│ └───┴────┘
r ┌───┬────┐ │ 5│NULL│ └───┴────┘
Ahora, las colocamos en linea como una lista: m.siguiente=&n; n.siguiente=&r; r.siguiente=NULL; m n r ┌────┬────┐ ┌────┬────┐ ┌────┬────┐ │ 3 │ ───┼─────│ 4 │ ──┼── │ 5 │NULL│ └────┴────┘ └────┴────┘ └────┴────┘ m.siguiente-->valor; n.siguiente-->valor; y ahora, los enlaces permiten recuperar datos de los elementos subsiguientes; por tanto, m.siguiente -> valor tiene valor 4, y m. siguiente -> siguiente -> valor tiene valor 5. 8.6 LISTAS ENLAZADAS Una lista enlazada en forma lineal es como un tendedero en el que las estructuras de datos cuelgan en secuencia. Hay un apuntador inicial que apunta al primer elemento de la lista, y cada elemento apunta a uno subsiguiente; el último elemento tendrá un valor de enlace NULL. Creamos el siguiente archivo de cabecera el cula lo incluiremos en los ejemplos siguientes. Archivo para incluir "lista.h". # define NULL 0 struct lista_enlazada { char d; struct lista_enlazada *siguiente;}; typedef struct lista_enlazada BASE 83
typedef BASE *CONEXION; Al querer trabajar con un nuevo tipo de dato mas complejo que el tipo char lo unico que hacemos es cambiar char por el nuevo tipo de dato, tambien utilizamos la instrucción typedef la cual nos permite definir nuevos tipos de datos. Los cuales se pueden definir como: struct lista_enlazada BASE,*CONEXION; 8.7 ASIGNACIÓN DE ALMACENAMIENTO Las definiciones anteriores unicamente declaran y defininen variables de tipo autoreferenciables, pero en ningun momento asignan almacenamiento de memoria. El sistema puede asignar almacenamiento declarando variables y arreglos de tipo BASE . Para asignar almacenamiento en forma dinámica utilizamos la función estándar malloc () que se encuentra disponible en alloc.h y en stdlib.h. ╔═══════════════╗ ║malloc (size); ║ ╚═══════════════╝ devuelve un apuntador hacia un almacenamiento suficiente para un objeto de tamaño size bytes. El argumento a malloc () es unsigned y el valor devuelto es un apuntador a char. Si ca es una variable de tipo CONEXION,entonces ca=(CONEXION)malloc(sizeof(BASE)); obtiene del sistema una porción adecuada para almacenar un BASE y asigna su dirección al apuntador ca. Al igual que en el ejemplo anterior, se utiliza con un cast y el operador sizeof, pues si no hubiera un cast , se produciría un aviso de falta de concordancia entre los tipos, debido a que ca no es un apuntador a char. Si queremos disponer de ese espacio de memoria utilizamos la función free. ╔═══════════╗ ║ free(n); ║ ╚═══════════╝ Donde n es un apuntador a char. veamos un ejemplo de la s funciones anteriores. main(){ char *r,*z; int p=60; r=malloc(p); /* asigna el valor de 60 bytes */ pasar(r,"manuel");print("%s",r); z=malloc(p); pasar(z,"antonio");printf("%s",z); free(z);z=r; printf("esto es z =%s y esto es r = %s ",z,r);} pasar(char *m,char *n){
84
while(*m++==*n++);} Crearemos en forma dinámica una lista enlazada linealmente almacenando los siguientes nombres: pedro,pablo,juan. ca= (CONEXION) malloc(sizeof(BASE)): ca--> valor = "pedro"; ca--> siguiente = NULL; Se crea una lista de un solo elemento.
Creación dinámica de una lista ┌─────┬─────┐ ca .──── │pedro│ NULL│ └─────┴─────┘ Con las asignaciones siguientes se añade un segundo elemento. ca->siguiente=(CONEXION)malloc(sizeofBASE)); ca --> siguiente --> valor = "pablo"; ca--> siguiente --> siguiente = NULL; Ahora hay una lista de dos elementos. ┌─────┬──┐ ┌──────┬──────┐ ca.───>│pedro ─┼─>┤ pablo│ NULL │ └─────┴──┘ └──────┴──────┘ para terminar se añade el último elemento. ca-->siguiente=(CONEXION)malloc(sizeof(BASE)); ca--> siguiente --> siguiente --> valor = "juan"; ca--> siguiente --> siguiente --> siguiente =NULL; Ahora se tiene una lista de tres elementos hacia la cual apunta la cabeza ca termina el valor centinela NULL ┌─────┬─────┐ ┌─────┬─────┐ ┌─────┬─────┐ ca.--> │pedro│ ---│->│pablo│ ----│->│juan │ NULL│ └─────┴─────┘ └─────┴─────┘ └─────┴─────┘ 8.8 OPERACIONES CON LISTAS Algunas de las operacones básicas con listas lineales son las siguientes: 1. Creación de una lista. 2. Cuenta de los elementos. 3. Encadenamiento de dos listas 4. Busqueda de un elemento. 5. Inserción de un elemento. 6. Eliminación de un elemento. Cada función requiere las especificaciones del archivo lista h. En estos ejemplos, d podría redefinirse
85
como una estructura de datos arbitrariamente complicada. 8.8.1. Creación de una lista: Vamos a diseñar la función que nos permite crear listas en dos formas diferentes; una en forma recursiva y la otra en forma interativa. Diseñamos una función en forma interativa llamada crear_in que produzca una lista a partir de una cadena; la función devolverá un apuntador CONEXION a la cabeza de la lista resultante. El núcleo de la función crea un elemento lista al asignar almacenamiento y valores miembro a los elementos. #include "lista.h" CONEXION crear_in(char m[]){ CONEXION car,ca = NULL, fin; int i; if (m[0] !='\0') { /* primer elemento*/ ca =(CONEXION) malloc(sizeof(BASE)); ca -> d=m[0]; fin = car; for (i=1;m[i]!='\0';++i) { /* añadir a fin */ fin -> siguiente=(CONEXION)malloc(sizeof(BASE)); fin=fin ->siguiente; fin -> d = m[i]; } fin -> siguiente = NULL; /* finaliza la lista */ } return (ca);} Veamos con un ejemplo sencillo el manejo de esta función; pasar una cadena nula a crear_in(),se crea la lista vacia haciendo que la rutina regrese con valor NULL. La creación de la lista de un elemento se hace con la primera parte del programa. La lista de un elemento creada a partir de la cadena "R" se muestra en el siguiente diagrama. Este es el estado del proceso antes de asignar el valor NULL al miembro siguiente. ┌┬───> ┌───┬───┐ ca└┘ │ R │ ? │ ┌┬────>└───┴───┘ fin└┘ En el caso de dos elementos, "RT", la creación de la lista en un diagrama es: Primero se crea la lista de un elemento que contenga a 'R'; luego se ejecuta la proposición for en la que i tiene valor 1 y m[1] tiene valor 'T'; entonces,se asigna un nuevo elemento a la lista. ┌┐ ca └┘-->┌─────┬─────┐ ┌─────┬─────┐ ┌┐-->│ R │ ----│->│ ? │ ? │ fin└┘ └─────┴─────┘ └─────┴─────┘ La proposición fin=fin -> siguiente; hace avanzar a fin al nuevo elemento, después, se le asigna 'T' a su miembro d. actualización de la cola ┌┐ ca└┴──>
┌───┬───┐ ┌───┬───┐ │ R │ --│-->│ T │ ? │ └───┴───┘ └┬──┴───┘
86
├┐ fin └┘ Ahora m[2] tiene el valor \0, y la proposición for termina con una lista de dos elementos. Por último, el final de la lista se marca con un NULL. Asignación de un NULL ┌───┬────┐ ┌────┬────┐ │ R │ --│-->│ T │NULL│ └───┴────┘ └────┴────┘ │ ├┐ fin └┘
┌┐ ca└┴──>
Los valores de miembros sin definir se presentan porque a malloc() no se le pide que asigne a la memoria valor inicial 0. Ahora estamos en condiciones de diseñar la otra forma de la creación de listas, que es la función en forma recursiva; a esta función la llamamos crear_re() y utilizamos caso anterior una cadena de tipo char. #include "lista.h" CONEXION crear_re(char m[]){ CONEXION ca; if (m[0] == '\0') /* caso base */ return (NULL); else{ ca = (CONEXION) malloc (sizeof(BASE)); ca -> d= m[0]; ca->siguiente=crear_re (m+1); return (ca); }} Obsérvese una vez más cómo la recursión tiene un caso base, que es la creación de una lista vacía y un caso general, que es la creación del resto de la lista. La llamada recursiva genera; devuelve como valor un apuntador CONEXION a la sublista restante. 8.8.2. Contar los elementos de una lista Creamos las funciones contador () e imprimir() las cuales hacen todo un recorrido de la lista, la primera devolvera el numero de elmentos de la lista y la segunda nos imprimira cada uno de los elementos de la lista. #include <lista.h> contador (CONEXION ca){ if (ca ==NULL) return (0); else return (1+contador(ca -> siguiente));} De la misma forma la función imprima(), recorre la lista e imprimira el valor que esta almacenado en d, en cada recorrido. #include<lista.h> imprimir (CONEXION ca){ if (ca== NULL )printf ("NULL");
87
else {printf (" % c --> ", ca -> d);imprima (ca-> siguiente);}} Para ilustrar el empleo de estas funciones, se escribirá un programa que convertirá la cadena "RTXM" en una lista y la imprimirá #include <lista.h> main() { CONEXION c; c= crear_re ("RTXM"); printf (" \ nla lista resultante es \n"); imprima(c); printf("\nesta lista tiene %d elementos", contador (c));} La salida del programa es: la lista resultante es R --> T --> X -->M--> NULL Esta lista tiene 4 elementos 8.8.3. Concatenar dos lista En algunas oportunidades deseamos tomar dos listas y producir una sola. El encadenamiento de las listas r y t, donde se asume que r no está vacía, será la lista t agregada al final de la lista r. Una función de encadenamiento recorerá toda la lista a buscando su final, marcado por el apuntador nulo, consevará el rastro del último apuntador no nulo y anexará la lista t al siguiente conexion del último elemento de la lista r. concatenar (CONEXION r,CONEXION t) { /* la lista r no debe ser vacia*/ if (r ->siguiente == NULL) r-> siguiente = t; else concatenar (r -> siguiente t);} 8.8.4. Buscar un elemento de una lista La busqueda de un elemento de una lista se hace secuencialmente y termina cuando se encuentra el elemento o se llega al final de la lista en cuyo caso el elemento no se encuentra en la lista. si r,t son lista tenenmos: buscar(CONEXION r) {char x; printf("valor a buscar ..");scanf("%c",&x); while(r!=NULL && r-->d!=x) r=r-->siguiente; if(r!=NULL) printf("%c esta en la dirección %.5x\n",x,r); else printf("%c no esta en la lista\n",x);return(r);} 8.8.5. Insertar un elementa a una lista Una de funciones más utiles de las listas es que podamos insertar un nuevo elemento en cualquier posición de la lista. Los valores de todos los elementos de la lista que estén después del nuevo valor insertado tendrán que moverse en lugar.
88
Veamos la inserción de un elemento en una lista con dos elementos adyacentes a los que apuntan r1 y r2 , y se insertará entre ellos elemento al cual apunte q. Inserción Antes: ... ┌────┬────┐ ┌────┬────┐ │ R │ ---│-> │ T │ ---│--> ... │└────┴────┘ └────┴────┘ │ │ r1 ┌┴┐ r2 ┌┴┐ └─┘ └─┘ ┌────┬────┐ ┌─┬──── │ M │NULL│ q └─┘ └────┴────┘ Después ... ┌────┬────┐ ┌─── ┌────┬────┐ ┌─│ R │ │ │ │ ┌─│ T │ ---│--> ... │ └────┴──┼─┘ │ │ └────┴────┘ │ │ │ │ r1 ├─┐ │ r2 ┌┴┐ │ └─┘ │ └─┘ │ │ ┌────┬┼───┐ ┌─┐ └──│ M ││ │ q └─┴─────────└────┴────┘ Ahora diseñemos la función inserta () que coloca el elemento apuntado por q en medio de los elementos apuntados por r1 y r2. inserta (r1,r2,q) CONEXION P1,P2,q;{r1 -> siguiente = q; q -> siguiente = r2;
/* insertar */
8.8.6. Eliminación de un elemento Eliminar un elemento de una lista es cambiar el apuntador de los elementos anterior y del que se va a borrar . El elemento que está antes del que se eliminará tiene asignada a su enlace la dirección del elemento que sigue al que se eliminará. Luego de cambiar la dirección de los apuntadores se debe liberar la memoria utilizando la función free().Como se muestra en el diagrama, el elemento que contiene a 'T' ya no es accesible y no tiene utilidad. A un elemento inaccesible como éste se le llama basura. ... ┌────┬────┐ ┌────┬────┐ ┌────┬────┐ ┌─│ R │ ---│->│ T │ ---│->│ M │ ---│->... │ └────┴────┘ └────┴────┘ └────┴────┘ ├─┐ r └─┘ Se ejecuta el código r -> siguiente = r -> siguiente -> siguiente; Después
┌───────────────┐ ... ┌────┬──┼─┐ ┌────┬────┐└─┌────┬────┐ ┌─│ R │ │ │ │ T │ ---│->│ M │ ---│->... │ └────┴────┘ └────┴────┘ └────┴────┘ ├─┐ r └─┘
89
Ahora estamos en condiciones de diseñar la función borrar(). borrar(CONEXION ca){if (ca ! = NULL){borrar(ca -> siguiente); free (ca); /* liberar el almacenamiento */ }} Aunque es posible convertir en un cast al argumento apuntador a free(), por convención no se hace, pues esta omisión no produce ninguna advertencia del compilador y la rutina trabaja adecuadamente 8.9 LISTAS CIRCULARES Una lista circular es una lista lineal donde el ultimo elemento se enlaza con el primer elemento de la lista, y por esto se puede acceder cualquier elemento de la lista desde cualquier parte. ca┌──┬──┐ ┌──┬──┐ ┌──┬──┐ ┌───┬──┐ ┌──┬─┐ ┌─┼─ │──┼───┤ │ ─┼──┤ │ ─┼───>│ │──┼──┤ │ ├─┐ │ └──┴──┘ └──┴──┘ └──┴──┘ └───┴──┘ └──┴─┘ │ └────────────────────────────────────────────────┘ Las funciones que podemos realizar son las mismas que las listas lineales. 8.9.1 EJERCICIO Realizar las funciones de listas con listas circulares. 8.10 PILAS Una pila es una forma particular de considerar los datos de que se dispone cón una lista de enlace lineal. Una pila tiene el acceso restringidio a la cabeza de la lista, que se domina tope. Ademas, la insercion y la eliminacion solo pueden hacerse en el tope, y estas retricciones las operaciones se conocen como introduccion (push) y extraccion (pop), respectivamente. Una pila puede imaginarse como una pila de platos. Cuando se saca un plato de la pila, siempre se hace por arriba, y cuando se devuelve uno, también se hace por arriba. En una gráfica, las pilas se dibujan en forma vertical. ┌──────┐ ┌──┐ │ data │ tope │──┼──── ├──────┤ └──┘ │ │ │ └──┼───┘ │ ┌──────┐ ├──────┤ │ . │ └──┼───┘ │ . . . ┌──────┐ ├──────┤ │NULL │ └──────┘ UNA PILA Se desea realiar las cuatro operaciones de pila estándar siguientes: función Acción estávacío(t) devuelve l si la pila está vacía; si no es vtop(t) devuelve elvalor del elemento tope pop(t,d) devuelve el valor del elemento tope y lo
90
así, devuelve o. saca de la pila.
push(t,d)
coloca el valor d en el tope de la pila
Se utilizará el siguiente archivo de encabezamiento: En el archivo stack.h: # define NULL O /* archivo de encabezamiento de pila */ Typedef char DATA; struct pila { DATA d;struct pila *siguiente;}; typedef struct pila ELEMENTO; typedef ELEMENTO *TOPE A hora se definen como funciones las cuatro operaciones básicas. /*** rutinas básicas de las pilas ***/ # include "stack.h" estávacía (t) TOPE t; { return (t == NULL);} DATA vtop(t) TOPE t; { return (t -> d);} pop(TOPE *t,DATA *x) {TOPE t1=*t; if(! estavacia(t1)){ *x=t1->d; *t=t1->siguiente; libre(t1);} else printf("\npila vacia");} push(t,x) TOPE *t;DATA x;{TOPE temp;temp = (TOPE) malloc(sizeof(ELEMENTO)); temp -> d = x; temp -> siguiente = *t; *t = temp;} La rutina push() el asignador de almacenamiento para crear un nuevo elemento en la pila,y la rutina pop () devuelve de nuevo al sistema el almacenamiento liberado. Una pila trabaja en régimen de último en entrar primero en salir (LIFO). eL último elemento que entró (push) en la pila es el primero 'a' y espues 'b', entonces pop () obtendría 'b' primero. Esta propiedad pude utilizarse para un programa que invierta una secuencia de caracteres. /*** invertir una cadena con una pila ** inviertase(s) DATA s[]; { int i; TOPE t = NULL; for (i = 0; s [i] != '\0';++i) push(&t, s[i]); for (i = 0; s [i] !='\0'; ++i) pop(&t, &s[i];} El algoritmo construye una pila local a invierte() hasta que se detacta el carácter de fin de cadena. Luego,la pila se devuelve al arreglo,invirtiendo el orden original en que estaban almacenados los valores char. 8.11 EJERCICIOS: Realizar un programa de una calculadora con funciones estadisticas y utilice pilas.
91
92
A9 7 8 - 9 5 8 - 9 7 2 3 2 - 9 - 6 - 0 A
93