93
MODULO V PROGRAMACIÓN EN LENGUAJE C PARA CONTROL

Modulo v Lenguaje C Para Control

Embed Size (px)

Citation preview

Page 1: Modulo v Lenguaje C Para Control

MODULO V

PROGRAMACIÓN EN LENGUAJE C

PARA CONTROL

Page 2: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

2

Page 3: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

3

TABLA DE CONTENIDO

Página

INTRODUCCIÓN ............................................................................................................ 5

FUNDAMENTACIÓN ..................................................................................................... 5

OBJETIVO ........................................................................................................................ 6

CAPITULO 1

INTRODUCCIÓN A LENGUAJE C .............................................................................. 7

OBJETIVO PARTICULAR 1: .............................................................................................................7

1.1 ORÍGENES DEL C ...................................................................................................................7

1.2 CARACTERÍSTICAS DEL LENGUAJE C ..................................................................................8

1.3 USO DEL C .............................................................................................................................8

CAPÍTULO 2

OPERADORES Y EXPRESIONES DE C ................................................................... 15

OBJETIVO PARTICULAR 2 ..........................................................................................................15

2.1 TIPOS DE DATOS ..................................................................................................................15

2.2 MODIFICADORES .................................................................................................................19

2.3 OPERADORES .......................................................................................................................23

2.4 OPERADORES RELACIONALES Y LÓGICOS .........................................................................24

2.5 OPERADORES A NIVEL DE BITS...........................................................................................25

CAPÍTULO 3

SENTENCIAS DE CONTROL ..................................................................................... 27

3.1 SENTENCIAS CONDICIONALES ............................................................................................28

3.2 SENTENCIAS ITERATIVAS ...................................................................................................30

CAPÍTULO 4

FUNCIONES BASICAS ................................................................................................. 33

4.1 FUNCIONES DE CONTROL DE PROGRAMA ..........................................................................33

4.2 FUNCIONES DE E/S ..............................................................................................................34

4.3 FUNCIONES DE CONSOLA ....................................................................................................37

CAPÍTULO 5

VARIABLES Y FUNCIONES ....................................................................................... 39

5.1 DECLARACIÓN DE FUNCIONES ...........................................................................................39

5.2 VALORES DEVUELTOS ........................................................................................................41

5.3 TIPOS DE VARIABLES ..........................................................................................................42

5.3 ESPECIFICADORES DE CLASE DE ALMACENAMIENTO ......................................................44

Page 4: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

4

5.4 REGISTER .............................................................................................................................45

5.4 AUTO ....................................................................................................................................46

CAPÍTULO 6

ARREGLOS DE MEMORIA ........................................................................................ 47

6.1 CONJUNTO ORDENADO DE VARIABLES (ARRAYS) ............................................................47

6.2 CONJUNTO ORDENADO DE CARACTERES (STRINGS) ........................................................49

6.3 ARRAYS Y STRINGS COMO ARGUMENTOS DE FUNCIONES ...............................................49

6.4 ARRAYS MULTIDIMENSIONALES. .......................................................................................51

CAPÍTULO 7

PUNTEROS ..................................................................................................................... 53

7.1 DECLARACIÓN DE VARIABLES TIPO PUNTERO ..................................................................53

7.2 PUNTEROS Y ARRAYS ..........................................................................................................55

7.3 ASIGNACIÓN ........................................................................................................................56

7.4 ARITMÉTICA DE PUNTEROS ................................................................................................57

7.5 PUNTEROS Y VARIABLES DINÁMICAS ..............................................................................58

7.6 PUNTEROS A STRINGS .........................................................................................................60

7.7 ARRAYS DE PUNTEROS .......................................................................................................62

CAPÍTULO 8

8.1 FUNCIONES DE ENTRADA Y SALIDA ...................................................................................65

8.2 CONFIGURACIÓN DE PUERTOS DE E/S ...............................................................................66

CONCLUSIONES ........................................................................................................... 69

BIBLIOGRAFÍA ............................................................................................................. 70

ANEXO A ........................................................................................................................ 71

ANEXO B ........................................................................................................................ 85

Page 5: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

5

INTRODUCCIÓN

Este curso esta dividido en dos secciones: la primera trata sobre la teoría básica del

lenguaje C y la segunda sobre las funciones para dirigir la información de un programa a

salidas físicas que serán usadas como medio de control del robot SCARA de este curso.

Los primeros 7 capítulos se explican los aspectos teoricos del lenguaje C con la finalidad de

mostrar los elementos de sintaxis necesarios para implementar un algoritmo de control. El

último capítulo muestra como utilizar las funciones de entrada y salida a puertos, así como

también, la forma de habilitar dispositivos de tipo programable que serán instalados en la

computadora como periféricos de control.

Los primeros capítulos muestran la siguiente secuencia: primero se da una introducción

sobre la historia y los creadores del lenguaje C, las características del lenguaje y el medio

para compilarlo y enlazarlo. El segundo capítulo trata el tema de los operadores los cuales

son la esencia de las operaciones lógicas y aritméticas ampliamente usadas en

programación. El capítulo 3 muestra la sintaxis de las principales sentencias de control,

estas se dividen en dos partes: las de tipo condicional y las de tipo iterativo. En el siguiente

capitulo se muestra el uso de las funciones básicas del C consideradas por la naturaleza de

este curso, se trata de dar una idea al programador de la forma de cómo utilizar las

funciones que son mejor conocidas en otros lenguajes como subrutinas.

Por otro lado el capitulo 5 trata el tema también de las funciones y las variables del

programa, sin embargo, las funciones de este capítulo son creadas por el usuario y los

argumentos de estas funciones son variables de diferentes tipos que se muestra la

metodología para hacer la declaración de dichos elementos.

Los capítulos 6 y 7 tratan el tema de arreglos de memoria y apuntadores los cuales son

pieza fundamental en la comprensión de los programas de control del robot, ya que se

destinará un arreglo de memoria para guardar las posiciones del manipulador de este curso

y además se utilizaran apuntadores para grabar los datos en localidades de memoria de

disco como respaldo, para la cual el uso de apuntadores es imprescindible.

Por último el capítulo 8 muestra el uso de funciones de entrada y salida de puertos paralelos

que serán el canal donde se transmita la información para activar el movimiento del robot y

recibir la información de las señales de retroalimentación.

FUNDAMENTACIÓN

Los elementos de un sistema mecatrónico no prosperan sin un buen cerebro de

computadora, actualmente la tecnología destina una gran parte de su inversión en el

desarrollo de nuevas tecnologías en el campo de la informática para desarrollar cerebros de

computadora más rápidos y baratos con la finalidad de hacer más eficiente e inteligente los

sistemas mecatrónicos. En este sentido la revolución de esta tecnología ha permitido que

cada vez mas usuarios pueden acceder a sistemas de computo que facilitan la

Page 6: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

6

implementación de algoritmos de control solo conocidos en forma teórica, es así, que este

modulo muestra como dar control a un robot de arquitectura abierta con el fin de utilizar

formulaciones de cinemática y realizar el control de lazo semi cerrado de un robot tipo

SCARA.

OBJETIVO

Utilizar la teoría de lenguaje C con la finalidad de realizar control motores y hacer la

lectura de sensores por una computadora personal, hasta conseguir los elementos de

control y adquisición de datos suficientes para implementar formulaciones de las tareas

cinemáticas de robots manipuladores de tipo industrial, con lo cual dotar de la habilidad

suficiente al participante para plantear en forma teórica la programación de control de un

sistema dinámico a lazo cerrado.

Page 7: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

7

CAPÍTULO 1

INTRODUCCIÓN A LENGUAJE C

Este primer capítulo proporciona una introducción sobre el lenguaje C, es decir, quien lo

inventó, qué tipo de lenguaje es y qué nivel tiene. Situar al lenguaje C en relación al nivel

que tiene permite conocer el poder de éste, porque a medida que es de más bajo nivel tiene

más capacidad, pero por otro lado, se hace muy complejo para el usuario. El lenguaje C es

el justo medio entre complejidad y capacidad. Específicamente se hablará del origen del

lenguaje C, algunas características importantes del lenguaje, pasos para realizar un

programa.

Objetivo particular 1:

Utilizar el entorno del editor del lenguaje C, aplicando las sentencias básicas para que

puedan ser empleadas en los programas de control.

1.1 Orígenes del C.

El lenguaje C fue inventado por Dennis Ritchie en 1972, cuando trabajaba junto con Ken

Thompson, en el diseño del sistema operativo UNIX.

El lenguaje C, deriva del lenguaje B de Thompson, el cual, a su vez, deriva del lenguaje

BCPL desarrollado por Martín Richards.

Durante muchos años el estándar de C, fue la versión proporcionada con el sistema

operativo UNIX versión 5. Pero pronto empezaron a surgir muchas implementaciones del

C, a raíz de la popularidad creciente de los micro-ordenadores. Por este motivo, se hizo

necesario definir un C estándar que está representado hoy por el ANSI C.

En este curso se va a estudiar el C, estándar. No obstante, si la opción turbo está activada,

también se incluye en la explicación la versión Turbo C de Borland International, que es

uno de los mejores compiladores de C, que existe en el mercado.

Cuando se habla de Turbo C, se hace referencia indistintamente de las diversas versiones

que existen sobre los paquetes Turbo C, Turbo C++ y Borland C++, puesto que en todos

ellos se puede programar en C.

El lenguaje C, suministrado por Turbo C, es simplemente una ampliación del ANSI C,

sobre todo en el número de funciones de librería suministradas.

Page 8: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

8

1.2 Características del lenguaje C.

Algunas características del lenguaje C, son las siguientes:

Es un lenguaje de propósito general. Este lenguaje se ha utilizado para el desarrollo de

aplicaciones tan dispares como: hojas de cálculos, gestores de bases de datos,

compiladores, sistemas operativos, etc.

Es un lenguaje de nivel medio. Este lenguaje permite programar a alto nivel (pensando a

nivel lógico y no en la máquina física) y a bajo nivel (con lo que se puede obtener la

máxima eficiencia y un control absoluto de cuanto sucede en el interior del ordenador).

C, es un lenguaje portátil. Los programas escritos en este lenguaje son fácilmente

transportables a otros sistemas.

Es un lenguaje potente y eficiente. Usando C, un programador puede casi alcanzar la

eficiencia del código ensamblador junto con la estructura del Algol o Pascal.

Como desventajas habrá que resaltar que es más complicado de aprender que otros

lenguajes como Pascal o Basic y que requiere una cierta experiencia para poder

aprovecharlo a fondo.

1.3 Uso del C.

Los pasos a seguir desde el momento que se comienza a escribir el programa C hasta que se

ejecuta son los siguientes:

1.- Escribirlo en un editor.

2.- Compilarlo en un compilador.

3.- Enlazarlo en un enlazador.

4.- Ejecutarlo.

Paso 1: Escribirlo

El programa se puede escribir en cualquier editor que genere archivos de texto estándar,

esto es, que los archivos generados no incluyan códigos de control y caracteres no

imprimibles. Estos archivos que contienen código C, se llaman archivos fuentes. Los

archivos fuentes son aquellos que contienen código fuente, es decir, archivos con texto que

el usuario puede leer y que son utilizados como entrada al compilador de C. Los programas

pequeños suelen ocupar un solo archivo fuente; pero a medida que el programa crece, se va

haciendo necesario distribuirlo en más archivos fuentes.

Paso 2: Compilarlo

El compilador produce archivos objetos a partir de los archivos fuentes. Los archivos

objetos son los archivos que contienen código objeto, es decir, archivos con código

Page 9: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

9

máquina (números binarios que tienen significado para el microprocesador) y que son

utilizados como entrada al enlazador. La extensión de estos archivos es OBJ, aunque

también hay con extensión LIB. A estos últimos se les llama también archivos de librería o

biblioteca; contienen código máquina perteneciente a código compilado suministrado por el

compilador.

Paso 3: Enlazarlo

El enlazador produce un archivo ejecutable a partir de los archivos objetos. Los archivos

ejecutables son aquellos que contienen código máquina y se pueden ejecutar directamente

por el sistema operativo. La extensión estos archivos es EXE o COM.

Al proceso de enlazado también se le suele llamar el proceso de linkado.

Paso 4: Ejecutarlo

El programa se puede ejecutar simplemente tecleando su nombre desde la línea de

comandos del sistema operativo.

Hoy día los compiladores de C son muy sofisticados e incluyen entornos integrados desde

los cuales se editan, compilan, enlazan, y es posible realizar una multitud de servicios más.

En algunos de ellos se pueden realizar los pasos de compilado, enlazado y ejecutado con la

pulsación de una sola tecla.

En Turbo C, se tiene las siguientes teclas relacionadas con este tema:

ALT-F9: Compilar a OBJ.

F9: Hacer archivo EXE

CTRL-F9: Ejecutar.

Se puede pulsar directamente CTRL-F9 para compilar, enlazar y ejecutar.

En programación, la experiencia es el gran maestro. Por ello es conveniente empezar a

hacer programas en C, cuanto antes. A continuación se van a presentar varios programas

completos en C, muy sencillos para ir familiarizándose en la programación de este

lenguaje.

/*****************************************************/ /********* PRIMER PROGRAMA C ************/ /*****************************************************/ #include <stdio.h>" main () { printf ("Hola mundo"); }

Page 10: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

10

La salida de este programa por pantalla es:

Hola mundo

Analizando a continuación este primer programa.

Los programas C, están compuestos de unidades de programa llamadas funciones, las

cuales son los módulos básicos del programa. En este caso, el programa está compuesto

por una sola función llamada main. Todos los programas C, deben tener una función main

(en español significa principal) pues es la primera función que se ejecuta cuando se hace

funcionar el programa. Los paréntesis que siguen a main identifican a ésta como nombre de

función. Un método de comunicación de datos entre funciones es el uso de argumentos.

Los argumentos son los datos que se les pasa a las funciones. Estos se encierran entre

paréntesis; main es una función sin argumentos, lo que se indica mediante ().

La línea con:

printf ("Hola mundo.");

Realiza una llamada a una función denominada printf, con el argumento “Hola mundo”;

printf es una función de biblioteca que realiza una escritura en la salida estándar.

Normalmente la salida estándar es el monitor.

La función printf escribe concretamente una cadena (conocido también con los nombres de

cadena de caracteres, constante de caracteres y string).

Una cadena es una secuencia de caracteres. Cada instrucción en C, termina con un punto y

coma. La línea del main () no va seguida de punto y coma porque no se trata de una

llamada a una función sino de la definición de una función. La definición de una función

específica las instrucciones que posee dicha función así como los argumentos que tiene.

Una función de librería printf está definida en el archivo stdio.h (standard input/output

header). Las funciones de librería son aquellas suministradas por el compilador y que están

a nuestra disposición. Para utilizar una función de librería es necesario incluir el

correspondiente archivo de cabecera antes de utilizarla. Cada archivo de librería incluye

muchas funciones. Por ejemplo, la librería stdio.h define funciones de entrada y salida

estándar. Pero en el archivo ejecutable de nuestro programa sólo están las funciones de

librería que se han utilizado. De esta forma el tamaño del código ejecutable se reduce al

mínimo.

Todas las líneas que empiezan con # no son en realidad instrucciones del lenguaje C, sino

que son líneas para ser manipuladas por el preprocesador. El preprocesador realiza algunas

tareas antes de empezar a actuar el compilador.

Por ejemplo La línea:

Page 11: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

11

#include <stdio.h>

Lo que hace es incluir la información que hay en el archivo stdio.h en este primer

programa.

En el archivo stdio.h se encuentra la definición de la función printf. Si no se pusiera este

include en nuestro programa, el compilador no sabría cómo es la función printf y daría

error.

A continuación se muestra un segundo ejemplo más complejo que el primero:

/**************************************************/ /******** SEGUNDO PROGRAMA C ********/ /*************************************************/ #include <stdio.h> main () { printf ("Segundo programa en C.\n"); printf ("Pulsa la tecla ENTER para terminar."); getch(); }

La salida por pantalla de este programa es:

Segundo programa en C.

Pulsa la tecla ENTER para terminar.

Analizando a continuación el segundo programa.

Hay dos novedades con respecto al primer ejemplo: la primera es la aparición del código \n

dentro de la cadena del primer printf. La segunda es la aparición de una nueva función de

librería: getch().

En C, todo lo que va entre comillas es una cadena. La secuencia \n es un caracter especial

que denota el caracter de nueva línea. Al ser \n un caracter se puede incluir en cualquier

parte de una cadena como cualquier otro caracter. En este programa, si se hubiese omitido,

la salida habría sido:

Segundo programa en C. Pulsa la tecla ENTER para terminar.

A todos los caracteres empezados por \ se les llaman secuencias de escape. Las secuencias

de escape son mecanismos para representar caracteres no imprimibles.

Page 12: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

12

Antes se vio la secuencia de escape \n que representaba a la nueva línea. Otras secuencias

de escape son \r para el retorno de carro, \t para el tabulador, \b para retroceso, \" para la

comilla, \' para el apóstrofe y \\ para la barra diagonal invertida.

Si nuestro primer programa lo ejecutamos desde un entorno integrado, en muchos de estos

entornos, a la finalización de la ejecución de este programa en C, la frase impresa

desaparece inmediatamente y se vuelve a la pantalla del entorno.

Todos estos entornos poseen mecanismos para visualizar la pantalla de ejecución.

En Turbo C, pulsando ALT-F5 se puede ver la pantalla de ejecución.

Una solución alternativa es incluir la función getch () al final de la función main ().

getch() es una función que espera la pulsación cualquier tecla por parte del usuario.

Esta función no necesita argumentos pero los paréntesis son necesarios puesto que se trata

de una función. getch() se encuentra en la librería stdio.h, por lo tanto, siempre que se

utilice esta función en un programa es necesario incluir la línea:

#include <stdio.h>

Último programa ejemplo de este capítulo.

/*************************************************************/ /****** TERCER PROGRAMA EN C *******/ /************************************************************/ #include <stdio.h> main () { int horas, minutos; horas = 3; minutos = 60 * horas; printf ("Hay %d minutos en %d horas.", minutos, horas);" getch(); }

La salida por pantalla de este programa es:

Hay 180 minutos en 3 horas.

Analizando a continuación este tercer programa.

En C, todo aquello que vaya entre un /* y un */ es ignorado. Las secuencias /* y */ denotan

el principio y el final de un comentario en C. Se deben utilizar comentarios en los

programas para hacerlos más comprensibles.

La línea: int horas, minutos; es una sentencia de declaración. En este caso se declaran dos

cosas:

Page 13: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

13

1) En algún sitio de la función se utilizarán las variables hora y minutos.

2) Estas dos variables son de tipo entero (integer)

El punto y coma final de la línea de declaración la identifican como una sentencia o

instrucción C.

También se podría haber escrito: int horas; int minutos;

Las variables son posiciones de memoria donde el valor de su contenido puede variar a lo

largo del programa. Se puede imaginar como cajas donde es posible meter cualquier cosa

que le venga bien a la caja.

En C, todas las variables utilizadas han de ser declaradas antes de su uso.

Las líneas horas= 3; minutos = 60 * horas;

son sentencias de asignación. La primera línea significa: dar a la variable horas el valor 3.

La segunda línea significa: dar a la variable minutos el resultado de multiplicar 60 por

horas. Nótese que las dos líneas terminan en punto y coma por ser dos sentencias o

instrucciones. En la línea int horas, minutos; se reserva espacio en memoria a las variables

horas y minutos. En las líneas hora = 3; minutos = 60 * horas; se les da valor a dichas

variables (al contenido de los espacios reservados). Posteriormente se les puede asignar a

estas variables valores diferentes. = es el operador de asignación y * es el operador de

multiplicación.

Otros operadores son: + (número positivo usado como operador unario y suma usado como

operador binario), - (número negativo usado como operador unario y substracción usado

como operador binario), / (operador de división), % (operador módulo, esto es, resto de la

división de dos números enteros).

En este momento, se mencionan estos operadores para empezar a hacer pequeños

programas. En lecciones posteriores se verán en detalle todos los operadores.

La línea printf ("Hay %d minutos en %d horas.", minutos, horas);

escribe: Hay 180 minutos en 2 horas.

Como se observa los dos %d no se han escrito y sin embargo se ha escrito en su lugar los

valores de las variables minutos y horas. El símbolo % avisa a la función printf que se va a

imprimir una variable en esta posición; la letra d informa que la variable a imprimir es

entera (digit).

printf significa escritura (print) con formato (format) porque nos permite formatear la

salida al gusto del ususario. La estructura de toda función C es:

{ declaración de variables sentencias }

Page 14: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

14

IMPORTANTE: La declaración de variables ha de ir al principio de la función, antes de la

primera sentencia ejecutable.

Con estos ejemplos lo que se ha pretendido es empezar a hacer programas completos en C

desde un primer momento, intentando ofrecer una visión global de éste.

Page 15: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

15

CAPÍTULO 2

OPERADORES Y EXPRESIONES DE C

En esta lección se hará un estudio completo sobre los tipos, operadores y expresiones del

lenguaje C. A modo de introducción se darán unas definiciones muy breves que serán

ampliadas a lo largo de toda la lección: Las variables y constantes son los objetos básicos

que se manipulan en un programa. Las declaraciones indican las variables que se van a

utilizar y establecen su tipo y, quizá su valor inicial. Los operadores especifican lo que se

va a hacer con ellas. Las expresiones combinan variables y constantes para producir

nuevos valores. Los programas funcionan con datos. Los datos son los números y los

caracteres que contienen la información a utilizar.

Objetivo particular 2

Identificar en un programa escrito en lenguaje C los operadores y expresiones que forman

parte de la sintaxis de dicho programa con la finalidad de aplicarlos en la solución de

problemas algebraicos simples utilizando los operadores lógicos y aritméticos, todo esto

en base a los elementos adquiridos en el capitulo anterior..

Una primera división de los datos se puede hacer en constantes y variables:

Las constantes son datos con valores fijos que no pueden ser alterados por el

programa.

Las variables son datos cuyo valor se puede cambiar a lo largo del programa.

Una segunda división de los datos se puede hacer según los tipos de que sean.

2.1 Tipos de datos

Existen cinco tipos de datos básicos en C:

Tabla 2.1 Tipos de datos

Tipo Descripción Longitud en bytes Rango char Carácter 1 0 a 255

int Entero 2 -32768 a 32767

float Flotante 4 -2147483648 a

2147483647

double flotante de doble precisión 8 -9223372036854775808 a

9223372036854775807

void sin valor 0 -

Page 16: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

16

La longitud en bytes, y por consiguiente, también el rango, de la tabla anterior, dependen de

cada tipo de procesador y de cada compilador de C. No obstante, la información reseñada

en la tabla es correcta para la mayoría de los ordenadores.

Ejemplos de asignación de variable tipo char:

char ch1, ch2; /* declaración de las variables ch1 y ch2 */" ch1 = 'A'; /* a la variable ch1 se le asigna el valor ascii de 'A': 65 */" ch2 = 65; /*a la variable ch2 se le asigna el código ASCII 65 que es 'A'*/"

Las dos asignaciones anteriores son equivalentes pero es preferible la primera asignación

porque es más portátil. A ch1 se le asigna en cualquier ordenador el carácter 'A'. Sin

embargo, a la variable ch2, en sistemas basados en código ASCII se le asigna el carácter 'A'

(el código ASCII de 65 es 'A'), y en sistemas basados en código EBCDIC se le asigna un

caracter distinto a 'A'. Todas las variables en C han de ser declaradas antes de poder ser

usadas. La forma general de declaración es la siguiente:

tipo lista_variables;

Aquí, tipo debe ser un tipo de datos válido de C y lista_variables puede consistir en uno o

más nombres de identificadores separados por comas. Las declaraciones deben estar antes

de la primera sentencia ejecutable. Ejemplos de declaraciones:

int i, j, k; char caracter;"

Los identificadores en C, son los nombres usados para referenciar las variables, las

funciones y otros objetos definidos por el usuario. Los nombres de los identificadores están

compuestos por letras, dígitos y el caracter de subrayado. El número de caracteres

significativos de los identificadores depende del compilador. El primer caracter de un

identificador ha de ser letra o el caracter de subrayado.

En Turbo C, el número de caracteres significativos por defecto es 32. Ciertos caracteres no

imprimibles se representan como constantes de caracter mediante secuencias de escape. A

continuación se muestran las secuencias de escape del ANSI C:

Código Significado \b retroceso

\f salto de página

\n nueva línea

\r retorno de carro

\t tabulación horizontal

\" comillas (")

Page 17: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

17

\' apóstrofe (')

\0 carácter nulo

\\ barra invertida (\)

\v tabulación vertical

\a alerta (bell, campanilla)

\ddd constante octal (ddd son tres dígitos como máximo)

\xddd constante hexadecimal (ddd son tres dígitos como máximo)

Hay otros caracteres no imprimibles que no tienen correspondencia en la tabla anterior.

Estos caracteres se pueden utilizar mediante los códigos \ddd, \xddd o simplemente usando

el número del código ASCII.

Ejemplo de asignaciones equivalentes:

char ch1, ch2, ch3, ch4; /*declaración de cuatro variables tipo caracter */ ch1 = '\n'; /* el caracter '\n' es el número 13 en ASCII */ ch2 = 13; /* 13 decimal <=> 12 octal <=> A hexadecimal */ ch3 = '\12'; /* también sería válido: ch3 = '\012'; */ ch4 = '\xA'; /* también sería válido: ch4 = '\xa'; */

La notación preferida es la primera. Aunque para los caracteres no imprimibles que no

tienen correspondencia en la tabla anterior, la única solución es una de las tres últimas

asignaciones del ejemplo.

Tipo entero

Es un número sin parte fraccionaria. Las constantes enteras se pueden escribir de uno de los

tres modos siguientes:

En decimal: escribiendo el número sin empezar por 0 (a excepción de que sea el

propio 0). Ejemplos: 1, 0, -2.

En hexadecimal: empezando el número por 0x. Ejemplos: 0xE, 0x1d, 0x8.

En octal: empezando el número por 0. Ejemplos: 02, 010.

Tipos Float y Double

Las constantes de este tipo tienen parte real y parte fraccionaria. El tipo double tiene doble

precisión que el tipo float. Por lo demás, los dos tipos son iguales. La sintaxis correcta de

las constantes de estos dos tipos es: [signo] [dígitos] [.] [dígitos] [exponente] [signo]

dígitos]

Donde:

signo es + o -;

dígitos es una secuencia de dígitos;

. es el punto decimal;

exponente es E o e.

Page 18: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

18

Los elementos que están entre [] son opcionales, pero el número no puede empezar por e o

E, ya que el compilador lo interpretaría en este caso como un identificador y no como un

número. Algunos ejemplos de constantes de este tipo: 1.0e9, -3E-8, -10.1.

Tipo void

Significa sin valor, sin tipo. Uno de los usos de void se puede observar al comparar estos

dos programas:

#include <stdio.h> #include <stdio.h> main () void main (void) { { printf ("Versión 1."); printf ("Versión 2."); getch (); getchar (); } }

Al poner void entre los paréntesis de la definición de una función, se define a ésta como

función que no tiene argumentos. No confundir con llamada a función, en cuyo caso no se

puede utilizar el void. Del mismo modo, al poner void antes del nombre de la función en la

definición de ésta, se declara como una función que no devuelve nada.

La segunda versión es preferible y es la que se utilizar.

/***********************************************************/ /********** PROGRAMA DE EJEMPLO 4 ***********/ /***********************************************************/ #include <stdio.h> void main (void) { int i = 1; char c = 'c'; float f = 1.0; double d = 1e-1; printf (" i = %d\n c = %c\n f = %f\n d = %lf\n", i, c, f, d); getch (); }

La salida de este programa es:

i = 1 c = c f = 1.000000 d = 0.100000

Como se puede observar en el programa, se puede asignar un valor a una variable en el

momento de la declaración.

Page 19: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

19

En la lección 1 ya se dijo que %d indica a la función printf el lugar en que se ha de escribir

una variable de tipo entera. Los códigos %c, %f y %lf indican a la función printf el lugar

en la cadena de caracteres en la que se han de escribir variables de tipo char, float y double

respectivamente.

2.2 Modificadores

A excepción del tipo void, los tipos de datos básicos pueden tener varios modificadores

precediéndolos. Hay modificadores de tipo y de acceso.

Modificadores de acceso

Un modificador de tipo se usa para alterar el significado del tipo base para que se ajuste

más precisamente a las necesidades de cada momento. Modificador Descripción Tipos a los

se les puede aplicar el modificador

signed con signo int, char

unsigned sin signo int, char

long largo int, char, double

short corto int, char

El uso de signed con enteros es redundante aunque está permitido, ya que la declaración

implícita de entero asume un número con signo. El estándar ANSI elimina el long float por

ser equivalente al double. Sin embargo, como se puede observar en el último ejemplo visto,

para escribir un double con la función printf es necesario utilizar el código de formato de

printf: %lf; que significa: long float. Se puede utilizar un modificador de tipo sin tipo; en

este caso, el tipo se asume que es int. La longitud (y por tanto, también el rango) de los

tipos dependen del sistema que se utilice, no obstante, la siguiente tabla es válida para la

mayoría de sistemas:

Page 20: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

20

Tabla 2.2 tipos de variables y sus asignaciones

Tipo Longitud en bytes Rango char 1 Caracteres ASCII

unsigned char 1 0 a 255

signed char 1 -128 a 127

int 2 -32768 a 32767

unsigned int 2 0 a 65535

signed int 2 Igual que int

short int 1 -128 a 127

unsigned short int 1 0 a 255

signed short int 1 Igual que short int

long int 4 -2147483648 a 2147483649

signed long int 4 -2147483648 a 2147483649

unsigned long int 4 0 a 4294967296

float 4 Aproximadamente 6 dígitos de

precisión

double 8 Aproximadamente 12 dígitos de

precisión

long double 16 Aproximadamente 24 dígitos de

precisión

Modificadores de acceso

También hay otra clase que son los modificadores de acceso. Como su propio nombre

indica, estos modificadores modifican el acceso a los tipos.

Estos modificadores son:

Tabla 2.3 Modificadores de acceso

Modificador Descripción const constante

volatile volátil

Las variables de tipo const son aquellas a las que se les asigna un valor inicial y este valor

no puede ser cambiado a lo largo del programa. Se utilizan para declarar constantes.

Ejemplo de declaración de una constante:

const unsigned int hola;

Las variables de tipo volatile previenen al compilador que dicha variable puede ser

cambiada por medios no explícitamente especificados en el programa.

Page 21: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

21

Algunas sentencias de C:

int v; v = 1; v = 2;

En estos casos, los compiladores suelen optimizar el código y la primera sentencia de

asignación se desecha y no se genera código para ella ya que es redundante. Si se hubiese

declarado la variable v como volatile:

volatile v;

la optimización descrita no se realizaría sobre la variable v, generándose código para las

dos asignaciones.

En C, existen tipos derivados. Los tipos derivados son aquellos, que como su propio

nombre indica, derivan de los tipos básicos.

A continuación se estudiará un tipo derivado muy común en C: las cadenas de caracteres.

Cadenas de caracteres

Una cadena de caracteres (también conocido por el nombre de string) es una secuencia de

caracteres encerrados entre comillas.

Ejemplos de cadenas:

"El amor es como la luna: cuando no crece es que mengua."

"abc"

"a"

"\n a \n b \n c \n"

Las comillas no forman parte de la secuencia. Sirven para especificar el comienzo y final

de ésta, al igual que los apóstrofes marcaban los caracteres individuales.

Las cadenas son tratadas por el C, como un array de caracteres.

Un array (conocido también con el nombre de vector) es una secuencia de datos que se

encuentran almacenados en memoria de una forma consecutiva.

Un array de caracteres es una secuencia de caracteres.

El array:

"abc"

se almacenaría en memoria como:

a b c \0

Page 22: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

22

El caracter '\0' se llama caracter nulo, y es utilizado por el C, para marcar el final de la

cadena en memoria.

El caracter nulo ('\0') no es la cifra 0 (cuyo código ASCII es 48), sino un caracter no

imprimible, cuyo código ASCII es 0.

Ejemplo:

void main (void) { char ch1, ch2, ch3, ch4; ch1 = '\0'; /* en memoria, ch1 tiene el valor 0 que es el valor ASCII*/ /* correspondiente al caracter '\0' */ ch2 = 0; /* en memoria, ch2 tiene el valor 0*/ ch3 = '0'; /* en memoria, ch3 tiene el valor 48 que es el valor ASCII */ /* correspondiente al caracter '0' */ ch4 = 48; /* en memoria, ch4 tiene el valor 48 */ }

Es importante destacar que en este programa no se ha puesto: #include <stdio.h>. Esto se

debe a que nuestro programa no utiliza ninguna información contenida en dicha librería.

En las asignaciones anteriores, a ch1 y ch2 se les asigna el caracter nulo, pero a las

variables ch3 y ch4 se le asigna el caracter cero. Teniendo en cuenta el caracter nulo en la

cadena "abc", esta cadena es un array de tamaño 4 (tres caracteres m s el caracter nulo).

Obsérvese el siguiente programa.

#include<stdio.h> void main (void) { printf ("\nInvertir en conocimientos produce siempre los mejores intereses. \n(%s)", "Benjamín Franklin"); }

La salida de este programa en pantalla es la siguiente:

Invertir en conocimientos produce siempre los mejores intereses.

Benjamín Franklin

En este ejemplo se puede observar la aparición de dos elementos nuevos: la división de una

cadena de caracteres en varias líneas y el código de formato %s.

El código %s le indica a la función printf que escriba una cadena en su lugar. Una cadena

de caracteres se puede escribir en varias líneas de archivo cerrando las comillas al final de

la línea y volviéndolas a abrir en la línea siguiente. Haciéndolo de este modo, el compilador

lo interpreta como una sola cadena de caracteres escrita en varias líneas. En C, los finales

de instrucciones no se detectan con los finales de línea sino con puntos y comas al final de

cada instrucción.

Page 23: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

23

2.3 Operadores

Los operadores en C se pueden dividir en cuatro grupos:"

a) Operadores aritméticos.

b) Operadores relacionales y lógicos.

c) Operadores a nivel de bits.

d) Operadores especiales.

Los operadores aritméticos realizan operaciones aritméticas. Son los siguientes:

Operador Acción - Resta, también menos monario

+ Suma, también suma monario

* Multiplicación

/ División

% División en módulo

-- Decremento

++ Incremento

Tabla 2.3 Operadores aritméticos

Los operadores de incremento y decremento solo se pueden aplicar a variables, no

constantes. El de incremento añade 1 a su operando y el de decremento resta 1. En otras

palabras, ++x; o x++; es lo mismo que x = x + 1; y --x; o x--; es lo mismo que x = x - 1;

Los operadores de incremento y decremento pueden preceder o seguir al operando. Si el

operador precede al operando, C lleva a cabo la operación antes de utilizar el valor del

operando. Si el operador sigue al operando, C utiliza su valor antes de incrementarlo o

decrementarlo. Esto se ve muy bien en los dos ejemplos siguientes:

int x, y; int x, y; x = 2; x = 2; y = ++x; y = x++; /* ahora x tiene el valor 3 /* ahora x tiene el valor 3 e y tiene el valor 3 */ e y tiene el valor 2 */

Los operadores del mismo nivel de precedencia son evaluados por el compilador de

izquierda a derecha. Se puede alterar el orden de evaluación utilizando paréntesis.

Page 24: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

24

Ejemplo:

void main (void) { int x1, x2, x3, x4, x5, x6; /* Asignaciones */ /* Orden de asignaciones */ x1 = 2 + 3 * 4; /* x1 = 14; */ x2 = (2 + 3) * 4; /* x2 = 20; */ x3 = -4 - (-1); /* x3 = -3; */ x4 = 10 / 2 % 3; /* x4 = 2; */ x5 = ++x3 - x4; /* x3 = -2; x5 = -4; */ x6 = x3++ - x4; /* x6 = -4; x3 = -1; */ x1 = -x1; /* x1 = -14; */ x2 = (x1 + x2) / x3; /* x2 = -6; */ x3 = ((x1++) + (x2++)) - x3; /* x3 = -19; x1 = -13; x2 = -5; */ x4 = -(-(-x3)); /* x4 = 19; */ x5 = (x6 * x6 + x6 / x6); /* x5 = 17; */ x6 = (x1++) + (++x2) - (++x6); /* x2 = -4; x6 = -3; x6 = -14; x1 = -12; */ x1++; /* x1 = -11; */ --x2; /* x2 = -5; */ }

2.4 Operadores relacionales y lógicos

La palabra relacional se refiere a la relación entre unos valores y otros. La palabra lógico se

refiere a las formas en que esas relaciones pueden conectarse entre sí.

Los operadores se basan en la idea de cierto (true en inglés) y falso (false en inglés). En C,

cualquier valor distinto de cero es cierto, y el valor 0 es falso. Las expresiones que son

ciertas toman el valor de 1 y las que son falsas toman el valor de 0.

Los operadores son:

Operadores relacionales Operadores lógicos

Operador Acción Operador Acción

> Mayor que && Y

>= Mayor o igual que || O

< Menor que ! NO

<= Menor o igual que

== Igual

!= No igual

Tabla 2.4 Operadores aritméticos y lógicos

Page 25: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

25

Ejemplo:

void main (void) { int x1, x2, x3, x4, x5, x6;" /* Asignaciones */ /* Orden de asignaciones */ x1 = 10 < 12; /* x1 = 1; */ x2 = 10 > 12; /* x2 = 0; */ x3 = -1 && 5; /* x3 = 1; */ x4 = 0 || x3; /* x4 = 1; */ x5 = x1 >= x2 <= x3; /* x5 = 1; */ x6 = x1 == x2 || x3 != x4; /* x6 = 0; */ x1 = !x1; /* x1 = 0; */ x2 = ! (!x1 || x3 <= x3); /* x2 = 0; */ x3 = 1 && 0; /* x3 = 0; */ x4 = 1 || 0; /* x4 = 1; */ x5 = !(-10); /* x5 = 0; */ x6 = !!x4; /* x6 = 1; */ }

Una particularidad interesante del C es que la evaluación de una expresión se termina en

cuanto se sabe el resultado de dicha expresión.

2.5 Operadores a nivel de bits

Estos operandos realizan operaciones sobre los bits de un byte o una palabra (dos bytes).

Solo se pueden utilizar con los tipos char e int. Estos operadores son:

Operador Acción & Y

| O

^ O exclusiva (XOR)

~ Complemento (NOT)

>> Desplazamiento a la derecha

<< Desplazamiento a la izquierda

Tabla 2.5 operadores logicos a nivel de bits

Los operadores relacionales y lógicos siempre producen un resultado que es 0 ó 1, mientras

que las operaciones entre bits producen cualquier valor arbitrario de acuerdo con la

operación específica. En otras palabras, las operaciones a nivel de bits pueden dar valores

distintos de 0 ó 1, pero los operadores lógicos siempre dan 0 ó 1.

Page 26: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

26

Ejemplo:

char x, y, z1, z2;

x = 2; y = 3;

z1 = 2 && 3;

z2 = 2 & 3; /* z1 = 1; z2 = 2 */

¿Porqué‚ (2 && 3) es 1 y (2 & 3) es 2?

2&&3: el compilador evalúa la expresión 1 && 1 que es 1.

2&3: el compilador evalúa 00000010 & 00000011 que es 00000010 (2 en decimal)

Sintaxis para los operadores de desplazamiento:

expresión >> número de bits a desplazar a la derecha

expresión << número de bits a desplazar a la izquierda

Dos observaciones sobre los operadores de desplazamiento:

1) Un desplazamiento no es una rotación. O sea, los bits que salen por un extremo no se

introducen por el otro.

2) Normalmente, a medida que se desplaza los bits hacia un extremo se va rellenando con

ceros por el extremo opuesto. PERO NO EN TODOS LOS ORDENADORES ES ASI.

Page 27: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

27

CAPÍTULO 3

SENTENCIAS DE CONTROL

En este capítulo se estudiara las sentencias de control que posee el C entre las que se

encuentran las condicionales if y switch; las sentencias iterativas while, for y do; y las

sentencias break, y return, entre las más importantes.

Objetivo particular 3:

Se empleará todas las sentencias que posee el C para controlar el flujo del programa.

Primero se estudiará a través de diagramas de flujo las principales sentencias de control,

entre las que se encuentran las condicionales if y switch; las sentencias iterativas while, for

y do; y las sentencias break, y return, todo esto con la finalidad de elaborar programas que

realicen calculos de álgebra lineal simples y conduzcan a las tecnicas de diseño de

algoritmos de control del robot scara.

Una sentencia en C puede ser:

printf ("Filosofía de Murphy: Sonría; mañana puede ser peor."); y = 4 + 1; /* sentencia de asignación */ ; /* sentencia que no hace nada */

Una sentencia compuesta:

{ /* sentencia compuesta formada por dos sentencias simples */ --x; printf ("Ley de Murphy: Si algo puede salir mal, saldrá mal."); } { } /* sentencia que no hace nada */

Las sentencias if, switch, while, for y do son sentencias simples. Todas estas sentencias

serán estudiadas en esta lección. Una sentencia compuesta está formada por ninguna, una o

varias sentencias simples delimitadas entre llaves. A las sentencias compuestas también

reciben el nombre de bloques. Las sentencias simples son todas aquéllas que no son

compuestas.

La mayoría de las sentencias de control de cualquier lenguaje están basadas en condiciones.

Una condición es una expresión cuya resolución da como resultado cierto

(true) o falso (false). Muchos lenguajes de programación incorporan los valores true y

false; C cualquier valor distinto de cero es true, y el valor cero es false.

Page 28: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

28

3.1 Sentencias condicionales

C posee dos sentencias condicionales: if y switch. Estas dos sentencias permiten hacer

algoritmos con toma de decisión bajo argumentos de tipo condición, es decir, bifurcar en un

programa a partir de una o más condiciones.

Existen dos tipos de sentencias como se mencionó, la primera es la if que permite bifurcar

bajo una sola condición. Mientras que la secuencia switch es para multiples condiciones.

Sentencia if if ( expresión )

sentencia

o

if (expresión) sentencia_1 else sentencia_2

Si expresión es cierta se ejecuta la sentencia correspondiente al if. Si expresión es falsa se

ejecuta la sentencia correspondiente al else si lo hay. En la segunda sintaxis se ejecuta

sentencia_1 o sentencia_2, pero nunca ambas.

Ejemplos:

if (contador < 50) if (x < y) if (ch == '\n')

Al ser la sentencia if una sentencia simple, la sentencias if se pueden anidar:

/*

A la variable numero_menor se le asigna la

variable con menor valor entre x, y, z

*/

if (x <= y) if (x <= z) numero_menor = x; else numero_menor = z; else if (y <= z) numero_menor = y; else numero_menor = z;

El else siempre está asociado al if más cercano. Los dos siguientes ejemplos son distintos: /**** Ejemplo 1: ****/ if (n > 0) if (a > b) z = a;

Page 29: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

29

else z = b;

/**** Ejemplo 2: ****/ if (n > 0) { if (a > b) z = a; } else z = b;

Sentencia switch switch (expresión) { case expresión_constante_1: sentencias_1 break; case expresión_constante_2: sentencias_2 break; case expresión_constante_3: sentencias_3 break; . . . default: sentencias_n }

Una expresión constante es una expresión en la que todos los operandos son constantes.

El switch evalúa expresión. A continuación evalúa cada una de las expresiones constantes

hasta que encuentra una que coincida con expresión. Cuando la encuentra ejecuta las

sentencias correspondientes a ese case. Si no hay ninguna expresión case que coincida con

expresión, se ejecuta las sentencias correspondientes al default.

Ejemplo:

switch (operando) { case 1: x=x * y; break; case 2: x=x / y; break; case 3: x=x + y; break; case 4: x=x- y; break;

Page 30: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

30

default: printf ("ERROR"); }

Observaciones

1) La sentencia default es opcional. Si fallan todas las comprobaciones de los case y no hay

default, no se ejecuta ninguna acción en el switch. Incluso el default puede ir en cualquier

posición y no obligatoriamente al final.

2) Las sentencias break en el switch son opcionales. El break hace que se produzca una

salida inmediata de la instrucción switch. Si no hay una sentencia break en un case, al

ejecutarse las sentencias que corresponden a ese case, también se ejecutarían las sentencias

correspondientes al siguiente case y así sucesivamente hasta encontrar un break o llegar al

final del switch. La sentencia break puede ir en cualquier sitio, no forzosamente al final de

las sentencias de los case.

3.2 Sentencias iterativas

Los bucles o sentencias iterativas permiten que un conjunto de instrucciones sea ejecutado

hasta que se alcance una cierta condición. Las sentencias iterativas son: while, for y do.

Sentencia while

Sintaxis

while (expresión) sentencia

Descripción

Se evalúa expresión. Si es cierta, se ejecuta sentencia y se vuelve a evaluar expresión. El

ciclo continúa hasta que expresión es falsa, momento en que la ejecución continúa con lo

que está después de sentencia.

Ejemplo:

While(conta<10) { gotoxy(10,10); printf(“El contador es:%d”,conta);

conta++; delay(300);

}

En este ejemplo el valor del contador se incrementa y despliega en la pantalla mientras sea

menor de 10. La función gotoxy manda poner la variable conta en la posición 10, 10 y la

función delay es un función de retardo y su argumento está dado en milisegundos, es decir,

para este caso el retardo es de 0.3 de segundo.

Page 31: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

31

Sentencia for

for (expresión_1; expresión_2; expresión_3) sentencia

Descripción

En la sentencia for, a expresión_1 se le llama inicialización, a expresión_2 se le llama

condición, y a expresión_3 se le llama incremento.

Ejemplo:

#include <stdio.h>

void main (void) { int i;

for(i=0;i<100;i++) { printf(“Variable i=%d”,i); } }

Observación

La instrucción:

for (;;)

sentencia; es un bucle infinito. Sin embargo, aunque en este bucle no es posible salir por la

condición del for, se puede salir por otros medio (por ejemplo, mediante la sentencia

break.)

Sentencia do

Sintaxis

do

sentencia

while (expresión);

En la instrucción do, primero se ejecuta sentencia y a continuación se evalúa expresión. En

caso de ser cierta, se ejecuta sentencia de nuevo y así sucesivamente. La iteración termina

cuando la expresión se convierte en falsa.

EJEMPLO: Imprime los 50 primeros números naturales

Page 32: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

32

#include <stdio.h>

void main (void) { int i = 1; do { printf ("%d ", i++); } while (i <= 50); }

Observación

Las llaves en el ejemplo anterior no son necesarias al tratarse de una sola sentencia; pero en

el caso de la sentencia do, es recomendable que siempre se ponga las llaves para hacer el

programa más legible (para el lector, no para el compilador).

En esta lección se han estudiado las mas importantes sentencias de control de programa que

posee el C. Entre ellas se incluyen los constructores de bucles while, for y do, las sentencias

condicionales if y switch.

Page 33: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

33

CAPÍTULO 4

FUNCIONES BASICAS

Este capítulo describe el manejo de las funciones básicas de entrada y salida para hacer

algunos programas básicos e introducirse en el campo de las funciones que en otros

lenguajes de cómputo son conocidas como subrutinas. El material de este capítulo solo

presenta algunas funciones como: printf, scanf, kbhit, exit y getch; Con la finalidad de

conocer el uso de las funciones y al mismo tiempo entender la filosofía del lenguaje C para

ser capaces de crear funciones propias en el siguiente capítulo.

Objetivo particular 4 Emplear las funciones de control de programa, de entrada, salida y de consola con el fin

de introducirse en el uso de funciones estandar.

4.1 Funciones de control de programa

En la lección anterior se vieron las sentencias de control de programa: if switch, while, for,

do.

A continuación se estudiarán las funciones que pueden afectar al flujo de control de un

programa; esta funcion es: exit();

Función exit ()

La función exit, que se encuentra declarada en la biblioteca estándar (stdlib.h), da lugar a la

terminación automática de un programa. Al describir una función siempre hay que

especificar los argumentos y el valor que devuelve si los hay. La función exit no devuelve

nada pero necesita un argumento que es recogido por el programa llamador (normalmente

el sistema operativo). Por convención, el valor 0 indica terminación normal; valores

distintos de 0 indican situaciones anormales.

En los programas que manipulan archivos, éstos han de abrirse, manipularse y cerrarse. Los

datos de estos archivos no se manipulan directamente sino a través de unos

almacenamientos temporales llamados buffers. La función exit cierra todos los archivos

abiertos, vacía todos los buffers de salida.

Page 34: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

34

4.2 Funciones de E/S

Se llaman funciones de entrada/salida (input/output), abreviado funciones de E/S (I/O), a

aquéllas que transportan datos entre el programa y la entrada y salida estándar.

La entrada estándar normalmente es el teclado y la salida estándar normalmente es la

consola. Mientras no se diga lo contrario, se considera la entrada estándar como el teclado y

la salida estándar como la consola.

El final de la entrada y salida se suele marcar (en el caso de archivos de texto ocurre

siempre) con un carácter especial llamado Fin-De-Archivo y se simboliza "EOF" (End-Of-

File). Hay una constante definida en el archivo stdio.h que se llama EOF y tiene el valor de

-1. El caracter de fin de archivo se suele escribir con CONTROL-Z (código ASCII 26) en el

DOS y CONTROL-D en UNIX. Algunas funciones del C (por ejemplo, scanf) devuelven el

valor de EOF cuando leen el caracter de marca de fin de archivo.

En las operaciones de E/S, los datos utilizados suelen pasar por buffers. Un buffer es una

cantidad de memoria utilizada para meter y sacar datos.

Tras estos preliminares ya estamos en condiciones de ver las principales funciones de E/S:

printf, scanf, putchar, getchar, puts y gets.

Funciones printf () y scanf ()

La función printf escribe datos formateados en la salida estándar. La función scanf lee datos

formateados de la entrada estándar. El término "con formato" se refiere al hecho de que

estas funciones pueden escribir y leer datos en varios formatos que están bajo su control.

Ambas funciones están declaradas en el archivo stdio.h, y tienen la forma general:

printf ("cadena de control", lista de argumentos);

scanf ("cadena de control", lista de argumentos);

La cadena de control está formada por caracteres imprimibles y códigos de formato. Debe

haber tantos códigos de formato como argumentos. Los códigos u órdenes de formato son

las siguientes:

Código Formato %c Simple caracter

%d Entero decimal con signo

%e Punto flotante en notación científica: [-]d.ddd e [+/-]ddd

%f Punto flotante en notación no científica: [-]dddd.ddd

%s Cadena de caracteres

%x Entero hexadecimal sin signo

%p Puntero

Tabla 4.1 Formato de los principales tipos de variables

Page 35: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

35

Las órdenes de formato pueden tener modificadores. Estos modificadores van entre el % y

la letra que identifica el código. Si el modificador es un número, especifíca la anchura

mínima en la que se escribe ese argumento. Si ese número empieza por 0, los espacios

sobrantes (si los hay) de la anchura mínima se rellenan con 0. Si ese número tiene parte real

y parte fraccionaria, indica el número de dígitos de la parte real y de la parte fraccionaria a

imprimir en el caso de imprimir un número, o indica el número mínimo y máximo a

imprimir en el caso de imprimir una cadena de caracteres. Por defecto, la salida se justifica

a la derecha en caso de que se especifique anchura mínima; si el modificador es un número

negativo, la justificación se hará a la izquierda. Otros dos modificadores son las letras l y

h; el primero indica que se va a imprimir un long, y h indica que se va a imprimir un short.

En la explicación de los modificadores se ha hablado de imprimir, es decir, se ha hablado

del printf. Los modificadores de scanf son los mismos.

Después de esta parrafada veamos unos ejemplos prácticos.

Ejemplos:

Sentencia printf () Salida

(":%f:", 123.456) :123.456001: (":%e:", 123.456) :1.234560e+02: (":%g:", 123.456) :123.456: (":%-2.5f:", 123.456) :123.45600: (":%-5.2f:", 123.456) :123.46: (":%5.5f:", 123.456) :123.45600: (":%10s:", "hola") :hola: (":%-10s:", "hola") :hola : (":%2.3s:", "hola") :hola: (":%x:", 15) :f: (":%o:", 15) :17: (":%05d:", 15) :00015: (":abc:%n", &var_int) :abc: (a demás la variable var_int toma el valor de 5)

Hay una diferencia muy importante entre los argumentos de printf y scanf. En printf los

argumentos son expresiones pero en scanf los argumentos han de ser direcciones de

memoria (punteros).

Los punteros se van a estudiar en un capítulo posterior. No obstante, hablaremos en este

momento un poco de ellos para saber utilizar la función scanf.

Los punteros hemos dicho que son direcciones de memoria. Para obtener la dirección de

memoria de una variable es necesario aplicar el operador monario & (no confundirlo con el

operador binario, que es el and entre bits) de la siguiente forma:

& variable

Page 36: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

36

Hay un tipo de variable un poco especial a este respecto, que son los vectores (también

llamados arrays), cuyo nombre es un puntero que apunta al primer elemento del vector.

Ahora mismo se pretende saber cómo usar la función scanf, no los punteros, que es tema de

otro capítulo lección; por cierto, el tema de los punteros es, quizás, una de los más difíciles

del C.

Ejemplo de cómo usar la función scanf

scanf ("%d %s %f", &variable_entera, cadena_de_caracteres, &variable_float);

Programa ejemplo:

/******************************************************************************************** Programa que lee números enteros de teclado hasta que se introduce un 0. El programa no es muy útil pero sí instructivo. ********************************************************************************************/ #include <stdio.h> /* para poder utilizar la función scanf */ void main (void) { int x; do { scanf ("%d", &x); } while (x != 0); }

Las llamadas a funciones son expresiones y como el resultado de evaluar una expresión es

un valor (a no ser que el resultado de la expresión sea de tipo void), las funciones pueden

devolver valores y la llamada a esa función toma el valor devuelto por la función.

Suponiendo que f() es una función que devuelve un entero, entonces, las siguientes

expresiones son correctas:

int x, y, z;

x = f ();

y = f () * 2;

f ();

(void) f ();

z = f () + f ();

if (f () < 0)

printf ("ERROR");

La función printf devuelve un valor entero que contiene el número de caracteres escritos.

En caso de error, devuelve EOF.

Page 37: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

37

4.3 Funciones de consola

Las funciones de consola que se describirán no están definidas en el estándar ANSI, ya que

son funciones, que por su propia naturaleza, dependen del entorno fijado y en gran parte no

son portátiles. Sin embargo, estos tipos de funciones tienen una importancia primordial a la

hora de crear un software de calidad.

Todo lo que se diga sobre estas funciones es válido para los dos compiladores de C más

importantes: el de Microsoft y el de Borland. Si utilizas otro compilador distinto a los

anteriores, es probable que los nombres de las funciones coincidan con las que vamos a ver,

en caso contrario, estas funciones tendrán otros nombres.

Las características de consola específicas de Borland sólo se estudian si la opción turbo

está en modo on.

Todas las funciones, y en general toda la información, de consola, están recogidas en la

librería <conio.h> (consola input/output). En esta lección vamos a ver diez funciones de

esta librería: cprintf, cscanf, putch, getch, getche, ungetch, cputs, cgets y kbhit

La función cprintf es similar a la función printf. Lo mismo sucede con los pares de

funciones: cscanf-scanf, cputs-puts, putch-putchar, getch-getchar, getche-getchar, cputs-

puts y cgets-gets.

Las diferencias entre estos pares de funciones se muestran en la tabla:

Funciones de E/S estándar Funciones de E/S de consola Se escribe en la salida estándar Se escribe en pantalla

Se lee de la salida estándar Se lee de teclado

Se escribe y lee a través de buffers No utiliza buffers

Para pasar a la línea siguiente es suficiente

escribir el caracter de nueva línea: '\n'

Para pasar a la línea siguiente hay que

escribir los caracteres de nueva línea y el

de retorno de carro: '\n' y '\r'

Tabla 4.2 funciones de entrada y salida

Consecuencia de estas diferencias:

1) Las funciones de escritura de conio.h siempre escriben en pantalla. Las funciones de

escritura de stdio.h normalmente escriben en pantalla, pero si se redirige la salida

(esto se puede hacer al ejecutar el programa mediante los símbolos >, >> o |) ya no

escribe en pantalla. Lo mismo se puede decir de las funciones de lectura y el

teclado.

2) En los programas interactivos no quedan bien cuando se trabaja con buffers. Si has

visto los ejemplos de lecciones anteriores, getchar lee un caracter, pero lo lee una vez

que se ha pulsado la tecla ENTER; además lo caracteres leídos hasta pulsar la tecla

ENTER se mantienen en el buffer para ser leídos posteriormente. Esto queda muy mal

en los programas interactivos. Las funciones getch y getche, que las estudiaremos un

poco más adelante, lee caracteres inmediatamente, es decir, tras pulsar la tecla.

Page 38: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

38

2) Las funciones de escritura estándar siempre escriben en pantalla con los colores

blanco sobre negro. Las funciones de escritura de consola escriben con cualquier

atributo de pantalla.

Función kbhit ()

La función kbhit devuelve un valor cierto (distinto de cero) si hay una tecla disponible y

falso (0) si no la hay.

Ejemplo:

#include <conio.h>

void main (void)

{

float numero = 0;

printf ("Pulsa cualquier tecla para finalizar.");

do{

numero++;

}while(!kbhit());

getch ();

}

Este programa incrementa en uno a la variable numero hasta que es presionada una tecla.

Page 39: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

39

CAPÍTULO 5

VARIABLES Y FUNCIONES

Este capítulo trata el tema de las funciones creadas por el usuario, su relación con las

variables que formaran parte del argumento de dichas funciones. La idea central de este

estudio es proporcionar al alumno en el campo fascinante de cómo crear las funciones y

emplearlas en un programa de control.

Objetivo particular 5:

Diseñar funciones de lenguaje C propias utilizando variables locales y globales.

Los puntos son:

Declaración y definición de variables y funciones.

Tipos de variables según el lugar de la declaración: variables locales, parámetros

formales y variables globales.

Especificadores de clase de almacenamiento: extern, static, register y auto

Reglas de ámbito de las funciones.

Los programas en C, al menos que sean muy simples, en cuyo caso estarían compuestos

sólo por la función main, están formados por varias funciones.

5.1 Declaración de funciones

La forma general de una función en el estándar ANSI actual es: especificador_de_tipo

nombre_de_la_funcion (lista_de_declaraciones_de_parametros)

{

cuerpo_de_la_funcion

}

especificador_de_tipo es el tipo del valor que devuelve la función, si es void, la función no

devuelve ningún valor, si no se pone se supone que la función devuelve un entero;

lista_de_declaraciones_de_parametros es una lista de declaraciones separadas por comas

donde cada declaración consta de tipo y nombre de parámetro; cuerpo_de_la_funcion es

una lista de sentencias C, incluso puede no haber ninguna: 'nada () {}' en cuyo caso la

función no hace nada (ser útil como un lugar vacío durante el desarrollo de un programa);

lista_de_parametros es una lista de nombres de parámetros separados por comas;

declaracion_de_los_parametros consiste en especificar el tipo de los parámetros.

Page 40: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

40

Ejemplo:

#include <stdio.h> /* Función declarada según la forma del estándar ANSI */ void funcion_1 (int numero_1_funcion_1, int numero_2_funcion_1) { printf ("\n%d + %d = %d", numero_1_funcion_1, numero_2_funcion_1," numero_1_funcion_1 + numero_2_funcion_1);" } void main (void) { int numero_1_funcion_main = 2, numero_2_funcion_main = 3;" funcion_1 (numero_1_funcion_main, numero_2_funcion_main);" funcion_1 (numero_1_funcion_main, numero_2_funcion_main);" }

La salida de este programa es:

2 + 3 = 5

2 - 3 = -1

El funcionamiento de este ejemplo parece claro. Hay una observación importante que hacer

acerca del mismo: Si la función main se hubiera definido antes de las funciones funcion_1

y funcion_2, el compilador al procesarlas llamadas a funcion_1 y funcion_2 no sabe que

tipo son dichas funciones y nos puede informar de un error o asumir que devuelven un

entero. Es bueno declarar todas las funciones a utilizar (excepto main) antes de su

definición para evitar problemas de este tipo. El ejemplo anterior se escribiría de la

siguiente forma:

#include <stdio.h> void funcion_1 (int numero_1_funcion_1, int numero_2_funcion_1); void funcion_2 (int numero_1_funcion_2, int numero_2_funcion_2); void main (void) { int numero_1_funcion_main = 2, numero_2_funcion_main = 3; funcion_1 (numero_1_funcion_main, numero_2_funcion_main); funcion_1 (numero_1_funcion_main, numero_2_funcion_main); } /* Función declarada según la forma del estándar ANSI */ void funcion_1 (int numero_1_funcion_1, int numero_2_funcion_1) { printf ("\n%d + %d = %d", numero_1_funcion_1, numero_2_funcion_1, numero_1_funcion_1 + numero_2_funcion_1); }

Page 41: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

41

En las declaraciones (no en las definiciones que son las descripciones completas de las

funciones) explícito suprimir el nombre de los parámetros, así que también se podría haber

hecho:

void funcion_1 (int, int); void funcion_2 (int, int);

e incluso también:

void funcion_1 (int, int), funcion_2 (int, int);

Al igual que se declaran las variables. A las declaraciones de las funciones también se les

llama prototipos.

5.2 Valores devueltos

Todas las funciones, excepto aquéllas del tipo void, devuelven un valor. Este valor se

especifíca explícitamente en la sentencia return y si no existe ésta, el valor es 0.

La forma general de return es:

return expresión;

Tres observaciones sobre la sentencia return:"

1) La sentencia return tiene dos usos importantes. Primero, fuerza a una salida inmediata

de la función, esto es, no espera a que se llegue a la última sentencia de la función para

acabar. Segundo, se puede utilizar para devolver un valor.

2) return no es una función sino una palabra clave del C, por lo tanto no necesita

paréntesis como las funciones, aunque también es correcto: return (expresión); pero

teniendo en cuenta que los paréntesis forman parte de la expresión, no representan una

llamada a una función.

3) En las funciones de tipo void se puede hacer: return; y de esta forma se provoca la

salida inmediata de la función.

Ejemplo:

#include <stdio.h> int maximo (int, int); long potencia (int, int); void main (void) { int a = 2, b = 3, c = 4, d = 5; printf ("\n%d elevado a %d es %d.\n", c, d, potencia(c, d)); }

Page 42: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

42

long potencia (int pa, int pb) { int i; long pot = 1; for (i = 1; i <= pb; i++) pot =pot* pa; return pot; }

La salida de este programa es:4 elevado a 5 es 1024.

5.3 Tipos de variables

Existen tres lugares básicos donde se pueden declarar variables: dentro de funciones, en la

definición de parámetros de funciones y fuera de las funciones. Estas variables son,

respectivamente, variables locales, parámetros formales y variables globales.

Variables locales

Son aquéllas que se declaran dentro de una función. Estas variables se declaran al principio

de un bloque de código, se destruyen al llegar al final del bloque de código y sólo puede ser

utilizada (ya que sólo tiene existencia) dentro de ese bloque. Recuerda que un bloque de

código empieza con una llave abierta y termina con una llave cerrada.

Ejemplos:

void f1 (void) { int x; /* se reserva memoria para x */ x = 10; /* se le asigna un valor */ } /* se libera la memoria asignada a x */ void f2 (void) { int x = 1; /* se reserva memoria para x */ /* sentencias */ { int y = 2; /* se reserva memoria para y */ /* sentencias */ } /* se libera memoria asignada a y */ /* sentencias */ /* en ese punto no existe la variable y */ } /* se libera memoria asignada a x */ void f3 (void) { int x, y; /* se reserva memoria para las variables x e y */

x = 1; /* se asigna 1 a la variable x */

y = x; /* se asigna x (1) a la variable y */

Page 43: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

43

{ /* comienzo de un bloque de código */ int x; /* se reserva memoria para x; ‚ésta es distinta a la anterior */ x = 2; /* se asigna 2 a la variable x de este bloque */ y = x; /* se asigna x (2) a la variable y */ } /* se libera memoria asignada a la variable x de este bloque */ y = x; /* se asigna x (1) a la variable y */ } /* se libera memoria asignada a las variables x e y */

Si una función va a usar argumentos, entonces debe declarar las variables que van a aceptar

los valores de esos argumentos. Estas variables son los parámetros formales de la función.

Se comportan como cualquier otra variable local de la función.

Variables globales

A diferencia de las variables locales, las variables globales se conocen a lo largo de todo el

programa y se pueden usar en cualquier parte de código. Además, mantienen su valor

durante toda la ejecución del programa. Las variables globales se crean al declararlas en

cualquier parte fuera de una función.

Ejemplo:

void f1 (void), f2 (void), f3 (void); int x; void main (void) { f1 (); f2 (); f3 (); } void f1 (void) { x = 10; } void f2 (void) { x = 11; } void f3 (void) { int x; /* esta variable x es local, es distinta a la global */ x = 12; /* se le asigna x a la variable x local, no a la global */ }

Page 44: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

44

5.5 Especificadores de clase de almacenamiento

Existen cuatro especificadores de clase de almacenamiento soportados por C. Son: extern,

static, register y auto.

Se usan para indicar al compilador cómo se debe almacenar la variable que le sigue. El

especificador de almacenamiento precede al resto de la declaración de variable. Su forma

general es:

especificador_de_almacenamiento tipo nombre_de_variable;

Extern

Consideremos los dos siguientes ejemplos:

int a; /* definición de una variable */ extern int b; /* declaración de una variable */

En la primera sentencia estamos definiendo una variable de tipo entero llamada a. En la

segunda sentencia se está declarando una variable de tipo entero llamada b. En la definición

de una variable se reserva un espacio de memoria para una variable. La declaración le

indica al compilador que esa variable está o será definida en otra parte, pero no reserva

memoria para ella. Así pues, una variable sólo se puede definir una vez pero se puede

declarar todas las veces que se desee.

El principal uso de extern se da cuando un programa está compuesto de varios archivos y

tenemos una variable global a varios de ellos.

Static

Las variables globales son variables permanentes. Tienen dos significados diferentes

dependiendo si son locales o globales.

Variables estáticas locales

La diferencia con las variables locales normales es que su contenido no se pierde al salirse

de la función, de tal manera que al volver a entrar en la función, la variable estática tiene el

mismo valor que el que tenía cuando terminó la función en la llamada anterior. La variable

estática sólo es inicializada en la primera llamada a la función.

Ejemplo:

#include <stdio.h> void f1 (void), f2 (void); void main (void) {

Page 45: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

45

f1 (); f1 (); f2 (); f2 (); } void f1 (void) { static int x = 1; printf ("\nx = %d", x); x++; } void f2 (void) { int y = 1; printf ("\ny = %d", y); y++; }

La salida de este programa es:

x = 1

x = 2

y = 1

y = 1

Variables estáticas globales

Cuando se aplica el modificador static a una variable global, se indica al compilador que

cree una variable global conocida únicamente en el archivo en el que se declara la variable

global static. Esto significa que, aunque la variable es global, las rutinas de otros archivos

no la reconocerán ni alternarán su contenido directamente; así, no esta sujeta a efectos

secundarios.

5.6 Register

El especificador register pide al compilador de C que mantenga el valor de las variables

definidas con ese modificador en un registro de la CPU en lugar de en memoria, que es

donde se almacenan normalmente las variables.

Varias observaciones:

1) El acceso a los registros de la CPU es mucho más rápido que el acceso a la memoria.

2) Las variables register se almacenan en los registros si se puede, si no, se almacenan en

memoria.

3) Las variables register sólo pueden ser de tipo int y char, y además han de ser locales no

estáticas o parámetros de función.

4) En la mayoría de los sistemas sólo se permiten una o dos variables register al mismo

tiempo. En la práctica, se declaran variables register aquéllas que se utilizan como índices

en los bucles."

Page 46: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

46

Ejemplo:

/* esta función calcula la potencia de dos números enteros */ int pot_ent (int base, int exponente) { register temporal = 1; for (; exponente; exponente--) temporal *= base; return temporal; }

5.7 Auto

Las variables auto (automáticas) son todas aquellas variables locales que no son estáticas.

En la práctica, este especificador de clase de almacenamiento no se utiliza nunca, ya que

todas las variables locales que no llevan el especificador static son consideradas auto.

Page 47: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

47

CAPÍTULO 6

ARREGLOS DE MEMORIA

Este capítulo trata el tema de arreglos de memoria, es decir, localidades de memoria que se

agrupan y pueden ser accesados en forma indexada. Este tipo de variables se les conoce

como vectores. Estos pueden ser arreglos de n dimensiones. Para el caso exclusivo de este

curso se emplean estos arreglos para guardar valores numéricos que representan las

posiciones del brazo del robot, esto con el fin de memorizar los datos en un conjunto que se

denominarán PATHS del movimiento. (El módulo de mecatrónica aplicada estudiará con

aplicaciones directas en el robot con mayor detalle.)

Objetivo particular 6

Realizar operaciones de álgebra lineal utilizando arreglos de una y dos dimensiones para

guardar en dichos arreglos los datos correspondientes a posiciones del robot.

6.1 Conjunto ordenado de variables (arrays)

Los arreglos o conjuntos de datos ordenados (arrays) recolectan variables del MISMO tipo,

guardándolas en forma secuencial en la memoria. La cantidad máxima de variables que

pueden albergar está sólo limitada por la cantidad de memoria disponible. El tipo de las

variables involucradas puede ser cualquiera de los ya vistos, con la única restricción de que

todos los componentes de un array deben ser del mismo tipo.

La declaración de un array se realiza según la siguiente sintaxis:

tipo de las variables nombre[ cantidad de elementos];

Por ejemplo:

int var1[10]; char nombre[50]; float numeros[200]; long double cantidades[25];

Si en el primer caso, se declara un array de 10 variables enteras, cada una de ellas quedará

individualizada por el subíndice que sigue al nombre del mismo es decir:

var1[0], var1[1], etc, hasta var1[9].

Nótese que la CANTIDAD de elementos es 10, pero su numeración va de 0 a 9, y no de 1 a

10. En resumen un array de N elementos tiene subíndices válidos entre 0 y N - 1. Cualquier

otro número usado como subíndice, traerá datos de otras zonas de memoria, cuyo contenido

no es conocido.

Page 48: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

48

Se puede referenciar a cada elemento, en forma individual, tal como se ha hecho con las

variables anteriormente, por ejemplo:

var1[5] = 40; contador = var1[3] + 7; if(var1[0] >>= 37)

También es posible utilizar como subíndice expresiones aritméticas, valores enteros

retornados por funciones, etc. Así podría escribir:

printf(" %d ", var1[ ++i] ); var1[8] = var1[ i + j ]; ............................... int una_funcion(void); var1[0] = var1[ una_funcion() ] * 15;

Por supuesto los subíndices resultantes de las operaciones tienen que estar acotados a

aquellos para los que el array fue declarado y ser enteros. La inicialización de los arrays

sigue las mismas reglas que vi para los otros tipos de variables, es decir: Si se declaran

como globales (afuera del cuerpo de todas las funciones) cada uno de sus elementos será

automáticamente inicializado a cero. Si en cambio, su declaración es local a una función,

no se realiza ninguna inicialización, quedando a cargo del programa cargar los valores de

inicio.

La inicialización de un array local, puede realizarse en su declaración, dando una lista de

valores iniciales:

int numero[8] = { 4, 7, 0, 0, 0, 9, 8, 7 };

Obsérvese que la lista está delimitada por llaves. Otra posibilidad, sólo válida cuando se

inicializan todos los elementos del array, es escribir:

int numero[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Donde se obvia la declaración de la cantidad de elementos, ya que está implícita en la lista

de valores constantes. También se puede inicializar parcialmente un array, por ejemplo:

int numero[10] = { 1, 1, 1 };

En éste caso los tres primeros elementos del mismo valdrán 1, y los restantes cero en el

caso que la declaración sea global, o cualquier valor impredecible en el caso de que sea

local.

Page 49: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

49

6.2 Conjunto ordenado de caracteres (strings)

Los strings son simplemente arrays de caracteres, con el agregado de un último elemento

constante: el caracter NULL ( ASCII == 0, simbolizado por la secuencia de escape \0 ).

Este agregado permite a las funciones que procesan a los mismos determinar fácilmente la

finalización de los datos. Podemos generar un string, declarando:

char car_str[] = { 'A', 'B', 'C', 'D', 0 }; char car_str[] = { 'A', 'B', 'C', 'D', '\0' };

Ambas maneras son equivalentes. Sin embargo hay, en el lenguaje C, una forma más

compacta de declararlos:

char car_str[] = "ABCD"; char car_str[5] = "ABCD"; int texto[] = "renglon 1 \n renglon 2 \n "; /* ERROR */ unsigned char texto[] = "renglon 1 \n renglon 2 \n ";

Simplemente en la declaración del mismo se encierran los caracteres que lo componen

entre comillas. Obsérvese que en la segunda declaración, se ha explicitado (no es

necesario), la cantidad de elementos que tiene el string, y es uno más que la cantidad de

caracteres con que se inicializa, para dejar lugar al NULL. Todas estas declaraciones

agregan automáticamente el NULL como último elemento del array.

Un caso interesante es el de la tercer línea (comentada como ERROR ), con el fin de poder

albergar al caracter "\n"20( ASCII 179 ) se intentó asignar el string a un array de enteros,

Esto no es permitido por el compilador, que lo rechaza como una asignación inválida.

La razón de ello se verá más adelante cuando se analicen punteros, ya que el string

constante usado como value es un puntero a char, y no a int. La solución más común para

este caso es, declarar el array como unsigned char, con lo que se lleva el alcance de sus

elementos a 255. Para el caso de tener que albergar en un string el caracter EOF ( -1 ) y al

mismo tiempo caracteres con ASCII mayor que 127, se podría definir el array como int,

pero su inicialización se tendrá que hacer obligatoriamente usando llaves, como se vio

anteriormente. Se deduce entonces, de lo antedicho que un string sigue siendo un array de

caracteres, con la salvedad del agregado de un terminador, por lo que las propiedades que

se estudiarán a continuación, se aplicarán indistintamente a ambos.

6.3 Arrays y strings como argumentos de funciones

Los arrays, como todos los otros tipos de variables, pueden ser pasados como argumentos a

las funciones. Vea esquemáticamente como sería la sintaxis:

double funcion_1(float numeros[10], char palabra[]); /*linea 1*/ main() /*linea 2*/ { float numeros[10] = { 1.1, 2.2, 3.0 }; /*linea 3*/

Page 50: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

50

char palabra[] = " Lenguaje C "; /*linea 4*/ double c; /*linea 5*/ c = funcion_1( numeros, palabra ) /*linea 6*/ } double funcion_1( float numeros[10], char palabra[])/*linea 7*/

Es necesario analizar con mucho detenimiento, este último ejemplo. En la primer línea se

declara el prototipo de funcion_1 () que recibe como argumentos dos arrays, uno de 10

elementos del tipo float, y otro de caracteres de longitud indeterminada.

En el primer caso la función necesitará saber de alguna manera cual es la longitud del array

numérico recibido, mientras que en el segundo, no hace falta, ya que la función puede ser

construida para que, por sí misma, detecte la finalización del string por la presencia del

caracter NULL. Se podría generalizar más el programa declarando:

double funcion_1( double numeros[], int longitud_array, char palabra[]);

En donde, en la variable longitud_array se enviaría la cantidad de elementos de numero[].

En la tercer línea se declara el array numérico, inicializándose sólo los tres primeros

elementos, y en la cuarta línea se declara el string. En la séptima línea se da la definición de

la función, de acuerdo al prototipo escrito anteriormente. Si al mirar con detenimiento la

sexta línea, el llamado a la función, se nota que los argumentos pasados sólo tienen el

NOMBRE de ambos arrays. Esta es la diferencia más importante entre este tipo de

estructura de datos y las variables simples vistas anteriormente, ya que los arrays son

pasados a las funciones por DIRECCION y no por valor.

En el lenguaje C se prefiere, para evitar el uso abusivo del stack, cuando hay que enviar a

una función una larga estructura de datos, en lugar de copiar a todos ellos, cargar el stack

sólo con la dirección de la posición de memoria donde está ubicado el primero. El nombre

de un array equivale sintácticamente a la dirección del elemento cero así será:

numero == dirección de numero[0] palabra == direccion de palabra[0]

Esto habilita a las funciones a que puedan acceder a los arrays directamente, allí donde el

programa los ha ubicado en la memoria, por lo que pueden MODIFICARLOS EN FORMA

PERMANENTE aunque no hayan sido declarados como locales a la función misma ni

globales al programa.

Es muy importante recordar este último concepto, a fin de evitar errores muy comunes, en

los primeros intentos de programación en C. Otra característica importante de los arrays es

que, su nombre (o dirección del primer elemento) es una CONSTANTE y no una variable.

El nombre de los arrays implican para el compilador el lugar de memoria donde empieza la

estructura de datos por lo que, intentar cambiar su valor es tomado como un error, así si

escribiera por ejemplo:

Page 51: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

51

char titulo[] = "Primer titulo";

.................................... titulo = "subtitulo";

La primer sentencia es correcta, ya que esta inicializando al string, pero la segunda

produciría un error del tipo " LVALUE REQUERIDO ", es decir que el compilador espera

ver, del lado izquierdo de una expresión, a una variable y en cambio se ha encontrado con

una constante título (o sea la dirección de memoria donde está almacenada la P de "Primer

título"). Esto al compilador le suena similar a una expresión de la clase: 124 = j y se niega

rotundamente a compilarla.

6.4 Arrays multidimensionales.

Las estructuras de datos del tipo array pueden tener más de una dimensión, es bastante

común el uso de arrays "planos" o matriciales de dos dimensiones, por ejemplo:

int matriz[ número total de filas ] [ número total de columnas ]; Si declara: int matriz[3][4];

esquemáticamente la disposición "espacial" de los elementos seria:

columnas: 0 1 2 3

filas 0 [0][0] [0][1] [0][2] [0][3] matriz[0][]

1 [1][0] [1][1] [1][2] [1][3] matriz[1][]

2 [2][0] [2][1] [2][2] [2][3] matriz[2][]

Por supuesto, aunque menos usados, se pueden generar arrays de cualquier número de

dimensiones. Para inicializar arrays multidimensionales, se aplica una técnica muy similar

a la ya vista, por ejemplo para dar valores iniciales a un array de caracteres de dos

dimensiones, se escribirá:

char dia_de_la_semana[7][8] = { "lunes", "martes", " miercoles", "jueves", "viernes", "sábado", "domingo" };

En este caso el elemento [0][0] será la "l" de lunes, el [2][3] la "r" de miércoles, el [5][2]

la "b" de sábado, etc. Nótese que los elementos [0][5], [1][6],etc están inicializados con el

caracter NULL y demás [0][6] y [0][7], etc no han sido inicializados. Si le parece que en

Page 52: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

52

este párrafo se nos escapó un error, está equivocado, lo que ocurre es que se olvidó de

contar los índices desde 0. Este último ejemplo también podría verse como un array

unidimensional de strings.

Page 53: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

53

CAPÍTULO 7

PUNTEROS

Este capítulo trata el complejo tema de los punteros en el Lenguaje C, son variables que

"apuntan", es decir que poseen la dirección de las ubicaciones en memoria de otras

variables, y por medio de ellos se tendrá un poderoso método de acceso a todas ellas.

Quizás este punto es el más conflictivo del lenguaje, ya que muchos programadores en

otros idiomas, y novatos en C, lo ven como un método extraño o al menos

desacostumbrado, lo que les produce un cierto rechazo. Sin embargo, y en la medida que

uno se va familiarizando con ellos, se convierten en la herramienta más cómoda y directa

para el manejo de variables complejas, argumentos, parámetros, etc, y se empieza a

preguntar como es que hizo para programar hasta aquí, sin ellos. La respuesta es que no lo

ha hecho, ya que se han usado en forma encubierta, sin decir lo que eran. ( Perdón por el

pequeño engaño ).

Objetivo particular 7

Utilizar los apuntadores de lenguaje C para llevar los datos de memoria RAM a memoria

fija en disco, con la finalidad de respaldar la información de las posiciones del robot.

7.1 Declaración de variables tipo puntero

Se verá primero, como se declara un puntero:

tipo de variable apuntada *nombre_del_puntero; int *pint; double *pfloat; char *letra, *codigo, *caracter;

En estas declaraciones sólo se dice al compilador que reserve una posición de memoria

para albergar la dirección de una variable, del tipo indicado, la cual será referenciada con el

nombre que se haya dado al puntero.

Obviamente, un puntero debe ser inicializado antes de usarse, y una de las eventuales

formas de hacerlo es la siguiente:

int var1; /* declaro ( y creo en memoria ) una variable entera ) */ int *pint; /* " " " " " un puntero que contendrá la dirección de una variable entera */ pint = &var1; /* escribo en la dirección de memoria donde está el puntero la dirección de la variable entera */

Page 54: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

54

Como se anticipó en temas anteriores " &nombre_de_una_variable " implica la dirección

de la misma. De cualquier manera es siempre obvio, en el contexto del programa el uso de

los mismos.

Esquemáticamente, se puede simbolizar de la siguiente manera: donde dentro del recuadro

está el contenido de cada variable.

Pint xxxxxx valor contenido por var1

Dirección de var1

yyyyyy (posición de memoria xxxxxx (posición de memoria

ocupada por el puntero ) ocupada por la variable)

En realidad, como se abordará más adelante, en la declaración del puntero, está implícita

otra información: cual es el tamaño (en bytes) de la variable apuntada. El símbolo &, o

dirección, puede aplicarse a variables, funciones, etc, pero no a constantes o expresiones,

ya que éstas no tienen una posición de memoria asignada. La operación inversa a la

asignación de un puntero, de referenciación del mismo, se puede utilizar para hallar el valor

contenido por la variable apuntada. Así por ejemplo serán expresiones equivalentes:

y = var1; y = *pint; printf("%d", var1 ); printf("%d", *pint);

En estos casos, la expresión " *nombre_del_puntero ", implica " contenido de la variable

apuntada por el mismo ". Vea un corto ejemplo de ello:

#include <stdio.h> main() { char var1; /*una variable del tipo caracter */ char *pchar; /* un puntero a una variable del tipo caracter */ pc = &var1; /*asigna al puntero la dirección de la variable */ for (var1 = 'a'; var1 <<= 'z'; var1++) printf("%c", *pchar); /* imprime el valor de la variable apuntada */ return 0; }

Se ve, que en el FOR se incrementa el valor de la variable, y luego para imprimirla usa la

de referencia de su puntero. El programa imprimirá las letras del abecedario de la misma

manera que lo habría hecho si la sentencia del printf() hubiera sido, printf("%c", var1 )

Hay un error, que se comete con bastante frecuencia, y es cargar en la dirección apuntada

por un puntero a un tipo dado de variable, el contenido de otro tipo de las mismas, por

ejemplo:

Page 55: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

55

double d = 10.0; int i = 7, *pint; pint = &i; *pint = 10; /* correcto, equivale a asignar a i el valor 10 */; *pint = d; /* ERROR se pretende cargar en una variable entera un valor double */ pint = &d; /* INCORRECTO se pretende apuntar a una variable double con un puntero declarado como apuntador a int */ pint = 4358; /* ?????? */

El primer error, la asignación de un double, produce la pérdida de información dada por la

conversión automática del tipo de variable, ya vista anteriormente, el segundo produce un

llamado de atención rotulado como " asignación sospechosa de un pointer ". Resumiendo,

las variables o constantes cargadas por diferenciación de un puntero, deben coincidir en

tipo con la declaración de aquel.

La asignación de una constante a un pointer o puntero, y no a la variable apuntada por él, es

un serio error ya que debe ser el compilador, el encargado de poner en él el valor de la

dirección, aquel así lo declara dando un mensaje de "conversión de puntero no

transportable ". Si bien lo compila, ejecutar un programa que ha tenido esta advertencia es

similar a jugar a la ruleta rusa, puede "colgarse" la máquina o lo que es peor destruirse

involuntariamente información contenida en un disco, etc.

Hay un sólo caso en el que esta asignación de una constante a un puntero es permitida,

muchas funciones para indicar que no pueden realizar una acción o que se ha producido un

error de algún tipo, devuelven un puntero llamado "Null Pointer", lo que significa que no

apunta a ningún lado válido, dicho puntero ha sido cargado con la dirección NULL ( por lo

general en valor 0 ), así la asignación: pint = NULL; es válida y permite luego operaciones

relacionales del tipo if( pint )..... o if( print != NULL ) para convalidar la validez del

resultado devuelto por una función.

Una advertencia: si bien se retomará más adelante sobre este tema, se debe desde ahora

tener en cuenta que los punteros no son enteros, como parecería a primera vista, ya que el

número que representa a una posición de memoria, sí lo es. Debido al corto alcance de este

tipo de variable, algunos compiladores pueden, para apuntar a una variable muy lejana, usar

cualquier otro tipo, con mayor alcance que el antedicho.

7.2 Punteros y arrays

Hay una relación muy cercana entre los punteros y los arrays. Ya vi previamente que el

designador (nombre de un array ) era equivalente a la dirección del elemento [0] del

mismo. La explicación de esto es ahora sencilla: el nombre de un array, para el compilador

C, es un PUNTERO inicializado con la dirección del primer elemento del array. Sin

embargo hay una importante diferencia entre ambos, que se hace notar más abajo. Ahora se

ven algunas operaciones permitidas entre punteros:

Page 56: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

56

7.3 Asignación

float var1, conjunto[] = { 9.0, 8.0, 7.0, 6.0, 5.0 );

float *punt;

punt = conjunto; /* equivalente a hacer: punt = &conjunto [0] */

var1 = *punt;

*punt = 25.1;

Es perfectamente válido asignar a un puntero el valor de otro, el resultado de ésta operación

es cargar en el puntero punt la dirección del elemento [0] del array conjunto, y

posteriormente en la variable var1 el valor del mismo (9.0) y para luego cambiar el valor de

dicho primer elemento a 25.1.

Observar cual es la diferencia entre un puntero y el denominador de un array: la primera es

una VARIABLE, es decir que puedo asignarlo, incrementarlo etc., en cambio el segundo es

una CONSTANTE, que apunta siempre al primer elemento del array con que fue declarado,

por lo que su contenido NO PUEDE SER VARIADO. Si lo piensa un poco, es lógico, ya

que "conjunto" implica la dirección del elemento conjunto [0], por lo que, si yo cambiara su

valor, apuntaría a otro lado dejando de ser, "conjunto". Desde este punto de vista, el

siguiente ejemplo nos muestra un tipo de error bastante frecuente:

ASIGNACIÓN ERRONEA

int conjunto[5], lista[] = { 5, 6, 7, 8, 0 ); int *apuntador; apuntador=lista; /* correcto */ conjunto=apuntador; /*ERROR(se requiere en Lvalue no constante )*/ lista = conjunto; /* ERROR ( idem ) */ apuntador=&conjunto; /* ERROR no se puede aplicar el operador & (dirección) a una constante */

A continuación las distintas modalidades del incremento de un puntero:

INCREMENTO O DECREMENTO DE UN PUNTERO int *pint, arreglo_int[5]; double *pdou, arreglo_dou[6]; pint = arreglo_int; /* pint apunta a arreglo_int[0] */ pdou = arreglo_dou; /* pdou apunta a arreglo_dou[0] */ pint += 1; /* pint apunta a arreglo_int[1] */ pdou += 1; /* pdou apunta a arreglo_dou[1] */ pint++; /* pint apunta a arreglo_int[2] */ pdou++; /* pdou apunta a arreglo_dou[2] */

Page 57: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

57

Se han declarado y asignado dos punteros, uno a int y otro a double, con las direcciones de

dos arrays de esas características. Ambos estarán ahora apuntando a los elementos [0] de

los arrays. En las dos instrucciones siguientes se incrementan en uno dichos punteros.

¿Adónde apuntaran hora?.

Para el compilador, estas sentencias se leen como: incremente el contenido del puntero

(dirección del primer elemento del array) en un número igual a la cantidad de bytes que

tiene la variable con que fue declarado. Es decir que el contenido de pint es incrementado

en dos bytes (un int tiene 2 bytes) mientras que pdou es incrementado 8 bytes ( por ser un

puntero a double ), el resultado entonces es el mismo para ambos, ya que luego de la

operación quedan apuntando al elemento SIGUIENTE del array, arreglo_int[1] y

arreglo_dou[1].

De ésta manera será muy fácil "barrer" arrays, independientemente del tamaño de variables

que lo compongan, permitiendo por otro lado que el programa sea transportable a distintos

tipos de hardware sin preocuparse de la diferente cantidad de bytes que pueden asignar los

mis, a un dado tipo de variable.

De manera similar las dos instrucciones siguientes, vuelven a incrementarse los punteros,

apuntando ahora a los elementos siguientes de los arrays Todo lo dicho es aplicable, en

idéntica manera, al operador de decremento --.

7.4 Aritmética de punteros

Debido a que los operadores * y ++ ó -- tienen la misma precedencia y se evalúan de

derecha a izquierda, y los paréntesis tienen mayor precedencia que ambos, muchas

operaciones que los utilizan en conjunto a todos estos operadores, pueden parecer poco

claras y dar origen a un sinnúmero de errores:

int *p, a[] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }; int var; p = a;

A partir de aquí, el puntero está apuntando a a[0]. Ver las distintas variantes que puede

tener la siguiente instrucción:

*p = 27;

La más sencilla de las opciones, simplemente se asigna al elemento apuntado por p ( a[0]

) un valor constante. Vea la inversa de ella:

var = *p;

var sería asignada al valor 0 (contenido de a[0]), y p seguiría apuntando al mismo elemento.

¿Qué hubiera pasado, si en vez de ello se hubiera escrito?

var = *( p + 1 );

Page 58: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

58

Se podría traducir el sentido de la operación como: cargue var con el contenido del

elemento siguiente al apuntado por p ( a[1] ). Lo interesante de remarcar acá es que p, en sí

mismo, NO VARIA Y LUEGO DE ESTA SENTENCIA SEGUIRA APUNTANDO A

a[0]. De la misma forma: var = *( p + 3 ) asignará 30 a var, sin modificar el contenido de p

En cambio la expresión:

var = *( p++ );

Poder leerla como: asigna el valor de lo apuntado por p y LUEGO incrementa éste para que

apunte al próximo elemento. Así en var quedaría 0 (valor de a[0] ) y p apuntaría finalmente

a a[1]. Si en vez de esto hubiera preincrementado a p tendría:

var = *( ++p );

la que puede leerse como: apunte con p al próximo elemento y asigne a var con el valor de

éste. En este caso var sería igualada a 10 ( a[1] ) y p quedaría apuntando al mismo. En las

dos operaciones anteriores los paréntesis son superfluos ya que al analizarse los operadores

de derecha a izquierda, daría lo mismo escribir:

var = *p++; /* sintácticamente igual a var = *(p++) */ var = *++p; /* " " " var = *(++p) */

La aritmética más frecuentemente usada con punteros son las sencillas operaciones de

asignación, incremento o decremento y diferenciación. Todo otro tipo de aritmética con

ellos está prohibido o es de uso peligroso o poco transportable. Por ejemplo no está

permitido, sumar, restar, dividir, multiplicar, etc, dos apuntadores entre sí. Lo cual es

bastante lógico, ya que de nada me serviría sumar dos direcciones de memoria, por

ejemplo.

Otras operaciones están permitidas, como la comparación de dos punteros, por ejemplo (

punt1 == punt2 ) o ( punt1 < punt2 ) sin embargo este tipo de operaciones son

potencialmente peligrosas, ya que con algunos modelos de pointers pueden funcionar

correctamente y con otros no.

7.5 Punteros y variables dinámicas

El ámbito o existencia de las variables, la menos duradera de ellas era la del tipo local a una

función, ya que nacía y moría con ésta. Sin embargo, esto es algo relativo, en cuanto a la

función main(), ya que sus variables locales ocuparán memoria durante toda la ejecución

del programa.

Para un caso típico, se debe recibir una serie de datos de entrada, del tipo double, y

procesar según un determinado algoritmo a aquellos que aparecen una o más veces con el

mismo valor.

Si no se está seguro de cuántos datos van a ingresar a nuestro programa, póngase alguna

limitación, suficientemente grande a los efectos de la precisión requerida por el problema,

diga 5000 valores como máximo, debe definir entonces un array de doubles capaz de

Page 59: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

59

albergar a cinco mil de ellos, por lo que el mismo ocupará del orden de los 40 k de

memoria.

Si se define este array en main(), ese espacio de memoria permanecerá ocupado hasta el fin

del programa, aunque luego de aplicarle el algoritmo de cálculo ya no se le necesite más,

comprometiendo seriamente la disponibilidad de memoria para albergar a otras variables.

Una solución posible sería definirlo en una función llamada por main() que se ocupará de

llenar el array con los datos, procesarlos y finalmente devolviera algún tipo de resultado,

borrando con su retorno a la masiva variable de la memoria.

Sin embargo en C existe una forma más racional de utilizar los recursos de memoria de

manera conservadora. Los programas ejecutables creados con estos compiladores dividen la

memoria disponible en varios segmentos, uno para el código ( en lenguaje máquina ), otro

para albergar las variables globales, otro para el stack ( a través del cual se pasan

argumentos y donde residen las variables locales ) y finalmente un último segmento

llamado memoria de apilamiento o amontonamiento ( Heap ).

El Heap es la zona destinada a albergar a las variables dinámicas, es decir aquellas que

crecen ( en el sentido de ocupación de memoria ) y decrecen a lo largo del programa,

pudiéndose crear y desaparecer (desalojando la memoria que ocupaban) en cualquier

momento de la ejecución

Vea cual sería la metodología para crearlas; suponga primero que quiere ubicar un único

dato en el Heap, se define primero un puntero al tipo de la variable deseada:

double *p;

Notar que esta declaración no crea lugar para la variable, sino que asigna un lugar en la

memoria para que posteriormente se guarde ahí la dirección de aquella. Para reservar una

cantidad dada de bytes en el Heap, se efectúa una llamada a alguna de las funciones de

librería, dedicadas al manejo del mismo. La más tradicional es malloc() ( su nombre deriva

de memory allocation ), a esta función se le da como argumento la cantidad de bytes que se

quiere reservar, y nos devuelve un pointer apuntando a la primer posición de la "pila"

reservada. En caso que la función falle en su cometido ( el Heap está lleno ) devolverá un

puntero inicializado con NULL.

p = malloc(8);

Se ha pedido 8 bytes ( los necesarios para albergar un double ) y he asignado a p el retorno

de la función, es decir la dirección en el Heap de la memoria reservada.

Como es algo engorroso recordar el tamaño de cada tipo variable, agravado por el hecho de

que, si reserva memoria de esta forma, el programa no se ejecutará correctamente, si es

compilado con otro compilador que asigne una cantidad distinta de bytes a dicha variable,

es más usual utilizar sizeof, para indicar la cantidad de bytes requerida:

p = malloc( sizeof(double) );

Page 60: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

60

En caso de haber hecho previamente un uso intensivo del Heap, se debería averiguar si la

reserva de lugar fue exitosa:

if( p == NULL ) rutina_de_error();

Si no lo fue estas sentencias me derivan a la ejecución de una rutina de error que tomará

cuenta de este caso. Por supuesto podría combinar ambas operaciones en una sola,

if( ( p = malloc( sizeof(double) ) ) == NULL ) { printf("no hay mas lugar en el Heap..... Socorro !!" ); exit(1); }

Se ha reemplazado aquí la rutina de error, por un mensaje y la terminación del programa,

por medio de exit() retornando un código de error.

Si ahora quisiera guardar en el Heap el resultado de alguna operación, sería tan directo

como,

*p = a * ( b + 37 );

y para recuperarlo, y asignarlo a otra variable bastaría con escribir:

|var = *p;

7.6 Punteros a strings

No hay gran diferencia entre el trato de punteros a arrays, y a strings, ya que estos dos son

entidades de la misma clase. Sin embargo analice algunas particularidades. Así como

inicializa un string con un grupo de caracteres terminados en '\0', pode asignar al mismo un

puntero:

p = "Esto es un string constante ";

Esta operación no implica haber copiado el texto, sino sólo que a p se le ha asignado la

dirección de memoria donde reside la "E" del texto. A partir de ello pode manejar a p como

lo he hecho hasta ahora. Véase el ejemplo siguiente:

#include <stdio.h> #define TEXTO1 "¿ Hola, como " #define TEXTO2 "le va a Ud. ? main() {

char palabra[20], *p; int i; p = TEXTO1;

Page 61: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

61

for( i = 0; ( palabra[i] = *p++ ) != '\0'; i++ ); p = TEXTO2; printf("%s", palabra ); printf("%s", p ); return 0;

}

Se definen primero dos strings constantes TEXTO1 y TEXTO2, luego se asigna al puntero

p la dirección del primero, y seguidamente en el FOR copia el contenido de éste en el array

palabra, observe que dicha operación termina cuando el contenido de lo apuntado por p es

el terminador del string, luego asigna a p la dirección de TEXTO2 y finalmente se

imprimen ambos strings, obteniendo una salida del tipo: " ¿Hola, como le va a UD?

(espero que bien).

Hay que reconocer que esto se podría haber escrito más compacto, si hubiera recordado que

palabra también es un puntero y NULL es cero, así se puede poner en vez del FOR.

while( *palabra++ = *p++ );

Véase que aquí se ha agregado muy poco a lo ya ha aprendido, sin embargo hay un tipo de

error muy frecuente, que se puede analizar, en el EJEMPLO siguiente:

¿Algún problema ?.

( CON ERRORES )

#include <stdio.h> char *p, palabra[20]; printf("Escriba su nombre: "); scanf("%s", p ); palabra = "¿ Cómo le va "; printf("%s%s", palabra, p ); }

Pues hay dos errores, a falta de uno, el primero ya fue analizado antes, la expresión

scanf("%s", p ) es correcta pero, el error implícito es no haber inicializado al puntero p, el

cual sólo fue definido, pero aun no apunta a ningún lado válido. El segundo error está dado

por la expresión: palabra = " ¿Cómo le va "; ( también visto anteriormente ) ya que el

nombre del array es una constante y no puede ser asignado a otro valor.¿Cómo se escribiría

para que funcione correctamente ?

(CORRECTO) #include <stdio.h> #include <stdlib.h> #include <string.h> char *p, palabra[20]; p = (char *)malloc(sizeof(char)128); printf("Escriba su nombre: "); scanf("%s", p );

Page 62: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

62

strcpy(palabra, "¿ Como le va " ); printf("%s%s", palabra, p ); }

Al observar que antes de scanf() se ha inicializado a p, mediante el retorno de malloc() y a

al array palabra se le ha copiado el string mediante la función vista anteriormente strcpy().

Se debe aclarar también que, la secuencia de control %s en el printf() impone enviar a la

pantalla un string, estando éste apuntado por el argumento siguiente al control, éste puede

ser tanto el nombre de un array, como un puntero, ya que ambos explicitan direcciones.

Una forma alternativa de resolverlo, sería:

( CORRECTO )

#include <stdio.h> main() { char p[20], *palabra; printf("Escriba su nombre: "); scanf("%s", p ); palabra = "¿ Como le va "; printf("%s%s", palabra, p ); }

Obsérvese, que es idéntico al primero, con la salvedad que se han invertido las

declaraciones de las variables, ahora el puntero es palabra y el array es p. Ambas soluciones

son equivalentes y dependerá del resto del programa, cual es la mejor elección.

7.7 Arrays de punteros

Es una práctica muy habitual, sobre todo cuando se tiene que tratar con strings de distinta

longitud, generar array cuyos elementos son punteros, que albergarán las direcciones de

dichos strings.

Conciba a un puntero como una flecha, un array de ellos equivaldría a un carcaj indio lleno

de aquellas. Así como:

char *flecha;

definía a un puntero a un caracter, la definición

char *carcaj[5];

implica un array de 5 punteros a caracteres.

Page 63: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

63

Inicialización de arrays de punteros

Los arrays de punteros pueden ser inicializados de la misma forma que un array común, es

decir dando los valores de sus elementos, durante su definición, por ejemplo si se quisiera

tener un array donde el subíndice de los elementos coincidiera con el nombre de los días de

la semana, podría escribir:

char *dias[] = { "número de día no válido", "lunes" , "martes" , "miercoles" , "jueves" , "viernes" , "sabado" , "por fin es domingo" }

Igual que antes, no es necesario en este caso indicar la cantidad de elementos, ya que el

compilador los calcula por la cantidad de términos dados en la inicialización. Así el

elemento dias[0] será un puntero con la dirección del primer string, dias[1], la del segundo,

etc.

Page 64: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

64

Page 65: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

65

CAPÍTULO 8

INSTRUCCIONES DE ENTRADA Y SALIDA

Este capítulo es el colofón de este módulo y trata el tema de entradas y salidas en forma

física de los datos y las señales que serán empleadas en el control del robot tipo SCARA de

este curso.

Estas instrucciones de entrada y salida son hechas por medio de funciones creadas por el

lenguaje y son usualmente poco utilizadas en aplicaciones generales, sin embargo, en este

curso son muy importantes, se emplearán durante todo el módulo siguiente para darle vida

al robot mencionado.

Todos los tópicos tratados en los capítulos anteriores serán empleados en las practicas de

este capítulo.

Objetivo particular 8:

Realizar funciones estructuradas de control a tiempo real para el control de motores y

lectura de sensores, aplicando integralmente los conocimientos de todo el módulo para

manejar en forma directa los movimientos del robot.

8.1 Funciones de entrada y salida

Para poder mandar datos a los puertos de la computadora personal, existen diversas

instrucciones dentro del lenguaje “C”, como son las siguientes:

inp Lee un byte de un puerto del hardware.

outp Saca un byte a un puerto de hardware.

Declaración:

int inp(unsigned portid);

int outp(unsigned portid, int value);

Observaciones:

Las instrucciones inp y inpw son macros que leen del puerto de entrada especificado por

portid.

Las instrucciones outp y outpw son macros que escriben a la salida del puerto especificado

por portid.

inp Lee un byte

Page 66: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

66

outp Saca el byte más bajo del dato.

Valor de Retorno:

inp Regresan el valor Leído

outp Regresan el parámetro "value".

8.2 Configuración de puertos de e/s

Para poder manipular los bits de los puertos de entrada y salida, usaremos la estructura

normal de programación de C.

Primero se verá el manejo de las instrucciones inp y outp, para el caso de leer un puerto y

sacar un dato por un puerto de salida.

Para lograr acceder a los puertos de la tarjeta Kentac que va en uno de los “slot” de la PC,

es necesario que dentro del programa se inicialice la función que tendrán cada uno de ellos

(puerto de entrada o de salida).

Por ejemplo para el caso de nuestra tarjeta de visualización la cual esta preparada para dos

puertos de salida por medio de LED’s y un puerto de entrada a través de interruptores, se

tiene la necesidad de programar los “chips” 8255 de esta manera, de salida o de entrada.

Haciendo referencia a las características de la tarjeta kentac, tenemos que los puertos de la

tarjeta de visualización están de la siguiente manera:

Puerto 300H (PA1) equivale a usar el Puerto F9 (Para el módulo kentac 846 )

Puerto 302H (PB1) equivale a usar el Puerto FC (En la tarjeta de visualización)

Puerto 308H (PA2) equivale a usar el Puerto FD ( “ )

Puerto 304H (PC1) equivale a usar el Puerto FE ( “ )

De la tabla 1, del mapa de puertos de E/S, se tiene que la dirección de la palabras de control

son 306H (CW1) y 30EH (CW2).

La palabra de control para el chip 1 (8255) es:

D7 D6 D5 D4 D3 D2 D1 D0 CW

1 0 0 1 0 0 1 0 92

S.Modo Modo 00 PA

(F9)

PC Al.

(FE)

Modo 0 PB (FC) PC Ba.

(FE)

En los puertos:

1 = Entrada

0 = Salida

Page 67: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

67

La palabra de control para el chip 2 (8255) es:

D7 D6 D5 D4 D3 D2 D1 D0 C.W

1 0 0 0 0 0 0 0 80

S.Modo Modo PA (FD) PCH M PB PCL

En los puertos:

1 = Entrada

0 = Salida

Page 68: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

68

Page 69: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

69

CONCLUSIONES

Este texto busca mostrar en forma muy resumida los elementos para hacer programación de

un sistema de robot a lazo semiabierto, la idea principal es contar con los elementos que un

programa de control requiere. Esto significa tener los elementos de sintaxis necesarios para

realizar una codificación en forma secuencial de aspectos de cinemática de robots,

específicamente del robot SCARA.

Los elementos mostrados de programación pueden ser implementados para realizar las

tareas de control a lazo cerrado de un sistema, para el siguiente módulo se mostrará la

forma de programar un sistema de control moderno mediante lenguaje C, el cual puede ser

el pilar de futuras implementaciones en este aspecto.

Llegar a un completo dominio de todos las funciones del lenguaje es altamente complejo en

un curso de tan corta duración, sin embargo, se cuenta con todos los aspectos mínimos

básicos que permiten de manera autodidacta el manejo de este gran volumen de

información que es el propio lenguaje.

El compilador de este lenguaje cuenta con multiples ayudas y ejemplos que facilitan la

utilización de las funciones y su sintaxis. Es por esta razón que esta información omite

algunas de estas referencias ya que acostumbra al usuario a utilizar de forma más ágil el

programa de compilación.

Page 70: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

70

BIBLIOGRAFÍA

Aitken y Jones

Aprendiendo C en 21 Días

Prentice Hall

Herbert Shieldt

Introducción a la Programación de C

McGraw Hill

Luis Joyanes Aguilar

Introducción a Turbo C++

Macrobit

Kernigan

Lenguaje de programación C

Prentice Hall

Borland

Turbo C++ 3.0,

User´s Guide

Page 71: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

71

ANEXO A

EJEMPLOS BÁSICOS DE PROGRAMACIÓN

Page 72: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

72

Practica 1 Elaborar un programa que escriba en pantalla la leyenda “HOLA MUNDO” hacerlo código ejecutable y emplear las funciones clrscr(), printf(); y getch(); /**********************************************************************************/ /****** PROGRAMA 1 INICIO DE LA PROGRAMACION EN C ******/ /*********************************************************************************/ #include<conio.h> #include<stdio.h> void main(void) { clrscr(); printf("HOLA MUNDO"); getch(); }

Práctica 2 Elabore un programa que calcule el valor de temperatura en grados centígrados a partir de la digitación de grados Fahrenheit, emplear las herramientas del depurador de lenguaje C para hacer la verificación de las variables. Utilizar las funciones scanf(); getch(); printf(); y clrscr(); /***********************************************************************************/ /****** PROGRAMA 2 INICIO DE LA PROGRAMACION EN C ******/ /*********************************************************************************/ #include<conio.h> #include<stdio.h> void main(void) { float temp_far,temp_cen; clrscr(); printf("INTRODUZCA EL VALOR DE LA TEMPERATURA EN GRADOS FAHRENHEIT:\n"); scanf("%f",&temp_far); temp_cen=(temp_far-32)*5/9; printf("\nLA TEMPERATURA EN GRADOS CENTRIGRADOS ES: %f",temp_cen); getch(); }

Page 73: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

73

Práctica 3 Utilizar los operadores y condicionales en la solución de la fórmula general de las ecuaciones de segundo grado. Emplear las funciones de práctica 1 y2 adicionalmente algunas funciones matemáticas incluidas en math.h y operadores de multiplicación, división, suma etc. Y el condicional if /***********************************************************************************************/ /****** PROGRAMA 3 USO DE OPERADORES Y CONDICIONALES EN C ******/ /**********************************************************************************************/ #include<conio.h> #include<stdio.h> #include<math.h> void main(void) { float a,b,c,x1,x2,im_x,root,deno; clrscr(); printf("CALCULO DE RAICES DE ECUACION DE 2ø GRADO\n\n\n"); printf("ax2+bx+c=0\n\n\n"); printf("INTRODUZCA LA CONSTANTE a= "); scanf("%f",&a); printf("INTRODUZCA LA CONSTANTE b= "); scanf("%f",&b); printf("INTRODUZCA LA CONSTANTE c= "); scanf("%f",&c); root=b*b-4*a*c; deno=2*a; if(deno==0){ printf("\n\n\n ERROR AL INTRODUCIR LOS DATOS"); getch(); exit(1); }; if(root<0){ root=fabs(root); printf("\n\n LA SOLUCION ES:\n\n"); x1=-b/2*a; im_x=sqrt(root)/2*a; printf("x1=%f %f i\n",x1,im_x); printf("x2=%f %f i\n",x1,-im_x); getch(); exit(1); }; printf("\n\n LA SOLUCION ES:\n\n"); x1=(-b+sqrt(root))/deno; x2=(-b-sqrt(root))/deno; printf("x1=%f\n",x1); printf("x2=%f\n",x2); getch(); }

Page 74: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

74

Práctica 4 Emplear el manejo de un bucle (loop) para realizar una operación iterativa como es el factorial de un numero entero /***********************************************************/ /******* PROGRAMA 4 USO DE BUCLES 1 *******/ /***********************************************************/ #include<conio.h> #include<stdio.h> #include<math.h> void main(void) { float fact=1; int n; clrscr(); printf("CALCULO DEL FACTORIAL\n\n\n"); printf("INTRODUZCA EL NUMERO = "); scanf("%d",&n); clrscr(); printf("\n\n\n\nEL FACTORIAL DE: %d ",n); do{ fact=fact*n; n=n-1; }while(n>1); printf("ES= %f",fact); getch(); }

Page 75: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

75

Practica 5

Emplear un vector unidimensional para realizar un algoritmo que encuentre el valor máximo de un vector dado por el usuario. /****************************************************************************************/ /******* PROGRAMA 5 USO DE VECTORES UNIDIMENSIONALES *******/ /****************************************************************************************/ #include<conio.h> #include<stdio.h> #include<math.h> #define no_items 5 void main(void) { float num[no_items],no_max; int i; clrscr(); printf("\n\n\n"); for(i=0;i<no_items;i++) { printf("INTRODUZCA NUMERO %d = ",i+1); scanf("%f",&num[i]); } no_max=num[0]; for(i=1;i<no_items;i++) { if(no_max<num[i])no_max=num[i]; } printf("\n\n\nEL NUMERO MAXIMO ES: %f",no_max); getch(); }

Page 76: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

76

Práctica 6 Realizar la multiplicación de dos matrices A = n x m por B = o x p dimensiones empleando arreglos de 2 dimensiones y utilizando bucles anidados para lograr el algoritmo. /*************************************************************************/ /******* PROGRAMA 6 USO DE BUCLES 3 *******/ /******* MULTIPLICACION DE MATRICES *******/ /************************************************************************/ #include<conio.h> #include<stdio.h> #include<math.h> #define R1 4 #define C1 6 #define R2 6 #define C2 2 void main(void) { float A[R1][C1]={ {5,6,1,2,8,2}, {4,2,8,5,9,1}, {8,5,4,6,4,0}, {7,9,5,8,6,1}, }; float B[R2][C2]={ {8,5}, {4,2}, {7,9}, {4,5}, {3,2}, {1,7}, }; float C[R1][C2]; float prod=0; int i,j,k; clrscr(); printf("\n\n\n"); for(i=0;i<R2;i++)

Page 77: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

77

{ for(k=0;k<C2;k++) { prod=0; for(j=0;j<C1;j++) { prod=prod+A[i][j]*B[j][k]; }C[i][k]=prod; } } for(i=0;i<R1;i++) { for(j=0;j<C2;j++) { printf(" %f ",C[i][j]); } printf("\n"); } getch(); }

Page 78: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

78

Práctica 7 Realizar un programa para tomar decisiones entre dos alternativas dadas desde el teclado, incrementar un número con flecha arriba, decrementarlo con flecha abajo, todo esto con una saturación inferior y superior de +127 a –128, el número es representado por la variable num de tipo char. /*********************************************************/ /******* PROGRAMA 7 USO DE SWITCH *******/ /*********************************************************/ #include<conio.h> #include<stdio.h> #include<math.h> #define ESC 27 #define ENTER 13 #define UP_ARROW 72 #define DW_ARROW 80 #define LEFT_ARROW 75 #define RIGHT_ARROW 77 #define F1 59 #define F2 60 #define F3 61 #define F4 62 #define F5 63 #define F6 64 #define F7 65 #define F8 66 #define F9 67 #define F10 68 void main(void) { char tecla,num=0; clrscr(); do{ gotoxy(10,10); printf("num= %d ",num); tecla=getch(); if(!tecla){ tecla=getch(); switch(tecla) { case UP_ARROW:{ if(num<127)num++; else num=127; break; } case DW_ARROW:{ if(num>-128)num--; else num=-128;

Page 79: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

79

break; } default: break; } } }while(tecla!=ESC); }

Practica 8

Hacer un programa básico del uso de apuntadores. Se asignará un valor a una variable, después se apunta a la dirección de dicha variable, posteriormente el apuntador muestra su contenido en la pantalla. /***********************************************************************/ /******* PROGRAMA 8 USO DE APUNTADORES *******/ /***********************************************************************/ #include<conio.h> #include<stdio.h> void main(void) { int *p; int x=0,i=0; p=&x; printf("EL VALOR APUNTADO ES: %d",*p); getch(); }

Page 80: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

80

Práctica 9

Emplear a los apuntadores conjuntamente con arreglos. Guardar en un vector con los valores de una señal senoidal y mostrarlos en pantalla a partir del uso de apuntadores. /***********************************************************************/ /******* PROGRAMA 9 USO DE APUNTADORES 2 *******/ /***********************************************************************/ #include<conio.h> #include<stdio.h> #include<math.h> #define Pi 3.1416 void main(void) { float *p; float teta=0,teta_rad=0,z[1000]; int i=0; for(i=0;teta<360;i++) { teta_rad=teta*Pi/180; z[i]=sin(teta_rad); teta++; } p=&z[0]; for(i=0;i<360;i++) { printf("z[%d]=%f\n",i,*p); p++; } getch();

}

Page 81: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

81

Práctica 10 Utilizar a los apuntadores como variables que emplea una función y pueden ser empleados en la función principal. Dibujar en modo gráfico un cuadro que tiene como dimensiones las coordenadas apuntadas por el mouse de la computadora y salir en el momento que esas coordenadas sean parte del cuadro. /***********************************************************************/ /******* PROGRAMA 10 USO DE APUNTADORES 3 *******/ /***********************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #include<math.h> #include<graphics.h> #define Pi 3.1416 #define ESC 27 void main(void) { char tecla=0; int px=0,py=0,x1,x2,y1,y2,x1_old=0,x2_old=0,y1_old=0,y2_old=0; int xmax,ymax; initgr(); mouse_reset(); cursor_on(); set_mouse_position(0,0); xmax=getmaxx(); ymax=getmaxy(); x1=xmax/2-10; y1=ymax/2-10; x2=xmax/2+10; y2=ymax/2+10; do{ mouse_position(&px,&py); setcolor(BLACK); rectangle(x1_old,y1_old,x2_old,y2_old); setcolor(YELLOW); rectangle(x1-px,y1-py,x2+px,y2+py); x1_old=x1-px;

Page 82: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

82

y1_old=y1-py; x2_old=x2+px; y2_old=y2+py; gotoxy(2,2); printf("x=%d y=%d ",px,py); delay(15); if(x1_old<px && y1_old<py)tecla=ESC; }while(tecla!=ESC); cursor_off(); mouse_reset(); closegraph(); clrscr(); } initgr() { int gdriver = DETECT,gmode, errorcode; initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); errorcode = graphresult(); if (errorcode != grOk) { clrscr(); printf("Graphics error: %s\n", grapherrormsg(errorcode)); printf("Press any key to halt:"); getch(); exit(1); /* terminate with an error code */ } } mouse_reset() { union REGS r; r.x.ax=0; /* reset al mouse */ int86(0x33,&r,&r); if((int) r.x.ax !=-1) { closegraph(); printf("hardware or software del mouse no esta instalado"); getch(); exit(1); } if(r.x.bx !=3) { closegraph(); printf("Se require mouse de dos botones"); getch();

Page 83: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

83

exit(1); } } /* DESHABILITACION DEL CURSOR DEL MOUSE */ cursor_off() { union REGS r; r.x.ax = 2; /* Remover el cursor del mouse */ int86(0x33,&r,&r); } /* HABILITACION DEL CURSOR DEL MOUSE */ cursor_on() { union REGS r; r.x.ax = 1; /* Mostrar el cursor del mouse */ int86(0x33,&r,&r); } mouse_position(int *x,int *y) { union REGS r; r.x.ax = 3; /* lee la posicion y el estatus del boton */ int86(0x33,&r,&r); *x=r.x.cx; *y=r.x.dx; } /* Retorna 1 si el boton derecho es presionado y 0 si no fue asi */ rightb_pressed(void) { union REGS r; r.x.ax = 3; /* lee posicion y estatus del boton */ int86(0x33,&r,&r); return r.x.bx & 2; } /* Retorna 1 si el boton izquierdo es presionado y 0 si no fue asi */ leftb_pressed(void) {

Page 84: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

84

union REGS r; r.x.ax = 3; /* lee posicion y estatus del boton */ int86(0x33,&r,&r); return r.x.bx & 1; } set_mouse_position(int x,int y) { union REGS r; r.x.ax = 4; /* Pone una posicion cualquiera */ r.x.cx = x; r.x.dx = y; int86(0x33,&r,&r); }

Page 85: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

85

ANEXO B

POGRAMACIÓN BÁSICA DE CONTROL

Page 86: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

86

/********************************************************************************************/ /**** PROGRAMA 1 ACTIVACIÓN DE PUERTOS DE SALIDA ****/ /**** PROGRAMA TOGGLE.C ****/ /**** ELABORADO POR EL ING. RICARDO BAUTISTA QUINTERO ****/ /**** FECHA: 15-AGOSTO-1999 ****/ /******************************************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #define f9 0x300 //input #define fc 0x302 //input #define fe 0x304 //output #define fd 0x308 //output #define CW1 0x306 #define CW2 0x30E #define unseg 700 void main(void) { char data=0; init_ppi(); clrscr(); do{ outp(fe,data); gotoxy(10,10); printf("EL DATO ES: %x",data); data=data^0x01; delay(unseg); }while(!kbhit()); } init_ppi() { outp(CW1,0X82); outp(CW2,0X80); }

Page 87: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

87

/*************************************************************************************************/ /**** PROGRAMA 4 LEE UN BIT ESPECIFICO DEL PUERTO DE ENTRADA ****/ /**** ELABORADO POR EL ING. RICARDO BAUTISTA QUINTERO ***/ /**** FECHA: 16-AGOSTO-1999 ****/ /************************************************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #define f9 0x300 //input #define fc 0x302 //input #define fe 0x304 //output #define fd 0x308 //output #define CW1 0x306 #define CW2 0x30E #define unseg 700 #define Bit0 0x01 #define Bit1 0x02 #define Bit2 0x04 #define Bit3 0x08 #define Bit4 0x10 #define Bit5 0x20 #define Bit6 0x40 #define Bit7 0x80 void main(void) { unsigned char dummy=0,flag=0; void init_ppi(); clrscr(); do{ gotoxy(10,10); dummy=inp(fc); dummy=dummy&Bit1; if(dummy){flag=1;printf("EL BIT n ESTA ACTIVADO: flag=%X",flag);} else {flag=0;printf("EL BIT n ESTA INACTIVO: flag=%X",flag); } }while(!kbhit()); } void init_ppi(void) { outp(CW1,0X92); outp(CW2,0X80); }

Page 88: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

88

/***********************************************************************************************/ /**** PROGRAMA 3 PONE A UNO UN BIT ESPECIFICADO ****/ /**** POR EL PUERTO DE SALIDA ****/ /**** PROGRAMA TURN_ON.C ****/ /**** ELABORADO POR EL ING. RICARDO BAUTISTA QUINTERO ****/ /**** FECHA: 17-AGOSTO-1999 ****/ /*********************************************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #define f9 0x300 //input #define fc 0x302 //input #define fe 0x304 //output #define fd 0x308 //output #define CW1 0x306 #define CW2 0x30E #define Bit0 0x01 #define Bit1 0x02 #define Bit2 0x04 #define Bit3 0x08 #define Bit4 0x10 #define Bit5 0x20 #define Bit6 0x40 #define Bit7 0x80 void main(void) { unsigned char dummy=0; void init_ppi(); clrscr(); gotoxy(10,10); dummy=inp(fe); printf("DUMMY ANTERIOR ES: %X",dummy); dummy=dummy|Bit0; outp(fe,dummy); gotoxy(10,11); printf("DUMMY ACUAL ES: %X",dummy); getch(); } void init_ppi(void) { outp(CW1,0X82); outp(CW2,0X80); }

Page 89: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

89

/***************************************************************************************************/ /**** PROGRAMA 4 PONE A CERO UN BIT ESPECIFICADO POR EL PUERTO *****/ /**** DE SALIDA *****/ /**** ELABORADO POR EL ING. RICARDO BAUTISTA QUINTERO ****/ /**** FECHA: 18-AGOSTO-1999 ****/ /***************************************************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #define f9 0x300 //input #define fc 0x302 //input #define fe 0x304 //output #define fd 0x308 //output #define CW1 0x306 #define CW2 0x30E #define Bit0 0x01 #define Bit1 0x02 #define Bit2 0x04 #define Bit3 0x08 #define Bit4 0x10 #define Bit5 0x20 #define Bit6 0x40 #define Bit7 0x80 void main(void) { unsigned char dummy=0; void init_ppi(); clrscr(); gotoxy(10,10); dummy=inp(fc); printf("DUMMY ANTERIOR ES: %X",dummy); dummy=dummy&~Bit0; outp(fc,dummy); gotoxy(10,11); printf("DUMMY ACUAL ES: %X",dummy); getch(); } void init_ppi(void) { outp(CW1,0X82); outp(CW2,0X80); }

Page 90: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

90

/*****************************************************************************************/ /**** PROGRAMA 5 INTEGRACION DE PROGRAMAS TURN_ON, ***/ /**** TURN_OFF Y TEST_BIT ****/ /**** PROGRAMA OUTIN.C ****/ /**** ELABORADO POR EL ING. RICARDO BAUTISTA QUINTERO ****/ /**** FECHA: 19-AGOSTO-1999 ****/ /***************************************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #define f9 0x300 //input #define fc 0x302 //input #define fe 0x304 //output #define fd 0x308 //output #define CW1 0x306 #define CW2 0x30E #define unseg 700 #define Bit0 0x01 #define Bit1 0x02 #define Bit2 0x04 #define Bit3 0x08 #define Bit4 0x10 #define Bit5 0x20 #define Bit6 0x40 #define Bit7 0x80 void main(void) { unsigned char dummy=0,flag=0; void init_ppi(); clrscr(); do{ if(test_bit(fc,bit0))turn_on(fe,actuador1); if(test_bit(fc,bit1))turn_off(fe,actuador1); }while(!kbhit()); } void init_ppi(void) { outp(CW1,0x82); outp(CW2,0x80); }

Page 91: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

91

void turn_on(int port,char mask) { char dummy; dummy=inp(port); dummy=dummy|mask; outp(port,dummy); } void turn_off(int port,char mask) { char dummy; dummy=inp(port); dummy=dummy&~mask; outp(port,dummy); } char test_bit(int port,char mask) { char dummy,flag; dummy=inp(port); dummy=dummy&mask; if(dummy)flag=1; else flag=0; return flag; }

Page 92: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

92

/********************************************************************************************/ /** PROGRAMA 6 PROGRAMACIÓN DE UNA FUNCIÓN A TIEMPO REAL ***/ /**** PROGRAMA INTER1.C ***/ /**** ELABORADO POR EL ING. RICARDO BAUTISTA QUINTERO ****/ /**** FECHA: 20-AGOS-1999 ****/ /*******************************************************************************************/ #include<conio.h> #include<stdio.h> #include<dos.h> #define Puerto_out 0x278 #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <dos.h> #include "c:\tc\user\icord.h" /* Header file */ #include "c:\tc\user\icord.c" int Count = -1,Count_max=1000,disp = 0, ref = 1; void taskDisp(void); /* Despliega el resultado de las tareas */ void task1(void); /* Funcion de interrupcion task1 */ void task2(void); /* Funcion de interrupcion task2 */ void taskErr(void); /* Funcion para prevenir timeout */ char Data_Task1=0,Data_Task2=0; void main(void) { int cmd; /* Bandera para iniciar o no el programa */ double clock = 1; /* Intervalo de base de tiempo (1 milisec) */ int stimeTask1 = 1000; /* No. de veces que se ejecuta Base de tiempo */ int stimeTask2 = 2; /* No de veces de ejecucion de task1 */ setTimmer(clock); /* Habilita funcion de interrupcion de 1ms*/ setTask1(stimeTask1, task1); /* Da las condiones de task1 */ setTask2(stimeTask2, task2); /* Da las condicones de task2 */ setErrfunc(taskErr); /* Da las condiciones de funcion para evitar*/ /* time out */ rtStart(); /* Inicia subrutina a tiempo real */ clrscr(); show_leds(); rtStop(); /* Termina el programa y deshabilita interr */ }

Page 93: Modulo v Lenguaje C Para Control

Centro Nacional de Actualización Docente Mecatronica Quinto curso internacional de ingeniería mecatrónica

MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo

93

show_leds() { do { gotoxy(10,10); printf("Data Task1=%x",Data_Task1); gotoxy(10,11); printf("Data Task2=%x",Data_Task2); }while(!kbhit()); outp(Puerto_out,0x00); } /********************************************************************/ /**** FUNCION DE INTERRUPCION TASK1 y TASK2 ***/ /********************************************************************/ void task1(void) { enable(); /*Habilita interrupcion*/ Data_Task1=Data_Task1^0x01; outp(Puerto_out,Data_Task1); return; } void task2(void) { enable(); /* Habilita interrupcion */ Data_Task2=Data_Task2^0x02; outp(Puerto_out,Data_Task2); return; } void taskErr(void) { printf("\nTIME OUT (taskErr) !!%c %d \n", 0x07, getErrcode()); exit(0); /*Se sale al existir translape en interrupcion*/ }