Está en la página 1de 160

Algoritmos y programas

Algoritmo
Secuencia ordenada de pasos que resuelve un problema concreto. Caractersticas - Correccin (sin errores). - Precisin (ausencia de ambigedades). - Repetitividad (solucin genrica de un problema dado). - Finitud (nmero finito de rdenes no implica finitud). - Eficiencia (temporal [tiempo necesario] y espacial [memoria utilizada])

Programa
Implementacin de un algoritmo en un lenguaje de programacin
Datos de entrada

Programa
Instrucciones

Datos de salida

Conjunto ordenado de instrucciones que se dan al ordenador indicndole las operaciones o tareas que ha de realizar para resolver un problema.

Introduccin a la Programacin

-1-

Lenguajes de programacin
Una instruccin es un conjunto de smbolos que representa una orden para el ordenador: la ejecucin de una operacin con datos. Las instrucciones se escriben en un lenguaje de programacin: - Se forman con smbolos tomados de un determinado repertorio (componentes lxicos) - Se construyen siguiendo unas reglas precisas (sintaxis) Lenguaje mquina El nico que entiende directamente la CPU del ordenador Depende del modelo de ordenador Repertorio de instrucciones reducido (operaciones muy elementales) Muy difcil programar en l (en binario, con cadenas de ceros y unos) Lenguaje ensamblador Equivalente al lenguaje mquina, cada lnea de cdigo se traduce en una instruccin para la mquina. Le asocia mnemnicos a las operaciones que entiende la CPU Repertorio de instrucciones reducido (operaciones muy elementales) Programas difciles de entender Lenguajes de alto nivel Permiten que el programador exprese el procesamiento de datos de forma simblica, sin tener en cuenta los detalles especficos de la mquina. Independientes del modelo de ordenador Proporcionan un mayor nivel de abstraccin
Introduccin a la Programacin -2-

Ejemplos de lenguajes de programacin de alto nivel FORTRAN (FORmula TRANslation) 1957, IBM (John Backus) Orientado a la resolucin de problemas cientficos y tcnicos COBOL (COmmon Business Oriented Language) 1959, Codasyl (Committee on Data System Languages) Aplicaciones comerciales de gestin LISP (LISt Processing) 1959, John McCarthy (MIT) Procesamiento de datos no numricos (usado en IA) BASIC (Beginners All-purpose Symbolic Instruction Code) 1964, John Kemeny & Thomas Kurtz (Darmouth College) Lenguaje interactivo para principiantes Simula 1967, Ole-Johan Dahl & Krysten Nygaard (Noruega) Primer lenguaje de programacin orientada a objetos Pascal 1971, Niklaus Wirth Lenguaje estructurado diseado para aprender a programar C 1972, Denis Ritchie (Bell Labs) Lenguaje pequeo, flexible y eficiente Smalltalk 1972, Alan Kay (Xerox PARC) Origen de los interfaces WIMP (Windows, Icons, Mouse & Pull-down menus) PROLOG (PROgramming in Logic) 1972, Alain Colmerauer (Universidad de Marsella) Basado en Lgica (usado en IA) Ada 1980, US Department of Defense Basado en Pascal, muy usado en aplicaciones militares
Introduccin a la Programacin -3-

C++ 1983, Bjarne Stroustroup (AT&T Bell Labs) Extensin de C que permite la programacin orientada a objetos Java 1995, Sun Microsystems Similar a C++, aunque ms sencillo de aprender y usar. C# 2000, Microsoft Corporation Alternativa de Microsoft a Java, muy similar a ste

Clasificacin de los lenguajes de programacin de alto nivel Lenguajes imperativos: Los programas indican al ordenador de forma inequvoca los pasos a seguir para la resolucin de un problema. o Programacin estructurada: La estructura del texto del programa debe auxiliarnos para entender la funcin que realiza: estrategia divide y vencers (la resolucin de un problema se divide en tareas y, stas, en subtareas). Ejemplos: C, Pascal, Fortran... o Programacin orientada a objetos: Estilo de programacin que basa la estructura de un programa en mdulos deducidos de los tipos de objetos que manipula (en lugar de basarse en las tareas que el sistema debe realizar). Ejemplos: Smalltalk, C++, Java, C#... Lenguajes declarativos (funcionales y lgicos): Los programas se implementan como conjuntos de funciones (o reglas lgicas) cuya evaluacin nos dar el resultado deseado. Ejemplos: LISP, PROLOG...
Introduccin a la Programacin -4-

Evolucin de los lenguajes de programacin: Lenguajes imperativos

Introduccin a la Programacin

-5-

Evolucin de los lenguajes de programacin: Lenguajes declarativos

Introduccin a la Programacin

-6-

Traductores
Los traductores transforman programas escritos en un lenguaje de alto nivel en programas escritos en cdigo mquina:

Tipos de traductores Compiladores Generan un programa ejecutable a partir del cdigo fuente

Intrpretes Van analizando, traduciendo y ejecutando las instrucciones del programa una a una. No se traduce una instruccin hasta que la ejecucin de la anterior haya finalizado.

Herramientas de programacin
Editores, depuradores, profilers... IDEs (entornos integrados de desarrollo) Ejemplos Microsoft Visual Studio .NET Borland C++Builder/Delphi Eclipse
Introduccin a la Programacin -7-

Eclipse, un IDE para Java (http://www.eclipse.org)

Microsoft Visual Studio .NET, un IDE para la plataforma .NET


Introduccin a la Programacin -8-

Desarrollo de aplicaciones informticas: Ciclo de vida del software


El ciclo de vida de una aplicacin comprende las siguientes etapas:

Planificacin
Delimitacin del mbito del proyecto, estudio de viabilidad, anlisis de riesgos, estimacin de costos, planificacin temporal y asignacin de recursos.

Anlisis (qu?): Elicitacin de requisitos.


Descripcin clara y completa de qu es lo que se pretende, incluyendo la presentacin de los resultados que se desean obtener (formato de las salidas) y la forma en que se va a utilizar la aplicacin (interfaz de usuario)

Diseo (cmo?): Estudio de alternativas


Diseo arquitectnico: Organizacin de los distintos mdulos que compondrn la aplicacin (diseo arquitectnico). Diseo detallado: Definicin de los algoritmos necesarios para implementar la aplicacin en lenguaje natural, mediante diagramas de flujo o en pseudocdigo [lenguaje algortmico].

Implementacin:
Adquisicin de componentes, creacin de los mdulos de la aplicacin en un lenguaje de programacin e integracin de los recursos necesarios para que el sistema funcione.

Depuracin y pruebas:
Comprobacin del funcionamiento de la aplicacin
Pruebas de unidad y de integracin, pruebas alfa, pruebas beta, test de aceptacin.

Verificacin (si se est realizando lo que se pretenda) Validacin (si se realiza lo correcto).

Explotacin: Uso y mantenimiento


Mantenimiento correctivo: Correccin de defectos o errores. Mantenimiento adaptativo: Adaptacin de la aplicacin a nuevas circunstancias e inclusin de nuevas prestaciones.
Introduccin a la Programacin -9-

Introduccin a la programacin El lenguaje de programacin C


El lenguaje de programacin ANSI C Componentes del estndar ANSI C Historia de C Herramientas de programacin en C Aplicaciones en C Programa de ejemplo Fases en la creacin y ejecucin de programas en C Caractersticas clave de C

El lenguaje de programacin ANSI C

Componentes del estndar ANSI C


Compilador Traduce a cdigo mquina el cdigo fuente escrito en C Preprocesador Acta sobre el cdigo fuente antes de la compilacin Biblioteca estndar Conjunto de funciones predefinidas Ejemplos:
stdio.h E/S bsica y ficheros math.h Funciones matemticas

Introduccin a la Programacin: C

- 11 -

Historia de C
Ao 1963 CPL (Combined Programming Language) Universidades de Cambridge y Londres Simplificacin derivada de ALGOL 60 (no implementado) 1967 BCPL (Basic CPL [Combined Programming Language]) Martin Richards (Universidad de Cambridge) Lenguaje sin tipos creado como herramienta para la construccin de compiladores y sistemas operativos. 1970 B (BCPL simplificado) Ken Thompson(AT&T Bell Labs, New Jersey) Lenguaje sin tipos creado para el primer sistema UNIX (para la PDP-7 de Digital Equipment Corporation [DEC]) 1972 Creacin del lenguaje de programacin C Dennis Ritchie (AT&T Bell Labs, New Jersey) 1974 UNIX reescrito en C 1978 Brian W. Kernighan & Dennis Ritchie The C Programming Language Prentice Hall, ISBN 0-13-110370-9 1983 C++ Bjarne Stroustroup (AT&T Bell Labs, New Jersey) Extensin de C (programacin orientada a objetos) 1989 Estndar ANSI C #X3J11/99-090 aprobado por el American National Standards Institute 1989 Segunda edicin del libro de Kernighan & Ritchie 1995 Java James Gosling (Sun Microsystems) Similar a C++, aunque ms sencillo de aprender y usar 1997 Estndar ANSI C++ aprobado por el American National Standards Institute 2000 C# Microsoft Corporation Alternativa a Java (base de la plataforma .NET)
Introduccin a la Programacin: C - 12 -

Herramientas de programacin en C
Existen mltiples compiladores de C y muchos entornos integrados de desarrollo [IDEs: Integrated Development Environments]

http://www.borland.com/ Borland C++BuilderX

http://www.eclipse.org/ Eclipse IDE


Open platform for tool integration

http://www.microsoft.com/ Microsoft Visual Studio .NET http://gcc.gnu.org/ GCC GNU Compiler Collection

http://www.openwatcom.org/ Open Watcom


Introduccin a la Programacin: C - 13 -

Aplicaciones en C
Datos de entrada Cdigo fuente (ANSI C) Cdigo mquina (.o|.obj) Compilacin Enlazado Ejecucin Resultados

Un programa puede tener miles (e incluso millones) de lneas de cdigo fuente. A medida que el programa va creciendo, ste sera inmanejable si no fusemos dividiendolo en mdulos mucho ms pequeos y manejables. Todos los programas en C consisten en una o ms funciones (fragmentos de cdigo que realizan tareas concretas). La ejecucin del programa escrito en C comienza en una funcin denominada main(), que siempre debe existir para que podamos crear un programa ejecutable. Una aplicacin se implementa como un conjunto de funciones a las que podemos llamar desde el programa principal (la funcin main). Las distintas funciones de nuestro programa, a su vez, pueden llamar a otras funciones cuando sea necesario. La biblioteca estndar de C define algunas funciones comunes que vienen implementadas para que podamos usarlas directamente (sin preocuparnos de su implementacin). Al compilar un programa en C, creamos el cdigo mquina correspondiente a la parte del programa que hayamos escrito nosotros. A continuacin, enlazamos nuestro cdigo mquina con el correspondiente a las funciones ya implementadas en bibliotecas para obtener un programa ejecutable.
Introduccin a la Programacin: C - 14 -

Programa de ejemplo
Cdigo fuente en C: Fichero programa.c

/* Mi primer programa en C */ #include <stdio.h> int main (int argc, char *argv) { printf(Hola); return 0; }

La primera lnea, entre /* y */, es un comentario (algo que no forma parte del cdigo del programa en s pero que se incluye como aclaracin para facilitar su lectura). La lnea #include <stdio.h> le indica al preprocesador de C que incluya en el programa el contenido del fichero de cabecera stdio.h, donde estn las declaraciones de las funciones estndar de entrada/salida en C. La lnea int main() define la cabecera de la funcion main, el punto donde comienza la ejecucin de un programa en C. Las llaves { } sirven para delimitar la secuencia de instrucciones que forman parte de la funcin main. La llamada a la funcin printf("Hola "); le indica al ordenador que muestre por pantalla el mensaje que se le indica entre comillas. La sentencia return indica el valor que devuelve la funcin main (por convencin, 0 indica que todo fue bien).
Introduccin a la Programacin: C - 15 -

Compilacin A continuacin tenemos que traducir nuestro programa escrito en C a un programa que pueda ejecutar directamente el ordenador:

cc programa.c

NOTA:

Segn el compilador de C que utilicemos, puede que tengamos que escribir gcc (GNU C), cl (Microsoft), wcc386 (Watcom), bcc o bcc32 (Borland).

Ejecucin Una vez compilado el programa, para ejecutarlo basta con escribir su nombre

programa

Resultado Como resultado de la ejecucin, obtenemos lo siguiente:

Introduccin a la Programacin: C

- 16 -

Fases en la creacin y ejecucin de programas en C


Fase I: Edicin Se crea un programa con la ayuda de un editor Se almacena en un fichero con extensin .c Fase II: Preprocesamiento El preprocesador realiza sustituciones textuales en el texto del programa escrito en C. Fase III: Compilacin El compilador lee el cdigo C tras su preprocesamiento. Si se detectan errores sintcticos, el compilador nos informa de ello. Se genera el cdigo mquina (en ficheros .o .obj) Fase IV: Enlace El enlazador [linker] junta todos los ficheros objeto que sean necesarios para crear el ejecutable (.exe en Windows). Fase V: Carga El sistema operativo lee el fichero ejecutable de disco y lo carga en la memoria principal del ordenador. Fase VI: Ejecucin Comienza la ejecucin de la funcin main de nuestro programa. NOTA: Conforme se ejecuta el programa, se hace uso de la memoria principal para almacenar los datos con los que trabaja la aplicacin.
- 17 -

Introduccin a la Programacin: C

Caractersticas clave de C

Lenguaje de programacin de propsito general Lenguaje estructurado (como Pascal) Lenguaje pequeo Lenguaje muy eficiente Lenguaje portable (independiente de la mquina) A menudo es elegido para el desarrollo de software de sistemas: es un lenguaje de programacin de alto nivel caracterizado por su acusada proximidad a la mquina Origen de muchos de los lenguajes usados actualmente (C++, Java, C#...)

"No es una herramienta para tontos y nios. En manos de un artesano habilidoso es capaz de trabajar de forma potente pero delicada. Su posibilidad de causar un serio dao es tan obvia que ese peligro proporciona el nico mecanismo de seguridad; un sano respeto por lo que puede hacer su uso despreocupado!"
B. Cox, "Software ICs and Objective-C", Productivity Products International (ahora StepStone Inc.), 1985

Introduccin a la Programacin: C

- 18 -

Datos y tipos de datos


Dato
Representacin formal de hechos, conceptos o instrucciones adecuada para su comunicacin, interpretacin y procesamiento por seres humanos o medios automticos.

Tipo de dato
Especificacin de un dominio (rango de valores) y de un conjunto vlido de operaciones a los que normalmente los traductores asocian un esquema de representacin interna propio.

Clasificacin de los tipos de datos En funcin de quin los define: Tipos de datos estndar Tipos de datos definidos por el usuario En funcin de su representacin interna: Tipos de datos escalares o simples Tipos de datos estructurados

Introduccin a la Programacin

- 19 -

Codificacin de los datos en el ordenador


En el interior del ordenador, los datos se representan en binario.

El sistema binario slo emplea dos smbolos: 0 y 1 Un bit nos permite representar 2 smbolos diferentes: 0 y 1 Dos bits nos permiten codificar 4 smbolos: 00, 01, 10 y 11 Tres bits nos permiten codificar 8 smbolos distintos: 000, 001, 010, 011, 100, 101, 110 y 111 En general, con N bits podemos codificar 2N valores diferentes N
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

2N
2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536

Si queremos representar X valores diferentes, necesitaremos N bits, donde N es el menor entero mayor o igual que log2 X
Introduccin a la Programacin - 20 -

Representacin de datos de tipo numrico Representacin posicional Un nmero se representa mediante un conjunto de cifras, cuyo valor depende de la cifra en s y de la posicin que ocupa en el nmero

NMEROS ENTEROS Ejemplo: Si utilizamos 32 bits para representar nmeros enteros, disponemos de 232 combinaciones diferentes de 0s y 1s: 4 294 967 296 valores. Como tenemos que representar nmeros negativos y el cero, el ordenador ser capaz de representar del 2 147 483 648 al +2 147 483 647. Con 32 bits no podremos representar nmeros ms grandes. 2 147 483 647 + 1 = 2 147 483 648 !!!

NMEROS REALES (en notacin cientfica) (+|) mantisa x 2exponente El ordenador slo puede representar un subconjunto de los nmeros reales (nmeros en coma flotante) Las operaciones aritmticas con nmeros en coma flotante estn sujetas a errores de redondeo.

Estndar IEEE 754 Precisin sencilla (bit de signo + 8 bits exponente + 23 bits mantisa) Precisin doble (bit de signo + 11 bits exponente + 52 bits mantisa)
Introduccin a la Programacin - 21 -

Representacin de textos Se escoge un conjunto de caracteres: alfabticos, numricos, especiales (separadores y signos de puntuacin), grficos y de control (por ejemplo, retorno de carro). Se codifica ese conjunto de caracteres utilizando n bits. Por tanto, se pueden representar hasta 2n smbolos distintos.
Ejemplos de cdigos normalizados

ASCII (American Standard Code for Information Interchange) - ANSI X3.4-1968, 7 bits (128 smbolos) - ISO 8859-1 = Latin-1, 8 bits (256 smbolos)

UNICODE, ISO/IEC 10646, 16 bits (65536 smbolos)

Introduccin a la Programacin

- 22 -

Tipos de datos primitivos en C


El lenguaje ANSI C define 6 tipos de datos bsicos que pueden ir acompaados de modificadores

Tipos de datos bsicos


char int float double void

Caracteres Nmeros enteros Nmeros en coma flotante (32 bits) Nmeros en coma flotante de doble precisin (64 bits) Tipo nulo Punteros Direcciones de memoria

Modificadores
Tamao del dato
short long

(int por defecto) (int por defecto)

Signo Aplicable a los tipos char, short, int y long


signed (con signo) unsigned (sin signo)

Modo de almacenamiento No se suele usar


register auto (por defecto) static extern
Introduccin a la Programacin: C - 23 -

Nmeros enteros
[unsigned] char, [unsigned] short, [unsigned] long

6 tipos bsicos para representar nmeros enteros:


- 3 con signo: - 3 sin signo: char, short, long unsigned (char | short | long)

Tipo de dato
char unsigned char short unsigned short long unsigned long

Espacio en memoria 8 bits 16 bits 32 bits

Valor Mnimo -128 0 -32768 0 -2147483648 0

Valor Mximo 127 255 32767 65535 2147483647 4294967295

int

El tipo de dato int es equivalente - al tipo de dato short en compiladores de 16 bits - al tipo de dato long en compiladores de 32 bits

unsigned int El tipo de dato unsigned int es equivalente - al tipo de dato unsigned short en compiladores de 16 bits - al tipo de dato unsigned long en compiladores de 32 bits

Introduccin a la Programacin: C

- 24 -

Literales enteros Los literales enteros pueden expresarse: - En decimal (base 10):
255

- En octal (base 8), con el prefijo 0:


0377

( 382 + 781 + 7 = 255 )

- En hexadecimal (base 16), con el prefijo 0x:


0xff

( 15*161 + 15 = 255)

Los literales enteros son de tipo int por defecto. Un literal entero es de tipo long si va acompaado del sufijo l o L:
123456789L es de tipo long

NOTA:

Se prefiere el uso de L porque l (L minscula) puede confundirse con 1 (uno).

Un literal entero unsigned debe ir acompaado del sufijo u o U:


123456789uL es de tipo unsigned long

Definicin Literal: Especificacin de un valor concreto de un tipo de dato.


Introduccin a la Programacin: C - 25 -

Operaciones con nmeros enteros Desbordamiento Si sobrepasamos el valor mximo que se puede representar con un tipo de dato entero, nadie nos avisa de ello: en la ejecucin de nuestro programa obtendremos un resultado incorrecto. Tipo
char short long

Operacin 127 + 1 32767 + 1 2147483647 + 1

Resultado -128 -32768 -2147483648

Para obtener el resultado correcto, hemos de tener en cuenta el rango de valores de cada tipo de dato, de tal forma que los resultados intermedios de un clculo siempre puedan representarse correctamente: Tipo
short long

Operacin 10000 * 10000 10000L * 10000L

Resultado -7936 100000000

Divisin por cero Si dividimos un nmero entero por cero, se produce un error en tiempo de ejecucin:
Divide error

La ejecucin del programa termina de forma brusca al intentar hacer la divisin por cero.

Introduccin a la Programacin: C

- 26 -

Nmeros en coma flotante


float, double, long double

El estndar ANSI C no establece su representacin fsica

Tipo Espacio en Mnimo Mximo Dgitos de dato memoria (valor absoluto) (valor absoluto) significativos
float double long double

32 bits 64 bits 80 bits

1.2 x 10-38 2.2 x 10-308 3.4 x 10-4932

3.4 x 1038 1.8 x 10308 1.2 x 104932

6 15 18

Literales reales - Cadenas de dgitos con un punto decimal


123.45 0.0 .001

- En notacin cientfica (mantisa10exponente)


123e45 123E+45 1E-6

Por defecto, los literales reales representan valores de tipo double Para representar un valor de tipo float, hemos de usar el sufijo f o F:
123.45F 0.0f .001f

El sufijo l o L se usa para los literales de tipo long double:


123.45L 0.0L .001L

Introduccin a la Programacin: C

- 27 -

Operaciones con nmeros en coma flotante Segn el estndar IEEE 754, las operaciones aritmticas en coma flotante pueden dar como resultado valores especiales: - Cuando el resultado de una operacin est fuera de rango, se obtiene +Inf o Inf (infinito). - Cuando el resultado de una operacin est indeterminado, se obtiene NaN (Not a Number) El estndar IEEE 754 establece los siguientes resultados: Operacin 1.0 / 0.0 -1.0 / 0.0 0.0 / 0.0 Resultado
+Inf -Inf NaN

No obstante, en funcin del compilador que utilicemos, puede que nos encontremos con un error en tiempo de ejecucin:
Floating point error: Domain. Abnormal program termination

O bien:
Floating point error: Divide by 0. Abnormal program termination

Precisin Las operaciones en coma flotante no son exactas debido a la forma en que se representan los nmeros reales en el ordenador Operacin 1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1 1.0 - 0.9 Resultado
0.5000000000000001 0.09999999999999998

Introduccin a la Programacin: C

- 28 -

Operadores aritmticos C incluye cinco operadores para realizar operaciones aritmticas: Operador
+ * / %

Operacin Suma Resta o cambio de signo Multiplicacin Divisin Mdulo (resto de la divisin)

- Si los operandos son enteros, se realizan operaciones enteras. - En cuanto uno de los operandos es de tipo float, double, o long double, la operacin se realiza en coma flotante. - No existe un operador de exponenciacin: para calcular xy hay que utilizar la funcin pow(x,y) que se encuentra en math.h Divisin (/) Operacin 7/3 7 / 3.0f 5.0 / 2 7.0 / 0.0 0.0 / 0.0 Tipo
int float double double double

Resultado
2 2.333333333f 2.5 +Inf NaN

- Si se dividen enteros, el resultado es entero y el resto se pierde. - Una divisin entera por cero produce un error. - Una divisin por cero, en coma flotante, produce Inf o NaN.

Mdulo (%): Resto de dividir nmeros enteros (no puede usarse con nmeros en coma flotante) Operacin 7%3
Introduccin a la Programacin: C

Tipo
int
- 29 -

Resultado
1

Expresiones aritmticas Se pueden combinar literales y operadores para formar expresiones complejas.

Ejemplo

3 + 4 x 10( y 5)( a + b + c ) 4 9+x + 9( + ) 5 x x y


En C se escribira as:
(3+4*x)/5 10*(y-5)*(a+b+c)/x + 9*(4/x + (9+x)/y)

- Las expresiones aritmticas se evalan de izquierda a derecha. - Los operadores aritmticos mantienen el orden de precedencia habitual (multiplicaciones y divisiones antes que sumas y restas). - Para especificar el orden de evaluacin deseado, se utilizan parntesis. NOTA: Es recomendable utilizar parntesis para eliminar interpretaciones errneas y posibles ambigedades

Definicin Expresin: Construccin que se evala para devolver un valor.


Introduccin a la Programacin: C - 30 -

Caracteres
char, unsigned char

Tipo Espacio en de dato memoria char 8 bits Literales de tipo carcter Valores entre comillas simples
a b c 1 2 3

Codificacin ASCII

Cdigos ASCII (en hexadecimal): \x?? \x0a (avance de lnea) \x0d (retorno de carro) Secuencias de escape para representar caracteres especiales: Secuencia de escape \t \n \r \b \f \a \ \ \\ \? \0

Descripcin Tabulador (tab) Avance de lnea (new line) Retorno de carro (carriage return) Retroceso (backspace) Salto de pgina (form feed) Sonido de alerta Comillas simples (apstrofe) Comillas dobles Barra invertida Signo de interrogacin Carcter nulo (NULL)

La biblioteca ctype.h define funciones bsicas para trabajar con caracteres:


isalpha(), isdigit(), islower(), isupper() tolower(), toupper()
Introduccin a la Programacin: C - 31

Cadenas de caracteres en C

En ANSI C no existen las cadenas de caracteres como tipo predefinido: una cadena de caracteres no es ms que un vector de caracteres

Literales Texto entra comillas dobles


Esto es una cadena Esto tambin es una cadena

Las secuencias de escape son necesarias para introducir determinados caracteres dentro de una cadena:
\Esto es una cadena entre comillas\

Formacin de cadenas de caracteres Para construir cadenas de caracteres en las que mostrar datos, se utilizan plantillas que se sustituirn por una representacin adecuada de los valores del tipo indicado: Plantilla %c %s %d %o %x %ld %f %lf %Lf
Introduccin a la Programacin: C

Tipo de dato
char

Cadena de caracteres int (en decimal) int (en octal) int (en hexadecimal)
long float double long double

- 32 -

Datos de tipo booleano


En C no existe explcitamente un tipo de dato booleano para representar algo que pueda ser verdadero (V) o falso (F). Cualquier valor entero distinto de 0 se considera verdadero. Por convencin, o Se usa el valor 1 para representar algo verdadero. o Se usa el valor 0 para representar algo falso.

Expresiones de tipo booleano Se construyen a partir de expresiones de tipo numrico con operadores relacionales. Se construyen a partir de otras expresiones booleanas (que en C son expresiones de tipo entero) con operadores lgicos.

Operadores relacionales - Operadores de comparacin vlidos para nmeros y caracteres - Generan un resultado de tipo int que interpretamos como booleano

Operador
== != < > <= >=

Significado Igual Distinto Menor Mayor Menor o igual Mayor o igual

Introduccin a la Programacin: C

- 33 -

Operadores lgicos/booleanos - Operandos booleanos. - Tienen menos precedencia que los operadores de comparacin. Operador Nombre ! NOT && AND || OR ^ XOR Significado Negacin lgica y lgico o inclusivo o exclusivo

Tablas de verdad X
0 1

!X
1 0

A
0 0 1 1

B
0 1 0 1

A&&B
0 0 0 1

A||B
0 1 1 1

A^B
0 1 1 0

- NOT (!) cambia el valor booleano. - AND (&&) devuelve verdadero si los dos son operandos son verdaderos. No evala el segundo operando si el primero es falso - OR (||) devuelve falso si los dos operandos son falsos. No evala el segundo operando si el primero es verdadero - XOR (^) devuelve verdadero si los dos operandos son diferentes. Con operandos booleanos es equivalente a != Ejemplos Nmero x entre 0 y 10 Nmero x fuera del intervalo [0,10] o bien
Introduccin a la Programacin: C - 34 -

(0 <= x) && (x <= 10) !((0 <= x) && (x <= 10)) (0 > x) || (x > 10)

Extra: Operadores a nivel de bits - Se pueden utilizar a nivel de bits con nmeros enteros. - No se pueden usar con datos de otro tipo (p.ej. reales).

Los operadores NOT (~), AND (&), OR(|) y XOR (^) - NOT (~) realiza el complemento a 1 de un nmero entero: Cambia los 0s por 1s y viceversa - AND(&), OR(|) y XOR(^) funcionan a nivel de bits como los operadores booleanos AND (&&), OR(||) y XOR (^), respectivamente.

Operacin ~10 10 & 1 10 & 2 10 & 3 10 | 1 10 | 2 10 | 3 10 ^ 1 10 ^ 2 10 ^ 3

A nivel de bits
~000001010 (111110101) 000001010 & 00001 (000000000) 000001010 & 00010 (000000010) 000001010 & 00011 (000000010) 000001010 | 00001 (000001011) 000001010 | 00010 (000001010) 000001010 | 00011 (000001011) 000001010 ^ 00001 (000001011) 000001010 ^ 00010 (000001000) 000001010 ^ 00011 (000001001)

Resultado
-11 0 2 2 11 10 11 11 8 9

Introduccin a la Programacin: C

- 35 -

Los operadores de desplazamiento <<, >> y >>> - El operador de desplazamiento a la izquierda (<<) desplaza los bits del primer operando tantas posiciones a la izquierda como indica el segundo operando. Los nuevos bits se rellenan con ceros. - El operador de desplazamiento a la derecha (>>) desplaza los bits del primer operando tantas posiciones a la derecha como indica el segundo operando. Los nuevos bits se rellenan con unos (si el primer operando es negativo) y con ceros (si es positivo).

Operacin 10 << 1 7 << 3 10 >> 1 27 >> 3 -50 >> 2 -50 << 2

A nivel de bits
00001010 << 1 (0010100) 00000111 << 3 (00111000) 00001010 >> 1 (00000101) 00011011 >> 3 (0000011) 11001110 >> 2 (11110011) 111001110 << 2 (11100111000)

Resultado
20 (==10*2) 56 (==7*23) 5 (==10/2) 3 (==27/23) -13 (!=-50/22) -200 (==-50*22)

x<<b es equivalente a

multiplicar por 2b
x>>b es equivalente a

realizar una divisin entera entre 2b cuando x es positivo

Introduccin a la Programacin: C

- 36 -

Variables
Una variable no es ms que un nombre simblico que identifica una direccin de memoria:

Suma el contenido de la posicin 3001 y la 3002 y lo almacenas en la posicin 3003 vs.

total = cantidad1 + cantidad2


Suma cantidad1 y cantidad2 y lo almacenas en total

Declaracin de variables Para usar una variable en un programa hay que declararla. - El ordenador conoce as cmo codificar la informacin que se va a almacenar en la posicin de memoria correspondiente. - Al declarar una variable, se reserva el espacio de memoria necesario para almacenar un valor del tipo de la variable. - El identificador asociado a la variable se puede utilizar para acceder al dato almacenado en memoria y para modificarlo.
Introduccin a la Programacin - 37 -

Declaracin de variables en C
<tipo> identificador; <tipo> lista de identificadores;

Las variables se han de declarar antes de poder usarlas. Los identificadores de las variables son los nombres que utilizaremos para referirnos a ellas. Al declarar una variable, hay que definir su tipo: la variable slo admitir valores del tipo especificado. En una misma declaracin se pueden declarar varias variables, siempre que sean del mismo tipo. En este caso, los identificadores de las variables se separan por comas.

Ejemplos // Declaracin una variable entera x de tipo int


int x;

// Declaracin de una variable real r de tipo double


double r;

// Declaracin de una variable c de tipo char


char c;

// Mltiples declaraciones en una sola lnea


int i, j, k;

Introduccin a la Programacin: C

- 38 -

Identificadores en C El primer smbolo del identificador ser un carcter alfabtico (a, , z, A, , Z, _) pero no un dgito. Despus de ese primer carcter, podremos poner caracteres alfanumricos (letras del alfabeto ingls o dgitos decimales) y guiones de subrayado (_). Los identificadores no pueden coincidir con las palabras reservadas, que ya tienen significado en C:
auto const enum goto else sizeof register unsigned break continue extern if return static switch void case default float int short struct typedef volatile char do for long signed double union while

Las maysculas y las minsculas se consideran diferentes. El guin de subrayado (_) se interpretan como una letra ms. Ejemplos vlidos
a, pepe, r456, tu_re_da, AnTeNa, antena

Ejemplos no vlidos
345abc caada mi variable camin Nombre.Largo usd$

C es un lenguaje sensible a maysculas/minsculas.


Introduccin a la Programacin: C - 39 -

Convenciones Los identificadores deben ser descriptivos: deben hacer referencia al significado de aquello a lo que se refieren.
int n1, n2; int anchura, altura; // MAL // BIEN

Los identificadores asociados a las variables se suelen poner en minsculas.


int CoNTaDoR; int contador; // MAL // BIEN

Cuando el identificador est formado por varias palabras, la primera palabra va en minsculas y el resto de palabras se inician con una letra mayscula (o bien se separan las distintas palabras por guiones de subrayado).
int mayorvalor; int mayor_valor; int mayorValor; // MAL // BIEN // BIEN

Inicializacin de las variables En una declaracin, las variables se pueden inicializar:


int i = 0; float pi = 3.1415927f; double x = 1.0, y = 1.0;

NOTA:

La inicializacin puede consistir en una expresin compleja que se evala cuando se ejecuta el programa.
- 40 -

Introduccin a la Programacin: C

Definicin de constantes en C
Una constante hace referencia a un valor que no puede modificarse

En ANSI C se suelen definir utilizando la directiva #define del preprocesador de C:


#define <IDENTIFICADOR> <valor>

Convenciones Los identificadores asociados a las constantes se suelen poner en maysculas.


#define PI 3.141592

Si el identificador est formado por varias palabras, las distintas palabras se separan con un guin de subrayado
#define RETORNO_DE_CARRO \n #define ELECTRONIC_CHARGE 1.6E-19

No se puede modificar el valor de una constante:


RETORNO_DE_CARRO = \r; // Ilegal

produce el siguiente error Lvalue required


(a la izquierda de una asignacin no se puede poner cualquier cosa)
Introduccin a la Programacin: C - 41 -

Expresiones y sentencias
Expresin
Construccin (combinacin de tokens) que se evala para devolver un valor.

Sentencia
Representacin de una accin o una secuencia de acciones. En C, todas las sentencias terminan con un punto y coma [;].

Construccin de expresiones
Literales y variables son expresiones primarias:
1.7 sum // Literal real de tipo double // Variable

- Los literales se evalan a s mismos. - Las variables se evalan a su valor. Los operadores nos permiten combinar expresiones primarias y otras expresiones formadas con operadores:
1 + 2 + 3*1.2 + (4 +8)/3.0

Los operadores se caracterizan por: - El nmero de operandos (unarios, binarios o ternarios). - El tipo de sus operandos (p.ej. numricos o booleanos). - El tipo del valor que generan como resultado.
Introduccin a la Programacin: C - 42 -

Nmero de operandos - Operadores unarios Operador


! ~

Descripcin Cambio de signo Operador NOT Complemento a 1 Descripcin Operadores aritmticos Operadores relacionales Operadores booleanos Operadores a nivel de bits

- Operadores binarios Operadores


+ - * / % == != < > <= >= && || ^ & | ^ << >>

Tipo de los operandos Operadores


+ - * / % == != < > <= >= && || ^ ~ & | ^ << >>

Descripcin Operadores aritmticos Operadores de igualdad Operadores de comparacin Operadores booleanos Operadores a nivel de bits

Operandos Nmeros (% slo enteros) Cualesquiera Nmeros o caracteres Booleanos Enteros

Tipo del resultado Operadores


+ - * / % == != < > <= >= && || ^ ~ & | ^ << >>

Descripcin Operadores aritmticos Operadores relacionales Operadores booleanos Operadores a nivel de bits

Resultado Nmero* Booleano Entero

Introduccin a la Programacin: C

- 43 -

Sentencias de asignacin
Las sentencias de asignacin constituyen el ingrediente bsico en la construccin de programas con lenguajes imperativos.

Sintaxis:
<variable> = <expresin>;

Al ejecutar una sentencia de asignacin: 1. Se evala la expresin que aparece a la derecha del operador de asignacin (=). 2. El valor que se obtiene como resultado de evaluar la expresin se almacena en la variable que aparece a la izquierda del operador de asignacin (=).

Restriccin: El tipo del valor que se obtiene como resultado de evaluar la expresin ha de ser compatible con el tipo de la variable.

Ejemplos
x = x + 1;

// Declaracin con inicializacin otraVariable = miVariable; // Sentencia de asignacin


int miVariable = 20;

NOTA IMPORTANTE: Una sentencia de asignacin no es una igualdad matemtica.


Introduccin a la Programacin: C - 44 -

Efectos colaterales
Al evaluar una expresin, algunos operadores provocan efectos colaterales (cambios en el estado del programa; es decir, cambios en el valor de alguna de las variables del programa).

Operadores de incremento (++) y decremento (--) El operador ++ incrementa el valor de una variable. El operador -- decrementa el valor de una variable. El resultado obtenido depende de la posicin relativa del operando: Operador
x++ ++x x---x

Descripcin Post-incremento Evala primero y despus incrementa Pre-incremento Primero incrementa y luego evala Post-decremento Evala primero y luego decrementa Pre-decremento Primero decrementa y luego evala Equivalencia
i=0; i=i+1; i=1; i=i+1; j=i; i=1; j=i; i=i+1; i=3; i=i+1; n=2*i; i=3; n=2*i; i=i+1; i=1; i=i+1; k=i+i;

Ejemplo
i=0; i++; i=1; j=++i; i=1; j=i++; i=3; n=2*(++i); i=3; n=2*(i++); i=1; k=++i+i;

Resultado
i=1; j=2; j=1; n=8; n=6; k=4;

El uso de operadores de incremento y decremento reduce el tamao de las expresiones pero las hace ms difciles de interpretar. Es mejor evitar su uso en expresiones que modifican mltiples variables o usan varias veces una misma variable.

Introduccin a la Programacin: C

- 45 -

Operadores combinados de asignacin (op=) C define 10 operadores que combinan el operador de asignacin con otros operadores (aritmticos y a nivel de bits): Operador
+= -= *= /= %= &= |= ^= <<= >>=

Ejemplo
i f n n n k k k x x += 1; -= 4.0; *= 2; /= 2; %= 2; &= 0x01; |= 0x02; ^= 0x04; <<= 1; >>= 2;

Equivalencia
i++; f = f n = n n = n n = n k = k k = k k = k x = x x = x 4.0; * 2; / 2; % 2; & 0x01; & 0x02; & 0x04; << 1; >> 2;

La forma general de los operadores combinados de asignacin es


variable op= expresin;

que pasa a ser


variable = variable op (expresin);

OJO:

Las expresiones con y sin operadores combinados de asignacin no son siempre equivalentes.

Ejemplo
v[i++]+= 2; y v[i++]=v[i++]+2; no son equivalentes.
Introduccin a la Programacin: C - 46 -

Conversin de tipos
En determinadas ocasiones, nos interesa convertir el tipo de un dato en otro tipo para poder operar con l. Ejemplo Convertir un nmero entero en un nmero real para poder realizar divisiones en coma flotante C permite realizar conversiones entre datos de tipo numrico (enteros y reales), as como trabajar con caracteres como si fuesen nmeros enteros: - La conversin de un tipo con menos bits a un tipo con ms bits es automtica (vg. de short a long, de float a double), ya que el tipo mayor puede almacenar cualquier valor representable con el tipo menor (adems de valores que no caben en el tipo menor). - La conversin de un tipo con ms bits a un tipo con menos bits se realizar de forma explcita con castings. Como se pueden perder datos en la conversin, un buen compilador de C nos avisa de posibles conversiones errneas (warnings)
int i; char b; i = 13; b = 13; b = i; // No se realiza conversin alguna // Se permite porque 13 est dentro // del rango permitido de valores // Podra ser un error // Fuerza la conversin // Almacena 14 en i // Sigue almacenando 14

b = (char) i; i = (int) 14.456; i = (int) 14.656;

Introduccin a la Programacin: C

- 47 -

Castings Para realizar una conversin explcita de tipo (un casting) basta con poner el nombre del tipo deseado entre parntesis antes del valor que se desea convertir:
char short long double c; x; k; d;

Sin conversin de tipo:


c x k d = = = = A; 100; 100L; 3.0;

Conversiones implcitas de tipo (por asignacin):


x k k d = = = = c; 100; x; 3; // // // // char short short long short long short double

Conversiones implcitas de tipos (por promocin aritmtica)


c+1 x / 2.0f // char short // short float

Posibles errores de conversin (no siempre detectados):


x = k; x = 3.0; x = 5 / 2.0f; // long short // double short // float short

Conversiones explcitas de tipo (castings):


x = (short) k; x = (short) 3.0; x = (short) (5 / 2.0f);

Introduccin a la Programacin: C

- 48 -

Algunas conversiones de inters De nmeros en coma flotante a nmeros enteros Al convertir de nmero en coma flotante a entero, el nmero se trunca (redondeo a cero). En la biblioteca math.h existen funciones que nos permiten realizar el redondeo de otras formas:
floor(x), ceil(x)

El redondeo al que estamos acostumbrados tendremos que implementarlo nosotros:


int i = x+0.5;

Conversin entre caracteres y nmeros enteros Como cada carcter tiene asociado un cdigo ASCII, los caracteres pueden interpretarse como nmeros enteros
int i; char c;

Ejemplo
i c c c = = = = a; 97; a+1; i+2;

Equivalencia
i c c c = = = = (int) a; (char) 97; (char) ((int)a+1); (char) (i+2);

Resultado
i c c c = = = = 97 a b c

Resumen de conversin de tipos Conversiones implcitas


long double > double > float > unsigned long > long > unsigned short > short > char

Conversiones explcitas (castings) (tipo) expresin


Introduccin a la Programacin: C - 49 -

Evaluacin de expresiones
- La precedencia de los operadores determina el orden de evaluacin de una expresin (el orden en que se realizan las operaciones): 3*4+2 es equivalente a (3*4)+2 porque el operador * es de mayor precedencia que el operador +

- Cuando en una expresin aparecen dos operadores con el mismo nivel de precedencia, la asociatividad de los operadores determina el orden de evaluacin. a b + c d es equivalente a ((a b) + c) d porque los operadores aritmticos son asociativos de izquierda a derecha a = b += c = 5 es equivalente a a = (b += (c = 5)) porque los operadores de asignacin son asociativos de derecha a izquierda

- La precedencia y la asociatividad determinan el orden de los operadores, pero no especifican el orden en que se evalan los operandos de un operador binario (un operador con dos operandos): En C, los operandos se evalan de izquierda a derecha: el operando de la izquierda se evala primero. Si los operandos no tienen efectos colaterales (esto es, no cambian el valor de una variable), el orden de evaluacin de los operandos es irrelevante.

NOTA: Siempre es recomendable el uso de parntesis. Los parntesis nos permiten especificar el orden de evaluacin de una expresin, adems de hacer su interpretacin ms fcil.
Introduccin a la Programacin: C - 50 -

Programas
Estructura de un programa simple
Los programas ms simples escritos en lenguajes imperativos suelen realizar tres tareas de forma secuencial: Entrada de datos Procesamiento de los datos Salida de resultados

La funcin main
El punto de entrada de un programa en C es la funcin main:
int main (int argc, char *argv[]) {

Declaraciones y sentencias escritas en C


return 0; }

Las llaves {} delimitan bloques de cdigo en C (conjuntos de declaraciones y sentencias). La ejecucin de un programa escrito en C comienza invocando a la funcin main().

Introduccin a la Programacin: C

- 51 -

El preprocesador de C
#include Inclusin de ficheros de cabecera
#include <stdio.h> #include biblioteca.h

#define Definicin de constantes simblicas y macros


#define CONSTANTE expresin

#define MAX(a,b) ( ((a)>(b))? (a):(b) )

#ifndef #endif Usado en ficheros de cabecera para no incluir lo mismo dos veces
#ifndef __XXX__ #define __XXX__ ... #endif

Introduccin a la Programacin: C

- 52 -

Estructura general de un fichero de cdigo en C

#includes de ficheros de cabecera (bibliotecas) #defines (constantes simblicas y macros)

Declaracin e implementacin de funciones

Funcionamiento del preprocesador

Fichero de entrada al compilador


Introduccin a la Programacin: C - 53 -

Operaciones de entrada/salida
Salida por pantalla con la funcin printf La funcin printf, que forma parte de la biblioteca estndar de funciones de entrada/salida <stdio.h>, nos permite mostrar mensajes de texto en la pantalla cuando ejecutamos un programa:
#include <stdio.h> int main (int argc, char *argv[]) { ... printf(Mi programa v1.0); ... }

Mostrar datos en funcin de su tipo


char c; ... printf (%c, c); int i; ... printf (%d, i); long x; ... printf (%ld, x); float f; ... printf (%f, f); double d; ... printf (%lf, d); long double r; ... printf (%Lf, r);

Mostrar mensajes en distintas lneas


printf (Una lnea de texto.\n); printf (Otra lnea de texto.\n);
Introduccin a la Programacin: C - 54 -

Entrada desde el teclado con la funcin scanf La funcin scanf, de la biblioteca estndar de funciones de entrada/salida <stdio.h>, nos permite leer datos desde el teclado para suministrarle datos de entrada a un programa:
#include <stdio.h> int main (int argc, char *argv[]) { ... scanf(%d,&dato); ... }

Leer datos en funcin de su tipo


char c; ... scanf (%c, &c); int i; ... scanf (%d, &i); long x; ... scanf (%ld, &x); float f; ... scanf (%f, &f); double d; ... scanf (%lf, &d); long double r; ... scanf (%Lf, &r);

Operaciones de entrada/salida
printf(plantilla de formato, lista de variables); scanf(plantilla de formato, lista de referencias a variables);

Introduccin a la Programacin: C

- 55 -

Salida de datos con formato Al representar un nmero o una cadena, podemos especificar cmo deseamos hacerlo:

Sintaxis general

%-n.mX

El nmero n indica el nmero de caracteres que se utilizarn como mnimo para reprentar el dato (nmero total de dgitos en el caso de los nmeros, tanto enteros como reales). El nmero .m indica el nmero mximo de caracteres que se utilizarn para representar el dato. En el caso de los nmeros reales, indica el nmero de decimales que se mostrarn. El signo menos (-) es opcional y lo usaremos para indicar que el texto ha de justificarse a la izquierda. X indica el tipo del dato:
%d %x %o %c %s %f %e

Nmero entero en decimal Nmero entero en hexadecimal Nmero entero en octal Carcter Cadena de caracteres Nmero real Nmero real en notacin cientfica

Introduccin a la Programacin: C

- 56 -

Ejemplos

Introduccin a la Programacin: C

- 57 -

Ejemplo
Longitud de la hipotenusa de un tringulo rectngulo
/* Hipotenusa de un tringulo rectngulo calculada segn el teorema de Pitgoras */ #include <stdio.h> #include <math.h> int main () { // Declaraciones float lado1, lado2, hipotenusa; // Entrada de datos printf( Clculo de la hipotenusa \n); printf(de un tringulo rectngulo\n); printf(--------------------------\n); printf(Primer lado: ); scanf(%f, &lado1); printf(Segundo lado: ); scanf(%f, &lado2); // Clculos hipotenusa = sqrt(lado1*lado1 + lado2*lado2); // Salida de resultados printf (La hipotenusa mide %f.\n, hipotenusa); return 0; }

Introduccin a la Programacin: C

- 58 -

Ejemplo
Programa para comprobar si un ao es bisiesto o no Un ao es bisiesto si es divisible por 4 pero no por 100, o bien es divisible por 400.
#include <stdio.h> int main () { // Declaracin de variables int year; int bisiesto; // Entrada de datos printf(Introduzca un ao: ); scanf(%d, &year); // Clculos bisiesto = ((year%4==0) && (year%100!=0)) || (year%400==0); // Salida de resultados if (bisiesto) { printf (El ao es bisiesto.); } else { printf (El ao no es bisiesto.); } return 0; }

NOTA: La sentencia if nos permite controlar la ejecucin de un conjunto de sentencias en funcin de que se cumpla una condicin.
Introduccin a la Programacin: C - 59 -

Ejemplo
Cuota de una hipoteca intersMensual () = intersAnual / 12
cuotaMensual = cantidad 1 1 (1 + ) aos12

#include <stdio.h> #include <math.h> int main () { // Declaracin de variables double double int double cantidad; interes; tiempo; cuota; // // // // en en en en euros porcentaje (anual) aos euros (mensual)

double interesMensual; // en tanto por uno // Entrada de datos printf("Importe de la hipoteca (): "); scanf("%lf", &cantidad); printf("Tipo de inters (%): "); scanf("%lf", &interes); printf("Perodo de amortizacin (aos)"); scanf("%d", &tiempo); // Clculo de la cuota mensual interesMensual = interes/(12*100); cuota = (cantidad*interesMensual) / (1.0 - 1/pow(1+interesMensual,tiempo*12)); // Resultado printf("Cuota mensual: %.2lf ", cuota); } return 0;
- 60 -

Introduccin a la Programacin: C

Documentacin del cdigo


Comentarios Los comentarios sirven para incluir aclaraciones en el cdigo. ANSI C permite dos tipos de comentarios:
// Comentarios de una lnea /* Comentarios de varias lneas */

Es bueno incluir comentarios que expliquen lo que hace el programa y sus caractersticas claves (p.ej. autor, fecha, algoritmos utilizados, estructuras de datos, peculiaridades).
// Clculo del MCD // usando el algoritmo de Euclides // Fernando Berzal, 2004

Los comentarios nunca han de limitarse a decir en lenguaje natural lo que ya est escrito en el cdigo: Jams se utilizarn para parafrasear el cdigo y repetir lo que es obvio.
i++; // Incrementa el contador

Los comentarios han de aclarar; esto es, ayudar al lector en las partes difciles (y no confundirle). Si es posible, escriba cdigo fcil de entender por s mismo: cuanto mejor lo haga, menos comentarios necesitar.
int mes; int mes; // Mes // Mes del ao (1..12)

ax = 0x723;

/* RIP L.v.B. */

NB: Beethoven muri en 1827 (0x723 en hexadecimal).


Introduccin a la Programacin: C - 61 -

Sangras Conviene utilizar espacios en blanco o separadores para delimitar el mbito de las estructuras de control de nuestros programas. Lneas en blanco Para delimitar claramente los distintos segmentos de cdigo en nuestros programas dejaremos lneas en blanco entre ellos. Identificadores Los identificadores deben ser descriptivos (reflejar su significado).
p, i, s... precio, izquierda, suma...

Declaraciones Usualmente, declararemos una nica variable por lnea. Nunca mezclaremos en una misma lnea la declaracin de variables que sean de distintos tipos o que se utilicen en el programa para distintos fines. Constantes Se considera una mala costumbre incluir literales de tipo numrico (nmeros mgicos) en medio del cdigo. Se prefiere la definicin de constantes simblicas (mediante la directiva #define del preprocesador de C).

Introduccin a la Programacin: C

- 62 -

Expresiones Uso de parntesis: Aunque las normas de precedencia de los operadores vienen definidas en el lenguaje, no abusaremos de ellas. Siempre resulta ms fcil interpretar una expresin si sta tiene los parntesis apropiados. Adems, stos eliminan cualquier tipo de ambigedad. Uso de espacios en blanco: Resulta ms fcil leer una expresin con espacios que separen los distintos operadores y operandos involucrados en la expresin.
a%x*c/b-1 ( (a%x) * c ) / b - 1

Expresiones booleanas: Es aconsejable escribirlas como se diran en voz alta.


!(bloque<actual) ( bloque >= actual )

Expresiones complejas: Es aconsejable dividirlas para mejorar su legibilidad Claridad: Siempre buscaremos la forma ms simple de escribir una expresin.
key = key >> ( bits ((bits>>3)<<3)); key >>= bits & 0x7;

Conversiones de tipo (castings): Evitaremos las conversiones implcitas de tipo. Cuando queramos realizar una conversin de tipo, lo indicaremos explcitamente.
i = (int) f;

Siempre se han de evitar los efectos colaterales (modificaciones no deseadas pueden afectar a la ejecucin del programa sin que nos demos cuenta de ello).
Introduccin a la Programacin: C - 63 -

IDEA CLAVE Escribimos cdigo para que lo puedan leer otras personas, no slo para que lo traduzca el compilador (si no fuese as, podramos seguir escribiendo nuestros programas en binario).

No comente el cdigo malo (uso de construcciones extraas, expresiones confusas, sentencias poco legibles...): Reescrbalo. No contradiga al cdigo: Los comentarios suelen coincidir con el cdigo cuando se escriben, pero a medida que se corrigen errores y el programa evoluciona, los comentarios suelen dejarse en su forma original y aparecen discrepancias. Si cambia el cdigo, asegrese de que los comentarios sigan siendo correctos.

El cdigo bien escrito es ms fcil de leer, entender y mantener (adems, seguramente tiene menos errores)

Errores de programacin
Errores sintcticos Errores detectados por el compilador en tiempo de compilacin. Errores semnticos Slo se detectan en tiempo de ejecucin: Causan que el programa finalice inesperadamente su ejecucin (p.ej. divisin por cero) o que el programa proporcione resultados incorrectos.
Introduccin a la Programacin: C - 64 -

Elementos lxicos del lenguaje de programacin C


Elementos lxicos de los lenguajes de programacin (tokens) Palabras reservadas Identificadores Literales Operadores Delimitadores Comentarios Apndices Construccin de expresiones en C Precedencia y asociatividad de los operadores en C

Elementos lxicos de C
Token
Componente lxico de un lenguaje de programacin

Palabra reservada
Palabra que tiene un significado concreto en el lenguaje de programacin, sin necesidad de que se lo asignemos nosotros. auto const enum goto else sizeof register unsigned break continue extern if return static switch void case default float int short struct typedef volatile char do for long signed double union while

Identificador
Palabra que podemos utilizar para denominar algo en el lenguaje. Identificadores en C - El primer smbolo del identificador ser un carcter alfabtico (a, , z, A, , Z, _). Despus de ese primer carcter podremos poner caracteres alfanumricos (a, , z) y (0, 1, , 9) y el guin de subrayado _. - Las maysculas y las minsculas se consideran diferentes. - El guin de subrayado se interpreta como una letra ms. - Los identificadores no pueden coincidir con las palabras reservadas. Ejemplos vlidos a, pepe, r456, tu_re_da, AnTeNa, antena Ejemplos no vlidos 345abc, mi variable, Nombre.Largo, caada, camin
Introduccin a la Programacin: C - 66 -

Literal
Especificacin de un valor concreto de un tipo de dato. Nmeros 3 3.1416 u|U l|L f|F 0 0x 0.31416e1 0.31416e+1 .31416e1f (unsigned) (long) (float) (octal) (hexadecimal)

Sufijos:

Prefijos:

Caracteres a b c ... 0 1 2 ...

Secuencias de escape \a \b \f \n \r \t \v \\ \' \" \? \O \xH \XH vg: \0 0x07 0x08 0x0C 0x0A 0x0D 0x09 0x0B 0x5c 0x27 0x22 0x3F BEL BS FF LF CR HT VT \ ' " ? Sonido de alerta Retroceso (Backspace) Salto de pgina (Form feed) Salto de lnes (Line feed) = Nueva lnea Retorno de carro Tabulador horizontal Tabulador vertical Barra invertida (Backslash) Apstrofe = Comilla simple Comillas = Comilla doble Signo de interrogacin O = Cadena de dgitos octales H = Cadena de dgitos hexadecimales H = Cadena de dgitos hexadecimales Carcter nulo

NULL

Cadenas de caracteres Cadena de caracteres en C \Mensaje entrecomillado\\n


Introduccin a la Programacin: C - 67 -

Operador
Igual que en Matemticas, realizan una accin especfica: - Suelen estar definidos en el ncleo del compilador (aunque tambin pueden estar definidos en bibliotecas externas) - Suelen representarse con tokens formados por smbolos. - Suelen utilizar notacin infija. - Pueden aplicarse a uno o varios operandos (argumentos). - Suelen devolver un valor.

Delimitador
Smbolos utilizados como separadores de las distintas construcciones de un lenguaje de programacin (esto es, los signos de puntuacin de un lenguaje de programacin. [ ] ( ) { } , ; : ... * = #

Corchetes: Se utilizan para especificar los subndices de los arrays. Parntesis: Agrupan expresiones e indican los parmetros de las funciones. Llaves: Delimitan sentencias compuestas (bloques de cdigo). Comas: Separan los elementos de una lista. Punto y coma: Indica el final de una sentencia. Dos puntos: Etiquetas. Elipsis (...): Funciones con un nmero variable de argumentos. Asteriscos (*): Punteros Inicializador (=): Separa la declaracin de la inicializacin de variables. Almohadilla (#): Directivas del preprocesador.
Introduccin a la Programacin: C - 68 -

Comentario
Aclaracin que el programador incluye en el texto del programa para mejorar su inteligibilidad. Comentarios en C: Cualquier secuencia de caracteres que comience con /*. El comentario termina cuando se encuentra el par */. No se pueden introducir comentarios dentro de otros ANSI C tambin permite comentarios en una lnea (al estilo de C++): Estos comentarios comienzan con dos barras // y terminan al final de la lnea.

Introduccin a la Programacin: C

- 69 -

Apndices
Construccin de expresiones en C
Operador de asignacin = Operadores de comparacin == != >= <= > <

Operadores aritmticos + cast-expression - cast-expression add-expression + multiplicative-expression add-expression - multiplicative-expression multiplicative-expr * cast-expr multiplicative-expr / cast-expr multiplicative-expr % cast-expr postfix-expression ++ ++ unary-expression postfix-expression --- unary-expression Operadores booleanos logical-AND-expr && inclusive-OR-expression logical-OR-expr || logical-AND-expression ! cast-expression (postincremento) (preincremento) (postdecremento) (predecremento)

Introduccin a la Programacin: C

- 70 -

Operadores a nivel de bits AND-expression & equality-expression exclusive-OR-expr ^ AND-expression inclusive-OR-expr | exclusive-OR-expression ~cast-expression shift-expression << additive-expression shift-expression >> additive-expression Operadores compuestos de asignacin *= /= %= += -= <<= >>= &= ^= |=

Operador condicional logical-OR-expr ? expr : conditional-expr Operadores para el manejo de punteros & cast-expression * cast-expression Operadores postfijos postfix-expression(<arg-expression-list>) array declaration [constant-expression] compound statement { statement list } postfix-expression . identifier postfix-expression -> identifier El operador sizeof sizeof unary-expression sizeof (type-name)

Introduccin a la Programacin: C

- 71 -

Precedencia y asociatividad de los operadores en C


Operador () [] . -> sizeof ++ -++ -~ ! + & * (tipo) * / % + << >> < <= > >= == != & ^ | && || ?: = Significado Llamada a una funcin Acceso a los elementos de un array Miembro de una estructua o unin Miembro de una estructura o unin (punteros) Tamao de una variable / tipo Postincremento (v++) Postdecremento (v--) Preincremento (++v) Predecremento (--v) Complemento bit a bit Negacin lgica Menos unario Ms unario Referencia (Direccin de) Indireccin (Contenido de) Casting (conversin de tipo) Multiplicacin Divisin Resto Suma Resta Desplazamiento de bits a la izquierda Desplazamiento de bits a la derecha Menor que Menor o igual que Mayor que Mayor o igual que Igual que Distinto de Operador AND (bit a bit) Operador XOR (bit a bit) Operador OR (bit a bit) Operador AND (lgico) Operador OR (lgico) Operador condicional Operador de asignacin += -= *= /= %= &= ^= |= >>= <<= Asociatividad De izquierda a derecha De derecha a izquierda

De izquierda a derecha

De derecha a izquierda

Introduccin a la Programacin: C

- 72 -

Tipos de datos en C
Tipos de datos bsicos
char int float double void Punteros Caracteres Nmeros enteros Nmeros en coma flotante (32 bits) Nmeros en coma flotante de doble precisin (64 bits) Tipo nulo Direcciones de memoria

Arrays Como en Pascal Estructuras Como los registros de Pascal. Uniones Variables que pueden contener datos de distintos tipos.

Modificadores
Tamao de la variable short long signed unsigned register auto (por defecto) static extern (int por defecto) (int por defecto)

Signo (char, short, int, long)

Modo de almacenamiento

Enumeraciones
enum [<identificador>] { <nombre_constante> [= <valor>], ... } [lista de variables];

enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat} anyday;

Tipos definidos por el usuario


typedef <tipo> <identificador>;

typedef unsigned char byte; typedef struct { double real, imag; } complex;

Declaracin de variables
<tipo> <identificador> [= <init>] [, ...] ;

Ejemplos: int x; int y = 4; int x = 1, y = 2; int *p; int **int_ptr; long double v; complex i; enum day hoy; char ch; unsigned char c1, c2; char *str; char str[] = "ATD1"; int int int int vector[]; vector[3]; vector[3] = {1, 2, 3}; matriz[3][4];

Estructuras de control
Programacin estructurada Estructuras condicionales La sentencia if La clusula else Encadenamiento y anidamiento El operador condicional ?: La sentencia switch Estructuras repetitivas/iterativas El bucle while El bucle for El bucle dowhile Bucles anidados Cuestiones de estilo Vectores y matrices Algoritmos de ordenacin Algoritmos de bsqueda

Las estructuras de control controlan la ejecucin de las instrucciones de un programa

Programacin estructurada
IDEA CENTRAL: Las estructuras de control de un programa slo deben tener un punto de entrada y un punto de salida.

La programacin estructurada... mejora la productividad de los programadores. mejora la legibilidad del cdigo resultante.

La ejecucin de un programa estructurado progresa disciplinadamente, en vez de saltar de un sitio a otro de forma impredecible

Gracias a ello, los programas resultan ms fciles de probar se pueden depurar ms fcilmente se pueden modificar con mayor comodidad

Estructuras de control - C

-1-

En programacin estructurada slo se emplean tres construcciones:

Secuencia Conjunto de sentencias que se ejecutan en orden Ejemplos: Sentencias de asignacin y llamadas a rutinas.

Seleccin Elige qu sentencias se ejecutan en funcin de una condicin. Ejemplos: Estructuras de control condicional if-then-else y case/switch

Iteracin Las estructuras de control repetitivas repiten conjuntos de instrucciones. Ejemplos: Bucles while, do...while y for.

Teorema de Bhm y Jacopini (1966): Cualquier programa de ordenador puede disearse e implementarse utilizando nicamente las tres construcciones estructuradas (secuencia, seleccin e iteracin; esto es, sin sentencias goto).

Bhm, C. & Jacopini, G.: Flow diagrams, Turing machines, and languages only with two formation rules. Communications of the ACM, 1966, Vol. 9, No. 5, pp. 366-371 Dijkstra, E.W.: Goto statement considered harmful. Communications of the ACM, 1968, Vol. 11, No. 3, pp. 147-148
Estructuras de control - C -2-

Estructuras de control condicionales


Por defecto, las instrucciones de un programa se ejecutan secuencialmente:

El orden secuencial de ejecucin no altera el flujo de control del programa respecto al orden de escritura de las instrucciones.

Sin embargo, al describir la resolucin de un problema, es normal que tengamos que tener en cuenta condiciones que influyen sobre la secuencia de pasos que hay que dar para resolver el problema:

Segn se cumplan o no determinadas condiciones, la secuencia de pasos involucrada en la realizacin de una tarea ser diferente

Las estructuras de control condicionales o selectivas nos permiten decidir qu ejecutar y qu no en un programa.

Ejemplo tpico Realizar una divisin slo si el divisor es distinto de cero.

Estructuras de control - C

-3-

La estructura de control condicional if


La sentencia if nos permite elegir si se ejecuta o no un bloque de instrucciones.

Condicin_1

Cierta

Cierta

Condicin_2

Falsa

Falsa

Bloque_1

Bloque_3

Bloque_

Bloque_2

Bloque_5

SIENTONCES

SIENTONCESSINO

Sintaxis
if (condicin) sentencia;

if (condicin) { bloque }

donde bloque representa un bloque de instrucciones.

Bloque de instrucciones: Secuencia de instrucciones encerradas entre dos llaves {....}


Estructuras de control - C -4-

Consideraciones acerca del uso de la sentencia if - Olvidar los parntesis al poner la condicin del if es un error sintctico (los parntesis son necesarios) - Confundir el operador de comparacin == con el operador de asignacin = puede producir errores inesperados - Los operadores de comparacin ==, !=, <= y >= han de escribirse sin espacios. - => y =< no son operadores vlidos en C. - El fragmento de cdigo afectado por la condicin del if debe sangrarse para que visualmente se interprete correctamente el mbito de la sentencia if:
if (condicin) { // Aqu se incluye el cdigo // que ha de ejecutarse slo // si se cumple la condicin del if // (sangrado para que se vea dnde // empieza y dnde acaba el if) }

Error comn:
if (condicin); sentencia;

es interpretado como
if (condicin) ; // Sentencia vaca sentencia;

La sentencia siempre se ejecutara!!!


Estructuras de control - C -5-

Ejemplo Decir si un nmero es positivo

#include <stdio.h> int main (int argc, char *argv[]) { int x; printf(Dme un numero); scanf(%d,&x); if (x>0) { printf(El numero %d es positivo,x); } return 0; }

Estructuras de control - C

-6-

La clusula else
Una sentencia if, cuando incluye la clusula else, permite ejecutar un bloque de cdigo si se cumple la condicin y otro bloque de cdigo diferente si la condicin no se cumple.

Condicin_1

Cierta

Cierta

Condicin_2

Falsa

Falsa

Bloque_1

Bloque_3

Bloque_4

Bloque_2

Bloque_5

SIENTONCES

SIENTONCESSINO

Sintaxis
if (condicin) sentencia1; else sentencia2;

if (condicin) { bloque1 } else { bloque2 }

Los bloques de cdigo especificados representan dos alternativas complementarias y excluyentes


Estructuras de control - C -7-

Ejemplo Decir si un nmero es positivo o negativo

#include <stdio.h> void main () { int x; printf(Dme un numero: ); scanf(%d,&x); if (x>=0) { printf(El numero %d es positivo, x); } else { printf(El numero %d es negativo, x); } }

La sentencia if anterior es equivalente a


if (x>=0) { printf(El numero %d es positivo, x); } if (x<0) { // Condicin complementaria a x>=0 printf(El numero %d es negativo, x); }

si bien nos ahorramos comprobar una condicin al usar else.


Estructuras de control - C -8-

Encadenamiento
Las sentencias if se suelen encadenar:

if else if

#include <stdio.h> void main () { float nota; printf(Dme una nota: ); scanf(%f,&nota); if (nota>=9) { printf(Sobresaliente); } else if (nota>=7) { printf(Notable); } else if (nota>=5) { printf(Aprobado); } else { printf(Suspenso); } }

El if encadenado anterior equivale a:


if (nota>=9) { printf(Sobresaliente); } if ((nota>=7) && (nota<9)) { printf(Notable); } if ((nota>=5) && (nota<7)) { printf(Aprobado); } if (nota<5) { printf(Suspenso); }
Estructuras de control - C -9-

Anidamiento
Las sentencias if tambin se pueden anidar unas dentro de otras.

Ejemplo Resolucin de una ecuacin de primer grado ax+b = 0


#include <stdio.h> void main() { float a,b; printf(Coeficientes de la ecuacin ax+b=0:); scanf (%f %f,&a,&b); if (a!=0) { printf(La solucin es %f, -b/a); } else { if (b!=0) { printf(La ecuacin no tiene solucin.); } else { printf(Solucin indeterminada.); } } }

El if anidado anterior equivale a


if (a!=0) { printf(La solucin es %f, -b/a); } if ((a==0) && (b!=0)) { printf(La ecuacin no tiene solucin.); } if ((a==0) && (b==0)) { printf(Solucin indeterminada.); }

En este caso, se realizaran 5 comparaciones en vez de 2.


Estructuras de control - C - 10 -

El operador condicional ?:
C proporciona una forma de abreviar una sentencia if

El operador condicional ?: permite incluir una condicin dentro de una expresin.

Sintaxis
condicin? expresin1: expresin2

equivale a
if (condicin) expresin1 else expresin2

Slo se evala una de las sentencias, por lo que deberemos ser cuidadosos con los efectos colaterales.

Ejemplos
max = (x>y)? x : y; min = (x<y)? x : y; med = (x<y)? ((y<z)? y: ((z<x)? x: z)): ((x<z)? x: ((z<y)? y: z));

Estructuras de control - C

- 11 -

Seleccin mltiple con la sentencia switch


Permite seleccionar entre varias alternativas posibles Sintaxis
switch (expresin) { case expr_cte1: sentencia1; case expr_cte2: sentencia2; ... case expr_cteN: sentenciaN; default: sentencia; }

Se selecciona a partir de la evaluacin de una nica expresin. La expresin del switch ha de ser de tipo entero. Los valores de cada caso del switch han de ser constantes. La etiqueta default marca el bloque de cdigo que se ejecuta por defecto (cuando al evaluar la expresin se obtiene un valor no especificado por los casos del switch). En C, se ejecutan todas las sentencias incluidas a partir del caso correspondiente, salvo que explcitamente usemos break:
switch (expresin) { case expr_cte1: sentencia1; break; case expr_cte2: case expr_cte3: sentenciaN; } switch (expresin) { case expr_cte1: sentencia1; break; case expr_cte2: sentencia2; break; default: sentencia; }
- 12 -

Estructuras de control - C

Ejemplo
#include <stdio.h> void main() { int nota; printf(Calificacin: ); scanf(%d, &nota); switch (nota) { case case case case case 0: 1: 2: 3: 4: printf(Suspenso); break;

case 5: case 6: printf(Aprobado); break; case 7: case 8: printf(Notable); break; case 9: printf(Sobresaliente); break; case 10: printf(Matrcula); break; default: printf(Error); } }

Si trabajamos con datos de tipo real, tendremos que usar sentencias if encadenadas.
Estructuras de control - 13 -

Estructuras de control repetitivas/iterativas repetitivas/iterativas


A menudo es necesario ejecutar una instruccin o un bloque de instrucciones ms de una vez. Ejemplo Implementar un programa que calcule la suma de N nmeros ledos desde teclado.

Podramos escribir un programa en el que apareciese repetido el cdigo que deseamos que se ejecute varias veces, pero Nuestro programa podra ser demasiado largo. Gran parte del cdigo del programa estara duplicado, lo que dificultara su mantenimiento en caso de que tuvisemos que hacer cualquier cambio, por trivial que fuese ste. Una vez escrito el programa para un nmero determinado de repeticiones (p.ej. sumar matrices 3x3), el mismo programa no podramos reutilizarlo si necesitsemos realizar un nmero distinto de operaciones (p.ej. matrices 4x4).

Las estructuras de control repetitivas o iterativas, tambin conocidas como bucles, nos permiten resolver de forma elegante este tipo de problemas. Algunas podemos usarlas cuando conocemos el nmero de veces que deben repetirse las operaciones. Otras nos permiten repetir un conjunto de operaciones mientras se cumpla una condicin.

Iteracin: Cada repeticin de las instrucciones de un bucle.


Estructuras de control - C - 14 -

El bucle while

while (condicin) sentencia;

while (condicin) { bloque }

Condicin

Bloque

S No

MUY IMPORTANTE

En el cuerpo del bucle debe existir algo que haga variar el valor asociado a la condicin que gobierna la ejecucin del bucle.

Estructuras de control - C

- 15 -

Ejemplo Tabla de multiplicar de un nmero


#include <stdio.h> void main () { int n, i; printf (Introduzca un nmero: ); scanf (%d, &n); i=0; // Inicializacin del contador while (i<=10) { printf (%d x %d = %d\n, n, i, n*i); i++; } }

Ejemplo Divisores de un nmero


#include <stdio.h> void main () { int n; int divisor; printf (Introduzca un nmero: ); scanf (%d, &n); printf (Los divisores del nmero son:\n); divisor = n; while (divisor>0) { if ((n%divisor) == 0) printf (%d\n, divisor); divisor--; } }

Estructuras de control - C

- 16 -

Ejemplo Suma de N nmeros


#include <stdio.h> void main() { int total; double suma; double n; int i;

// // // //

Nmero de datos Suma de los datos Nmero ledo desde el teclado Contador

printf (Nmero total de datos: ); scanf (%d,&total); suma = 0; // Inicializacin de la suma i = 0; // Inicializacin del contador while (i<total) { printf (Dato %d: , i); scanf (%lf,&n); suma = suma + n; i++; } printf (Suma total = %lf\n, suma); }

Tal como est implementado el programa, fcilmente podramos calcular la media de los datos (suma/total). EJERCICIO Ampliar el programa anterior para que, adems de la suma y de la media, nos calcule tambin el mximo, el mnimo, la varianza y la desviacin tpica de los datos. Pista:
Estructuras de control - C

La varianza se puede calcular a partir de la suma de los cuadrados de los datos.


- 17 -

En los ejemplos anteriores se conoce de antemano el nmero de iteraciones que han de realizarse (cuntas veces se debe ejecutar el bucle): En este caso, la expresin del while se convierte en una simple comprobacin del valor de una variable contador (una variable que se incrementa o decrementa en cada iteracin y nos permite contabilizar la iteracin en la que nos encontramos). En otras ocasiones, puede que no conozcamos de antemano cuntas iteraciones se han de realizar. Ejemplo Sumar una serie de nmeros hasta que el usuario introduzca un cero
#include <stdio.h> void main() { double suma; double n;

// Suma de los datos // Nmero ledo desde el teclado

suma = 0; // Inicializacin de la suma printf (Introduzca un nmero (0 para terminar): ); scanf (%lf, &n); while (n!=0) { suma = suma + n; printf (Introduzca un nmero (0 para terminar): ); scanf (%lf, &n); } printf (Suma total = %lf\n, suma); }

El valor introducido determina si se termina o no la ejecucin del bucle.


Estructuras de control - C - 18 -

El bucle for
Se suele emplear en sustitucin del bucle while cuando se conoce el nmero de iteraciones que hay que realizar. Sintaxis
for (exp1; exp2; exp3) { bloque; }

Equivalencia entre for y while


for (expr1; expr2; expr3) { bloque; }

equivale a

expr1; while (expr2) { bloque; expr3; }


- 19 -

Estructuras de control - C

Ejemplo Clculo del factorial de un nmero


Bucle for

#include <stdio.h> void main() { long i, n, factorial; printf ("Introduzca un nmero: "); scanf ("%ld", &n); factorial = 1; for (i=1; i<=n; i++) { factorial *= i; } printf ("factorial(%ld) = %ld", n, factorial); }

Bucle while

#include <stdio.h> void main() { long i, n, factorial; printf ("Introduzca un nmero: "); scanf ("%ld", &n); factorial = 1; i = 1; while (i<=n) { factorial *= i; i++; } printf ("factorial(%ld) = %ld", n, factorial); }
Estructuras de control - C - 20 -

for (expr1; expr2; expr3) { bloque; }

En un bucle for La primera expresin, expr1, suele contener inicializaciones de variables separadas por comas. En especial, siempre aparecer la inicializacin de la variable que hace de contador. Las instrucciones que se encuentran en esta parte del for slo se ejecutarn una vez antes de la primera ejecucin del cuerpo del bucle (bloque). La segunda expresin, expr2, es la que contiene una expresin booleana (la que aparecera en la condicin del bucle while equivalente para controlae la ejecucin del cuerpo del bucle). La tercera expresin, expr3, contiene las instrucciones, separadas por comas, que se deben ejecutar al finalizar cada iteracin del bucle (p.ej. el incremento/decremento de la variable contador). El bloque de instrucciones bloque es el mbito del bucle (el bloque de instrucciones que se ejecuta en cada iteracin).

Estructuras de control - C

- 21 -

Cabecera del bucle


for (i=0; i<N; i++)

Nmero de iteraciones N

for (i=0; i<=N; i++)

N+1

for (i=k; i<N; i++)

N-k

for (i=N; i>0; i--)

for (i=N; i>=0; i--)

N+1

for (i=N; i>k; i--)

N-k

for (i=0; i<N; i+=k)

N/k

for (i=j; i<N; i+=k)

(N-j)/k

for (i=1; i<N; i*=2)

log2 N

for (i=0; i<N; i*=2)

for (i=N; i>0; i/=2)

log2 N + 1

suponiendo que N y k sean enteros positivos

Bucles infinitos Un bucle infinito es un bucle que se repite infinitas veces:


for (;;) while (1) /*bucle infinito*/ /*bucle infinito*/

Si nunca deja de cumplirse la condicin del bucle, nuestro programa se quedar indefinidamente ejecutando el cuerpo del bucle, sin llegar a salir de l.
Estructuras de control - C - 22 -

El bucle do while
Tipo de bucle, similar al while, que realiza la comprobacin de la condicin despus de ejecutar el cuerpo del bucle. Sintaxis
do sentencia; while (condicin);

do { bloque } while (condicin);

El bloque de instrucciones se ejecuta al menos una vez. Especialmente indicado para validar datos de entrada (comprobar que los valores obtenidos estn dentro del rango de valores esperados).

Estructuras de control - C

- 23 -

Ejemplo Clculo del factorial comprobando el valor del dato de entrada


#include <stdio.h> void main() { long i, n, factorial; do { printf ("Introduzca un nmero (entre 1 y 12): "); scanf ("%ld", &n); } while ((n<1) || (n>12)); factorial = 1; for (i=1; i<=n; i++) { factorial *= i; } printf ("factorial(%ld) = %ld", n, factorial); }

IMPORTANTE

En todos nuestros programas debemos asegurarnos de que se obtienen datos de entrada vlidos antes de realizar cualquier tipo de operacin con ellos.

Estructuras de control - C

- 24 -

Ejemplo Clculo de la raz cuadrada de un nmero

#include <stdio.h> #include <math.h> void main() { // Declaracin de variables double n; double r; double prev; // Nmero real // Raz cuadrada del nmero // Aproximacin previa de la raz

// Entrada de datos do { printf("Introduzca un nmero positivo: "); scanf("%lf", &n); } while (n<0); // Clculo de la raz cuadrada r = n/2; do { prev = r; r = (r+n/r)/2; } while (fabs(r-prev) > 1e-6); // Resultado printf("La raz cuadrada de %lf es %lf", n, r); }

NOTA: La funcin abs nos da el valor absoluto de un nmeo entero. Para trabajar con reales hemos de usar fabs.

Estructuras de control - C

- 25 -

Bucles anidados
Los bucles tambin se pueden anidar:

for (i=0; i<N;i++) { for (j=0; j<N; j++) { printf((%d,%d) ,i,j); } }

genera como resultado:


(0,0) (0,1) (0,2) (0,N) (1,0) (1,1) (1,2) (1,N) (N,0) (N,1) (N,2) (N,N)

Ejemplo
#include <stdio.h> void main () { int n,i,k; n = 0; for (i=1; i<=2; i++) { for (k=5; k>=1; k-=2) { n = n + i + k; } } printf("N vale %d", n); }
Paso N i k 1 0 ? ? 1 5 3 1 1 2 3 4 6 5 3 4 10 5 3 4 12 2 5 3 1 1 5 3 6 2 3 4 19 5 3 4 24 5 3 4 27 3 5 3 6 2 7

// Paso 1 // Paso 2 // Paso 3 // Paso 4 // Paso 5 // Paso 6 // Paso 7

Estructuras de control - C

- 26 -

Cuestiones de estilo
Escribimos cdigo para que lo puedan leer otras personas, no slo para que lo traduzca el compilador.

Identificadores
q

Los identificadores deben ser descriptivos


p, i, s... precio, izquierda, suma...

En ocasiones, se permite el uso de nombres cortos para variables locales cuyo significado es evidente (p.ej. bucles controlados por contador)
for (elemento=0; elemento<N; elemento++ ) for (i=0; i<N; i++)

Constantes
q

Se considera una mala costumbre incluir literales de tipo numrico (nmeros mgicos) en medio del cdigo. Se prefiere la definicin de constantes simblicas (con #define o, mejor an, con enum).
for (i=0; i<79; i++) for (i=0; i<columnas-1; i++)

Estructuras de control - C

- 27 -

Expresiones
q

Expresiones booleanas: Es aconsejable escribirlas como se diran en voz alta.


if ( !(bloque<actual) ) if ( bloque >= actual )

Expresiones complejas: Es aconsejable dividirlas para mejorar su legibilidad


x += ( xp = ( 2*k<(n-m) ? c+k: d-k )); if ( 2*k < n-m ) xp = c+k; else xp = d-k; x += xp;

max = (a > b) ? a : b;

Comentarios
q

Comentarios descriptivos: Los comentarios deben comunicar algo. Jams se utilizarn para parafrasear el cdigo y repetir lo que es obvio.
i++; /* Incrementa el contador */

/* Recorrido secuencial de los datos*/ for (i=0; i<N; i++) ...

Estructuras de control - C

- 28 -

Estructuras de control
q

Sangras: Conviene utilizar espacios en blanco o separadores para delimitar el mbito de las estructuras de control de nuestros programas. Lneas en blanco: Para delimitar claramente los distintos bloques de cdigo en nuestros programas dejaremos lneas en blanco entre ellos. Salvo en la cabecera de los bucles for, slo incluiremos una sentencia por lnea de cdigo. Sean cuales sean las convenciones utilizadas al escribir cdigo (p.ej. uso de sangras y llaves), hay que ser consistente en su utilizacin. while () { } while () { } for (;;) { } if () { }

for (;;) { }

if () { }

El cdigo bien escrito es ms fcil de leer, entender y mantener (adems, seguramente tiene menos errores)

Estructuras de control - C

- 29 -

Metodologa de la programacin
Ciclo de vida del software Fases del ciclo de vida: Anlisis, diseo, implementacin... Programacin estructurada Cuestiones de estilo Identificadores Constantes Expresiones Declaraciones Estructuras de control Comentarios Convenciones

Bibliografa
Steve McConnell: Code Complete. Estados Unidos: Microsoft Press, 1994. ISBN 1-55615-484-4. Brian W. Kernighan & Rob Pike: La prctica de la programacin. Mxico: Pearson Educacin, 2000. ISBN 968-444-418-4. Francisco J. Cortijo, Juan Carlos Cubero & Olga Pons: Metodologa de la Programacin. Granada: Proyecto Sur, 1993. ISBN 84-604-7652-9. C Style Guide. NASA Software Engineering Laboratory, August 1994. SEL-94-003

Ciclo de vida del software


El ciclo de vida de una aplicacin comprende las siguientes etapas: Planificacin: mbito del proyecto, estudio de viabilidad, anlisis de riesgos, planificacin temporal, asignacin de recursos. Anlisis (qu?): elicitacin de requerimientos Diseo (cmo?): estudio de alternativas, diseo arquitectnico Implementacin: adquisicin, creacin e integracin de los recursos necesarios para que el sistema funcione. Pruebas: pruebas de unidad, pruebas de integracin, pruebas alfa, pruebas beta, test de aceptacin. Mantenimiento (correctivo y adaptativo)

Programacin estructurada
IDEA CENTRAL: Las estructuras de control de un programa slo deben tener un punto de entrada y un punto de salida. La programacin estructurada... mejora la productividad de los programadores. mejora la legibilidad del cdigo resultante. La ejecucin de un programa estructurado progresa disciplinadamente, en vez de saltar de un sitio a otro de forma impredecible

En programacin estructurada slo se emplean tres construcciones: Secuencia Conjunto de sentencias que se ejecutan en orden (asignaciones y llamadas a rutinas) Seleccin Estructura de control condicional (if-then-else, case/switch) Iteracin Estructura de control repetitiva (bucles: while, do...while, for)

Teorema de Bhm y Jacopini (1966) Cualquier programa de ordenador puede disearse e implementarse utilizando nicamente las tres construcciones estructuradas (secuencia, seleccin e iteracin; esto es, sin sentencias goto).

Bhm, C. & Jacopini, G.: Flow diagrams, Turing machines, and languages only with two formation rules. Communications of the ACM, 1966, Vol. 9, No. 5, pp. 366-371 Dijkstra, E.W.: Goto statement considered harmful. Communications of the ACM, 1968, Vol. 11, No. 3, pp. 147-148

Cuestiones de estilo
IDEA Escribimos cdigo para que lo puedan leer otras personas, no slo para que lo traduzca el compilador (si no fuese as, podramos seguir escribiendo nuestros programas en binario).

Identificadores
q

Seleccin de los identificadores: Los identificadores deben ser descriptivos (reflejar su significado). p, i, s... precio, izquierda, suma...

Uso de minsculas y maysculas: Generalmente, resulta ms cmodo leer texto en minsculas, por lo que usaremos siempre identificadores en minsculas, salvo: - para construir identificadores compuestos (p.ej. otraVariable) y - para definir constantes simblicas y macros (con #define). En ocasiones, se permite el uso de nombres cortos para variables locales cuyo significado es evidente (p.ej. bucles controlados por contador) for (elemento=0; elemento<N; elemento++) ... for (i=0; i<N; i++) ...

Constantes
q

Se considera una mala costumbre incluir literales de tipo numrico (nmeros mgicos) en medio del cdigo. Se prefiere la definicin de constantes simblicas (con #define o, mejor an, con enum). for (i=0; i<79; i++)... for (i=0; i<columnas-1; i++)...

Expresiones
q

Uso de parntesis: Aunque las normas de precedencia de los operadores estn definidas por el estndar de C, no abusaremos de ellas. Siempre resulta ms fcil interpretar una expresin si sta tiene los parntesis apropiados. Adems, stos eliminan cualquier tipo de ambigedad. Uso de espacios en blanco: Resulta ms fcil leer una expresin con espacios que separen los distintos operadores y operandos involucrados en la expresin. a%x*c/b-1 ( (a%x) * c ) / b - 1

Expresiones booleanas: Es aconsejable escribirlas como se diran en voz alta. if ( !(bloque<actual) ) ... if ( bloque >= actual ) ...

Expresiones complejas: Es aconsejable dividirlas para mejorar su legibilidad (p.ej. operador ?:). x += ( xp = ( 2*k < (n-m) ? c+k: d-k )); if ( 2*k < n-m ) xp = c+k; else xp = d-k; x += xp; max = (a > b) ? a : b;

Claridad: Siempre buscaremos la forma ms simple de escribir una expresin. key = key >> ( bits ((bits>>3)<<3)); key >>= bits & 0x7;

Conversiones de tipo (castings): Evitaremos las conversiones implcitas de tipo. Cuando queramos realizar una conversin de tipo, lo indicaremos explcitamente. i = (int) f;

Declaraciones
q

Usualmente, declararemos una nica variable por lnea. Nunca mezclaremos en una misma lnea la declaracin de variables que sean de distintos tipos o que se utilicen en el programa para distintos fines. int i, datos[100], v[3], ok;

Estructuras de control
q

Sangras: Conviene utilizar espacios en blanco o separadores para delimitar el mbito de las estructuras de control de nuestros programas. Lneas en blanco: Para delimitar claramente los distintos bloques de cdigo en nuestros programas dejaremos lneas en blanco entre ellos.

Comentarios
q

Comentarios descriptivos: Los comentarios deben comunicar algo. Nunca han de limitarse a decir en lenguaje natural lo que ya est escrito en el cdigo. Jams se utilizarn para parafrasear el cdigo y repetir lo que es obvio. i++; /* Incrementa el contador */

/* Recorrido secuencial de los datos */ for (i=0; i<N; i++) ...

int mes; /* Mes */ int mes; /* Mes del ao (1..12) */

Comentarios de prlogo: Al principio de cada mdulo han de incluirse comentarios que resuman la tarea que realiza el mdulo y su interfaz (parmetros...). // // // // // Clculo del MCD utilizando el algoritmo de Euclides Parmetros: Los nmeros a y b Resultado: Mximo comn divisor de a y b

Usualmente, tambin se incluyen comentarios que aclaren los algoritmos y tcnicas utilizados en la implementacin del programa. Al comienzo de cada fichero de cdigo, se suele incluir un comentario en el que aparece el autor del mdulo y una lista de las revisiones que ha sufrido a lo largo de su vida. // // // // // // // Revisor ortogrfico Fernando Berzal, 2003 Revisiones: v2.0 Nov03 Anlisis de sufijos v1.1 Oct03 Diccionario mejorado v1.0 Oct03 Versin inicial

No comente el cdigo malo (uso de construcciones extraas, expresiones confusas, sentencias poco legibles...): Reescrbalo. No contradiga al cdigo: Los comentarios suelen coincidir con el cdigo cuando se escriben, pero a medida que se corrigen errores y el programa evoluciona, los comentarios suelen dejarse en su forma original y aparecen discrepancias. Si cambia el cdigo, asegrese de que los comentarios sigan siendo correctos. Los comentarios han de aclarar; esto es, ayudar al lector en las partes difciles (y no confundirle). Si es posible, escriba cdigo fcil de entender por s mismo: cuanto mejor lo haga, menos comentarios necesitar.

ax = 0x723;

/* RIP L.v.B. */

NB: Beethoven muri en 1827 (0x723 en hexadecimal).

Convenciones
q

Siempre se han de evitar los efectos colaterales (modificaciones no deseadas que pueden afectar a la ejecucin del programa): #define MAX(a,b) (((a)>(b))?(a):(b)) ... k = MAX(i++,j++); scanf (%d %d, &pos, &v[pos]);

Salvo en la cabecera de los bucles for, slo incluiremos una sentencia por lnea de cdigo. Sean cuales sean las convenciones utilizadas al escribir cdigo (p.ej. uso de sangras y llaves), hay que ser consistente en su utilizacin.

while (...) { ... }

while (...) { ... } for (...) { ... } if (...) { ... }

for (...) { ... }

if (...) { ... }

El cdigo bien escrito es ms fcil de leer, entender y mantener (adems, seguramente tiene menos errores)

Estructuras de control
q

Sangras: Conviene utilizar espacios en blanco o separadores para delimitar el mbito de las estructuras de control de nuestros programas. Lneas en blanco: Para delimitar claramente los distintos bloques de cdigo en nuestros programas dejaremos lneas en blanco entre ellos. Salvo en la cabecera de los bucles for, slo incluiremos una sentencia por lnea de cdigo. Sean cuales sean las convenciones utilizadas al escribir cdigo (p.ej. uso de sangras y llaves), hay que ser consistente en su utilizacin. while () { } while () { } for (;;) { } if () { }

for (;;) { }

if () { }

El cdigo bien escrito es ms fcil de leer, entender y mantener (adems, seguramente tiene menos errores)

Estructuras de control - C

- 29 -

Fernando Berzal

Expresiones
q

Expresiones booleanas: Es aconsejable escribirlas como se diran en voz alta.


if ( !(bloque<actual) ) if ( bloque >= actual )

Expresiones complejas: Es aconsejable dividirlas para mejorar su legibilidad


x += ( xp = ( 2*k<(n-m) ? c+k: d-k )); if ( 2*k < n-m ) xp = c+k; else xp = d-k; x += xp;

max = (a > b) ? a : b;

Comentarios
q

Comentarios descriptivos: Los comentarios deben comunicar algo. Jams se utilizarn para parafrasear el cdigo y repetir lo que es obvio.
i++; /* Incrementa el contador */

/* Recorrido secuencial de los datos*/ for (i=0; i<N; i++) ...

Estructuras de control - C

- 28 -

Fernando Berzal

Cuestiones de estilo
Escribimos cdigo para que lo puedan leer otras personas, no slo para que lo traduzca el compilador.

Identificadores
q

Los identificadores deben ser descriptivos


p, i, s... precio, izquierda, suma...

En ocasiones, se permite el uso de nombres cortos para variables locales cuyo significado es evidente (p.ej. bucles controlados por contador)
for (elemento=0; elemento<N; elemento++ ) for (i=0; i<N; i++)

Constantes
q

Se considera una mala costumbre incluir literales de tipo numrico (nmeros mgicos) en medio del cdigo. Se prefiere la definicin de constantes simblicas (con #define o, mejor an, con enum).
for (i=0; i<79; i++) for (i=0; i<columnas-1; i++)

Estructuras de control - C

- 27 -

Modularizacin
Uso de subprogramas Razones vlidas para crear un subprograma Cohesin y acoplamiento Pasos para escribir un subprograma El nombre y los parmetros de un subprograma Tipos de datos abstractos (TDAs)

Bibliografa
Steve McConnell: Code Complete. Estados Unidos: Microsoft Press, 1994. ISBN 1-55615-484-4.

Uso de subprogramas
Razones vlidas para crear un subprograma
q q q q q q q

Reducir la complejidad del programa (divide y vencers). Eliminar cdigo duplicado. Limitar los efectos de los cambios (aislar aspectos concretos). Ocultar detalles de implementacin (p.ej. algoritmos complejos). Promover la reutilizacin de cdigo (p.ej. familias de productos). Mejorar la legibilidad del cdigo. Facilitar la portabilidad del cdigo.

Cohesin
Medida del grado de identificacin de un mdulo con una funcin concreta. Cohesin aceptable (fuerte)
q

Cohesin funcional (un mdulo realiza una nica accin). Cohesin secuencial (un mdulo contiene acciones que han de realizarse en un orden particular sobre unos datos concretos). Cohesin de comunicacin (un mdulo contiene un conjunto de operaciones que se realizan sobre los mismos datos). Cohesin temporal (las operaciones se incluyen en un mdulo porque han de realizarse al mismo tiempo; p.ej. inicializacin).

Cohesin inaceptable (dbil)


q

Cohesin procedural (un mdulo contiene operaciones que se realizan en un orden concreto aunque no tengan nada que ver entre s). Cohesin lgica (cuando un mdulo contiene operaciones cuya ejecucin depende de un parmetro: el flujo de control o lgica de la rutina es lo nico que une a las operaciones que la forman). Cohesin coincidental (cuando las operaciones de una rutina no guardan ninguna relacin observable entre ellas).

Acoplamiento
Medida de la interaccin de los mdulos que constituyen un programa. Niveles de acoplamiento (de mejor a peor):
q

Acoplamiento de datos (acoplamiento normal): Todo lo que comparten dos rutinas se especifica en la lista de parmetros de la rutina llamada. Acoplamiento de control: Una rutina pasa datos que le indican a la otra rutina qu hacer (la primera rutina tiene que conocer detalles internos de la segunda). Acoplamiento externo: Cuando dos rutinas utilizan los mismos datos globales o dispositivos de E/S. Si los datos son de slo lectura, el acoplamiento se puede considerar aceptable. En general, este tipo de acoplamiento no es deseable porque la conexin existente entre los mdulos no es visible.

Acoplamiento patolgico: Cuando una rutina utiliza el cdigo de otra o altera sus datos locales (acoplamiento de contenido). La mayor parte de los lenguajes estructurados incluyen reglas para el mbito de las variables que impiden este tipo de acoplamiento.

Objetivo Reducir al mximo el acoplamiento y aumentar la cohesin de los mdulos.

Pasos para escribir un subprograma


1. 2. 3. 4. 5. 6. 7. 8. 9. Definir el problema que el subprograma ha de resolver. Darle un nombre no ambiguo al subprograma. Decidir cmo se puede probar el funcionamiento del subprograma. Escribir la declaracin del subprograma (cabecera de la funcin). Buscar el algoritmo ms adecuado para resolver el problema. Escribir los pasos principales del algoritmo como comentarios. Rellenar el cdigo correspondiente a cada comentario. Revisar mentalmente cada fragmento de cdigo. Repetir los pasos anteriores hasta quedar completamente satisfecho.

El nombre de un subprograma q Procedimiento: Verbo seguido de un objeto. q Funcin: Descripcin del valor devuelto por la funcin. El nombre debe describir todo lo que hace el subprograma. Se deben evitar nombres genricos que no dicen nada (p.ej. calcular) Se debe ser consistente en el uso de convenciones. Los parmetros de un subprograma Orden: (por valor, por referencia) == (entrada, entrada/salida, salida) Si varias rutinas utilizan los mismos parmetros, stos han de ponerse en el mismo orden (algo que la biblioteca estndar de C no hace). De acuerdo con la primera norma, las variables de estado o error se ponen al final. No es aconsejable utilizar los parmetros de una rutina como si fuesen variables locales de la rutina. Se han de documentar las suposiciones que se hagan acerca de los posibles valores de los parmetros. Slo se deben incluir los parmetros que realmente necesite la rutina para efectuar su labor. Las dependencias existentes entre distintos mdulos han de hacerse explcitas mediante el uso de parmetros.

Tipos de datos abstractos TDAs


Los tipos definidos por el usuario son una de las capacidades ms importantes que ofrecen los lenguajes de programacin para clarificar el significado de un programa.
q

Se simplifican las modificaciones que tengamos que realizar. Se encapsulan detalles de implementacin (en vez de aparecer por todas partes, estos detalles slo aparecen en la declaracin del tipo). Se ampla el vocabulario que podemos utilizar en nuestro programas.

TDA Coleccin de datos y todas las operaciones que se efectan sobre esos datos Ejemplos: Una ventana, un men, un fichero, una lista, una tabla... PUNTO CLAVE: El acceso a los datos se realiza siempre a travs de las operaciones definidas en el propio TDA.

Beneficios de la utilizacin de TDAs q Se ocultan detalles de implementacin. q Se facilitan las modificaciones que puedan afectar al programa. q Es ms fcil mejorar la eficiencia del programa. q Es ms fcil verificar la correccin del programa. q La legibilidad de los programas mejora. q Se simplifican las interfaces de los mdulos del programa. q Se definen operaciones en funcin de los objetos sobre los que se efectan.

Recursividad
Una funcin que se llama a s misma se denomina recursiva

Utilidad
Cuando la solucin de un problema se puede expresar en trminos de la resolucin de un problema de la misma naturaleza, aunque de menor complejidad. Slo tenemos que conocer la solucin no recursiva para algn caso sencillo (denominado caso base) y hacer que la divisin de nuestro problema acabe recurriendo a los casos base que hayamos definido. Como en las demostraciones por induccin, podemos considerar que tenemos resuelto el problema ms simple para resolver el problema ms complejo (sin tener que definir la secuencia exacta de pasos necesarios para resolver el problema).

Funcionamiento
- Se descompone el problema en problemas de menor complejidad (algunos de ellos de la misma naturaleza que el problema original). - Se resuelve el problema para, al menos, un caso base. - Se compone la solucin final a partir de las soluciones parciales que se van obteniendo.

Diseo de algoritmos recursivos


1. Resolucin de problema para los casos base: o Sin emplear recursividad. o Siempre debe existir algn caso base.

2. Solucin para el caso general: o Expresin de forma recursiva. o Pueden incluirse pasos adicionales (para combinar las soluciones parciales).

Siempre se debe avanzar hacia un caso base: Las llamadas recursivas simplifican el problema y, en ltima instancia, los casos base nos sirven para obtener la solucin.

int factorial (int n) { int resultado; if (n==0) // Caso base resultado = 1; else // Caso general resultado = n*factorial(n-1); return (resultado); } int potencia (int base, int exp) { if (exp==0) // Caso base return 1; else // Caso general return base * potencia(base,exp-1); }

Recursividad vs. iteracin


Aspectos que hay que considerar al decidir cmo implementar la solucin a un problema (de forma iterativa o de forma recursiva): - La carga computacional (tiempo de CPU y espacio en memoria) asociada a las llamadas recursivas. - La redundancia (algunas soluciones recursivas resuelven un problema en repetidas ocasiones). - La complejidad de la solucin (en ocasiones, la solucin iterativa es muy difcil de encontrar). - La concisin, legibilidad y elegancia del cdigo resultante de la solucin recursiva del problema.

Ejemplo: Sucesin de Fibonacci

Solucin recursiva int fibonacci (int n) { if ((n == 0) || (n == 1)) return 1; else return fibonacci(n-1) + fibonacci(n-2); }

Solucin iterativa int fibonacci (int n) { int actual, ant1, ant2; ant1 = ant2 = 1; if ((n == 0) || (n == 1)) { actual = 1; } else for (i=2; i<=n; i++) { actual = ant1 + ant2; ant2 = ant1; ant1 = actual; } } return (actual); }

Clculo recursivo de fibonacci(5)

Ejemplo: Las torres de Hanoi

Mover n discos del poste 1 al poste 3 (utilizando el poste 2 como auxiliar): hanoi (n, 1, 2, 3);

Solucin recursiva: void hanoi (int n, int inic, int tmp, int final) { if (n > 0) { // Mover n-1 discos de "inic" a "tmp". // El temporal es "final". hanoi (n-1, inic, final, tmp); // Mover el que queda en "inic" a "final" printf (Del poste %d al %d.\n, inic, final); // Mover n-1 discos de "tmp" a "final". // El temporal es "inic". hanoi (n-1, tmp, inic, final); } }

Solucin para 3 discos

Segn la leyenda, los monjes de un templo tenan que mover una pila de 64 discos sagrados de un sitio a otro. Slo podan mover un disco al da y, en el templo, slo haba otro sitio en el que podan dejarlos, siempre ordenados de forma que los mayores quedasen en la base. El da en que los monjes realizasen el ltimo movimiento, el final del mundo habra llegado

Vectores y matrices
Declaracin
Vector (array unidimiensional): <tipo> <identificador> [<componentes>];
<tipo>

Tipo de dato de los elementos del vector


<identificador>

Identificador de la variable.
<componentes>

Nmero de elementos del vector. Puede ser un literal o una constante de tipo entero. Nunca ser una variable

Matriz (array bidimensional): <tipo> <identificador> [<filas>][<columnas>];

Acceso

- En C, el ndice de la primera componente de un vector es siempre 0. - El ndice de la ltima componente es <compontentes>-1 Vector <identificador> [<ndice>] Matriz <identificador>[<ndice1>][<ndice2>]

Inicializacin
En la declaracin, podemos asignarle un valor inicial a los elementos de un vector. int vector[3] = {4, 5, 6}; int matriz[2][3] = { {1,2,3}, {4,5,6} }; El compilador puede deducir las dimensiones del array: int vector[] = {1, 2, 3, 5, 7};

Manipulacin de vectores y matrices


Las operaciones se realizan componente a componente

No es necesario utilizar todos los elementos del vector, por lo que, en C, al trabajar con ellos, se suele utilizar una variable entera adicional que nos indique el nmero de datos utilizados. float media (float datos[], int N) { int i; float suma = 0; for (i=0; i<N; i++) suma = suma + datos[i]; return suma/N; } IMPORTANTE: Cuando se pasa un vector como parmetro, el paso de parmetros es por referencia (un vector es, en realidad, un puntero en C). Por tanto, tenemos que tener cuidado con los efectos colaterales que se producen si, dentro de un mdulo, modificamos un vector que recibimos como parmetro.

Algoritmos de ordenacin
Ordenacin por seleccin

void OrdenarSeleccion (double v[], int N) { int i, j, pos_min; double tmp; for (i=0; i<N-1; i++) { // Menor elemento del vector v[i..N-1] pos_min = i; for (j=i+1; j<N; j++) if (v[j]<v[pos_min]) pos_min = j; // Coloca el mnimo en v[i] tmp = v[i]; v[i] = v[pos_min]; v[pos_min] = tmp; = } }

En cada iteracin, se selecciona el menor elemento del subvector no ordenado y se intercambia con el primer elemento de este subvector.

Ordenacin por insercin

void OrdenarInsercion (double v[], int N) { int i, j; double tmp; for (i=1; i<N; i++) { tmp = v[i]; for (j=i; (j>0) && (tmp<v[j-1]); j--) v[j] = v[j-1]; v[j] = tmp; } }

En cada iteracin, se inserta un elemento del subvector no ordenado en la posicin correcta dentro del subvector ordenado.

Ordenacin por intercambio directo (mtodo de la burbuja)

void OrdenarBurbuja (double v[], int N) { int i, j; double tmp; for (i=1; i<N; i++) for (j=N-1; j>i; j--) if (v[j] < v[j-1]) { tmp = v[j]; v[j] = v[j-1]; v[j-1] = tmp; } } En cada iteracin Estado del vector tras cada iteracin:

Ordenacin rpida (QuickSort)

1. Se toma un elemento arbitrario del vector, al que denominaremos pivote (p).

2. Se divide el vector de tal forma que todos los elementos a la izquierda del pivote sean menores que l, mientras que los que quedan a la derecha son mayores que l.

3. Ordenamos, por separado, las dos zonas delimitadas por el pivote.

void quicksort (double v[], int izda, int dcha) { int pivote; // Posicin del pivote if (izda<dcha) { pivote = partir (v, izda, dcha); quicksort (v, izda, pivote-1); quicksort (v, pivote+1, dcha); } }

Obtencin del pivote

Mientras queden elementos mal colocados respecto al pivote: a. Se recorre el vector, de izquierda a derecha, hasta encontrar un elemento situado en una posicin i tal que v[i] > p. b. Se recorre el vector, de derecha a izquierda, hasta encontrar otro elemento situado en una posicin j tal que v[j] < p. c. Se intercambian los elementos situados en las casillas i y j (de modo que, ahora, v[i] < p < v[j]).

// Intercambio de dos valores void swap (double *a, double *b) { double tmp; tmp = *a; *a = *b; *b = tmp; }

// Divisin el vector en dos partes // - Devuelve la posicin del pivote int partir (double v[], int primero, int ultimo) { double pivote = v[primero]; // Valor del pivote int izda = primero+1; int dcha = ultimo; do { // Pivotear

while ((izda<=dcha) && (v[izda]<=pivote)) izda++; while ((izda<=dcha) && (v[dcha]>pivote)) dcha--; if (izda < dcha) { swap ( &(v[izda]), &(v[dcha]) ); dcha--; izda++; } } while (izda <= dcha); // Colocar el pivote en su sitio swap (&(v[primero]), &(v[dcha]) ); return dcha; // Posicin del pivote }

Algoritmos de bsqueda
Bsqueda lineal = Bsqueda secuencial
// Bsqueda lineal de un elemento en un vector // - Devuelve la posicin de dato en el vector // - Si dato no est en el vector, devuelve -1 int search (double vector[], int N, double dato) { int i; int pos = -1; for (i=0; i<N; i++) if (vector[i]==dato) pos = i; return pos; }

Versin mejorada // Bsqueda lineal de un elemento en un vector // - Devuelve la posicin de dato en el vector // - Si dato no est en el vector, devuelve -1 int search (double vector[], int N, double dato) { int i; int pos = -1; for (i=0; (i<N) && (pos==-1); i++) if (vector[i]==dato) pos = i; return pos; }

Bsqueda binaria
Precondicin El vector ha de estar ordenado Algoritmo Se compara el dato buscado con el elemento en el centro del vector: - Si coinciden, hemos encontrado el dato buscado. - Si el dato es mayor que el elemento central del vector, tenemos que buscar el dato en segunda mitad del vector. - Si el dato es menor que el elemento central del vector, tenemos que buscar el dato en la primera mitad del vector.

// Bsqueda binaria de un elemento en un vector // - Devuelve la posicin de dato en el vector // - Si dato no est en el vector, devuelve -1 // Implementacin recursiva // Uso: binSearch (vector, 0, N-1, dato) int binSearch ( double vector[], int izq, int der, double buscado) { int centro = (izq+der)/2; if (izq>der) return -1; else if (buscado==vector[centro]) return centro; else if (buscado<vector[centro]) return binSearch(vector, izq, centro-1, buscado); else return binSearch(vector, centro+1, der, buscado); } // Implementacin iterativa // Uso: binSearch (vector, N, dato) int binSearch (double vector[], int N, double buscado) { int izq = 0; int der = N-1; int centro = (izq+der)/2; while ((izq<=der) && (vector[centro]!=buscado)) { if (buscado<vector[centro]) der = centro 1; else izq = centro + 1; centro = (izq+der)/2; } if (izq>der) return -1; else return centro; }

Punteros
Definicin
Un puntero es un dato que contiene una direccin de memoria.

NOTA:

Existe una direccin especial que se representa por medio de la constante NULL (definida en <stdlib.h>) y se emplea cuando queremos indicar que un puntero no apunta a ninguna direccin.

Declaracin
<tipo> *<identificador>
<tipo>

Tipo de dato del objeto referenciado por el puntero


<identificador>

Identificador de la variable de tipo puntero.

Cuando se declara un puntero se reserva memoria para albergar una direccin de memoria, pero NO PARA ALMACENAR EL DATO AL QUE APUNTA EL PUNTERO. El espacio de memoria reservado para almacenar un puntero es el mismo independientemente del tipo de dato al que apunte: el espacio que ocupa una direccin de memoria.

char c = a; char *ptrc; int *ptri;

Operaciones bsicas con punteros

Direccin Operador & &<id> devuelve la direccin de memoria donde comienza la variable <id>. El operador & se utiliza para asignar valores a datos de tipo puntero:

int i; int *ptr; ... ptr = &i;

Indireccin Operador * *<ptr> devuelve el contenido del objeto referenciado por el puntero <ptr>. El operador * se usa para acceder a los objetos a los que apunta un puntero:

char c; char *ptr; ptr = &c; *ptr = A;

// Equivale a escribir: c = A

Asignacin Operador =

A un puntero se le puede asignar una direccin de memoria concreta, la direccin de una variable o el contenido de otro puntero.

Una direccin de memoria concreta: int *ptr; ... ptr = 0x1F3CE00A; ... ptr = NULL;

La direccin de una variable del tipo al que apunta el puntero: char c; char *ptr; ... ptr = &c;

Otro puntero del mismo tipo: char char char ptr1 ptr2 c; *ptr1; *ptr2; = &c; = ptr1;

Como todas las variables, los punteros tambin contienen basura cuando se declaran, por lo que es una buena costumbre inicializarlos con NULL.

Ejemplo
int main () { int y = 5; int z = 3; int *nptr; int *mptr;

nptr = &y;

z = *nptr;

*nptr = 7;

mptr = nptr;

mptr = *z;

*mptr = *nptr;

y = (*nptr) + 1; return 0; }

Errores comunes
Asignar punteros de distinto tipo int a = 10; int *ptri = NULL; double x = 5.0; double *ptrf = NULL; ... ptri = &a; ptrf = &x; ptrf = ptri; // ERROR

Utilizar punteros no inicializados char *ptr; *ptr = a; // ERROR

Asignar valores a un puntero y no a la variable a la que apunta int n; int *ptr = &n; ptr = 9; // ERROR

Intentar asignarle un valor al dato apuntado por un puntero cuando ste es NULL int *ptr = NULL; *ptr = 9; // ERROR

Punteros a punteros
Un puntero a puntero es un puntero que contiene la direccin de memoria de otro puntero-

int main () { int a = 5; int *p; // Puntero a entero int **q; // Puntero a puntero

p = &a;

q = &p; }

Para acceder al valor de la variable a podemos escribir a *p (forma habitual) (a travs del puntero p)

**q (a travs del puntero a puntero q) q contiene la direccin de p, que contiene la direccin de a

Aritmtica de punteros Correspondencia entre punteros y vectores


Cuando declaramos un vector <tipo> <identificador> [<dim>] en realidad 1. Reservamos memoria para almacenar <dim> elementos de tipo <tipo>. 2. Creamos un puntero <identificador> que apunta a la primera posicin de la memoria reservada para almacenar los componentes del vector. Por tanto, el identificador del vector es un puntero. int v[3]; int *ptr; ... ptr = v; // Equivale a ptr = &v[0] v[0] = 6; // *v = 6; *(&v[0]) = 6;

Aritmtica de punteros <tipo> *ptr; ptr + <desplazamiento> devuelve un puntero a la posicin de memoria sizeof(<tipo>)*<desplazamiento> bytes por encima de ptr. int v[]; int *ptr = v;

ptr+i apunta a v[i] *(ptr+i) v[i]

NOTA: La suma de punteros no tiene sentido y no est permitida. La resta slo tiene sentido cuando ambos apuntan al mismo vector y nos da la distancia entre las posiciones del vector (en nmero de elementos).

Ejemplo: Distintas formas de sumar los elementos de un vector int suma ( int v[], int N) { int i, suma; int *ptr, *ptrfin; /* Alternativa 1 */ suma = 0; for (i=0 ; i<N ; i++) suma = suma + v[i]; /* Alternativa 2 */ suma = 0; for (i=0 ; i<N ; i++) suma = suma + (*(v+i)); /* Alternativa 3 */ suma = 0; ptrfin = ptr + N-1; for (ptr=v ; ptr<=ptrfin ; ptr++) suma = suma + *ptr; return suma; } Punteros y matrices <tipo> mat [<dimF>][<dimC>];

direccin(i,j) = direccin(0,0) + i*dimC + j

Ejemplo: Intercambio de valores

void Cambia(int *a, int *b) { int aux; aux = *a; *a = *b; *b = aux; } int main() { int x=0, y=1; Cambia(&x,&y); return 0; }

Gestin dinmica de la memoria


Organizacin de la memoria

Segmento de cdigo (cdigo del programa). Memoria esttica (variables globales y estticas). Pila (stack): Variables automticas (locales). Heap (montn): Variables dinmicas.

Reserva y liberacin de memoria Cuando se quiere utilizar el heap, primero hay que reservar la memoria que se desea ocupar: ANSI C: Funcin malloc C++: Operador new Al reservar memoria, puede que no quede espacio libre suficiente, por lo que hemos de comprobar que no se haya producido un fallo de memoria (esto es, ver si la direccin de memoria devuelta es distinta de NULL). Tras utilizar la memoria reservada dinmicamente, hay que liberar el espacio reservado: ANSI C: Funcin free C++: Operadore delete Si se nos olvida liberar la memoria, ese espacio de memoria nunca lo podremos volver a utilizar

Ejemplo: Vector de tamao dinmico


#include <stdio.h> #include <stdlib.h> float media (float v[], int n) { int i; float suma = 0; for (i=0; i<n; i++) suma += v[i]; return suma/n; }

int main(int argc, char *argv[]) { int i; int n; float *v; printf("Nmero de elementos del vector: "); scanf("%d",&n); // Creacin del vector v = malloc(n*sizeof(float)); // Manejo del vector for (i=0; i<n; i++) v[i] = i; printf("Media = %f\n", media(v,n)); // Liberacin de memoria free(v); return 0; }

Ejemplo: TDA Vector Dinmico


Tipo de los elementos del vector dinmico typedef int Dato; Estructura de datos del vector typedef struct Vector { Dato *datos; int usado; int capacidad; };

// Vector de datos // Elementos usados del vector // Capacidad del vector

typedef struct Vector *Vector;

Creacin del vector (constructor) Vector crearVector (void) { Vector v =(Vector) malloc ( sizeof(struct Vector) ); v->usado = 0; v->capacidad = 2; v->datos = malloc ( (v->capacidad)*sizeof(Dato) ); return vector; } Destruccin del vector (destructor) void destruirVector (Vector *v) { free ( (*v)->datos ); free ( *v ); *v = NULL; } Constructor y destructor nos permiten manejar vectores sin tener que conocer su estructura de datos interna (ni siquiera tendremos que utilizar malloc y free).

Acceso al contenido del vector Funciones que permiten ocultar los detalles de implementacin del TDA

Nmero de elementos del vector:

int elementosVector (Vector v) { return v->usado; }

Acceso a los elementos concretos del vector:

Obtencin del valor almacenado en una posicin del vector:

Dato obtenerDato (Vector v, int pos) { if ((pos>=0) && (pos<elementosVector(v))) return v->datos[pos]; else return NULL; }

Modificacin del valor almacenado en una posicin del vector:

void guardarDato (Vector v, int pos, Dato dato) { if ((pos>=0) && (pos<elementosVector(v))) { v->datos[pos] = dato; } }

Insercin de datos void agregarDato (Vector v, Dato dato) { int i; Dato *datos; if (v->usado == v->capacidad) { // Redimensionar el vector v->capacidad *= 2; datos = malloc ( (v->capacidad)*sizeof(Dato) ); for (i=0; i < v->usado; i++) datos[i] = v->datos[i]; free(v->datos); v->datos = datos; } v->datos[v->usado] = dato; v->usado ++; } Eliminacin de datos void eliminarDato (Vector v, int pos) { int i; if ((pos>=0) && (pos<elementosVector(v))) { for (i=pos; i<elementosVector(v)-1; i++) v->datos[i] = v->datos[i+1]; v->usado --; } }

OJO!

En la implementacin mostrada no contemplamos la posibilidad de que la funcin malloc devuelva NULL (algo que siempre deberemos hacer al programar).

Ejemplo de uso del TDA Vector Dinmico

#include <stdio.h> #include vector.h /* Rutina auxiliar */ void mostrarVector (Vector v) { int i; printf( "Vector de tamao %d:\n", elementosVector(v) ); for (i=0; i<elementosVector(v); i++) printf("- %d\n", obtenerDato(v,i)); }

/* Programa principal */ int main () { Vector v = crearVector(); mostrarVector (v); agregarDato (v,1); agregarDato (v,2); agregarDato (v,3); mostrarVector (v); eliminarDato (v,1); mostrarVector (v); guardarDato (v, 0, obtenerDato(v,0)+2); mostrarVector (v); destruirVector(&v); return 0; }

Operaciones de E/S en ANSI C


Las operaciones de entrada/salida estndar (realizadas habitualmente con printf y scanf) se realizan en realidad sobre ficheros que representan los dispositivos mediante los cuales el usuario interacciona con el ordenador. La biblioteca estndar stdio (incluida en el ANSI C) nos permite manipular ficheros desde nuestros programas en C, para lo cual hemos de incluir la siguiente directiva al comienzo de nuestros ficheros de cdigo (para evitar que el compilador encuentre tipos y funciones no definidas):

#include <stdio.h>

E/S de caracteres
Al nivel ms bajo, las operaciones de entrada/salida se realizan con bytes, si bien resulta engorroso tener que programar a este nivel: getchar La funcin getchar devuelve el siguiente carcter ledo desde el teclado. putchar Muestra un carcter a travs del dispositivo de salida estndar (la pantalla, generalmente).

NOTA: La mayora de los sistemas operativos utilizan buffers para gestionar las operaciones de entrada/salida, por lo que no se leer un carcter hasta que el usuario introduzca un retorno de carro y, posiblemente, no se mostrar nada por pantalla hasta que se tenga una lnea completa por mostrar.

Ejemplo: Contar el nmero de caracteres de un fichero

#include <stdio.h> int main () { int c = 0; while (getchar() != EOF) c ++; printf("%d\n", c); return 0; }

Ejemplo: Poner un texto en maysculas

#include <ctype.h> #include <stdio.h> int main () { int ch;

/* Definicin de toupper */ /* getchar, putchar, EOF */

while ((ch = getchar()) != EOF) putchar(toupper(ch)); return 0; }

NOTA: Para indicar el final de un fichero cuando se estn introduciendo los datos desde el teclado hay que escribir CONTROL+Z en Windows (CONTROL+D en UNIX/Linux).

E/S con formato


La biblioteca estndar de C incluye dos funciones que nos facilitan un control preciso sobre las operaciones de entrada y salida: printf Nos permite especificar el formato en que queremos mostrar datos por pantalla Parmetros: Cadena de formato (cmo se visualizan los datos) Lista de valores (datos que se visualizan)

scanf Permite leer datos con formato desde el teclado. Parmetros: Cadena de formato (cmo se introducen los datos) Lista de punteros (dnde se almacenan los datos)

Cadena de formato %[flag][ancho][.prec][modificador][tipo] Tipo: %c %s %d %x %f Carcter (char) Cadena de caracteres (string) Nmero entero (decimal) Nmero entero (en hexadecimal) Nmero real (float)

Modificador:

%ld Nmero entero (long int) %lf Nmero real (double) %Lf Nmero real (long double)

[ancho] indica el nmero mnimo de caracteres que se utilizarn para visualizar el dato (el espacio sobrante se rellena con espacios o con ceros). [.prec] indica el nmero mximo de dgitos/caracteres que se mostrarn. Las cadenas de caracteres se truncan, los nmeros reales se redondean utilizando prec decimales. [flag]: Por defecto, los datos se justifican a la derecha. Poniendo -, los datos se justifican a la izquierda. Con + se indica que siempre queremos visualizar el signo de un nmero (+ -).

E/S de lneas
Si no estamos interesados en el formato de nuestros datos (o, simplemente, no podemos predecir su formato de antemano), podemos leer y escribir lneas completas de caracteres con otras dos funciones estndar: gets (cadena) Lee una lnea completa (hasta que se alcanza un retorno de carro [\n] o el final del fichero [EOF]). NOTAS: - gets devuelve NULL cuando se llega al final de la entrada. - gets no comprueba la longitud de la cadena de entrada, por lo que siempre utilizaremos la funcin fgets, que s lo hace. puts (cadena) Escribe una lnea de texto y le aade un retorno de carro al final.

Ejemplo: Doble espaciado #include <stdio.h> int main () { char line[256]; /* Suficientemente grande? */

while ( gets(line) != NULL) { puts(line); printf("\n"); } return 0; } NOTA: Se pueden mezclar libremente las operaciones de E/S con formato, E/S de caracteres y E/S de lneas.

Redireccin de ficheros en Windows y UNIX


La biblioteca estndar de E/S incluye variantes de las funciones de E/S ya vistas para trabajar con ficheros, si bien podemos utilizar las funciones de E/S estndar para trabajar con ficheros si utilizamos redireccionamientos. Los sistemas operativos ms comunes permiten utilizar un fichero como entrada estndar a un programa (en vez de tener que teclear los datos a mano) y almacenar la salida estndar en un fichero de texto. Esto se puede conseguir fcilmente desde la lnea de comandos del sistema operativo:

programa <entrada.txt ejecuta el programa leyendo los datos del fichero de texto entrada.txt

programa >salida.txt ejecuta el programa y guarda los resultados en el fichero salida.txt

programa <entrada.txt >salida.txt lee los datos de entrada.txt y guarda los resultados en salida.txt

La redireccin resulta fcil de utilizar y nos permite que un nico programa funcione leyendo datos desde el teclado o desde un fichero:

Podemos escribir los programas para que lean los datos desde el teclado y muestren los resultados por pantalla. Despus los utilizaremos con datos almacenados en ficheros (y guardar en ficheros los resultados que obtengamos).

Algunos programas necesitan acceder a distintos ficheros, para lo cual recurriremos a las funciones de manipulacin de ficheros definidas en la biblioteca estndar de C

Manipulacin de ficheros en C
La biblioteca <stdio.h> incluye un tipo de dato que nos permitir manipular ficheros mediante punteros: el tipo FILE *

Para utilizar un fichero, hemos de declararlo como una variable ms: FILE *fichero;

Antes de poder acceder a l, hay que abrir el fichero. La funcin fopen devuelve el puntero a travs del cual accederemos al fichero: fichero = fopen(salida.txt, w) Si, por cualquier motivo, el fichero no puede abrirse, la funcin fopen devuelve NULL, por lo que siempre deberemos comprobar el resultado de llamar a la funcin fopen: if (fichero == NULL) fprintf (stderr, No se pudo acceder al fichero\n);

Siempre que se abre un fichero, hay que cerrarlo despus de usarlo: fclose (fichero); Suele existir un lmite sobre el nmero de ficheros que pueden estar abiertos simultneamente, por lo que es conveniente cerrar el fichero justo despus de utilizarlo si no se va a volver a acceder a l.

Existen tres ficheros predefinidos en la biblioteca estndar de C: stdin (entrada estndar: el teclado o un fichero redirigido). stdout (salida estndar: la pantalla o un fichero al que se enva la salida). stderr (salida estndar para mensajes de error: la pantalla).

fopen Abre un fichero Parmetros: Nombre del fichero Modo de acceso r Lectura w Escritura (crear un fichero nuevo) a Escritura (aadir al final del fichero)

fclose Cierra un fichero Parmetro: Puntero al fichero (que debe estar abierto).

Operaciones de E/S con ficheros Existen funciones para trabajar con ficheros que son anlogas a las funciones de entrada/salida estndar (slo tenemos que indicar el fichero sobre el cual deseamos realizar la operacin correspondiente):

equivale a putc(c,stdout) getc(stdin) fprintf(stdout,) fscanf(stdin,) fputs(cadena,stdout) fgets(cadena,longitud,stdin) putchar(c) getchar() printf() scanf() puts(cadena) gets(cadena)

Operaciones con cadenas de caracteres


sprintf/scanf La biblioteca de E/S estndar incluye dos funciones anlogas a printf/scanf que nos permiten trabajar directamente sobre cadenas de caracteres: sprintf almacena datos con formato en una cadena de caracteres (que debe ser lo suficientemente grande como para albergar los datos con formato). sscanf toma los datos de una cadena y los almacena en las variables especificadas de acuerdo con la cadena de formato que indiquemos (p.ej. para convertir una cadena en un valor numrico). string.h El estndar ANSI C incluye otra biblioteca que incluye varias funciones para facilitarnos la manipulacin de cadenas de caracteres (algo muy habitual cuando trabajamos con ficheros):

#include <string.h>

Entre las funciones ms utilizadas de esta biblioteca se encuentran las siguientes: strcpy(dest,src) copia la cadena src en dest, si bien tiene el mismo defecto que la funcin gets. strncpy(dest,n,src) copia la cadena src en dest, si bien tiene en cuenta el tamao de dest. El parmetro n debe ser igual al tamao del vector dest menos 1 (si queremos dejar espacio para el \0 final). strcmp(cad1,cad2) compara las cadenas cad1 y cad2. Devuelve 0 si las cadenas son iguales. strlen(cadena) devuelve la longitud de la cadena (el nmero de caracteres que hay hasta que nos encontramos un \0).