Fundamentos de Programación en Lenguaje C Felipe Rolando Menchaca Garcia
Short Description
Descripción: La escalada de la comunicacion escrita iniciada en el Renacimiento con la invencion de la imprenta y elevad...
Description
CIENCIAS DE LA COMPUTACION
FUNDAMENTOS DE PROGRAMACION EN LENGUAJE
C
F. ROLANDO MENCHACA GARCIA
FUNDAMENTOS IDE PROGRAMACION
EN LENGUAJE C
CENTRO DE INVESTIGACION EN COMPUTACION NSTITUTO
POLITECNICO -MEXICO-
NACIONAL
PRIMERA EDICION: 1999 PRlMERA REIMPRESION: 2002 Se prohfbe la reproduccion total 0 parcial de esta obra -incluido el disefio tipognifico y de portadasea cual fuere el medio, electronico 0 mecanico, sin el consentimiento por escrito del editor. D.R. © 2002 INSTITUTO POLITECNICO NACIONAL Direccion de Publicaciones Tresguerras 27, 06040, DF D.R. © 2002 UNTVERSIDAD AUTONOMA DE MEXICO Torre de Rectoria, 9° Piso, Ciudad Universitaria, 045100, Mexico DF D.R. © 2002 FONDO DE CULTURA ECONOMICA Carretera Picacho-Ajusco 227, 14200, Mexico DF ISBN
970-18-2059-2 (colecci6n) 970-18-222] -8
Impreso en Mexico / Printed in Mexico
Ciencia de fa Computaci6n La escalada de la comunicacion escrita iniciada en el Renacimiento con la invencion de la imprenta y elevada a niveles inimaginables hasta nuestros dias, ha obligada al ser humano a alfabetizarse en un nuevo orden relacionado con las formas especfficas de los medios, adem as de la escritura. Uno de estos medios es la computadora, objeto del mundo moderno que multiplica los espacios de accion y conocimiento del ser humano, donde las utopias adquieren realidad y el nuevo alfabeto cotidiano se adentra en LIn presente marcado por el ente computacional. Sin embargo, y aun cuando el ente computacional forma parte de nuestra vida cotidiana, el texto impreso no ha sido desplazado por el texto electronico; por el contrario, ambos se han convertido en elementos simbioticos que conforman una herramienta fundamental para acelerar el paso hacia una sociedad y economia avanzadas y reestructuradas en torno a la ciencia, la tecnologia y la difusi6n y promocion del conocimiento. Solo a traves de esta comunicacion de conocimientos se puede crear una cultura cientffica, fundada en la bllsqueda permanente de la verdad, la critica informada y el proceder sistematico, riguroso e inteligente del quehacer humano. En este contexto, la Coleccion de Ciencia de la Computacion, editada por el Centro de Investigacion en Computacion (CIC) del Instituto Politecnico Nacional, con la colaboracion de la Universidad Autonoma de Mexico y el Fondo de Cultura Econom ica, presenta los trabajos de destacados especialistas mexicanos yextranjeros -tanto en su labor docente, como de investigacion- en temas de computo docente, modelado y simulacion de sistemas, anal isis numerico, sistemas de informacion, ingenieria de software, geoprocesam iento, sistemas digitales, electronica, control automatico, reconocimiento de patrones y procesamiento de imagenes, tecnologfa delenguaje natural e inteligencia artificial. De esta forma, la obra editorial, del CIC, que incluye la Revista Computacion y Sistemas, la coleccion Research on Computing Science, Informes Tecnicos, Memorias de eventos academicos, catalogos de soluciones y esta colecci6n de libros, entre otros, reafirma el compromiso de asegurar altos estandares academicos y de productividad cientifica, vinculacion y orientacion al trabajo, asf como desarrollo de habilidades y destrezas en la formacion de recllrsos humanos. La Colecci6n esta dirigida a estudiosos del campo de la Computacion, tiene la finalidad de que estos actualicen y refuercen su informacion en esta dinamica area del conocimiento; tambien se pretende sea L1na herramienta de trabajo y consLllta en sus investigaciones y labores de ensefianza. As!, se consol ida L1no de los trabajos fundamentales de la comunidad cientifica, que es la difusion y promocion de la clencla. Consideramos que todos y cada uno de los libros de esta Coleccion, deberan estar presentes en \a biblioteca de todo profesional en computacion y areas afines,
que crea que el estudio y la actualizaci6n son esenciales para impulsar el desarrollo personal y de nuestro pais; un buen apoyo para ello, puede ser esta Colecci6n, que tiene como caracterfsticas relevantes SlI originalidad y excelente calidad.
DR. JUAN LUIS DiAZ DE LEON SANTiAGO
Centro de Investigacion en Computacion Director
Con gran carino dedico este trabajo a mi adorable esposa, Reyna Catalina Mendez Montano, quien me ha acompanado con toda su comprension, dedicacionyamor.
A mis hijos Rolando, Ricardo y Adriana, que seguramenle superaran ampliamente la pequena aportacion que su padre ha logrado entregar a esle mundo en procesO de peljeccionamiento.
AGRADECIMIENTO
Debo externar mi mas profundo reconocimiento a mis alumnos que con sus dudas y comentarios me ayudaron a realizar este libro.
CONTENIDO PREFACIO
xv
CapItulo 1: lNTRODUCCION 1.1
ANTECEDENTES HIST6RICOS DEL LENGUAJE C PLA TAFORMAS DE C6MPUTO ACTUALES LENGUAJES DE PROGRAMACI6N Gramaticas Estructuras Lexico, sintaxis, semantica Compiladores e interpretadores Depuradores Enlazadores (ligadores) Ambientes de programacion del lenguaje C TurboC++ Menu de compilacion Menu de proyecto Menti de depuracion Menu de corrida Menu de opciones Menu de ventanas HERRAMIENT AS METODOL6GICAS DE LA COMPUT ACION IA lA.l Programaci6n estructurada lA.2 Especificacion IA.3 Arquitectura del programa lAA Diagrama de flujo I A.5 Especificaci6n en pseudoc6digo IA.6 Software reutilizable 1A.7 Programacion orientada a objetos LA COM PUT ACI6N Y LAS TELECOMUNICACIONES 1.5 Preguntas suplementarias
2 2 5 5
Capftulo.2: EL LEXICO DEL LENGUAJE C
25
1.2 1.3 1.3.1 1.3.2 1.3.3 1.3A 1.3.5 1.3.6 1.3.7 1.3.8
2.1 2.2 2.2.1
TIPOS DE "TOKENS" SEPARADORES Espacios, saltos tabulares, cambios de renglon
6
7 7 8 8 8 9
11 12 12 13 14 14 14 15 15 16
17 18
20 21 22 24
25 25 25
2.2.2 Comentarios 2.2.3 El terminador de instrucci6n 2.2.4 Las llaves { y } 2.2.5 Operadores 2.3 CONSTANTES 2.3.1 Enteros 2.3.2 Numeros de pun!o flotante 2.3.3 Caracteres 2.3.4 Cadenas 2.3.5 Constantes simb6licas 2.4 IDENTIFICADORES 2.4.1 Modo de construcci6n de un identificador 2.4.2 Atributos de un identificador Clase de almacenamiento Tipo de dato 2.4.3 Uso del mismo identificador para diferentes tipos de elemento OPERADORES 2.5 Operadores aritmeticos Operadores relacionales Operadores logicos Operadores logicos a nivel de bit (compuertas logicas) Operadores de asignacion Operadores tipo lenguaje ensamblador aperadores de expresion prima ria Operadores de Junciones especiales
2.6
PALABRAS CLAVE
Ejercicios
26
28 28 28 29 29 30 30 31
32 32 32 33 33
34 34 35 35 36 36 36 36 37 37 37 37 39
CapItulo 3: ESTRUCTIJRA DE UN PROGRAMA EN C
41
3.1
ESTRUCTURA GENERAL
41
3.2
ESTRUCTURA DE UNA DECLARACION
42 42 42 44
Estructura general de una declaraci6n Especificadores de clase de almacenamiento y alcance Alc':'YLce 0 ambito de un identificador 0 variable Especificadores de tipo de dato 3.2.3 Tipos de datos basicos Tipos de datos compuestos 3.2.4 Estructura de los declaradores 3.2.5 Ejemplos de declaraciones sin inicializador 3.2.6 Inicializadores 3.2.1 3.2.2
ii
44
45 45 46 47 48
3.2.7 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.4 3.5
Declaracion de nombres tipo ESTRUCTURA GENERAL DE UNA DEFINICI6N DE FUNCI6N Estructura general de la definici6n de una funci6n Especificador y valor retornado Declarador de funci6n y panlmetros formales Cuerpo de la funci6n Recursividad Funciones de biblioteca estandar EJEMPLOS SENCILLOS DE SEGMENTOS DE PROGRAMAS EN C LA FUNCION PRINCIPAL main Y sus ARGUMENTOS argc Y argv Ejercicios
Capitulo 4: 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.1'2 4.13 4.14 4.15 4.16
51 51 51
52
53 53 54 55 59
60
61
ASIGNACION SIMPLE Sintaxis de La expresi6n ASIGNACION COMPUESTA INSTRUCCION EXPREsrON INSTRUCCION COMPUESTA (BLOQUE) INSTRUCCION CONDICIONAL INSTRUCCION while INSTRUCCION do .. while INSTRUCCION for INSTRUCCION switch-case INSTRUCCION break INSTRUCCION continue INSTRUCCIONES return Y exit INSTRUCCION goto etiquetas INSTRUCCION NULA EXPRESION CONDICIONAL INSTRUCCION CONVERSION Ejercicios
CapItulo 5: 5.1 5.1.1 5.1.2
lNSTRUCCIONES
50
TIPOS DE DATOS
61 62
63 64 65 65 66 67 68 69 71 72 73 73 74 74 74 76 77
ENTEROS Introducci6n Enteros sin signo Notaci6n Declaraci6n Longitud
77 77 77 77 78
79
iii
5.1.3 Operaciones matematicas y logicas con enteros sin signo Conversiones de tipo
5.1.4 Enteros con signo
5.1.5 5.1.6 5.2 5.2.1 5.2.2 5.2.3 5.2.4 5.2.5 S.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.3.6 5.4 5.4.1 5.4.2 5.4.3 5.4.4 5.5 5.5.1 5.5.2 5.5.3 5.5.4 5.5.5 5.5.6
5.5.7
Declaracion Operaciones aritmeticas sobre enteros Operaciones relacionales y 16gicas sobre enteros con signo Operaciones Logicas a niveL de bit y operaciones tipo lenguaje ensamblador, sobre enteros con signo Funciones estandar de enteros con signo Reglas de precedencia y asociatividad CARACTERES Introduccion Dec1araci6n Conversi6n caracteres a enteros Operaciones con caracteres Funciones estandar que operan con caracteres NUMEROS DE PUNTO FLOTANTE Introducci6n Dec1araci6n Conversion punto tlotante-entero Operaciones con numeros de punto flotante Reglas de precedencia Funciones estandar con numeros de punto flotante ARREGLOS Introducci6n Dec1araci6n Inicializaci6n Ejemplo de aplicaci6n ApUNT ADORES Introducci6n Dec1araci6n EI operador de direcci6n de memoria & y el de contenido de memoria * Modos de direccionamiento Apuntadores, arreglos y aritmetica de apuntadores Paso como pardmetro del apuntador a un arreglo Cadenas y apuntadores a canicter Inicializacion de arregLos de apuntadores a cadenas de caracteres Funciones que ope ran con cadenas Apuntadores vs. arreglos multidimensionales iv
80 87 91 91 92 93 93 94 98 99 99 101 101 102 102 104 104 105 106 106 108 108 110 110 112 112 113 116 116 119 120 121 122 124 126 126 127 130
5.5.8 5.6 5.6.] 5.6.2 5.6.3 5.7 5.7.1 5.7.2 5.8 5.9
Apuntadores a funciones
DEFINICION DE TIPOS COMPUESTOS
131 131 131 132 133 136 136 136 136 138
Ejercicios
140
ESTRUCTURAS Introducci6n Declaraci6n Referencia a elementos de una estructura/notaci6n punto UNIONES Declaraci6n Referencia a elementos de una uni6n/notaci6n punto ARCHIVOS
Capitulo 6: FUNCIONES
141
6.]
INTRODuccrON
141
6.2 6.3
SrNTAxrs DE UNA FUNcrON EN C
142
ESPECIFICACION EN PSEUDOCObIGO VALOR RETORNADO DECLARACIONES DE LOS ARGUMENTOS
143
Paso de panimetros por valor y por referencia Paso de panimetros de tipo apuntador ALCANCE DE UN NOMBRE DE IDENTIFICADOR DENTRO DE UNA
150 150
6.4
6.5 6.5. ) 6.5.2 6.6 6.7 6.7.1 6.8 6.9
148
149
FUNCION LA FUNCION PRINCIPAL mainO
153
152
Argumentos de la funci6n mainO
153
RECURSIVIDAD EJECUCION DE FUNCIONES POR DIRECCIONAMIENTO INDIRECTO
153
Ejercicios
165
155
Capitulo 7: FUNCIONES DE ENTRADA Y SALIDA
167
7. I
INTRODUCCION NOMBRES DEARCHIVOS
167 167
ENTRADA Y SALIDA ESTANDAR Biblioteca de entrada/salida estandar Redireccionamiento de Ia entrada y la salida eshindar Funciones de entrada y salida estandar
169
7.2 7.3 7.3.1 7.3.2 7.3.3
Fu"ci Com p ila d 0 r Fuente
Objeto
L._ Figura 1.2: Funcion del compilador.
8
Fundamentos de Programacion en Lenguaje C
La diferencia entre un compilador y un interpretador es que el primero traduce el programa completo, el cual se encuentra en un archivo de texto escrito de acuerdo a las reglas gramaticales dellenguaje, y produce un archivo de codigo 0 programa objeto en lenguaje de maquina, el cual debidamente enlazado con los modulos de biblioteca, constituye un programa ejecutable. En cambio, el interpretador traduce y ejecuta a la vez el programa fuente.
1.3.5 Depuradores Los depuradores son programas que permiten ejecutar un programa paso a paso, o por segmentos, para verificar el comportamiento de variables y estructuras de datos clave y determinar donde y por que estan ocurriendo las fall.~s. Mientras que el compilador es una herramienta para detectar y corregir los errores lexicos y sintacticos, el depurador ayuda a corregir los errores semanticos, para lograr que el programa haga exactamente 10 que se requiere de e1.
1.3.6 Enlazadores (ligadores) Los enlazadores son programas que concatenan 0 enlazan el c6digo objeto generado por el compilador, con los codigos de las bibliotecas, para de esta manera generar un c6digo ejecutable. EI enlazador permite interrelacionar 0 vincular los distintos segmentos de programa compilados por separado, con los archivos de biblioteca, y dejar el programa objeto de tal manera que pueda ejecutarse como una entidad independiente.
1.3.7 Ambientes de programacion dellenguaje C Debe reca1carse que un ambiente de programacion esta constituido por el sistema operativo, el editor, el compilador, el depurador, el enlazador y las bibliotecas. Ya se comentaron las funciones del compilador, del depurador y el enlazador. La funcion del editor es la de servir como herramienta para escribir el programa fuente. Algunos editores modernos proporcionan innumerables ayudas, como es diferenciar los distintos elementos lexicos, dar herramientas de procesamiento y edicion de textos, busquedas, reemplazos, etcetera. Las bibliotecas son segmentos de programas reutilizables que pueden emplearse para desarrollar otros programas de manera mas rapida y eficiente. Las
Introducci6n
9
bibliotecas son parte del software del compilador, sin embargo, pueden enriquecerse y mejorarse con el software reutilizable desarrollado por el usuario. EI sistema operativo es la plataforma de software sobre ]a cual corren los programas. Por esa razon, el sistema operativo es determinante de la funcionalidad y operatividad de un programa. Es decir, el programa solo dispone de los recursos que Ie puede dar el sistema operativo para correr. Actualmente existen en el mercado productos como es el caso de Turbo C++ o Borland C++, que proporcionan todos los elementos del ambiente de programacion descritos anteriormente; sin que esto quiera decir que son los unicos. En la siguiente secci6n se describe, a grandes rasgos, el ambiente de programaci6n que se tiene en Turbo C++.
1.3.8 Turbo C++ Turbo c++ es un ambiente de programaci6n que cuenta con las herramientas indicadas en la seccion 1.3.6 y se considera adecuado para trabajar con los conceptos y aspectos de programacion y computaci6n contemplados en el curso cubierto en este libro. Dicho producto proporciona un ambiente de trabajo con base en ventanas mu16ples, por medio del cual se pueden tener diversas ventanas de edicion, la ventana de presentaci6n de la salida del programa en ejecucion; una ventana de mensajes del compilador y una ventana de observaci6n de variables para propositos de depuracion. Tambien se puede tener una ventana de observaci6n de los registros del procesador y ae la memoria de la computadora (para analizar y depurar programas). EI editor de Turbo C++ es arnigable y cuenta con todos los elementos de edicion de un procesador de textos de calidad profesional. En la tabla 1.1 se resumen algunos de los comandos de edicion mas usuales. Entre estos comandos se incluyen comandos de borrado, busqueda, ubicaci6n en el archivo, inserci6n de otros archivos, etcetera. EI numero de ventanas de edici6n que pueden manejarse con Turbo C++ depende de la configuraci6n que tenga el sistema operativo de la computadora. En el DOS (disk operating system), principalmente se tiene que considerar el mlmero de buffers y el numero de archivos abiertos. Sin embargo, a pesar de las muchas limitaciones de este sistema operativo, es digno de resaltarse el hecho de que se pueden abrir varias ventanas a la vez, inc1uyendo Ia ventana de ayuda, de la cual se pueden copiar directamente segmentos de programas de los ejemplos, los cuales se pueden adecuar y utilizar. Oprimiendo el boton derecho del rat6n 0 la tecla Fl, se tiene acceso a Ia ayuda en lfnea.
10
Fundamentos de Programaci6n en Lenguaje C
Tabla 1.1: Comandos de edici6n de Turbo C++ Funci6n Borrar caracter sobre cursor Borrar caracter antes cursor Borrar palabra siguiente Borrar linea actual Borrar resto de la lfnea Borrar bloque
I Comando Oprimir Oprimir Oprimir Marcar con el mouse Oprimir Marcar con el mouse Oprimir Marcar con el mouse Oprimir
Copiar bloque
Marcar con el mouse Oprimir Ubicar el cursor al inicio de la copia Oprimir 5Shift>
Mover bloque
Marcar con el mouse Oprimir Borrar el bloque Ubi car el cursor al inicio del lugar a donde se movera el blogue. Oprimir Ubi car con el mouse Ubicar con el mouse Ubi car con el mouse Ubi car con el mouse Oprimir Oprimir Oprimir Oprimir Abrir ventana con archivo Seleccionar todo el archivo Oprimir Ubi car el cursor en la ventana a donde se va a insertar Oprimir Seleccionar material Oprimir Abrir ventana Ubi car el cursor en la ventana a donde se va a insertar Oprimir Seleccionar menu edici6n Dar texto Seleccionar menu edici6n Dar texto a buscar Dar texto a corregir
A vanzar un caracter Retroceder un caracter AVanzar una linea Retroceder una lfnea A vanzar pagina Retroceder pagina Iral final del archivo Ir al principio del archivo Insertar archivo
Guardar material en un archivo
Buscar texto Buscar y sustituir texto
I Comando alterno oprimir oprimir oprimir Marcar inicio y fin con: oprimir Marcar inieio y fin con: Ubi ear cursor con las teclas de flecha Oprimir Marcar inieio y fin eon: y Ubicar cursor con las teclas de flecha Oprimir Oprimir Oprimir Oprimird,> Oprimir Oprimir Oprimir Oprimir Oprimir Ubi car el cursor Oprimir Dar el nombre del archivo
Seleccionar bloque Oprimir Dar el nombre del archivo
Oprimir Dar el Texto Oprimir Dar texto a buscar Dar texto a corregir
In troducci6n
11
Menu de compilaci6n Las funciones de compilacion de Turbo C estan disponibles a traves del menu de compilacion. Se tienen disponibles los comandos de este menu, cuando esta activa una ventana de edicion. Los comandos disponibles en este menu son: Compilar Hacer Enlazar Construir todo Informacion Quitar mensajes
(Compile) (Make) (Link) (Build All) (Informati on) (Remove Messages)
Para usar las instrucciones compilar, hacer, construir y enlazar, debe estar abierto un archivo en una ventana activa, y para usar hacer, construir y enlazar, debe estar definido un proyecto. EI compilador traduce un archivo con extension C (.C) 0 .CPP activo en una ventana de edicion a un archivo .OBI. Al estar compilando, en una caja de dialogo se presentan los resultados de la compilacion: lfneas compiladas, numero de errores y advertencias y memoria disponible, y en la ventana de mensajes se indican en detalle los errores y advertencias. Cada mensaje de error se vincula directamente con la linea de la ventana de edicion, en la cual se detecto el error. Esto se hace con el comando compilar (Compile). El comando hacer (Make) invoca al administrador de proyectos para ejecutar un proyecto, creando un archivo ejecutable con el nombre del proyecto 0 del archivo activo en la ventana de edicion. El comando enlazar (Link) toma los archivos incluidos en el proyecto activo y los enlaza. Es decir, determina todas las referencias cruzadas entre los archivos objeto generados para cada archivo fuente y crea el archivo ejecutable, orde.nando los segmentos de software y datos de manera adecuada. EI comando construir todo (Build All) reconstruye todos los archivos incluidos en el proyecto. Es similar al comando hacer, excepto que reconstruye todos los archivos, sean 0 no actuales, en los siguientes pasos: Borra los archivos de encabezado (.SYM), si existen Borra cualquier informacion de autodependencia registrada en el proyecto Pone en cero la fecha y la hora en todos los archivos objeto del proyecto Ejecuta el comando hacer El comando informacion (Information) muestra una caja de dialogo con las estadfsticas del archivo actual.
12
Fundamentos de Programaci6n en Lenguaje C
Con quitar mensajes (Remove Messages) se quita la ventana de mensajes de la pantalla de la computadora.
Menu de proyecto El menu de proyecto tiene los siguientes comandos: Crear 0 abrir un proyecto Cerrar un proyecto Agregar archivos al proyecto Borrar archivos del proyecto Establecer opciones de compilacion de un archivo en el proyecto Especificar el nombre del modulo objeto resultante, su ubicacion, si es un modulo de "overlay" y SI debe contener informacion de "overlay" Ver los archivos "include" de un archivo especifico del proyecto
Menu de depuraci6n Los comandos del menu de depuracion permiten especificar la informacion que se requiere verificar en la ventana de depuracion, y se dispone de los siguientes: Inspeccionar Evaluar/Modificar Invocar la Pila Observaciones Boton de puntos de pausa Puntos de pausa
(Inspect) (EvaluatelModify) (Call Stack) (Watches) (Toggle Breakpoint) (Breakpoints)
lnspeccionar (Inspect) abre una ventana de inspeccion, en la cual se examinan los valores que van tomando los elementos de datos. El tipo de elemento que se esta inspeccionando determina el tipo de informacion presentada en la ventana. Pueden inspeccionarse en Turbo C++ los siguientes tipos de datos: caracteres, enteros, reales, arreglos,. apuntadores, estructuras, tipos, uniones y funciones. Para abrir una ventana de inspeccion se coloca el cursor en el elemento de datos que se desea inspeccionar y se elige el comando inspeccionar 0 bien en el menu de depuracion, se elige el comando inspeccionar y se indica por medio de entrada por teclado, el concepto a inspeccionar. El estado 0 valor de dicho concepto se muestra en la ventana de inspeccion.
Introducci6n
13
La inspeccion se puede combinar con una corrida paso a paso, para verificar como ha variado el concepto a inspeccionar, al ejecutar una determinada instrucci6n del programa. Tambierr al terminar la ejecuci6n del programa. El comando observaciones (Watches) abre el menu de observacion que tiene los siguientes comandos: Agregar observaci6n Borrar observaci6n Edicion de observacion Eliminar observaciones
(Add Watch) (Delete Watch) (Edit Watch) (Remove All Watches)
Se pide la observaci6n de las variables 0 estructuras, del mismo modo que en la inspecci6n. La diferencia es que en el caso de las observaciones se esta vigilando constantemente como estan cambiando los valores 0 estados de la variable o dato a observar, y la inspecci6n s610 presenta la informaci6n cuando se pide. El comando evaluar y modificar (Evaluate and Modify) permite evaluar una expresion y/o modificar el valor de una variable 0 dato, durante una corrida paso a paso.
Menu de corrida Este menu tiene los comandos para correr los programas y para realizar las tareas de depuraci6n. Los comandos de que dispone son: Correr
(Run)
Reinicializar el programa
(Program Reset)
Ir al cursor
(Go to Cursor)
Traza a
(Trace Into)
Paso a paso
(Step Over)
Argumentos
(Arguments)
Corre el programa desde el inicio Reinida la ejecucion paso a paso Corre el programa hasta donde esta el cursor Corre el programa hasta la siguiente funcion Corre el programa instrucci6n por instruccion Indica los argumentos del programa
Para usar los comandos reinicializar, ir al cursor, traza y paso a paso se debe haber compilado y enlazado con la opcion de depuracion del menu de
14
Fundamentos de Programacion en Lenguaje C
depuracion puesta en "on". Si no se desea depurar el programa se puede quitar esta opcion.
Menu de opciones Este menu contiene comandos para ver y cambiar los panimetros de configuracion del ambiente de programacion del Turbo C++. Con el puede indicar el compilador a utilizar, de no desear el propio del ambiente; el enlazador, los directorios de trabajo, entre otras caracteristicas que Ie hagan sencilla su tarea de creacion de programas. La mayoria de los parametros se presentan mediante una caja de dialogo que faciIita la configuracion en cada caso. Las opciones del Inenu son: Aplicacion Compilador Transferencia Hacer Enlazador Bibliotecas Depurador Directorios ... Ambiente Salvar
(Application... ) (Compiler. .. ) (Transfer ... ) (Make ... ) (Linker ... ) (Librarian ... ) (Debugger... ) (Directories ... ) (Environment. .. ) (Save ... )
Menu de ventanas Contiene los comandos de manejo de ventanas. Las ventanas se pueden mover, amp li ar, poner en cascada, elegir la siguiente, cerrar, cerrar todas y listarlas. Como ya se comento, se puede tener abiertas tantas ventanas de edicion como se desee, por ejemplo, la de salida, la de mensajes del compilador, la de proyectos, la de registros y la de observacion.
1.4 HERRAMIENTAS METODOLOGICAS DE LA COMPUTACION En esta seccion se discuten de manera sucinta algunas metodologias que se han constituido en paradigmas de programacion. La programacion, ademas de ser una tarea de desarrollo tecnologico que requiere de los conocimientos cientifi-
Introduccion
15
cos de soporte del sistema que se necesita programar, es un arte que requiere de gran imaginacion y creatividad.
1.4.1 Programaci6n estructurada La estructura es el modelo 0 marco general con que se desarrolla un programa. Ella permite visualizar y entender mejor un algoritmo 0 programa y facilita la tarea de desarrollo y depuracion del mismo. Los elementos fundamentales de la estructura de un programa son: arquitectura, modularidad, funcionalidad de los distintos modulos, e infraestructura (bibliotecas y software reutilizable con que se cuente).
1.4.2 Especificaci6n La especificacion de un programa indica con todo detalle la tarea que se debe realizar. Por ejemplo, tratandose de una calculadora cientifica, la especificacion debe incluir: a. b. c. d. e.
f
Como debe ser la interfaz con el usuario: como presentar el menu de opciones, como adnlitir los datos, como presentar los resultados Que operaciones debe realizar Con que precision debe realizar las operaciones Como debe manejar los errores Que servicios de edicion de datos debe proporcionar al usuario Como se debe activar y desactivar, etcetera.
La especificacion establece la funcionalidad y define las caracteristicas del programa. Como otro ejemplo, consideremos el disefto e implementacion de un sistema de informacion. Cabe hacer notar que la especificacion de un sistema cualquiera, establece: a. b. c. d. e.
f
sus objetivos, las distintas necesidades de informacion que se requiere satisfacer, la distribucion fisica de las distintas entidades que deben utilizar el sistema, los datos que se deben capturar como entradas del sistema, las caracteristicas del equipo y de la interfaz de captura, la forma en que debe fIuir la informacion entre los distintos integrantes del sistema,
16
Fundamentos de Programaci6n en Lenguaje C
g. h. i.
las restricciones de acceso a la infonnacion, tanto al nivel de consulta como de modificacion, la rapidez con que se debe entregar la informacion, los elementos a incluir en los reportes y la precision y caracteristicas de la informacion que se requiere presentar, etcetera.
1.4.3 Arquitectura del programa La arquitectura de un programa es la concepcion global del mismo. Constituye el disefio de sistema del prograrna de computadora. Define a grandes bloques los elementos principales del sistema y su interrelacion, asi como la funcionalidad y caracteristicas de cada uno de esos bloques 0 modulos. Retomando el ejemplo de un sistema de informacion, su arquitectura estani integrada por la definicion estructural de los distintos modulos y la especificacion de como fluyen los datos y reportes entre cada uno de los integrantes del propio sistema. La figura 1.3 muestra la arquitectura de un sistema de informacion generico que tiene la filosofia cliente/servidor.
Estacion de Adquisici6n
Cliente de Consulta Cliente de Consulta
Cliente de Consulta
Cliente de Consulta
Figura 1.3: Arquitectura de un sistema de bases de datos cliente/servidor.
Introduccion
17
1.4.4 Diagrama de flujo El diagrama de flujo es otra importante herramienta metodologica. Su uso es muy adecuado para especificar detalladamente un algoritmo de solucion de un problema cualquiera, sea de ingenieria, matematico, etc. Por 10 anterior, su ambito de aplicacion ideal es en la especificaci6n de segmentos de programa 0 m6dulos que ejecutan tareas especificas, como pueden ser: un ordenanliento, una busqueda, la solucion de un sistema de ecuaciones, etc. A manera de ejemplo, la figura 1.4 muestra el diagrama de flujo del metodo de ordenamiento conocido como metodo de la burbuja.
~
T
< > J=\..lOPg 1
r
oftllalizar datos par (OSi hay desorden int °t .....- J
1 ~
:---
TCFE
~NO ~
J
Figura 1.4: Diagrama de flujo del algoritmo del me to do de la burbuja.
EI algoritmo del me to do de la burbuja para ordenar de manera creciente N elementos, funciona de la siguiente manera: 1) Para iniciar se asigna como TOPE, el elemento numero N del conjunto, se define e inicializa a cero una variable t que indica el ultimo elelnento intercambiado (sc intercambian los elementos para ordenarse); 2) Se realiza un proceso iterativo de analisis e intercambio de elementos desde el elemento 1 hasta el elemento TOPE-i, para ello se usa el indice J que se va incrementando hasta analizar todo el conjunto; 3)
18
Fundamentos de Programaci6n en Lenguaje C
Cuando se encuentra un par de elelnentos desordenados se intercambian y se Ie da a t el valor de J, al realizarse el intercambio; al terminar una iteracion t queda con el valor indice del ultimo elemento intercambiado; 4) Si al terminar la iteracion t=O, se termina el ordenamiento, si no, se da a TOPE el valor de J y se realiza otra iteracion. La figura 1.5 muestra los pasos de ordenamiento de siete numeros. Como se aprecia, los elementos se ordenan en cinco iteraciones. En la primera se lleva el 88 hasta la posicion de la extrema derecha y el tope queda ubicado en la posicion seis. En la segunda se lleva el 23, hasta antes del 88 y se recorre el TOPE a su izquierda. En la tercera se lleva el 19, en la cuarta el 16 y en la quinta y ultima iteracion quedan ordenados los numeros.
16 15 15 15 15 15 15 15 15 14
15 16 16 16 16 16 16 16 14 15
I
19 19 19 19 19 19 14 14 16 16
23 23 23 23 14 14 19 17 17 17
I
88 88 14 14 23 17 17 19 19 19
I
14 14 88 17 17 23 23 23 23 23
I
17 17 17 88 88 88 88 88 88 88
Figura 1.5: Ejemplo de ordenamiento por el metodo de la burbuja.
1.4.5 Especificacion en pseudocodigo La especificacion en pseudocodigo es otra herramienta metodologica de gran utilidad en el desarrollo de programas de computadora. Esta herramienta consiste en programar la estructura principal del programa, dividiendolo por modulos 0 funciones que realizan tareas especificas, las cuales se pueden especificar por medio de comentarios, en el lenguaje de programacion de trabajo; en nuestro caso el lenguaje C. Los detalles de programacion pueden realizarse despues con mayor facilidad, ya que se divide la tarea grande en tareas mas pequenas y manejables, como son los modulos 0 funciones. En e1 ejemplo 1.1 se muestra la especificacion en pseudocodigo de un programa que debe trazar una de las figuras geometricas 0 curvas que se indican en su menu, con los datos que Ie proporcione el usuario.
Introducci6n
19
Especificacion en pseudocodigo de un trazador de figuras geometricas
*/
Ejemplo 1.1: Trazador de figuras geometricas.
/*
int MENUO
{/* MENU presenta en la pantalla, el menu con la lista de figuras geometricas que puede desplegar el programa. Estas son: * Linea, dando el punto inicial y final * Circulo, dando el centro y el radio * Rectangulo, dando dos vertices * Polfgono, dando numero de lados y los vertices * Curva, dando una secuencia de puntos Funcion, dada su ecuacion y el rango de valores de la variable indep. * Elipse, dado su centro, longitud del eje mayor y del menor * Salir MENU entrega a su salida un numero entero que representa la seleccion realizada.
*
*/ } int LINEAO
{
/* Obtiene las coordenadas de /* Traza la linea */
los puntos inicial y final
*/
/* Retorna un valor negativo y un mensaje de error, si las coordenadas estan fuera de rango (0, simplemente, "Mensaje de error" en 10 sucesivo) */
} int CIRCULOO
{ /* Obtiene las coordenadas del centro y el radio * / el drculo */ /* Mensaje de error* /
/* Traza }
int RECTANGULOO
{
/* Obtiene las coordenadas de los vertices * / /* Traza el rectangulo * / /* Mensaje de error * / } int POLIGONOO
{
/*
Obtiene el numero y las coordenadas de los puntos * / /* Traza el Polfgono*/ /* Mensaje de error */
}
20
Fundamentos de Programaci6n en Lenguaje C
int CURVAO { /* Obtiene el numero y las coordenadas de los puntos */ 1* Traza la curva *1 1* mensaje de error *1 } int FUNCIONMATO { 1* Presenta un menu de funciones y pide la selecci6n*1 1* Obtiene los valores lImite de los parametros */ 1* Traza la curva correspondiente *1 /* mensaje de error *1 } int ELIPSEO { 1* Obtiene las coordenadas del centro y la longitud del eje mayor y del menor*I /* Traza la elipse * / 1* mensaje de error *1 } int mainO { int SALIR = 0; while (!SALIR) { 1* Presenta el MENU PRINCIPAL *1 if (J*Seleccion = Salir *1) SALIR =1; 1* Ejecuta la funcion correspondiente al MENU } }
Es evidente que hay que hacer la programacion detaIl ada de cada uno de los modulos de programa indicados como funciones en la especificacion, sin embargo, es obvio que la estructura del programa y las indicaciones de que debe hacer, ya estan contenidas en la especificacion en pseudocodigo (codigo en lenguaje C y comentarios).
1.4.6 Software reutilizable Una pnictica que ha dado resultados excelentes en el desarrollo de la computacion ha sido trabajar con el objetivo de ir construyendo sistemas basados en una infraestructura que va quedando como resultado del trabajo y la experiencia. El desarrollo del software con la vision de poderlo reutilizar en otros proyectos, ha
Introducci6n
21
pennitido construir poderosos ambientes de programaci6n como el que ha ido creandose alrededor de los lenguajes de programacion como FORTRAN y C. Las bibliotecas de estos lenguajes, que estan disponibles tanto en los ambientes de desarrollo propios (dellenguaje), como en paquetes de software adicionales, son verdaderamente impresionantes, ya que permiten desarrollar cosas que en otros tiempo~ hubiera sido increible el poderlas realizar. EI concepto de reutilizacion, consiste en el desarrollo de software de manera modular, en fonna de funciones, estructuras y modulos, los cuales pueden ser usados de manera sencilla, conociendo la especificacion precisa de los parametros de entrada con los que trabajan dichas funciones y las salidas 0 efectos que producen en el ambiente dichas funciones. Una funci6n 0 segmento de programa, puede verse como un modulo 0 susbsistema que tiene un conjunto de entradas, un conjunto de efectos sobre el ambiente de programacion y una salida que es el valor retomado, como se indica esquematicamente en la figura 1.6. Los modulos de programa generados con la filosofia de la figura 1.6, pueden quedar -----1>1
SEGMENTO DE PROGRAMA
----t>
Figura 1.6: Modulo
0
SALIDAS Valor Retornado Variables Globales I-----I-c>:rstructuras Globaies Perifericos f-----+ Archivos ----------~
segmento de programa.
1.4.7 Programacion orientada a objetos EI concepto de software reutilizable se puede llevar a un grade de modularidad, tal que los modulos generados puedan manejarse como componentes u objetos con los cuales puedan construirse sistemas complejos. Un objeto es una estructura de datos que tiene asociado un conjunto de funciones 0 acciones que pueden realizarse sobre dicha estructura, y son construidos de manera tal que puede decirse que los datos y funciones se encuentran empaquetados como integrantes de un objeto, como si fueran componentes de una clase 0 tipo determinado. Al conjunto de funciones y operaciones que se Ie pueden aplicar al objeto, suele llamarsele el comportamiento.
22
Fundamentos de Programacion en Lenguaje C
Asi como hoy se construyen aparatos electronicos empleando componentes (chips, transistores, resistencias y demas componentes que pueden tambien emplearse para construir otros aparatos), en el software es posible tener objetos modulares con los cuales se puede integrar un sistema, como pueden ser menus, menus grMicos, ventanas, iconos, ventanas de dialogo, grMicas, hojas de calcu10, tablas, textos, sonidos digitales, imagenes, manejadores de raton, etcetera. En el ambiente de programacion orientada a objetos, los tipos de objetos se conocen como "c1ases", y los objetos son instancias de la c1ase, en el mismo sentido que las variables 0 estructuras son instancias de un tipo de datos. Orientado a objetos significa que el software se organiza como una coleccion de objetos definidos por su estructura de datos y su comportamiento (funciones y operaciones que pueden realizarse sobre el objeto). Los objetos tienen identidad (un objeto es diferente de cualquier otro, aun del mismo tipo de clase). Ademas, pueden construirse objetos complejos teniendo como base otros objetos, mediante el concepto de herencia. Para definir 0 especificar un objeto determinado, se establece primeramente su c1ase, esta especifica la estnlctura de datos y las funciones que pueden actuar sobre dicha estructura. Como ya se comento, los objetos se dec1aran como "instancias" de la c1ase especificada. La programacion orientada a objetos es actualmente una poderosa herramienta de desarrollo de software, que no solo ha influido grandemente en la construccion de sistemas de informacion y de otras herramientas para el desarrollo, sino que ha estado llegando a las aulas de cada vez mas escuelas en todo -el mundo. Sale del alcance de este libro la explicacion de la programacion orientada a objetos, sin embargo, se considera recomendable que antes de aprender algun lenguaje de programacion orientado a objetos, se conozca y se haya experimentado con un lenguaje como el C, estudiado en esta obra. Previendo esta situacion cuando se habla de tipos de datos, tambien se mencionan sus operaciones asociadas, para dar asi, una posible concepcion de "objeto".
1.5 LA COMPUTADORA Y LAS TELECOMUNICACIONES Comunicaciones y computacion han fonnado un binomio que en los ultimos quince anos han cambiado radicalmente la forma de trabajar y de vivir de nuestra sociedad. Hoy en dia, la computadora es indispensable en toda oficina, institucion educativa, comercio, centro de desarrollo 0 de asesoria de cualquier tipo, pero tambien ya es indispensable que toda computadora este conectada a las redes de transmision de datos, propias de la empresa 0 institucion, 0 bien a redes globales.
Introduccion
23
Internet ha sido un importante acontecimiento, pues ha pennitido interconectar pnicticamente a toda la comunidad mundial, empleando nuevas fonnas de comunicacion, como son: el correo electronico, los boletines electronicos, los bancos de infonnacion y sus buscadores asociados, el web (los escaparates electronicos y las hojas de presentacion institucional), los grupos de amilisis y discusion, los c1ubes de famiticos, los grupos 0 comunidades de investigaci6n y desarrollo, etcetera. De manera que comunicaciones y computacion han constituido una simbiosis de gran impacto en el desarrollo de la sociedad. Han penetrado juntas en casi todos los ambitos, a traves de herramientas modernizadoras que hacen mas eficiente la labor de los seres humanos. Por medio de ellas se han constituido sistemas nacionales e internacionales, como los sistemas bancarios, apoyados en los cajeros automaticos y sistemas de banca electr6nica; las redes de distribuci6n comercial, los sistemas de telereservaciones de transportes y servicios, etcetera. Conceptos como los de redes locales, redes metropolitanas, redes de area amplia, red digital de servicios integrados, red digital integrada, etc., generalizan su aplicacion en todos los ambitos, pennitiendo tender la infraestructura basica para implantar los sistemas distribuidos.Por otro lado, las comunicaciones han experimentado una marc ada tendencia hacia la digitalizacion, en la cual la computadora en sus diversas instancias (grandes procesadores, microprocesadores, microcontroladores, procesadores digitales de sefiales, entre otros), se ha constituido en el componente basico para el desarrollo de equipos y sistemas. Equipos como las centrales de conmutacion, o conmutadores, nodos de transmision de datos, multiplexores y concentradores, enrutadores, centrales de mantenimiento y administraci6n de redes, servidores de s~rvicios de comunicaciones e infonnacion, etc., son desarrollados por medio de una 0 varias computadoras integradas. Adicionalmente, hoy en dia coexisten redes digitales que manejan una gran diversidad de infonnacion, por ejemplo: telefonia, facsimil, sonido, animaciones, videoconferencia, television, etcetera. Puede parecer evidente al lector que en los diversos campos y actividades a que se ha referido en esta seccion, la programacion de las computadoras, el desarrollo del software, representa una de las actividades mas criticas e importantes. Y particularmente, la programaci6n en lenguaje C ha sido de gran importancia en el desarrollo de equipos y sistemas de control y de telecomunicaciones.
24
Fundamentos de Programacion en Lenguaje C
Preguntas suplementarias 1.1 Explique que es un Registro de un Procesador 1.2 Explique el Modelo de computadora de programa almacenado 0 modele de Von Newmann 1.3 Diga que es un puerto de entrada/salida 1.4 l,Que es un lenguaje de alto nivel? 1.5 l,Que significa lenguaje libre de contexto? 1.6 Explique que es la memoria principal de una computadora 1.7 Explique que es un sistema operativo 1.8 Explique el proceso que realiza una computadora cuando se Ie comanda para que ejecute un programa 1.9 Explique como se lleva a cabo el proceso para almacenar un archivo en un disco magnetico.
Capitulo 2
EL LEXICa DEL LENGUAJE
C
El16xico de un lenguaje de programacion, es el conjunto de palabras y simbolos con que se construyen las instrucciones y programas en dicho lenguaje. En la tenninologia de desarrollo de lenguajes de programacion, se dice que cada uno de esos elementos es un "token" 0 "elemento semantico". Como ya se puntualizo en el Capitulo 1, los lenguajes de programacion se utilizan para especificar en fonna sistematizada y ordenada las tare as que debe realizar una computadora para resolver un problema. En este capitulo estudiamos el lexico dellenguaje C.
2.1 TIPOS DE "TOKENS" En C, se tienen diferentes tipos de elementos semanticos pueden agrupar en los siguientes seis grandes gropos:
0
tokens, los cuales se
Separadores Constantes Identificadores Operadores Palabras clave Con estos elementos semanticos se construyen las distintas partes de que consta un programa.
2.2 SEPARADORES 2.2.1 Espacios, saltos tabulares, cambios de reng16n Para el lenguaje C, los espacios en blanco, los saltos tabulares y los cambios de renglon son separadores de elementos semanticos. Estos elementos no tienen
26
Fundamentos de Programacion en Lenguaje C
otro significado para C que el de separadores y por 10 tanto no causan ningun otro efecto en el programa especificado; a diferencia de otros lenguajes, como el BASIC 0 el FORTRAN, en los cuales el cambio de renglon representa el terminador de una instruccion. No obstante 10 anterior, no debe inc1uirse cambios de renglon 0 tabuladores como elementos de una cadena de caracteres, ya que se tiene un formato especial para representar estos elementos dentro de la cadena, como se vera mas adelante en este mismo capitulo. En el ejemplo 2.1 presentado a continuacion, se muestra como el cambio de renglon, los tabuladores y los espacios en blanco, pueden usarse para separar tokens, sin producir un efecto indeseable en el programa. En el ejemplo se usan tabuladores para dar mejor presentaci6n al programa, cambios de reng16n y comentarios intennedios en una dec1aracion de cadenas de caracteres, espacios en blanco entre los elementos semantic os de una funcion, en este caso una funci6n de salida estandar, y tambien se inc1uyen comentarios intennedios entre los tokens de esta misma funcion. EI lector puede compilar este programa y comprobar que los cambios de renglon, tabuladores y espacios en blanco, unicamente tienen la funci6n de separadores de tokens. Ejemplo 2.1: Uso de los cambios de rengl6n, tabuladores y espacios en blanco. mainO
{ NOMl[] = "JUAN CARLOS",
char
/*
Esta es una declaracion
*/
NOM2[] == "JULIO CESAR"; clrscrO; printf
("HOLA NO ECHEN
RELAJO %s %5 PORQUE .... ", /* Esta, es una funcion de salida estandar */
NOMl, NOM2); return (0);
}
2.2.2 Comentarios EI lenguaje C pennite introducir comentarios por medio de los caracteres /* y */. Los comentarios son tratados como espacios en blanco y pueden aparecer en cualquier parte del programa en donde pueda "escribirse" un espacio 0 un cam-
EI Lexica del Lenguaje C
27
bio de renglon, como se ilustra en el ejemplo 2.1. Algunos compiladores no permiten que se aniden comentarios, es decir, que aparezca un comentario encerrado con las parejas /* y */ dentro de otro comentario igualmente encerrado. El diagrama lexicografico del comentario aparece en la figura 2.1 a continuacion:
Figura 2.1: Diagrama lexicografico del comentario.
Los comentarios se usan para documentar el programa, de manera que sea mas flicil de leer y entender, tanto por el programador original, como por otros programadores que mas adelante pudieran revisar, corregir 0 simplemente utilizar ese programa. Otros ejemplos de comentarios son los siguientes:
/* -------------------------------------------------------------------------------------DEFINICION DE PARAMETROS DE TRABAJO
--------------------------------------------------------------------------------- */ 1***************************************************** ********
* * *
Programa principal: Protocolo de Comunicacion PPP Elaborada par: Juan H. 1. (SistematiCO) Fecha: 10 de septiembre, 1998
* *
*
****************************************************** *******1 /* DEFINICION DEL TAMANO DE LOS BUFERS
*/ #define TBUFT
10
/*
Tamafio del bufer de transmision
*/
El compilador de Turbo C++ tambien acepta comentarios de final de linea precedidos por dos diagonales (II), como en el siguiente ejemplo: #define TBUFT
10
/1 Tamafio del
bufer de transmision
28
Fundamentos de Programacion en Lenguaje C
2.2.3 El terminador de instrucci6n Cualquier instruccion (;). Ejemplos:
0
declaracion en C debe tenninarse con un punto y coma
char COMAN DO;
II Declaracion de variable tipo char
printf(" ALTAS: A \n"); II Funcion de bibliateca para printf(" BAJAS: B \n"); II imprimir en pantalla printf(" CAM BIOS: C \n"); printf(" SALIR: S \n\n"); printf("\n\n\n INDICA LA OPERACION QUE DESEAS REALIZAR:"); COMANDO = getcharC); while (getcharO != '\n');
/ / Instruccion asignacion /I Instruccion while
2.2.4 Las Haves { y } Las Baves {... } se utilizan para crear instrucciones compuestas, 0 bloques de instrucciones, de manera que sintacticamente sean consideradas por el compilador de C como el equivalente a un instruccion simple. La instruccion compuesta construida en esta fonna no tiene que terminarse con punto y coma (;), es decir, despues del canicter}, no debe, forzosamente, ir un punto y coma. Como ejemplo, a continuaeion se muestra una instruccion if, a la eual esta asociada una instruccion compuesta que se ejecuta si se cumple la expresion relacional AB) {
II Instruccion compuesta MAX = A; printf ("Ahara el maximo es %d\n", MAX);
}
II ... 2.2.5 Operadores En el contexto de una expresion, los operadores aritmeticos, relacionales, logicos, etc., ademas de su funcion como operador en el contexto semantico, fungen :omo separadores de los distintos elementos de la expresion. En el tema 2.6 se presentan los operadores, desde el punto de vista lexico, y en el Capitulo 4 se estudia su funcionamiento y caracteristicas semanticas.
EI Lexico del Lenguaje C
29
2.3 CONSTANTES En C es posible manejar tipos diferentes de constantes, como son: enteros numeros de punto flotante caracteres, Y cadenas En el diagrama lexicografico de la figura 2.2 se especifica la construcci6n de los distintos tipos de constantes numericas utilizadas en C; en la figura 2.3, el diagrama lexicografico de la constante "caracter", y en la figura 2.4, el diagrama de la constante cadena. En el Capitulo 4 se estudian con detalle los tipos de datos correspondientes a estos cuatro tipos de constantes.
2.3.1 Enteros Las constantes enteras pueden expresarse en cuatro diferentes formas: octal hexadecimal decimal, y entero de 10ngitud grande Las forma en que se expresan estas cuatro modalidades de enteros, es la siguiente: Octal. El numero debe comenzar con un cero. Ejemplos:
07
017
02177
02234
Hexadecimal. El numero debe empezar con los caracteres OX, 6 Ox. Ejemplos:
OxFF
OXFFFF
OXIA
OXIIFF
Decimal. El numero debe empezar con un digito dell a19. Ejemplos: 1986
12
4
2234
Fundamentos de Programacion en Lenguaje C
30
Enteros de longitud grande: El numero debe terminar con la letra I 0 l (mayuscula 0 minuscula). Ejemplos: 01
OxFFFFFFI
02234l
07l
2.3.2 Numeros de punto flotante Una constante de punto flotante consiste de una parte entera, un punto decimal, una parte fraccionaria, una e 0 E, Y un exponente entero con signo opcional. Puede no usarse la parte entera 0 la fraccionaria (no ambas a la vez) y el punto decimal 0 el exponente. Ejemplos: 1.5
2e-3
1.7S4E-S
7.345e3
Figura 2.2: Diagrama lexicografico de la constante numerica.
2.3.3 Caracteres Una constante tipo caracter, no es otra cosa que un caracter encerrado entre comillas sencillas (' .,. '). Ejemplos: 'x'
'I'
'Y'
'X'
'$'
Algunos caracteres especiales del lenguaje C, se representan de la siguiente manera: Linea Nueva Retroceso Tabulador Retorno de Carro
IF BS HT CR
'\n' '\b' '\t' '\r'
EI Lexico del Lenguaje C
Nueva pagina "slash" Comilla Nulo Patron de bits
FF
'\f'
\
'\\' '\' ,
I
31
'\0' '\ddd'
Los digitos ddd especifican el canicter deseado (en octal). Vease en la figura 2.3, el correspondiente diagrama lexicognifico. En dicho diagrama, el especificador es el caracter 0 patron de bits indicado en la !ista anterior.
---o~1
r
caracter
1_-8-1f.L
especificador
~o-
IJ
Figura 2.3: Diagrama lexicognifico de la constante canicter.
2.3.4 Cadenas Una cadena se expresa como una secuencia de caracteres entre comillas dobles (" ... "). Ejemplos: "Nombre de pila\n"
"Ocupacion \n"
Una cadena es un arreglo de caracteres y puede manejarse como arreglo en el contexto de un programa. Sin embargo, una constante no puede modificarse en el transcurso del programa.
i---'-~O·-
1-8-1
especificador
Figura 2.4: Diagrama lexicografico de la cadena.
32
Fundamentos de Programacion en Lenguaje C
2.3.5 Constantes simb61icas Por medio de la directiva de compilaci6n #define utilizada al inicio del prograrna, pueden definirse referencias simbolicas a constantes de cualquiera de los tipos referidos en las cuatro secciones anteriores. Vease el ejemplo mostrado a continuacion:
/* Ejemplo de definicion de constantes simbolicas */ #define #define
NOMBRE EDAD
"ROLANDO MENCHACA" 22
EI compilador, antes de realizar su tarea de compilacion, sustituye la cadena de la derecha, siempre que encuentra el nombre simbolico de la izquierda. Vease el diagrama sintactico de este tipo de construccion en la figura 2.5.
-1
caract.r
h I
---I>'0B
identlficador-
cadena
e----
numero
Figura 2.5: Diagrama sintactico de la definicion simbolica de una constante.
2.4
IDENTIFICADORES
2.4.1 Modo de construcci6n de un identificador Los identificadores se utilizan para designar los distintos tipos de variables, campos, constantes simbolicas y funciones que es po sible manejar en C. Un identificador puede ser cualquier secuencia de letras 0 digitos que comience con una letra. El caracter '_' puede usarse como cualquier letra. Para C, las letras mayilsculas son diferentes de las minusculas. Solo los primeros caracteres son significativos para distinguir entre un identificador y otro,
EI Lexico del Lenguaje C
33
aun cuando el identificador puede tener cualquier longitud, la cantidad de caracteres significativos depende del compilador en particular, en Turbo C++ es un panimetro que se puede configurar. Vease el diagrama lexicognifico del identificador en la figura 2.6. En ellenguaje C las palabras clave deben escribirse con minusculas. Lo anterior se debe a que para C las letras mayusculas son diferentes de las mimisculas, y por 10 tanto es diferente un identificador escrito con mayusculas de otro escrito con minusculas. POl' ejemplo, las siguientes variables son todas diferentes: Nombre_de_Pila NOMBRE_DE_PILA nombre_de_pila Nombre_De_Pila NombreDePiia NOMBRE_de_PlLA nombre_De_pila
------~.~--~~------~--------~~----------
I_-B
-,
Figura 2.6: Diagrama lexicografico del identificador.
2.4.2 Atributos de un identificador Son atributos de un identificador, la clase de almacenamiento que tiene asociado y el tipo de dato 0 significado semantico de las secuencias de bits encontradas en el almacenamiento reservado para el identificador.
Clase de almacenamiento La clase de almacenamiento asociada con un identifieador detennina su localizaei6n y tiempo de vida. Hay cuatro clases de almaeenamiento declarables, 10 eual detennina diferentes tipos de variables: automatieas, estatieas, externas y registro.
34
Fundamentos de Programaci6n en Lenguaje C
En el Capitulo 3 se describini el campo de aplicacian y demas caracteristicas de estos distintos tipos de variables.
Tipo dedato Como ya se indica, el tipo de dato es el significado que tiene una secuencia de bits almacenada en cierta localidad de memoria. Por ejelnplo, el "caracter" es un tipo de dato de ocho bits de longitud, con el que se pueden representar las letras mayusculas y minusculas del alfabeto, los digitos decimales, los signos de puntuacion gramatical, los operadores matematicos, etc. El "entero" es un tipo de dato, tipicamente de 16 bits, con el cual se pueden representar numeros enteros en el rango de -32768 a 32767. Ellenguaje C soporta varios tipos de datos que son: caracteres enteros enteros sin signo numeros de punto flotante numeros de punto flotante, de doble precision arreglos funciones apuntadores estructuras uniones, y archivos Ademas, los metodos de construccion de objetos cOlnplejos como los apuntadores, arreglos, estructuras y uniones, pueden conjugarse incluso de manera recursiva. En el Capitulo 5 se estudian los tipos de datos y las operaciones y funciones que pueden realizarse con ellos.
2.4.3 Uso del mismo identificador para diferentes tipos de elemento Los identificadores asociados con variables ordinarias, asi como los asociados con nombres de miembros de estructuras 0 uniones, y los asociados con los nombres de las estructuras 0 uniones, forman clases disjuntas de identificadores. Los nombres de declaraciones de tipo, con la palabra clave typedef, pertenecen a la misma clase que los identificadores ordinarios.
EI Lexico del Lenguaje C
35
De este modo, un mismo identificador puede usarse, bajo el mismo ambito 0 alcance, para diferentes aplicaciones, con algunas restricciones; por ejemplo, es ilegal dec1arar una estructura 0 union que contenga una instancia de ella misma, pero se permite que la estructura 0 union tenga apuntadores a instancias de las mismas. (Vease en la seccion 3.2.2 la explicacion del alcance 0 ambito de aplicacion de la dec1aracion de una variable.) Si el alcance 0 ambito de aplicacion de las variables es diferente, es decir, si no se aplican en el mismo segmento de programa (funcion 0 instruccion compuesta), entonces, el mismo identificador puede usarse para variables ordinarias diferentes (vease la seccion 3.2.2.).
2.5 QPERADORES Ellenguaje C soporta varios tipos de operadores que podemos c1asificar bajo los siguientes rubros: operadores aritmeticos operadores relacionales operadores logicos operadores logicos al nivel de bit operadores de asignacion operadores de manipulacion de datos en bajo nivel operadores de expresion primaria, y operadores especiales A continuacion se listan los distintos tipos de operadores y su significado semantico en C. La descripcion de las correspondientes operaciones aritmeticas y logicas se presenta, conjuntamente con la descripcion de los tipos de datos a los cuales son aplicables los diferentes operadores, en el Capitulo 5.
Operadores aritmeticos Negativo Suma Resta Multiplicacion Division Residuo
+
* I %
36
Fundamentos de Programaci6n en Lenguaje C
Operadores relacionales Menor que Mayor que Menor que 0 igual a Mayor que 0 igual a Igual que Diferente de
< > =
!=
Operadores logicos Negacion Funcion 0 Funcion Y
II &&
Operadores logicos al nivel de bit (compuertas logicas) Complemento a 1 Funcion 0 Funcion Y Funcion 0 Exclusiva
I & A
Operadores de asignacion Asignacion si~ple Incremento aritmetico Decremento aritmetico Incremento geometrico Decrementogeometrico Modulo Corrimiento a la derecha. Corrimiento a la izquierda Ventana 0 logica Ventana Y logica Ventana 0 Exclusiva
+=
*= /= %=
»= «=
1= &=
EI Lexico del Lenguaje C
37
Operadores lipo lenguaje ensamblador Corrimiento a la derecha Corrimiento ala izquierda Indireccion Apuntador Incremento geometrico Decremento geometrico
» «
* &
*= /=
Operadores de expresi6n primaria Apuntador Funcion Arreglo Campo (modo indirecto) Campo (modo directo)
*
() [] ->
Operadores de funciones especia/es Conversion de tipos (casta) Expresion condicional Expresion intermedia
(tipo) ?:
En el Capitulo 5 se explica la forma en que se usan los distintos operadores, en conjuncion con la descripcion de la fonna en que deben hacerse las declaraciones de los tipos de datos que se pueden manejar en ellenguaje C.
2.6 PALABRAS CLAVE Las palabras clave son los elementos semanticos base de las instrucciones y declaraciones que son posibles en un lenguaje como C. Las palabras clave no deben usarse como identificadores. A continuacion se presenta una lista de las palabras clave, basicas de C.
38
Fundamentos de Programacion en Lenguaje C
int char float double struct union long short unsigned auto extern register static typedef goto return sizeof break continue
if else for do while switch case default
tipo entero tipo caracter tipo punto flotante tipo doble precision Estructura Union tipo entero de longitud grande tipo entero de longitud pequefia tipo entero sin signo variable automatic a variable externa variable registro variable estatica definicion de tipo de dato instruccion salta incondicional instruccion dato a retomar funcion tamafio de objeto instruccion interrupcion instruccion continuar instruccion condicional subinstruccion "en caso contrario" instruccion ciclo instruccion ciclo con plueba al final instruccion ciclo con prueba al inicio instruccion salto condicional multidireccion etiqueta para especificar un caso posible con la instruccion switch etiqueta para todos los demas casos no especificados que pudieran ocurrir, en una instruccion switch
En el Capitulo 4 se explica la sintaxis y la fonna en que se usan las distintas instrucciones dellenguaje C.
EI Lexico del Lenguaje C
39
Ejercicios 2.1 2.2 2.3 2.4 2.5 2.6
Explique que es un operador loPara que se utilizan los comentarios en un programa en lenguaje C? loPara que se usan el punto y coma (;) y las Haves en lenguaje C? Explique desde el punto de vista computacional que es una constante Explique que es un canicter y que una cadena loCmil es el valor decimal de los siguientes mimeros en base octal? 07, 017, 12177 Y 02234
2.7
loCual es el valor decimal de los siguientes numeros en base hexadecimal? OxFF, OXFFFF, OX1A, OXllFF, Ox7L, Ox2234L
2.8 2.9 2.10 2.11
Presente la tabla de valores ASCII estandar. Diga que entiende por clase de almacenamiento y que por alcance de una variable. loSe puede usar el mismo identificador para diferentes datos, variables u objetos, en un mismo programa? Calcule las siguientes operaciones: (125 % 27) % 2 ! (255) 255 I 255 1000 A 1000
2.12
Si A = 10 calcule las siguientes operaciones: A += 17 A *= 25 A %= 10 A «= 2 A&= 8
2.13 2.14
(5 && 0) II (3) '" (255) 255 & 255
A -= 100
A/= 2 A »= 2 AI 8 A A= 8
Presente los valores maximos de los numeros: enteros sin signo, enteros, punto flotante y punto flotante de doble precision, en C estandar. loCuantos y cmiles tipos de datos estandar maneja ellenguaje C?
Capitulo :3
ESTRUCTURA DE UN PROGRAMA EN C En este capitulo se describe la estructura general de un programa en lenguaje C, con el objetivo principal de que el lector identifique las partes principales que debe tener un programa y pueda planificar la estructura de los programas que va a desarrollar. Particulannente, debe planificar y luego declarar las estructuras de datos principales que va a necesitar, dividir su proceso computacional en modulos que puedan ser desarrollados por medio de las funciones de C y definir, a traves de la funcion main, la manera en que se van a interrelacionar los distintos elementos para llevar a termino y hacer funcionar correctamente el programa.
3.1 ESTRUCTURA GENERAL Un programa en C esta compuesto por una secuencia de declaraciones de datos y estructuras de datos y de un conjunto de definiciones de funciones. Una de esas funciones debe ser main. Es usual que esta funcion sea la primera en ser definida, y antes de ella se declaran todas las variables 0 estructuras de datos globales (las que son aplicables durante toda la ejecucion del programa), as! como las distintas funciones con el tipo de dato que fetoman y el tipo de parametros. Despues de main se definen las distintas funciones de que consta el programa. Un programa en C, al menos debe constar de la funcion main. En la figura 3.1 se muestra e1 diagrama sintactico de la estructura general de un programa.
dec!araci6n de datos
Definici6n de funci6n
Figura 3.1: Diagrama sintactico de un programa en C.
42
Fundamentos de Programaci6n en Lenguaje C
A continuacion describiremos la estructura general de las declaraciones de tipos de datos y de las definiciones de funciones.
3.2 ESTRUCTURA DE UNA DECLARACION 3.2.1 Estructura general de una declaraci6n Una declaracion en C consta de un conjunto de especificadores y una lista de declaradores con sus inicializadores opcionales (vease el diagrama sintactico de la figura 3.2). Los especificadores pueden ser de clase de almacenamiento y/o de tipo de dato. Los declaradores constituyen los datos, variables 0 estructuras de datos a ser declarados, y los inicializadores constituyen los valores iniciales de las variables 0 estructuras de datos declaradas.
Especificador de Clase de Almacenamiento
------"L-t>j
Especificador d tip 0 d e d at 0
Figura 3.2: Diagrama sintactico de una declaracion.
3.2.2 Especificadores de c1ase de almacenamiento y a1cance Los especificadores de clase de almacenamiento determinan el tiempo de vida, alcance 0 ambito de aplicacion de las distintas variables declaradas. Se dispone de los siguientes especificadores de clase de almacenamiento en lenguaje C: auto static register extern typedef
variable automatic a variable estatica variable registro variable extema definicion de tipo
Estructura de un Programa en C
43
Excepto typedef y extern, estos especificadores Ie dan al compilador Ia clave para que asigne el tipo de memoria que se requiere para una determinada variable. En el caso de extern debe existir una dec1aracion externa de los correspondientes identificadores y por 10 tanto la asignacion de memoria requerida para elIos. Por dec1aracion externa se entiende una declaracion aparecida en un segmento de programa compilado por separado, 0 simplemente fuera de la funcion en que se declaro la variable extema (variable global).
Especificador de clase de Almacenamiento
- - - - - - - - - - -... 1Especificador de Tipo def--_ __ Dato
Figura 3.3: Diagrama sintactico del especificador.
El especificador typedef no implica que se reserve memoria, sino que permite crear castas 0 tipos complejos de datos; aunque semanticamente es diferente de los otros especificadores de c1ase de almacenamiento, sintacticamente es equivalente (ocupa la misma posicion en el contexte de la declaracion). En la figura 3.3 se muestra el diagrama sintactico del especificador. Una declaracion solo puede tener uno 0 ningun especificador de clase de aImacenamiento. Si no contiene especificador de clase de almacenamiento se considera que la variable es externa, si la dec1aracion se realizo en el segmento de declaraciones externas (globales) del programa. Si la declaracion se realiza en el interior de una funcion, por omision se considera que la variable es automatica. En el segmento de declaraciones externas solo pueden declararse variables externas 0 estaticas. Las declaraciones de variables tipo registro, solo son aplicables a tipos de datos que dependen de la implementacion (por ejemplo: enteros, caracteres 0 apuntadores). Empleando apropiadamente las declaraciones de variables registro, pueden construirse program as mas rapidos.
44
Fundamentos de Programaci6n en Lenguaje C
Alcance 0 ambito de un identificador 0 variable Existen dos clases de alcance 0 ambito de un identificador. Ellexicognifico y el semantico. EI ambito lexicografico detennina la region del programa en que puede emplearse el identificador sin que el compilador considere que esta indefinido (no se ha declarado) y que por 10 tanto exista error. El ambito lexicografico de las variables declaradas como extemas se extiende desde el lugar de la declaraci6n, hasta el final del archivo en el cual aparece la declaraci6n; el de los parametros formales se mantiene en toda la funci6n a la que pertenecen; el de los identificadores declarados dentro de un bloque (instrucciones encerradas entre Haves { ... }), se mantiene en todo el bloque; el de una etiqueta, abarca toda la funci6n en la cual aparece. En el inicio del bloque de c6digo- perteneciente a una funci6n 0 de cualquier otro bloque de c6digo, puede usarse un identificador anterionnente usado en una declaraci6n extema como variable local y en ese caso, la declaraci6n extema deja de aplicarse durante todo el bloque de c6digo correspondiente. Es conveniente recordar que los identificadores asociados con variables ordinarias, constituyen clases disjuntas con los asociados con estructuras 0 uniones o con los asociados con miembros de estructuras 0 uniones (vease Secc. 1.4.3), por 10 que puede usarse un mislno identificador para dos 0 nlas propositos, en el mismo segmento de c6digo. Vease tambien la declarad6n de estructuras 0 uniones en las secciones 5.6 y 5.7. EI ambito semantico se refiere principalmente a la regIa de que las referencias al mismo identificador extemo, son referencias al mismo objeto. En un programa repartido en varios archivos s610 debe haber una declaraci6n del identificador de una variable global que no haya sido calificada con el especificador extern; en todas las demas declaraciones debe usarse dicho declarador para referirse al objeto correspondiente. Si un identificador se declara como estatico, por medio del especificador static, el identificador no sera visible en otros archivos. Las funciones tambien pueden ser declaradas como estaticas.
3.2.3 Especificadores de tipo de dato . Los especificadores de tipo de dato, detenninan el tipo de dato 0 elemento de informaci6n que contendra el area de memoria reservada para las variables declaradas por medio de la declaraci6n en proceso. Vease en Ia figura 3.3 el diagrama sintactico del especificador. Podemos clasificar los tipos de datos en dos grandes grupos: datos basicos y datos compuestos.
Estructura de un Programa en C
45
Tipos de datos basicos Los tipos de datos basicos que maneja C y las palabras clave que constituyen sus correspondientes especificadores, son los siguientes: Tipe
Palabra
caracter entero de longitud estandar entero de longitud grande entero de longitud pequefia entero sin signo punto flotante (real) punto flotante doble precision apuntadores
char int long int short int unsigned float double
0
simbolo clave
*
En el Capitulo 5 se analizan con detaUe los distintos tipos de datos y las operaciones y funciones de biblioteca mas usuales que son aplicables a dichos tipos de datos. Los apuntadores se declaran anteponiendo al identificador 0 declarador el simbolo *. El tipo de dato al eual sefiala el apuntador es determinado por medio del correspondiente especificador.
Tipos de datos compuestos Ellenguaje C maneja varios tipos de datos compuestos, 0 estructuras, que agrupan varios datos de un mislno tipo 0 de tipos diferentes, los tipos compuestos mas simples son: Tipo
Palabra
arreglo estructura union archivo
[] struct union
0
simbolo clave
FILE
Estos tipos base pueden combinarse para formar estructuras mas complejas. Por medio del simbolo *, utilizado incluso en forma recursiva, se pueden declarar apuntadores a estructuras complejas, 0 estructuras complejas que contengan apuntadores 0 elementos constituidos porapuntadores. Pueden tambien crearse archivos que contengan secuencias de estructuras complejas 0 de tipos de datos basicos.
46
Fundamentos de Programacion en Lenguaje C
Las funciones que retoman un valor numerico 0 apuntador, pueden formar parte de expresiones 0 manejarse como un dato basico. Una explicacion mas detallada de los tipos de datos y las operaciones que son aplicables a eUos se da en el Capitulo 5. Por otro lado, por medio de la definicion de nombres de tipo descrita en la seccion 3.2.7, se pueden definir nuevos tipos de datos para usarse como especificadores para dec1arar variables de ese tipo 0 derivados de el.
3.2.4 Estructura de los declaradores Los dec1aradores estan determinados basicamente por los identificadores de las variables a ser dec1aradas y por operadores de expresion primaria. Los dec1aradores son calificados por los operadores de expresion primaria; 0 sea: el operador apuntador, *; el operador arreglo, [ ]; y el operador funcion, ( ). Pueden formarse estructuras de datos mas complejas, volviendo a calificar un dec1arador encerrado entre parentesis con estos operadores de expresion primaria. Vease en la figura 3.4 el diagrama sintactico &~l declarador.
Hsta de iniciaHi-
zadores IniciaBi1----1
zador
!dentificador I+------~'-r---L-----------'-_t>
Q)_--.Jl Figura 3.4: Diagrama sintactico del dec1arador.
Cada dec1arador de term ina una variable del tipo indicado por los especificadores de la dec1aracion. Si el especificador es del tipo T y el dec1arador tiene la forma *declarador, entonces la variable dec1arada es un apuntador a un dato de tipo T. Si el especificador indica que el dato es de tipo T y el declarador es de la forma declarador[expresion-dimension], la estructura de datos dec1arada es un
Estructura de un Programa en C
47
arreglo del tipo T, cuya dimensi6n esta definida por la expresi6n-dimensi6n, la cual debe ser constante de tipo entero sin signo. En C el primer elemento de un arreglo es el elemento O. Si el especificador indica que el objeto es de tipo T y el declarador es de la forma deciaradorO, entonces 10 que se dec1ara es una funci6n que retoma un dato de tipo T. Las funciones no pueden retomar arreglos, estructuras, uniones 0 funciones, pero S1 pueden retomar apuntadores a dichos elementos. Entre los parentesis se pueden definir, opcionalnlente, los panimetros de la funci6n, tal como se indica en la figura 3.4. La lista de inicializadores encerrada entre Haves, mostrada en la figura 3.4, se aplica a la declaraci6n de un arreglo 0 a la de una estructura. EI especificador debe indicar si se trata de una estructura 0 de un arreglo. Los arreglos de uniones pueden tener miembros de diferentes tipos, declarados de acuerdo a las reglas aplicables a las uniones, especificadas en esta secci6n y en el Capitulo 5. Un arreglo, estructura 0 uni6n no puede contener una funcion, pero sf un apuntador a una funci6n.
3.2.5 Ejemplos de dec1araciones sin inicializador El ejemplo 3.1, declara un entero I, un apuntador IP a un entero, una funcion F que retoma un entero, una funcion FIP que retoma un apuntador a un entero y un apuntador PFI a una funci6n que retorna un entero. Ejemplo 3.1: Declaracion de enteros y objetos relacionados.
El ejemplo 3.2 declara un arreglo tridimensional extemo con dimension 3x5x7. La estructuracion de arreglos en C es asociativa de izquierda a derecha, por 10 cual se interpreta que el arreglo X3D es de tres matrices de 5x7. 0 bien tres arreglos de cinco filas y siete columnas. Ejemplo 3.2: Declaracion de un arreglo tridimensional. extern int X3D[3][S][7];
En el ejemplo 3.3 se declara una estructura del tipo NODO con cuatro miembros, NOMBRE, que es un arreglo de 20 caracteres, CONTADOR, que es un entero, e IZQUIERDO y DERECHO, que son apuntadores a una estructura del mismo tipo NODO.
48
Fundamentos de Programacion en Lenguaje C
Ejemplo 3.3: Declaraci6n de una estructura. struct NODO {
char int struct NODO struct NODO };
NOMBRE [20]; CONTADOR; *IZQUIERDO; *DERECHO;
3.2.6 Inicializadores Ellenguaje C pennite inicializar cualquier variable declarada, a un valor 0 conjunto de valores especifico. El inicializador es el correspondiente valor 0 conjunto de valores que sera almacenado en la localidad 0 localidades de memoria de la variable que se requiere inicializar. El inicializador va precedido del signo =, como se aprecia en el diagrama sintactico de la figura 3.2. El inicializador consiste de una expresi6n 0 una lista de expresiones encerradas entre Haves, tal como se indica en el diagrama sintactico de la figura 3.5.
---~'I
e.presion
~~I,----elt._pr_eS_i6_n~-----;------ICD-
'-----fOI4Q
- -
Figura 3.5: Diagrama sintactico del inicializador.
Las expresiones que definen al inicializador de una variable estatica 0 externa deben ser constantes 0 una direcci6n de una variable declarada previamente, a 10 sumo modificada por un corrimiento determinado por una expresi6n cons!ante. Si una variable estatica 0 extema no es inicializada explicitamente, por omision C la inicializa a cero. Las variables automaticas 0 tipo registro pueden inicializarse con expresiones arbitrarias que involucren constantes, variables declaradas previamente 0 fun-
Estructura de un Programa en C
49
ciones. Si este tipo de variables no son inicializadas, C no las inicializa por omision, de manera que tendnin la "basura" que el sistema les hubiere dejado. Cuando se inicializa un apuntador, 0 un dato de tipo aritmetico, el inicializador consistini de una sola expresion, que puede encerrarse entre Haves { }. EI valor inicial del objeto es el correspondiente valor resultante de la evaluacion de la expresi6n. Al evaluar la expresi6n, C realiza las conversiones que normalmente efectlia en forma automatic a en la ejecucion de instrucciones de asignacion. Estas conversiones se describen en el Capitulo 5, conjuntamente con los diferentes tipos de datos y sus operaciones asociadas. Cuando la variable declarada es una estructura 0 arreglo, el inicializador esta constituido por una lista de expresiones separadas por comas (,) y encerradas entre Baves, {}. La lista debe escribirse de acuerdo al subindice u orden de la estructura 0 arreglo. Si uno 0 varios de los elementos de la estructura son otras estructuras, esta regIa se aplica recursivamente. Si se declaran menos elementos de los que debe tener el conjunto, todo el resto del conjunto se inicializa a ceros. Los elementos componentes de una estructura, que es a su vez elemento de otra estructura, pueden 0 no encerrarse entre Haves. C considera un error que una lista encerrada entre Baves tenga mas miembros que los que debe tener la correspondiente estructura. A continuacion se ilustra con ejemplos las reglas anteriores: Ejemplo 3.4: Inicializacion de un arreglo bidimensional, agrupando los datos por filas. float Y[4][3]
= {{1,3,5},{2,4,6},{3,5,7},};
Ejemplo 3.5: Inicializacion de un arreglo bidimensional, sin agrupar por filas. float Y[4][3] = {1,3,5,2,4,6,3,5,7,};
Las declaraciones de los ejemplos 3.4 y 3.5 son equivalentes; 1,3 y 5, inicializan la primera fila de un arreglo de cuatro filas x tres columnas; 2,4 y 6, la segunda; 3, 5 y 7, la tercera; y la cuarta se inicializa a ceros. Ejemplo 3.6: Inicializacion truncada de un arreglo. float Y[3][4] = {1,2,3,4};
En el ejemplo 3.6 se inicializa la primera fila de un arreglo de 3x4, con los valores 1,2,3 y 4; el resto del arreglo se inicializa con ceros. EI lenguaje C no permite que se inicialicen uniones, tampoco permite que se inicialicen estructuras 0 arreglos declarados como automaticos.
50
Fundamentos de Programaci6n en Lenguaje C
Un arreglo de caracteres puede inicializarse con una cadena (recuerdese que la cadena es en sl una constante y a la vez un arreglo de caracteres). EI ejemplo 3.7 ilustra este tipo de declaracion. Ejemplo 3.7: Declaracion e inicializacion de una cadena de caracteres. char
*mensaje
= "Error de sintaxis en la linea %d \n";
Recuerdese que \n representa un cambio de renglon. Los caracteres %d indican posiciones en el arreglo cuyo contenido puede ser modificado por el programa.
3.2.7 Declaraci6n de nombres tipo Hay dos casos en los cuales es necesario definir tipos de datos con nombres especiales: a) para especificar conversiones de tipo por medio de una casta 0 ins truccion de conversion de tipo y, b) para contar con un argumento del operador sizeof, para determinar y especificar la longitud de un tipo 0 estructura de datos.
La definicion de un nombre tipo puede realizarse por medio de una de claracion, en la cual, como especificador de clase de alrnacenamiento, se utiliza la palabra clave typedef. Los ejemplos 3.8 y 3.9 muestran, respectivamente, la forma en que se declaran y usan los nombres tipo, deiinidos por medio del especificador typedef. En la seccion 4.16 se describe la sintaxis de las conversiones de tipo. Ejemplo 3.8: Declaracion de un tipo de dato mediante typedef. typedef struct {double REAL, IMAGINARIO;} COMPLEJO;
En este ejemplo se declara un nombre tipo denominado COMPLEJO, el cual es una estructura compuesta de dos elementos que son, anlbos, reales de doble precision y se denominan REAL e IMAGINARIO, respectivamente. Ejemplo 3.9: Uso de un tipo de dato declarado con typedef. COMPLEJO Z, *AP_Z;
Estructura de un Programa en C
51
En este ejemplo, aprovechando la dec1aracion descrita en el ejemplo 3.8, se declara una variable de tipo COMPLEJO y un apuntador a una variable del mismo tipo.
3.3
ESTRUCTURA DE UNA DEFINICION DE FUNCION
3.3.1 Estructura general de la definicion de una funcion Como puede apreciarse en el diagrama sintactico de la figura 3.6, la definicion de una funcion consta de un especificador, el declarador de la fundon y el cuerpo de la funcion.
Especificador
Declarador de Funci6n
Cue rp 0 de la Funci6n
1-
Figura 3.6: Diagrama sintactico de la definicion de una funcion.
EI especificador establece el tipo de dato que retomara 0 entregara como resultado la funcion cada vez que se invoque; el declarador de la funcion incluye su identificador, y la declaracion de sus parametros, los cuales son opcionales, y, finalmente, el cuerpo de la funcion, que debe estar encerrado entre Haves, constituye la rutina de programacion que se ejecuta cada que se invoca la funcion. El cuerpo de la funci6n debe tener, al menos, las Haves con que se inicia y termina la definicion. Si el cuerpo de la funcion no incluye instruccion alguna, la funcion no realiza tarea alguna; sin embargo, el compilador de C considera correcta la sintaxis de la funcion. A continuacion se describe cada uno de estos elementos de la definicion de una funcion en ellenguaje C.
3.3.2 Especificador y valor retomado Una funcion que retoma algun valor (0 funcion retomante), puede ser utilizada como expresion primaria y, por 10 tanto, puede formar parte de expresiones mas complejas. Por ejemplo, dicha funcion puede sumarse, multiplicarse, restarse, dividirse, etc., con otras expresiones. EI valor que debe retomar la funcion, es el valor que tamara la misma, el cual sera utilizado para evaluar la correspondiente
52
Fundamentos de Programaci6n en Lenguaje C
expresion compleja de la que fonna parte. Por medio de la instruccion return se define el valor que retomani la funcian. La sintaxis de la expresion se describe en la seccion 4.1, conjuntamente con la de la instruccion de asignacion, y Ia de la instruccion return, en la seccion 4.12. La sintaxis del especificador es la misma que se describe en la seccion 3.2. No obstante, en este caso los unicos especificadores de clase de almacenamiento pennitidos son extern y static. El tipo de valor que retoma la funcion se define con el especificador de tipo de dato, el cual tiene la sintaxis descrita en la seccion 3.2.3, excepto que el valor a retornar solo puede ser de uno de los tipos basicos indicados en la seccion 3.2.3.0 sea que, no se puede retomar una estructura, arreglo 0 funcion; sin embargo, sf puede retornarse un apuntador a cualquier tipo de estructura de datos.
3.3.3 Declarador de funci6n y parametros formales En la figura 3.7 se muestra el diagrama sintactico del declarador de funcion, que consta del identificador de funcion y la lista de panimetros encerrada entre parentesis. C solo pennite el paso de panimetros por valor y unicamente de los tipos basicos, indicados en la seccion 3.2.3. No obstante, el no contar con una forma directa de pasar parametros por referencia 0 de tipo estructura, arreglo 0 funcion, no es una limitacion de C, ya que pueden pasarse apuntadores a cualquiera de este tipo de datos y con ello pueden resolverse las necesidades de programacion que pudieran tenerse al respecto y tambien se resuelve el problema del paso de parametros por referencia. Como se menciono con anterioridad, los parametros son opcionales, pero si se incluyen, toda la lista de parametros debe ser declarada entre los parentesis, tal como se indica en la figura 3.7. Estas declaraciones tienen la misma sintaxis descrita en la seccion 3.2, pero cada parametro debe tener una declaracion independiente; es decir, no se pueden incluir dos 0 mas parametros en una misma declaracion. Se reca1ca que el campo de aplicacion de los parametros fonnales, es todo el cuerpo de la funcion.
----
Id entitle ill d 0 r
---e{!)-.-----------r--e>t lis ta de '---- deelaraeiones de param etros
_
Figura 3.7: Diagrama sintactico del declarador de funcion.
Estl1Jctura de un Programa en C
53
3.3.4 Cuerpo de la funci6n En la figura 3.8 se muestra la sintaxis del cuerpo de la funcion y, como se aprecia, consta de dos partes: la lista de declaraciones particulares de la funcion y la lista de instrucciones. decla'aclon
~
I
instruccion
T0~
~~
Figura 3.8: Diagrama sintactico del cuerpo de la funcion.
En el cuerpo de la funcion pueden declararse variables que solo tienen aplicacion en la propia funcion. A tiempo de ejecucion, se obtienen las areas de memoria que son reservadas para estas variables, y una vez que termina de ejecutarse la funcion, dichas areas se reutilizan para almacenar otras variables. La sintaxis de estas declaraciones es identica a la descrita en la sec cion 3.2,y puede declararse cualesquiera de los tipos de dato 0 estructura ahi referidos. Luego de las declaraciones, se deben escribir las instrucciones. C cuenta con instrucciones de control de secuencia para ejecucion condicional, ejecucion condicional multiple, ciclos de ejecucion con pruebas de salida del ciclo al principio 0 al final, ciclos con variable 0 variables de control, salto incondicional, salida incondicional de un ciclo, 0 continuacion de cicIo; pueden hacerse llamadas a otras funciones del mismo programa,.o de las bibliotecas estandar. El lenguaje C tambien cuenta con diversos tipos de asignacion y, ademas, pueden construirse instrucciones compuestas mediante las Baves { }. La descripcion de todas estas instrucciones se realiza en el Capitulo 4.
3.3.5 Recursividad En C, las funciones pueden usarse recursivamente, es decir, pueden Bamarse a sf mismas, en el cuerpo de su definicion. En el ejemplo 3.14, se muestra la definicion de una funcion recursiva. Con elIas se pueden ahorrar muchas lineas de programacion en la solucion de algunos problemas, por ejemplo, para el ca1cul0 de series aritmeticas 0 geometricas, para las busquedas en estructuras de datos tipo arbol, etcetera.
54
Fundamentos de Programacion en Lenguaje C
EI lenguaje C no pennite definir funciones dentro de otras funciones, tal y como 10 penniten otros lenguajes, por ejemplo, Pascal. A esto se Ie conoce como "declaracion anidada de funciones".
3.3.6 Funciones de biblioteca estcindar EI lenguaje C tiene varias bibliotecas estandar de funciones y estructuras de datos especiales para realizar distintos tipos de tareas. Por ejemplo, las funciones de entrada y salida para comunicacion con perifericos; para calculo de funciones matematicas; para dibujo, etc. La tabla 3.1 muestra algunas de las bibliotecas estandar mas usuales. Dependiendo de la implantacion, el compilador puede reconocer directamente estas funciones, incluyendo la biblioteca correspondiente mediante la directiva include; 0 puede ser necesario declararlas como funciones extemas y despues se requerira concatenar el archivo del programa con las correspondientes bibliotecas, por medio del concatenador 0 enlazador (0 ligador) del correspondiente sistema. En el mercado existen bibliotecas adicionales aplicables en areas especificas de programacion, como son: bases de datos, graficacion, interfaces de usuario, comunicaciones, instrumentacion virtual, procesamiento de senales, etc. Estas bibliotecas pueden hacer mucho mas facilla tarea de programacion.
Tabla 3.1: Algunas importantes bibliotecas de C. Biblioteca
Descri pCion
Prueba de clasificacion de caracteres Entrada/Salida Numeros de error Constantes de punto t10tante Graficas Limites definidos en la implantacion Funciones matematicas Saltos no-locales Sefiales Listas de argumentos variables Entrada y salida estandar Funciones de utileria Funciones para cadenas Funciones de fecha y hora
Estructura de un Programa en C
55
En el Capitulo 5 se describen algunas de las funciones matematicas y de manejo de caracteres de las bibliotecas de C; en el 6 se describen las funciones en forma general; en el 7 las funciones de entrada/salida estandar y otros elementos de programacion que son utilizados por C como interfaz con el sistema operatiVO, y en el 8 se describen algunas funciones utilizadas en graficaci6n.
3.4 EJEMPLOS SENCILLOS DE SEGMENTOS DE PROGRAMAS EN C Ejemplo 3.10: Programa "vacio.c".
/* Esta funcion no ejecuta acciones, se puede usar mientras se prueba un segmento de programa
*/ void VACIAO {} mainO {
VACIAO; }
La funcion VACIA del ejemplo 3.10 representa la sintaxis minima que debe tener la declaracion de una funcion en C, para que sea reconocida como correcta por el compilador. Declaraciones como esta son utiles cuando se esta elaborando un programa y hay una determinada funcion que todavia no se desarrolla. El programa del ejemplo 3.10 no genera mensajes de error al compilarse y se ejecuta correctamente, pero 10 que hace es, simplemente, nada. Ejemplo 3.11: Pro gram a "maximo.c", calculo del valor maximo.
/* La funcion MAXIMO da como resultado el valor maximo de los tres enteros que se Ie pasan como argumentos int MAXIMO(int A, int B, int C)
*/
/ / Notese que cada parametro tiene su / / declaracion independiente
{
int M; M = (A > B) ? A : B; return (( M > C ) ? M : C); }
mainO {
/ / Uso de la expresion condicional para elegir el / / mayor entre A y B, asignandolo a M / / Retorno del mayor de entre M y C
56
Fundamentos de Programacion en Lenguaje C
printf("\nEI maximo es %d\n", MAXIMO(-25, 3, -75));
}
El ejemplo 3.11 ya es un programa completo que realiza una tarea especifica: encontrar el valor maximo de tres variables y presentarlo en pantalla. La funcion MAXIMO retoma el valor del mayor de tres datos que Ie son pasados como parametros. Utiliza una variable cuyo campo de aplicacion solo es local, que es M. Para definir el valor del mayor de los tres datos de entrada, utiliza el operador condicional ?. Primero compara dos de los datos y Ie asigna el valor del mayor a la variable M, luego compara la variable M con el otro dato de entrada y retoma el mayor de los dos. Mediante la funcion printf utilizada en main, se imprime el valor maximo de los enteros: -25,3, -75. Lo que se presenta en la pantalla es: EI maximo es 3. El programa del ejemplo 3.12 es ya un poco mas elaborado, y busca en la secuencia de caracteres que se Ie da como entrada, la palabra BUSCADA, e imprime cada linea que contiene esa palabra. Si la linea no tiene la palabra no la imprime. El programa consta de tres funciones: main, LEE e IN DICE. Ademas, main hace uso de la funcion de salida estandar printf y LEE hace uso de la funcion de entrada estandar getchar. En el programa se hace uso de diversas estructuras que se discuten mas adelante con detenimiento y por ello se aconseja no analizar en este momento estos aspectos, sino unicamente la estructura general del prograrna.
Ejempl0 3.12: Programa "busca.c", busqueda de una secuencia de caracteres conocida. #define MAXLONG
100
/* --------------------------------------------------------------------------------------------*/ /* Programa Principal */ int mainO { char LINEA[MAXLONG]; while( LEE( LINEA, MAXLONG ) > 0) if (INDICE(LINEA,uBUSCADA") >= 0) printf( 11%5", LINEA );
}
/* int LEE( char S[ { int 1=0;
Lectura de la Siguiente Unea
J,
int L )
*/
Estructura de un Programa en C
57
char C; while ( (--L > 0) &&·(C = getcharO != EOF) && (C != '\n'» S [1++] = C; if (C == '\n') S [1++] = C;
S [I]
= '\0';
return I;
}
/*
Indice de la Cadena Buscada
*/
int INDICE( char S[], char T[ ])
{ int I, J, K, R; R = -1; for ( 1=0; S[ 1 ] != '\0'; 1++ ) for(J=I, K=O; (T[K] !='\O') && (S[J] ==T [K]); J++, K++) if (T [K+l] == '\0' ) R = I; return R;
}
No obstante 10 anterior, a continuacion se describe el funcionamiento de la~ funciones LEE e INDICE. La funcion LEE obtiene la siguiente linea del archivo de entrada y la guarda en el arreglo LINEA, cuyo apuntador a su inicio se Ie pasa como parametro a LEE. Si la linea leida es de longitud cero (0), es decir, si ya no hay otra linea que leer, se suspende la ejecucion del programa; si no, se prosigue leyendo e imprimiendo (si la linea contiene la cadena BUSCADA). Obtiene la siguiente linea de la entrada (tec1ado), caracter por caracter, por medio de la funcion estandar getchar, hasta obtener un cambio de renglon (,\n'), llegar al final del archivo, 0 que se exceda la longitud maxima pennitida para la linea, la cual se Ie pasa por medio del parametro L; y va guardando los caracteres en fonna secuencial en el arreglo cuya direcci6n es la dada por el parametro S. Al encontrar el cambio de reng16n, 10 guarda en S, luego guarda un caracter nulo y retoma la longitud de la cadena. Si encontro el final del archivo, retoma un cero (0). La funcion IN DICE prueba si la cadena BUSCADA esta contenida en LINEA, retoma la indicacion de que S1 se encuentra, y luego main, por medio de la funcion estandar printf imprime la linea. IN DICE compara la cadena BUSCADA cuya direccion de inicio se Ie pasa por medio del parametro T, con la cadena aimacenada en el bufer de la siguiente linea, cuya direccion se Ie pasa a IN DICE, por medio del parametro S. La comparacion se va realizando recorriendo la linea y comparando caracter por caracter, hasta encontrar que aparece Ia cadena BUSCADA 0 que ya se tennin6 la linea. En este programa se usan las estructuras de programacion para iteraciones c1clicas while y for, la instruccion condicional if, la instruccion de asignacion
58
Fundamentos de Programacion en Lenguaje C
simple, la instruccion return y las funciones estandar getchar 0 printf. Todos estos elementos de programacion se discutiran con detenimiento, en los Capitulos 4,5 Y 6.
Ejemplo 3.13: Programa "potene.e", ealcula potencias enteras de un entero. PROGRAMA PARA CALCULAR POTENCIAS /***** mainO { int I; for ( 1==0; I < 10; ++1) printf("%d %d %d \n", I, POWER(2,I), POWER(-3,I»; } CALCULO DE LA POTENCIA /***** int POWER(int X, int N) { int I, P==l; for (1==1; I 0) if (CAR == ") NCAR++; printf("EI numero de blancos del Archivo 0/05 es %d \n", ACAR, NCAR); fclose(ARCHIVO); return 0;
}
Con la instruccion while de la doceava linea (del codigo anterior), se realiza el conteo de blancos, despues de abrir el archivo con la estructura if, que empieza en la septima linea.
4.7 INSTRUCCION dO".while La instruccion do-while es otra estructura de programacion iterativa que tiene la forma de la figura 4.2. Como se ve en dicha figura, la estructura while tiene su prueba que determina si se ejecuta la siguiente iteracion, al final del ciclo. Igualmente, en el cuerpo del ciclo do-while esta la instruccion que se va a ejecutar de manera iterativa, la cual desde luego puede ser una instruccion compuesta. Esta estructura es equivalente al repeat-until de Pascal.
j instrucci6n
1
FALSO
Figura 4.3: Estructura do-while.
68
Fundamentos de Programacion en Lenguaje C
La expresi6n logica de la prueba final, igualmente puede ser una tautologfa, y entonces se tiene que abandonar el ciclo por medio de la instrucci6n goto, break 0 exitO, mediante alguna otra prueba de control de secuencia intermedia. La sintaxis de esta instrucci6n es: do instrucci6n while (expresi6nJ6gica);
En el programa del ejemplo 4.2 se ilustra el uso del do-while. En el se cuenta el numero de comas (,) que tiene un archivo de caracteres. Ejemplo 4.2: Programa "cuentcom.c", contador de comas dentro de un archivo. # include FILE *ARCHIVO; main(int argc, char *argv[]) { char CAR, *ACAR = argv[l], ARCH[20]; int NCAR = 0; if(argc == 1) {printf("NOMBRE DEL ARCHIVO?\n"); scanf("%s",ARCH); ACAR = ARCH; ARCHIVO = fopen(ARCH,"r");} else ARCHIVO = fopen(argv[l],"rll); do if «CAR = getc(ARCHIVO)) == ',') NCAR++; while (CAR> 0); printf("EI numero de Comas del Archivo 0/05 es %d \n", ACAR, NCAR); fclose(ARCHIVO); return 0;
}
La forma en que esta realizado este programa es muy similar a la del ejemplo 4.1, s6lo se cambia la instrucci6n while por una estructura do-while y el mensaje de la funci6n de salida printf. En la pnictica es menos usual esta estructura que while 0 for; sin embargo, especialmente cuando la instruccion del cuerpo del do-while se tiene que ejecutar por 10 menos una vez, es conveniente usarla.
4.8 lNsTRuCCION for La instrucci6n for es heredera del ciclo iterativo do original de Fortran y de las instrucciones for-next de Basic y Pascal; sin embargo, el for de C es mucho mas flexible y poderoso. Algunas de las caracteristicas que 10 hacen una estructura mas poderosa son: inicializaci6n multiple de variables, expresi6n logica de
Instrucciones
69
prueba de cualquier complejidad y no unicamente restringida a que la variable de control alcance un valor final y especificacion multiple de incrementos. La sintaxis del for es la siguiente: for (expr_inicializadoras; expr_de_control; expr_de_incremento) instrucci6n; La estructura de la instruccion for se muestra en la figura 4.3. Como se ve, la prueba que determina si se ejecuta la siguiente iteracion, en este caso es al principio del cielo. En el cuerpo del cielo for esta la instruccion que se va a ejecutar de manera iterativa, la cual desde luego, puede ser una instruccion compuesta. La expresion 16gica de la prueba, puede ser una tautologia, en cuyo caso se tiene que abandonar el cielo par media de la instruccion goto, break 0 exitO, mediante alguna otra prueba de control de secuencia intermedia; 0 bien una expresion logica compleja que implique el cumplimiento 0 incumplimiento de diversas premisas.
inicializaci6n
. - - - < - . expresi6n
/'-----t>
I instrucci6n
Figura 4.4: Estructura for.
4.9 INSTRUCCION switch-case La instruccion switch-case representa una estructura de programacion de decision multiple y ha sido de gran utilidad en la programacion estructurada. Su sintaxis es: switch( expresi6n_entera ) {
case exp_const : instrucci6n;
70
Fundamentos de Programacion en Lenguaje C
default exp_const : instrucci6n;
}
La instruccion switch-case opera de la siguiente manera: se avalua la expresion entera que sigue a la palabra switch y que constituye la expresion de control; y a continuacion se ejecutan las instrucciones en el cuerpo del switch, empezando con la que se encuentra marcada por el case (caso) que tiene como etiqueta un valor constante que toma la expresion de control del switch, en un momento dado. La figura 4.4 muestra la estructura basica de esta instruccion. En esta figura se ve que se ejecutan todas las instrucciones asociadas a los casos que comienzan a partir del caso que se cumple, es decir, el correspondiente al valor que toma la expresion de control.
No "-
~~i J
~
I
Instr~cci6nl
No •
Figura 4.5: Estructura switch-case.
Puede salirse desde puntos intennedios de la estructura switch-case mediante la instruccion break; tal como se muestra en el ejemplo 4.3, que contiene la estructura de ejecucion del menu principal de una ca1culadora estadistica; en la estructura de la figura 4.5 tambien se muestra el uso de break para salir de la estructura switch-case. Esta estructura es muy apropiada para realizar menus de comandos, como el que se ilustra en el ejemplo 4.3. En ese ejemplo, la funcion MENUESTADISTICO presenta el menu en la pantalla, pide el comando y regresa el numero de comando que eligio el usuario. Este numero de comando define los casos que conforman las etiquetas de la estructura y, por 10 tanto, se ejecuta unicamente la fun-
Instrucciones
71
cion estadistica que fue elegida. Se supone que METERDATOS cargara los datos en forma interactiva con el usuario. Ejemplo 4.3: Estructura switch-case para una ca1culadora estadistica. switch (MENUESTADISTICOO) { case 1: PROMEDIO(DATOS); break;} case 2: VARIANZA(DATOS); break;} case 3: MODA(DATOS); break;} case 4: MEDIANA(DATOS); break;} case 5: DESVSTANDAR(DATOS); break;} case 6: DISTACUMU(DATOS); break;} case 7: MAXIMO(DATOS); break;} case 8: MINIMO(DATOS); break;} case 9: METERDATOS(DATOS) break;} case 10: exit(O); /* salir del programa */ }
Expresi6n
I
1
Figura 4.6: Estructura switch-case con break.
4.10 INSTRUCCION break La instruccion break se utiliza para abandonar una estructura iterativa 0 switchcase en un punto cualquiera de la estructura y no necesariamente al principio 0 al final. break saca al programa del cicio 0 estructura, en el nivel de anidamiento actual. La figura 4.7 ilustra una estructura while, en la cual se usa break en conjuncion con una instruccion de decision if para salir del ciclo iterativo.
72
Fundamentos de Programacion en Lenguaje C
1
Figura 4.7: Estructura while con un break.
4.11
INSTRUCCION
continue
Esta instrucci6n representa una fonna de alterar la secuencia de ejecuci6n dentro de un cicIo iterativo, al encontrarse continue se reinicia la ejecuci6n del cicIo, sin realizar algunas instrucciones posteriores que se encuentren dentro del cicIo. La figura 4.8 muestra esta variante de estructura lograda con continue.
1
.----~-------~-------------~
1
~~ I L~
[comi rwe;I
i
I
instruccion
Figura 4.8: Estructura while con un continue.
Instrucciones
73
4.12 INsTRuccroNEs return y exit Estas instrucciones tambien permiten alterar la secuencia de ejecuci6n del programa. Al encontrarse una instrucci6n return se da por terminada la ejecuci6n de la funci6n actual, se retoma al punto de donde se llam6 la funci6n y se entrega el resultado numerico producto de la ejecuci6n de la funci6n. EI argumento de return es precisamente el valor que se retoma 0 entrega como resultado. La sintaxis de esta instrucci6n es: return expresion;
La instrucci6n exitO permite dar por terminada la ejecuci6n del programa. Tiene un argumento que es ademas el valor que retoma el programa al sistema operativo, exit(O) implica la terminaci6n normal.
4.13 INsTRuccrON goto-etiquetas EI goto es una instrucci6n que cay6 en el desprestigio al entrar en el ambito de la computaci6n la programaci6n estructurada. La gran mayorfa de los programadores expertos recomiendan que no se use esta instrucci6n, en virtud de que un programa bien disefiado y estructurado no debe requerir del uso de ella. Sin embargo, esta disponible y en algunos casos complejos se puede requerir de ella para inventar nuevas estructuras de programaci6n. Los ejemplos 4.4, 5.28 Y 5.29 ilustran el uso de la pareja de recursos de C, representada por la etiqueta y el goto.
4.14 lNsTRuccrONNuLA La instrucci6n nula 0 instrucci6n vacfa, puede ser muy util en algunos casos y consiste unicamente del terminador de instrucci6n (;). Un ejemplo de uso importante de la instrucci6n nula es el siguiente: while ( getcharO != '\n');
Dentro de la expresi6n 16gica de control del while se incluye una funci6n de entrada de caracteres getchar, la cual toma caracteres del buffer de entrada hasta que encuentra un cambio de rengl6n. La instrucci6n del cuerpo del while es una instrucci6n nula.
74
Fundamentos de Programaci6n en Lenguaje C
4.15
EXPRESION CONDICIONAL
La expresion condicional es una altemativa a Ia instruccion if-else, la cual tiene la ventaja de que puede usarse como parte de una expresion. Toma un valor que se puede utilizar como operando de otra operacion aritmetica, relacional, logica o funcional. Por ejemplo, consideremos que A, Bye son variables de punto flotante que tomaron un determinado valor en el transcurso de la ejecucion del programa. Entonces la instruccion de asignacion: C += ((A> B)?A:B)*2 Ie asigna a C el valor mayor entre A y B, multiplicado por dos.
4.16
INSTRUCCION DE CONVERSION (CASTA)
Cuando se realiza una operacion con operandos de diferentes tipos, dichos operandos se convierten a un tipo comnn, de acuerdo a un conjunto de reglas de conversion. Se realiza la conversion en forma automatica, cuando dicha conversion es de un tipo de datos angosto a uno ancho. Es decir, de entero a flotante, de caracter a entero 0 flotante, de flotante a doble precision, etc. La conversion se realiza automaticamente cuando no bay posibilidades de perdida de informaci6.n. De otra manera, la conversion debe realizarse mediante una operacion de casta 0 conversion. EI programa del ejemplo 4.4 ilustra el uso de la openicion de castas con apuntadores que es la aplicacion mas frecuente, el cual permite visualizar en diversos formatos, cualquier dato numerico almacenado en la computadora. Ejemplo 4.4: Programa "uso_casLc". /* Este programa se usa para ilustrar como es posible visualizar cualquier tipo de dato almacenado en memoria principal convirtiendolo por medio de castas (u operadores de conversion de tipo de dato). EI dato que se requiere inspeccionar se introduce interactivamente, a traves de la terminal. Este dato, puede ser un natural 0 entero sin signo, un entero, 0 un real. Luego este mismo dato se puede presentar en diversos formatos: binario, octal, decimal, hexadecimal. De este modo se observa la estructura que utiliza C para almacenar estos tipos de datos.
*/ typedef char *apcar; char buffer[S], *AP_real, *AP_entero, *AP_natural;
Instrucciones
int Entero; float Real; unsigned Natural; mainO { unsigned comando; int aux,au; AP_entero = (apcar) &Entero; AP_real = (apcar) &Real; AP_natural= (apcar) &Natural;
/ / operacion de conversion / / operacion de conversion / / operacion de conversion
INICIO: for (aux = 0; aux=0;au--) printfC%c",«l < B A = B A == B A!= B A II B A && B (!A) && B !A (A II B) && C (A < B) && B
= 0 = 1 =0 = 1 = 0 =0 = 1 = 1 =0 = 1 =1 = 0 =1
Tabla 5.4: Operaciones logicas bit a bit con enteros sin signo. Complemento a 1 -A
Funcion 0
AlB
Funcion Y
A&B
Funcion 0 exc1u- A /\ B SIva
El resultado de esta operacion es el mimero sin signo cuyos bits son los complementos de los bits del numero representado por la variable A. Por ejemplo, si A=O, -A=65535 EI resultado es el numero sin signo cuyos bits son el producto de la disjuncion (funcion 0) de los bits de los numeros representados por las variables A y B. Por ejemplo, si A=3 y B=3, AIB=3 EI resultado es el numero sin signo cuyos bits son el producto de la conjuncion (funcion Y) de los bits de los numeros representados por las variables A y B. Por ejemplo, si A=O y B=65535, A&B=O El resultado de esta operacion es el numero sin signo cuyos bits son el producto de la funcion 0 exc1usiva de los bits de los numeros representados por las variables A y B. Por ejemplo, si A=7 y B=3, A!\B=4
Tipos de Datos
83
La tabla 5.4 muestra las operaciones logicas bit a bit, aplicables a variables enteras sin signo. Estas operaciones son tipicas de los lenguajes ensambladores; sin embargo, el lenguaje C tambien cuenta con ellas, 10 cual 10 hace apropiado para el desarrollo de sistemas en los que es necesario manipular los bits de una variable, en forma independiente. Como en el caso de las tablas ya presentadas, la tabla 5.4 muestra la sintaxis de las operaciones en su segunda columna yen la tercera, la descripcion de los resultados que se obtienen al realizar la operacion. El manejo de operaciones logicas al nivel de bit Ie da a C un gran poder y 10 hace adecuado para trabajar con programas que antes de que apareciera este lenguaje, solo podian desarrollarse en lenguaje ensamblador. Particularmente, la realizacion de sistemas de control digital por computadora, se facilita al contar con las operaciones logicas presentadas en la tabla anterior. Por ejemplo, cada bit puede ser uno de los bits de las entradas de control de un mUltiplexor, selector 0 distribuidor, 0 uno de los bits de uno de los campos de un protocolo, y como estos se pueden dar muchos mas ejemplos. Las operaciones se realizan bit a bit, a manera de compuertas logicas 0 como en las instrucciones logicas tipicas de un lenguaje ensamblador; considerando que las variables y constantes son numeros binarios, esto implica que el bit 0 de uno de los operandos se combina con el bit 0 del otro, el bit 1 con el otro bit 1, Y as! sucesivamente. Para esto, debemos considerar que la longitud de los enteros sin signo es de 16 bits. Vease el ejemplo 5.4, en el eual supusimos que se han dec1arado tres variables: A, B Y C, las cuales se usan posteriormente en las distint as operaciones logicas bit a bit. Notese que se pueden realizar operaciones complejas combinando estas operaciones 10gicas en expresiones, de manera recursiva. Ejemplo 5.4: Operaciones logicas bit a bit con enteros sin signo expresadas en forma binaria y decimal, sean:
A B
=
C
/*** -A -B
Entonces:
-c AlB A&B AAB A& (-B)
= =
0110011001100110 0000000001111111 0000000000000000
=
26214 127 0
***/
1001100110011001 1111111110000000 = 1111111111111111 = o 1 100 1 100 1 111 1 1 1 0000000001100110 0110011000011001 0110011000000000 =
= = =
39321 65408 65535 = 26239 = 102 26137 = 26112
84
Fundamentos de Programacion en Lenguaje C
La tabla 5.5 muestra las operaciones de asignaci6n simple y compuesta que pueden realizarse en C; como es usual, presenta la sintaxis de la operacion y el resultado que se obtiene. La asignacion es una operacion que puede realizarse como parte de una expresion, 0 bien como una instrucci6n. Como se coment6 en el Capitulo 4, asignar un valor a una variable equivale a guardar en la localidad reservada para esa variable, el valor de la expresion colocada del lado derecho del operador de asignacion. Esta operacion es la Hamada asignacion simple en la tabla 5.5. Las asignaciones compuestas implican un cambio en el valor que tiene almacenado el operando del lado izquierdo de la operacion de asignacion, cambio que puede ser un incremento aritmetico 0 geometrico, un ventaneo logico, un corrimiento de los bits, etc., tal como se indica en la tabla 5.5.
Tabla 5.5: Operaciones de asignacion con enteros sin signo Asignacion simple
A=B
Incremento aritmetico
A += B
Decremento aritmetico
A -= B
Incremento geometrico
A *= B
Decremento geometrico
A/=
Modulo
A 0/0= B
Corrimiento a Ia derecha
A»= B
Corrimiento a la izq.
A«= B
Ventana 0 Iogica:
A 1= B
Ventana Y Iogica:
A&= B
Ventana 0 exc1usiva
A A= B
B
Se Ie asigna a A el valor de B. B representa una expresion de tipo entero sin signo Se Ie asigna a A el valor que tenia asignado mas el valor de B. Se Ie asigna a A el valor que tenia asignado, decrementado en el valor de B Se Ie asigna a A el valor que tenia asignado, multiplicado por el valor de B Se Ie asigna a A el cociente del valor que tenia asignado, entre el valor de B Se Ie asigna a A el residuo de la division entera del valor que tenia asignado, entre el valor de B Se Ie asigna a A el valor binario que tenia, recorrido a la derecha B posiciones. Los bits de la izquierda se rellenan con ceros Se Ie asigna a A el valor binario que tenia asignado recorrido a la izquierda B posiciones. Los bits de la derecha se rellenan con ceros Se Ie asigna a A el valor binario que resulta de la operacion logica a nivel de bit
AlB Se Ie asigna a A el valor binario que resulta de la operacion logica a nive! de bit
A&B Se Ie asigna a A el valor binario que resulta de la operacion AA B
Tipos de Datos
85
En el ejemplo 5.5 se ilustran las operaciones de asignacion. Debe observarse que estas estan sujetas a las mismas restricciones que las operaciones aritmeticas y logicas normales; es decir, si se sale de rango la operacion, ocurren errores semanticos que el programador debe detectar, en virtud de que el compilador no puede realizar dicha tarea. El ejemplo 5.5 presenta la operacion y el resultado que se guardaria en el operando de la izquierda. Se considera que los distintos ejemplos presentados son independientes, y que al realizarse la operacion las variables tienen los valores indicados al inicio del ejemplo. Ejemplo 5.5: Ejemplo de operaciones de asignacion compuesta con enteros sin signo. Sean A y B enteros sin signo, y ... A = 25 B = 10
/***** entonces: *****/ A= A += A-= A *= AI: A 0/0= AI= A &= A A: A»= A«=
B B B B B B B
B B B B
implica implica implica implica implica implica implica implica implica implica implica
que que que que que que que que que que que
A A A A A A A A A A A
= = = = = = = = = = =
10 35 15 250 2 5 27 8 19 0 27 648
La tabla 5.6 muestra otros operadores, con los cuales pueden manipularse los bits de una variable entera sin signo, como es el corrimiento de los bits a la derecha y/o a la izquierda, adicionalmente se presenta el incremento y el decremento unitario, el calculo 0 determinacion de la direccion que ocupa una variable (apuntador) y el contenido de una localidad, de la cual se cuenta con la direccion (indireccion). Las operaciones de corrimiento a la derecha, corrimiento a la izquierda, indireccion, apuntador, incremento unitario y decremento unitario son operaciones tipicas de los ensambladores de los procesadores y microprocesadores de las computadoras; sin embargo, de la misma forma que para el caso de las operaciones logicas a nivel de bit, el lenguaje C dispone de estos mecanismos que 10 hac en muy poderoso y adecuado para aplicarse en el desarrollo de tare as que de otra forma solo serian posibles en lenguaje ensamblador.
86
Fundamentos de Programacion en Lenguaje C
Las operaciones de incremento 0 decremento unitario son muy utiles, porque pueden usarse para modificar el valor de una variable, en este caso un entero sin signo, a la vez que integran una expresion aritmetica 0 logica. Cuando se coloca el operador a la derecha de la variable, primero se calcula el valor de la expresion y luego se incrementa 0 decrementa el valor de la variable, y cuando el operador se coloca dellado izquierdo, primero se incrementa 0 decrementa la variable y luego se calcula el valor de la expresion que se desea calcular.
Tabla 5.6: Operaciones tipo lenguaje ensamblador con enteros sin signo. Corrimiento a la derecha
Corrimiento a la izqui erda
Indireccion Apuntador Incremento unitario
Decremento unitario
A »1 El resultado de esta expresion, es el valor bi-
nario que tenia asignado A, recorrido a la derecha una posicion. El primer bit de la izquierda se rellena con cero. Este valor se Ie queda asignado a A. A «1 El resultado de esta expresion, es el valor binario que tenia asignado A, recorrido a la izquierda una posicion. El primer bit de la derecha se rellena con cero. Este valor se Ie queda asignado a A. *A Esta expresion da el valor que se encuentra almacenado en la direccion A. &A El resultado de esta expresion es la direccion de la variable A. ++A Esta expresion da el valor que tenia asignado A, incrementado en uno. Este valor se Ie A++ queda asignado a A. --A Esta expresion da el valor que tenia asignado A-A, decrementado en uno. Este valor se Ie queda asignado a A
Las operaciones de indireccion y de calculo de una direccion permiten manejar de una manera sumamente flexible la memoria principal de la computadora, ya que el programador puede tener acceso de esta manera, a cualquier localidad de memoria; es decir, a manejar apuntadores de manera muy basta y flexible. El operador de indireccion (*) se puede usar de manera recursiva; asi por ejemplo *(*AP)) da el valor almacenado en la localidad de memoria cuya direccion esta almacenada en la variable AP.
Tipos de Datos
87
La tabla 5.6 muestra otras dos operaciones relacionadas con los enteros sin signa que son: la detenninacion de la longitud de memoria ocupada por el tipo de dato y la conversion de tipo de dato u operacion casta.
Tabla 5.7: Operaciones de tipo con enteros sin signo. Longitud del operando
sizeof (A)
Conversion de tipos
(unsigned)OT
Siendo A un entero sin signo, el resultado de esta expresion, es la longitud del entero sin signo que maneja el sistema. EI resultado de esta expresion, es Ia conversion del tipo de la expresion OT a un entero sin signo.
Los operadores sizeof y (unsigned) penniten calcular el numero de bits que ocupa el dato en memoria y convertir un dato a entero sin signo, respectivamente. Esta ultima operacion tambien se denomina en el ambiente de programacion como operacion de casta. A continuacion se comenta mas ampliamente esta operacion.
Conversiones de tipo En la evaluacion de una expresion cualquiera, se realizan las conversiones de tipo en fonna automatica, siguiendo las reglas indicadas en la seccion 4.16. En particular, cuando se combinan en una expresion aritmetica, un entero sin signo y un entero con signo, 0 un 'caracter, el resultado es un entero sin signo. Asimismo, al asignar el valor de un caracter, 0 entero con signo, a una variable declarada como entero sin signo, por medio de cualquiera de las instrucciones de asignacion, la conversion de tipos se hace automaticamente. No as! en el caso de un dato real 0 de punto flotante, en cuyo caso se debe indicar la operacion explicitamente, por medio del operador de "casta" que no es mas que el tipo al que se desea convertir encerrado entre parentesis, como se muestra en la tabla 5.7. Para convertir un entero sin signo a un entero de longitud grande, se llena con ceros los lugares excedentes. Tambien se pueden convertir enteros sin signo a caracteres, y en este caso, se trunca por la izquierda. Para convertir un real a un entero sin signo, se trunca la parte fraccionaria. Y para convertir un entero de longitud grande a uno sin signo, se eliminan los bits de orden superior.
88
Fundamentos de Programaci6n en Lenguaje C
Mediante el programa del ejemplo 5.6 se ilustra el funcionamiento de los distintos operadores aplicables a variables y constantes de tipo unsigned. Ejemplo 5.6: Programa "unsigned.c", ejemplos de operaciones con enteros sin SIgnO. #include unsigned UNSA, UNSB; void DATOSO, ARITMETICASO, RELACIONALESO, LOGICASO, LOGIBITO, ASIGNACIONO, ESPECIALESO, ENSAMBLADORO; mainO
{ char COMAN DO; printf("\t\tPROGRAMA PARA ILUSTRAR EL MANEJO DE NUMEROS SIN SIGNO\n\n"); DATOSO; getcharO; while (1) { getcharO; printf("\tAhora presentamos los resultados de las operaciones\n"); printf("\tque pueden reallzarse can numeros sin signo. \n\n\n"); printf("\t\tEUGE UNA OPCION\n\n\n"); printf("\t\tMETER OTROS DATOS\t\tO\n"); printf("\t\tOPERACIONES ARITMETICAS\t\tA\n"); ll printf(lI\t\tOPERACIONES RELACIONALES\tR\n ); printf("\t\tOPERACIONES LOGICAS\t\tL\n"); printf("\t\tOPERACIONES LOGICAS DE BITS\tB\n"); printf("\t\tOPERACIONES DE ASIGNACION\tS\n"); printf(lI\t\tOPERACIONES DE ENSAMBLADOR\tM\n"); pri ntf(lI\t\tOPERACION ES ESPECIALES\tE\n \n \n"); printf(lI\t\tTERMINAR LA EJECUCION\t\tT\n\n\n"); printf("\tIntroduce el Comando del Tipo de Operaciones que deseas Observar\nll); COMANDO getcharO; switch (COMAN DO) { case 'A':{ARITMETICAS(UNSA,UNSB); break;} case 'B':{LOGIBIT(UNSA,UNSB); break;} case 'E':{ESPECIALESO; break;} case 'L':{LOGlCAS(UNSA,UNSB); break;} case 'M':{ENSAMBLADOR(UNSA); break;} case 'O':{DATOSO;break;} case 'R':{RELACIONALES(UNSA,UNSB); break;} case 'S':{ASIGNACION(UNSA,UNSB); break;}
=
Tipos de Datos
case 'T:exit(O); } } }
void DATOSO { pri ntf("\t\t\t\tDATOS\n \n "); printf("\t\tSe usaran para ilustrar las distintas operaciones con\n"); printf("\t\tenteros sin signo las variables UNSA y UNSB. \n"); printf("\t\tIntroduce a continuacion los valores de UNSA y UNSB. \n"); printf("\n\n\n\t\tUNSA = "); scanf("% u",&UNSA); "); printf("\n\t\tUNSB scanf("%u" ,&UNSB); } void ARITMmCAS(unsigned UNS1, unsigned UNS2) { printf("\n\n\t\tOPERACIONES ARITMETICAS\n\n"); printf("\t\tUNSl + UNS2 = %u\n", UNSl +UNS2); printf("\t\tUNSl - UNS2 = %u\n", UNSI-UNS2); printf("\t\tUNSl * UNS2 = %u\n", UNSl *UNS2); printf("\t\tUNSl / UNS2 = %u\n", UNS1/UNS2); printf("\t\tUNSl \% UNS2 = %d\n", UNSl % UNS2); printf("\t\tOprime \n"); getcharO; } void RELACIONALES(unsigned UNS1, unsigned UNS2) { printf("\t\tOPERACIONES RELACIONALES\n\n"); printf("\t\tUNSl < UNS2 = %u\n", (UNSl UNS2»; printf("\t\tUNSl = UNS2 = %u\n", (UNS1>=UNS2»; printf(lI\t\tUNSl == UNS2 = %u\n", (UNS1==UNS2»; printf("\t\tUNSl != UNS2 = %u\n", (UNS1!=UNS2»; printf("\t\tOprime \n"); getcharO; } void LOGICAS(unsigned UNS1, unsigned UNS2) { printf("\t\tOPERACIONES LOGICAS\n\n"); printf("\t\t!UNSl = %u\n", (!UNS1»; printf("\t\tUNSl II UNS2 = %u\n", (UNSIIIUNS2»; printf("\t\tUNSl && UNS2 = %u\n", (UNS1&&UNS2»; printf("\t\tOprime \n");
89
90
Fundamentos de Programacion en Lengl!aje C
getcharO; } void LOGIBIT(unsigned UNSl, unsigned UNS2) { printf("\t\tOPERACIONES LOGICAS A NIVEL DE BIT\n\n"); printf("\t\tIVUNS1 = %u\n", (IVUNS1»; printf("\t\tUNSl I UNS2= %u\n", (UNSIIUNS2»; printf("\t\tUNSl & UNS2 = %u\n", (UNSl&UNS2»; printf("\t\tUNSl 1\ UNS2 = %u\n", (UNS1I\UNS2»; printf("\t\tOprime \n"); getcharO; } void ESPECIALESO { printf("\t\tOPERACIONES ESPECIALES\n\n"); printf("\t\tsizeof(unsigned) = %d\n", sizeof(unsigned»; printf("\t\t(unsigned)(2.S) = %u\n", (unsigned)(2.S»; printf("\t\tOprime \n"); getcharO; } void ENSAMBLADOR(unsigned UNS1) { unsigned *AP = &UNSl; printf("\t\tOPERACIONES TIPO ENSAMBLADOR\n\n"); printfC'\t\tUNS1> > 1 = %u\n", (UNS1> > 1»; printf("\t\tUNS1«1 = %u\n", (UNS1«1»; printf("\t\t*(&UNS1)= %u\n", *(AP»; printf("\t\t&UNSl = %u\n", &UNS1); printf("\t\t++UNSl = %u\n", ++UNS1); printf("\t\t--UNS1 = %u\n", --UNS1); printf("\t\tOprime \n"); getcharO; }
void ASIGNACION(unsigned UNS1, unsigned UNS2) { unsigned UNSC; printfC'\t\tOPERACIONES DE ASIGNACION\n\n"); printf("\t\tUNSC = UNS1 => UNSC = %u\n", (UNSC=UNS1»; printf("\t\tUNSC += UNSl => UNSC = %u\n", (UNSC+=UNS1»; printfC'\t\tUNSC -= UNS1=> UNSC = %u\n", (UNSC-=UNS1»;
Tipos de Datos
91
printf("\t\tUNSC *= UNSl => UNSC = O/ou\n", (UNSC*=UNSl)); printf("\t\tUNSC /= UNSl => UNSC = O/ou\n", (UNSC/=UNS1)); printf("\t\tUNSC \% == UNS2 ==> UNSC == %u\n", (UNSc%==UNS2)); printf("\t\tUNSC «= UNS2 ==> UNSC == %u\n", (UNSC«=UNS2)); printf("\t\tUNSC »== UNS2 => UNSC == O/ou\nll, (UNSC»==UNS2)); printfC'\t\tUNSC 1= UNSl => UNSC == %u\nll, (UNSq==UNSl)); printfC'\t\tUNSC &= UNSl ==> UNSC == O/ou\nll, (UNSC&=UNSl)); printf(lI\t\tUNSC A= UNSl => UNSC = O/ou\nll, (UNSCA=UNSl)); printf("\t\tOprime \n"); getcharO; }
5.1.4 Enteros con signo
Declaracion Como ya se menciono, C cuenta con tres diferentes longitudes de enteros con signo que son: corta, estandar y grande; las variables de este tipo se declaran de acuerdo a la siguiente sintaxis: especificador_de_aim especificador_de_aim especificador_de_aim
short int int long int
dentificador, identiicador, ... ; identiicador, identiicador, ... ; identiicador, identiicador, ... ;
En la declaracion de enteros de longitud corta 0 grande se puede omitir la palabra clave int. Por otro lado, si un compilador no tiene implantadas las longitudes corta y/o larga, se considera que el entero declarado con alguna de esas longitudes es de longitud estandar. Como en el caso de los enteros sin signo 0 como en cualquier otro caso de' declaracion de variables, se puede hacer la inicializacion de las variables directamente en la declaracion, tal como se muestra en el ejemplo 5.7, en el cual se hace la declaracion e inicializacion de las variables y luego se imprimen sus valores. Obviamente, la impresion de los enteros largos debe hacerse con el formato de enteros largos. Ejemplo 5.7: Programa "entdlong.c", declaracion e enicializacion de variables enteras. mainO { short int
CORTOl = 1, CORT02;
92
Fundamentos de Programacion en Lenguaje C
int ENTEROl = -10, ENTER02; long int LARGOl = 100000, LARG02; printf("CORTOl = 0/od\tCORT02 = %d\n", CORT01,CORT02); printf("ENTEROl = 0/od\tENTER02 = %d\n", ENTER01,ENTER02); printf("LARGOl = 0/0Id\tLARG02 = %ld\n", LARG01,LARG02);
Operaciones aritmeticas sobre enteros Las operaciones aritmeticas que pueden realizarse sobre los enteros con signo (largos, estandar y cortos), son las mismas .que se indican en la tabla 5.1 Y son aplicables a los enteros sin signo; adicionalmente, puede realizarse la operacion unaria: "negativo de". Las diferencias entre las operaciones con enteros de diferente longitud estan precisamente en la longitud de los numeros y por en de en los valores maximos de las variables que pueden emplearse. En el programa del ejemplo 5.11 se muestra una forma de obtener los valores maximos y minimos de los diferentes tipos de enteros, empleando los identificadores de la biblioteca . Estos son: INT_MAX, INT_MIN, LONG_MAX, LONG_MIN, SHRT_MAX Y SHRT_MIN. Si se mezclan enteros de diferente longitud en una expresion aritmetica, el resultado tiene la longitud del entero mas largo que interviene en la misma. En una asignacion se hace la conversion al tipo de dato de la variable a la que se Ie esta asjgnando valor, pero si esta es de menor longitud que la expresion dellado derecho de la asignacion, se genera un error semantico que no es detectado por el compilador, ya que se truncan los octetos mas significativos y solo queda almacenada la informacion que cabe en el area de memoria asignada a la variable. En el ejemplo 5.8 se ilustran las operaciones aritmeticas con enteros. En la operacion modulo 0 residuo (A % B), debe tomarse en cuenta que dicho residuo conserva el signo del dividendo. Ejemplo 5.8: Operaciones aritmeticas con enteros.
1* Sean A y B enteros con signa declarados como enteros estandar, y A = 17 Y B = -13; entonces: */
-A
= -17
A+B A-B A*B AlB
=4 = 30 = -221 = -1 =4
A% B
Tipos de Datos
93
Operaciones relacionales y logicas sobre enteros con signa Las operaciones relacionales de la tabla 5.2 tambien se aplican en su totalidad a los numeros enteros con signo de cualquiera de las tres longitudes. Unicamente hay que tomar en cuenta que un numero es menor entre mas negativo es. De igual manera se .aplican las operaciones logicas de la tabla 5.3 a los enteros con signo, con las mismas reglas de semantica que en el caso de los enteros sin signo; es decir, una cantidad no cero se considera que tiene el valor logico CIERTO y la que tiene el valor cero, toma el valor logico FALSO. El ejemplo 5.9 a continuacion, ilustra las operaciones relacionales y logicas realizadas con enteros con signo. Obviamente, por 10 que se comento en el parrafo anterior, en estos tipos de operaciones pueden mezc1arse operandos enteros de diferente tipo sin consecuencias en errores sintacticos 0 semanticos, siempre y cuando se tengan en cuenta los efectos de los truncamientos que se producen. Ejemplo 5.9: Operaciones logicas y relacionales con enteros. /* Sean A y B enteros con signo y A= 0, B = -10 Y C = 10; entonces: */ A< B A> B A = B A == B A!= B A II B A&&B !A l(A> B) (A II B) && C (A < B) && B
= = = = = = = =
0 1 0 1 0 1 1 0 1 0 1 0
Operaciones logicas a nivel de bit y operaciones tipo lenguaje ensamblador, sobre enteros con signo Las operaciones indicadas en las tabla 5.4. y 5.6 tambien se aplican a los mimeros enteros con signo, desde luego, en el contexto de este tipo de numeros. A continuacion presentamos el ejemplo 5.10, en el que se ilustran las operaciones indicadas en las tablas referidas.
94
Fundamentos de Programacion en Lenguaje C
Ejemplo 5.10: Operaciones logicas a nivel de bit con enteros. Expresadas en forma binaria y decimal, sean:
A B
=
C
=
0110011001100110 111 1 1 1 1 1 1 000 0 001 0000000000000000
=
26214 -127 0
/*** Entonces: *** / -A -B -C AlB A&B AAB A & (-B) A»1 A«1 B++ B--
= = = = = = =
1001100110011001 0000000001111110 1 1 1 1 1 1 1 1 1 111 1 111 1 1 1 1 1 1 1 1 1 1 100 1 1 1 0110011000000000 100 1 100 1 1 1 100 1 1 1 0000000001100110 001 100 1 100 1 100 1 1 1100110011001100 111 1 1 1 1 1 1 0 0 0 0 0 1 0 1111111110000000
= = = = = = = = = =
-26215 126 -1 -25 26112 -26137 102 13107 -13108 -126 -128
5.l.5 Funciones estandar de enteros con signo En la biblioteca se cuenta con tres importantes funciones que realizan acciones relacionadas con enteros, estas son: la funcion atoi, que convierte una cadena ASCII que indica un numero entero, al correspondiente valor entero, la funcion rand 9 que da un entero pseudo-aleatorio y la funcion abs 9 que da el valor absoluto de su argumento entero. El uso de estas tres funciones de biblioteca se ilustra por medio de la funcion FUNCIONES, del programa "enteros.c" del ejemplo 5.11; este pennite probar las operaciones con enteros y entender 10 que sucede en situaciones criticas. Es recomendable correr el programa y probar sus resultados con diferentes datos. El programa esta construido de manera modular; inicialmente presenta un menu con los distintos grupos de operaciones, de los cuales se elige uno con la letra indicada en el menu y se obtienen los resultados de las operaciones del grupo. Ejemplo 5.11: Programa "enteros.c", operaciones y funciones con enteros.
#include #include #include int INTA, INTB;
Tipos de Datos
95
void DATOSO, ARITMmCASO, RELACIONALESO, LOGICASO, LOGIBITO, ASIGNACIONO, ESPECIALESO, ENSAMBLADORO, VMAXIMOSO, FUNCIONESO; mainO
{ char COMAN DO; printf("\t\t\tPROGRAMA PARA ILUSTRAR EL MANEJO DE NUMEROS ENTEROS\nll); DATOSO; getcharO; while (1) { getcharO; ll printf("\tAhora presentamos los resultados de las operaciones\n ); printf(,,\t que pueden realizarse con numeros enteros.\n\n\n"); ll printf(lI\t\tEUGE UNA OPCION\n\n\n ) ; printf("\t\tMETER OTROS DATOS\t\tO\n"); printf("\t\tOPERACIONES ARITMmCAS\t\tA\n"); printfC'\t\tOPERACIONES RELACIONALES\tR\n"); printf("\t\tOPERACIONES LOGICAS\t\tL\nll); printf("\t\tOPERACIONES LOGICAS DE BITS\tB\nll); printf("\t\tOPERACIONES DE ASIGNACION\tS\n"); printf("\t\tOPERACIONES DE ENSAMBLADOR\tM\n"); printf("\t\tOPERACIONES ESPECIALES\t\tE\n"); ll printf("\t\tVALORES MAXIMOS DE LOS ENTEROS\tV\n ); printf("\t\tFUNCIONES QUE MANEJAN ENTEROS\tF\n\n\n"); printf("\t\tTERMINAR LA EJECUCION\t\tT\n\n\n"); printf("\tIntroduce el Comando del Tipo de Operaciones que deseas Observar\nll); COMAN DO = getcharO; switch (COMANDO)
{ case'A':{ARITMmCAS(INTA,INTB); break;} case 'B':{LOGIBIT(INTA,INTB); break;} case 'E':{ESPECIALESO; break;} case 'F':{FUNCIONES(INTA,INTB); break;} case 'L':{LOGICAS(INTA,INTB); break;} case 'M':{ENSAMBLADOR(INTA); break;} case 'O':{DATOSO;break;} case 'R':{RELACIONALES(INTA,INTB); break;} case 'S':{ASIGNACION(INTA,INTB); break;} case 'V':{VMAXIMOSO; break;} case'T:exit(O);
} } } void DATOSO
96
Fundamentos de Programacion en Lenguaje C
{
printf(l\t\t\t\tDATOS\n\n"); printf("\t\tSe usaran para ilustrar las distintas operaciones con\n"); printf("\t\t enteros sin signo las variables INTA e INTB. \n"); printf(,,\t\tIntroduce a continuaci6n los valores de INTA y INTB.\n"); printf("\n\n\n\t\tINTA = "); scanf("%d" ,&INTA); printf("\n\t\tINTB = "); scanf("%d",&INTB); } void ARITMETICAS(int INT1, int INT2) { printf("\n\n\t\tOPERACIONES ARITMETICAS\n\n"); printf("\t\tINTl + INT2 = %d\n", INT1+INT2); printf("\t\tINTl - INTI = %d\n", INTl-INT2); printf("\t\tINTl * INT2 = %d\n", INTl *INT2); printf("\t\tINTl / INT2 = %d\n", INTl/INT2); printf("\t\tINTl \°/0 INT2 = O/od\n", INTI % INT2); printf("\t\tOprime \n"); getcharO; } void RELACIONALES(int INTl, int INT2) { printf("\t\tOPERACIONES RELACIONALES\n\n"); printf("\t\tlNTl < INT2 = °/od\n", (INTlINT2»; printf("\t\tlNTl = INT2 = %d\n", (INTl>=INT2»; printf("\t\tlNTI == INT2 = O/od\n", (INTI==INT2»; printf("\t\tINTl != INT2 = %d\n\n", (INT1!=INT2»; printf("\t\tOprime \n"); getcharO; } void LOGICAS(int INTl, int INT2) { printf("\t\tOPERACIONES LOGICAS\n\n"); printf("\t\t!INTl = %d\n", (lINTI»; printf("\t\tINTl II INT2 = %d\n", (INTlIIINT2»; printf("\t\tINTI && INT2 = %d\n", (INTI&&INT2»; printf("\t\tOprime \n"); getcharO; } void LOGIBIT(int INTl, int INT2) { printf("\t\tOPERACIONES LOGICAS A NIVEL DE BIT\n\n"); printf("\t\tINTI = %o\n", INTl);
Tipos de Datos
printfC'\t\tlNT2 = %o\n", INT2); printf("\t\trvINT1 = %o\n", (rvINT1)); printf("\t\tINT1 1 INT2 = %o\n", (INT1IINT2)); printf("\t\tINT1 & INT2 = %o\n", (INT1&INT2)); printf("\t\tINT1 A INT2 = %o\n", (INT1 AINT2)); printf("\tLos resultados estan en numeraci6n octal\n"); printf("\t\tOprime \n"); getcharO; } void ESPECIALESO { printfC'\t\tOPERACIONES ESPECIALES\n \n"); printf("\t\tsizeof(int) = %d\n", sizeof(int)); printf("\t\tsizeof(short int) = %d\n", sizeof(short int)); printfC'\t\tsizeof(long int) = %d\n", sizeof(long int)); printf("\t\t(int)( -2.5) = %d\n", (int)( -2.5)); printf("\t\tOprime \n"); getchar(); } void ENSAMBLADOR(int INT1) { int *AP = &INT1; printfC'\t\tOPERACIONES TIPO ENSAMBLADOR\n\n"); printf("\t\tINT1»1 = %d\n", (INT1»1)); printf("\t\tINTI < < 1 = %d\n", (INT1 < < 1)); printf("\t\t*(&INT1)= %d\n", *(AP)); printfC'\t\t&INT1 = %x\n", &INT1); printf("\t\t++INTl = %d\n", ++INTl); printf("\t\t--INTl = %d\n", --INT1); printf("\t\tOprime \n"); getcharO; } void ASIGNACION(int INTi, int INT2) { int INTC = 0; printf("\t\tOPERACIONES DE ASIGNACION\n\n"); printf("\t\tINTC = INT1 => INTC = %d\n", (INTC=INT1)); printf("\t\tINTC += INT1 => INTC = %d\n", (INTC+=INT1)); printf("\t\tINTC -= INTl ==> INTC == %d\n", (INTC-=INT1)); printfC'\t\tINTC *= INT1 => INTC == %d\n", (INTC*=INT1)); printf("\t\tINTC /= INT1 ==> INTC = %d\n", (INTC/=INT1)); printfC'\t\tINTC \%= INT2 => INTC = %d\n", (INTc%==INT2)); printf("\t\t INTC = %0 O\n", (INTC =255)); printf("\t\tINTC «=INT2 => INTC = %0 O\n", (INTC«=INT2)); printf("\t\tlNTC »=INT2 => INTC = 0/0 0 O\n", (INTC»=INT2)); printf("\t\tINTC 1= INT1 => INTC == %0 O\n", (INTCI=INTl)); printf("\t\tINTC &= INTI => INTC == %0 O\n", (INTC&=INT1)); printf("\t\tlNTC A= INT1 => INTC = %0 O\n ll , (INTC A ==INT1));
97
98
Fundamentos de Programacion en Lenguaje C
printf(,,\tLos resultados maracados con una 0 al final estan en numeraci6n octal\n"); printf("\t\tOprime \n"); getcharO;
} void VMAXIMOSO { printf("\t\tVALORES MAXIMOS DE LOS ENTEROS\n\n"); printf(,,\t\tshort MINIMO = %d\n", SHRT_MIN); printf("\t\tshort MAXIMO = %d\n", SHRT_MAX); printf("\t\tint MINIMO = %d\n", INT_MIN); printf("\t\tint MAXIMO = %d\n", INT_MAX); printf("\t\tlong MINIMO = %ld\n", LONG_MIN); printf("\t\tlong MAXIMO = %ld\n", LONG_MAX); printf("\t\tOprime \n"); getcharO; } void FUNCIONES(int INT1, int INT2) { printf("\t\tFUNCIONES QUE MANEJAN ENTEROS\n\n"); printf("\tCONVERSION CADENA A ENTERO CON LA FUNCION atoi( const char *s)\n"); printf("\t\t\tatoi(\11996\") = %d\n", atoi("1996")); printf("\tNUMERO PSEUDOALEATORIO CON LA FUNCION randO\n"); printf("\t\t\trandO = %d\n", randO); printf("\tVALOR ABSOLUTO DE UN ENTERO CON LA FUNCION abs(int n)\n"); printf("\t\t\tabs(INT1) = %d\n", abs(INT1)); printf("\t\t\tabs(INT2) = %d\n", abs(INT2)); printf("\t\tOprime \n"); getcharO; }
5.1.6 Reglas de precedencia y asociatividad La precedencia y la asociatividad son conceptos muy importantes que se aplican en el calculo de las expresiones aritmeticas, logicas y relacionales. La tabla 5.8 muestra las reglas de precedencia y asociatividad de los operadores en ellenguaje C. En esta tabla, los operadores estan presentados en orden de precedencia, por filas. Las primeras filas tienen mas precedencia que las ultimas. Los operadores que aparecen en la misma fila tienen igual precedencia.
Tipos de Datos
99
Las reglas de precedencia y asociatividad de la tabla 5.8 se aplican a las operaciones con enteros, pero igualmente se aplican a los demas tipos de datos a los cuales se aplican las operaciones correspondientes. Dichas reglas implican, por ejemplo, que en una expresi6n aritmetica, primero se realizan las multiplicaciones y luego las sumas y restas. Igualmente, primero se calculan las funciones y luego se realizan los productos y divisiones.
Tabla 5.8: Precedencia y asociatividad de los operadores . . Operadores
C) [ ] -> ++ -!
-
* /
Asociatividad
*
& CTIPO) sizeof
0/0
+ » « < >= !=
-& /\
I &&
II ?:
= += -= *= /= 0/0= &= /\= 1= «= »= I
5.2
izquierda a derecha derecha a izquierda izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha izquierda a derecha derecha a izquierda derecha a izquierda izquierda a derecha
CARACTERES
5.2.1 Introducci6n Los caracteres son los simbolos de escritura unitarios que utiliza el ser humano para formar sus lenguajes. Hasta antes del advenimiento de los modos grcificos, las entradas y salidas a las computadoras se realizaban casi en su totalidad por medio de caracteres. Aun en la actualidad la entrada/salida de caracteres es uno de los medios de comunicacion con la computadora mas utilizados. Por ejemplo, la entrada por teclado se realiza por medio de caracteres ASCII y la salida a la mayoria de las impresoras de golpe tambien es por medio de caracteres. Asimismo, la salida a la pantalla de video, en sistemas operativos como MS-DOS y UNIX, es por medio de caracteres ASCII.
100
Fundamentos de Program acion en Lenguaje C
Los caracteres se han codificado en 5, 6, 7 u 8 bits. El C6digo Baudot, que fue uno de los primeros c6digos de caracteres, empleaba 5 bits. El c6digo ASCII, introducido por la ANSI, primeramente utiliz6 7 caracteres, luego introdujo un conjunto de caracteres gnificos, ademas de los caracteres de escritura y emple6 c6digos de 8 bits. Ellenguaje C soporta el tipo caracter y Ie asocia las caracteristicas numericas de los enteros sin signo que obedecen a las leyes de la aritmetica binaria, con la salvedad de que su longitud 0 espacio de memoria es de un octeto 0 byte. A continuaci6n se describen las caracteristicas de este tipo de datos, as! como de las funciones y operadores que son aplicables a ellos. Ejemplo 5.12: Programa "asciis.c", que da una lista de los caracteres ASCII imprimibles, con c6digo numerico mayor a 32 (40 en octal) y menor que 127 (177 en octal). #include mainO { char c='\40' ,CR=O; printf("USTA DE CARACTERES Y SUS VALORES ASCII\n"); while (c= 4){printf("\n"); CR=O;}} return 0;
}
La tabla 5.9 a continuaci6n, muestra la salida de caracteres ASCII y sus valores numeric os que entrega el programa del ejemplo 5.12. Tabla 5.9: Lista de caracteres imprimibles y sus valores ASCII. ! ( /
6 =
0
K R Y g n u
I
33 40 47 54 61 68 75 82 89 96 103 110 117 124
" )
0 7 >
E L S Z
a h 0
v }
34 41 48 55 62 69 76 83 90 97 104 111 118 125
#
*
1 8 ?
F M T [ b i P w
-
35 42 49 56 63 70 77 84 91 98 105 112 119 126
$
+ 2 9 @ G N
U \
c j q x ......
36 43 50 57 64 71 78 85 92 99 106 113 120 127
%
, 3 :
A
H 0 V
] d k
r y
37 44 51 58 65 72 79 86 93 100 107 114 121
&
4 ,
B I
P W A
e
1 s
z
38 45 52 59 66 73 80 87 94 101 108 115 122
,
5 <
C J
Q X
f m
t {
39 46 53 60 67 74 81 88 95 102 109 116 123
Tipos de Datos
101
5.2.2 DECLARACION La dec1aracion de una variable tipo canicter se realiza de la siguiente fonna: especificador_de_alm inicializador, ... ;
char identificador = inicializador, identificador =
Notese que bajo una misma dec1aracion pueden inc1uirse varias variables del tipo char y que es posible inicializar todas las variables al hacer la dec1aracion, como se comento en los casos de las dec1araciones de enteros; 0 tambien se puede omitir la inicializacion de algunas 0 de todas las variables dec1aradas. El especificador de tipo de almacenamiento especificador_de_alm, es el ya explicado en la Secc.3.2.2; en este caso las variables pueden ser automaticas, estaticas, extemas 0 registro y tambien se pueden declarar sinonimos del tipo char, mediante typedef.
5.2.3 Conversion caracteres'a enteros Los caracteres se pueden manejar como enteros de 8 bits que representan su codigo ASCII. De manera que la conversion de enteros a caractcres y viceversa es automatica. No obstante, al convertir un entero a caracter se truncan los 8 bits mas significativos del entero. El programa del ejemplo 5.13 ilustra estas conversiones, se imprime tanto el caracter A como el numero 1089 en notacion octal para que se observe que los 8 bits menos significativos de ambos son iguales, de manera que al truncar a 8 bits el numero 1089 da como resultado el caracter A. Las impresiones en pantalla resultado de la corrida, se presentan al final del programa. Al ejecutar una operacion aritmetica en la que intervienen enteros y caracteres, el resultado es un entero.Ejemplo 5.13: Programa "charconv .c", ilustra el proceso de conversion de caracteres a enteros y visceversa. mainO { char C ='A'; int ENT = 1089; printf("ASCII DE A = %d\n", C); printf("A EN OCTAL = %o\n", C); printf("1089 EN OCTAL = %o\n", ENT); printf("(char) 1089 = %c\n", C = (char)ENT); return 0; }
102
Fundamentos de Programacion en Lenguaje C
/* IMPRESIONES RESULTADO DE LA CORRIDA ASCII DE A A EN OCTAL 1089 EN OCTAL (char) 1089
= = = =
65 101 2101 A
*/
5.2.4 Operaciones con caracteres De hecho, todas las operaciones que son posibles con enteros sin signo son posibles con los caracteres. Esto Ie da un enonne poder de manejo de caracteres al lenguaje C, ya que pueden hacerse conversiones y manipulaciones con caracteres que no estan disponibles en otros lenguajes. Por ejemplo, para convertir de mayusculas a minusculas basta restar 32, 0 pasar el caracter por una compuerta & con 95. El ejemplo 5.14 ilustra estas conversiones y divers as operaciones en las que intervienen caracteres. Debe recalcarse por otro lado, que los caracteres confonnan un conjunto ordenado y por 10 tanto pueden aplicarse a ellos las operaciones relacionales basicas; es decir, se pueden comparar para detenninar si son iguales, uno es mayor que el otro, etcetera. Ejemplo 5.14: Operaciones con caracteres. Sean A y B caracteres, y A='A' Y B = 'a'; entonces: A +.2 B-2 A*2 A/2 A % 255 !(A < B) A< B A> B A = B A == B A!= B A II B A&&B !A
= = = = = = = = = = = = = =
'c'
' ,
'e' ', 'A' 0 1 1 1 0 0 1 1 1 0
A 132 B & 95 AAB A« 1 B» 1 A++ A-B++ B-sizeof( char) 512 + A A+B A - B A I B A& B
= = = = =
'a' 'A' 32
= = = = = =
'@'
'e' '-'
'B'
= =
'b'
'" 1 577 162 32 'a' 'A'
= =
'6'
5.2.5 Funciones estandar que operan con caracteres Algunas de las funciones estandar mas importantes con las que se manejan caracteres, son las mostradas en la tabla 5.10, las cuales se encuentran en la bi-
Tipos de Datos
103
blioteca , por 10 que debe incluirse esta biblioteca en los programas que utilicen dichas funciones. N6tese que un canicter es el argumento de todas estas funciones. Tabla 5.10: Biblioteca isalnum(c) isalpha(c) iscntrl(c) isdigit(c) isgraph(c) islower(c) isprint(c) ispunct(c) isspace(c) isupper(c) isxdigit( c) tolower(c) toupper(c)
Toma el valor verdadero (1), si el argumento es letra 0 mimero Toma el valor verdadero (1), si el argumento es letra Toma el valor verdadero (1), si el argumento es canicter de control Toma el valor verdadero (1), si el argumento es numero Toma el valor verdadero (1), si el argumento es imprimible, excepto espacio Toma el valor verdadero (1), si el argumento es letra minuscula Toma el valor verdadero (1), si el argumento es imprimible Toma el valor verdadero (1), si el argumento es imprimible, excepto espacio, letra 0 numero Toma el valor verdadero (1), si el argumento es espacio, avance de linea, nueva linea, retorno de carro, tabulador, tabulador vertical Toma el valor verdadero {I), si el argumento es letra mayliscula Toma el valor verdadero (1), si el argumento es dig ito hexadecimal Convierte a minuscula, regresa la minuscula Convierte a mayliscula, regresa la mayliscula
La tabla 5.11 muestra un conjunto de funciones de entrada/salida que manejan caracteres. Por medio de estas funciones puede tenerse comunicaci6n interactiva con el usuario, metiendo y sacando caracteres. EI uso de estas funciones se ilustra mas ampliamente en el Capitulo 7. Estas funciones se encuentran disponibles a traves de la biblioteca stdio.h Tabla 5.11: Biblioteca getcharO getchO getc(buffer) putchar(c) putc(c,buffer) ungetc( c,buffer)
Mete un canicter de la entrada estandar, debe usarse retorno de carro para indicar que ya esta tecleado el caracter Mete un caracter de la entrada estandar, no se necesita usar el retorno de carro como en el caso anterior Retorna el siguiente caracter del buffer del archivo Escribe el caracter c en la salida estandar Escribe el caracter c en el buffer del archivo Regresa el caracter, de nuevo al buffer del archivo
104
5.3
Fundamentos de Programacion en Lenguaje C
NUMEROS DE PUNTO FLOTANTE
5.3.1 Introducci6n Originalmente, los procesadores trabajaban a nivel de lenguaje de maquina con mimeros enteros. Para trabajar con numeros reales 0 de punto flotante, hubo necesidad de crear un codigo numerico especial, asi como todos los programas para ejecutar las distintas operaciones aritmeticas y funciones reales que pueden realizarse con este tipo de numeros. Posteriormente las computadoras inc1uyeron un hardware especial para realizar las operaciones de punto flotante u operaciones con numeros reales, conocido como el procesador de punto flotante. Esto se hizo porque las operaciones de punto flotante eran las que los procesadores ejecutaban mas lentamente y los procesadores de punto flotante, como los de la familia 80x87, ejecutan dichas operaciones directamente y mas rapido. Hoy, las maquinas Pentium han incorporado el co-procesador en el mismo chip. Existe un estandar que es el IEEE 754-85, que especifica eI codigo para representar numeros de punto flotante en una computadora digital. Este estandar debe ser respetado tanto en el disefio de procesadores de punto flotante como de compiladores y herramientas diversas de hardware y software. El estandar 75485 define el formato basico de los numeros de punto fiotante, las operaciones aritmeticas y de redondeo que deben realizar los procesadores y los compiladores, adem as de las distintas situaciones de excepcion,o de error, como es la division entre cero, el desbordamiento, etcetera. Como puede apreciarse en la figura 5.1, los fonnatos de los numeros de punto flotante simples y los de doble precision tienen tres eiementos que son: signo, exponente y fraccion. Segun se aprecia en la figura referida, la longitud del signo es de 1 bit en los dos esquemas, la del exponente es de 8 bits en el caso de los numeros de punto flotante simples (float en C) y de 11 en el caso de los de doble precision (double en C), y final mente la de la fraccion es de 23 bits en el caso de los mimeros de punto fiotante simples y de 52, en el caso de los de doble precision. Es evidente que el codigo numerico estandarizado para representar numeros reales tiene la estructura general de los numeros con notacion cientifica, excepto que no se contempla una parte entera, sino solamente la parte fraccionaria. De esta manera pueden almacenarse rangos de numeros sumamente amplios y con una gran precision. En la practica, los valores maximos que maneja el procesador 0 el compilador dependen de la forma en que se implemento el sistema. Obviamente, los numeros reales constituyen un tipo de datos fundamental en la ingenieria y en los sistemas computacionales, practicamente todos los lenguajes de programacion soportan el manejo de este tipo de numeros, ya que con
Tipos de Datos
105
ellos se trabajan todo tipo de problemas y aplicaciones. A continuacion se explican los distintos aspectos del tratamiento computacional de los numeros reales en el lenguaje C, las dec1araciones, las operaciones que pueden realizarse con ellos, las funciones de biblioteca que tiene disponibles para trabajar con este tipo de datos, etcetera.
bMs
bms bMs
[oms
52 bMs
bms bMs bMs
bi~
bms
bit man os signlificOltivo
Mas
bms
significa~i"o
Figura 5.1: Formato de los numeros de punto flotante.
5.3.2 Declaraci6n La dec1aracion de numeros de punto flotante y de uoble precision, en lenguaje C es como sigue: especificador_de_aim float identificador= inicializador, identificador=inicializador, ... ; especificador_de_a Im dou ble identificador= in icia Iizador, identificador= in icia Iizador, ... ;
Debe tomarse en cuenta que es opcionalla inicializacion de las variables, y en este caso el especificador de almacenamiento puede ser extern, static, auto 0 typedef.
La implantacion de una variable de tipo float en un registro no es posible en la nlayoria de los ambientes de programacion, sin embargo, si esto se especifica, normalmente el compilador solo ignora la solicitud. Obviamente, cuando se hace una definicion de tipo con typedef no se inicializa el correspondiente identificador. EI uso de los otros tres especificadores de almacenamiento determina el campo de aplicacion de la variable, como ya se ha venido explicando con anterioridad.
106
Fundamentos de Programaci6n en Lengljaje C
5.3.3 Conversion punto flotante-entero Tal como en los casos de los enteros y los caracteres, se pueden hacer conversiones de otros tipos de dato a numeros de punto flotante 0 de doble precision, mediante la operacion de casta, en la forma ilustrada en el ejemplo 5.15. Ejemplo 5.15: Conversiones de tipo a punto flotante. Supongamos que REAL es una variable dec1arada como tipo float, ENTERO una variable entera y DOBLEP una de doble precision. As!, podemos hacer las siguientes conversiones: REAL DOBLEP
=
(float)ENTERO; (double) REAL;
En general, cuando una operacion se realiza con operandos de diferente tipo, estos se convierten automaticamente, siguiendo un conjunto reducido de reglas. Las conversiones que podrian implicar perdidas de informacion por truncamiento, como es la de un float a entero 0 a caracter, pueden producir una advertencia del compilador ("warning"). Las reglas de conversion que se aplican mas frecuentemente durante la realizacion de una operacion aritmetica en la que intervienen numeros enteros y de punto flotante, son las siguientes: a) b)
Si cualquiera de los operandos es double, el otro se convierte a double. Si uno de los operandos es float y el otro es de longitud igual 0 menor, se convierte el otro operando a float.
No esta permitido el uso de un numero de punto flotante como subindice.
5.3.4 Operaciones con numeros de punto flotante Las operaciones aritmeticas, relacionales y logicas, que ya fueron descritas en su aplicacion a enteros y caracteres, se aplican tambien a los numeros de punto flotante. Las operaciones tipo ensamblador, logicas bit a bit y corrimientos son ilegales en el caso de los numeros de punta flotante. Los incrementos y decrementos igualmente pueden aplicarse. En el ejemplo 5.16 se ilustran las operaciones con numeros de punto flotante, estas operaciones se realizaron con el programa "reales.c" del ejemplo 5.17. Las operaciones marcadas como ilegales en los ejemplos 5.16 y 5.l7, son sefialadas como ilegales por el compilador del lenguaje C.
Tipos de Datos
Ejemplo 5.16: Operaeiones tonees:
d~
punto flotante. Sean A = 255.5 Y B = - 556, en-
1* Operaciones Aritmeticas *1 A+ B = -300.5 A*B = -142058.0 A % 255 es ilegal -B = 556.0
1* Operaciones A = B A!= B
=1 =1
A&&B
=1
=
1
0
Operaciones de Logicas Binaria */ A&B es ilegal A A B es ilegal AlB es ilegal - A es ilegal B »1 es ilegal A «1 es ilegal
1*
1* Incrementos y ++A --A
= =
Decrementos 256.5 255.5
*/ ++B --B
= =
-555.0 -556.0
=
8
1* Operaciones Diversas */ sizeof(float) =
4
sizeof(double)
Ejemplo 5.17: Programa "reales.e", ilustra las operaeiones con numeros de punto flotante. mainO { float A = 255.5, B = -556; printf("A + B = 0/06.1f\t\t", A + B); printf("A * B = 0/06.1f\t", A * B); printf(IIA % 255 es ilegal\t"); printf("A < B = %d\t\t",A < B); printf("A B); printf("A >= B = %d\n",A >= B); printf("A != B = %d\n",A!= B); printf("A && B = %d\n",A && B); printf("- A = 0/o6.1f\n", -A); printf("A A B es ilegal\n");
108
Fundamentos de Programacion en Lenguaje C
printf("A < < 1 es ilegal\t\t"); printfC'B > > 1 es ilegal\n"); printf("++A == %6.1f\t\t",++A); printf("--A == %6.1f\n",--A); printf("--B == %6.1f\n",--8); printf("++B == %6.1f\t\t",++B); printf("AIB es ilegal\t\t"); printf("A&8 es ilegal\n"); printf("sizeof(f1oat) == %d\n", sizeof(float)); printf("sizeof( double)= %d\n", sizeof( double)); return 0; }
5.3.5 Reglas de precedencia En las operaciones con numeros reales 0 de punto flotante simples 0 de doble precision se aplican las mismas reglas de precedencia indicadas en la tabla 5.8.
5.3.6 Funciones estandar con numeros de punto flotante En la biblioteca se dispone de las funciones matematicas basicas, como son las funciones trigonometricas, logaritmicas, exponenciales, hiperbolicas, etc. Estas funciones tienen como parametros, numeros de punto flotante de doble precision y retoman numeros de doble precision; no obstante, si se les pasa como argumento un numero de tipo float, normal mente el compilador no indica error. .En la tabla 5.12 se qescriben brevemente las funciones de la biblioteca . Algo que es relevante y se debe remarcar es que ellenguaje C no cuenta con un operador de exponenciacion y que esta operacion se realiza por medio de la funcion pow(X,Z), donde X es la base y Z el exponente. Tambien debe remarcarse que por medio de estas funciones puede realizarse cualquier calculo algebraico 0 trigonometrico y se pueden programar formulas con funciones hiperbolicas, directamente. EI programa "fcreales.c" del ejemplo 5.18, ilustra el manejo de las funciones matematicas de la biblioteca , de manera simple. Recuerdese que la biblioteca se incluye mediante la directiva #include. En el programa, por sencillez se declaran e inicializan dentro de main las variables que se utilizanin como parametros de las funciones. Se puede analizar la operacion de las funciones y los errotes que se producen cambiando los valores de inicializacion de las variables, recompilando y ejecutando nuevamente el programa. El valor 0 retomado por la funcion main solo indica la terminacion normal del programa. En el ejemplo 5.19 se muestran los resultados que el programa del ejemplo 5.18 present:l en la pantalla del monitor. En el programa del ejemplo 5.18, A es un angulo dado en radianes, X un numero cuyo modulo debe ser menor que la unidad, B debe ser un numero real
Tipos de Datos
109
mayor que cero, Y y Z son numeros reales cualquiera y N debe ser un entero. Si el m6dulo de X es mayor que uno, obviamente se producini un error al calcular el arco sene 0 el arco coseno. De igual manera si B es negativo se producini un error al calcular ellogaritmo natural 0 de base diez.
Tabla 5.12: Biblioteca sin(A) cos(A) tan(A) asin(X) acos(X) atan(Y) sinh(B) cosh(B) tanh(B) exp(B)
log(C) log10(C) pow(X,Z) sqrt(B)
ceil(Z) floor(Z) fabs(B) Idexp(8,N) fmod(BrA)
Seno de A, A esta en radianes Coseno de A, A esta en radianes Tangente de A, A esta en radianes Arco sene de X, el resultado esta en el range [-1[/2, 1[12], X debe estar en el ran go [-1, 1] Arco coseno de X, el resultado esta en el rango [0, 1[], X debe estar en el rango [-1, 1] Arco tangente de Y, el resultado esta en el rango [-1[/2, 1[12] Seno hiperb6lico de B Coseno hiperb6lico de B Tangente hiperb6lica de B Funci6n exponencial, tf3 Logaritmo natural de C, In(C), C>O Logaritmo de base 10 de C, log/O(C), C>O Potencia Z de X, X Z, Ocurre error de dominio si X=O y Z= 'a'»11 (SIG_CAR == 'x') II (SIG_CAR >= 'X'» return 1; else return 0; }
PAREN_C() { if (SIG_CAR == I)') return 1; else return 0; }
PAREN_AO { if (SIG_CAR == '(') return 1; else return 0; }
COMAO {
if (SIG_CAR == ',') return 1; else return 0; }
GATOO {
if (SIG_CAR == '#') return 1; else return 0; } COLONO {
if (SIG_CAR
== I:') return 1;
Funciones
161
else return 0;
} SEMICOLO
{
== ';') return 1;
if (SIG_CAR else return 0;
} DIAGONALO
{
== 'I') return 1;
if (SIG_CAR else return 0;
} ASTERISO
{
== '*') return 1;
if (SIG_CAR else return 0;
} ESPACIOSO
{ if «SIG_CAR else return 0;
== ' ')//CSIG_CAR == '\n')//CSIG_CAR == '\t')) return 1;
} OTROO { return 1; }
/*
RUTINA DE BUSQUEDA EN LA TABLA DE PALABRAS RESERVADAS Esta rutina se realiza mediante el algoritmo de busqueda dicotomica, en la tabla de palabras reservadas. *1
int RESERVS(CADEN) char *CADEN;
{ int int int int int
AUX; COD Ox101; 1* Inicializacion con el codigo de identificador BAJO = 0; MEDIO; ALTO = NO_PAL_RES;
while (BAJO <
{
=
= ALTO)
MEDIO BAJO + (ALTO - BAJO)/2; if «AU X strcmp(TAB_PALAB_RS[MEDIO].PALAB_RS, CADEN))
=
{ COD
*1
= TAB_PALAB_RS[MEDIO].CODIGO;
break;
== 0)
162
Fundamentos de Programacion en Lenguaje C
} else { if (AUX < 0) BAJO = MEDIa + 1; else ALTO = MEDIa - 1; } } printfC'%d\n" ,COD); return COD; } /* RUTINA PARA DETERMINAR EL VALOR DE UNA CADENA NUMERICA */ int VALUE(CANT) char *CANT;
{ int AUX = 1; int N2=0; int VAL=O; if (CANT[O]=='O')
{ switch (CANT[l])
{ case 'b': case 'B':{ N2=yyleng-2; while «CANT[N2]!='b')&& (CANT[N2]!='B'» { VAL=VAL+(CANT[N2-- ]-'O')*AUX; AUX*=2;
} break; } case 'x': case 'X':{ N2=yyleng-2; while «CANT[N2]!='x')&& (CANT[N2]!='X'» { if (CANT[N2] < ='9') VAL=VAL+(CANT[N2--]-'O')*AUX; else VAL = VAL + (9 + (CANT[N2--] & OxOf»*AUX; AUX*=16;
} break;
} default: { N2=yyleng-2; while «CANT[N2]!=' ')&& (N2)=0))
{ VAL=VAL+(CANT[N2--]-'O')*AUX; AUX*=8; } break;
Funciones
163
}
} } else VAL:;: atoi(CANT); return (VAL);
} /* RUTINA DE SEGUIMIENTO DEL AUTOMATA DE ESTADOS FINITOS DEL ANALIZADOR LEXICOGRAFICO *1 ATR_LEX TRANSLEX(ESTADO) ATR_LEX ESTADO;
{ int CONT = 0; while (1) { if «*ESTADO)[CONTJ.CARACTERESO
{
==
1)
=
SAL_LEX (*ESTADO)[CONTJ.EST_FINAL; return(*(*(*ESTADO)[CONTJ·SIG_ESTADO»;
} else ++CONT; }
} /* RUTINA DE ANALISIS LEXICOGRAFICO Esta rutina escudrina en el archivo de entrada, hasta encontrar un elemento semantico dellenguaje bajo analisis. Esto 10 hace lIamando repetidamente a la rutina de seguimiento del aut6mata de estados finitos, luego de leer un caracter mas, hasta lIegar a un estado final. Cuando se lIega a un estado final, la rutina retorna, con el valor del token reconocido. yylexO, entrega ademas, la longitud del token reconocido y la cadena que re presenta a dicho token, a traves de las variables yyleng y yytext, respectivamente.
*/ int yylexO { int N2 = 0; yylval :;: 0; SAL_LEX = 0; yyleng = 0; /* longitud del token */ ESTADOLEX = (ATR_LEX) INICIAL; while (SAL_LEX == 0)
{
SIG_CAR = SIG_LINEA[N2++]; if (!«ESTADOLEX == (ATR_LEX)INICIAL)&&ESPACIOSO» yytext[yyleng++] = SIG_CAR; ESTADOLEX = TRANSLEX(ESTADOLEX);
164
Fundamentos de Programacion en Lenguaje C
} yytext[yyleng] = 1\01; switch (SAL_LEX) { case Ox010l:{SAL_LEX = RESERVS(yytext); break;} case Ox0138:{ yylval=VALUE(yytext); break;} case OxffOl:{ERRLEXI(l); break;} case Oxff02:{ERRLEXI(2); break;} case Oxff03:{ERRlEXI(3); break;} } return (SAL_LEX);
}
/*
RUTINA DE ATENCION DE ERRORES LEXICOGRAFICOS
*/
ERRLEXI(TIPO) intTIPO;
{ switch (TIPO)
{ case 1:{ printf("CARACfER NO ACEPTADO POR LA GRAMATICA DE LEMEF\n"); break;
} case 2:{ printf(IISE ESPERABA UN TEXTO EN C\n"); break;
} case 3:{
ll printf("SE ESPERABA UN COMENTARIO\n );
}
} return 0; } int salida=!; mainO { INICIALEXO; while (salida)
{ int NSIG_CAR=O; ll printf("ESCRIBE EL ELEMENTO SEMANTICO QUE DESEAS RECONOCER\n ); while «SIG_LINEA[NSIG_CAR++ ]=getcharO) != '\n'); SIG_LINEA[ --NSIG_CAR]=I\OI; printf("Se reconocio el token no. %d\nl1, yylexO); printf(" %s\n", yytext); if (yylval!=O) printf(" VALOR = %d\nll, yylval);
Funciones
165
while (getcharO != '\n'); printf("Deseas continuar con esta prueba?\n"); if (getcharO == In') salida =0; while (getcharO != '\n'); } return 0;
}
Ejercicios 6.1
Desarrollar el programa de la calculadora estadistica especificado en el ejemplo 6.3.
6.2 Desarrollar una funcion que ordene alfabeticamente un conjunto de cadenas materializadas por medio de un arreglo de apuntadores a cadena y el conjunto ordenado se almacene en otro arreglo de apuntadores. La funcion debe tener como panimetros los apuntadores a ambos arreglos. Desarrollar un programa para probar esta funcion. 6.3
Desarrollar una funcion que presente un juego de menus de dos niveles. Un primer menu es la entrada 0 menu principal del sistema y permite acceder a menus especificos que ofrecen diversos servicios. Las etiquetas de cada menu 0 apuntadores a elIas deben pasarse como panimetros a la funcion MENU, 10 mismo que apuntadores a funciones que ejecuten los servicios ofrecidos en los submenus (segundo nivel).
Capitulo 7
FUNCIONES DE ENTRADA Y SALIDA
7.1 lNTRODUCCION Las funciones de entrada y salida no forman parte de la definicion del 1enguaje C, pero normalmente esuin disponibles en la biblioteca estandar de cualquier sistema. Por ejemplo, ellas permiten a los programas: a. b.
c. d.
interactuar con el Qsuario, almacenar y recuperar informacion de los dispositivos de almacenamiento secundario, manipular informacion en la memoria principal, y recibir y transmitir informacion a traves de una red.
La tabla 7.1 muestra las fases por las que deben pasar todas las operaciones de entrada/salida, con cualquier dispositivo periferico. Las operaciones de lectura y escritura pueden realizarse sobre dispositivos de entrada/salida, archivos en dispositivos de almacenamiento secundario 0 buffers impJantados en memoria principal. Ademas de las operaciones basicas realizadas durante las tres fases de trabajo con archivos de entrada/salida, existen otras operaciones con archivos. La tabla 7.2 muestra algunas de estas.
7.2
NOMBRES DE ARCHIVOS
Los nombres de los archivos y de los dispositivos de entrada/salida son dependientes del sistema operativo. En el DOS la identificacion de un archivo consta de tres elementos: la ruta de directorio, el nombre y la extension. La ruta de directorio esta dada por el nombre del dispositivo y la secuencia de nombres de directorio separados por el caracter '\' que indica la ubicacion del archivo en el arbol de directorios del dispositivo en donde se encuentra almacenado. En virtud de que en la especificacion de cadenas en lenguaje C el caracter '\' se usa como
168
Fundamentos de Programacion en Lenguaje C
canicter de control, para que el compilador 10 interprete correctamente se debe escribir doble '\\'. El nombre de archivo es un identificador construido con caracteres alfanumericos, la maxima longitud de este nombre de archivo es de ocho caracteres. La extension, de tres caracteres, va separada del nombre por medio del caracter punto C.). Ejemplos de nombres de archivos en DOS son los siguientes: A:\EJEMPLOS\DATOS.OOl C:\TRABAJO\EJERCICI\TEXTO.TXT
Tabla 7.1: Fases de operacion de un archivo de entrada/salida. Fase
Apertura del archivo
Operaci6n: funci6n de E/S
Con apuntador: fopen freopen
Con descriptor: open creat
Transferencia de Informacion
Cierre del archivo
lectura de caracteres: getch, getc lectura de lineas: gets, fgets read lectura de bytes: lectura de objetos: fread lecturas formateadas: scanf, fscanf escrituras formateadas: printf, fprintf escritura de objetos: fwrite write escritura de bytes: escritura de lineas: gets, fgets escritura de caracteres: putchar, putc Con apuntador: fclose Con descriptor: close
Tabla 7.2: Otras operaciones con archivos. Operaci6n
Comandar el flujo de salida Borrar archivo Cambio de nombre de archivo Crear un archivo temporal Crear un nombre temporal Posicionamiento
Funci6n ff1ush remove rename tmpfile tmpnam fseek, Iseek
Funciones de Entrada y Salida
7.3
169
ENTRADA Y SALIDA EST ANDAR
7.3.1 Biblioteca de entrada/salida estandar Para poder hacer uso de las rutinas de entrada y salida estandar se debe incluir en el programa la biblioteca stdio.h, mediante la llamada al preprocesador #include
Esta biblioteca, ademas de las rutinas de entrada/salida, contiene la definicion de diversas estructuras de datos, constantes e identificadores que son importantes en la formulaci6n de los segmentos de entrada/salida de los programas. Algunos de los mas importantes son los siguientes: stdin stdout stderr EOF
NULL FILE
Nombre del archivo de entrada estandar Nombre del archivo de salida estandar Nombre del archivo de error estandar Valor entregado por las rutin as de lectura cuando encuentran el final de un archivo 0 algun error Apuntador nulo Estructura us ada para declarar apuntadores de archivos
Las funciones de entrada/salida estandar operan con la entrada y la salida estandar del sistema. Normalmente, la entrada estandar es el teclado de la terminal 0 computadora de usuario y la salida estandar es la pantalla. Las funciones de entrada y salida estandar son las mostradas en la tabla 7.3.
Tabla 7.3: Funciones de entrada/salida estandar. Funci6n getch, getchar
putchar scanf printf gets puts
Operaci6n
Entrada estandar caracter por caracter. Salida estandar canicter por caracter. Entrada formateada. Salida formate ada. Entrada estandar linea por linea Salida estandar linea por linea
170
Fundamentos de Programacion en Lenguaje C
7.3.2 Redireccionamiento de la entrada y la salida estandar La entrada y salida estandar asociadas con un programa pueden modificarse en el momento de la ejecuci6n. La entrada estandar se modifica mediante una linea de comando como la siguiente: PROGRAMA < entrada
donde PROGRAMA es el nombre del programa ejecutable que se ha desarrollado. La nueva entrada (especificada) puede ser un archivo en un disco u otro puerto de E/S. Por su parte, la salida estandar puede modificarse mediante un comando como: PROGRAMA > salida
Igualmente, la salida, puede ser un archivo en disco u otro dispositivo, como puede ser la impresora. Si se requiere modificar tanto la entrada como la salida, el comando seria el siguiente: PROGRAMA < entrada > salida
A traves de los ductos (pipes, en ingles) de DOS 0 de UNIX, tambien es posible conectar la salida estandar de un programa con la entrada de otro que esta corriendo en paralelo, el correspondiente programa en este caso seria el siguiente: PROGRAMA
I OTROPROGRAMA
7.3.3 Funciones de entrada y salida estandar Funcion estandar de entrada getchO/getcharO Por medio de la instrucci6n: getchO;
se obtiene el siguiente caracter introducido al sistema por la entrada estandar que regulannente es el tec1ado de la computadora. Como se hace notar en la
Funciones de Entrada y Salida
171
secci6n 4.17, una funci6n retomante, como getchO, puede fonnar parte de cualquier expresi6n compleja, siguiendo la sintaxis indicada en la misma secci6n. El valor retomado por getchO 'es el caracter introducido en la entrada estandar. El prototipo de getch es char getch(void);
Cuando getchO encuentra el final del archivo que se esta leyendo, retoma el valor -1, el cual indica fin de archivo (EOF). La instrucci6n getcharO;
ejecuta la misma operaci6n que getchO, pero opera hasta que se introduce un canicter (retorno de carro).
Funcion estandar de salida putchar(C) Para escribir un caracter en la salida estandar, se utiliza la funci6n putchar(C), cuyo prototipo es: int putchar( char C);
donde C es el caracter que se desea imprimir. La funci6n putchar retoma el caracter impreso en la salida.
Funcion estandar de salida printf(FORMATO, CONCEPTOS) Por medio de esta funci6n se puede escribir una cadena de caracteres cualquiera, en la salida estandar del sistema. Esta funci6n fonnatea los distintos tipos de datos basicos manejados por C, convirtiendolos en caracteres que luego son enviados a la salida estandar. El prototipo de esta funci6n es: int printf(char *FORMATO, ARG1, ARG2, ... ) printf retorna el numero de caracteres impreso en la salida estandar. Tiene un numero de parametros variable, pero dicho numero debe coincidir con los especificadores de [ormato indicados en la cadena FORMATO.
172
Fundamentos de Programaci6n en Lenguaje C
ARG1, ARG2, ... , constituyen los datos que seran convertidos a una cadena de caracteres y posteriormente senin copiados en la salida estandar. FORMATO, es una cadena de control encerrada entre comillas (" "), la cual contiene dos tipos de elementos que son: caracteres ordinarios y especificadores de conversion. Los caracteres ordinarios son copiados directamente en la salida estandar. Por su parte, los especificadores de conversion, determinan el formato con que deberan imprimirse los argumentos de printf. Los especificadores de conversion se inician con el caracter % y terminan con el caracter que de term ina el tipo de conversion a realizar. Entre el signo % y el canicter de conversion pueden existir los elementos calificadores indicados en la tabla 7.4.
Tabla 7.4: Caliticadores de especificador de formato. Un signo-
que indica ajuste a la izquierda.
Una cadena de digitos
que indica el ancho mininlo del campo.
Un punto
que indica un campo de longitud fija. La longitud es determinada por una cadena de digitos subsecuente al punto.
El modificador de longitud I
que indica que el argumento es un entero largo.
Una cadena de digitos con un punto intermedio
En el caso de cantidades de punto £10tante 0 de doble precision, indica el numero total de digitos, y el numero de digitos a la derecha del punto decimal que deben imprimirse.
Los caracteres de conversion permiten indicar la impresion de numeros enteros en formato decimal, octal 0 hexadecimal, numeros reales en formato decimal o en notacion exponencial, caracteres y cadenas de caracteres; dichos caracteres de conversion son los de la tabla 7.5. El ejemplo 7.1 ilustra el uso de. printf, en dicho ejempl0 se presentan algunos errores tipicos, como en la sexta linea en la que se indica un campo numerico con numero de digitos de la fraccion, mayor que la longitud total del campo y luego el argumento es una cadena. Asimismo, en la primera linea falta un argumento de tipo cadena.
Funciones de Entrada y Salida
173
Tabla 7.5: Especificadores de formato de impresion. d 0
x u
e 5
e
f
9
~l ar~mento se convierte a notacion deciI?al. EI argumento se convierte a notacion octal sin signo y sin ceros a la izquierda. EI argumento se convierte a notacion hexadecimal sin signo y sin el Ox precedente. EI argumento se convierte a notacion decimal sin signo. EI argumento es un solo caracter. EI argumento es una cadena de caracteres. Los caracteres de la cadena se imprimen hasta que se encuentra un caracter nulo 0 hasta que el numero de caracteres indicado por el especificador fue alcanzado. EI argumento es de punto flotante 0 doble precision y se convierte a una notacion de la forma: [-]m.nnnnnn E±xx donde la longitud de la cadena de n's es la precision 0 numero de digitos ala derecha del punto decimal que deb en imprimirse. La precision por omision es de 6 digitos. EI argumento es de punto flotante 0 doble precision y se convierte a una notacion de la forma: [-]mmm.nnnnnn donde la longitud de la cadena de n's es la precision 0 numero de digitos ala derecha del punto decimal. La precision por omision es de 6 digitos Indica que se use el formato %e 0 %f, el que resulte mas corto. No se imprimen los ceros no significativos.
Ejemplo 7.1: Uso de printf. printf("Hola %e %d 0/05 \n", '\t', 15); printf("0/0-s.2f\n", 123.234); printf("%s.2f\n", 3.234); printf("0/o10s\n", "Hola''); printf("0/0-.3s\n", "Hola"); printf("%s.7f\n", "123456789',);
II
Imprime: Hola 15 (null) / / Error, imprime correcto 123.23 II Imprime: 3.23 1/ Imprime: Hola / / Imprime: Hoi / / Error, imprime 0.00000000
EI campo numerico del printf de la segunda linea del ejemplo 7.1 tambien esta especificado en forma incorrecta, porque si se desea imprimir dos digitos decimales y la parte entera, el campo debe tener una longitud minima total de 6 digitos y no de 5, ya que el punto decimal tambien se cuenta. Con el printf de la
174
Fundamentos de Programaci6n en Lenguaje C
tercera linea se imp rime 3.23, con el de la cuarta se imprime el mensaje Hola cargado a la derecha y con una longitud de 10 caracteres, y con el de la quinta linea se imprime el mensaje Hoi, truncando asi esta cadena.
Funcion estandar de entrada scanf(CONTROL, CONCEPTOS) Por medio de la funcion scanf se puede leer una cadena de caracteres cualquiera de la entrada estandar del sistema. Esta funcion formatea los distintos tipos de datos basicos manejados por C, convirtiendolos de los caracteres que son enviados por la entrada estandar, al formato del correspondiente tipo de dato. Regresa EOF cuando encuentra este elemento en la entrada 0 bien ocurre un error y cuando tiene exito regresa el mimero de datos convertidos y asignados. El prototipo de esta funcion es la siguiente: int scanf(char *CONTROL, ARG1, ARG2, ... )
donde ARG1, ARG2, ... , son los argumentos de scanf, y constituyen las direcciones donde se almacenaran los datos que seran leidos de la entrada estandar. Todos estos argumentos indican variables en las cuales se van a depositar los datos y por 10 tanto deben ser apuntadores. CONTROL, es una cadena de control encerrada entre comillas, la cual puede contener espacios, tabuladores y cambios de renglon que son transparentes a la interpretacion y por 10 tanto, son ignorados; caracteres ordinarios (diferentes de 0/0), los cuales se espera que coincidan con el subsiguiente canicter de entrada (que no sea un espacio); y especificadores de conversion, que determinan el formato de los argumentos de scanf. Los especificadores de conversion se inician con el car:kter % y terminan con el caracter que determina el tipo de conversion a realizar. Entre el signo % y el caracter de conversion puede haber un numero que especifica el ancho del campo, 0 el canicter * que indica supresion. Los caracteres de conversion son los indicados en la tabla 7.6. Tabla 7.6: Especificadores de Formato de Conversion de Entrada d 0
x h C
s f
El dato de entrada es entero decimal. El dato de entrada es entero octal. EI dato de entrada es entero hexadecimal. EI dato de entrada es entero corto. El dato de entrada es un solo canicter. El dato de entrada es una cadena de caracteres. EI dato de entrada es de punto flotante, con formato: signo opcional, cadena de numeros con punto decimal opcional, y exponente opcional conteniendo e 0 E Y el exponente.
Funcionesde Entrada y Salida
175
Los especificadores d, 0 Y x, pueden ser precedidos por una I, en cuyo caso, indicaran que el dato de entracla es un entero largo. El ejemplo 7.2 ilustra el uso de scanf (CONTROL, CONCEPT05). N6tese que en este caso los argumentos deben ser los apuntadores a las variables 0 arreglos, en donde se guardaran los datos de entrada Ejemplo 7.2: Uso de scanf. scanf("%d", &CUENTA); / /Mete un entero decimal a la variable CUENTA scanf("%s", CADENA); //Mete una cadena de caracteres al arreglo que //empieza en la direccion CADENA scanf("%20s", CADENA); //Mete una cadena de 20 caracteres al arreglo que //empieza en la direccion CADENA scanf("%c%c%c", &A, &B, &C);//Mete tres caracteres a las variables A, B Y C scanf("%s ", NOMBRE); //Mete una cadena de caracteres al arreglo que //empieza en la direccion NOMBRE scanf("%f", &REAL); / /Mete un numero de punto f10tante a la variable //REAL
Funcion estandar de entrada gets(S) Esta funci6n lee la siguiente linea de entrada y la deja en el arreglo apuntado por la cadena especificada en su argumento. Reemplaza el cankter de fin de linea por '\0' y regresa el apuntador a la cadena capturada, 0 bien EOF si encontr6 el final del archivo 0 hubo error en la captura. Su prototipo es: char *gets( char *5)
en donde 5 es un arreglo en el que se va a guardar la cadena de entrada.
Funcion estandar de salida puts(S) Esta funci6n escribe la cadena indicada en su argumento y un retorno de carro y nueva linea en la salida estandar. Regresa EOF si ocurri6 un error de escritura. De otra manera regresa un valor no-negativo. No altera el contenido del arreglo apuntado por el argumento. Su prototipo es: char *puts( char *5)
En la funci6n GETNUM, cuyo programa se muestra en el ejemplo 7.3, se ilustra el uso de gets y puts. GETNUM retorna el valor numerico entero de la cadena
176
Fundamentos de Programaci6n en Lenguaje C
de digitos que se tecleo a la entrada, e indica que debe ser un numero si no se tecleo un numero entero. Para esto utiliza el hecho de que gets deja en la 111tima posicion de la cadena el '\0'. Ejemplo 7.3: Uso de gets y puts.
/* Programa GETNUM.C */ GETNUMO
{ char NUM[80], n; do{ gets(NUM); if (!NUMERO(NUM)) {puts("debe ser numero\n"); n=O;} else n = 1; } while (!n); return (atoi(NUM));
} NUMERO(char *5) { int T; for ( T=O; S[T]; T ++) if (!isdigit(S[T])) return 0; return 1;
} mainO
{ printf ("EI numero tecleado es %d \n\n",GETNUMO); }
7.4 ACCESO A ARCHIVOS Ademas de la entrada y la salida estandar, la biblioteca de E/S estandar de C, stdio.h, pennite tener acceso a uno 0 varios archivos. Se dispone de funciones para abrir y cerrar archivos para lectura, escritura 0 lectura y escritura, de fun-
ciones para leer y para escribir sobre los archivos, en las diferentes formas indicadas en la tabla 5.1 (caracteres, lineas, secuencias fonnateadas, bytes y objetos), y de funciones para posicionarse en un punto especifico de un archivo. Para poder leer 0 escribir sobre un archivo, primeramente se debe abrir 0 crear el archivo. Se pueden abrir 0 crear archivos con dos modalidades, para trabajar con un apuntador al archivo, 0 para trabajar con un descriptor del archivo. EI apuntador se obtiene mediante las funciones fopen 0 freopen, y el descriptor es retomado por las funciones open y create.
Funciones de Entrada y Salida
177
7.4.1 Acceso a archivos mediante apuntadores a archivo Apertura del archivo con lafunci6n fopen(NOMBRE,MODO) Con la Hamada a esta funci6n, se obtiene un apuntador de tipo FILE, al cual puede despues hacerse referencia para realizar las transferencias de informaci6n. Esta funci6n tiene el siguiente prototipo: FILE fopen(char *NOMBRE, char *MODO); El tipo FILE esta declarado en la biblioteca , por 10 cual, para acceder a archivos en memoria 0 en disco, 0 de otro dispositivo perif6rico, es necesario incluir esta biblioteca en el encabezado del programa. NOMBRE es el nombre del archivo al que se va a acceder; obviamente, este nombre debe tener la estructura de nombres de archivo del sistema operativo. MODO es el modo en que se va a trabajar el archivo que puede ser: "r"
"w"
"a" "r+" "w+" "a+"
Abre archivo de texto para lectura Crea archivo de texto para escritura, descarta el contenido previo si existe Agrega; abre 0 crea un archivo para escribir al final Abre un archivo para actualizaci6n, lectura 0 escritura Crea archivo de texto para actualizaci6n; descarta contenidos previos Agrega, abre 0 crea el archivo de texto para actualizaci6n, escribiendo al final
El modo actualizaci6n permite la lectura y escritura del mismo archivo. Si se Ie agrega una b a la cadena se indica que el archivo es binario. El apuntador entregado por la funci6n fopen debe guardarse en una variable de tipo apuntador a archivo (tipo FILE), para que luego pueda hacerse referencia a 61. Por ejemplo: FILE *SALIDA; SALIDA
/ / Declaracion del apuntador a archivo
= FOPEN("A:\\Archivo1.txt:", "w"); 1/ Asignacion del apuntador de archivo
Transferencias de datos a archivos de caracteres Una vez abierto el archivo se pueden hacer transferencias de datos mediante funciones de entrada/salida que operan con apuntadores a archivos que fueron
178
Fundamentos de Programaci6n en Lenguaje C
obtenidos con fopen, las cuales tambien se tienen disponibles en la biblioteca stdio.h. Las funciones de la tabla 7.7 son las que operan con archivos de caracteres. Tabla 7.7: Funciones de entrada/salida para archivos de caracteres getc putc fscanf fprintf fgets fputs ungetc
Entrada de archivo canicter por canicter. Salida a archivo caracter por caracter. Entrada formateada desde un archivo de texto Salida formateada hacia un archivo de texto Entrada de archivo, linea por linea, de maximo N caracteres Salida a archivo, linea por lfnea Regresa un caracter leido al buffer del archivo
Las seis primeras funciones de la lista anterior funcionan de manera similar a las funciones de E/S estandar, con la unica salvedad de que el archivo de entrada o salida es el especificado como tipo FILE, y cuyo apuntador fue obtenido con la funcion fopen. EI prototipo de estas funciones es: char getc(FlLE *ARCHIVO); char putc(int C, FILE *ARCHIVO); int fprintf(FILE *ARCHIVO, char *CONTROL, ARG1, ARG2, ... ); int fscanf(FILE *ARCHIVO, char *CONTROL, ARG1, ARG2, ... ); char *fgets(char *5, int N, FILE *ARCHIVO); char *fputs(char *5, FILE *ARCHIVO);
En todos los casos, ARCHIVO es el apuntador a archivo retomado por fopen. es el numero maximo de caracteres que se van a leer, 0 bien una lfnea. Los otros argumentos tienen exactamente la misma descripcion que en el caso de las funciones de E/S estandar. ungetc regresa el caracter indicado, al buffer del ARCHIVO. Su prototipo es N
char *ungetc(int C, FILE *ARCHIVO);
donde C es el caracter y ARCHIVO el apuntador al archivo obtenido con fopen.
Entrada/Salida de objetos diversos. Funciones fread y
fwrite
La biblioteca stdio.h tambien cuenta con funciones que permiten dar entrada 0 salida a datos de fndole diversa y no como secuencias de caracteres. Las funcio-
Funciones de Entrada y Salida
179
nes fread y fwrite realizan estas tareas, es decir envian a un archivo cuyo apuntador se obtuvo con fopen objetos de cualquier longitud, 0 bien leen del archivo, objetos de cualquier longitud. EI prototipo de estas dos funciones es: size_t fread(const void *PTR, size_t SIZE, size_t NOBl, FILE *ARCHIVO) size_t fwrite(const void *PTR, size_t SIZE, size_t NOBl, FILE *ARCHIVO)
donde PTR es el buffer de salida 0 de entrada, de donde se toman 0 en donde se colocan los NOB] objetos de tamafio SIZE que se van a leer 0 a escribir en el archivo cuyo apuntador es ARCHIVO. fread retoma el numero de objetos leidos y fwrite el numero de objetos escritos.
7.4.2 Acceso a archivos mediante descriptores de archivos EI descriptor de archivos es un entero positivo que el sistema operativo proporciona si tiene exito la operacion de apertura de un archivo mediante la funcion open. Si el archivo existe 0 se puede crear y si se tiene autorizado el acceso a el, la operacion de apertura tiene exito. EI descriptor de archivo se emplea en lugar del nombre del archivo al realizar las operaciones de E/S. Los descriptores de los tres archivos estandar son:
o 1
2
stdin stdout stderr
Los descriptores de archivQs son una opci6n a los apuntadores a archivo de tipo FILE, los cuales se han descrito con anterioridad, y son retomados por la funcion fopen. Ademas, son utilizados por funciones de E/S como read y write y otras funciones de control de dispositivos de E/S.
Apertura del archivo con lafunci6n
open(NOMBRE,ACCESO,MODO)
Esta funcion se encuentra en la biblioteca io.h. Con la Hamada a la funcion open(NOMBREI MODO), se obtiene un entero, al cual representa el descriptor de archivo al que despues debe hacerse referencia para realizar transferencias de informacion. Tiene el prototipo: int open(const char *NOMBRE1 int ACCESO [
I
unsigned MODO] );
180
Fundamentos de Programacion en Lenguaje C
donde NOMBRE es la trayectoria y nombre del archivo que se va a abrir, ACCESO es una de las siguientes constantes, cuando se trabaja con archivos previamente creados: O_RDONLY O_WRONLY O_RDWR
Abre solo para lectura Abre solo para escritura Abre para lectura y escritura
Se puede crear un archivo con la opcion de acceso O_CREATE
Crea y abre un archivo
En este ultimo caso se debe indicar el MODO, que puede ser uno de los siguientes: Crea archivo solo para lectura Crea archivo solo para escritura Si se desean ambos modos, se debe crear el archivo combinando los dos modos mediante la operacion logica binaria " I". Las constantes se encuentran definidas en la biblioteca fcntl,h, por 10 cual tambien se debe de incluir.
Funciones read y write Estas funciones permiten dar salida 0 entrada a secuencias de bytes, como archivos binarios, y se encuentran en la biblioteca io.h. La sintaxis de read es: int read(int DA, char BUFER[ ], int NBYTES); donde DA es el descriptor de archivos obtenido con open, BUFER es el area de memoria en donde se depositara la informacion leida y NBYTES el numero de bytes que se requiere leer. read retoma el numero de bytes leidos, el cual puede ser diferente de NBYTES, si se Uega al fin de archivo 0 hay algun error. La sintaxis de write es: int write(int DA, char BUFER[ ], int NBYTES);
Funciones de Entrada y Salida
181
donde DA es el descriptor de archivos obtenido con open, BUFER es el area de memoria de donde se tomara la informacion a la que se Ie va a dar salida y NBYTES e1 numero de bytes que se requiere escribir. write retoma el numero de bytes escritos, el cual puede ser diferente de NBYTES si hay algun error.
7.5 ACCESO ALEATORIO A ARCHIVOS La entrada y la salida normalmente es secuencial, cada lectura 0 escritura en el archivo ocurre en una posicion justo despues de la anterior. Cuando es necesario leer de acuerdo a una secuencia aleatoria, puede usarse la funcion fseek para posicionar el apuntador en un e1emento cualquiera del archivo. La sintaxis de esta funcion es: long fseek(FIlE *ARCHIVO, long DESP, int ORIGEN); donde ARCHIVO es el apuntador retomado por una funcion fopen al abrir un archivo. ORIGEN puede ser 0, 1 0 2, para especificar que el desplazamiento sera desde el principio del archivo, desde la posicion actual 0 desde el final del archivo, respectivamente, y DESP es el desplazamiento. Algunos ejemplos de uso de esta funcion, son: fseek(ARCHI, Ol, 2) fseek(ARCHI, Ol, 0)
1* Se va al final del archivo *1 1* Se va al principio del archivo *1
Iseek es similar a fseek pero opera con el descriptor de archivos obtenido mediante la Hamada open. El programa del ejemplo 7.4 ilustra una aplicacion de las instrucciones open, creat y Iseek. El programa "agregatx.c", abre 0 crea e1 archivo que se Ie indica, recorre el apuntador al final del archivo y agrega el texto que se Ie dio al programa a traves de la entrada estandar (teclado). Ejemplo 7.4: Programa "agregatx.c".
1******* Este programa prueba la forma en que debe emplearse la lIamada
open; y/o la lIamada creat, para agregar texto a un archivo en disco. EI programa interactua con el usuario, abre y cierra el archivo indicado por el parametro, agregando el texto que se introduce, al solicitar el programa el nuevo texto a agregar. Notese que para poder agregar texto se debe utilizar la lIamada Iseek para posicionarse en el lugar adecuado. ********************************/ #include #include
182
Fundamentos de Programacion en Lenguaje C
int SALIDA; mainO
{ int ap, CON; char nuevotexto[512], NOMBRE[20]; for(CON = 0; CON < 512; CON++ )nuevotexto[CON] = 0; printf("DAME EL NOMBRE DEL ARCHIVO\n"); scanf("%s", NOMBRE); if «SALIDA=open(NOMBRE,O_RDWR,O)) BDCOLOR); setfillstyle(SOLID_FILL, PV-> BDCOLOR); rectangle( PV - > VXI + 5, PV- > VYI -5, PV- > VXF+ 5, PV- > VYF- 5); floodfill(PV->VXI+6,PV->VYI, PV->BDCOLOR); setcolor(PV-> FONDCOLOR); setfilistyle(SOLID_FILL,PV-> FONDCOLOR); rectangle(PV- > VXI,PV-> VYI,PV- > VXF, PV- > VYF); floodfill(PV->VXI+l,PV->VYI+l, PV->FONDCOLOR); setcolor(PV-> TXCOLOR); settextstyle(PV-> TIPOC,HORIZ_DIR,PV-> TAMC); }
*/
200
Fundamentos de Programacion en Lenguaje C
int MENUO
{ /* MENU presenta en la pantalla el menu con la lista de figuras geometricas que puede trazar el programa. MENU entrega a su salida un numero entero que representa la selecci6n realizada. */ int SELECCION; /*Crear una ventana gratica de texto con parametros de la estructura PVTO */ VENlTXTG(&PVTO); /* Escribir el MENU */ outtextxy(40,20,"* [1] LINEA dando el punto inicial y final"); outtextxy(40,40,"* [2] CIRCULO dando el centro y el radio"); outtextxy(40,60,"* [3] ELIPSE dados su centro y longitudes de los ejes"); outtextxy(40,80,"* [4] RECfANGULO dando dos vertices"); ll outtextxy(40,lOO,"* [5] POLIGONO dando numero de lados y vertices ); outtextxy(40,120,11* [6] CURVA dando una secuencia de puntos"); outtextxy(40,140,11* [7] FUNCION dada su ecuaci6n y el rango de valores de la var. "); outtextxy(40,160,"* [8] Salir");
/* Retornar la selecci6n * / return (getchO-'O');
} int LINEAO { int PIX, PlY, PFX, PFY; char BUFER[20]; /* Crea una ventana grafica de texto */ VENTTXTG(&PVT1); /* Obtener las coordenadas de los puntos inicial y final y hacer el eco de dichos datos */ outtextxy(190,320,"Coordenadas del Punto Inicial PI"); outtextxy(240,340, II PIX: "); cscanf("%dll,&PIX); sprintf(BUFER,"%d" ,PIX); outtextxy(275,340,BUFER); outtextxy(320,340, II PlY: "); cscanf("%dll,&PIY); sprintf(BUFER,"%d",PIY); outtextxy(355,340,BUFER); outtextxy(190,360,"Coordenadas del Punto Final PF"); outtextxy(240,380,"PFX: "); cscanf(l%d",&PFX); . sprintf(BUFER,"%d",PFX); outtextxy(275,380,BUFER); outtextxy(320,380,"PFY: "); cscanf("%d",&PFY); sprintf(BUFER,"%d",PFY); outtextxy(355,380,BUFER);
/* Borrar la pantalla* / cleardeviceO;
Graficos
201
/* Trazar la linea */ line(PlX, PlY, PFX, PFY); /* Hacer una pausa */ getchO; getcharO;
} int ClRCULOO { int CX, CY, R; char BUFER[20]; /* Crear una ventana de texto grafica * / VENTIXTG(&PVT1); /* Obtiene las coordenadas del centro y el radio y hace el eco de dichos datos outtextxy(190,320,"Coordenadas del Centro"); outtextxy(240,340,"CX: "); cscanf("%d",&CX); sprintf(BUFER,"%d",CX); outtextxy(275,340,BUFER); outtextxy(320,340,"CY: "); cscanf(l%d",&CY); sprintf(BUFER, II %d II ,CY); outtextxy(355,340,BUFER); outtextxy(190,360,"Radio del drculo"); outtextxy(240,380,"R: "); cscanf("%d ,&R); sprintf(BUFER,"%d",R); outtextxy(275,380,BUFER);
*/
ll
/* Borrar la pantalla*/ cleardeviceO;
/* Traza el
drculo * / circle(CX,CY,R);
/*
Hacer una pausa * / getchO; getcharO;
} int ELIPSEO { int AlNI = 0, AFIN = 360; int LEX, LEY, CX, CY; char BUFER[20];
/*
Crear una ventana de texto grafica VENTIXTG(&PVT1);
*/
/* Obtiene las coordenadas del centro y la longitud de los ejes mayor y menor */ outtextxy(190,320,"Coordenadas del Centro"); outtextxy(240,340,"CX: "); cscanf("%d",&CX);
202
Fundamentos de Programacion en Lenguaje C
sprintf(BUFER,"%d",CX); outtextxy(275,340,BUFER); outtextxy(320,340/'CY: "); cscanf("%d",&CY); sprintf(BUFER,"%d",CY); outtextxy(355,340,BUFER); outtextxy(190,360,"Longitud de los ejes"); outtextxy(240,380,"LEX: "); cscanf("%d",&LEX); sprintf(BUFER,"%d",LEX); outtextxy(275,380,BUFER); outtextxy(320,380,"LEY: "); cscanf("%d",&LEY); sprintf(BUFER,"%d",LEY); outtextxy(355,380,BUFER); /* Borrar la pantalla*/ cleardeviceO; /* Traza la elipse */ ellipse(CX,CY,AINI,AFIN,LEX/2,LEY/2);
/*
Hacer una pausa * / getchO; getcharO;
} int RECTANGULOO { int VIX, VIY, VFX, VFY; char BUFER[20]; /* Crea una ventana grMica de texto */ VENTTXTG(&PVT1); /* Obtiene las coordenadas de los vertices y hace el eco de dichos datos * / outtextxy(190,320,"Coordenadas del Vertice Inicial"); outtextxy(240,340,"VIX: "); cscanf("%d",&VIX); sprintf(BUFER,"%d",VIX); outtextxy(275,340,BUFER); outtextxy(320,340,"VIY: "); cscanf("%d",&VIY); sprintf(BUFER,"%d",VIY); outtextxy(355,340,BUFER); outtextxy(190,360,"Coordenadas del Vertice Final"); outtextxy(240,380,"VFX: "); cscanf("%d",&VFX); sprintf(BUFER,"%d",VFX); outtextxy(275,380,BUFER); outtextxy(320,380,"VFY: "); cscanf("%d",&VFY); sprintf(BUFER,"%d",VFY); outtextxy(355,380,BUFER); /* Borrar la pantalla*/ cleardeviceO; /* Traza el rectangulo * / rectangle(VIX, VIY, VFX, VFY); /* Hacer una pausa * / getchO; getcharO;
}
Graficos
203
int POLIGONOO
{ int NP, AUX, TAM, PPOLIGONO[40]; char BUFER[20]; void *BUFFG; /* Crea una ventana grafica de texto */ VENTIXTG(&PVT1); /* Obtiene el numero y las coordenadas de los puntos y hace el eco de dichos datos */ outtextxy(190,320,"Numero de puntos del polfgono"); outtextxy(240,340,"NP: "); cscanf("%d",&NP); sprintf(BUFER,"%d",NP); outtextxy(275,340,BUFER); outtextxy(190,360,"Coordenadas del Vertice"); TAM = imagesize(240,380,380,390); BUFFG = malloc(TAM); getimage(240,380,380,390,BUFFG); for(AUX=O; AUX
View more...
Comments