Вы находитесь на странице: 1из 61

T EMA 1:

Introduccin a los lenguajes de programacin


1.1. Concepto de un lenguaje de programacin
El termino alfabeto denota cualquier conjunto finito de smbolos. Una
cadena sobre algn alfabeto es un secuencia finita de smbolos tomados de
ese alfabeto. Por lo tanto, el trmino lenguaje se refiere a cualquier conjunto de
cadenas de un alfabeto finito que cumple con ciertas reglas gramaticales.
Cualquier notacin para describir algoritmos y estructuras de datos se
puede calificar como lenguaje de programacin.
Los componentes de software se construyen mediante lenguajes de
programacin que tiene un vocabulario limitado, una gramtica definida
explcitamente y reglas bien formadas de sintxis y semntica. Estos atributos
son esenciales para la traduccin hecha por la mquina. Las clases de
lenguajes que se utilizan actualmente son los lenguajes mquina o de bajo
nivel, los lenguajes de alto nivel y los lenguajes no procedimentales.
Los lenguajes mquina son una representacin simblica del conjunto de
instrucciones de la CPU. Si un programador produce programas mantenibles y
bien documentados, puede utilizar el lenguaje mquina para hacer un uso
extremadamente eficiente de la memoria y para optimizar la velocidad de
ejecucin del programa. Pero si el programa esta mal diseado y tiene poca o
nada documentacin, el lenguaje mquina puede convertirse en una pesadilla.
El lenguaje ensamblador es un ejemplo de lenguaje mquina.
Los lenguajes de alto nivel permiten al programador y al programa
independizarse de la mquina, ya que utilizan instrucciones similares a las de
los lenguajes utilizados entre los humanos para comunicarse, como el ingls, y
se pueden ejecutar en diversos tipos de computadoras. FORTRAN, Pascal, C,
etc. son lenguajes de alto nivel.

1.2. Paradigmas de programacin


Los llamados paradigmas de programacin son conceptualizaciones
genricas, que renen en un nombre a distintos lenguajes y tcnicas
empleados para escribir programas. En otras palabras, definiremos como
Paradigma de software a un conjunto de reglas que establecen la forma para
analizar, disear y escribir programas.

La diferencia entre los lenguajes que pertenecen a uno u otro paradigma


de programacin radica en la manera en que se orientan a la resolucin del
problema y a la forma en que hacen referencia a los datos.
En este subtema identificaremos los diferentes paradigmas de
programacin y veremos algunos ejemplos de cdigos de los lenguajes ms
representativos de cada uno de ellos.

1.2.1 Procedurales
Es tambin conocido como paradigma imperativo, el cual define a la
programacin como el desarrollo de procedimientos. Aqu se puede hacer la
siguiente divisin: Lenguajes simples de procedimientos y Lenguajes de
procedimientos estructurado en bloques.

Lenguajes simples de procedimientos.- Estos lenguajes se


componen de procedimientos, llamados subprogramas, funciones
o subrutinas) que se ejecutan cuando son llamados. Ejemplos de
lenguajes que caen dentro de este paradigma son Fortran y
lenguaje C. Observemos el siguiente programa en lenguaje C:

// En este lenguaje las variables se definen antes de que se


usen
#include <stdio.h>
void
{

saludo(

printf ("%s", "Hola mundo");


}
main(
{
int
i=2;
if (i==2) saludo ( );

)
i;

}
Observaste que en la funcin main() se invoca a la funcin
saludo()?. En este paradigma la manera de escribir programas es
crear estructuras de datos y funciones como entidades separadas
.

Constatmoslo con el siguiente ejemplo en lenguaje Fortran,


que es tambien un lenguaje simples de procedimientos, en el que
el programa principal invoca a una funcin definida fuera de l .
PROGRAM
INTEGER
i=2
IF
(i.EQ.2)
STOP
END
SUBROUTINE
PRINT
*
RETURN
END

TRIVIAL
i
CALL

SALUDO(

"HOLA

SALUDO
MUNDO"

Observa que el programa principal TRIVIAL invoca a la SUBROUTINE


SALUDO.

Lenguajes de procedimientos estructurado en


bloques.- Este tipo de lenguajes emplea reglas de alcance
y una estructura de bloques anidados para guardar y tener
acceso a datos. Un lenguaje ejemplo de este paradigma es
el Pascal. Observa en el siguiente cdigo que el
procedimiento saludo esta anidado dentro del programa
principal trivial.

program
trivial
var
i=integer;
procedure
begin
writeline
("hola
end;
begin
i:=2;
if
(i=2)
then
end.

(input,output);
saludo;
mundo");

saludo;

Es importante sealar que la programacin de los cdigos anteriores es muy


similar debido a que pertenecen al mismo paradigma. Veamos los siguiente
paradigma.

1.2.2 Lgicos

Un ejemplo de lenguaje que entra en este paradigma es Prolog, el cual no


est orientado a la programacin para usos generales, sino que se orienta a
resolver problemas usando el clculo de predicados. Veamos el siguiente
cdigo ejemplo en Prolog:
/*Base de datos en prolog*/:
le_gusta (juan, libros)

/*A Juan le gusta libros*/

le_gusta (juan, mara)

/*A Juan le gusta Mara */

le_gusta (juan, pescado) /*A Juan le gusta pescado */


--------------------------------------------------------------Consulta en Prolog:
?_le_gusta
Yes
?_le_gusta
X=
X=
X= pescado;

(juan,
(juan,

libros)
X)
libros;
mara;

Prolog trata de emular una pltica usuario-mquina. Esta forma de


programacin es muy diferente a la vista anteriormente.

1.2.3 Funcionales
Como lenguajes representativos de este paradigma podemos mencionar a
Lisp, ML, Scheme , entre otros. Este tipo de lenguajes est destinado a
programarse en forma aplicativa.
Lisp fue creado por John McCarthy y un grupo del Massachussets Institute
of Technology en 1960 (MIT), el lenguaje se ha utilizado en la investigacin en
ciencias de la computacin, sobre todo en la Inteligencia Artificial (robtica,
procesamiento de lenguaje natural, prueba de teoremas, etc.). En seguida se
muestra un cdigo ejemplo Lisp:

>

(define
((cond
(eq

i
(T

>
> hazlo

(define

2)

(hola
i)
(print
"Hola
mundo"))
(print
"Adios
mundo")))
(hazlo)(hola
2))

"Hola mundo"

Veamos el siguiente paradigma.

1.2.4 Orientados a Objetos


En este caso las unidades de datos se consideran objetos activos. La
caracterstica principal de los lenguajes orientados a objetos es la capacidad de
representar definiciones de objetos a modo de esqueletos que pueden usarse
una y otra vez para construir mltiples objetos con las mismas propiedades o
modificarse para construir nuevos objetos con propiedades similares. Algunos
ejemplos de lenguajes de programacin orientada a objetos son C++, Java,
SmallTalk, Caf. Veamos el siguiente programa ejemplo en C++
class
trivial
#include
<iostream.h>
class
trivial
{
public:
//definicin
de
la
funcin
//miembro
saludo
void
saludo(
)
{
cout
<<
"Hola
mundo";
}
};
main()
{
trivial
ob1;
ob1.saludo(
);
}

1.2.5 Otros

PARADIGMA RELACIONAL

Este caso la representacin utilizada se basa en un conjunto de


relaciones o tablas. Este constituye uno de los paradigmas ms utilizados
gracias al xito y madurez de los sistemas Manejadores de Bases de Datos
Relacionales y se complementa en la tecnologa O.O. en el campo de las
Bases de Datos Orientadas a Objetos.

EL PARADIGMA DE BASE DE DATOS

Una base de datos es ms o menos un archivo permanente con


estructura. En su forma ms simple, es un archivo de grabaciones, como una
especie de catlogo de entidades, las cuales no desaparecen al terminar el
programa, sino que, una vez organizadas, son permanentes.
El paradigma de la base de datos est estrechamente relacionado con
los lenguajes basados en la lgica. Las relaciones entre sus entidades estn
preservadas de cambios externos, por lo que otra caracterstica a tener en
cuenta es la del control de cambios. Un sistema de gestin de bases de datos,
DBMS (Database Management System) incluye normalmente un lenguaje de
definicin de datos, DDL (Data Definition Language), para la descripcin de
nuevos hechos o datos; y un lenguaje de manipulacin de datos, DML (Data
Manipulation Language), para la interaccin con las bases de datos existentes.
El DML es a menudo embebido por otro lenguaje de programacin de alto nivel
para mayor flexibilidad.
SQL (Structured Query Language) es el lenguaje de base de datos ms
utilizado y, a pesar de no ser completamente funcional en el sentido de ser tan
potente como un lenguaje procedural, dota de operaciones suficientes a las
aplicaciones de base de datos. Tiene muchas deficiencias; la ms seria de ellas
es que nunca fue realmente diseado de acuerdo con ambas partes (lgebra y
clculo), y por lo tanto, est lleno de numerosas restricciones y reglas
especiales. Una base de datos puede ser vista de diferentes formas. En el nivel
ms bajo se encuentra la physical view, la cual describe los discos fsicos en
los cuales se encuentran los datos. En el siguiente nivel nos encontramos la
storage view, que estructura los datos fsicos. La ms comn es la denominada
en ingls "B-tree". Los administradores y programadores, pero no el usuario,
interaccionan con este nivel.
La siguiente y ms alta abstraccin es la conceptual view, que describe
como estn organizados los datos. Finalmente hay varias visiones externas o
external views de una base de datos. stas son visualizadas y utilizadas por el
usuario, a menudo a travs de un lenguaje de rdenes. Todas estas formas de
ver la base de datos juntas, son las que conforman la
DBMS.

EL PARADIGMA DE POA

Programacin Orientada a Aspectos, conocida en el idioma ingls como


AOP: Aspect Oriented Programming.
La POA es un nuevo paradigma de programacin, creado por Gregor
Kiczales. El principal objetivo que persigue es encapsular, capturar, aquellos
conceptos que se escapan a los mtodos actuales de descomposicin de
sistemas. Estos conceptos reciben el nombre de aspectos.
A partir de aqu los lenguajes se inventan por una necesidad especfica,
el segundo lenguaje fue inventado para jugar ajedrez. Aqu se presenta una

tabla con una lista de lenguajes que existen. Cabe mencionar que no son todos
los lenguajes, ya que en la actualidad existen mas de 2500.

1.3. Compiladores e intrpretes


Los compiladores e intrpretes de los lenguajes de alto nivel producen
lenguaje mquina como salida. En seguida estableceremos la definicin de
ambos y las diferencias entre ellos.

1.3.1 Definicin y diferencias


En forma general, definiremos a un compilador como un programa que
lee un programa escrito en un lenguaje (conocido como cdigo fuente) y lo
traduce a un programa equivalente en otro lenguaje reconocido por la
computadora (llamado lenguaje objeto). Como parte importante de este
proceso de traduccin, el compilador informa al usuario de la presencia de
errores en el programa fuente.
Cuando cada instruccin en un programa fuente de nivel alto se traduce
de manera individual y se ejecuta inmediatamente al momento de la traduccin,
el lenguaje de programacin utilizado se llama lenguaje interpretado, y el
programa que efecta la traduccin se llama interprete.
El interprete en lugar de producir un programa objeto como resultado de
una traduccin, un intrprete realiza las operaciones que indica el programa
fuente. Para una proposicin de asignacin, por ejemplo un intrprete podra
construir un rbol como el de la figura 1.1 e inmediatamente ejecutar las
operaciones de los nodos conforme recorre el rbol. En la raz descubrira que
tiene que realizar una asignacin, y llamara a una rutina para evaluar la
expresin de la derecha y despus almacenara el valor resultante en la
localidad de memoria asociada con el identificador posicin. En el hijo derecho
de la raz, la rutina descubrira que tiene que calcular el valor de la expresin
velocidad * 60. Despus sumara ese valor al valor de la variable inicial.

Figura 1.1. rbol sintctico para posicin:= inicial + velocidad * 60


Muchas veces los intrpretes se usan para ejecutar lenguajes de
rdenes, pues cada operador que se ejecuta en un lenguaje de rdenes suele
ser una invocacin de una rutina compleja, como un editor o un compilador. Del
mismo modo, algunos lenguajes de alto nivel, como APL, normalmente son
interpretados porque hay muchas cosas sobre los datos, como el tamao y la
forma de las matrices que no se pueden deducir en el momento de la
compilacin.
En seguida se describirn las fases de un programa compilado.

1.3.2 Anlisis del programa fuente


Adems de un compilador, se pueden necesitar otros programas para
crear un programa objeto ejecutable. Un programa fuente se puede dividir en
mdulos almacenados en archivos distintos. En la figura 1.2 se muestra una
compilacin tpica.

Figura 1.2. Sistema para procesamiento de un lenguaje


Enseguida analizaremos la funcin de cada una de estas etapas .

1.3.2.1. Preprocesador
Los preprocesadores producen la entrada para un compilador y puede
realizar las funciones siguientes:
1. Procesamiento de Macros. Un preprocesador puede permitir a un usuario
definir macros y abreviaturas para representar una parte del programa y utilizar
esa abreviatura cuantas veces lo necesite. Cada vez que aparece la
abreviatura o macro llamada, el preprocesador la reemplaza con la definicin
original.
2. Inclusin de archivos: Algunos preprocesadores pueden insertar archivos de
encabezamiento en el texto del programa. Por ejemplo: El preprocesdador de C
hace que el archivo <global.h> reemplace a la proporcin #include "global.h"
cuando procesa un archivo que contenga a esa preposicin.
3. Extensiones a Lenguajes: Estos preprocesadores tratan de crear
posibilidades al lenguaje que equivalen a macros incorporados. Ejemplo, el
lenguaje Equel es un lenguaje de consulta de base de datos integrado en C. El
procesador considera las proposiciones que empiezan con # # como
proposiciones de acceso a la base de datos, sin relacin con C y se traducen a
llamadas de procesamiento a rutinas que realizan el acceso a base de datos.
4. Eliminan Comentarios. Por ejemplo: los smbolos para los comentarios en
C, // o / * */

1.3.2.2. Compilador

Conceptualmente, un compilador opera en fases, cada una de las cuales


transforma el programa fuente de una representacin en otra. Ver la figura 1.3

Figura 1.3. Fases de un compilador

1.3.2.2.1 Anlisis Lxico


El analizador lxico es la primera fase de un compilador su principal
funcin consiste en leer los caracteres de entrada y elaborar como salida una
secuencia de componentes lxicos que utilizar el analizador sintctico para
hacer el anlisis.
El analizador lxico debe realizar las siguientes funciones:
* Eliminar los espacios en blanco y comentarios
* Reconocer las constantes
* Reconocimiento de identificadores y palabras claves.
En general hay un conjunto de cadenas en la entrada, para lo cul se
produce como salida el componente lxico. Este conjunto de cadenas se
describe mediante una regla llamada patrn asociado al componente lxico. Se
dice que el patrn concuerda con cada cadena del conjunto.
Un lexema es una secuencia de caracteres en el programa fuente con la
que concuerda el patrn para un componente lxico.
Se considera componentes lxicos a las palabras claves, operadores,
identificadores, constantes, cadenas, literales y signos de puntuacin.

En la prctica los componentes lxicos suelen tener un solo atributo que


es un apuntador a la entrada en la tabla de smbolos donde se guarda la
informacin sobre el componente lxico.
Por ejemplo, en el anlisis lxico los caracteres de la proposicin de
asignacin
posicin = inicial + velocidad * 60
1. El identificador posicin.
2. El smbolo de asignacin =.
3. El identificador inicial.
4. El signo de + (suma).
5. El identificador velocidad.
6. El signo de * (multiplicacin).
7. El nmero 60 .
Los espacios en blanco que separan los caracteres de estos
componentes lxicos normalmente se eliminan durante el anlisis lxico.

1.3.2.2.2 Anlisis Sintctico


En el anlisis sintctico se agrupan los componentes lxicos del
programa fuente en frases gramaticales que el compilador utiliza para sintetizar
la salida. Por lo general, las frases gramaticales del programa fuente se
representan mediante un rbol de anlisis sintctico como el que se ilustra en
la figura 1.4.

Figura 1.4. rbol de anlisis sintctico para posicin:= inicial + velocidad * 60


En la expresin inicial + velocidad * 60, la frase velocidad * 60 es una
unidad lgica, porque las convenciones usuales de las expresiones aritmticas
indican que la multiplicacin se hace antes que la suma. Puesto que las
expresiones inicial + velocidad va seguida de un *, no se agrupan en una sola
frase independiente en la figura anterior.
La estructura jerrquica de un programa normalmente se expresa
utilizando reglas recursivas. Por ejemplo, se pueden dar las siguientes reglas
como parte de la definicin de expresiones:
1. Cualquier identificador es una expresin.
2. Cualquier nmero es una expresin.
3. Si expresin1 y expresin2 son expresiones, entonces
tambin lo son
expresin1
expresin1
(expresin1)

+
*

expresin2
expresin2

Las reglas 1 y 2 son reglas no recursivas, en tanto que la regla 3 define


expresiones en funcin de operadores aplicados a otras expresiones. As, por
la regla 1, inicial y velocidad son expresiones. Por la regla 2, 60 es un
expresin, mientras que por la regla 3, primero podemos inferir que velocidad *
60 es un expresin, y finalmente que inicial + velocidad * 60 tambin es una
expresin.

1.3.2.2.3 Anlisis Semntico


Las fases de anlisis semntico revisa el programa fuente para tratar de
encontrar errores semnticos y rene la informacin sobre los tipos para la fase
posterior de generacin de cdigo. En ella se utiliza la estructura jerrquica
determinada por la fase de anlisis sintctico para identificar los operadores y
operandos de expresiones y proposiciones.
Un componente importante del anlisis semntico es la verificacin de
tipos. Aqu el compilador verifica si cada operador tiene operandos permitidos
por la especificacin del lenguaje fuente. Por ejemplo, las definiciones de
muchos lenguajes de programacin requieren que el compilador indique un
error cada vez que se use un nmero real cono ndice de una matriz. Sin
embargo, las especificaciones del lenguaje puede permitir ciertas coerciones a
los operandos, por ejemplo, cuando un operador aritmtico binario se aplica a
un nmero entero y a un nmero real. En este caso, el compilador puede
necesitar convertir el nmero entero a real.

1.3.2.2.4 Generador de cdigo intermedio

Despus de los anlisis sintctico y semntico algunos compiladores


generan un cdigo intermedio explcito del programa fuente.
La representacin intermedia puede tener diversas formas, una de ellas
es el cdigo de 3 direcciones el cual consiste de un secuencia de instrucciones
cada una de las cuales tiene como mximo 3 operandos, el cdigo de 3
direcciones tienen las siguientes reglas:
1. Cada instruccin de 3 direcciones tienen a lo ms un operador adems de la
asignacin.
2. El compilador debe generar un nombre temporal para guardar los valores
calculados
por
cada
instruccin.
3. Algunas instrucciones de 3 direcciones tienen menos de 3 operandos.
Por ejemplo, la instruccin id1 = id2 + id3 * 60 en cdigo de tres
direcciones queda de la siguiente forma
temp1
temp2
temp3
id1 = temp3

=
=
=

conv_de_entero_a_real
id3
*
id2
+

(60)
temp1
temp2

1.3.2.2.5 Optimizador de cdigo


Esta fase trata de mejorar el cdigo intermedio, de modo que resulte un
cdigo de mquina ms rpido de ejecutar. En el ejemplo anterior, el
compilador puede deducir que la conversin de 60 de entero a real se puede
hacer en la misma lnea, temp1= velocidad * 60.0, adems temporal 3 se usa
slo una vez para transmitir su valor id1. Entonces resulta seguro sustituir id1
por temp3, a partir de lo cual la ltima proposicin no se necesita y se obtiene
el cdigo siguiente
temp1
id1 = id2 + temp1

id3

60.0

1.3.2.2.6 Generador de cdigo


La fase final de un compilador es la generacin de cdigo objeto, que por
lo general consiste en cdigo de mquina relocalizable o cdigo ensamblador.
Las posiciones de memoria se seleccionan para cada una de las variables
usadas por el programa. Despus cada una de las instrucciones intermedias se
traducen a una secuencia de instrucciones mquina que ejecuta la misma
tarea. Un aspecto decisivo es la asignacin de variables a registros.
MOVF
MOVF
MULF
MOVF
ADDF
MOVF id1, DX

AX
BX,
BX,

60.0
id3

AX
DX,
DX,

id2
BX

1.3.2.2.7 Administrador de tabla de smbolos


Una tabla de smbolos es una estructura de datos que contiene un
registro por cada identificador, con los campos para los atributos del
identificador.
Estos atributos proporcionan informacin sobre la memoria asignada a un
identificador, su tipo, su mbito y en el caso de procedimientos o funciones el
mtodo para pasar cada argumento (Por valor o referencia) y el tipo de dato
que devuelve, si lo hay.
Desde el primer momento en que el analizador lxico detecta un
identificador en el programa fuente, el identificador se introduce a la tabla de
smbolos.

1.3.2.2.7 Deteccin e informacin de errores


Cada fase puede encontrar errores. Sin embargo despus de detectar un
error cada fase debe tratar de alguna forma ese error, para poder continuar la
compilacin permitiendo la deteccin de ms errores en el programa fuente. Un
compilador que se detiene cuando encuentra el primer error no resulta tan til
como debiera.

1.3.2.3 Ensamblador
Algunos compiladores producen cdigo ensamblador, otros realizan el
trabajo del ensamblador, produciendo cdigo de mquina relocalizable que se
puede pasar directamente al editor de carga y enlace. El cdigo ensamblador
es una versin nemotcnica del cdigo de mquina.
En el cdigo mquina se usan nombres en lugar de cdigos binarios para
operaciones y tambin se usan nombres para las direcciones de memoria.

1.3.2.4 Editor de carga y enlace


Por lo general, un programa llamado cargador realiza las 2 funciones de
carga y edicin de enlace. El proceso de carga consiste en tomar el cdigo de
mquina relocalizable, modificando las direcciones relocalizables, y ubicar las
instrucciones y datos modificados en las posiciones apropiadas de la memoria.
El editor de enlace permite formar un solo programa a partir de varios
archivos de cdigo de mquina relocalizable. Estos archivos pueden haber sido
el resultado de varias compilaciones distintas, y uno o varios de ellos pueden
ser archivos de biblioteca de rutina proporcionadas por el sistema y disponibles
para cualquier programa que los necesite.

T EMA 2: Lenguaje C

2.1 Manejo del Compilador de C


Sin apunte.
Tema visto en la prctica en el laboratorio del edificio A

2.2 Tipo de datos primitivos y operadores


Tambin conocidos como tipos de datos Normalizados, son aquellos que
forman parte de la mayora de las computadoras y comprenden a los nmeros

enteros
reales (nmeros de punto flotante)
valores lgicos (false, true)
conjunto de caracteres de escritura.

En seguida analizaremos cada uno de ellos


Nmeros enteros
La computadora es binaria, es decir, nicamente reconoce unos y ceros. Para
ejemplificar la manera en que la computadora representa a los nmeros
enteros, hagamos la siguiente abstraccin: Supongamos una mquina
hipottica de 5 bits, entonces los nmeros enteros positivos y negativos que se
representaran en ella son
Nmero en Binario
base diez positivo

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

00000
00001
00010
00011
00100
00101
00110
00111
01000
01001
01010
01011
01100
01101
01110
01111

Nmero en Binario
base diez negativo

-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16

11111
11110
11101
11100
11011
11010
11001
11000
10111
10110
10101
10100
10011
10010
10001
10000

Nota: El primer dgito del nmero binario es conocido como bit de signo, 0 para
positivos
y
1
para
negativos. Para obtener los nmeros binarios Negativos utilizar Complemento a
dos, esto es tomar el binario del nmero en su forma positiva, enseguida
cambiarle los unos a ceros y los ceros a unos, y al nmero binario resultante
sumarle un 1.
Las computadoras personales reales son de 32 bits, pero como en el caso
anterior, algo similar sucede en nuestra computadora, es slo que en esta el
tamao designado a los enteros es de 2 bytes (16 bits). Por lo tanto el 15 se
representa en nuestra mquina de la siguiente forma
0 000000000001111

Nmeros punto flotante


Para representar a los nmeros de punto flotante se requieren de 4 bytes (32
bits) de memoria. La manera en que se representan es
1 bit
para 8 bits para
el
exponente
Signo

el

23 bits para la mantisa

Cuando se almacenan en punto flotante, el signo, la mantisa y el exponente se


guardan de manera individual en campos separados. El nmero de bits
utilizado para cada campo determina la precisin del nmero.
La tabla siguiente muestra los formatos para un nmero en punto flotante. Este
formato est regido por la norma 754-1984 de la IEED (Institute of Electrical
and Electronic Engineers).
Formato de Datos

Bit del signo

Exponente

Mantisa

Precisin Sencilla

23

Doble Precisin

11

52

Extendida

15

64

El bit del signo se refiere al signo de la mantisa.

Puesto que todas las mantisas, excepto por el nmero cero tienen siempre uno
al principio, seguido por los puntos binarios, esos dos elementos nunca se
guardan de manera explcita.
El punto binario permanece implcitamente a la izquierda del bit 22 de la
mantisa y siempre se asume que hay un 1 al principio.
El nmero binario cero se puede especificar al establecer todos los bits de la
mantisa y exponente con cero. Slo para estos casos el bit implcito al principio
de la mantisa es cero.
El algoritmo para representar en memoria a los nmeros de punto flotante es:
1.- Convertir el nmero de punto decimal a binario.
2.- Recorrer el punto decimal tantos lugares a la izquierda hasta antes del
ltimo uno y expresarlo en forma exponencial, en donde el exponente ser el
numero de espacios que fue recorrido el punto. O recorrer el punto tantos
lugares a la derecha hasta encontrar el primer uno, en este caso el exponente
ser negativo. Convertir el exponente tambin a binario.
3.- Colocar cero en el primer bit si el nmero es positivo y si es negativo colocar
un uno.
4.- Para el exponente calcular 127 + exponente o 127 - exponente segn sea el
caso. Al sumar 127 a cada exponente se consigue codificar un exponente
negativo en el campo del exponente sin necesidad de hacer explcito el bit del
signo, por ejemplo, el exponente -3 se almacena utilizando el equivalente
binario 127 - 3 = 124 =1111100.
5.- Para la mantisa colocar todos los nmeros que quedaron despus del
punto, llenar con ceros todas las localidades que quedaron vacas.
Ejemplo:
Para representar el -18.125 en una mquina de 32 bits aplicaremos el algoritmo
descrito previamente
Paso 1: Convertir el nmero de punto decimal a binario es decir el
-18.125 se representa en binario como 1 0 0 1 0 . 0 0 1
Paso 2: recorremos el punto hacia la izquierda 4 posiciones hasta antes del
ltimo uno
1 . 0 0 1 0 0 0 1 E4
Convirtiendo el exponente a binario queda
1 . 0 0 1 0 0 0 1 E100

Paso 3: Como el nmero es negativo, ponemos un 1 en el primer bit


1 0000000000000000000000000000000

Paso 4: Calculamos el exponente 127+4=131 que en binario queda 10000011


1 1000001100000000000000000000000

Paso 5: Del nmero obtenido en el paso 2 colocamos los nmeros que estn
despus del punto en la mantisa quedando el numero de la siguiente forma
1 1000001100100010000000000000000

Caracteres y cadenas
Cada computadora puede leer o escribir cierto nmero de caracteres distintos.
El conjunto ms completo de caracteres incluye letras maysculas y
minsculas, los 10 dgitos, una amplia variedad de signos de puntuacin, una
coleccin de caracteres especiales tiles en matemticas y administracin y, a
veces, hasta letras griegas.
Con el fin de transmitir estos caracteres a las computadoras, se les ha
asignado a cada uno un nmero. La correspondencia entre caracteres y
enteros se denomina cdigo de caracteres.
Un cdigo muy utilizado es el ASCII (American Standard Code for Information
Interchange). Otro cdigo de 8 bits muy ocupado es el ABCDIC de IBM,
utilizado en las grandes macro computadoras de IBM, que aunque ya es
obsoleto, IBM lo sigue usando por motivos de compatibilidad.
Ejemplos de cdigo ASCII:
Para
'
/
' el
nmero
Los
cdigos
de
Para ' @ ' le corresponde el 100

en

cdigo
A-Z

ASCII
son

es

el
134
141-172

Los caracteres ocupan un byte (8 bits) de memoria y su representacin en


memoria se muestra en el siguiente ejemplo.

El cdigo ASCII de '&' es 46 y en binario se representa 1 0 1 1 1 0 entonces en


memoria queda
0 0101110
A una secuencia de caracteres se le denomina cadena y una cadena
normalmente se coloca entre comillas (" "), por ejemplo "Introduccin a las
tcnicas de Programacin". Las cadenas pueden estar compuestas de letras,
caracteres especiales, nmeros o signos de puntuacin y su longitud es
variable.

Booleanos
El tipo de dato booleano consiste en datos que slo pueden tener uno de dos
valores, cierto o falso (true or false). La representacin de almacenamiento
para un dato de tipo booleano ocupa un slo bit. Puesto que los bits
individuales pueden no ser direccionables por separado en la memoria, esta
representacin de almacenamiento se suele aplicar para que sea una sola
unidad direccionable, como un byte o una palabra.
Normalmente la representacin en la computadora de un dato de tipo booleano
se logra utilizando un bit particular para el valor, con frecuencia es el bit del
signo, con 0 es falso , con 1 es verdadero.
Otra forma de representacin puede ser colocar un valor cero en la unidad de
almacenamiento completa para indicar falso y cualquier otro valor diferente de
cero ser cierto.

Operadores
Una computadora debe de contener un conjunto de operaciones primitivas
interconstruidas. Un conjunto tpico incluir primitivas para aritmtica sobre
cada tipo numrico de datos, por ejemplo, suma, resta, multiplicacin, divisin
de reales y enteros.
Existen operadores binarios y operadores monoario. Los binarios son los que
tienen dos operandos y un operador, por ejemplo
a+b
el operador suma (+) es binario ya que tiene el operando a y el operando b. Los
operadores monoarios son los que tiene un slo operando, por ejemplo el
operador menos para indicar los nmeros negativos
-8

el signo - solo tiene el operando 8.


Los operadores se han clasificado en operadores de asignacin, aritmticos,
relacionales y operadores lgicos, en seguida se mostrarn.

Operador de Asignacin
La asignacin es la operacin bsica para cambiar el valor a una variable. La
asignacin en algunos lenguajes es representada por el operador '=', como es
el caso de C, pero Pascal utiliza el ":=".Veamos el siguiente ejemplo
a=b
en este caso el valor que tenga 'b' ser asignado a la variable 'a', la cual
perder cualquier valor previo que pudiese tener.

Operadores aritmticos
Dentro de los operadores aritmticos podemos mencionar la suma, la resta, la
multiplicacin, la divisin o cociente, el mdulo, la potencia y radicales. Cada
lenguaje emplea sus caracteres especiales para representarlas por ejemplo:
La suma se representa con el smbolo + en casi todos los lenguajes, y se utiliza
para indicar un incremento, por ejemplo
x=a+b
en este caso al valor de a se le incrementar el valor de b y el resultado se
asignar a la variable x.
La resta se representa con el smbolo - , y se utiliza para decrementar, ejemplo
x=a-b
en este caso al valor de a se le resta el valor de b y el resultado se asigna a la
variable x.
En cuanto a la multiplicacin normalmente se representa con el smbolo *, y se
utiliza para multiplicar, ejemplo
x=a*b
en este caso el valor de a es multiplicado por el valor de b y el resultado es
asignado a la variable x.

Por otra parte la divisin en algunos lenguajes se representa con el smbolo /, y


se utiliza para dividir, ejemplo
x=a/b
en este caso el valor de a es dividido entre el valor de b y el resultado es
asignado a la variable x.
Otra operacin muy utilizada es el mdulo y se representa segn la sintaxis del
lenguaje, en C se utiliza el smbolo %, y se utiliza para obtener el residuo del
conciente, ejemplo
x=7%2
en este caso el valor del residuo del cociente de 7 / 2 es 1 el cual es asignado a
la variable x.
Otro operador es el de potencia y el smbolo que se utiliza depende del
lenguaje, por ejemplo FORTRAN usa **, y se utiliza para multiplicar a la base el
numero de veces que indique el exponente, ejemplo
x = a ** 4
en este caso el valor de la base es a y el exponente es 4, lo que implica que el
resultado de multiplicar a*a*a*a ser asignado a la variable x. En algunos
lenguajes este tipo de operacin es una funcin a la cual se le pasa la base y el
exponente, la funcin devuelve el resultado de multiplicar a la base tantas
veces como lo marque el exponente.
En cuanto a los radicales su representacin depende del lenguaje, y se utiliza
para obtener la raz del operando. En algunos lenguajes este tipo de operacin
es una funcin a la cual se le pasa un valor, la funcin devuelve el resultado de
la raz. Por ejemplo, C utiliza la funcin sqrt() para obtener la raz cuadrada del
dato deseado
x = sqrt(4)
en este caso la raz cuadrada de 4 es 2 que ser asignado a la variable x.

Operadores relacionales
Los operadores relacionales son operadores binarios y son utilizados para
verificar si una expresin es mayor que otra, o es menor que, o es mayor o
igual, o es menor o igual, o diferente de, o igual que. En el caso de lenguaje C
los smbolos utilizados para ellos son
El "mayor que" se representa con el smbolo >, por ejemplo a > b y da como
resultado un verdadero si el valor de a es mayor estrictamente que el valor de
b, es falso en caso contrario.

El "menor que" se representa con el smbolo <, por ejemplo a < b y da como
resultado un verdadero si el valor de a es absolutamente menor que el valor de
b, es falso en caso contrario.
Por otra parte el "mayor o igual" se representa con el smbolo >= , por ejemplo
a >= b y da como resultado un verdadero si el valor de a es mayor o igual que
el valor de b, es falso en caso contrario.
En cuanto al "menor o igual" se representa con el smbolo <=, por ejemplo a <=
b y da como resultado un verdadero si el valor de a es menor o igual que el
valor de b, es falso en caso contrario.
Para verificar si dos expresiones son diferentes se utiliza el operador !=, por
ejemplo a != b y da como resultado un verdadero si el valor de a es diferente al
valor de b, es falso en caso contrario.
De manera similar, para verificar si dos expresiones son iguales se utiliza el
operador ==, por ejemplo en la expresin a == b y da como resultado un
verdadero si el valor de a es igual al valor de b, en caso contrario es falso.
En FORTRAN el "mayor que" se representa con .GT., el "menor que" se
representa con .LT., el "mayor o igual" .GE., el "menor o igual" con .LE., el
"diferente " con .NE. y el "igual" con EQ. Por lo tanto se debe averiguar la
forma de representar a los operadores relacionales en el lenguaje que se est
utilizando.

Operadores lgicos
Estos operadores estn conformados por el AND, OR y NOT, y su resultado es
uno de los valores lgicos (Falso o Verdadero). Los resultados de evaluacin
se muestran en la siguiente tabla de verdad.
a b a OR a AND NOT a NOT b
b
b
0 00

0 11

1 01

1 11

Donde el 0 se interpreta como falso (false) y el 1 como verdadero (true). En el


lenguaje C, el AND se representa con && , el OR con || y el NOT con ! .
Ejemplo:

((a>0) && (a < 100))


dependiendo del valor de a la expresin puede ser falsa o verdadera, siguiendo
la tabla anterior. Esto es si a=50, entonces la expresin es verdadera, pero si
a=200 la expresin es falsa.

Precendencia de operadores y evaluacin de expresiones


Por precedencia de operadores se entiende a que operador se ejecuta primero
en una expresin durante la ejecucin de un programa. La precedencia para
los operadores aritmticos se muestra en la siguiente tabla
Mas alta
negativos)

(para nmeros

^ (exponente)
* / %
Mas baja

+ -

Lo que significa que en la siguiente expresin


a+b/c
primero se desarrollar el cociente b / c , y en luego el resultado ser
incrementado a la variable a.
En cuanto a la precedencia de los operadores relacionales y lgicos el orden
queda como se muestra a continuacin
Mas alta

! (negacin)
==

!=

respectivamente)
< > >= <=
&&
Mas baja

||

Por lo tanto en la expresin siguiente

(igual que y diferente

a==b && b!= 0 || a> 100


La expresin ser verdadera si a=5 y b=5, ya que primero se verifica que
a==b , luego se verifica que b!=0 es verdadera lo que deduce que la expresin
a==b && b!= 0 es verdadera y ya no se analiza la siguiente parte de la
expresin, porque como se pudo ver en la tabla de verdad slo debe de existir
un verdadero en el OR para que toda la expresin sea verdadera.
Pero si a=105 y b=5, primero se verifica que a==b es falso, sin verificar mas
se deduce que a==b && b!= 0 es falso, en esta ocasin es imperioso verificar
que a> 100 es verdadera, por lo tanto (a==b && b!= 0 || a> 100) es verdadera.
En el caso de que a=8 y b=5, primero se verifica que a==b es falso, sin
verificar mas se deduce que a==b && b!= 0 es falso, en seguida se verifica que
a> 100 es falso, por lo tanto (a==b && b!= 0 || a> 100) es falsa
Observar que en los casos anteriores la evaluacin de las expresiones fue en
el orden que marca las reglas de precedencia de los operadores.

Uso de parntesis
El orden de precedencia de los operadores puede ser cambiada con el uso de
los parntesis, vemoslo en el siguiente ejemplo
En la expresin
a-b+c*d
Por la precedencia de operadores, primero se ejecutar el producto c * d, en
seguida el resultado se sumar a b y el valor obtenido se restar a la variable
a. Es decir, si a=5, b=3, c=2 y d=4 entonces el resultado de la operacin de la
primera expresin sera c*d= 2*4 = 8, en seguida se ejecutara b+8=3+8=11 y
este resultado ser restado a a -11= 5-11= - 6.
Pero si a la misma expresin le agregamos los parntesis
(a - b + c) * d
independientemente de las reglas de precedencia de operadores, primero se
ejecutar lo que est entre parntesis (a - b + c) ,en seguida el resultado se
multiplicar con la variable d. Es decir, si a=5, b=3, c=2 y d=4 entonces el
resultado de la operacin (a - b + c) = (5-3+2)= 4 , luego se ejecutar
4*d=4*4=16. Como se puede observar el uso de los parntesis no slo altera el
orden de precedencia de los operadores sino tambin altera el resultado de las
operaciones.

2.3 Palabras reservadas del lenguaje

{lzklmlzkmzl
k

2.4

Tipos

de

datos

definidos

por

el

usuario

2.4.1 struct

En C una estructura es una coleccin de variables que se referencian bajo el


mismo nombre. Una estructura proporciona un medio conveniente para
mantener junta informacin relacionada. Las variables que conforman la
estructura son llamados elementos estructurados. Para definir una estructura
struct
dire
{
char
nombre
[30];
char direccion [50];
char
estado
[3];
unsigned
long
int
codigo;
};

Generalmente todos los elementos en estructura son relacionados lgicamente


unos con otros. Por ejemplo, se puede representar normalmente la informacin
de nombre y direccin de una lista de correo en una estructura. Este fragmento
de cdigo declara la plantilla de la estructura que define los campos nombre y
direccin. La palabra clave struct dice al compilador que se est definiendo una
plantilla de escritura.
Observar que la definicin termina en punto y coma. La razn para el punto y
coma es que para una definicin de estructura es una sentencia, adems, la
estructura dire identifica esta estructura de datos particular y es especificador
de tipo.
En este momento del cdigo, realmente no ha sido declarada ninguna variable.
El cdigo slo ha definido el formato de los datos. Para declarar una variable
real con esa estructura, se escribir:
struct dire mivar;
Esta lnea declara la variable mivar de tipo estructura dire , la cual se
representar en memoria con cinco campos: uno para nombre con 30
caracteres (30 bytes), otro para direccin con 50 caracteres (50 bytes), uno
para estado con 3 caracteres (3 bytes) y uno para cdigo (4 bytes)

mivar
30 bytes
nombre

50 bytes
direccin

3 bytes
estado

4 bytes

cdigo

Cuando se define una estructura, esencialmente se define un tipo de variable


compleja que compone la estructura de los elementos. Slo cuando se declare
una variable de ese tipo existir realmente.
Se puede declarar una o ms variables cuando se define una estructura. Por
ejemplo:
struct
dire
{
char
nombre
[30];
char direccion [50];
char
estado
[3];
unsigned
long
int
codigo;
} info_dire, binfo, cinfo;

Este cdigo define un tipo de estructura llamado dire y declara las variables
info_dire, binfo y cinfo del mismo tipo.
El formato general de una definicin de estructura es:
struct nombre_de_estructura
{
tipo
nombre_variable1;
tipo
nombre_variable2;
tipo
nombre_variable3;
.
.
.
} variables_estructuras ;
Donde se puede omitir el nombre de la estructura tipo nombre_de_estructura y
las variables_estructura, pero no ambas
Se referencian elementos individuales de la estructura usando el operador
punto (.). Por ejemplo, el siguiente cdigo asignara el cdigo postal 12345 al
campo correspondiente de la variable estructura info_dire que se declar antes
info_dire. codigo = 12345 ;

El nombre de la variable estructura, que se sigue por un punto y el nombre del


elemento referenciar ese elemento individual de estructura. Se accede a los
elementos de estructura usando este formato. El formato general es:
nombre_estructura.nombre_elemento
por lo tanto, para imprimir el cdigo postal en la pantalla, se escribir:
printf (" %d ",info_dire.codigo);
que imprimir el cdigo postal dentro del cdigo postal de la variable
estructurada info_dire.
En el mismo sentido, se puede usar el carcter matriz info_dire.nombre para
llamar a gets (), como se muestra a continuacin:
gets (info_dire.nombre);
Esta llamada gets () pasar a un puntero de un caractr al comienzo del
elemento
nombre.
Para acceder a los elementos individuales de info_dire.nombre. se podr
indexar nombre. Por ejemplo, se puede imprimir los elementos de
info_dire.nombre de caractr en caractr usando este cdigo:
int t;
for (t=0; info_dire.nombre[t] ; ++t) putchar (info_dire.nombre[t]) ;

2.4.2 typedef
Turbo C permite definir nuevos nombres de datos explcitamente usando la
palabra clave typedef. Realmente no se est creando una nueva clase de
datos, sino un nuevo nombre para un tipo existente. Este nuevo proceso puede
ayudar a hacer programas independientes de la mquina, i.e. ms portables;
slo se necesita cambiar las sentencias typedef, el formato general es:
typedef nombre_de_tipo;
donde nombre_de_tipo es cualquier tipo de dato y nombre es el nuevo nombre
para ese tipo. El nombre que se define es adems, y no reemplazable, por el
nombre de tipo existente.
Por ejemplo, se podra crear un nuevo nombre para float usando
typedef float balance;

Esta sentencia le dice al compilador reconocer balance como otro nombre para
float . Despus podra crear una variable float usando balance:
balance over_due;
Aqu over_due es una variable en punto flotante de tipo balance, que es otra
palabra para float.
Se puede usar typedef para crear nombres para tipos mas complejos, todava
como se muestra aqu:
typedef struct client {
float due;
int over_due;
char name [40];
};
clien clist [NUM_CLIENTS]; /*define el array clist de estructuras de tipo struct
client*/
Usando typedef puede ayudar a que el cdigo sea ms legible y fcil de portar
a una mquina nueva. Sin embargo, recordar que no se est creando ningn
tipo de datos nuevo.
Ahora que se ha visto el poder de personalizar los tipos de datos de Turbo C,
se esta preparando para pasar a los operadores avanzados de este mismo

2.4.3 unin
En C, una unin es una posicin de memoria que se usa para varias variables
similares, que pueden ser de tipos diferentes. La definicin de unin es similar
a la de una estructura, como se demuestra a continuacin:
union u_tipo {
int i;
char ch;
};
Como con una declaracin de estructura, esta definicin no declara ninguna
variable. Se puede declarar una variable poniendo su nombre al final de la
definicin o usando una sentencia separada de declaracin. Para declarar una
variable unin cnvt de tipo u _ tipo usando la definicin, que se escribira:
unin u_tipo cnvt
En cnvt, tanto el entero i y carcter ch comparten la misma posicin de
memoria. (sin embargo , ocupa dos bytes y ch solo uno). La figura siguiente
muestra la forma en que i y ch comparten la misma direccin.

cnvt

2 bytes para el entero i


1 byte para el char ch

Cuando se declara una unin, C crear automticamente una variable lo


suficientemente grande para que quepa el tipo de variable mas largo en la
unin.
Para acceder a un elemento de unin () se usa la misma sintaxis que se usara
para guardar el tipo mas grande de variable.
Para acceder al elemento unin se usa la misma sintaxis que se usa para las
estructuras: el operador de punto y el operador de flecha (si se usa puntero a
union)
Elemento de unin directamente, usar el operador de punto. Si se accede a
unin a travs de un puntero, usar el operador de flecha. Por ejemplo, para
asignar el entero 10 al elemento i de cnvt, se escribir:
cnvt.i=10;
En el ejemplo siguiente, el cdigo pasa a un puntero para cnvt a la funcin:
funcl
un->
}

i=10;

(unin
/*asigna
1-

cnvt

u_tipo
usando

un

*un){
puntero
*/

Usando una unin puede ayudar en la produccin y la de la independencia de


la mquina o portable. Como el compilador mantiene la pista del tamao de las
variables que constituyen la unin, el uso de dicha unin no produce
dependencias de la maquina. No necesita preocuparse del tamao de un
entero, un carcter, una variable en punto flotante o similares.
En C se usan frecuentemente las uniones cuando las conversiones de tipo son
necesarias.

2.5 Estructuras de control

2.5.1 if
La sentencia if funciona de la misma manera en casi todos los lenguajes.
Su forma ms sencilla es
if (condicin) sentencia
donde condicin es una expresin que se evala de falsa o verdadera (en el
lenguaje C, verdadero es no cero y falso cero). Ejemplo
if (10 < 11) printf ("10 es menor que 11")
En la lnea anterior, la condicin es verdadera por lo tanto se imprimir
en pantalla el mensaje dado en la instruccin printf de C.
Otra forma de manejar a la sentencia if es recurriendo al else que se lee
"si no", y en su caso ejecutar las instrucciones en caso de que la condicin
sea falsa, su estructura general es
if

(condicin)
ejecuta sentencia(s) si la condicin es verdadera

else
ejecuta sentencia(s) si la condicin es falsa

Ejemplo
if

(n
<
printf ("%d es menor que 11", n);

11)

else
printf ("%d es mayor o igual que 11", n);
En el ejemplo depender del valor que tome n para ejecutar la instruccin
indicada.

Por ltimo, veremos la sentencia if en su forma anidada, su estructura


general es
if

(condicin
1)
ejecuta sentencia(s) si la condicin 1 es verdadera

else
ejecuta
...

if
sentencia(s)

si

(condicin
la
condicin

2)
es
verdadera

else

if
(condicin
ejecuta sentencia(s) si la condicin-n es verdadera

n)

else
ejecuta sentencia(s) si las condiciones de la 1 a la n fueron falsas

Ejemplo
if

((n>=0)&&(n
<
11))
printf ("%d es mayor o igual que 0 pero menor que 11", n);

else

if
((n>=11)&&(n
<
20))
printf ("%d es mayor o igual que 11 pero menor que 20", n);

else

if
((n>=21)&&(n
<
30))
printf ("%d es mayor o igual que 21 pero menor que 30", n);

else
printf ("%d es mayor o igual 30", n);
En el ejemplo depender del valor que tome n para ejecutar la instruccin
indicada.

En seguida veremos las sentencias de ciclo, tambin denominadas bucles,


permiten ejecutar en forma repetitiva (o iterativa) el conjunto de instrucciones
definidas dentro de ellas. Son ejemplo de estas sentencias el while, do-while y
for, que enseguida se describirn.

2.5.2 for
El bucle for presenta la siguiente estructura en su forma ms sencilla es
for (inicializacin, condicin, incremento) sentencia;
donde inicializacin establece la variable de control del bucle a un valor. La
condicin es una expresin que se evala de falsa o verdadera cada vez que
se repite el bucle. Se mantiene el bucle en funcin mientras la condicin es
verdadera. La porcin incremento incrementa la variable de control. Ejemplo
int contador;
for(contador =1; contador<=100; contador++) printf (" % d", contador);
En la lnea anterior, el contador se inicializa con 1, cada vez que se repite
el bucle, el programa comprueba la condicin contador <=100. Si la condicin
es verdadera, el program ejecuta la sentencia printf() e incrementa en uno al

contador. Cuando contador es ms grande que 100, la condicin el falsa y el


bucle se detiene. Se imprimirn en pantalla los nmeros del 1 al 100.

2.5.3 while
El bucle while presenta la siguiente estructura en su forma ms sencilla es
while (condicin) sentencia;
donde sentencia puede ser una sentencia vaca, una sentencia nica o un
bloque de sentencias que se repetirn. La condicin es una expresin que se
evala de falsa o verdadera cada vez que se repite el bucle. El bucle itera
mientras la condicin sea verdadera. Cuando llega a ser falsa, el control del
programa pasa a la lnea que sigue al bucle. Ejemplo
int con=0;
while(con != -1) scanf(" % d", &cont);
En la lnea anterior, la variable con se estar leyendo indefinidamente
hasta que el usuario introduzca un -1.
El while comprueba la condicin en lo alto del bucle, lo que significa que
el cdigo del mismo no se ejecuta siempre. Por esta razn es necesario
inicializar a con=0 antes del while.

2.5.4 do
Al contrario del while el bucle do-while examina la condicin en la parte
baja. Esta caracterstica provoca que el do-while siempre se ejecute al menos
una vez . La forma general del bucle es
do{
sentencia
} while (condicin) ;
La condicin es una expresin que se evala de falsa o verdadera cada vez
que se repite el bucle. El bucle itera mientras la condicin sea verdadera.
Cuando llega a ser falsa, el control del programa pasa a la lnea que sigue al
bucle. Ejemplo
int con;
do {
scanf(" % d", &cont)

}while(con != -1) ;
En la lnea anterior, la variable con se estar leyendo indefinidamente
hasta que el usuario introduzca un -1 . La diferencia con el ejemplo del while es
que en este caso no necesita inicializarse la variable cont ya que se ejecuta al
menos una vez el cdigo interno del bucle.

2.6 Funciones
El formato general de una funcin en lenguaje C es
tipo_de_dato_que_devuelve_la
(lista_de_parmetros)

_funcion

nombre_de_funcin

{
cuerpo

de

la

funcin

}
El tipo_de_dato_que_devuelve_la _funcion especifica el valor que la funcin
devolver mediante el uso de return. El valor puede ser de cualquier tipo valido.
Si no se especifica un valor, entonces la computadora asume por defecto que
la funcin devolver un resultado entero.
La lista_de_parmetros es una lista de nombres de variables separados por
comas que recibe los valores de los argumentos cuando se llama a la funcin.
El tipo de dato de la declaracin debe anteponerse a las variables.
Las funciones terminan y devuelven el control automticamente al
procedimiento que las invoca, precisamente a la siguiente lnea de donde
fueron llamadas.

2.6.1 La sentencia return


La sentencia return tiene dos usos importantes. Primero se puede usar para
provocar la salida inmediata de la funcin en la que se esta; es decir return
provocar que el programa en su ejecucin vuelva al cdigo que llam a la
funcin en el sitio que lo hizo. Segundo se puede usar return para devolver un
valor.
a) Volviendo desde una funcin
Hay dos formas en las que una funcin termina y vuelve al cdigo que la llam.
La primera, la computadora ejecuta la ltima sentencia de la funcin y
entonces, conceptualmente, encuentra el terminador de la funcin.
La segunda forma es a travs de la sentencia return. Se puede usar esta
sentencia sin ningn valor asociado.

Una funcin puede tener varias sentencias return, si embargo; se cuidadoso:


teniendo demasiadas sentencias return se puede enturbiar el funcionamiento
de una rutina y confundir su significado. As lo mejor es usar mltiples
sentencias return slo cuando ayudan a clarificar una funcin.
b) Valores devueltos
Todas las funciones excepto las que se declaran de tipo void devuelven un
valor. Este valor es definido explcitamente por una sentencia return, o es 0 si
no se usa tal sentencia. As mientras no se declare una funcin como void se
puede usar como un operando en cualquier expresin valida de C.
Aunque todas las funciones que no son de tipo void devuelven valores, las
funciones que se escribirn habitualmente sern de tres tipos. El primero es
simplemente de clculo. Se disea esta funcin especficamente para realizar
las operaciones sobre sus argumentos y devolver un valor basado en esa
operacin -en esencia, es una funcin "pura"-. Ejemplos de este tipo de funcin
son las funciones de biblioteca sqrt( ) y sin( ) que devuelven la raz cuadrada de
un nmero y su seno respectivamente.
El segundo tipo de funciones manipula informacin y devuelve un valor que
indica simplemente si esta manipulacin sali bien o fallo. Ejemplo es fwrite( ),
que se usa para escribir informacin sobre un archivo de disco. Si tiene xito la
operacin de escritura, entonces fwrite( ) devuelve el nmero de bytes que se
pidi que se escribieran: cualquier otro valor indica que ha ocurrido un error.
Ejemplo:
main
(
)
{
int
x,
y;
printf("dame un numero o entero");
scanf("%d",&x);
y=
potencia(x);
printf("El cuadrado de %d es %d", x, y);
getch(
);
}
int
potencia
{
int
resul=p*p;
return

(int

p)
resul;
(resul);

2.6.2 Reglas de mbito de las funciones


El cdigo que comprende el cuerpo de la funcin esta oculto al resto del
programa y -a menos que el cdigo use variable o datos globales- no puede
afectar ni ser afectado por otras partes del programa.

Hay tres tipos de variables: variables locales, parmetros formales y variables


globales.
a) Variables locales
Como se sabe las variables que se declaran dentro de una funcin se llaman
variables
locales.
Una variable se puede declarar en un bloque de cdigo y ser local a ese
bloque. As las variables locales no son conocidas fuera de su propio bloque de
cdigo y su mbito esta limitado al bloque en el que se declaran.
Una variable local se crea al entrar en su bloque y se destruye despus de
salir.
El lenguaje C contiene la palabra clave auto, que se puede usar para declarar
variables locales.
La principal ventaja de declarar una variable local en un bloque condicional es
que la computadora asignar memoria para la variable slo si se necesita. La
razn para esto es que las variables locales no existen hasta que la
computadora entra en el bloque en que se declaran.
Como la computadora crea y destruye las variables locales con cada entrada y
salida del bloque en que se declara, sus contenidos se pierden una vez que la
computadora
deja
el
bloque.
As las variables locales no pueden retener sus valores entre llamadas.
b) Parmetros formales
Si una funcin usa argumentos entonces se deben declarar las variables que
aceptarn los valores de los argumentos. Estas variables se llaman parmetros
formales de la funcin.
Asegurarse que los parmetros formales que se declaran son del mismo tipo
que los argumentos que se usarn en la llamada de la funcin.
Una segunda forma de declarar parmetros en el estndar ANSI (y turbo c)
permite una variacin en la forma que permite declarar parmetros en las
funciones. Se puede poner la declaracin entera de cada parmetro dentro del
parntesis que se asocia con la funcin.
c) Variables globales
Al contrario de las variables locales las globales se conocen en el programa
entero y se pueden usar en cualquier funcin. En esencia su mbito es global
al programa. Las variables globales tambin guardarn sus valores durante la
ejecucin entera del programa. Se pueden crear variables globales
declarndolas fuera de cualquier funcin. Cualquier funcin puede acceder a
ellas sin tener en cuenta en que funcin este dicha expresin.

Las variables globales son tiles cuando se usa el mismo dato en muchas
funciones del programa. Sin embargo se debera evitar el uso innecesario de
las variables globales por tres razones: primera, ocupan memoria durante toda
la ejecucin del programa y no slo cuando se necesita; segunda, el uso de la
variable global en lugar de una local restringir la generalidad de una funcin
ya que depende de una variable que debe definirse fuera de s misma; tercera,
usando una serie grande de variables globales se pueden conducir a errores de
programa con efectos laterales desconocidos e indeseables.
Ejemplo:
/*prototipo
de
la
int potencia (int base, int potencia);

funcin*/

void
main(
)
{
int
y;
/*variable
local*/
clrscr(
);
for
(y=1;
y<=10;
y++)
{
printf("El cuadrado de %d es %d",y);
potencia (y, 2);
/*parmetros reales*/
}
getch(
);
}
int
potencia
(int
base,
int
potencia)
/*base y potencia son parmetros formales*/
{ int
x;
int
prod=1;
for
(x=1;x<=potencia
;x++)
{
prod=
prod*
base;
}
return(prod);
}

2.6.3 Argumentos de funciones


Como se ha visto anteriormente se debe asegurar que los parmetros formales
de funcin son del mismo tipo que los argumentos que se usan en la llamada a
la funcin (conocidos como parmetros reales). Si hay un error de tipo el
compilador no dar un mensaje de error pero se producirn resultados
inesperados. En el lenguaje C los parmetros pueden se pasados por valor o
referencia, como se establece a continuacin.
Llamada por valor y llamada por referencia

En general se puede pasar argumentos a funciones en uno de los dos sentidos.


La primera forma es denominada llamada por valor. Este mtodo copia el valor
de un argumento en el parmetro formal de la subrutina. Por tanto, los cambios
que se hacen a los parmetros de la subrutina no tienen efecto en las variables
que usa para llamarla.
La segunda forma en la que se puede pasar los argumentos a una subrutina es
llamada por referencia. Este mtodo copia la direccin de un argumento en el
parmetro. Dentro de la subrutina, la direccin se utiliza para acceder al
argumento real usado en la llamada. Esto significa que lo que se hace con el
parmetro afectar la variable que se usa para llamar a la subrutina.
El lenguajes C usa el mtodo de la llamada por valor por default para pasar
argumentos. En general, dando este mtodo no se permite alterar las variables
usadas para llamar a la funcin.

Creando una llamada por referencia


Incluso aunque la convencin de paso de parmetro de C se llama por valor, se
puede simular una llamada por referencia pasando un puntero al argumento.
Como este proceso provocar que la computadora pase la direccin del
argumento a la funcin, se puede cambiar el valor del argumento fuera de la
funcin.
Llamando funciones con arreglos
Cuando se usa un arreglo como un argumento a la funcin, se pasa slo la
direccin del arreglo y no copia el arreglo entero. Cuando se llama a una
funcin con un nombre de arreglo, se pasa un puntero al primer elemento en el
arreglo de la funcin.
Esto significa que la declaracin de parmetro debe ser de un tipo puntero
compatible. Hay tres formas de declarar un parmetro que se recibir como un
puntero de arreglo.

Primero se puede declarar como un arreglo. Ejemplo:

/*prototipo de la funcin*/
imprime(int num[10]);
main(
)
{
int t [10], i;
for(i=0;
i<10;i++)
t[i]=1;
imprime(
t
);
}

imprime(int
{
int
for(i=0;
printf ("
}

num[10])

%d

i;
i<10;i++)
", num[i)];

Una segunda manera de declarar un parmetro arreglo es


especificar el parmetro como un arreglo sin tamao. Ejemplo:

/*prototipo
de
la
funcin*/
imprime(int num[10]);
main(
)
{
int t [10], i;
for(i=0;
i<10;i++)
t[i]=1;
imprime(
t
);
}
imprime(int
num[
])
{
int
i;
for(i=0;
i<10;i++)
printf (" %d ", num[i)];
}
El ltimo camino en que se puede declarar un parmetro arreglo,
y la forma ms comn en los programas C escritos profesionales,
es un puntero. Ejemplo:

/*prototipo de la funcin*/
imprime(int num[10]);
main(
)
{
int t [10], i;
for(i=0; i<10;i++) t[i]=1;
imprime(
t
);
}
imprime(int
*num)
{
int
i;
for(i=0;
i<10;i++)
printf (" %d ", num[i)];
}

Es importante entender que cuando se pasa un arreglo como un argumento de


una funcin, la computadora pasa la direccin del arreglo a una funcin. Este
punto es una excepcin a la convencin de paso de parmetro de la llamada
por valor. As el cdigo dentro de la funcin estar funcionando y
potencialmente alterando los contenidos reales del arreglo que se ha usado
para llamar a la funcin.

2.6.4 Los argumentos argc y argv de main( )


A veces es til pasar informacin a un programa cuando se ejecuta.
Generalmente se pasa informacin a main( ) usando los argumentos de la lnea
de ordenes. Un argumento de lnea de rdenes es la informacin que sigue al
nombre del programa en la lnea de rdenes del sistema operativo.
El parmetro argc mantiene el nmero de argumentos de la lnea de ordenes y
es un entero. Siempre es al menos uno ya que el nombre del programa se
erige en el primer argumento. El parmetro argv es un puntero a un array de
punteros de caracteres. Los corchetes vacos indican que argv es un array de
longitud indeterminada.
Usualmente
se
usa
argc
393939393939393939393939393939`b 39

y395@

40bjbj22404040404040404040404040404040404040

41
.X41X4141X4141`Z
4141414141414141414141414141414141414141414141414141414141 4
14141414141414141 414141414141414141 4141414141414141414141
414141414141414141414141414141414141414141414141414141414141414
141414141414141414141414141

4141414141414141414141414141414141

4141414141

4141414141

414141414141414141414141414141`b 41

4141414141
4141415@

42bjbj22424242424242424242424242424242424242

43.X43X4343X4343`Z
4343434343434343434343434343434343434343434343434343434343 4
34343434343434343 434343434343434343 434343434343434343434
343434343434343434343434343434343434343434343434343434343434343
4343434343434343434343434343 434343434343434343434343434343434
3 4343434343 4343434343 4343434343 4343be usar un proceso de dos
pasos. Primero, se debe dar un especificador explcito de tipo a una funcin;
segundo, se puede identificar el tipo de la funcin antes de hacer la primera
llamada. Este proceso es la nica manera para que el compilador C pueda
generar el cdigo correcto para funciones que devuelven valores no enteros.
Se puede declarar las funciones para devolver cualquier tipo valido de datos. El
mtodo de declaracin es similar al mtodo que se usa para las variables: el
especificador de tipo precede al nombre de funcin. El especificador de tipo le
dice al compilador que tipo de datos devolver la funcin. Esta informacin es
crtica si el programa va a funcionar correctamente ya que diferentes tipos de
datos tienen tamaos y representaciones internas diferentes.
Antes de poder usar una funcin que envuelve un tipo no entero, se debe dar a
conocer el tipo al resto del programa. La razn para hacer esto es fcil de
entender. Mientras no se indique lo contrario, Turbo C asumir que una funcin
va a devolver un valor entero. Si el programa llama a una funcin que devuelva
un tipo diferente antes de la declaracin de la funcin, entonces el compilador
generar el cdigo errneo para la llamada de la funcin. Para prevenir este
fallo se debe poner cerca de principio del programa un formato especial de la
sentencia de declaraciones para decirle al compilador que valor de la funcin
se devuelve realmente. Ejemplo:
float
sum(
);
main(
)
{
float
primero,
segundo;
primero=
123.23;
segundo=
99.09;
printf("
%f
",sum(primero,
segundo));
}
float sum(float a, float b)
{
return
a+b;
/*suma
de
flotantes*/
}

2.6.6 Devolviendo punteros

Aunque se manejan las funciones que devuelven punteros exactamente en la


misma forma que cualquier otro tipo de funcin, se necesita discutir algunos
conceptos importantes.
Los punteros a variables no son ni enteros, ni enteros sin signo. Son
direcciones de memoria de ciertos tipos de datos. La razn para esta distincin
reside en el hecho de que, cuando la computadora realiza la aritmtica de
punteros es relativo el tipo de base; es decir, si se incrementa un puntero
entero, contendr un valor 2 veces mayor que su valor anterior.
Generalizando, cada vez que un puntero se incrementa, apuntar al siguiente
dato de su tipo. Como cada tipo de dato puede ser de diferente longitud, el
compilador debe saber que tipo de dato esta apuntando el puntero para
apuntar exactamente al dato siguiente. Ejemplo:
char
*match(
main(
{
char
s[80],
gets(s);
ch=getche(
p=match(ch,
if(p)
printf("
%s
else
printf("coincidencia no
}

);
)
*p,ch;
);
s);
",p);
encontrada");

2.6.7 Funciones de tipo void


Una de las extensiones al viejo estndar UNIX para C es el tipo de datos void.
Uno de sus usos es para declarar explcitamente las funciones que no
devuelven valores. Usando void se evita el uso de estas funciones en cualquier
expresin y ayuda a evitar errores accidentales.
Antes de que se pueda usar esta funcin -o cualquier otra funcin void- se
debe declarar. Si no, Turbo C asumir que se esta devolviendo un entero. As,
cuando se alcance realmente la funcin, el compilador declarara un fallo de
tipo. Ejemplo:
void
imprime_vertical(
main(
{
imprime_vertical("hola");
}

);
)

void imprime_vertical(char *str)


{
while(*str)
printf("
%c
\n",
*str++);
}

2.6.8 Prototipo de funcin


Como se sabe, antes de usar una funcin que devuelva un valor distinto de int,
se debe definir. En Turbo C se puede tomar esta idea un paso por delante
declarando tambin el nmero y tipos de los argumentos de la funcin. Esta
definicin expandida se llama un prototipo de funcin. Los prototipos de funcin
no son parte de UNIX C original, pero fueron aadidos por el comit del
estndar ANSI. Habilitan C para proporcionar comprobacin rigurosa de
comprobacin de tipo similar a la proporcionada por lenguajes tales como
Turbo Pascal. En un lenguaje fuertemente tipado, el compilador emite errores si
se llama una funcin con argumentos de tipo que son diferentes de los
definidos.
Generalmente, es una buena idea usar prototipos de funcin en programas
ms grandes o en esas situaciones donde estn trabajando varios
programadores
en
el
mismo
proyecto.
Ejemplo:
void func(int p, float q);
main(
{
int
x=10;
func(x,
}

)
x,

y;
y=10;
y);

void func(int p, float q)


{
printf("%f %f ", p , q);
}

2.6.9 Pasando de estructuras a funciones


Cuando se pasa un elemento de una variable de estructura a una funcin,
realmente se pasa el valor de ese elemento. As que se est pasando una
variable simple- a menos que ese elemento sea complejo, como una matriz de
caracteres-. Por ejemplo considerar esta estructura:

struct
char
int
float
char
} mike;

fred{
x;
y;
z;
s[10];

esta es la manera en que se pueden pasar cada elemento a una funcin


func (mike.x); /*pasa el valor carcter de x a la funcin func*/
func2 (mike.y); /*pasa el valor entero de y a la funcin func2*/
func3 (mike.z); /*pasa el valor float de z a la funcin func3*/
func4 (mike.s); /*pasa el valor de la cadena s a la funcin func4*/
inc (mike.s[2]); /*pasa el valor de carcter de s [2] a la funcin inc*/
sin embargo, para pasar la direccin de un elemento individual de estructura de
forma que se pueda pasar un parmetro de llamada por valor, se pondra el
operador & antes del nombre de variable. Por ejemplo para pasar las
direcciones de los elementos en la variable de estructura mike se escribira:
func (&mike.x); /*pasa la direccin de x a la funcin func*/
func2 (&mike.y); /*pasa la direccin de y a la funcin func2*/
func3 (&mike.z); /*pasa la direccin de z a la funcin func3*/
func4 (&mike.s); /*pasa la direccin s a la funcin func4*/
inc (mike.s[2]); /*pasa la direccin de s [2] a la funcin inc*/
El operador & precede el nombre de la variable de estructura y no al nombre
del elemento individual, observar que el elemento de la cadenas ya significa
una direccin de forma que el uso de & no se requiere en esa lnea de cdigo.

2.6.10 Pasando de estructuras enteras a funciones


Cuando se usa una estructura como argumento para una funcin. Turbo C
pasa la estructura entera usando el mtodo estndar de llamada por valor. Este
mtodo significa que cualquier cambio de contenido de la estructura dentro de
la funcin a la que se pasa dicha estructura no afecta a la estructura que se
usa como argumento.
La consideracin ms importante a tener en cuenta cuando se usa una
estructura como parmetro es que el tipo de argumento debe coincidir con el
tipo de parmetro. Por ejemplo, este programa declara el argumento arg y el
parmetro parm con el mismo tipo de estructura:
struct
int
char
} arg;

prueba{
a,b;
ch;

main
{
arg.a=1000;
f1
}

()
(arg);

void f1(struct prueba parm)


{
printf (" %d " , parm.x);
}
Este programa imprimir el nmero 1000 en la pantalla.

2.7 Arreglos
Un arreglo (array) es una coleccin de variables del mismo tipo que se
referencian utilizando un nombre comn. Normalmente los arreglos constan de
posiciones de memoria contiguas. Un arreglo puede tener una o varias
dimensiones. Para acceder a un elemento especfico de un arreglo se usa un
ndice.
Los arreglos son estructuras estticas de almacenamiento, ya que el tamao
que se les designa en tiempo de compilacin no puede aumentar o disminuir en
tiempo de ejecucin.

2.7 Arreglos unidimensionales


El formato general para la declaracin de un arreglo unidimensional vara en
cada lenguaje de programacin. Por ejemplo, en C se declaran con el formato
siguiente:
tipo nombre_de_arreglo [tamao]
en donde tipo determina el tipo de datos de cada elemento del arreglo, el
tamao define cuantos elementos se almacenarn en l. Por ejemplo
int ejemplo[10];
lo que significa que se reservarn 10 espacios de memoria contigua para
almacenar 10 enteros, como se muestra en la siguiente figura

En el lenguaje C, Java, etc., los arreglos usan cero como ndice del primer
elemento. Por ejemplo, el programa siguiente carga un arreglo de enteros con
los nmeros del 0 al 9.
main()
{
int x[10];
int i;
for (i=0; i<10; i=i+1)
{
x[i]=i;
}
for (i=0; i<10; i=i+1)
{
printf(" %i ", x[i]);
}
}
En este ejemplo, num[0] almacenar el valor 1, num[1] guardar el valor 2,
num[2] almacenar el valor 3, y as sucesivamente como se observa en la
imagen:

Para un arreglo bidimensional, se calcula el tamao total de un arreglo en bytes


as:
bytes_totales = tamao_en_bytes_del_tipo_de_datos * tamao_del_arreglo
Para almacenar al vector X se requieren de 2*10= 20 bytes
Los arreglos son muy comunes en programacin porque permite tratar
fcilmente muchas variables relacionadas.
5.3 No comprobacin de contornos
Aunque el lenguaje C no realiza comprobacin de contornos en los arreglos,
esto significa que si no se detiene la escritura fuera del final del arreglo, se
asignarn valores a otra variable o a un trozo del cdigo del programa, pues se
sobrepasa el final durante una operacin de asignacin.
Otra manera de ver este problema es: indexar un arreglo de tamao N por
encima de N sin provocar ningn mensaje de error en tiempo de compilacin o
ejecucin, incluso aunque se provoque el fallo del programa.
El programador deber asegurarse de que todos los arreglos sean lo
suficientemente grandes para guardar lo que pondr en ellos el programa,

adems de proporcionar las comprobaciones de contorno cuando sea


necesario:
/*
main()
{
int
for(i=0;
}

un

programa

incorrecto

crash[10],
i<100;

*/
i;
crash[i]=i;

i++)

Turbo C compilar y ejecutar el programa sin importar que el arreglo crash se


sobrepase; el bucle iterar cien veces a pesar de que crash tiene 10 elementos
de longitud.
5.4 Los arreglos unidimensionales son listas
Los arreglos unidimensionales son esencialmente listas de informacin del
mismo tipo:
char ch[7];
main()
{
int i;
for(i=0; i<7; i++) ch[i] = 'A'+i;
}
despus de ejecutar este programa, ch se ve as:
ch[0]
ch[1]
ABCDEFG

ch[2]

ch[3]

ch[4]

ch[5]

ch[6]

5.5 Cadenas
En C, una cadena consta de un arreglo unidimensional de caracteres que
termina en un nulo '\0' (generalmente cero), por lo tanto, se debern declarar
los arreglos de caracteres con un carcter ms que la cadena ms larga que se
vaya a guardar. Esto es:
Si se quiere declarar una arreglo str que guarde una cadena de diez
caracteres, se escribir de la siguiente forma:
char str[11];

ya que esta declaracin permite hacer un sitio para un nulo al final de la


cadena.
Las cadenas o listas de caracteres debern encerrarse entre dobles comillas,
por ejemplo la cadena de caracteres
"HOLA"
no se necesitar aadir el nulo manualmente al final de las constantes de
cadenas, ya que el compilador de Turbo C lo hace automticamente; as la
cadena se ver en memoria as:
H O L A '\0'
5.6 Leyendo una cadena desde el teclado
Para introducir una cadena desde el teclado se usar una funcin de biblioteca
llamada gets, su formato general es:
gets(nombre_arreglo);
gets puede usarse como el nombre de un arreglo, pero sin ningn ndice como
argumento. Despus de volver a gets(), el arreglo guardar la cadena que se
introduce desde el teclado. gets seguir leyendo caracteres hasta que se
introduzca un retorno de carro.
Ejemplo:
/* Un sencillo programa de cadenas */
main()
{
char str[80];
gets(str); /* lee una cadena desde el teclado */
printf("%s",
}

str);

este programa solo repite la cadena que se teclea. Se puede usar str como un
argumento para printf(). El programa usa el nombre del arreglo sin ndices. Si
se introduce una cadena ms larga que el tamao del arreglo, sta se
sobrescribe.
5.7 Algunas funciones de cadena de la biblioteca
Turbo C reconoce un amplio rango de funcin de manipulacin de cadenas, las
mas comunes son:

strcpy(
strcat(
strcmp(
strlen( )

)
)
)

- La funcin strcpy( ) utiliza el siguiente formato:


strcpy(a,desde);
y se usa para copiar los contenidos de la cadena desde a la cadena a. El
arreglo a deber ser lo suficientemente grande para guardar desde. Por
ejemplo:
main()
{
char
strcpy(str,
}

str[80];
"hola");

Este programa lo que hace es copiar "hola" en la cadena str.


-

La

funcin

strcat(

utiliza

el

siguiente

formato:

strcat(s1,s2);
esta funcin aade s2 al final de s1; s2 no se altera. Ambas cadenas terminan
con un nulo y el resultado termina en nulo. Por ejemplo:
main()
{
char first[20], second[10];
strcpy(first, "hola");
strcpy(second, "amigos");
strcat(s1, s2);
printf("%s",
}
Este programa imprimir hola amigos en la pantalla.
- La funcin strcmp( ) utiliza el siguiente formato:

s1);

strcmp(s1, s2);
sta funcin compara dos cadenas y devuelve 0 si son iguales. Si s1 es
lexicogrficamente mayor que s2, entonces la funcin devuelve un nmero
positivo; si s1 es menor que s2, la funcin devuelve un nmero negativo.
Tambin se puede utilizar como una rutina de verificacin de palabra de
acceso:
/* devuelve verdad si acepta la palabra de paso, falso */
password()
{
char s[80];
printf("introducir palabra de paso: ");
gets(s);
if(strcmp(s, "palabra de paso"))
{
printf("palabra de acceso invlida\n");
return 0;
}
return 1;
}
strcmp devuelve falso cuando coinciden las cadenas y por lo tanto tambin se
puede usar el operador NOT si se quiere hacer algo cuando las cadenas son
iguales, por ejemplo:
main()
{
char s[80];
for(;;)
{
printf(": ");
gets(s);
if(!strcmp("salir", s)) break;
}
}
contina pidiendo entradas hasta que se teclea quit.
- La funcin strlen( ) tiene el siguiente formato:
strlen(s);

donde s es una cadena. La funcin strlen( ) devuelve la longitud de la cadena


que apunta s.
El siguiente programa imprime la longitud de la cadena que se introduce por el
teclado:
main()
{
char str[80];
printf("introducir una cadena: ");
gets(str);
printf("%d",
}

strlen(s));

si se introduce hola amigos, el programa visualizar 10 caracteres y la funcin


strlen( ) no cuenta el terminador nulo.
El siguiente programa imprime el inverso de la cadena que se introduce por el
teclado, al introducir una la cadena de caracteres HOLA, el programa imprimir
ALOH, esto es porque las cadenas de caracteres son solo arreglos de modo
que se pueden referir a cada una individualmente.
/* Imprime una cadena hacia atrs */
main( )
{
char str[80];
int i;
gets(str);
for(i=strlen(str)-1; i>=0; i--)
printf("%c", str[i]);
}
En este ultimo programa, se har uso de las cuatro funciones de cadena:
main()
{
char s1[80], s2[80];
gets(s1);
gets(s2);

printf("longitude: %d %d\n",strlen(s1), strlen(s2));


if(!strcmp(s1, s2))
printf("Las cadenas son igual a\n");
strcat(s1, s2);
printf("%s\", s1);
}
Al ejecutar este programa y se introducen las cadenas hola y hola, la salida
ser:
Longitud: 5 5
Las cadenas son igual a
holahola
Para estar seguro, usar el ! para invertir la condicin, si se comprueba la
igualdad.

5.8 Usando el terminador nulo


La ventaja de que las cadenas terminen todas en nulo es simplificar las diversa
operaciones de cadena. Por ejemplo, mirar cmo lo requiere el siguiente
cdigo:
/* convierte una cadena a maysculas */
main()
{
char str[80];
int i;
strcpy(str, "esto es una prueba");
for(i=0; str[i]; i++) str[i] = toupper(str[i]);
printf("%s", str);
}
este programa imprimir ESTO ES UNA PRUEBA. Para convertir cada carcter
en la cadena, se us la funcin de biblioteca toupper( ), que devuelve el
equivalente en maysculas al argumento de carcter.
5.9 Una variacin del printf( )

printf( ) se usa para visualizar la cadena guardada en el arreglo de caracteres


usado y su formato general es:
printf("%s", nombre del arreglo);
el primer argumento de printf( ) es una cadena e imprime todos los caracteres
que no son ordenes de formato.
Para imprimir una cadena se usar es siguiente formato;
printf(nombre del arreglo);
por ejemplo:
main()
{
char str[80];
strcpy(str, "Hola Tom");
printf(str);
}
aqu se imprime Hola Tom.

5.10 Arreglos bidimensionales


Se permiten crear arreglos multidimensionales, pero la forma bidimensional o
de dos dimensiones es la ms utilizada. En el lenguaje C para definir un arreglo
de dos dimensiones de 3 x 3, para flotantes se escribe
float mat [3] [3];
Veamos el siguiente programa ejemplo, que carga un arreglo bidimensional con
los nmeros del 1 al 12
main()
{
int num[3] [4];
int i, j;
for (i=0; i<3; i=i+1)
{
for (j=0; j<4; j=j+1)
{
num[i][j])=(i*4+i+1);

}
}
for (i=0; i<3; i=i+1)
{
for (j=0; j<4; j=j+1)
{
printf("%d ", num[i][j]);
}
printf (" \n");
}
}

En este ejemplo, num[0][0] almacenar el valor 1, num[0][1] guardar el valor 2,


num[0][2] almacenar el valor 3, y as sucesivamente como se observa en la
imagen:
num

Normalmente los arreglos bidimensionales estn formados de filas y columnas,


donde le primer ndice indica la fila y el segundo la columna
Para saber el tamao en bytes que almacena un arreglo se puede utilizar la
siguiente frmula
bytes= fila * columna * tamao_en_bytes_del_tipo_de_datos
Por lo tanto el arreglo num ocupa 3*4*4= 48 bytes de memoria.
Direccin de memoria m m + 7
1,0
1,1
1,2
1,3
Primer
2,0
2,1
2,2
ndice
3,0
3,1
3,2
4,0
4,1
4,2
4,3
m
+
(c
Un arreglo bidimensional en memoria.

0,0 0,1 0,2 0,3 0,4


1,3
1,5
2,3
2,4
2,5
3,3
3,4
3,5
4,4
4,5
x
8)

0,5 0,5 0,7


1,6
1,7
2,6
2,7
3,6
3,7
4,6
4,7
1

2.7.3 Arreglos de estructuras


Quiz el uso ms comn de las estructuras es un arreglo de estructuras. Para
declarar un arreglo de estructura, primero se debe definir una estructura y
despus declarar una variable de arreglo de ese tipo. Por ejemplo, para
declarar un arreglo de 100 elementos de la estructura dire que ha sido definida;
se deber escribir:

struct
dire
{
char
nombre
[30];
char direccion [50];
char
estado
[3];
unsigned
long
int
codigo;
};
struct dire arreglo_dire
[5];
ste cdigo crea 5 conjuntos de variables que se organizan como se defini en
la estructura dire.
arreglo_dire [5]
arreglo_dire [0].nombre

arreglo_dire [0].direccion

arreglo_dire [0].estado

arreglo_dire [0].codigo

arreglo_dire [1].nombre

arreglo_dire [1].direccion

arreglo_dire [1].estado

arreglo_dire [1].codigo

arreglo_dire [2].nombre

arreglo_dire [2].direccion

arreglo_dire [2].estado

arreglo_dire [2].codigo

arreglo_dire [3].nombre

arreglo_dire [3].direccion

arreglo_dire [3].estado

arreglo_dire [3].codigo

arreglo_dire [4].nombre

arreglo_dire [4].direccion

arreglo_dire [4].estado

arreglo_dire [4].codigo

nombre

direccin

estado

cdigo

Para acceder a un campo especifico de la estructura, se indexa con el nombre


de arreglo, el ndice de la posicin y el nombre del campo de la estructura. Por
ejemplo:
arreglo_dire[2].codigo = 01410
Ver en la siguiente figura que en la posicin indicada aparece 01410
arreglo_dire [5]
arreglo_dire [0].nombre

arreglo_dire [0].direccion

arreglo_dire [0].estado

arreglo_dire [0].codigo

arreglo_dire [1].nombre

arreglo_dire [1].direccion

arreglo_dire [1].estado

arreglo_dire [1].codigo

arreglo_dire [2].nombre

arreglo_dire [2].direccion

arreglo_dire [2].estado

01410

arreglo_dire [3].nombre

arreglo_dire [3].direccion

arreglo_dire [3].estado

arreglo_dire [3].codigo

arreglo_dire [4].nombre

arreglo_dire [4].direccion

arreglo_dire [4].estado

arreglo_dire [4].codigo

nombre

direccin

estado

2.8 Punteros (Apuntadores)

cdigo

AN SIN HABILITAR

2.8.3 Punteros a estructuras


C permite punteros a estructuras de la misma forma que los permite a cualquier
otro tipo de variable. Sin embargo, hay algunos aspectos especiales de los
punteros de estructura que deben aclararse.
Se declara un puntero de estructura poniendo el * delante del nombre de la
variable de estructura. Por ejemplo, si se supone la estructura dire definida
antes, lo siguiente declara puntero_dire para puntero de datos de ese tipo:
struct dire *puntero_dire;
Hay dos usos principales para punteros estructurados. El primero uso es
conseguir una llamada por referencia a una funcin. El segundo uso es crear
listas enlazadas y otras estructuras dinmicas de datos usando el sistema de
asignacin de Turbo C.
Hay una desventaja principal pasando todo en vez de estructuras mas simples
a las funciones: es el recargo de tiempo para poner (y quitar) todos los
elementos de la pila. En las estructuras simples con pocos elementos, este
recargo no es importante, pero si una estructura usa varios elementos o si
alguno de ellos son arreglos, entonces el rendimiento del tiempo de ejecucin
puede degenerar a niveles inaceptables. La solucin a este problema es pasar
un solo puntero.
Cuando se pasa un puntero a una estructura a una funcin, la computadora
pone (y quita) slo la direccin de la estructura en la pila. Esto significa que
Turbo C puede ejecutar una llamada muy rpida de la funcin. Tambin, como
la funcin referenciar la estructura real y no una copia, la funcin puede
modificar los contenidos de los elementos de la estructura usada en la llamada.
Para encontrar la direccin de una variable de estructura, se pone el operador
& antes del nombre de variable de estructura. Por ejemplo, dando el fragmento
siguiente:
struct bal {
float balance;
char name[80];
} persona;
struct bal *p; /* declara un puntero de estructura*/
entonces
p=&persona;

pone la direccin de persona en el puntero p. Para referenciar el elemento base


se escribir:
(*p).balance
Los parntesis son necesarios alrededor del puntero por que el operador de
punto tiene una prioridad mas alta que el operador *.
Realmente hay dos mtodos que se pueden usar para referenciar un elemento
en una variable de estructura, dando el puntero a esa variable. El primer
mtodo usa referencias explicitas de puntero y se considera arcaico por los
estndar de hoy. Sin embargo, como algn cdigo antiguo que exista de C
puede usar esta aproximacin, es importante familiarizarse con el.
Tambin crea un seguimiento que permite entender el segundo y ms comn
mtodo. Este segundo mtodo de acceso a los elementos de estructuras
usando punteros utiliza el operador ->. Por lo tanto
(*p).balance es lo mismo que p->balance
Para ver como se puede usar un puntero de estructura, examinar este sencillo
programa que imprime horas, minutos, y segundos en la pantalla usando un
temporizador por software:
/* visualiza un temporizador de software */
visualiza
delay( );
struct
int
int
int
};
main()
{
struct
hora.hours=0;
hora.minutes=0;
hora.seconds=0;
for
actualiza
visualiza
}

(struct

tm

tm

*t);

{
hours;
minutes;

seconds;

tm

(;;)

hora;

{
(&hora);
(&hora);

}
/*versin 1 - explica la s referencias de puntero */
actualiza(struct
tm
*t)
{
t->seconds++;
if
(t->seconds==60)
{

t->seconds=0;
t->minutes++;
}
if

( t->minutes==60)

t->minutes=0;
t->hours++;
}
if

(t->hours==24)

t->hours=0;
delay

();

}
visualiza
{
printf
printf
printf
}
delay(
{
long
for
}

(struct

tm

("%d:",
("%d:",
("%d:",

*t)

t->hours)
;
t->minutes);
t->seconds);

)
int

t;
(t=1;t<128000;t++);

Se puede ajustar el retardo de este programa variando el contador de bucle en


delay ().
Como se puede ver, el programa define estructura global llamada tm, pero no
declara variable. Dentro de main (), se declara e inicializa la estructura hora a
00:00:00; as hora se conoce directamente solo por main ().
El programa pasa la direccin de hora a dos funciones: actualiza (), que cambia
la hora, y visualiza (), que la imprime. En ambas funciones se declaran los
argumentos como estructura de tipo tm de manera que el compilador sabr
como referenciar los elementos de la estructura.
El programa consigue la referencia real de cada elemento de estructura
mediante el uso de un puntero. Por ejemplo, para reestablecer de nuevo a cero
las horas cuando el programa alcance las 24:00:00, se escribir:
if(t->hours==24) t->hours=0;
Esta lnea de cdigo dice al compilador que coja la direccin de t - que es hora
en main()- y asigna cero a su elemento de llamado horas.
Recordar que se usa el operador de punto para acceder a los elementos de
estructura cuando se trabaja sobre la propia estructura. Cuando se tiene un
puntero a una estructura, entonces se usara el operador de flecha. Tambin,
recordar que se tiene que pasar la direccin de la estructura a una funcin
usando el operador &.

Вам также может понравиться