Você está na página 1de 96

Curso de Lenguaje C

VARIABLES, CONSTANTES, OPERADORES Y EXPRESIONES IDENTIFICADORES Un identificador est constitudo de caracteres alfabticos y numricos, adems es posible hacer uso del caracter subrayado. El primer caracter del identificador debe ser obligatoriamente una letra o un subrayado. Para el lenguaje C las letras minsculas son totalmente diferentes de las maysculas. Son significativos los primeros 32 caracteres (TURBO C - Microsoft C). Son significativos los primeros 8 caracteres (Latice C Ver. 3.0 y UNIX C). Toda palabra reservada se escribe en minscula. TIPOS DE DATOS Tipo char int float double void (Microsoft C) bits 8 16 32 64 0 Rango -128 -32768 -3.4e+48 -1.7e+308 sin valor a a a a 127 32767 3.4e+48 1.7e+308

Significado caracter entero flotante doble vacio

MODIFICADORES DE TIPO Los modificadores o calificadores de tipo, se aplican a los enteros y caracter.sin embargo es posible aplicar long al tipo de datos double. char signed char unsigned char int short unsigned int long int unsigned long long unsigned unsigned long 8 8 8 16 16 16 32 32 -128 -128 0 -32768 -32768 0 -2147483648 0 a a a a a a a a 127 127 255 32767 32767 65535 2147483647 4294967295

equivale a long int equivale a unsigned int equivale a unsigned long int

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

DECLARACION DE VARIABLES Formato: tipo lista_de_variables; tipo variable1 [,variable2, ... variable_n]; Ejemplo: int a, b; char ch; float f, g; long l, k; double d; signed char ca;

SITIOS DONDE SE DECLARAN VARIABLES 1. Fuera de todas las funciones incluyendo main(). 2. Dentro de una funcin. 3. En los parmetros formales de una funcin. EJEMPLOS DE CONSTANTES char 'a' '\n' '9' int 12000 long 1236377 unsigned 292999 float o double 12432.89 CONSTANTES HEXADECIMALES Y OCTALES Las constantes hexadecimales comienzan por: 0x (cero x). Una constante octal comienza por : 0 (cero). Ejemplo: int h; int oc; h=0xFF /* 255 en decimal */ oc=011 /* 9 en decimal */ CONSTANTES DE CADENA Las constantes de cadena se entrecomillan con comilla doble ("). Las constantes de caracter se entrecomillan con comilla simple ('). Ejemplo: "Esto es una cadena" "a" 'a' Nota: "a" es diferente de 'a' La representacin de 'a' como caracter y "a" como cadena en la memoria seria: caracter cadena a a\0 CONSTANTES DE BARRA INVERTIDA \b Retroceso
2

-354 -6775774 0 -0.89 1.0E100

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

\a \f \n \r \t \" \' \\ \v \x \N

Alarma Alimentacin de pgina Nueva linea Retorno de carro Tabulador horizontal Doble comilla Comilla simple Barra invertida Tabulador vertical (Impresora) Constante hexadecimal Constante octal donde N es una constante octal

Ejemplo: ch = '\n' INICIALIZACION DE VARIABLES Formato: tipo variable = constante; Ejemplo : char ch = 'a'; float f = 123.675; CONSTANTES SIMBOLICAS #define nombre_constante valor Ejemplo: #define PI 3.1416 #define ERR_1 printf("Error 26\n") OPERADORES Operadores aritmticos + Suma Resta * Multiplicacin / Divisin % Modulo ++ Incremento -decremento () Agrupar Precedencia ++ -- () * / % + Operadores relacionales y lgicos:

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

Operadores de relacin : > >= < <= == != Operadores lgicos : && || ! and or not

Presedencia de los operadores relacionales y lgicos ! > >= < <= == != && || Ejemplo de algunas expresiones: 1 && !0 || 1 /* resulta 1 */ 1 && !(0 || 1) /* resulta 0 */ El operador sizeof() : Devuelve el tamao de un tipo de dato o de una variable en bytes. EXPRESIONES Conversin de tipo char y short ............. int float ................. double Ejemplo: char ch; int i; float f; double d; r = (ch / i) + (f * d) - (f + i); | | | | | | int double float | | | | / / \ / / \ / / double | double CAST : Forza a una expresin a ser de un tipo especfico. Formato: (tipo) expresin Ejemplo: int x; float r;

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

x = 35; r = (float) x / 2; /* resulta 17.5 */ r = (float) (x / 2) /* resulta 17.0 */ OPERADORES Y EXPRESIONES DE ASIGNACION Formato : variable op= exp; op es uno de los siguientes operadores: + - * / % << >> & ^ | ~ Ejemplo : x *= y + 1; a -= 4;

y es equivalente a : x = x * (y + 1); a = a - 4;

TABLA COMPLETA DE PRESEDENCIA DE OPERADORES () [] -> . ....... Izq. a derecha ! ~ ++ -- (tipo) * & sizeof ..... " " " * / % ........ " " " << >> ........ " " " < <= > >= ........ " " " == != ........ " " " & ........ " " " ^ ........ " " " | ........ " " " && ........ " " " || ........ " " " ?: ........ Derecha a izq. = += -= etc. ........ " " " , ........ Izq. a derecha ENTRADA Y SALIDA DE CONSOLA FORMATEADA printf() : Escribe datos en diversos formatos, por lo tanto se formateada. printf() escribe datos en la consola. Formato: printf("cadena_de_ctrl", lista_de_argumentos); cadena_de_ctrl : Comienza con un signo de porcentaje (%) y luego le sigue el cdigo de formato. lista_de_argumentos : Son variables, constantes o expresiones a visualizar. denomina tambin salida

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

Tabla de ordenes de formato de printf() ------------------------------------------------------Codigo Significado ------------------------------------------------------%c visualiza un caracter %d visualiza decimal %i visualiza decimal %e visualiza en notacin cientifica %f visualiza datos en punto flotante %g usa %e %f la que sea ms corta %o visualiza octal %s visualiza cadena de caracteres %u visualiza decimal sin signo %x visualiza hexadecimal %% imprime signo % %p visualiza un puntero Ejemplo: printf("Datos %c %d %s\n", 'a', 100, "caracteres"); /* visuliza : Datos a 100 caracteres */ /***** * * suma de valores * *****/ main() { int a, b; a = 10; b = 40; printf("Suma de a + b = %d\n", a+b); } ESPECIFICADOR DE ANCHO DE CAMPO Completa la salida con blancos o ceros para asegurar que es al menos la longitud mnima. Si una cadena o nmero es mayor que el mnimo ancho especificado, esta se imprimir completa. El relleno por defecto es blanco. Si se desea un relleno con ceros se debe poner cero antes del especificador de ancho de campo. Ejemplo: printf("%05d", 48); /* visualiza :00048 */

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

printf("%5d", 48); /* visualiza : 48 */ Si se desea especificar posiciones decimales para un valor en punto flotante, se pone un punto decimal seguido por el nmero de decimales. Ejemplo: printf("%10.2f", 123.1283); /* visualiza : 123.12 */ Nota : Tenga en cuenta que el valor que aparece antes del punto especifica el ancho total de campo incluyendo las posiciones decimales y el punto decimal. Lo anterior se podra leer como campo de tamao diez de los cuales siete se tomarn para la parte entera, dos para decimales y uno para el punto. Por defecto toda salida formateada se justifica a la derecha; si se desea un efecto contrario entonces se debe colocar un guin despus del signo porciento. Ejemplo: printf("%-5d", 48); /* visualiza :48 */ printf("%-5.2f", 48); /* visualiza :48.00 */ Cuando se usa el punto en una cadena; el valor que le sigue al punto indica el mximo ancho de la cadena. Ejemplo: printf("%5.7s", "Jos perez"); El cinco indica que la cadena tendr al menos cinco caracteres y un mximo de siete. Si la cadena es ms larga que el ancho mximo especificado, los caracteres adicionales se truncan por la derecha. Ejercicio: /***** * * formateo de la salida * *****/ main() { int i = 100; float f = 3.5; printf("i = %4d, f = %2.2f\n", i, f); } MODIFICADORES DE FORMATO PARA printf() QUE PERMITEN VISUALIZAR ENTEROS CORTOS Y LARGOS

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

l ................... dato long h ................... dato short Los anteriores modificadores se pueden aplicar a los cdigos de formato : d, i, o, u y x. Ejemplo : printf("%ld", p); /* visuliza un long int */

scanf() : Funcin de entrada de propsito general que lee la corriente stdin. Formato : scanf("cadena_de_ctrl", lista_de_argumentos); cadena_de_ctrl : Consta de tres clasificaciones de caracteres: 1. Especificadores de formato 2. Caracteres de espacio en blanco 3. Caracteres de no espacio en blanco El cdigo de formato le dice a scanf() que tipo de datos se lee a continuacin. Tabla de cdigos de formato de scanf() --------------------------------------------------Codigo Significado --------------------------------------------------%c lee un caracter %d lee un decimal entero %i lee un decimal entero %e lee un nmero en punto flotante %f lee un nmero en punto flotante %o lee un nmero octal %s lee una cadena %x lee un nmero hexadecimal %p lee un puntero Un caracter de espacio en blanco en la cadena de control provoca que scanf() salte sobre uno o ms caracteres de espacio en blanco tabulado o return en la corriente de entrada. Ejemplo: scanf("%d %f %s", &i, &f, &str); /* la entrada podria ser: 20 3.5

maria */

Un caracter de no espacio en blanco provoca que scanf() lea y descarte un caracter que no encaje. Ejemplo: scanf("%d,%d", &x, &y); /* la entrada podria ser : 20,50 */ Si no se encuentra el caracter especificado terminar scanf().

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

Supresin de la asignacin con *. Si en un scanf() se especifica el caracter %*, el campo de entrada no ser tomado en cuenta. Ejemplo: scanf("%d%*c%d", &x, &y); /* la entrada podria ser :20/40 */ /* x = 20 y = 40 */ En las ordenes de formato se puede especificar el modificador mximo ancho de campo. Ejemplo : scanf("20s", str); /* lee mximo 20 caracteres */ Si la entrada tiene ms de 20 caracteres, el siguiente scanf() o cualquier llamada a una posterior entrada comenzar donde qued la anterior. Sea cuidadoso, la entrada para un campo puede terminar antes de completar la longitud mxima de la misma al encontrar un espacio en blanco. scanf() se mover al prximo campo. Ejemplo: scanf("%2d %f %*d %2s", &i, &f, &nom); /* al leer :5674 139 49abc74 quedar: i = 56 f = 74.00 saltar 139 nom = "49" */ La siguiente llamada a cualquier funcin de entrada comenzar a partir de a. EJERCICIOS DE APLICACION Desarrolle una serie de ejercicios para poner en prctica todo lo estudiado hasta el momento. Programas ejemplo /***** * * lee un valor y devuelve su cuadrado * *****/ main() { int a; printf("Teclea un valor :"); scanf("%d", &a); printf("Cuadrado de %d es igual a %d\n", a, a*a); } /***** *

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

* conversion de grados celcius a fahrenheit * C = (5/9)(f-32) * *****/ main() { float fahr, celcius; printf("Gardos fahrenheit :"); scanf("%f", &fahr); celcius = (5.0 / 9.0) * (fahr -32); printf("%6.2f grados fahrenheit equivalen a %6.2f celcius\n", fahr, celcius); } ARCHIVOS DE INCLUSION O CABECERA Los archivos de inclusin contienen definiciones y declaraciones que pueden ser incorporados en un programa especfico que as lo requiera. Para llamar un archivo de inclusin o cabecera es necesario hacer uso de la directiva #include la cul tiene el siguiente formato: #include nombre_de_archivo_cabecera Donde nombre_de_archivo_cabecera es el nombre de un archivo que contiene las declaraciones y definiciones para un propsito especfico. Este archivo se distingue por tener la extencin .h. El nombre_de_archivo_cabecera se debe encerrar entre comillas (" ") o signos menor y mayor que (< >). Ejemplo: #include "stdio.h" #include <stdio.h> Las comillas le dicen a C que busque primero en el directorio de trabajo actual el archivo de inclusin, si no lo encuentra, busca entonces en el directorio especificado en la linea de ordenes, y finalmente si an no lo ha encontrado, entonces busca en el directorio standard que se halla definido durante la instalacin. Si el archivo de inclusin se encierra entre signos menor y mayor qu, el compilador busca primero en el directorio especificado en la linea de ordenes. si no lo encuentra busca entonces en el directorio standard. Jams busca en el directorio de trabajo. S en la inclusin se especifica nombre de ruta o camino, entonces busca en dicho directorio. Ejemplo : #include "c:\cabercera\stdio.h" #include <c:\include\ctype.h>

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

10

Dentro de un archivo cabecera se pueden tener otros #include anidados. ENTRADA Y SALIDA DE CONSOLA Para el uso de estas funciones es necesario incluir el archivo "stdio.h". Funcin getchar() : Funcin getche() : Funcin getch() : carro. Funcin putchar() : Funcin gets() : Funcin puts() : Funcin cprintf() : Funcion kbhit() : Funcin fgets() : Funcin fputs() : Lee un caracter desde el teclado; espera por el retorno de carro. Lee un caracter del teclado; no espera por retorno de carro. Le un caracter del teclado, no hace eco y no espera por retorno de Escribe un caracter en la pantalla. Lee una cadena desde el teclado. Escribe una cadena en la pantalla. Escribe caracter formateado. Espera por la pulsacin de una tecla. Lee una cadena de tamao especfico y la almacena en una variable. Funcin contraria a fgets().

Ejemplo: #include "stdio.h" main() { char ch; printf("Digita un caracter :");ch=getche(); printf("%c\n", toupper(ch)); } SENTENCIAS DE CONTROL La sentencia if() / ?: Formato: if(<expL>) sentencia; [else sentencia; ] Cuando se desea ejecutar un grupo de instrucciones en un if() es necesario formar un bloque usando llaves. Ejemplo: if(<expL>) { sentencia_1; sentencia_2; . . sentencia_n; } ---------------------------if(<expL>)

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

11

sentencia; else { sentencia_1; sentencia_2; . . sentencia_n; } ----------------------------if(<expL>) { sentencia_1; . . sentencia_n; } else { sentencia_1; . . sentencia_n; } ?: Formato: (<expL>) ? <exp1> : <exp2> <expL> :Es la condicin a ser evaluada. <exp1> :Se ejecuta si <expL> es verdadera. <exp2> :Se ejecuta si <expL> es falsa. Ejemplo: z = (a > b) ? a : b; m = (mes > 6) ? 8 : 2; #include "stdio.h" main() /* convierte letra a tipo contrario */ { char ch; puts("Digita un caracter :");ch=getche(); printf("%c\n",(islower(ch) ? toupper(ch) :tolower(ch)); } if() else if() if(<expL>) sentencia; else if(<expL>) sentencia; else if(<expL>) sentencia;

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

12

. . . else sentencia; LA EXPRESION CONDICIONAL Cuando el resultado de una condicin es verdadero su valor es uno y cundo ste es falso su valor es cero. De esta manera una expresin condicional podra tener el siguiente aspecto: if(co) sentencia; else sentencia; co ser evaluado como verdadero si su valor es diferente de cero, de lo contrario ser falso. Ejemplo: main() { int i printf("Numero entero :"); scanf("%d", &i); if(i) printf("%d\n", i/2); else printf("No puedo dividir por cero\n"); } LA SENTENCIA switch() Seleciona entre varias alternativas dependiendo del valor de una variable. Formato: switch(<var>) { case constante_1: secuencia_de_sentencias break; case constante_2: secuencia_de_sentencias break; . . . default : secuencia_de_sentencias } Ejemplo:

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

13

SENTENCIAS switch() ANIDADAS Se pueden anidar sentencias switch() con el fin de implementar rutinas donde las opciones tienen subdivisiones. BUCLES EL BUCLE for() Formato: for(inicializacin; <expL>; variacin) sentencia; inicializacin : Es normalmente una asignacin para dar un valor inicial a la variable controladora de ciclo. <expL> : La expresin lgica determina hasta cuando ha de repetir el bucle. variacin : Forma o manera en que debe cambiar la variable del ciclo. Ejemplo: #define MAXN 10 main() { int i; for(i=0; i<MAXN; i++) printf("%d ",i); } main() { int i; for (i = 10; i > 0; i--) printf("%d ",i); } main() { int x; for(x=0; x<10; x +=2) printf("%d ", x); } main() { int x, y; for(x=0, y=0; x<10; x++, y++) printf("x=%d, y=%d\n", x, y); }

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

14

#include <stdio.h> main() { char ch; for(;;) { printf(Digita un caracter :"); ch=getche(); if(ch=='$') break; /* rompe el ciclo */ } } main() { int x; for(x=0; x != 100;) { printf("Introduce un nmero 100 para salir"); scanf("%d",&x); } } #include <stdio.h> #include <ctype.h> main() { int i, j, resp; char done = ' '; for(i=1; i<=100 && done != 'N'; i++) { for(j=1; j<=10; j++) { printf("Cunto es %d + %d ?",i, j); scanf("%d",&resp); if(resp != i+j) printf("\nErrado\n"); else printf("\nOk\n"); } printf("Sigue (S/N)? "); done = toupper(getche()); } } BUCLES for() SIN CUERPO Un bucle sin cuerpo consiste en colocar en el sitio donde v la sentencia un punto y coma. Ejemplo:

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

15

for(t=0; t<NMAX; ++t) ; EL BUCLE while() Desarrolla un ciclo mientras una condicin sea verdadera. Formato: while (<expL>) sentencia; Ejemplo: #define FIN '*' #include <stdio.h> main() { char ch = '\0'; while(ch != FIN) ch=getche(); } #include "stdio.h" main() { int c; while((c=getchar()) != EOF) putchar(c); } #include "stdio.h" main() { int c, nc=1; printf("%4d :", nc); while((c=getchar()) != EOF) { if(c == '\n') { ++nc; putchar(c); printf("%4d :",nc); } else putchar(c); } } EL BUCLE do/while() Ejecuta un grupo de instrucciones al menos una vez mintras se cumpla una condicin debido a que el chequeo de la condicin se lleva a cabo al final del bloque de instrucciones.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

16

Formato : do { sentencia; . . . } while(<expL>); Ejemplo: #include <stdio.h> main() { char opc; printf("Desea seguir (S/N) ? "); do { opc=toupper(getche()); } while(opc != 'S' && opc != 'N'); } LA SENTENCIA continue continue : obliga a ejecutar la siguiente iteracin y salta medias. Ejemplo: main() /* imprime nros. pares */ { int x; for(x=1; x<100; x++) if(x%2) continue; printf("%d\n", x); } ETIQUETAS y goto Una etiqueta es un nombre de identificador vlido para C que termina en dos puntos (:). Una etiqueta debe estar en la misma funcin donde est el goto que la utiliza. Ejemplo: loop: x++; if (x<100) goto loop; cualquier cdigo entre

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

17

goto puede ser apropiado cuando se desea salir de varios niveles de anidacin. ARRAYS Y CADENAS Arrays unidimensionales: Formato: tipo nombre_array[<expN>] [,nombre_array[<expN>],...]; Los ndices de los arrays deben arrancar desde cero (0) y que el primer elemento comienza en esa posicin. Ejemplo: #define N 10 main() { int i, tem, j=N-1, a[N]; for(i=0; i<N; ++i) a[i]= i; for(i=0; i< N/2; i++, j--) { tem = a[i]; a[i] = a[j]; a[j] = tem; } for(i=0; i<N; i++) printf("%d ",a[i]); } Nota: El lenguaje C no har comprobaciones de contornos en los arrays por lo tanto es reponsabilidad del programador el manejo adecuado de los arreglos evitando el desbordamiento de los mismos escribiendo o leyendo fuera de los limites. CADENAS O STRING Una cadena es un arreglo de tipo caracter. Ejemplo: char nombre[30]; /* declara la variable nombre de 30 caracteres */ Toda cadena de caracteres termina en un nulo '\0'. Ejemplo: #define TM 5 #include "stdio.h" main() { char s[TM];

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

18

puts("Escribe hola"); gets(s); printf("%s\n", s); } La cadena s quedar as en memoria:

/* convierte una cadena en mayscula */ #include <stdio.h> #include <ctype.h> main() { char string[80]; int i; printf("Introduce una frase en minscula :"); gets(string); for(i=0; string[i]; i++) cprintf("%c", toupper(string[i])); } #include "stdio.h" main() { char s[80]; int i; printf("Escribe una frase :"); gets(s); for(i=0; s[i]; i++) printf("%c", (s[i] == ' ') ? '\n' : s[i]); } FUNCIONES DE CADENA DE LA BIBLIOTECA Estas funciones se hallan definidas en el archivo "string.h". strcpy() :Copia el contenido de la cadena origen en la cadena destino. Formato : strcpy(destino, origen); Ejemplo:

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

19

#include "string.h" main() { char a[80]; strcpy(a, "hola mundo"); printf("%s\n", a); } strcat() :Concatena dos cadenas. Formato : strcat(cadena1, cadena2); Concatena la cadena2 al final de la cadena1. Ejemplo: #include <string.h> #include <stdio.h> main() { char a1[80], a2[40]; strcpy(a1,"cartagena"); strcpy(a2," colombia"); strcat(a1, a2); puts(a1); } strcmp() :Compara dos cadenas y devuelve cero si son iguales. Formato : strcmp(cadena1, cadena2); Si cadena1 es mayor que cadena2 devuelve un valor mayor que cero. Si cadena1 es menor que cadena2 devuelve un valor negativo. Ejemplo: #include <string.h> #include <stdio.h> main() { char s[80]; puts("Password :"); gets(s); if((strcmp(s, "pass")) == 0) puts("Ok..."); else { puts("Password equivocado"); exit(0);

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

20

} } strlen() :Devuelve la longitud de una cadena. Formato : strlen(cadena); Ejemplo : #include <string.h> #include <stdio.h> main() { int s[80]; strcpy(s, "Hello..."); printf("%d\n", strlen(s)); getche(); } strchr() strstr() :Ver su funcionalidad luego de haber tratado el tema de FUNCIONES DE CARACTER Las funciones de caracter hacen uso de el archivo cabecera "ctype.h". isalnum() Devuelve diferente de cero (0) si el caracter es una Formato :isalnum(ch); Ejemplo : #include <stdio.h> #include <ctype.h> main() { char ch; for(;;) { ch=getche(); if(ch==' ') break; if(isalnum(ch)) printf("%c\n",ch); } } iscntrl() :Devuelve diferente de cero (0) si el caracter es un caracter de control. Los caracteres de control estan comprendidos entre 0 ... 0x1F y 0x7F (DEL). Formato : iscntrl(ch); Ejemplo : #include <ctype.h> letra o un dgito. punteros.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

21

#include <stdio.h> main() { char ch; for(;;) { ch=getche(); if(ch==' ') break; if(iscntrl(ch)) printf("%c\n"); } } isdigit() :Devuelve diferente de cero (0) si el caracter es un Formato : isdigit(ch); Ejemplo : #include <ctype.h> #include <stdio.h> main() { char ch; for(;;) { ch=getche(); if(ch==' ') break; if(isdigit(ch)) printf("%c\n", ch); } } isgraph() :Devuelve diferente de cero si el caracter es imprimible y distinto de espacio. Formato : isgraph(ch); islower() :Devuelve diferente de cero si se trata de un caracter minscula. Formato : islower(ch); isupper() :Devuelve diferente de cero si el caracter es mayscula. Formato : isupper(ch); isprint() : Devuelve diferente de cero si el caracter es imprimible incluyendo el espacio. Formato : isprint(ch); dgito.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

22

ispunct() :Devuelve diferente de cero si el caracter es un caracter de puntuacin. Nos referimos a un caracter de puntuacin como todos aquellos diferentes de los alfabticos y numricos. Formato : ispunt(ch); isspace() :Devuelve diferente de cero si el caracter es un espacio. Formato : isspace(ch); Ejemplo : #include <ctype.h> #include <stdio.h> #define NMAX 80 main() { char s[NMAX]; int i; printf("Introduce una frase :"); gets(s); for(i=0; s[i]; ++i) printf("%c", (isspace(s[i]) ? '\n' : s[i]); } isxdigit() :Devuelve diferente de cero si el caracter es un hexadecimal es: 0 ... 9 A ... F, a ... f. Formato : isxdigit(ch); ARRAYS BIDIMENSIONALES Formato : tipo nombre_array[nro_filas][nro_col]; Ejemplo : int a[2][4]; Define un arreglo con la siguiente estructura: 0 1 2 3 dgito hexadecimal. Un dgito

Haciendo uso de la siguiente frmula podemos averiguar el nmero de bytes de memoria usados por un array: bytes = filas * columnas * sizeof(tipo_de_datos)
Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia. 23

Ejemplo : 2 * 10 * 2 = 40 bytes Ejemplo : #define NMAX 4 main() { int a[NMAX][NMAX], i, x; for(i=0; i<NMAX; i++) for(x=0; x<NMAX; x++) a[i][x] = i * x; for(i=0; i<NMAX; ++i) printf("%d ", a[i][i]); } ARRAYS DE CADENAS Ejemplo : char lineas[30][80]; Define un array de 30 cadenas cada una con un mximo de 80 caracteres. Para acceder a una cadena individualmente, se especifica el indice de la fila. Ejemplo : gets(lineas[0]); ARRAYS DE MULTIPLES DIMENSIONES Formato : tipo nombre_array[<expN1>][<expN2>][expN3>]...[expNn>]; Ejemplo : int a[2][3][3]; INICIALIZACION DE ARRAYS En lenguaje C se pueden inicializar arrays globales. Para inicializar un array local, es necesario declararlo como static. Formato : especificador de tipo nombre_de_array[<expN1>]...[<expNn>] = { lista_de_valores}; lista_de_valores :Es una lista de constantes que son del tipo compatible con el tipo base del array separada por comas. Ejemplo : int i[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Los arrays de cadenas permiten ser inicializados segn el siguiente formato:

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

24

char nombre_de_array[<expN>] = "cadena"; Ejemplo : char str[6] = "hola"; char str1[6] = {'h','o','l','a','\0'}; Ejemplo : int pad[10][2] = { 1, 1, 2, 4, 3, 5, 6, 4, 8, 9, 1, 0, 4, 6, 7, 6, 8, 5, 0, 3 }; INICIALIZACION DE ARRAYS SIN TAMAO Ejemplos : char e1[] = "Error de lectura"; char e2[] = "Archivo no hallado"; char e3[] = "Datos no disponibles"; Se puede verificar el tamao en bytes de cualquiera de las anteriores cadenas as: printf("%s tiene %d caracteres\n", e1, sizeof(e1)); Para arrays multidimensionales se deben especificar todas las dimensiones excepto la de ms a la izquierda. Ejemplo : int datos[][2] = { 1, 3, 5, 6, 7, 4, 9, 1, 0, 8, 4, 0, 5, 8 }; MODOS DE ALMACENAMIENTO (ESPECIFICADORES DE ALMACENAMIENTO) Formato: especificador tipo_name Variables Automticas: Toda variable declarada dentro de una (auto) funcin por defecto es automtica. Si se desea dejar clara la intencin se emplea la palabra auto al frente de la declaracin de

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

25

variable. Toda variable local es automtica. Cundo no se especifca ninguna clase de almacenamiento, se supone que la variable es automtica. Ejemplo: main() { auto int a, b; auto char ch; auto float f= 4.5; } Variables Estticas : Son variables locales a la funcin o bloque donde fueron declaradas . La diferencia radica en que sus valores persisten entre llamadas, de tal manera que encontraremos en ellas cada vez que entremos al bloque o funcin, el ltimo valor almacenado, la ltima vez que se llam la funcin. Las variables estticas que no se inicializan, contienen un valor 0 la primera vez, o nulo si es tipo char. Normalmente las variables que contienen valores fijos para una determinada funcin, se declaran y se inicializan static. Ejemplo main() { cuenta(); cuenta(); cuenta(); } cuenta() { static int x=0; printf("%d\n",x); x++; } Variables Externas: Las variables que se declaran fuera de una (extern) funcin son consideradas externas, pero adems se pueden declarar variables externas dentro de una funcin que la emplea utilizando la palabra extern. Cuando una variable es declarada en archivos diferentes tambin se puede declarar extern para indicar que y esa variable fue declarada en el primer archivo. Las variables extern son el medio para establecer comunicacin entre mdulos compilados separadamente. Ejemplo: int a=4; main() { printf("%d\n",a); func(); } func()

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

26

{ printf("%d\n",a); } extern int x; main() { extern int x; . } Ejemplo: int i; /* variables externas */ char ch; main() { extern int i; /* fue declarada extern */ auto char ch; /*no es ch extern */ Ejemplo: int i; main() { int i; . . . } otra() { auto int i; } Variables registro: Son variables que se almacenan en registros de C.P.U por lo tanto sern rpidas a diferencia de variables almacenadas en memoria. No debemos declarar demasiadas variables registro para evitar que el compilador nos coloque las que no puedan almacenarse en C.P.U en memoria como cualquier otra variable. Nunca debe tomar la direccin de una variable register recuerde que residen en registros de la C.P.U y no en RAM. Las variables register son siempre enteras. Ejemplo: main() { register int a,b; . .

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

27

. } Ejemplo: main() { register int i_rpida; . . . } MODIFICADORES DE ACCESO Formato: modificador tipo var_name; CONST : Son variables que no pueden ser cambiadas por el programa durante la ejecucin. Es posible darles un valor inicial. Ejemplo: Const float f=48.5 FUNCIONES Una funcin se puede definir como un subprograma la cul nos permite descomponer un programa en sus mnimos componentes. Para definir una funcin se debe hacer uso de un identificador de tipo vlido con el cul daremos nombre a la funcin, luego se deben colocar dentro de parentesis los argumentos si es que existen. Cuando los argumentos no existen los parentesis deben quedar vacos. Debemos recordar que los argumentos deben definirse del tipo de datos vlidos que se ha pasado a la funcin. Formato de una funcin: tipo_de_funcin nombre_funcin(lista_de_argumentos); declaracin de argumentos_o_parmetros; { cuerpo_de_la_funcin } Por defecto toda funcin devuelve un valor entero a menos que se especifique otra cosa. SALIENDO DE UNA FUNCION Existen dos formas de salir de una funcin: 1. Al encontrar la ltima llave que cierra la funcin. 2. Haciendo uso de la sentencia return.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

28

Cuando una funcin encuentra la ltima llave de la misma o cuando encuentra una sentencia return automticamente termina la ejecucin. LA SENTENCIA return return puede terminar una funcin sin retornar ningn valor. En caso de que la funcin devuelva algn valor, la expresin o el valor debe ser colocado al frente de return. LLAMANDO A UNA FUNCION Para llamar a una funcin se escribe en sitio adecuado el nombre de la funcin seguido de parentesis abierto y cerrado. Si se pasan parmetros, estos deben colocarse dentro de los parentesis separados por coma. Ejemplo: main() { int a = 10, b = 20; printf("suma de a + b = %d\n", suma(a, b)); } suma(x, y) int x, y; { return(x + y); } Ejemplo : main() { int a = 10, b = 20; printf("%d\n", max(a, b)); } max(x, y) int x, y; { return((x > y) ? x : y); } Ejemplo: main() { int x=10;

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

29

imprime_cadena(x); } imprime_cadena(n); int n; { int i; for(i=0; i<n; ++i) printf("%c", 45); } PARAMETROS POR VALOR Se le conoce como paso de parmetros por valor al hecho de enviar valores a una funcin, estos valores sern recibidos en variables temporales de tal manera que si se llevan a cabo modificaciones, los cambios no se reflejaran en las variables originales. Ejemplo: main() { printf("%d\n", power(4, 2)); } power(n, x) int n, x; { int p; for(p=1; x>0; x--) p *= n; return(p); } /* funcion xtolower() */ xtolower(s) char ch; { if(s > 65 && s < 91) s += 32; return(s); } AMBITO DE LAS VARIABLES Una variable puede ser conocida solo dentro de una funcin especifca lo cul no debe crear conflictos con otras variables que tienen el mismo nombre dentro de otras funciones.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

30

FUNCIONES Y ARRAYS Es posible pasar elementos individuales o un array completo a una funcin lo cul se ilustrar a continuacin: /***** * * ejemplo de una clasificacion de array por metodo de shell * y busqueda binaria. * *****/ #define SALIDA 0 #define MAXNUM 10 int lista[MAXNUM] = {1, 5, 4, 2, 8, 3, 9, 10, 7, 6}; main() /* main program */ { int x, a, index; /* mostrar valores del array en desoreden */ puts("lista desordenada ..."); for(x = 0; x < MAXNUM; x++) printf("%d ", lista[x]); cprintf("%c", '\n'); shell(lista, MAXNUM); /* clasificar lista */

/* mostrar valores del array ya ordenados */ puts("lista ordenada ..."); for(x = 0; x < MAXNUM; x++) printf("%d ", lista[x]); cprintf("%c", '\n'); /* buscar un valor dado en el array lista hasta SALIDA */ puts("\nvalor a buscar"); scanf("%d", &a); while(a != SALIDA) { index = binary(a, lista, MAXNUM); printf("\n%d\n", (index != -1) ? lista[index] : index); scanf("%d", &a); } } /* end of main() */ /***** * * udf shell(v, n)

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

31

* clasifica un array de enteros por metodo de shell * *****/ shell(v, n) int v[], n; { int gap, i, j, tem; for(gap = n/2; gap > 0; gap /= 2) for(i = gap; i < n; ++i) for(j = i-gap; j>=0 && v[j]>v[j + gap]; j -= gap) { tem = v[j]; v[j] = v[j + gap]; v[j + gap] = tem; } } /* end of function shell */ /***** * * udf binary(x, v, n) * busqueda binaria * busca a x en v[0]...v[n-1] * *****/ binary(x, v, n) int x, v[], n; { int low, high, mid; low = 0; high = n - 1; while(low <= high) { mid = (low + high) / 2; if(x < v[mid]) high = mid - 1; else if(x > v[mid]) low = mid + 1; else return(mid); /* lo encontro */ } return(-1); /* x no fue hallado */ } /* end of function binary() */ val(s) char s[]; {

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

32

int i, n; n = 0; for(i = 0; s[i] >= '0' && s[i] <= '9'; ++i) n = 10 * n + s[i] - '0'; return(n); } FUNCIONES QUE DEVUELVEN VALORES NO ENTEROS Para crear funciones que devuelven valores no enteros, se deben tener en cuenta los dos siguientes pasos: 1. Se debe especificar el tipo de funcin. 2. Se identifica el tipo de funcin antes del primer llamado. Formato: tipo nombre_de_funcin(); Ejemplo: float suma(); /* identificamos la funcin */ main() { float a, b; a=35.8; b=56.5; printf("%f", suma(a, b)); } float suma(x, y) float x, y; { return(x + y); } FUNCIONES DE TIPO void Una funcin se declara de tipo void para evitar que la misma devuelva algn valor. Ejemplo: void imprime_col(s) char s[]; { int i; for(i=0; s[i]; ++i) printf("%c\n", s[i]); } PROTOTIPOS DE FUNCION

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

33

Se le conoce con el nombre de prototipos de funcin al hecho de declarar el nmero y tipo de parmetros en una funcin. Al hacer uso de los prototipos de funcin, se habilita al lenguaje C para que haga una comprobacin rigurosa. Nota : No son parte del original UNIX. PUNTEROS Son variables que contienen la direccin de memoria de otra variable. Ejemplo: Localizacin de memoria Variable +-------+ 1000 --------------------> | 003 | --+ +-------+ | 1001 --------------------> | | | +-------+ | 1002 --------------------> | | | +-------+ | 1003 --------------------> | | <-+ +-------+ 1004 --------------------> | | +-------+ 1005 --------------------> | | +-------+ MEMORIA Formato: tipo *nombre_de_variable; Ejemplo: int *m; char *ch; OPERADORES DE PUNTERO *, & El signo (&) indica la direccin de memoria apuntada. El signo (*) indica el valor contenido en la direccin apuntada. IMPORTANCIA DEL TIPO BASE DE UN PUNTERO Es importante tener en cuenta el tipo base para definir un puntero y que de acuerdo a ello en un incremento o decremento determina el nmero de posiciones a avanzar o retroceder.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

34

Un puntero slo permite operaciones de suma y resta. Ejemplo: /* sumando a un puntero */ main() { int arr1[5], *p1, i; float arr2[5], *p2; for(i = 0; i < 5; i++) { arr1[i] = i; arr2[i] = i; } p1 = arr1; p2 = arr2; for(i = 0; i < 5; i++) printf("valor punteros + %d = %u } El resultado del anterior programa podria ser: valor punteros + 0 = valor punteros + 1 = valor punteros + 2 = valor punteros + 3 = valor punteros + 4 = 2708 2710 2712 2714 2716 2720 2724 2728 2732 2736

%u\n", i, p1+i, p2+i);

esto se debe a que cada puntero int es de dos bytes y cada puntero float es de cuatro bytes y al sumarle una unidad, simplemente direcciona la posicin de comienzo del prximo elemento de su tipo en la memoria. ARITMETICA DE PUNTEROS Anteriormente se dijo que las nicas operaciones aritmticas que se pueden llevar a cabo son suma y resta. Si se ha definido pt como puntero, pt++ ++pt hace que pt apunte al siguiente elemento y pt += i hace que pt apunte al i-esimo elemento. Si pt apunta al a[0] *(pt+1) se refiere al contenido de a[1]. *++pt es equivalente a lo anterior. a + 2 == &a[2] /* se trata de la misma direccin */ *(a + 2) == a[2] /* se trata del mismo valor */ *(a + 2) *a + 2 /* tercer elemento de a */ /* suma 2 al valor del primer elemento */

OPERACIONES QUE SE PUDEN REALIZAR CON PUNTEROS

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

35

1. ASIGNACION. Se puede asignar una direccin de memoria a un se usa con el nombre de un array o con el signo &.

puntero. Comunmente operador *

2. ACCEDER AL VALOR GUARDADO EN UNA DIRECCION DE MEMORIA. El devuelve el valor almacenado en una posicin de memoria apuntada.

3. SE PUEDE OBTENER DIRECCION DE UN PUNTERO. Es posible obtener la direccin de memoria de un puntero. Con el operador & podemos hallar la direccin de un puntero. 4. INCREMENTAR UN PUNTERO. Y sabemos que al incrementar un la direccin del prximo elemento de su tipo. 5. DECREMENTO. Al decrementar un puntero retrocedemos o sealamos memoria del anterior elemento de su tipo. APUNTADORES Y ARGUMENTOS DE FUNCIONES La nica forma de pasar a una funcin parmetros por referencia, es haciendo uso de punteros. Si deseamos que una funcin llamada altere las variables pasadas a ella, debemos pasar la direccin de memoria de dicha variable. Ejemplo: main() /* demostracion de parmetros por referencia */ { int a = 10, b = 20; printf("Valores actuales de a=%d, b=%d\n", a, b); swap(&a, &b); printf("Valores de a=%d, b=%d despus del llamado a swap\n",a,b); } /***** * * funcion swap() * intercambia valores de variables * *****/ swap(x, y) int *x, *y; { int tem; tem = *x; *x = *y; *y = tem; } puntero obtenemos a la posicin de

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

36

APUNTADORES Y ARRAYS Existe una estrecha relacin entre arreglos y apuntadores que es posible acceder a un arreglo mediante un indice o mediante un puntero. Aunque es ms rpido acceder a un arreglo usando punteros, puede ser ms difcil de entender para un programador iniciado. A continuacin mostramos algunas formas de acceder al primer elemento de un arreglo versin puntero. int a[10], *pt; pt = &a[0]; /* copia en pt la direccin de memoria de a[0] */ Otra forma podria ser: pt = a; /* copia en pt la direccin de memoria de a[0] */ PASANDO ARRAYS A FUNCIONES Al pasar un array a una funcin, realmente estamos pasando la direccin de memoria del primer elemento. Ejemplo: #define NMAX 10 main() /* imprime los valores de un array */ { int a[NMAX], i; for(i=0; i<NMAX; i++) a[i]=i; display(a); } display(s) int s[]; { int j; for(j=0; j<NMAX; j++) printf("%d ",s[j]); getche(); } /**** * * invierte un array * ****/

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

37

void _areverse(); #include "stdio.h" #define NMAX 4 main() { int a[NMAX], i; for(i=0; i<NMAX; i++) a[i] = i; _areverse(a); for(i=0; i<NMAX; i++) printf("%d\n",a[i]); printf("........%d\n",sizeof(a)); getche(); } void _areverse(x) int x[]; { int j = NMAX / 2, l = NMAX - 1, t, k; printf("------ %d\n",sizeof(x)); for(k=0; k<j; k++, l--) { t=x[k]; x[k]=x[l]; x[l]=t; } } int media(); main() { int arr[5], x; for(x = 0; x < 5; x++) arr[x] = x; printf("La media aritmetica es %d\n", media(arr, 5)); } /***** * * media(array, n) * *****/

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

38

int media(a_vlrs, n) int *a_vlrs, n; { int i; int suma; if(n > 0) { for(i = 0, suma = 0; i < n; ++i) suma += *(a_vlrs + i); return((int) (suma / n)); } else { printf("Elementos no hallados\n"); return(0); } } Observe que *a_vlrs es un puntero al primer elemento del array y adems pudo haberse declarado como a_vlrs[]. ARREGLOS DE APUNTADORES Al hacer una declaracin como la siguiente : char *lineas[MAX_LINE]; se obtiene un array de apuntadores, o cuando hacemos declaraciones como: char s[]; char *s;

INICIALIZACION DE ARREGLOS DE APUNTADORES A continuacin encontramos un ejemplo de arrays de apuntadores y su inicializacin. Ejemplo : /* encontrando el nombre del mes a partir de su numero */ char *month_name(); main() { int x = 6; printf("mes de %s\n", month_name(x)); } /***** * * month_name(n)

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

39

* devuelve el nombre del mes * *****/ char *month_name(n) int n; { static char *name[] = { "mes fuera de rango", "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" }; return((n < 1 || n > 12) ? name[0] : name[n]); } APUNTADORES A CARACTERES Y FUNCIONES Una constantes de cadena como : "Hola mundo..." es un arreglo de caracteres a la cul el compilador aade internamente el caracter terminador nulo (\0). De esta manera es posible que un programa pueda encontrar el final de la cadena. Ejemplo : main() /* demostracin de apuntadores a caracteres */ { char *mensaje = "esto es una prueba"; while(*mensaje) printf("%c", *mensaje++); } El tamao de una cadena es uno ms que el nmero de caracteres que aparecen entre comillas. Si hacemos uso de una funcin como la siguiente en un programa: printf("El poder del lenguaje C\n")l La funcin printf recibe un puntero de tipo caracter al primer elemento de la cadena de

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

40

caracteres. Tambin es posible declarar variables como punteros a cadenas como: char *mensaje; Luego es posible hacer una asignacin de la siguiente forma: mensaje = "error de e/s"; Recuerde que mensaje no contiene la copia de la cadena, sino que apunta al primer caracter de la cadena. El lenguaje C no tiene manera de manipular cadenas como una entidad. Ejemplos: main() /* demostracin de apuntadores a caracteres */ { char *mensaje = "esto es una prueba"; printf("%s\n", mensaje); } #include "stdio.h" main() /* ejemplo de strcpy() */ { char a[20]; strcpy(a, "cadena de prueba"); puts(a); } /***** * * funcion xstrcpy() * copia cadena origen en destino * *****/ xstrcpy(dest, orig) char *dest, *orig; { while(*dest++ = *orig++) ; } FUNCIONES DE TIPO PUNTERO Otra de las posibilidades que tenemos al programar en lenguaje C es hacer uso de funciones que devuelven punteros.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

41

Ejemplo: /***** * * STRING.C * devuelve n caracteres * *****/ char *string(); main() { printf("%s", string('*', 5)); } /***** * * string(<expC>, <expN>) * *****/ char *string(ch, n) char ch; int n; { int i; char x_str[200]; for(i=0; i<n; ++i) x_str[i]=ch; x_str[i]='\0'; return(x_str); } LOS ARGUMENTOS DE main() La funcin main() tiene 3 argumentos de los cuales estudiaremos dos. Estos argumentos hacen posible que un programa permita argumentos al momento de ejecutarlo. Los dos argumento ms importantes de main() son argv y argc que estudiaremos a continuacin. argv : Es un arreglo de punteros de tipo char donde cada uno seala al comienzo de cada argumento dado al frente del nombre de un programa al momento de ejecutarlo. argc : Es un contador de tipo int que nos dice cuntos argumentos fueron pasados a main(). Ejemplo:

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

42

/* visualiza argumentos */ main(argc, argv) int argc; char *argv[]; { while(--argc > 0) printf("%s%c", *++argv, (argc > 1) ? ' ' : '\n'); } ASIGNACION DINAMICA DE MEMORIA malloc y free malloc: Asigna memoria del montculo Formato: void *malloc (unsigned int n) n :tamao de la memoria a asignar Devuelve el puntero al primer Byte. Si no hay suficiente memoria disponible se produce un fallo y Ejemplo: float *f; f=(float *) malloc (sizeof(float)); if (!f) { printf ("error de asignacin \n"); exit (1); } free: Devuelve o libera la memoria previamente asignada. Formato: free (void *p); Recomendacin: Incluye el archivo "stdlib.h". Ejemplo: #include "stdlib.h" main() /* demostracin de asignacin dinmica */ { int *p,t; p= (int *) malloc (40 * sizeof (int)); if (!p) { printf ("error de asignacin \n"); exit (1);

devuelve nulo

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

43

} for(t=0; t<40;++t) *(p++)=t ; for( t=0; t<40; ++t) printf("%d ",*(p+t)); } ESTRUCTURAS Una estructura se puede definir como un conjunto de campos los cuales conforman una unidad de informacin. Cada campo o miembro de la estructura puede ser de diferente tipo. Formato: struct [identificador] { tipo identificador; . . . }[identificador[,identificador, ...]]; Ejemplo: struct usr { int nro_usr; char nombre[35]; float cuota; } reg_usr; Otra posible forma seria: struct usr { int nro_usr; char nombre[35]; float cuota; }; struct usr reg_usr; ESTRUCTURAS ANIDADAS Una estructura puede contener miembros compuestos por otras estructuras en tal caso se dice que hay una estructura anidada. Ejemplo: struct date { int day; int month;

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

44

int year; }; struct usr_date { int nro_usr; char nombre[35]; struct date date_in; struct date date_out; } reg_usr; REFERENCIANDO MIEMBROS DE UNA ESTRUCTURA Para referenciar los miembros de una estructura es necesario hacer uso de el operador punto (.) flecha (->). Ejemplo: reg_usr.nro_usr = 453; printf("%s\n", reg_usr.nombre); reg_usr.date_in.day = 15; Los miembros de una estructura pueden ser apuntadores. Ejemplo: struct usr { char *name; char *keyword; }; /* Un ejemplo ms */ struct data { int ident; char *text; } Xdat; main() { Xdat.ident = 454; Xdat.text = "cadena"; printf("%d %s\n",Xdat.ident, Xdat.text); } ARRAYS DE ESTRUCTURAS Es posible crear arreglos de estructuras, a continuacin ilustramos este aspecto.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

45

#define NMAX 100 struct key { int nro; char *keyword; } lst_key[NMAX]; En el ejemplo anterior se ha declarado un array de 100 estructuras. INICIALIZACION DE ESTRUCTURAS /*** * programa de demostracion de inicializacion * (arrays de estructuras) * */ struct date { char *cmonth; int nmonth; } month[12] = { "Ene", 1, "Feb", 2, "Mar", 3, "Abr", 4, "May", 5, "Jun", 6, "Jul", 7, "Ago", 8, "Sep", 9, "Oct",10, "Nov",11, "Dic",12 }; main() { int i; for(i = 0; i <= 11; ++i) printf("%s %2d\n", month[i].cmonth, month[i].nmonth); } PASO DE ESTRUCTURAS Y MIEMBROS DE ESTRUCTURA A NUNA FUNCION PASANDO ELEMENTOS INDIVIDUALES A UNA FUNCION De igual manera que se pasa una varible no estructurada a una funcin es posible pasar cada campo simple de una estructura.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

46

Ejemplo: /*** * demostracion de estructuras * pasando elementos de una estructura a una funcion * pasa parametros por referencia */ /* intercambio de valores de los campos de una estructura */ main() { static struct { int a; int b; } d = { 4, 8}; printf("a = %d b = %d antes del cambio\n", d.a, d.b); swap(&d.a, &d.b); printf("a = %d b = %d despues del cambio\n", d.a, d.b); } /*** * udf swap() * recibe : punteros a cada campo de estructura * devuelve: datos intercambiados */ swap(x, y) int *x, *y; { int t; t = *x; *x = *y; *y = t; } PUNTEROS A ESTRUCTURAS Para pasar una estructura a una funcin se puede proceder enviando cada uno de sus elementos individualmente o enviando un apuntador a la estructura. Ejemplo: /*** * demostracion del paso de estructuras a una funcion */

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

47

#include <stdio.h> struct { char *name; int nro_cta; float saldo; } reg; main() { void ajuste(struct reg *pt); /* prototipo */ static struct reg usr = { "Maria", 3423, 555860.5 }; printf("%10s %4d %9.2f\n", usr.name, usr.nro_cta, usr.saldo); ajuste(&usr); printf("%10s %4d %9.2f\n", usr.name, usr.nro_cta, usr.saldo); } /*** * udf ajuste() */ void ajuste(struct reg *pt) { pt->name = "Seferino"; pt->nro_cta = 5000; pt->saldo = 2000; } El operador flecha ( -> ) es comunmente usado cuando se trabaja con punteros a estructuras ya que es ms comodo que la notacin (*varest).miembro. ESTRUCTURAS AUTOREFERENCIALES Una estructura es autoreferencial cuando uno de sus miembros es Este tipo de estructura es utilizado para creacin de estructuras de datos tales como listas. Ejemplo: /*** * crea una lista */ #include <stdio.h> #define LOCALIZAR (struct nodo *) malloc(sizeof(struct nodo))

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

48

struct nodo { int info; struct nodo *sig; }; main() { struct nodo *cab, *q; int i = 10; cab = NULL; while(i > 0){ q = LOCALIZAR; q->info = i; q->sig = cab; cab = q; i--; } } TIPOS DE DATOS DEFINIDOS POR EL USUARIO typedef typedef es usado para definir nuevos tipos de datos que los programadores requieren con frecuencia para dar mayor claridad en cuanto a documentacin de un programa. Ejemplo: typedef int ENTERO; y luego declarar: ENTERO a, i, j; Ejemplo: typedef char *CADENA; y luego declarar: CADENA ch, lineas[NMAX]; Ejemplo: typedef struct usr { int nro; char name[35]; } REGISTRO; REGISTRO usr_reg;

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

49

CAMPOS BIT Los campos bit son un medio adecuado para manipular datos bit a bit en un byte. Existen varias razones que hacen de los campos bit una herramienta de programacin de extrema utilidad. Algunas de estas razones son las siguientes: Los campos bit nos permiten almacenar en un mismo byte datos de tipo booleano (Verdadero/Falso) lo cual significa un ahorro de espacio. Algunos dispositivos transmiten informacin codificada en bits de un byte. Es posible encriptar informacin manipulando los bits de cada byte para hacer de esta manera un encriptado ms eficiente e impenetrable. El formato para la definicin de campos bit es: struct [identificador] { tipo identificador : longitud; . . . }[identificador [, identificador, ...]]; Ejemplo: struct bits { unsigned a: 1; unsigned b: 1; unsigned c: 1; unsigned d: 1; unsigned e: 1; unsigned f: 1; unsigned g: 1; unsigned h: 1; } byte; Usted puede apreciar que los campos bit son declarados como unsigned debido a que cada bit de la palabra debe ser 1 0 sin tener en cuenta el signo. Algunos compiladores ordenan los campos bit de derecha a izquierda mientras que otros lo hacen en sentido contrario. Nosotros asumiremos la ordenacin de derecha a izquierda. En el ejemplo anterior los campos bits pueden ilustrarse as: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

50

-------------------- h g f e d c b a Sin usar podriamos declarar otra estructura de campos bit como: struct { unsigned a : 1; unsigned b : 1; unsigned c : 5; unsigned d : 2; unsigned e : 3; unsigned f : 4; } word; En este ejemplo estamos haciendo uso de toda la palabra y podriamos esquematizarla as: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ---------- ------- ----- ------------ b a f e d c UNIONES Las uniones se tratan de estructuras donde el mismo area de almacenamiento es compartido por varios miembros. Ejemplo : union word { char w[2]; int i; 0 Xword; Esto podria ser esquematizado de la siguiente manera: Xword +------------------+ w -------+-------w[0] w[1] +------+------+ i +-----------------+ A continuacin mostramos un ejemplo que cubre uniones y campos bit: /*** * toma caracteres del teclado y los visualiza en binario (ASCII) */

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

51

#include <stdio.h> #include <conio.h> /* estructura de campos bit (un byte) */ struct byte { unsigned a : 1; unsigned b : 1; unsigned c : 1; unsigned d : 1; unsigned e : 1; unsigned f : 1; unsigned g : 1; unsigned h : 1; }; /* se comparte la misma area de memoria como un caracter (ch) o como ocho bits que pueden manejarse individualmente (bit) */ union bits { char ch; struct byte bit; } ascii; void decodifica(union bits b); /* prototipo */ main() { while((ascii.ch = getche()) != 'q') { printf(": "); decodifica(ascii); } } /*** * udf decodifica() * recibe : union del tipo bits * devuelve : nada */ void decodifica(union bits b) { printf("%d ", (b.bit.h) ? 1 : 0); printf("%d ", (b.bit.g) ? 1 : 0); printf("%d ", (b.bit.f) ? 1 : 0); printf("%d ", (b.bit.e) ? 1 : 0); printf("%d ", (b.bit.d) ? 1 : 0); printf("%d ", (b.bit.c) ? 1 : 0);

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

52

printf("%d ", (b.bit.b) ? 1 : 0); printf("%d ", (b.bit.a) ? 1 : 0); printf("\n"); } /*** * demostracion de campos bit */ #include <stdio.h> main() { unsigned m, d, a; static struct { unsigned a : 2; unsigned b : 2; unsigned c : 3; unsigned d : 1; } cbit = { 3, 5, 7, 1}; printf("%d %d %d %d\n", cbit.d, cbit.c, cbit.b, cbit.a); /* salida : 1 7 1 3 */ } Analice la salida del anterior programa. Preste atencin especial en el contenido del campo b. ENUMERACIONES La enumeracin es un tipo de datos similar a la estructura o la unin. Sin embargo sus miembros son constantes con valores establecidos. Formato: enum [identificador] { identificador, . . . } [identificador [,identificador,...]]; Ejemplo: enum colores {negro, azul, cyan, verde, magenta, rojo,

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

53

blanco, amarillo }; enum colores fondo, primerplano; Se puede hacer la misma definicin de la siguiente forma: enum {negro, azul, cyan, verde, magenta, rojo, blanco, amarillo } fondo, primerplano; Automaticamente los valores para cada constante de la enumeracin serian: negro 0 azul 1 cyan 2 verde 3 magenta 4 rojo 5 blanco 6 amarillo 7 Los valores automaticos que se le asignan a las constantes de la enumeracin pueden ser modificados. Ejemplo: enum {negro, azul = 4, cyan, verde, magenta, rojo, blanco, amarillo } fondo, primerplano; Los valores para las constantes de enumeracin son ahora: negro 0 azul 4 cyan 5 verde 6 magenta 7

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

54

rojo 8 blanco 9 amarillo 10 Podriamos hacer asignacines como las siguientes; primerplano = blanco; Es posible condicionar las costantes de enumeracin: if(fondo == azul) primerplano = blanco; else primerplano = azul; Otra forma valida podria ser: switch(fondo) { case negro: primerplano = blanco; break; case azul: cyan: verde: magenta: rojo: primerplano = amarillo; break; case blanco: primerplano = negro; break; case amarillo: primerplano = azul; break; default: puts("Error en seleccin del color de fondo"); } OPERADORES AVANZADOS OPERADORES DE BITS En algunas aplicaciones puede ser necesario el manejo de los bits individuales de una palabra. Frecuentemente se hace uso del lenguaje Ensamblador para tal proposito. Sin embargo el lenguaje C dispone de un conjunto de operadores que manipulan eficientemente los bits.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

55

OPERADOR DE COMPLEMENTO A UNO (~) Este operador se aplica a un solo operando y su funcin es la de negar es decir, los bits que estan en uno (1) se convierten en cero (0) y los bits cero (0) se combierten en uno(1). El operando debe ser un entero (char, int, long, unsigned, short). Ejemplo: OPERADOR LOGICO Y (&) A NIVEL DE BITS Da como resultado un uno (1) si el bit del primer operando y el segundo operando es uno (1). En otro caso el resultado sera cero (0). Ejemplo: OPERADOR LOGICO O (|) A NIVEL DE BITS Da como resultado un uno (1) si por lo menos el bit del primero o segundo operando esta en uno (1). Ejemplo: OPERADOR LOGICO O EXCLUSIVO (^) A NIVEL DE BITS Da como resultado un uno (1) si el bit del primer oprando esta en uno (1) y el bit del segundo operando esta en cero (0) o lo contrario. En cualquier otro caso da como resultado cero (0). Ejemplo: OPERADOR DE DESPLAZAMIENTO DE BITS A LA DERECHA ( >> ) Desplza o mueve todos los bits a la derecha el nmero de posiciones especificado. Si el oprando es de tipo unsigned se asegura que las posiciones a la izquierda se llenaran con cero (0). Ejemplo: OPERADOR DE DESPLAZAMIENTO A LA IZQUIERDA ( << ) Desplza o mueve todos los bits a la izquierda el nmero de posiciones especificado. Ejemplo: ENTRADA Y SALIDA (ARCHIVOS) /*** * copia cualquier archivo */

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

56

#include <stdio.h> #include <stdlib.h> main(argc, argv) int argc; char *argv[]; { FILE *in, *out; char ch; if(argc != 3){ puts("Error en parametros..."); exit(1); } if((in=fopen(argv[1],"rb"))==NULL) { puts("No puedo abrir archivo..."); exit(1); } if((out=fopen(argv[2],"wb"))==NULL) { puts("No puedo abrir archivo..."); exit(1); } while(!feof(in)) putc(getc(in), out); fclose(in); fclose(out); } /*** * * las funciones fgets() y fputs() * char *fgets(char *str, FILE *fp); * char *fputs(char *str, int long, FILE *fp); *---------------------------------------------------------* fgets() : lee una cadena desde la corriente especificada * hasta que encuentra el caracter de nueva linea * fputs() : escribe una cadena en la corruente especificada */ #define TAM 100 #include <stdio.h> #include <string.h> main(argc, argv) int argc; char *argv[]; {

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

57

FILE *fp; int x; char Xstring[TAM]; if(argc != 2){ puts("Uso : prog <file>"); exit(1); } if((fp=fopen(argv[1], "w"))==NULL){ puts("Error en apertura de datos"); exit(1); } printf("-=> "); gets(Xstring); while(strlen(Xstring) != 0){ fputs(Xstring, fp); printf("-=> "); gets(Xstring); } fclose(fp); } /*** * * las funciones fgets() y fputs() * char *fgets(char *str, FILE *fp); * char *fputs(char *str, int long, FILE *fp); *---------------------------------------------------------* fgets() : lee una cadena desde la corriente especificada * hasta que encuentra el caracter de nueva linea * fputs() : escribe una cadena en la corruente especificada */ #define TAM 100 #include <stdio.h> #include <string.h> main(argc, argv) int argc; char *argv[]; { FILE *fp; int x; char Xstring[TAM]; if(argc != 2){ puts("Uso : prog <file>"); exit(1);

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

58

} if((fp=fopen(argv[1], "r"))==NULL){ puts("Error en apertura de datos"); exit(1); } while((fgets(Xstring, TAM, fp)) != NULL) printf("%s", Xstring); fclose(fp); } /*** * * la funcion fseek() * int fseek(FILE *fp, long num_bytes, int origen); * establece el localizador de posicion en un byte especifico * num_byte : numero de bytes desde el origen a alcanzar la nueva * posicion * * origen : * comienzo del archivo SEEK_SET 0 * posicion actual SEEK_CUR 1 * fin de archivo SEEK_END 2 */ #include <stdio.h> #define SIZE 20 main() { FILE *fp; char ch; if((fp = fopen("texto", "rb")) == NULL){ puts("Error en apertura de archivo"); exit(1); } fseek(fp, SIZE, 0); ch = getc(fp); putchar(ch); fclose(fp); }

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

59

INTERRUPCIONES LA ROM-BIOS Est activa durante todo el tiempo que est trabajando el computador. La ROM-BIOS proporciona todos los servicios fundamentales que se necesitan para que puedan llevarse a cabo todas las operaciones del computador. Por lo general el BIOS controla los dispositivos perifericos tales como la pantalla, el teclado y controladores de disco. Dentro del BIOS se encuentran los programas encargados de realizar el control de dispositivos. Los programas residentes en BIOS transforman un simple comando de un programa en toda la secuencia de pasos necesarios para que se desarrolle en forma efectiva dicha accin. ROM-BIOS guarda ademas la hora y el dia. VECTORES DE INTERRUPCION Los computadores IBM PC como todos los basados en la familia de microprocesadores 8086 de INTEL se controlan a traves del uso de interrupciones, que se pueden generar o bien por hardware o bien por software. Cada vez que se necesita un servicio se debe indicar en la interrupcion el nmero asociado a ella. Cuando ocurre una interrupcin, el control del computador pasa a la rutina de tratamiento de la interrupcion. Las direcciones segmentadas utilizadas para localizar la rutinas de tratamiento de interrupciones se llaman vectores de interrupcion. Los vectores de interrupcion se establecen en el momento en que se carga el sistema operativo. Las interrupciones quedan almacenadas en RAM como tablas formando una especie de pares de palabras, con la porcion de la direccion relativa, en primer lugar, y la porcion del segmento en segundo lugar. El programa de gestion de la interrupcin se llama cargando su direccin segmentada en el registro que controla el flujo del programa : Registro CS (segmento de codigo) y el registro IP (puntero de instrucciones) o par CS:IP. Cada interrupcin tiene un grupo asociado de opciones. Las interrupciones del PC se pueden dividir en siete categorias las cuales son: 1. Microprocesador 2. Hardware 3. Software 4. DOS 5. BASIC 6. Direccionamiento 7. Generales INTERRUPCIONES DEL MICROPROCESADOR: Se conocen tambien como interrupciones

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

60

logicas, estan integradas en el propio microprocesador, cuatro de ellas son (0, 1, 3, 4) son generadas por el propio microprocesador. La interrupcion 2 o interrupcion no enmascarable se activa mediante una seal que envia un dispositivo externo. INTERRUPCIONES HARDWARE : Estan implementadas en el hardware del PC. Ocho de estas interrupciones estan cableadas en el interior del microprocesador, o en la placa principal (tarjeta madre) y no pueden ser modificadas. Todas las interrupciones hardware son supervisadas por el chip 8259A PIC. Los codigos reservados son 2, 8, 9 y del 11 al 15. INTERRUPCIONES SOFTWARE : Estan incorporadas dentro del diseo del PC y son parte de los programas de la ROM-BIOS. Las rutinas del BIOS no pueden cambiarse, pero los vectores que aputan a esas rutinas pueden ser alteradas para que apunten a rutinas diferentes. Los codigos reservados son: 5, 16 al 28 y 72. INTERRUPCIONES DOS : Se encuentran siempre disponibles cuando el DOS esta en uso. Algunos lenguajes y programas hacen uso de estos servicios a traves de interrupciones DOS para manejar sus operaciones basicas de entrada y salda del disco. Los codigos reservados van del 32 al 255 (se aconseja usar del 32 al 96 el resto no conviene tocarlos). INTERRUPCIONES BASIC : Son asignadas por el BASIC y estan disponibles cuando se utiliza BASIC. Los codigos reservados van del 128 al 240. INTERRUPCIONES DE DIRECIONAMIENTO : Son una parte de la tabla de los vectores de interrupcion y se utilizan para almacenar direcciones segmentadas. No hay rutinas de tratamiento asociadas a estas interrupciones. En particular estan asociadas con tres tablas muy importantes : 1. La inicializacin de video 2. La tabla base de disco 3. La tabla de caracteres graficos Estas tablas contienen parametros que utiliza la ROM-BIOS en procedimientos de puesta en marcha y ademas para la generacion de caracteres graficos. Los codigos reservados van del 29 al 31, 68 y el 73 (78 y 63 solo para PCJr). INTERRUPCIONES DE USO GENERAL : Estn establecidas para los programas para su uso temporal. Los codigos reservados van del 96 al 103. Los vectores de interrupcin estan almacenados en las localizaciones ms bajas de memoria. La primera localizacin de memoria contiene el vector para la interrupcion numero 0 (cero) y asi sucesivamente. Para encontrar la localizacin de cualquiera interrupcion se multiplica el numero de interrupcin por cuatro, debido a que cada vector tiene una longitud de dos palabras. por ejemplo el vector para interrupcion 5 (interrupcion de servicio de escritura en pantalla) tendra el byte de direccion relativa 20 (5 x 4 =20).

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

61

Con la ayuda del depuador del sistema DEBUG y dando este valor en hexadecimal podemos examinar el vector de interrupcion del mismo. Ejemplo: 20 decimal es igual a 14 hexadecimal de esta manera podriamos escribir: DEBUG <cr> D 0000:0014 L 4 <cr> La respuesta seria: 54 FF 00 F0 Convirtiendo este resultado en una direccion segmentada y teniendo en cuenta el almacenamiento "back word" (palabra invertida), se puede apreciar que el vector de interrupcion para el punto de entrada en la ROM de la rutina es F000:FF54. EL MICROPROCESADOR 8088 El 8088 es un microprocesador de 16 bits (CPU). El 8088 controla las operaciones basicas del ordenador, envia y recibe seales de control, direcciones de memoria y datos de una parte a otra del computador a traves de la red electronica de interconecciones llamadas bus. A lo largo del bus se encuentran los puertos de E/S, las diversas memorias y los chips de soporte. Dentro del 8088 existen 14 registros, que proporcionan un area edecuada para poder realizar la transferencia de los datos y su procesamieto. Los 14 registros del 8088 forman una memoria de 28 bytes y pueden almacenar datos, direcciones de memoria, punteros de instruccin e indicadores de estado y control. LOS CHIPS DE SOPORTE El microprocesador por si solo no es capaz de controlar todo el computador para lo cual delega algunas funciones a otros chips, pudiendo de esta manera encargarse de su propio trabajo. Aunque existen muchos chips de soporte en nuestro estudio solo trataremos el controlador de interrupciones 8259. EL CONTROLADOR 8259 (Controlador de interrupciones) Este chip supervisa la realizacin de las interrupciones. Las interrupciones son seales enviadas a la CPU por el hardware para requerir su atencin, o responder a alguan accin. Este chip intercepta las seales, determina su nivel de prioridad con relacin a otras seales que se esten recibiendo y activa una seal de interrupcin de la CPU en funcin de su desicin. En cuanto la CPU recibe la seal de interrupcin, llama a un programa especifico asociado con el dispositivo periferico involucrado en el proceso. Es este programa el que llevar a cabo la accin especifica. Luego de haber terminado la ejecucin de la rutina llamada en la interrupcin, el control vuelve nuevamente al sitio donde estaba cuando ocurrio la interrupcin. Hay tres categorias principales de interrupciones.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

62

Interrupciones generadas por la circuiteria del ordenador en respuesta a algun acontecimiento, tal como la pulsacin de una tecla. Estas interrupciones son manejadas por el chip 8259, el cual le d prioridad en orden de importancia antes de enviarlas a la CPU. Interrupciones generadas por la CPU como resultado de alguna operacin inusual producida por el programa por ejemplo divisin por cero. Interrupciones generadas por los programas como un camino para invocar servicios almacenados en ROM o RAM estas interrupciones reciben el nombre de interrupciones por software y sern nuestro tema principal para lograr algunas funciones como el borrado de la pantalla y otras en nuestro curso de lenguaje C. Es posible crear nuevas rutinas de interrupcin y hacer que los vectores de interrupcin apunten a ellas para que as puedan ser ejecutadas en el momento que se requieran. Las interrupciones guardan automaticamente los valores contenidos en los registros (CS) e (IP). De esta forma el computador puede volver al sitio donde estaba cuando se produjo la interrupcin. COMO DIRECCIONA LA MEMORIA EL 8088? El 8088 direcciona la memoria de tres maneras: -Forma directa o indirecta -A traves de punteros. -Mediante interrupciones La memoria puede ser utilizada para leer o escribir. Los datos se almacenan en localizaciones que se identifican a traves de un nmero llamado direccin de memoria. Se puede acceder directamente a la memoria por medio del chip 8237A, o controlador de acceso directo a memoria (DMA) o indirectamente a traves de los registros internos del 8088. El controlador de disco y puertos en serie pueden acceder directamente a la memoria a traves del controlador (DMA) el resto de dispositivos transfiere datos a y desde la memoria haciendo uso de registros del 8088. USO DE LOS RECURSOS DEL SISTEMA Permiten: 1. Acceso directo a los recursos del sistema operativo. 2. Acceso al entorno del computador. 3. Acceso a rutinas standard de biblioteca. 4. Manejar una funcin por uno mismo. FAMILIA DE MICROPROCESADORES INTEL 8086 Contiene 14 registros en los que pone la informacin para procesar o el programa de control. Los registros se dividen en 4 categorias: 1. De proposito general. 2. De base de puntero indice. 3. De segmento.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

63

4. De proposito especial. Cada registro tiene una longitud de 16 bits (2 Bytes). 1. Registros de proposito general Son registros de trabajo de la CPU. En ellos se ponen los valores para su procesamiento. El procesamiento incluye : Sumar, restar, multiplicar, dividir, comparaciones, bifurcaciones. A cada registro de proposito general se accede de dos formas: -Como registro de 16 bits. -Como registro de 8 bits. 2. Registros base de puntero e indice. Proporcionan soporte a cosas como direccionamiento relativo, puntero de pila e instrucciones para mover un bloque. 3. Registros de segmento. Soportan el esquema de memoria segmentada del 8086. CS :Segmento de codigo actual. DS :Segmento de datos actual. ES :Segmento extra. ES :Segmento de pila. 4. Registros de proposito especial. Registro de indicadores. Guardan el estado de la CPU. Registro puntero de instrucciones. Apunta a la siguiente instruccin en la CPU. UNA VISION DETALLADA DE LOS REGISTROS DEL 8088. Registros de proposito general

Registros de puntero e indice SP Puntero de pila BP Puntero base Registros de segmento CS Segmento de codigo DS SS Segmento de pila ES SI Puntero indice DI Indice destino

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

64

Segmento de dato Segmento extra registros de proposito especial IP Registro indice Puntero de instrucciones

Las interrupciones del 8086 y PC-DOS Una interrupcin es un tipo de instruccin especial que provoca la parada en la ejecucin del programa, guarada el estado actual del sistema en la pila y salta a la rutina de manejo de la interrupcin que se determina por el nmero de interrupcin. Luego regresa de vuelta de la interrupcin y reanuda la ejecucin del programa. Existen dos tipos de interrupcin: 1. Por hardware 2. Por software La instruccin INT es usada para llevar a cabo interrupciones. Ejemplo : INT 21h El nmero de interrupcin es usado para hallar el manejador de adecuado de interrupcin. Se reserva el primer Kilo Byte de memoria para usarlo con una tabla de vectores de interrupcn. Esa tabla contiene las direcciones de los manejadores de interrupcin, en forma de segmento/desplazamiento. Cada direccin requiere de cuatro Bytes. 256 vectores de interrupcin. INT 5 -=> 5 x 4 = 20 0014h. El sistema operativo ha asignado una serie de estos vectores para usar con el ROM-BIOS y DOS. Mediante interrupciones accedemos a funciones del sistema operativo. La funcin accedida es determinada por el registro AH, la informacin adicional se pasa en los registros AL, AX, CX y DX. El sistema operativo PC-DOS se divide en ROM-BIOS y DOS. /*** * INTER1.C * interrupcion ROM-BIOS 19h * activacion de la rutina de arranque del sistema * (bootstrap) *------------------------------------------------* Objetivo : Utilizo frecuentemente esta interrupcion para dos * cosas: * 1. El inmediato cierre de las operaciones del * computador cuando se encuentra una situacion * intolerable, por ejemplo el intento de copia de * un software. * 2. Para hacer un arranque del sistema sin hacer * las operaciones de reset y restart. */

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

65

#include <dos.h> void boot(); main() { boot(); } void boot() { union REGS r; int86(0x19, &r, &r); } /*** * INTER2.C * interrupcion DOS (21h) * Servicio : 35h Captar el vector de interrupcion * Entrada: * AH = 35 * AL = nro de interrupcion * Salida: * ES Segmento * BX Desplazamiento *------------------------------------------------*/ #include <dos.h> void showvec(); main() { showvec(); } void showvec() { int i; union REGS r; struct SREGS sr; for(i = 0; i < 256; ++i){ r.h.ah = 0x35; r.h.al = i; intdosx(&r, &r, &sr); printf("Interrupcion %3d, Segmento %8x Offset %8x\n", i, sr.es, r.x.bx);

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

66

} } /*** * INTER3.C * interrupcion DOS (21h) * escribir caracteres en la impresora *------------------------------------------------* Entrada: * AH = 5h * AL = caracter * Devuelve: * none */ #include <dos.h> void escricar(); char *output = "prueba"; main() { while(*output) escricar(*output); } void escricar(c) int c; { union REGS r; r.h.ah = 0x5; r.h.al = c; intdos(&r, &r); } /*** * INTER4.C * interrupcion ROM-BIOS 13h * sistema de disco * servicio : 1 * obtiene status del disco *------------------------------------------------* Entrada: * AH = 1 * Devuelve: * AL : 1 comando incorrecto * 2 marca de direccion no encontrada * 3 intento de escritura en disco protegido

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

67

* * * * * * * * */

4 sector no encontrado 6 disco retirado 8 rebasar el limite del DMA 9 DMA mas alla de los 64K 10 mal CRC 20 fallo del controlador NEC 40 falo de busqueda 80 time out

#include <dos.h> drive_st(); main() { int i; i = drive_st(); printf("%d\n", i); } drive_st() { union REGS r; r.h.ah = 0x1; return(int86(0x13, &r, &r)); } /* WHEREX.C obtiene la columna actual del cursor */ /* Uso : wherex(); */ /* Ejemplo : x = wherex(); */ #include <dos.h> union REGS regs; wherex() { regs.h.ah = 3; /* obtener posicion del cursor */ regs.h.bh = 0; /* para la pagina 0 */ int86(0x10, &regs, &regs); return(regs.h.dl); /* columna actual */ } /* WHEREY.C obtiene la fila actual del cursor /* Uso : wherey(); */ */

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

68

/* Ejemplo : y = wherey(); #include <dos.h> union REGS regs;

*/

wherey() { regs.h.ah = 3; /* obtener posicion del cursor */ regs.h.bh = 0; /* para la pagina 0 */ int86(0x10, &regs, &regs); return(regs.h.dh); /* fila actual */ } /* GOTOXY.C posiciona el cursor en un sitio de la pantalla */ /* Uso : gotoxy(x, y); */ /* Ejemplo : gotoxy(10, 2); col 10, fil 2 */ #include "dos.h" gotoxy(col, row) int col, row; { union REGS regs; regs.h.ah = 2; regs.h.bh = 0; regs.h.dh = row; regs.h.dl = col; int86(0x10, &regs, } EL SISTEMA EXTENDIDO DE CLIPPER Este capitulo contiene toda la informacin que usted necesita para escribir funciones de usuario en otros lenguajes como C o Assembler. Temas a cubrir: 1. Descripcin del sistema extendido de Clipper 2. Sumario de funciones extendidas 3. Haciendo la interface con C 4. Ejemplo de funciones C 5. Compilando y enlazando sus funciones C /* establece la posicion del cursor */ /* pagina de video 0 */ /* fila */ /* columna */ &regs);

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

69

6. Ejercicios de demostracin DESCRIPCION DEL SISTEMA EXTENDIDO DE CLIPPER La arquitectura abierta de Clipper permite escribir funciones en otros lenguajes y ademas dispone de herramientas para pasar y recibir parametros a o desde dichas funciones. Las funciones pueden ser llamadas desde cualquier programa Clipper que as lo requiera. Por ejemplo, el valor que devuelve una funcin puede ser almacenado en una variable, empleado en un calculo o desplegado en la pantalla. Ejemplo: Xvar_mem = funcion(<exp>) Es posible escribir funciones en Lenguaje C o Assembler 8088 mediante el sistema extendido de Clipper, luego puede enlazar estas funciones a sus programas de aplicacion Clipper compilados de antemano. Las funciones escritas en C o Assembler pueden ser usadas para obtener la informacin necesaria por un programa Clipper o para realizar alguna tarea procedimental. No se debe interntar hacer manejo de archivos usando funciones de entrada y salida como fopen(), open(), printf() etc. como tampoco es posible acceder a la estructura de los archivos de base de datos atravez de la forma convencional. Para lograr todo lo anterior se debe hacer uso de las interrupciones del DOS. Las funciones de usuario creadas en C o Assembler deben ser llamadas usando el mismo nombre con el cual fueron declaradas. No se permiten abreviaturas sin embargo la funcin puede ser llamada usando minusculas o mayusculas. Estas funciones de usuario pueden ser declaradas explicitamente en el programa de aplicacin o declaradas EXTERNAL al momento de compilarlas para luego ser incluidas como simbolos al momento de enlazarlas. Las funciones de usuario en un REPORT, LABEL FORMs o expresin INDEX, deben ser declaradas como EXTERNAL. Ejemplo: EXTERNAL func_1, func_2 SUMARIO DE FUNCIONES EXTENDIDAS Tipo de dato Prototipo C Assembler Clipper ________________________________________________________________ character char*_parc(int [,int]) __PARC datechar *_pards(int [,int]) __PARDS logicalint _parl(int [,int]) __PARL numericint _parni(int [,int]) __PARNI numericlong _parnl(int [,int]) __PARNL numericdouble _parnd(int [,int]) __PARND

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

70

int int int

_parclen(int [,int]) __PARLEN _parcsiz(int [,int]) __PARCSIZ _retclen(int) __RETCLEN

charactervoid_retc(char*) __RETC datevoid _retds(char*) __RETDS logicalvoid _retl(int) __RETL numericvoid _retni(int) __RETNI numericvoid _retnl(long) __RETNL numericvoid _retnd(double) __RETND (no return value)void_ret(void) __RET HACIENDO LA INTERFACE CON C Clipper permite la escritura de funciones de usuario en Lenguaje C mediante sistema extendido. Este mecanismo es el camino para llamar funciones especializadas que soportan el paso de parametros en ambos sentidos Clipper a C, C a Clipper. Estas funciones se hallan en la libreria Clipper. Las funciones de usuario en C pueden ser declaradas despues de incluir el archivo NANDEF.H y EXTEND.H. En estos archivos se encuentran las declaraciones y definiciones necesarias para escribir funciones de usuario en C. RECIBIENDO PARAMETROS EN C El concepto de parametros formales C desaparece de este punto. Todos los parametros pueden ser accedidos usando las funciones _par(). DEVOLVIENDO VALORES DESDE C Las funciones _ret() son usadas para devolver valores a Clipper. Estas funciones como toda funcin solo devuelven un valor. El uso de una de las funciones _ret depende del tipo de dato que se quiera devolver. EJEMPLO DE FUNCIONES C Este es el esquema de una funcion de usuario tipica para enlazar con Clipper. En C: CLIPPER <function_name>() /* parametros formales C omitidos */ { <declaracin de variables locales> if (<parametros son validos> { <codigo a ejecutar> } else {

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

71

<codigo a ejecutar para parametros indefinidos> return; } } En Clipper: DECLARE arr[3] arr[1] = "Devorah" arr[2] = 456.56 arr[3] = CTOD("09/01/87") Arrfunc(arr) En C: #include "extend.h" /* Declaras Sistema Extendido */ #include "stdio.h"/* libreria standard io */ #include "math.h"/* libreria standard math */ CLIPPER arrfunc() /* especifica CLIPPER */ /* typedef void pascal */ { int i; for (x = 1; x <= 3; ++x) { /* variables string */ if (_parinfa(1, x) == CHARACTER) { cprintf("%s\n", _parc(1, x)); } /* entero o de punto flotante */ if (_parinfa(1,X) == NUMERIC) { cprintf("%f\n", _parnd(1, x)); } else /* fecha */ if (_parinfa(1, x) == DATE) { cprintf("%s\n", _pards(1, i)); } } _ret(); } Nota: El uso de cprintf() es unicamente para proposito de demostracion. Le recomiendo que toda la entrada y salida la realice desde Clipper o la haga mediante el uso de interrupciones.

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

72

COMPILANDO Y ENLAZANDO SUS FUNCIONES C Si la funcin o funciones que desaean enlazar con sus programas Clipper fueron escritas en Microsoft C 5.0, es necesario que la compilacin se haga estableciendo los switchs de compilacin adecuados los cuales se describen a continuacin: CL /c /AL /Zl /Oalt /FPa /Gs <nombre_archivo>.c Donde: CL = Invoca el compilador CL.EXE /c = Compilar sin hacer enlace /AL = Genera codigo para modelo largo de memoria (L)arge /Zl = No hace busqueda en las librerias por defecto (l)ibrary-search /Oalt = control de optimizacin Donde: a = No chequea alias l = Habilita la optimizacin de los loop t = Ejecuta a la maxima velocidad /FPa = Manejo de punto flotante usando la libreria alterna. (a)lternate library /Gs = Quita las llamadas a rutinas para chequeo de pila (s)tack-checking routine Para Microsoft Quick C la compilacin es la siguiente: QCL /c /AL /Zl /Oalt /FPi /Gs <nombre_archivo>.c /FPi = Manejo de punto flotante emulada por software si no est caso de encontrarlo, este ser utilizado. /FPi87 = Manejo de punto flotante por Hardware 8087. ENLACE DE UNA FUNCION C CON UN PROGRAMA CLIPPER Para hacer el enlace se debe usar el enlazador que ms le simpatice. Particularmente me gusta trabajar con TURBO LINK de Borland (TLINK). Ejemplo: Suponga que desea enlazar una funcin C que se encuentra en un archivo llamado udf_c.obj con un programa Clipper que se encuentra en el archivo prog.obj. Imagine ademas que Clipper se encuentra en el directorio CLIPPER que se desprende del raiz: Las librerias Quick C se encuentran en el directorio QC25\LIB, entonces la linea de orden podria ser: TLINK prog + udf_c,,,\CLIPPER\CLIPPER+\CLIPPER\EXTEND+\QC25\LIB\LLIBCE MACROS C PREDEFINIDOS presente el 8087 en

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

73

Para simplificar la sintaxis y hacer ms legible el codigo, se ha colocado en el archivo EXTEND.H una serie de macros que permiten hacer el chequeo o validacin de los parametros pasados a la funcin de usuario: #defines en EXTEND.H Tipo Devuelve ------------------------------------indefinido = UNDEF caracter = CHARACTER numerico = NUMERIC logico = LOGICAL fecha = DATE por referencia = MPTR memo = MEMO arreglo = ARRAY MACROS C INTERFACE PREDEFINIDOS EXTEND.H MacroDefinido como -----------------------------------------------------PCOUNT(_parinfo(0)) ISCHAR(order) (_parinfo(order) & CHARACTER) ISNUM(order) (_parinfo(order) & NUMERIC) ISLOG(order) (_parinfo(order) & LOGICAL) ISDATE(order) (_parinfo(order) & DATE) ISMEMO(order) (_parinfo(order) & MEMO) ISBYREF(order) (_parinfo(order) & MPTR) ISARRAY(order) (_parinfo(order) & ARRAY) ALENGTH(order) (_parinfa(order, 0)) En una funcin de usuario, usted puede usar el macro PCOUNT y cualquiera de los macros IS<tipo> para determinar cuantos parametros se han pasado y de que tipo. Esto le permite validar para asegurarse de que si se han pasado los parametros correctos y el nmero esperado. REFERENCIA - FUNCIONES C INTERFACE DEL SISTEMA EXTENDIDO _parc() Pasa un puntero a una cadena de caracteres Clipper. Sintaxis de uso: #include <extend.h> char *_parc(order, index)

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

74

int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index; Indice para parametros tipo array. Descripcin: _parc() es usado para recibir parametros caracter que se pasan desde Clipper. Si se pasa parametro por valor, se har una copia de tipo char *. Si se pasa parametro por referencia, estar trabajando sobre el parametro actual Clipper (La misma direccin de memoria). _parclen() Devuelve la longitud de una cadena en caracteres. Sintaxis de uso: #include <extend.h> int _parclen(order, index) int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index; Indice para parametros tipo array. Descripcin: _parclen() devuelve la longitud de una cadena de caracteres pasada desde Clipper. _parclen() Obtiene la longitud de la cadena sin contar el terminador nulo. _parcsiz() Devuelve el tamao de una cadena. Sintaxis de uso: #include <extend.h> int _parcsiz(order, index) int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index; Indice para parametros tipo array. Descripcin: _parcsiz() Devuelve el nmero de bytes en memoria que ocupa una cadena especifica incluyendo el terminador nulo. _parsize() Devuelve cero para cuando se pasan constantes. Ejemplo:

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

75

DO <proces> WITH "ABC" _pards() Pasa un puntero caracter a una fecha Clipper. Sintaxis de uso: #include <extend.h> char *_pards(order, index) int order; sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index; Indice para parametros tipo array. Descripcin: _pards() Pasa un puntero char * a una fecha que se recibe desde Clipper. La fecha queda representada como una cadena en el formato YYYYMMDD. _parinfa() Permite chequear tipos de elementos de un arreglo que se ha pasado como parametro. Sintaxis de uso: #include <extend.h> int _parinfa(order, index) int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index;Indice para parametros tipo array. Descripcin: _parinfa() Devuelve el tipo al cual pertenece un elemento de un arreglo. _parinfa(<n>, 0) devuelve el nmero de elementos del array. Ejemplo: La siguiente funcin, arrfunc(), toma un array definido en Clipper y muestra todos los elementos formateados de acuerdo al tipo de dato. En Clipper: DECLARE array[2] array[1] = "Devorah" array[2] = 456.56

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

76

ArrFunc(array) En C: for (x = 1; x <= _parinfa(1, 0); ++x) { /* variables string */ if (_parinfa(1, x) == CHARACTER) { cprintf("%s\n", _parc(1, x)); } /* entero o punto flotante */ if (_parinfa(1, x) == NUMERIC) { cprintf("%f\n", _parnd(1, x)); } } _parinfo() Chequea el tipo de parametro. Sintaxis de uso: #include <extend.h> int _parinfo(order) int order; Sitio que ocupa el parametro en la lista Clipper.parameters to type-check Descripcin: _parinfo() Es usado para chequear el tipo de parametro pasado. _parinfo(0) Devuelve el nmero de parametros pasados y _parinfo(<n>) Devuelve el tipo de parametro <n> donde <n> es la posicin en la lista de parametros. El valor devuelto es uno de los siguientes: /* _parinfo types from extend.h*/ #define UNDEF 0 #define CHARACTER 1 #define NUMERIC 2 #define LOGICAL 4 #define DATE 8 #define ALIAS 16 #define MPTR 32 #define MEMO 64 #define WORD 128 #define ARRAY 512 de parametros pasados desde

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

77

Ejemplo: La siguiente funcin de usuario, cfunc(), recibe cuatro parametros desde Clipper, un tipo caracter, un tipo numerico, un tipo logico y un tipo fecha; declara las variables C que deben recibir los valore, y despues valida los parametros: CLIPPER cfunc() { char *parm1; double parm2; int parm3; /* logico declarado como int */ char *parm4; /* fecha declarado como char (YYYYMMDD) */ if (PCOUNT == 4 && ISCHAR(1) && ISNUM(2) && ISLOG(3) && ISDATE(4)) { <codigo a ejecutar si los parametros son validos> } else { <codigo a ejecutar si los parametros son invalidos> } } _parl() Pasa un entero como valor lgico, 1 = .T., 0 = .F. Sintaxis de uso: #include <extend.h> int _parl(order, index) int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index;Indice para parametros tipo array. Description: _parl() Recibe un parametro lgico desde Clipper y lo combierte en entero donde (1 = .T. and 0 = .F.). _parnd() Pasa un dato numerico doble. Sintaxis de uso:

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

78

#include <extend.h> double _parnd(order, index) int order;Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index; Indice para parametros tipo array. Descripcin: _parnd() Recibe un parametro numerico desde Clipper y lo convierte en doble. _parni() Pasa un dato numerico entero. Sintaxis de uso: #include <extend.h> int _parni(order, index) int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index;Indice para parametros tipo array. Descripcin: _parni() Recibe un dato numerico entero desde Clipper y lo convierte en entero. _parnl() Pasa un dato numerico largo. Sintaxis de uso: #include <extend.h> long _parnl(order, index) int order; Sitio que ocupa el parametro en la lista de parametros pasados desde Clipper. int index; Indice para parametros tipo array. Descripcin: _parnl() Recibe un parametro numerico desde Clipper y lo convierte en largo (long). _exmgrab()

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

79

Asigna memoria. Sintaxis de uso: #include <extend.h> unsigned char* _exmgrab(bytes) unsigned int bytes; Tamao de la memoria a asignar. Descripcin: _exmgrab() Asigna memoria del tamao solicitado. Si la asignacin tiene exito, devuelve un puntero char * a la direccin de comienzo de la memoria asignada; de otra manera, devuelve NULL. Ejemplo: size = 512 buff = _exmgrab(size)/* asignar memoria */ if (buff)/* si todo salio bien (!null) */ check = TRUE; _exmback() Libera la memoria asignada por _exmgrab(). Ejemplo: size = 512 buff = _exmgrab(size)/* asigna memoria */ if (buff)/* si todo salio bien (!null) */ check = TRUE; if (check) _exmback(buff, size);/* libera memoria */ _exmback() Libera la memoria asignada. Sintaxis uso: #include <extend.h> void * _exmback(pointer, bytes) unsigned char *pointer; Puntero de _exmgrab() unsigned intbytes; Tamao pasado a _exmgrab() Descripcin: Libera la memoria asignada por _exmgrab().

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

80

DEVOLVIENDO VALORES DESDE C _ret() No devuelve ningun valor a Clipper: #include <extend.h> void _ret(void) Descripcin: _ret() No devuelve ningun valor a Clipper. Es utilizado en funciones que devuelven nada. Funciones procedimentales. _retc() Pasa una cadena de caracteres a Clipper. Sintaxis de uso: #include <extend.h> void _retc(string) char *string; Puntero a string Descripcin: _retc() Devuelve una cadena de caracteres a Clipper. _retclen() Pasa la longitud de un string a Clipper. Sintaxis de uso: #include <extend.h> void _retclen(string, int) char *string; Cadena de caracteres a la cual se le quiere calcular su longitud. int; longitud de la cadena. Descripcin: _retclen() Devuelve la longitud de una cadena incluyendo CHR(0)s. _retds()

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

81

Pasa una cadena fecha a Clipper convirtiendola en tipo DATE Sintaxis de uso: #include <extend.h> void _retds(string) char *string; Fecha como cadena (YYYYMMDD) Descripcin: _retds() Pasa a Clipper una cadena como fecha char* YYYYMMDD. La cadena es convertida al formato DATE de Clipper. _retl() Pasa un entero a Clipper como valor lgiico. Sintaxis de uso: #include <extend.h> void _retl(flag) int flag; Valor Boolean Descripcin: _retl() Pasa a unentero a Clipper como un valor lgico, donde 1 es true (.T.) y 0 es false (.F.). _retnd() Pasa un double a Clipper. Sintaxis de uso: #include <extend.h> void _retnd(x); double x; Expresin numerica Descripcin: _retnd() Pasa un double a Clipper. El valor es convertido al tipo NUMERIC de Clipper. _retni()

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

82

Pasa un entero a Clipper. Sintaxis de uso: #include <extend.h> void _retni(n) int n; Expresin numerica Descripcin: _retni() pasa un entero a Clipper como dato NUMERIC. _retnl() Pasa un dato numerico largo a Clipper. Sintaxis de uso: #include <extend.h> void _retnl(n) long n; Expresin numerica long Descripcin: _retnl() Pasa un entero largo a Clipper como dato de tipo NUMERIC. EJERCICIOS DE DEMOSTRACION /*** * * DIRE.C * Funciones de usuario para manejo de directorios. * Nota : Para enlazar con CLIPPPER/SUMMER '87. * Estas funciones deben ser compiladas con Microsoft C 5.0 . * Fecha: Cartagena, Noviembre 22 De 1991. * Copyright (c) 1991. Anibal G. Martinez Arcia. * (Especialista en Lenguaje C). * * * *--------------------------------------------------------------* Contenido: * ========== * FUNCION PROPOSITO *--------------------------------------------------------------* get_drive() Obtiene la unidad por defecto.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

83

* set_drive() Establece la unidad por defecto. * makedir() Crea directorio. * changedir() Cambia de directorio. */ #include <dos.h> #include <nandef.h> #include <extend.h> #include <direct.h> /*** * get_drive() * Int DOS. (21h). * servicio 19h. Captar unidad de disco actual. * AH : 19h * AL : devuelve unidad de disco actual * : 0 = A, 1 = B, 2 = C, Etc. * Proposito : Captar unidad de disco actual. * Ej. Uso : var = get_drive() * */ CLIPPER get_drive() { static char *drv_name[] = {"A:", "B:", "C:", "D:", "E:", "F:"}; union REGS r; r.h.ah = 0x19; intdos(&r, &r); _retc(drv_name[r.h.al]); } /**** * set_drive() * Int DOS. (21h). * Servicio 0Eh. Selecciona la unidad de disco implicita. * AH : 0xE * DL : Unidad de disco deseada 0=A, 1=B, 2=C, etc. * AL : Salida -> numero total de unidades de disco * presente. * Proposito : Establecer unidad de disco implicita. * Ej. Uso : set_drive(1) */ CLIPPER set_drive() { int drive = _parni(1); union REGS regs; regs.h.ah = 0x0E; regs.h.dl = drive;

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

84

intdos(&regs, &regs); /* return(regs.h.al); */ _ret(); /* no debuelva nada */ } /*** * makedir(<path>) * Proposito : Crear directorio. * Recibe : Path. * Devuelve : 0 = Exito. -1 = Error. * Ej. Uso : var = makedir("\usr") */ CLIPPER makedir() { int error; char *path = _parc(1); error = mkdir(path); _retni(error); } /*** * changedir(<path>) * Proposito : Cambiar de directorio. * Recibe : Path. * Devuleve : 0 = exito. -1 = Error. * Uso : vas = changedir("\usr") */ CLIPPER changedir() { char *path = _parc(1); int error; error = chdir(path); _retni(error); } /*** * * STRING.C * Funciones de usuario para manejo de cadenas. * Nota : Para enlazar con CLIPPPER/SUMMER '87. * Estas funciones deben ser compiladas con Microsoft C 5.0 . * Fecha: Cartagena, Noviembre 22 De 1991. * Copyright (c) 1991. Anibal G. Martinez Arcia. * (Especialista en Lenguaje C). * * * *-------------------------------------------------------------

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

85

* Contenido: * ========== * FUNCION PROPOSITO *------------------------------------------------------------* cnt_cadena() Devuelve el numero de veces que una subcadena se * una cadena. */ #include <dos.h> #include <nandef.h> #include <extend.h> /*** * cnt_cadena(<expC1>, <expC2>) * Proposito : Devuelve el numero de veces que una subcadena se * encuentra * en una cadena. * <expC1> : Cadena. * <expC2> : Subcadena. * Ej. Uso : var = cnt_cadena("esto es una prueba", "es") */ CLIPPER cnt_cadena() { char *string = _parc(1); /* cadena */ char *sub_string = _parc(2); /* subcadena */ int i, j, k, conta = 0; for(i = 0; string[i]; i++) for(j = i, k = 0; sub_string[k] == string[j]; k++, j++) if(sub_string[k+1]){ conta++; /* encontro la cadena y se incrementa */ break; /* inicia busqueda de la siguiente ocurrencia */ } _retni(conta); } /*** * examplec.c * * Example "C" functions using the CLIPPER Extend interface. * * The CLIPPER callable functions are..... * * SOUNDEX() * STUFF() * DISKSPACE() * **/

encuentra en

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

86

/*** * SOUNDEX() * kevin j. shepherd, NANTUCKET Corporation. * 09/14/87 * * Produces a code based on the "Soundex" method originally * eveloped by M.K. Odell and R.C. Russell. Algorithm can * be found on page 392 of Knuths' book 'Sorting and * Searching', volume 3 of 'The Art of Computer * Programming", Addison/Wesley publisher. * * code = SOUNDEX(name) * * code - character string. * name - character string. * * Non-alphabetic characters in input stream will cause the * function to abort and return a NULL pointer. * **/ #include "nandef.h" #include "extend.h" #define ISALPHA(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z') #define UPPER(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 32 : (c)) #define MAX_OMITS 9 /** characters to be ignored **/ #define MAX_GROUPS 6 /** +1 for NULL pointer in static declare/init **/ #define MAX_DIGITS 4 /** number of digits in code sequence **/ #define CODE_ALLOC 5 /** size of code sequence **/ static byte omit_letter[MAX_OMITS] = " AEHIOUWY"; static byte *code_group[MAX_GROUPS + 1] = { "BFPV", "CGJKQSXZ", "DT", "L", "MN", "R", NULL }; extern Boolean name_2_code(); extern byte translate(); extern Boolean omit(); /*** *

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

87

* soundex() * kjs * 09/14/87 * * Main soundex function, does param checking, allocation, * string prep, and deallocation. * **/ CLIPPER SOUNDEX() { Boolean error; quant i; quant name_size; byte *name; byte *code; code = NULL; error = (PCOUNT != 1 || !ISCHAR(1) || _parclen(1) == 0); if (!error) { name = _parc(1); name_size = (quant)(_parclen(1) + 1); /** +1 for NIL byte **/ code = _exmgrab(name_size >= CODE_ALLOC ? name_size : CODE_ALLOC); /** make uppercase **/ for (i = 0; i < name_size; i++) name[i] = UPPER(name[i]); error = name_2_code(name, name_size, code); } if (!error) _retc(code); else _retc(""); if (code) _exmback(code, name_size >= CODE_ALLOC ? name_size : CODE_ALLOC); } /*** * * name_2_code() * kjs

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

88

* 09/14/87 * * Converts a name into 4 unit code (alpha, digit, digit, digit) * as per the SOUNDEX method rules. * * error = name_2_code(source, source_size, target) * **/ Boolean name_2_code(source, source_size, target) byte *source; quant source_size; byte *target; { Boolean error; quant i; quant j; error = FALSE; /** first character not translated **/ target[0] = source[0]; i = 1; j = 1; /** copy while filtering unwanted characters **/ while (i < (source_size - 1) && !error) { if ((target[j - 1] != source[i]) && !omit(source[i])) { error = !ISALPHA(source[i]); if (!error) { target[j] = source[i]; j++; } } i++; } /** truncate string **/ if (j > MAX_DIGITS) j = MAX_DIGITS; target[j] = NIL;

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

89

if (!error) { /** translation **/ for (i = 1; i < j; i++) target[i] = translate(target[i]); /** zero fill **/ for (i = j; i < MAX_DIGITS; i++) target[i] = '0'; target[i] = NIL; } return (error); } /*** * * translate() * * Translates a character into a code digit. * * digit = translate(chr) * **/ byte translate(chr) byte chr; { Boolean found; quant i; quant j; byte digit; found = FALSE; i = 0; j = 0; digit = NIL; /** scan groups until match is found **/ while (i < MAX_GROUPS && !found) { /** scan the list of character in this group **/ j = 0;

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

90

while (j < strlen(code_group[i]) && !found) { found = (chr == code_group[i][j]); j++; } if (!found) i++; } digit = (i + 1) + 48; /** convert the subscript to asci **/ return (digit); } /*** * * omit() * * Check the character if it is on the omit list. * * status = omit(chr) * **/ Boolean omit(chr) byte chr; { quant i; Boolean found; found = FALSE; for (i = 0; (i < MAX_OMITS && !found); i++) found = (chr == omit_letter[i]); return (found); } /*** * STUFF() * kevin j. shepherd, NANTUCKET Corporation. * 09/13/87 * * Replace LENGTH number of characters in SOURCE starting at START * with the entire MODIFIER string. *

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

91

* target = STUFF(source, start, length, modifier) * * target - character string. * source - character string. * start - numeric. * length - numeric. * modifier - character string. * **/ CLIPPER STUFF() { quant i; quant j; quant s_max; quant m_max; quant buffer_size; quant start; quant length; byte *source; byte *modifier; byte *buffer; /** parameter OK? **/ if (PCOUNT == 4 && ISCHAR(1) && ISNUM(2) && ISNUM(3) && ISCHAR(4) && _parclen(1) + _parclen(4) > 0) { /** local copies **/ source = _parc(1); modifier = _parc(4); start = (quant)(_parnl(2) >= 0 ? _parnl(2) : 0); length = (quant)(_parnl(3) >= 0 ? _parnl(3) : 0); /** string sizes **/ s_max = (quant)_parclen(1); m_max = (quant)_parclen(4); /** allocate a work buffer. **/ buffer_size = _parclen(1) + _parclen(4) + 1; buffer = _exmgrab(buffer_size); /** adjust dBASE string base values to 'C' base, off-by-one, yea! **/ start = (start > 0 ? start - 1 : 0); /** get first part of source string. **/ j = 0; while (j < start && j < s_max)

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

92

{ buffer[j] = source[j]; j++; } /** insert **/ i = 0; while (i < m_max) { buffer[j] = modifier[i]; j++; i++; } /** copy the rest of the source string. **/ i = start + length; while (i < s_max) { buffer[j] = source[i]; j++; i++; } buffer[j] = NIL; _retclen(buffer, j); _exmback(buffer, buffer_size); } else { _retc(""); } } /*** * DISKSPACE() * Tom Rettig, Brian Russell * 11/01/85 * * Bytes of empty space on a disk drive. The drive is specified * by the drive_code parameter. DRIVE_CODE is a numeric * from 0 to n. 0 is the default if code is omitted and * indicates the currently selected drive. 1 to n reference * drives A to x. * * count = DISKSPACE([drive_code]) * * count - numeric. * drive_code - numeric.

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

93

* * Placed in the public domain by Tom Rettig Associates. **/ #define DEFAULT 0

CLIPPER DISKSPACE() { struct /* structure to hold disk info */ { unsigned no_clusts; /* number of free clusters */ unsigned secs_clusts; /* sectors per cluster */ unsigned clusts_drv; /* total clusters per drive */ } drv_info; /* if there is one parameter and it is numeric */ if (PCOUNT == 1 && ISNUM(1)) { _dspace(_parni(1), &drv_info); /* specified drive */ } else _dspace(DEFAULT, &drv_info); /* default drive */ /* bytes ::= number of clusters times sectors per cluster times 512 */ _retnl(512L * (long)drv_info.secs_clusts * (long)drv_info.no_clusts); } ARCHIVOS ENCABEZADO DEL SISTEMA EXTENDIDO /*** * nandef.h * * Nantucket defines */ #define FALSE 0 #define TRUE 1 #define NIL '\0' #define NULL 0L typedef unsigned char byte; typedef unsigned int quant; typedef int Boolean; /*** *extend.h *

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

94

*DEFINEs and EXTERNs for interfacing with Clipper from C. * *Large model C only (double word pointers to code and data) * *Copyright (c) Nantucket Corporation 1987 */ #define CLIPPERvoid pascal /* _parinfo types */ #define UNDEF 0 #define CHARACTER 1 #define NUMERIC 2 #define LOGICAL 4 #define DATE 8 #define ALIAS 16 #define MPTR 32 /* or'ed with type when passed by reference */ #define MEMO 64 #define WORD 128 #define ARRAY 512 /* parameter count/type */ extern int _parinfo(int); extern int _parinfa(int, int); /* parameter values */ extern char *_parc(int, ...); extern int _parcsiz(int, ...); extern int _parclen(int, ...); extern int _parni(int, ...); extern long _parnl(int, ...); extern double _parnd(int, ...); extern int _parl(int, ...); extern char *_pards(int, ...); /* one and only one of the _ret?? functions must used */ /* Clipper-function return values */ extern void _retc(char *); extern void _retclen(char *, int); extern void _retni(int); extern void _retnl(long); extern void _retnd(double); extern void _retl(int); extern void _retds(char *); /* procedure (DO) return */ extern void _ret(void); /* allocate memory */ /* parameter: requested size in bytes */

Curso de Lenguaje C - Por: Ing.Anibal Martinez Arcia.

95

/* returns: far pointer to memory or NULL */ extern unsigned char *_exmgrab(unsigned); /* free allocated memory */ /* parameters: pointer from _exmgrab(), same size passed to _exmgrab() */ extern void _exmback(unsigned char *, unsigned); /* misc. */ extern unsigned strlen(unsigned char *); /* parameter check macros */ #define PCOUNT(_parinfo(0)) #define ISCHAR(n)(_parinfo(n) & CHARACTER) #define ISNUM(n)(_parinfo(n) & NUMERIC) #define ISLOG(n)(_parinfo(n) & LOGICAL) #define ISDATE(n)(_parinfo(n) & DATE) #define ISMEMO(n)(_parinfo(n) & MEMO) #define ISBYREF(n)(_parinfo(n) & MPTR) #define ISARRAY(n)(_parinfo(n) & ARRAY) #define ALENGTH(n)(_parinfa(n, 0)) /* Header structure */ typedef struct { byte signature;/* 03 = dbf, 83 dbf+dbt */ byte ymd[3]; /* y+1900 m d */ long last_rec; quant data_off; quant rec_size; byte pad[20]; } DBF_HEADER; extern DBF_HEADER *_dbfhead(); extern int _dbfopen();

Curso de Lenguaje C - Por: Anibal Martinez Arcia.

96