Anda di halaman 1dari 93

MODULO V

PROGRAMACIÓN EN LENGUAJE C
PARA CONTROL
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

2
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

3
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

4
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

5
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

6
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

7
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

8
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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");
}

9
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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:

10
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

#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.

11
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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:

12
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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
}

13
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

14
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 -

15
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 (")

16
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

\' 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.

17
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

18
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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:

19
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

20
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

21
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

22
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

23
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

24
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

25
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

26
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

27
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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;

28
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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;

29
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

30
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

31
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

#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.

32
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

33
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

34
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

35
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

36
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 Para pasar a la línea siguiente hay que
escribir el caracter de nueva línea: '\n' 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.

37
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

38
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

39
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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);
}

40
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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));
}

41
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 */

42
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

{ /* 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 */
}

43
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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)
{

44
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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."

45
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

46
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

47
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

48
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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*/

49
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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:

50
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

51
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

52
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 */

53
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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:

54
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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:

55
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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] */

56
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 );

57
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

58
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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) );

59
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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;

60
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 );

61
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

62
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

63
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

64
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

65
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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 PC Al. Modo 0 PB (FC) PC Ba.
(F9) (FE) (FE)

En los puertos:

1 = Entrada
0 = Salida

66
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

67
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

68
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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.

69
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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

70
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

ANEXO A

EJEMPLOS BÁSICOS DE PROGRAMACIÓN

71
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();
}

72
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();
}

73
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();
}

74
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();
}

75
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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++)

76
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

{
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();
}

77
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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;

78
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();

79
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();

80
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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;

81
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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();

82
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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)
{

83
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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);
}

84
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

ANEXO B

POGRAMACIÓN BÁSICA DE CONTROL

85
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

/********************************************************************************************/
/**** 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);
}

86
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

/*************************************************************************************************/
/**** 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);
}

87
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

/***********************************************************************************************/
/**** 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);
}

88
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

/***************************************************************************************************/
/**** 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);
}

89
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

/*****************************************************************************************/
/**** 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);
}

90
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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;
}

91
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

/********************************************************************************************/
/** 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 */


}

92
MODULO V Programación en lenguaje c para control M. en C. Bautista Quintero Ricardo
Centro Nacional de Actualización Docente Mecatronica
Quinto curso internacional de ingeniería mecatrónica

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*/
}

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

Anda mungkin juga menyukai