Programación en C

67
Programación en C Prólogo El avance de l a tecnología y la concurrente entrega de información, nos permite generar una edición, variable y alter nativa en la enseñanza del lenguaje de programación que más impacto social ha tenido en la historia de la informática. Este libro ha sido forjado con la incansable ayuda de informáticos de habla hispana, quienes byte a byte han colaborado por hacer de la información una fuente de conocimiento global. De la misma forma, continúa hoy siendo modificado en una constante búsqueda de superación de la calidad. Esta obra está llamada a ser la piedra angular en la enseñanza de la programación, logrando abarcar todos los aspectos del lenguaje en diversos niveles y de esta forma ser tanto una referencia técnica para qui enes ya dominan el lenguaje como una intr oducción sencilla para quienes están empezando a conocerlo. Viajaremos por la historia del lenguaje, veremos su propósito e indagaremos en la ciencia de la programación. El fin es otorgar al lector una doctrina clara de la programación y el lenguaje C; lo induciremos a conseguir un manejo importante del lenguaje. ¿Para quién es este libro? Este libro está dirigido a todos los que deseen obtener conocimientos de programación, pues el objetivo explícito que nos ha motivado a crearlo es difundir la importancia del lenguaje C en el mundo de la informática. Si nos enfocamos a un grupo social específico, podremos indicar que este libro contribuirá con los estudiantes de carreras del área informática, debido a que los temas convenidos, son parte d e su plan de estudios. ¿Por qué otro manual de C? Porque el lenguaje C es la base fundamental de la programación. Para quienes están en el ambiente de la informática es crucial tener por lo menos nociones de este lenguaje. Varios sistemas operativos, cientos de bibliotecas, y miles de programas están construidos utilizando C, al conocerlo es posible entender, colaborar y desarrollar en este lenguaje. Los sistemas, programas, juegos y herramientas que nosotros disfrutamos hoy fueron construidos por personas como nosotros, que empezaron con nuestro mismo potencial y fueron aprendiendo a hacer cosas fantásticas con las herramientas que tenían a mano. Una razón importante para otro libro de lenguaje C es también que los libros existentes muestran muy poca documentación de calidad. En Internet existe una cantidad inmensa de información publicada pero está dispersa, y mal manejada en algunos sitios. Es la intención de este libro crear un buen compendio de información, que permita a los interesados aprender a programar en C. Enlaces Nociones básicas de programación (generales, independientes del lenguaje):  Fundamentos de programación Wikilibro similar a éste en inglés  C Programming esquema de operadores y expresiones

Transcript of Programación en C

  • Programacin en C

    Prlogo El avance de la tecnologa y la concurrente entrega de informacin, nos permite generar una edicin, variable y alternativa en la enseanza del lenguaje de programacin que ms impacto social ha tenido en la historia de la informtica. Este libro ha sido forjado con la incansable ayuda de informticos de habla hispana, quienes byte a byte han colaborado por hacer de la informacin una fuente de conocimiento global. De la misma forma, contina hoy siendo modificado en una constante bsqueda de superacin de la calidad.

    Esta obra est llamada a ser la piedra angular en la enseanza de la programacin, logrando abarcar todos los aspectos del lenguaje en diversos niveles y de esta forma ser tanto una referencia tcnica para quienes ya dominan el lenguaje como una introduccin sencilla para quienes estn empezando a conocerlo.

    Viajaremos por la historia del lenguaje, veremos su propsito e indagaremos en la ciencia de la programacin. El fin es otorgar al lector una doctrina clara de la programacin y el lenguaje C; lo induciremos a conseguir un manejo importante del lenguaje.

    Para quin es este libro? Este libro est dirigido a todos los que deseen obtener conocimientos de programacin, pues el objetivo explcito que nos ha motivado a crearlo es difundir la importancia del lenguaje C en el mundo de la informtica. Si nos enfocamos a un grupo social especfico, podremos indicar que este libro contribuir con los estudiantes de carreras del rea informtica, debido a que los temas convenidos, son parte de su plan de estudios.

    Por qu otro manual de C? Porque el lenguaje C es la base fundamental de la programacin. Para quienes estn en el ambiente de la informtica es crucial tener por lo menos nociones de este lenguaje. Varios sistemas operativos, cientos de bibliotecas, y miles de programas estn construidos utilizando C, al conocerlo es posible entender, colaborar y desarrollar en este lenguaje.

    Los sistemas, programas, juegos y herramientas que nosotros disfrutamos hoy fueron construidos por personas como nosotros, que empezaron con nuestro mismo potencial y fueron aprendiendo a hacer cosas fantsticas con las herramientas que tenan a mano.

    Una razn importante para otro libro de lenguaje C es tambin que los libros existentes muestran muy poca documentacin de calidad. En Internet existe una cantidad inmensa de informacin publicada pero est dispersa, y mal manejada en algunos sitios. Es la intencin de este libro crear un buen compendio de informacin, que permita a los interesados aprender a programar en C.

    Enlaces Nociones bsicas de programacin (generales, independientes del lenguaje):

    Fundamentos de programacin

    Wikilibro similar a ste en ingls

    C Programming

    esquema de operadores y expresiones

  • [1]

    Licencia y autores

    Copyright 2004 Envite

    Copyright 2005 Alejandro Moreno Calvo

    Copyright 2006 Andreu Correa Casablanca

    Copyright 2009 zerohours

    Ver el historial de cada pgina para el resto de autores.

    Cmo contribuir a este WikiLibro? Contribuir con este libro es muy simple primero deberas registrarte un usuario y/o entrar (esto no es necesario pero si muy conveniente) a Wikilibros, para que podamos identificar tus ediciones. Luego, si nunca has contribuido en un proyecto de wikipedia o en otro wiki deberas leer el manual de uso de wikilibros.

    Una vez hecho esto todo lo que tienes que hacer es agregar el contenido que consideres necesario para el libro. Para editar cualquier seccin basta con hacer click al link que dice editaren la pestaa en la parte superior de la pagina, seria bueno revisar (antes de editar cualquier cosa) la pestaa de discusin que est ah para ser usada. Ten en cuenta que el material que ya est fue escrito por personas que deseaban contribuir igual que t, as que trata de respetarlo. Aunque con esto no me refiero a que si se necesita alguna correccin, reorganizacin, quitar partes que sean ambiguas, no dejes de hacerlo. Lo mejor sera que todos contribuyramos de cualquier manera al libro.

    Adems, es recomendable consultar la pgina de discusin del libro y la del articulo en particular que quieras modificar, ya que de esta manera se pueden coordinar esfuerzos.

    Recuerda que todo el contenido que aadas al libro es publicado bajo la licencia GFDL, por lo que no uses material que no haya sido escrito por ti o que no est ya publicado bajo GFDL. Recientemente wikimedia decidi adoptar la Licencia Creative Commons Compartir-Igual 3.0 para todos los aportes, por lo que actualmente el libro tiene una licencia dual.

    Introduccin

    Objetivos El objetivo principal de este Wikilibro es que cualquier persona sin conocimientos previos de programacin pueda ser capaz de programar en el lenguaje C.

    Una vez logrado el dominio del lenguaje, es probable que los lectores se interesen por otros temas ms complejos que superen a los temas bsicos. Tambin les ser ms o menos sencillo aprender cualquier otro lenguaje de programacin estructurada.

    Sin embargo, este no es un libro que apunte nicamente a programadores principiantes. Tambin puede resultar de inters para quienes ya tengan experiencia en el rea de programacin. En esta introduccin hay dos secciones en las que se explica para los dos grupos principales de lectores qu camino seguir para comenzar a programar en el lenguaje C o bien perfeccionar conocimientos.

    El lenguaje C es tan usado porque es un lenguaje de programacin que emplea pocas instrucciones en lenguaje mquina para traducir elementos del cdigo. Esto reduce los tiempos de ejecucin de los programas.

    Nota sobre la exactitud

  • Muchas de las cosas expresadas en este wikilibro, especialmente en los primeros captulos, no son completamente exactas, aunque son buenas aproximaciones. Los detalles ms exactos irn apareciendo posteriormente, una vez que los materiales anteriores hayan sido correctamente asimilados por el lector. En general, dadas dos definiciones o datos contradictorios en este wikilibro, debe considerarse siempre como ms exacto al segundo, habiendo aparecido el primero como una introduccin ms general al tema.

    Estndar utilizado El lenguaje C fue creado en los aos setenta, y a lo largo de su historia ha pasado por muchas modificaciones, tanto con respecto a la sintaxis como con respecto al cdigo incluido dentro de la biblioteca estndar. Es por ello que se fueron desarrollando estndares, para que todos sepan con qu versin del lenguaje se est trabajando.

    Los distintos estndares del lenguaje C han sido: el C de Kernighan y Ritchie, un estndar no-oficial que surgi luego de la publicacin de su libro en 1978; el C89 o C90, el primer estndar oficial, posterior a la publicacin de los estndares ANSI en 1989 e ISO en 1990; y el C99, publicado en 1999.

    En este libro se utilizar el estndar C99, si bien por cuestiones de estilo y compatibilidad muchas veces se utilizar cdigo compatible con el estndar C89.

    Para los principiantes Para quien no haya programado antes, es recomendable seguir el orden del libro. Los temas estn especialmente organizados de manera incremental o acumulativa. Tal vez, lo que se te va a hacer ms til en el camino del aprendizaje es la constancia; s terco, no trastabilles, no te rindas, tal vez tu pregunta sea cuntas veces tengo que intentar?, las veces necesarias para lograr tu objetivo, sera la respuesta.

    Claro que el principal enemigo de nosotros los humanos es el tiempo y por eso en caso de que de verdad ests trancado en algo busca ayuda de alguien que sepa "ms que t". Que no tienes a nadie a tu alrededor con esa caracterstica? Tal vez no buscaste bien y tal vez quieras usar la red de redes. Utiliza los buscadores, pregunta en IRC, en foros de programacin, en listas de correo.

    Para los ms avanzados El lanzamiento queda libre por supuesto, solo t sabes lo que necesitas. Las reglas del juego son las mismas de siempre: primero saber lo que se quiere o necesita y atacar por ah.

    En este caso, te ser til acceder a los contenidos a partir del ndice, eligiendo slo aquellos que te sean necesarios.

    Requisitos Se presupone que los lectores tienen conocimientos elementales de informtica a nivel de usuario, y son capaces de instalar un compilador del lenguaje C en sus sistema. Los detalles sobre la instalacin se vern en la seccin Herramientas.

    Con respecto al Hardware, slo ser necesario contar con una PC con sistema operativo, donde sea posible instalar un compilador, y en lo posible un entorno de desarrollo. Cuanto mejor sea la computadora, ms rpido ser el proceso de compilacin y ejecucin de los programas. Sin embargo, cualquier PC sirve para aprender con los ejemplos de este libro.

    Para quienes no tengan conocimientos bsicos de programacin, puede ser una buena idea comenzar leyendo los primeros captulos del Wikilibro Fundamentos de programacin, ya que algunos temas explicados en ese libro se asumen ya conocidos.

  • Finalmente, un requisito imprescindible en todo programador o programadora es tener sentido comn. Muchas veces se pueden adoptar mejores o peores soluciones ante los diversos problemas, y la decisin de cul elegir pasa por la aplicacin del sentido comn. yapa

    Herramientas Para programar tanto en C, como en C++, Java o cualquier otro lenguaje de programacin, necesitamos contar con aplicaciones o herramientas que nos permitan poner en funcionamiento nuestro programa.

    El lenguaje de programacin C es compilado, as que en este caso necesitaremos un compilador, que ser el encargado de transformar nuestro cdigo fuente en cdigo que la computadora pueda ejecutar.

    Adems, para facilitar la tarea de los programadores existen los denominados Entorno de desarrollo integrados (IDE). En muchos casos, estos entornos incluyen un compilador, un depurador, y otras herramientas.

    Las herramientas a instalar dependern del sistema operativo utilizado. A continuacin se listan algunas posibilidades para el sistema operativo Windows o GNU/Linux, no es imprescindible utilizar estas herramientas en particular, cualquier compilador puede servir.

    Windows Uno de los entornos de desarrollo ms conocidos entre los programadores de C sobre Windows, tanto novatos como expertos, es el Bloodshed Dev-C++, que es un entorno libre multiplataforma. Tal entorno de desarrollo fue abandonado y retomado mejorndolo pasando a llamarse WxDev-C++. Otro entorno libre y gratuito es el Code::Blocks. Ambos entornos pueden utilizarse tanto para C como para C++.

    Tambin hay otras alternativas privativas como los compiladores de Borland o de Microsoft (Microsoft Visual C++).

    GNU/Linux En los sistemas GNU/Linux, ser necesario tener instaladas las herramientas gcc y make y la versin 6 de la glibc con su documentacin, que son las que permitirn compilar los programas.

    Para escribir y modificar el cdigo, es posible utilizar cualquier editor de texto plano (en lo posible que cuente con resaltado de sintaxis), como son emacs, vim, kate, gedit o geany.

    Sin embargo, para quienes son novatos en la programacin, es recomendable utilizar un entorno de desarrollo como son el Anjuta DevStudio (para el entorno GNOME) o KDevelop (para el entorno KDE), ya que incluyen facilidades adicionales para la ejecucin y solucin de problemas.

    Los programas mencionados se incluyen dentro de la instalacin estndar de la mayora de las distribuciones actuales de GNU/Linux, de modo que para instalarlos slo ser necesario seguir el procedimiento usual de instalacin de aplicaciones para la distribucin deseada.

    Historia de C El lenguaje de programacin C fue creado por Dennis Ritchie entre 1969 y 1973 cuando trabajaba en Bell Laboratories de AT&T junto con Ken Thompson en el diseo del sistema operativo UNIX. C fue creado para poder escribir dicho sistema operativo en un lenguaje de alto nivel, independiente del hardware donde se ejecutara.

  • Contar con un lenguaje de alto nivel permiti el avance de los sistemas operativos, ya que el mismo cdigo poda ser utilizado en las distintas plataformas, propiciando la reutilizacin de cdigo y reduciendo los tiempos de desarrollo. As es que los sistemas operativos basados en UNIX, el sistema BSD, el sistema GNU/Linux y muchos otros fueron desarrollados en C.

    Adems, con el paso del tiempo se han desarrollado cientos de bibliotecas que permiten a los programadores de C utilizar el cdigo desarrollado por otros para la realizacin de tareas comunes. Esto, a su vez, ha propiciado el desarrollo de aplicaciones en lenguaje C.

    Actualmente es imposible contar la cantidad de aplicaciones y herramientas desarrolladas en C.

    Evolucin A mediados de los aos 60s, Martin Richards dise el lenguaje BCPL con la finalidad de usarlo para escribir software de sistemas operativos y compiladores.

    En 1969, Ken Thompson escribi el Lenguaje B, en Bell Laboratories, con el objetivo de recodificar UNIX (escrito hasta ese momento en lenguaje ensamblador) usando un lenguaje de alto nivel ms portable y flexible.

    Durante los siguientes aos, Dennis Ritchie modific el lenguaje B, llegando a crear el lenguaje C y reescribiendo el sistema UNIX en dicho lenguaje; aadi caractersticas nuevas, como son el diseo de tipos y las estructuras de datos.

    En 1978, Dennis Ritchie y Brian Kernighan publicaron la primera edicin del libro El lenguaje de programacin C. Este libro fue durante aos la especificacin informal del lenguaje. El lenguaje descrito en la primera edicin de este libro, fue conocido como "el C de Kernighan y Ritchie" o simplemente "K&R C". En este libro se introdujeron nuevas caractersticas al lenguaje: los tipo de datos struct, long int y unsigned int; los operadores =+ y =- fueron sustituidos por += y -=.

    A mediados de los aos 80, Bjarne Stroustrup (tambin de los laboratorios Bell), crea el lenguaje C++, un lenguaje basado en C, con numerosas caractersticas adicionales, siendo la principal que est orientado a objetos. Si bien se han creado muchos lenguajes basados en C, C++ es el que ha permanecido ms asociado a C.

    En los aos siguientes a la publicacin del C de Kernighan y Ritchie, se aadieron al lenguaje muchas caractersticas no oficiales, que estaban presentes en algunos compiladores y no en otros. Fue por ello que en 1989 ANSI (American National Standards Institute) public el primer estndar oficial de C, que es conocido como ANSI C.

    En este estndar se tomaron muchas de las funcionalidades no oficiales y se agregaron funcionalidades nuevas como los prototipos de funcin, y un preprocesador mejorado. Tambin se cambi la sintaxis de la declaracin de parmetros de funciones, para que incluyeran el tipo junto con el nombre.

    Al ao siguiente, en 1990 se public la estandarizacin ISO del lenguaje. Este estndar es bsicamente el estndar ANSI, con unas pocas modificaciones de formato. A este estndar se lo conoce, entonces, como C89, o C90, y se trata del mismo lenguaje.

    Basndose en el estndar ANSI que estaba en preparacin, en 1988 Kernighan y Ritchie publicaron la segunda edicin de su libro, que es an hoy utilizada como una de las referencias principales del lenguaje.

    Durante los siguientes aos, el lenguaje C permaneci sin demasiados cambios. Sin embargo, como haba sucedido antes, los distintos compiladores fueron incorporando caractersticas adicionales, que otros compiladores no tenan, siendo C++ la principal influencia.

    Fue por ello que a finales de los noventa se decidi revisar el estndar de C, lo que llev a la publicacin del estndar C99. Este estndar incluye varias nuevas caractersticas como son: las funciones inline; la posibilidad de declarar variables en cualquier parte del cdigo; los comentarios de una sola lnea utilizando //; los tipos de datos long long int, bool y complex, entre otras.

  • An hoy el proceso de evolucin del lenguaje sigue avanzando, y desde 2007 se est trabajando en el armado de un nuevo estndar.

    Ms informacin

    Lenguaje de programacin BCPL

    Historia del lenguaje del programacin C

    The Development of the C Language

    Fundamentos de programacin En este captulo veremos un resumido listado de conceptos bsicos, esta informacin puede encontrarse en forma ms elaborada en el WikiLibro Fundamentos de programacin.

    Definiciones

    Se denomina algoritmo a una secuencia de instrucciones que permiten obtener un

    resultado en particular. No necesariamente son programas de computadora, una receta de

    cocina, o las instrucciones para cambiar un neumtico son ejemplos de algoritmos de la vida

    real.

    Las computadoras, son maquinas sin inteligencia propia, cuya nica finalidad es interpretar el cdigo que se les provee.

    El lenguaje de mquina es el nico lenguaje que la computadora "entiende" y es capaz de ejecutar.

    Los lenguajes de programacin son el medio de comunicacin entre el programador y

    una computadora. El programador escribe en algn lenguaje de programacin y utiliza las

    herramientas provistas por ese lenguaje para transformarlo en lenguaje de mquina.

    Finalmente, denominamos programa a una secuencia de rdenes a ser ejecutadas por una computadora. Un programa debe estar escrito en algn lenguaje de programacin, y puede

    incluir uno o ms algoritmos.

    Tipos de lenguajes Existe una gran cantidad de lenguajes de programacin, que estn pensados para distintas finalidades, siguen distintos paradigmas, y de una u otra forma se diferencian de los dems.

    Esquemas de programacin El esquema de programacin llamado Programacin Imperativa, consiste en escribir una secuencia de instrucciones una detrs de la otra, que se ejecutarn en orden. Algunas de esas instrucciones pueden hacer que la mquina pase a una instruccin que no sea la siguiente, tal vez porque se cumpla una condicin que hayamos establecido.

    En los ltimos aos ha tomado fuerza otro paradigma de computacin, llamado Programacin Orientada a Objetos , en el cual se intentan modelar los sistemas creados como extensiones de

  • la realidad mediante la definicin de "objetos" que modelan entidades de la vida real y que interactan entre s mediante "mensajes" llamadas mtodos.

    El lenguaje C es un lenguaje imperativo, no orientado a objetos.

    Alto o bajo nivel Por otro lado, los lenguajes de programacin se clasifican en niveles. Un lenguaje es de ms bajo nivel cuanto ms cercano est al cdigo de mquina, y un lenguaje que es de ms alto nivel cuanto ms lejano est de la mquina y ms cercano al lenguaje humano.

    C es un lenguaje de alto nivel aunque tiene muchas caractersticas de lenguaje de bajo nivel (como el uso que permite hacer de la memoria). Estas caractersticas hacen que C sea un lenguaje muy potente, ya que permite optimizar al mximo los recursos de la mquina. Por ende, esto tambin hace que la dificultad y que los errores que se puedan cometer programando aumenten. As que a C se le considera de nivel medio.

    Lenguajes de ms alto nivel que C son aquellos en los que el programador no necesita encargarse de manipular la memoria, como Java, C#, Python, Ruby, entre otros.

    Compilados o interpretados Otra forma de clasificar a los lenguajes de programacin que es segn la forma en que se ejecutan sus rdenes. Existen los lenguajes que son interpretados, cuyas rdenes pasan a travs de un intrprete que se encarga de ejecutarlas (a partir del cdigo fuente) en el mismo momento en que estn siendo ledas. Algunos de los lenguajes interpretados son Python, Perlo Tcl, entre muchos otros.

    La contraparte de los lenguajes interpretados son los lenguajes compilados (como el mismo C) que se diferencian en que las rdenes son transformadas a lenguaje de mquina que se almacena en un archivo ejecutable. Ese archivo puede ejecutarse luego, sin recurrir al compilador.

    Los lenguajes compilados tienen la ventaja de la velocidad y la eficiencia, pero los interpretados tienen la ventaja de que, generalmente, son muy portables y de ms alto nivel.

    Estructura de la memoria Parte de esta potencia de C viene de que permite acceder con mucha libertad a la memoria de la mquina. Para entender un poco cmo es posible, debemos entender cmo se guardan los datos en la memoria.

    Imaginemos que la memoria tiene un montn de casillas, una enorme fila de casillas, cada una de las cuales contiene un dgito binario (bit):

    0101001010100001010101001010000100111010110010010101001011010110001101010110101010110111...

    Es exactamente as, pero es ms cmodo recordar que esos bits se encuentran agrupados de ocho en ocho, formando octetos (bytes):

    01010010 10100001 01010100 10100001 00111010 11001001 01010010 11010110 00110101 01101010 10110111 ...

    Cada octeto puede contener combinaciones distintas de ceros y unos, es decir, cualquier nmero entre 0 y 255:

    82 161 84 161 58 201 82 214 181 106 183 ...

    Tambin podemos representar estos nmeros en base hexadecimal:

    0x52 0xA1 0x54 0xA1 0x3A 0xC9 0x52 0xD6 0x35 0x6A 0xB7 ...

    O considerarlos caracteres, mediante alguna codificacin:

  • R T : R 5 j ...

    Este es el tipo de dato ms elemental que nos podemos encontrar en C: el caracter. Un caracter ocupa exactamente un byte (8 bits) de memoria, y puede contener un nmero entre 0 y 255, o entre -128 y 127, dependiendo si queremos considerarlo como sin signo o con l.

    Primer programa en C En el libro "El Lenguaje de Programacin C", Kernighan y Ritchie introdujeron al lenguaje C utilizando un sencillo programa que mostraba un saludo por la pantalla. Desde entonces se hizo tradicin empezar con cualquier lenguaje de programacin con el ejemplo del Hola mundo.

    En particular en C se involucran muchas partes y sintaxis del lenguaje, por lo cual es especialmente til verlo como el primer ejemplo de programacin en C.

    Ejemplo: Hola mundo

    /* Inclusin de archivos */ #include /* Funcin principal */ int main (int argc,char **argv) { /* Impresin por pantalla y salida del programa*/ printf("Hola mundo\n"); return 0; }

    Para poder editar y ejecutar este programa ser necesario utilizar algn editor y luego un compilador, como se explic en la seccin Herramientas necesarias.

    Si se tiene el compilador gcc en un entorno UNIX o GNU/Linux, la forma sencilla de compilar y ejecutar ser:

    $ gcc holamundo.c

    $ ./a.out

    Hola Mundo

    $

    Es decir que el compilador genera un archivo, en este caso llamado a.out, y la salida generada por ese archivo es "Hola mundo". A continuacin una explicacin detallada sobre el proceso de compilacin del programa, y luego un anlisis lnea por lnea del contenido de este ejemplo.

    Pre-requisitos para la compilacin de programas Como ya se mencion, ser necesario tener instalado el compilador y un editor o entorno de desarrollo que permitan escribir el cdigo a compilar. Para ms informacin ver la seccinHerramientas necesarias.

    El cdigo a compilar debe guardarse con un nombre que represente al programa en cuestin y la extensin .c. En el caso del ejemplo del Hola mundo, el archivo puede llamarse hola.c.

    En las explicaciones a continuacin, se asume que se cuenta con un compilador instalado y se ha editado un archivo hola.c que se quiere compilar. Si tu sistema operativo no aparece en esta lista busca en internet, ya que seguro que existe algn compilador para ese sistema.

  • Compilacin de programas segn la plataforma Windows Para compilar un programa C en entornos Windows, debemos seguir una serie de pasos que varan segn el compilador de C que queramos utilizar. Antes que nada, sera bueno que se revises la documentacin del compilador elegido para conocer los comandos exactos.

    Compilacin del cdigo fuente

    Si se utiliza un entorno de desarrollo, ser posible compilar directamente desde el entorno, mediante un botn o una combinacin de teclas.

    Si se ejecuta el compilador desde la lnea de comandos, la lnea ser distinta segn el compilador utilizado. A continuacin algunos ejemplos de ciertos comandos segn el compilador:

    En Turbo C de Borland es: tcc hola.c

    En C++ de Borland: bcc hola.c

    En Visual C de Microsoft: cl hola.c

    En GNU gcc: gcc hola.c o cc hola.c

    El C de Zortech: ztc hola.c

    Una vez compilado el cdigo fuente se genera un archivo llamado archivo objeto o programa objeto que es luego enlazado mediante el enlazador, para generar el archivo ejecutable.

    Los compiladores actuales suelen hacer dos funciones de una vez, compilando y enlazando todo en una sola funcin, aunque es posible pedirles que no lo hagan mediante parmetros adicionales.

    Segn el compilador y la configuracin utilizada, se obtendrn dos o tres archivos:

    El archivo fuente

    hola.c

    El archivo objeto

    hola.obj

    El archivo ejecutable

    hola.exe

    Este ltimo es el que nos interesa, puesto a que es el cdigo ejecutable, el programa en s. Al ejecutarlo se producir la salida deseada en una ventana de consola.

    Salida por pantalla

    Si ejecutamos en entorno Windows el programa directamente desde el navegador de archivos, o tambin desde algunos entornos de desarrollo, lo que suceder ser que apenas abierta la ventana de la consola, se mostrar la cadena esperada y luego de terminada la funcin, la consola se cerrar sin tener el tiempo suficiente de ver nuestro mensaje en pantalla.

    Para poder ver la salida por pantalla ser necesario ejecutar el programa desde la lnea de comandos, o modificar la configuracin del entorno de desarrollo para que muestre la salida por pantalla al ejecutar el programa.

  • Una posible solucin es agregar una funcin adicional a nuestro "hola.c":

    /* Inclusin de archivos */ #include #include /* Funcin principal */ int main (int argc,char **argv) { /* Impresin por pantalla y salida del programa*/ printf("Hola mundo\n"); system ("pause"); return 0; }

    Las dos lneas agregadas permiten que utilicemos la biblioteca stdlib, que incluye la funcin system y que mediante esta funcin se ejecute el comando pause del sistema, que evita que el programa siga hasta que se presione una tecla.

    As es posible visualizar que la salida de hola.c se complet perfectamente.

    Linux Si bien existen otros compiladores, lo ms usual y ms sencillo para compilar un programa en GNU/Linux es el compilador gcc, ya que es el que se incluye en todas las distribuciones.

    De cualquier forma, es posible realizar la compilacin desde lnea de comandos o desde el entorno grfico.

    Para realizarla desde lnea de comandos, ser necesario contar con una terminal (xterm, konsole, gnome-terminal, etc). No es necesario contar con permisos de root para crear o compilar programas. En esa terminal ser necesario escribir

    gcc hola.c

    Si no existen errores en el cdigo, este comando nos crear un archivo ejecutable, que por omisin se llama "a.out", y que podemos ejecutar desde la lnea de comandos de la siguiente forma:

    ./a.out

    Hola mundo

    Es una buena idea especificar el nombre que el archivo ejecutable tendr, pasando como parmetro al compilador la opcin -o, de la siguiente forma:

    gcc hola.c -o hola

    Con lo cual, el nombre del archivo creado ser hola. Este archivo no tiene extensin ya que es la forma usual de llamar a los archivos ejecutables en los entornos UNIX y GNU/Linux, sin embargo funcionara de la misma forma si se llamara hola.exe.

    Para ejecutarlo, haremos los mismo que en el caso anterior:

    ./hola

  • Hola mundo

    Existen otros parmetros que podemos especificar al compilador en la lnea de comandos, dependiendo del tipo de programa, y en funcin de la complejidad del mismo. Por ejemplo, podemos agregar las siguientes opciones:

    gcc hola.c -o hola -Wall -pedantic

    La opcin -Wall nos mostrar todos los avisos que produzca el compilador, no solamente los errores. Los avisos nos indican dnde y/o porqu podra surgir algn error en nuestro programa.

    La opcin -pedantic nos aporta ms informacin sobre los errores y los avisos mostrados por GCC.

    Diseccionando el "Hola Mundo" A continuacin veremos cul es la estructura bsica de un programa en C, para poder entender qu hace cada una de las lneas de nuestro sencillo programa.

    Es probable que lo primero que salte a la vista sea la lnea:

    printf("Hola mundo\n");

    Esta es la lnea que hace aparecer la cadena Hola Mundo en nuestra pantalla. Notamos que en C la sentencia para imprimir algo por pantalla es printf() y, adems, hay que colocar parntesis alrededor de lo que queremos imprimir para utilizarla.

    Esto se debe a que en C, printf es una funcin, que imprime su argumento (la cadena Hola Mundo\n) en la pantalla. Se denomina invocar una funcin a la accin de utilizarla para que realice una accin.

    Podemos observar tambin que la cadena a imprimir termina con una extraa combinacin: \n. La combinacin \n no representa a dos caracteres independientes, sino que representa un nico carcter no imprimible: el salto de lnea. Sin el salto de lnea, el resultado al ejecutar el programa sera:

    $ ./a.out

    Hola Mundo$

    Es decir que no hay salto de lnea entre la cadena impresa, y la siguiente entrada de la lnea de rdenes, que no es lo que esperbamos.

    Lo ltimo a notar en la lnea es que termina con un punto y coma. En C, todas las sentencias terminan con un punto y coma. Al principio puede parecer obvio dnde termina una sentencia, pero ya veremos ms adelante que no lo es tanto.

    Observemos ahora la siguiente sentencia del programa:

    return 0;

    Luego de esta sentencia, termina el programa. En el caso de la instruccin return dentro de la funcin main, el resultado es que se finaliza el programa, comunicndole al sistema operativo que el valor de retorno (un cdigo numrico que el sistema utiliza para saber si el programa ha funcionado bien o ha dado fallos) es 0, es decir, correcto.

    Las dos ltimas sentencias se encuentran encerradas entre llaves. De esta manera, forman un bloque, es decir, un grupo de sentencias que se ejecutarn siempre de correlativa.

  • Y qu es esa lnea que precede (en realidad, que da nombre) al bloque?

    int main (int argc, char **argv)

    Pues es la definicin de una funcin, en este caso llamada main. En C (y en general en todos los lenguajes de programacin estructurada) todo se hace a base de funciones, como main yprintf.

    La funcin main es especial, porque es el la que se invoca cuando se ejecuta el programa. Todos los programas en C comienzan su ejecucin al principio de la funcin main, y cuando sta acaba, el programa tambin.

    Veamos con ms detalle la definicin de la funcin:

    int main (int argc, char **argv) { ... }

    El nombre de la funcin que viene a continuacin, entre llaves, es main.

    Recibe dos argumentos: int argc y char **argv (que representan a la cantidad de argumentos ingresados al ejecutar el programa y a los valores de estos argumentos

    respectivamente).[1]

    La funcin devuelve como resultado un nmero entero, int (que es el 0 de la instruccin return).[2]

    Finalmente, y un tanto aparte (est separada del resto por una lnea en blanco), tenemos la lnea:

    #include

    Que parece bastante distinta al resto del programa, y que, adems, parece no tener sentido, puesto que ya hemos definido la funcin main que hace todo el trabajo.

    Efectivamente, esa lnea no es parte del programa, aunque sea imprescindible. La lnea es una instruccin del preprocesador de C, como nos lo indica el smbolo #, y lo que hace es incluir en ese punto el contenido de otro fichero, antes (de ah el nombre de preprocesador) de que comience la compilacin. El fichero stdio.h es el que contiene la definicin de la funcinprintf(), que antes utilizamos pero que no escribimos, ya que forma parte de la biblioteca estndar de C.

    Comentarios Una vez escrito un cdigo, tratar de entenderlo un ao ms tarde solo con leerlo puede ser frustrante: no hay manera de saber (si el programa es medianamente complicado) qu es cada variable, o qu hace cada bloque de cdigo. Por esto, en cualquier lenguaje de programacin son importantes los comentarios.

    Un comentario en C es todo lo que se encuentre entre los smbolos /* y */. Hay que tener en cuenta que los comentarios no se pueden anidar: si dentro de un comentario hay un /*, seguir siendo el primer */ el que finalice el comentario, no se esperar al segundo.

    Hay otro tipo de comentarios en C, procedentes del lenguaje C++, e incorporadas al estndar de C a partir de C99: //. Todo lo que est despus de estos signos, hasta el final de la lnea, se considerar un comentario y el compilador no lo tomar en cuenta.

    En el ejemplo presentado pueden verse tres lneas con comentarios, que documentan someramente las distintas funcionalidades del cdigo. En los prximos captulos podrn verse mejores usos de los comentarios dentro del cdigo.

    Tambin podra decirse que es una herramienta bsica basada en compilador

  • 1. Volver arriba En un captulo posterior podr ver un ejemplo del uso de los parmetros que

    recibe main.

    2. Volver arriba Es importante sealar que el estndar dice que main deber definirse como funcin

    que retorna un entero, o de lo contrario el resultado queda indefinido.

    Tipos de datos

    Historia En el lenguaje C estandarizado como C89, existan cuatro tipos de datos bsicos que son: los nmeros enteros, los nmeros reales, los caracteres, y los punteros. A partir del estndar C99 se agregan: los valores lgicos (verdadero o falso) y los nmeros complejos.

    Estos tipos de datos son parte del lenguaje, y por ello se los considera primitivos. Ms adelante veremos que con el uso de estructuras y uniones es posible crear tipos compuestos de datos a partir de estos tipos primitivos.

    En este captulo veremos los enteros, los reales y los caracteres. Ms adelante se vern otros tipos de datos ms complejos, como son los vectores, las cadenas de caracteres, y los punteros en general.

    Enteros Los enteros son el tipo de dato ms primitivo en C. Se usan para representar nmeros enteros. Pero siempre se pueden encontrar otras aplicaciones para los nmeros enteros. En general se pueden usar para representar cualquier variable discreta.

    Los tipos de datos enteros son: short, int, long y long long, cada uno representando un nmero entero de un tamao o capacidad determinado. Segn el compilador y la plataforma de hardware, cada uno de estos tipos de dato puede ocupar desde 1 byte hasta 8 bytes en memoria (para ms detalles busca en la referencia).

    Adems, el lenguaje C hace la distincin de si el entero es con signo (signed) o sin signo (unsigned). En caso de que no se declare si es con signo o sin signo, se toma con signo.

    Algunos ejemplos de declaraciones de enteros:

    int a; unsigned int a; signed long a; signed long long a = 10000000;

    Todos los nmeros son representados en memoria mediante una cadena de bits. En el caso de los nmeros con signo, el bit ms significativo es el que se usa para representar el signo. La representacin de los nmeros negativos se realiza mediante el complemento a dos, que es una tcnica que permite operar con los nmeros negativos de forma lgica.

    A modo de ejemplo, la representacin en memoria del nmero -8 en una variable de 2 bytes, entera, con signo, sera la siguiente:

    1111111111111000

    Flotantes

  • Se denomina flotantes a los tipos de datos que representan a los nmeros reales, ya que utilizan un sistema de representacin basado en la tcnica de coma flotante, que permite operar con nmeros reales de diversas magnitudes, mediante un nmero decimal llamado mantisa y un exponente que indica el orden de magnitud.

    El tipo de dato flotante en lenguaje C slo tiene dos tamaos: el float y el double, que son 4 bytes y 8 bytes respectivamente. Se los puede utilizar tanto para representar nmeros decimales, como para representar nmeros enteros con un orden de magnitud muy grande.

    La forma de declarar una variable flotante es escribiendo en una lnea uno de los tipos de datos flotantes y a continuacin el nombre de la variable y tal vez algn valor que se les quiera dar.

    Algunos ejemplos:

    float a; double a = 1e23; double a = 3.1416; float a = 4e-9; double a = -78;

    Hay que tener en cuenta que aunque los valores flotantes son ms convenientes para algunas aplicaciones, hay casos en los que se prefieren los enteros. Esto se debe a que los nmeros flotantes no necesariamente tienen soporte de hardware, en particular en las plataformas integradas. Una alternativa que se utiliza en estas situaciones es interpretar los enteros como decimales de forma que 150 se interprete como 1.5 y 2345 como 23.45.

    Para el caso de los flotantes de 4 bytes, se utiliza 1 bit para el signo, 8 bits para el exponente y 23 bits para el valor del nmero. El procedimiento para almacenar un nmero en una variable flotante es el siguiente:

    1. Se convierte a binario la parte entera. 2. Se coloca el signo en el bit ms significativo de la misma manera que en los enteros (1

    para el - y 0 para el +).

    3. Se mueve la coma (en la representacin binaria de la parte entera) hasta que est a la derecha del primer uno y ste se descarta (el uno ms significativo). El valor del exponente ser

    el nmero de posiciones que se movi la coma. El exponente usa la representacin de un

    entero con complemento a dos.

    4. Se convierte en binario la parte decimal del nmero. Esto usando el peso de los bits. el bit decimal ms significativo vale 1/2, el siguiente vale 1/4, el otro 1/8, el otro 1/16 y as hasta

    completar lo que falta para los 23bits del valor.

    5. Se concatena todo y ese es el valor flotante representado en memoria.

    Caracteres Los caracteres se representan utilizando el tipo char, que tiene slo 1 byte de tamao. Este tipo se utiliza para representar los 256 caracteres de la tabla de caracteres del sistema. El tipochar es tambin un tipo entero, ya que puede tomar valores de 0 a 255. Por lo tanto tambin puede ser signed o unsigned.

    En cuanto a la forma de declarar variables de tipo char es la misma forma que con los otros tipos.

    char a; char a = 's'; unsigned char a = 48;

  • Como puedes ver, se le puede asignar un nmero a una variable char, ya que se trata de un tipo entero. En muchas situaciones se utiliza el tipo char para almacenar nmeros pequeos, ya que ocupa en memoria slamente un byte.

    Es importante notar que con la llegada de la codificacin UTF-8, los caracteres de los diversos idiomas pueden ocupar 1, 2, 3 o 4 bytes, de modo que el tipo char ya no alcanza para la representacin de todos los caracteres posibles. Por ello, el estndar C99 introduce el tipo wchar que puede ocupar ms de 1 byte, segn sea necesario para la codificacin utilizada por el sistema.

    Interaccin con el usuario En este captulo veremos un poco ms sobre como interactuar con el usuario de nuestros programas desde la consola, utilizando printf() como vimos en el primer ejemplo "Hola mundo", as como scanf() para la lectura del teclado.

    Imprimir por pantalla Como hemos visto hasta ahora en los ejemplos, hay una funcin que utilizamos para sacar por pantalla textos arbitrarios o el resultado de alguna operacin: la funcin printf().

    Si miramos (en la documentacin) su definicin, no nos aclarar demasiado:

    int printf (const char *TEMPLATE, ...)

    ...claro que por algo tiene una seccin completa de la documentacin para ella sola.

    Vemosla poco a poco. Se trata de una funcin de la biblioteca estndar, lo que quiere decir que para utilizarla tenemos que incluir previamente su definicin. La encontraremos en.

    Lo primero que vemos en la definicin es que es una funcin de tipo int, lo que quiere decir que devuelve un entero. Ese entero es el nmero de caracteres impresos en la pantalla, o un nmero negativo en caso de que se produzca algn error.

    Lo siguiente a notar es su primer argumento: const char *TEMPLATE. Se trata de una cadena de caracteres (char *) que no ser modificada por la funcin (const), con lo que puede ser una constante de cadena o una variable que contenga una cadena, pero siempre debe acabar con el carcter nulo \0.

    Y luego vienen esos extraos puntos suspensivos. Esa elipsis nos indica que como argumentos adicionales de printf() podemos poner una serie ilimitada de otros argumentos, que se supone que la funcin sabr qu hacer con ellos. Y eso es justamente lo que hace tan fabulosa y til a printf().

    Como hemos visto, el uso ms simple de printf() es imprimir una cadena de texto simple y corriente. Como ya vimos:

    printf("Hola Mundo\n"); /*imprime la cadena*/

    Y tambin hemos visto printf() tambin puede, con un argumento extra y una sintaxis especial, imprimir un nmero entero que hayamos almacenado en una variable:

    char resultado; resultado=5+2; printf("Resultado de la suma: %i\n",resultado);

    Aqu el punto de insercin es la secuencia %i. printf() siempre trata las secuencias que comiencen por % como secuencias de control que le dicen que debe imprimir algo que le proporcionamos en los otros argumentos. As, podemos imprimir varios enteros distintos en los sitios que queramos de la cadena, insertando varias de estas secuencias %i:

  • int numero; numero=3; printf("El doble de %i es %i y su cuadrado es %i\n",numero,numero*2,numero*numero);

    Lectura de datos del teclado La entrada de datos se puede hacer de muchas maneras y entre ellas estn desde el uso de dispositivos especiales hasta nuestro simple teclado. La entrada de datos se refiere a cualquier forma de influencia del usuario sobre los datos que posee el sistema.

    Con el fin de mostrar una forma de entrada simple para el aprendizaje vamos a hablar de la funcin scanf() que se encuentra definida en y que se usa para capturar diferentes tipos de datos.

    La funcin scanf() scanf() es una de las funciones ms usadas por los principiantes para hacer entrada de datos en el lenguaje C. Tiene una sintaxis muy parecida a printf: recibe una cadena con el formato de los datos y luego se ponen las variables en orden que correspondan a ese tipo de datos. Es decir, as como en printf se pueden mostrar por pantalla los datos de varias variables en una misma sentencia, en scanf se pueden capturar varios datos en una sola sentencia.

    #include int main() { int a; printf ("diga un valor para a:"); scanf("%i",&a); printf ("el valor es: %i\n",a); return 0; }

    Por ahora no nos interesan las dems sentencias, slo la que contiene scanf. En el cdigo se ve lo siguiente:

    scanf("%i",&a);

    Se observa que la funcion printf dej en pantalla una peticin para que el usuario introdujera un valor. Entonces, scanf recibe como argumento una cadena del formato en que se van a capturar los datos y la lista de variables que van a recibir valores y que deben coincidir con los del formato.

    En este caso la cadena de formato, "%i", especifica que el usuario ingresar un nmero entero. Luego se designa a la variable a para contener a ese nmero. El smbolo (&) que precede aa es para especificar que lo que se est enviando como argumento no es el valor que posee la variable a sino la direccin de memoria en que se encuentra. En este momento eso no tiene mucha relevancia, slo hay que recordar que se debe usar el smbolo & dentro del scanf. En el momento en que hablemos de punteros veremos ms detalles de esto.

    Otro ejemplo del uso de scanf:

    #include int main() { int a,b; printf ("introduzca dos valores con el formato \"a,b\" :"); scanf("%i,%i",&a,&b); printf ("el primer valor : %i\n",a); printf ("el segundo valor : %i\n",b); return 0; }

  • Aqu hemos introducido una nueva variable en el cdigo. La cadena de formato, "%i,%i" especifica que el usuario ingresar un nmero, seguido de una coma, y luego otro nmero. El primer %i ser capturado por la variable a y el segundo por b.

    Expresiones Vamos a tratar ahora de que el ordenador haga un poco de matemticas para nosotros. Por ejemplo, que realice unas pocas sumas, restas multiplicaciones y divisiones.

    #include int main(void) { int resultado; resultado=5+2; printf("Resultado de la suma: %i\n",resultado); resultado=5-2; printf("Resultado de la resta: %i\n",resultado); resultado=5*2; printf("Resultado de la multiplicacin: %i\n",resultado); resultado=5/2; printf("Resultado de la divisin: %i\n",resultado); return(0); }

    Despus de grabarlo (por ejemplo, con el nombre ejemplo.c), lo compilamos y ejecutamos, con (respectivamente):

    $ gcc ejemplo.c

    $ ./a.out

    Resultado de la suma: 7

    Resultado de la resta: 3

    Resultado de la multiplicacin: 10

    Resultado de la divisin: 2

    $

    Fijmonos en la lnea del principio de la funcin main:

    int resultado;

    Esta lnea lo que hace es reservar un trozo de memoria, del tamao de un int (normalmente 4 bytes), y asignarle el nombre resultado, para poder despus referirnos a l. A partir de este momento, podemos considerar que en nuestro programa existe una variable, que no tiene valor definido, pero a la que le podremos dar valor posteriormente.

    Las lneas con printf() ya las conocemos, pero hay algo en ellas que no habamos visto antes. Esos %i y la parte de resultado son nuevas para nosotros.

    La funcin printf() no slo sabe imprimir cadenas simples, como "Hola Mundo\n", sino tambin imprimir variables. Para ello, en el lugar de la cadena donde queremos que aparezca el valor de la variable, introducimos lo que se llama una cadena de conversin de printf(). Estas cadenas siempre empiezan por %, siendo %i la cadena para imprimir un entero, como es en nuestro caso int resultado. Finalmente, printf() debe saber qu valor escribir, por eso le damos otro

  • argumento (u otros), usando , como separador, que contienen las variables cuyos valores queremos mostrar.

    En el resto del programa hemos visto cmo decirle al ordenador que ejecute una suma, una resta, una multiplicacin y una divisin entera, con los operadores +, -, * y /. Es de notar que el resultado de una operacin como estas entre nmeros enteros ser siempre otro entero, como se puede observar en la divisin, en la que no obtenemos un bonito decimal, sino un resultado entero. Adems, hemos visto que el resultado de esas operaciones, que llamamos expresiones, puede ser asignado a una variable:

    resultado = 7;

    Esa asignacin se hace mediante el operador de asignacin: =. Con l, ya conocemos cinco operadores.

    Pero, como = tambin es un operador, cmo sabe el ordenador qu operador debe ejecutar primero? Y si es un operador, por qu no da un resultado? No crea una expresin?

    Operadores Precedencia * / Izq. a Der. + - Izq. a Der. = Der. a Izq.

    Empezando por las ltimas preguntas, el operador de asignacin s crea una expresin, como los operadores de suma, resta, multiplicacin y divisin, y esa expresin tiene un resultado, que es el valor que obtiene el lado izquierdo al realizar la operacin. En cuanto a saber qu se debe ejecutar primero, el ordenador tiene una lista de precedencia, segn la cual siempre ejecuta primero las multiplicaciones y divisiones, de izquierda a derecha, a continuacin las sumas y restas, de izquierda a derecha, y a continuacin las asignaciones, de derecha a izquierda. Para ms detalles acerca de la precedencia de los operadores ver el anexo de los operadores.

    En cuanto a los caracteres de punto y coma, notamos aqu que una expresin tambin puede ser una sentencia por s misma, sin necesidad de que haya ninguna funcin. De hecho, una sentencia puede no tener siquiera una expresin. La lnea: ; es una sentencia perfectamente vlida, la sentencia vaca, que sera til en puntos donde el lenguaje requiera una sentencia pero no sea necesaria para nuestro programa.

    Instrucciones de control Como ya se ha mencionado, C es un ejemplo de programacin estructurada. En este tipo de programacin, es necesario contar con ciertas estructuras que permitan controlar el flujo del programa, es decir, tomar decisiones y repetir acciones.

    La estructura condicional if ... else En la gran mayora de los programas ser necesario tomar decisiones sobre qu acciones realizar. Esas decisiones pueden depender de los datos que introduzca el usuario, de si se ha producido algn error o de cualquier otra cosa.

    La estructura condicional if ... else es la que nos permite tomar ese tipo de decisiones. Traducida literalmente del ingls, se la podra llamar la estructura "si...si no", es decir, "si se cumple la condicin, haz esto, y si no, haz esto otro".

    Un ejemplo sencillo sera el siguiente (no se trata de un programa completo, sino tan slo una porcin de cdigo):

    if (edad < 18) printf("No puedes acceder.\n"); else printf("Bienvenido.\n");

  • Este cdigo de ejemplo dice que si el valor de la variable edad es menor que 18 se imprimir "No puedes acceder.\n", mientras que en caso contrario se imprimir "Bienvenido.\n".

    Como se ve en el ejemplo, la estructura de un condicional es bastante simple:

    if (condicin) { sentencias_si_verdadero; } else { sentencias_si_falso; }

    La condicin, encerrada entre parntesis, es una expresin que puede dar como resultado 0 (interpretado como falso) o cualquier valor distinto de 0 (interpretado como verdadero). Cuando la condicin sea verdadera, se ejecutarn las sentencias dentro del primer bloque de cdigo, cuando la condicin sea falsa, se ejecutarn las sentencias del segundo bloque de cdigo. Las expresiones y valores de tipo verdadero/falso son tambin llamados valores lgicos o booleanos.

    La indentacin o sangra (los espacios al comienzo de las lneas) no es necesaria, pero ayuda a la claridad del cdigo. La utilizacin de las llaves {...} es obligatoria cuando se quiere utilizar ms de una instruccin por bloque, y optativa cuando slo se quiere escribir una instruccin. Por claridad, sin embargo, es recomendable utilizarlas an cuando slo vaya a haber una instruccin.

    El bloque del else es opcional. Si no se lo encuentra, slo se realizar la accin correspondiente al bloque if.

    A continuacin, un ejemplo con una funcin, que devuelve el mayor de dos nmeros:

    int mayor(int a, int b) { if (b > a) { return b; }// No posee especificacin de la parte "else", ya que no es necesaria. return a; // Finaliza la funcin retornando el valor de "a". }

    Operadores de comparacin El smbolo > visto en el ltimo ejemplo es un operador, que en este caso compara dos nmeros enteros y devuelve verdadero si el primero es mayor, falso en caso contrario.

    A continuacin un listado de los posibles operadores de comparacin en C y su significado.

    Operadores de Comparacin Operador Significado

    < estrictamente menor que > estrictamente mayor que = mayor o igual que == igual a != distinto de

    Teniendo en cuenta que en C se toma como falso el valor 0, y como verdadero cualquier otro valor, una prctica comn es expresar condiciones sin utilizar ningn operador:

    float division(int dividendo, int divisor) { if (divisor) { return dividendo / divisor;

  • } else { printf ("No se puede dividir por cero\n"); return 0; } }

    En este caso, la expresin (divisor) es equivalente a (divisor != 0).

    Operadores lgicos Los operadores && ("y"), || ("o") y ! ("no") son operadores lgicos. Permiten operar con expresiones lgicas para generar expresiones ms complejas.

    Por ejemplo: determinar si un ao es bisiesto o no. Los aos son bisiestos si son divisibles por 4, pero no si son divisibles por 100, a menos que tambin sean divisibles por 400.

    if ( (!(a % 4) && ((a % 100))) || !(a % 400) ) { printf("es un ao bisiesto.\n"); } else { printf("no es un ao bisiesto.\n"); }

    En realidad, teniendo en cuenta la prioridad de los operadores utilizados, podemos simplificar la expresin anterior del siguiente modo:

    if ( !(a % 4) && (a % 100) || !(a % 400) ) { printf("es un ao bisiesto.\n"); } else { printf("no es un ao bisiesto.\n"); }

    Adems, como a cada rama del if le sigue una nica instruccin, podemos expresar la expresin anterior del siguiente modo:

    if ( !(a % 4) && (a % 100) || !(a % 400) ) printf("es un ao bisiesto.\n"); else printf("no es un ao bisiesto.\n");

    En este caso, se utiliza el operador mdulo (%), que obtiene el resto de la divisin entera de un nmero por otro. Cuando un nmero es divisible por otro, el resto de su divisin entera ser cero. Siendo que cero es equivalente a falso, y cualquier valor distinto de cero es equivalente a verdadero, podemos usar el operador % para verificar si el nmero es mltiplo de 4, de 100 o de 400.

    Evaluacin de cortocircuito La evaluacin en corto circuito es una caracterstica del lenguaje C que se utiliza para optimizar la ejecucin de programas. Consiste en que el programa puede verificar si una expresin es verdadera o falsa antes de haber evaluado toda condicin.

    Por ejemplo, si se tiene una condicin como la siguiente:

    if ((a > 2) || (b < 4)) { ... }

    Al ejecutarse el programa, se evaluar primero si a > 2. En el caso en que sea verdadero, no continuar con la siguiente condicin, ya que el resultado ser de cualquier modo verdadero.

    De la misma forma, si la condicin fuera:

  • if ((a > 2) && (b < 4)) { ... }

    En este caso, si no se cumple que a > 2, no se evaluar la siguiente condicin, ya que el resultado ser falso de todos modos.

    Esta caracterstica no tiene demasiada importancia al comenzar a programar, pero facilitar ciertas operaciones y optimizaciones en programas avanzados.

    La estructura condicional switch ... case La estructura condicional switch ... case se utiliza cuando queremos evitarnos las llamadas escaleras de decisiones. La estructura if nos puede proporcionar, nicamente, dos resultados, uno para verdadero y otro para falso. Una estructura switch ... case, por su parte, nos permite elegir entre muchas opciones. Ejemplo:

    #include #include int main(void) { int dia; printf("que nmero de da de la semana es?"); scanf("%d",&dia); switch(dia) { case 1 : printf("Lun, Lunes"); break; case 2 : printf("Mar, Martes"); break; case 3 : printf("Mier, Miercoles"); break; case 4 : printf("Jue, Jueves"); break; case 5 : printf("Vie, Viernes"); break; case 6 : printf("Sab, Sabado"); break; case 7 : printf("Dom, Domingo"); break; default : printf("No existe"); } return 0; }

  • La estructura anterior, de realizarse con sentencias if, necesitara cuatro de ellas, resultando un enorme bloque muy difcil de leer. En la mayora de los casos, adems, la sentencia switchproporciona una ganancia en velocidad del cdigo, pues permite al compilador trabajar en base a que se trata de una decisin mltiple para una nica variable, cosa que con sentencias ifel compilador no tiene por qu detectar.

    Como vemos, para cada valor de la variable se ejecuta un bloque de sentencias distinto, en el que no necesitamos llaves. Hay un caso especial, default, que se ejecuta si ningn otro corresponde, y que no es necesario poner. Es, en todo, equivalente al bloque else de una sentencia if.

    Las sentencias break son muy importantes, ya que el comportamiento normal de un bloque switch es ejecutarlo todo desde la etiqueta case que corresponda hasta el final. Por ello, si no queremos que se nos ejecute ms de un bloque, pondremos sentencias break al final de cada bloque excepto el ltimo.

    Es decir, las etiquetas case son puntos de entrada de la ejecucin, y no implican que al acabarse el bloque case la ejecucin salte al final del bloque switch. Las etiquetas case siguientes a la que hemos utilizado para entrar son, sencillamente, ignoradas.

    A la ausencia de sentencias break se le llama, en ocasiones, "dejar caer la cascada switch".

    El bucle while El bucle while sirve para ejecutar cdigo reiteradas veces.

    while (/*condicion*/) { /* Cdigo */ }

    La condicin debe de ser una expresin lgica, similar a la de la sentencia if. Primero se evala la condicin. Si el resultado es verdadero, se ejecuta el bloque de cdigo. Luego se vuelve a evaluar la condicin, y en caso de dar verdadero se vuelve a ejecutar el bloque. El bucle se corta cuando la condicin da falso.

    Ejemplo: imprimir los nmeros de 0 a 99:

    int i = 0; while (i < 100) { printf("%d\n", i); i = i + 1; }

    El bucle for El bucle for es un bucle muy flexible y a la vez muy potente ya que tiene varias formas interesantes de implementarlo, su forma ms tradicional es la siguiente:

    for (/* inicializacin */; /* condicin */; /* incremento */) { /* cdigo a ejecutar */ }

    Inicializacin: en esta parte se inicia la variable que controla el bucle y es la primera sentencia que ejecuta el bucle. Slo se ejecuta una vez ya que solo se necesita al principio del bucle.

    Expresin condicional: al igual que en el bucle while, esta expresin determina si el bucle continuar ejecutndose o no.

    Incremento: es una sentencia que ejecuta al final de cada iteracin del bucle. Por lo general, se utiliza para incrementar la variable con que se inicio el ciclo. Luego de ejecutar el incremento, el bucle revisa nuevamente la condicin, si es verdadera tiene lugar una ejecucin ms del cuerpo del ciclo, si es falsa se termina el ciclo y as.

  • Aqu se muestra el mismo ejemplo visto para el bucle while, pero implementado con un bucle for:

    int i; for (i=0; i < 100; i = i + 1) { printf("%d\n", i); }

    Nota: En C, la sentencia i = i + 1 puede escribirse en forma ms reducida como i++. Esta forma se utiliza ms comnmente en el bucle for:

    int i; for (i=0; i < 100; i++) { printf("%d\n", i); }

    El bucle do...while El bucle do...while es un bucle que, por lo menos, se ejecuta una vez. Do significa literalmente "hacer", y while significa "mientras"

    Su forma es esta:

    do { /* CODIGO */ } while (/* Condicin de ejecucin del bucle */)

    Os muestro un ejemplo sencillo de uso:

    int aleatorio; do { aleatorio = rand(); } while (aleatorio != 25);

    La verdad es que este ejemplo puede resultar un poco absurdo, pero es bastante intuitivo. El cdigo del bucle asigna un valor aleatorio a la variable definida anteriormente, y mientras esa variable no tenga el valor 25, el bucle sigue ejecutndose.

    La sentencia goto La sentencia goto sirve para indicar al programa que continue ejecutndose desde la lnea de cdigo indicada. Su sintaxis es ms o menos as:

    /* Cdigo */ ETIQUETA: /* Cdigo */ goto ETIQUETA; /* Cdigo */

    As, cuando se ejecute la sentencia goto, el programa "saltar" y continuar su ejecucin a partir de la etiqueta marcada.

    Como se puede observar se puede usar para crear un bucle, o para ir a una parte del cdigo u otra si se combina con una sentencia if...else. Pero por lo general puede obtenerse el mismo efecto utilizando los bucles anteriormente vistos.

    Por eso, la sentencia goto es poco aceptada por la comunidad de programadores, pues puede provocar que se hagan programas un poco "sucios" y confusos. Slo en ocasiones muy excepcionales ser recomendado el uso del goto al crear iteraciones muy complejas. Sin embargo, con el pasar de los aos este comando ya ha quedado prcticamente descartado del lenguaje de los programadores.

  • Uso de Funciones

    Funciones Como vimos anteriormente C tiene como bloque bsico la funcin main() , tambin hemos visto la sentencia printf() que es otra funcin, y de igual forma hay muchas ms funciones predefinidas, pero nosotros mismos tambin podemos definir nuestras propias funciones. De hecho, es fundamental hacerlo.

    Podemos definir una funcin cualquiera de la misma manera en que definimos la funcin main(). Basta con poner su tipo, su nombre, sus argumentos entre parntesis y luego, entre llaves, su cdigo:

    /* Inclusin de archivos */ #include void holamundo(void) /* Funcin donde se ejecuta la lgica del programa */ { printf("Hola Mundo\n"); /* imprime la cadena */ return; /* sale de la funcin */ } int main(void) /* Funcin principal del programa */ { holamundo(); /* llamada a la funcin holamundo */ return 0; /* sale del programa con cdigo 0 (correcto) */ }

    Este cdigo es en todo equivalente al "Hola Mundo" original, slo que nos muestra cmo escribir y cmo utilizar una funcin. Y adems nos muestra un principio de buena programacin: meter las sentencias que "hacen el trabajo" en otras funciones especficas para sacarlas de main(), dejando en sta tan slo un guin general de lo que hace el programa, no las rdenes especficas. De esta manera se facilita la comprensin del programa, y por tanto el futuro trabajo de modificarlo.

    La sentencia return La sentencia return puede utilizarse dentro de una funcin para terminar su ejecucin.

    En el ejemplo anterior, la funcin holamundo fue declarada con valor de retorno de tipo void (es decir, valor de retorno nulo). En ese caso, la sentencia return no lleva ningn parmetro adicional, ya que la funcin no debe devolver ningn valor a la funcin que la llama.

    En cambio, la funcin main tiene un valor de retorno de tipo int, por lo que return debe ir seguido de un valor entero (0 en el ejemplo). El valor 0 se utiliza para indicar que el programa ha llegado a un punto en el que todo se ha desarrollado correctamente y se utiliza cualquier otro valor para indicar que ha habido algn tipo de error.

    La instruccin return no es una funcin, se trata de una sentencia que lo que hace es retornar como valor de la funcin el valor que se le proporciona como argumento.

    Argumentos Las funciones tambin pueden recibir argumentos o parmetros, para modificar su comportamiento. Por ejemplo, la definicin de una funcin para sumar dos nmeros sera de la siguiente manera:

    #include int sumar(int numero1, int numero2)

  • { return numero1 + numero2; } int main(void) { int suma = sumar(5, 3); printf("La suma es: %d ", suma); return 0; }

    En este ejemplo, la funcin sumar recibe dos argumentos de tipo int y su valor de retorno tambin es de tipo int. Dentro de la funcin main, se llama a la funcin sumar poniendo entre parntesis los valores deseados para sus argumentos, en orden, separados por una coma. As, dentro de sumar el nmero 5 ser asignado a la variable numero1 y el nmero 3 a numero2.

    Declaracin y definicin En el ejemplo anterior podemos notar que la funcin sumar figura en el cdigo antes que main. Qu pasara si las escribiramos en distinto orden?

    #include int main(void) { int suma = sumar(5, 3); /* ERROR, sumar no ha sido declarada an */ printf("La suma es: %d ", suma); return 0; } int sumar(int numero1, int numero2) { return numero1 + numero2; }

    En este caso el programa es errneo y no compila, ya que en la lnea donde se llama a la funcin sumar, el compilador an no conoce ninguna funcin con ese nombre, y cules son sus argumentos y valor de retorno.

    Una posible solucin es declarar el prototipo de la funcin al principio, para informar al compilador que existe, y luego definir el cuerpo de la misma en cualquier lugar del programa:

    #include /* Declaracin */ int sumar(int numero1, int numero2); int main(void) { int suma = sumar(5, 3); printf("La suma es: %d ", suma); return 0; } /* Definicin */ int sumar(int numero1, int numero2) {

  • return numero1 + numero2; }

    Paso de Parmetros Las funciones pueden recibir datos como lo hemos observado, pero existen dos formas de enviar los datos hacia una funcin por valor ypor referencia, las cuales modifican en diferente forma el comportamiento de el programa.

    Por Valor

    El paso por valor enva una copia de los parmetros a la funcin por lo tanto los cambios que se hagan en ella no son tomados en cuenta dentro de la funcin main(). Ejemplo:

    /* * por_valor.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include void sumar_valor(int numero); /* prototipo de la funcin */ int main(void) { int numero = 57; /* definimos numero con valor de 57*/ sumar_valor(numero); /* enviamos numero a la funcin */ printf("Valor de numero dentro de main() es: %d\n", numero); /* podemos notar que el valor de numero se modifica * slo dentro de la funcin sumar_valor pero en la principal * nmero sigue valiendo 57 */ return 0; } void sumar_valor(int numero) { numero++; /* le sumamos 1 al numero */ /* el valor de nmero recibido se aumenta en 1 * y se modifica dentro de la funcin sumar_valor() */ printf("Valor de numero dentro sumar_valor() es: %d\n", numero); return; } Por Referencia

  • El paso por referencia se hace utilizando apuntadores. Se enva la direccin de memoria de la variable, por lo tanto los cambios que haga la funcin si afectan el valor de la variable. Ejemplo:

    /* * por_referencia.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include void sumar_referencia(int *numero); /* prototipo de la funcin */ int main(void) { int numero = 57; /* definimos numero con valor de 57*/ sumar_referencia(&numero); /* enviamos numero a la funcin */ printf("\nValor de numero dentro de main() es: %d ", numero); /* podemos notar que el valor de numero se modifica * y que ahora dentro de main() tambin se ha modificado * aunque la funcin no haya retornado ningn valor. */ return 0; } void sumar_referencia(int *numero) { *numero += 1; /* le sumamos 1 al numero */ /* el valor de numero recibido se aumenta en 1 * y se modifica dentro de la funcin */ printf("\nValor de numero dentro sumar_referencia() es: %d", *numero); return; }

    Variables Locales y Globales Adems de pasar valores a una funcin, tambin se pueden declarar tipos de datos dentro de las funciones, estos tipos de datos declarados dentro de una funcin solo son accesibles dentro de esta misma funcin y se les conocen como variables locales, as pues podemos definir los mismos nombres de variables en diferentes funciones, ya que estas variables solo son accesibles dentro de esas funciones. Ejemplo:

    /* * locales.c * * Julio Csar Brizuela 2009

  • * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include void funcion1() { int dato = 53; /* definimos dato en 53*/ char num1 = 'a'; /* num1 vale a */ /* imprimimos */ printf("Funcion1, dato=%d, num1=%c\n", dato, num1); return; } void funcion2() { int dato = 25; /* definimos dato en 25*/ char num2 = 'z'; /* num2 vale z*/ /* imprimimos */ printf("Funcion2, dato=%d, num2=%c\n", dato, num2); return; } int main(void) { funcion1(); /* llamamos a funcion1() */ funcion2(); /* llamamos a funcion2() */ return 0; }

    En este caso la variable dato, esta definida dentro de cada una de las funciones y son totalmente distinta una de otra y no se puede utilizar fuera de esta, as pues num2 no puede ser utilizada por la funcion1() y num1 tampoco puede ser utilizada por funcion2().

    Existen pues variables que se definen fuera de la funcin principal main() y fuera de cualquier otra funcin creada por nosotros, estas variables se les conoce con el nombre de Variables Globales ya que se pueden utilizar dentro de main() y dentro de cualquier funcin creada por nosotros. Ejemplo:

    /* * global.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */

  • #include int variable_global = 99; /* inicializamos la variable global */ void funcion(); int main(void) { /* imprimimos el valor*/ printf("main(), acceso a variable_global %d\n", variable_global); /* llamamos a la funcin */ funcion(); return 0; } void funcion() { /* imprimimos el valor*/ printf("funcion(), acceso a variable_global %d\n", variable_global); return; }

    Funciones Recursivas La recursividad (recursin) es la propiedad por la cual una funcin se llama a s misma directa o indirectamente. La recursin indirecta implica utilizar ms de una funcin.

    Se puede considerar la recursividad como una alternativa a la iteracin. La recursin permite especificar soluciones naturales, sencillas, que seran, en caso contrario, difciles de resolver. Toda funcin recursiva debe contemplar un caso base o condicin de salida, para terminar, o la recursividad no podr terminar nunca.

    Una funcin recursiva podra definirse as:

    funcion_recursiva( /* parmetros recibidos por la funcin */ ) { /* Cdigo */ funcion_recursiva( ); /* llamada a la funcin misma */ /* Cdigo */ }

    Uno de los ejemplos ms representativos en la recursividad es el factorial de un numero ( n! ):

    la definicin de recursividad del factorial es:

    En esta definicin, n = 0, es nuestro caso base, que le da fin a la recursividad.

  • Entonces nuestro programa que calcula el factorial es:

    /* *factorial.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include long factorial(int n) { if (n == 0) /* caso base */ return 1; /* como 0! = 1, se retorna 1*/ else return n * factorial (n - 1); /* llamada a esta misma funcin */ } int main(void) { /* en este caso se llama a la funcin y se imprime directamente*/ printf("%ld ", factorial(5)); return 0; }

    Tambin existen otros tipos de funciones recursivas como lo es el producto de dos nmeros. El producto de a b, donde a y b son nmeros enteros positivos seria:

    Solucin iterativa:

    Solucin recursiva:

    As pues es:

    Podemos ver que la multiplicacin de dos nmeros a, b se puede transformar en otro problema ms pequeo multiplicar a por (b-1), el caso base se produce cuando b = 0 y el producto es0. Ejemplo:

    /* * producto.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico

  • */ #include int producto(int a, int b) { if (b == 0) /* caso base */ return 0; /* como b = 0, se retorna 0*/ else return a + producto (a, b - 1); /* llamada a esta misma funcin */ } int main(void) { /* en este caso se llama a la funcin y se imprime directamente*/ printf("%i ", producto( 7, 3)); return 0; }

    Recursividad indirecta o recursin mutua Esta se produce cuando una funcin llama a otra, que esta a su vez terminar llamando de nuevo a la primera funcin. El siguiente programa visualiza el alfabeto utilizando recursin indirecta o mutua:

    /* * elalfabeto.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include void funcionA(char c); /* se declara el prototipo de la funcin para que el llamado */ void funcionB(char c); /* a la misma en la funcin no sea implcita */ int main(void) { funcionA('z'); /* llamado a funcionA */ return 0; } void funcionA(char c) { if (c > 'a') /* caso base mientras c no sea menor que A */ funcionB(c); /* llamado a la funcionB */ printf("%c ", c); /* imprimimos el valor de c */ *la variable es un parametro no utilizado para este proceso

  • } void funcionB(char c) { funcionA(--c); /* llamado a la funcionA decrementando el valor de 'z' */ }

    Recursin versus Iteracin Tanto la iteracin como la recursin se basan en estructura de control: la iteracin utiliza una estructura repetitiva y la recursin una estructura de seleccin. La iteracin utiliza explcitamente una estructura repetitiva mientras que la recursin consigue la repeticin mediante llamadas repetitivas a funciones.

    La iteracin termina si la condicin del bucle no se cumple, mientras que la recursin termina cuando se reconoce un caso base.

    La recursin puede presentar desventajas ante la iteracin ya que se invoca repetidas veces al mecanismo de llamada de funciones y se necesita un tiempo mayor para realizar cada llamada.

    La razn por la cual se puede elegir u optar por usar recursividad es que existen muchos problemas complejos que poseen naturaleza recursiva y, en consecuencia, son mas fciles de implementar.

    Ejemplo Iterativo /* * iterativo.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include long factorial(int numero); int main(int argc, char** argv) { int contador = 0; /* calcula el factorial de 0 a 10 */ for ( contador = 0; contador = 1; i-- )

  • resultado *= i; return resultado; } Ejemplo Recursivo /* * recursivo.c * * Julio Csar Brizuela 2009 * * para el wikilibro "Programacin en C" * bajo licencia FDL, adaptado del Dominio Pblico */ #include long factorial(int numero); int main(int argc, char** argv) { int contador = 0; /* calcula el factorial de 0 a 10 */ for ( contador = 0; contador
  • double valores[128];

    En este ejemplo declaramos un vector de 128 elementos del tipo double, los ndices de los elementos iran entre 0 (para el primer elemento y 127 para el ltimo).

    De la misma forma que con las otras declaraciones de variables que hemos visto se le puede asignar un valor iniciar a los elementos.

    O tambin se pueden declarar:

    tipo_elemento nombre[largo]={valor_0, valor_1, valor_2};

    En caso estamos asignadole valores a los primeros 3 elementos del vector nombre. Notar que largo debe ser mayor o igual a la cantidad de valores que le estamos asignando al vector, en el caso de ser la misma cantidad no aporta informacin, por lo que el lenguaje nos permite escribir:

    tipo_elemento nombre[]={valor_0, valor_1, valor_2};

    Que declarar nombre como el vector de largo 3.

    Para acceder a un elemento accederemos a travs de su posicin. Es decir:

    tipo_elemento elemento; ... elemento = nombre[2];

    Asumiendo que tenemos el vector anterior definido estaramos guardando valor_2 en elemento.

    Veamos algunos ejemplos:

    /* * Ejemplo : El producto escalar de dos vectores */ #include double producto_escalar(double v1[], double v2[], int d); int main() { const int largo = 3; double vector_1[] = {5,1,0}; double vector_2[] = {-1,5,3}; double resultado = producto_escalar(vector_1, vector_2, largo); // imprime el resultado printf("(%f, %f, %f) . (%f, %f, %f) = %f\n", vector_1[0], vector_1[1], vector_1[2], vector_2[0], vector_2[1], vector_2[2], resultado); return 0; } /* producto escalar entre dos vectores */ double producto_escalar(double v1[], double v2[], int d) { double resultado = 0; int i; for (i=0; i < d; i++) {

  • resultado += v1[i] * v2[i]; } return resultado; }

    En el ejemplo anterior usamos los vectores de C para representar vectores matemticos y calcular el producto escalar entre ellos. Una peculiaridad que se puede notar es que al recibir un arreglo en una funcin no se especifica el largo, volveremos a esto en un captulo posterior.

    Otra funcin clsica es la bsqueda de un mximo o mnimo, que podemos escribirla de la siguiente manera:

    int buscar_maximo(double valores[], int num_valores) { int maximo_pos = 0; for (int i = 1; i < num_valores; i++) { if (valores[i] > valores[maximo_pos]) { maximo_pos = i; } } return maximo_pos; }

    Otro ejemplo sencillo, calcular el promedio de los valores.

    double promedio(double valores[], int largo) { double suma=0; for (int i=0;i

  • int matriz[3][7]; int tabla[3][4]={ { 1, 2, 3, 4}, { 5, 6, 7, 8}, /* los espacios y saltos de lneas no son tomados en cuenta */ { 9,10,11,12} }; double v[2][2][2]; ... printf("tabla[0][1]: %i\n", tabla[0][3]); // Imprime 4 printf("tabla[2][0]: %i\n", tabla[2][0]); // Imprime 9 ...

    En este ejemplo tabla es un vector de longitud 3, cuyos elementos son vectores de longitud 4 de elementos de tipo int.

    En resumen, suponiendo que v[n] es un vector de cualquier tipo de dato con n cantidad de posiciones, al vector v se le aplican las siguientes reglas:

    1. La primera posicin siempre ser v[0] 2. La ltima posicin es v[n-1] 3. En versiones previas a C99 n es una constante definida antes de la declaracin de v[n]

    Cadenas de caracteres

    Las cadenas de caracteres (tambin llamadas cadenas o strings) son un tipo particular de vectores, son de

    hecho vectores de char, con la particularidad que tienen una marca de fin (el caracter '\0'), adems el

    lenguaje nos permite escribirlas como texto dentro de comillas dobles. Veamos unos ejemplos de su

    declaracin:

    char cadena_hola[]="Hola"; char otro_hola[]={'H','o','l','a','\0'}; // Igual al anterior char vector[]={'H','o','l','a'}; /* Un vector de 4 elementos, con los elementos 'H','o','l' y 'a' */ char espacio_cadena[1024]="Una cadena en C"; char cadena_vacia[]="";

    Cmo vimos anteriormente al declarar un vector se define la cantidad de elementos que puede contener, en

    el caso de las cadenas se debe tener en cuenta el espacio adicional necesario para el \0. Viendo el ejemplo,

    tanto cadena_hola y otro_hola tienen un largo 5 y cadena_vacia tiene un largo de 1.

    Tambin vimos anteriormente que al usar vectores debemos tener en cuenta su largo, y as es que el largo o

    cantidad de elemento lo necesitamos en todas las funciones que definimos usando vectores y lo recibimos

    como un parmetro ms en estas, en el caso de las cadenas al tener una marca de fin podemos prescindir del

    largo y procesar una cadenas hasta llegar a la marca de fin.

    Por ejemplo, la siguiente funcin calcula el largo de una cadena:

    /* devuelve la cantidad de caracteres en cadena sin contar el '\0' */ int largo_cadena(char cadena[]) { int largo=0 while (cadena[largo]!='\0') largo++; return largo;

  • }

    Se debe tener en cuenta que el largo de una cadena y el largo del vector con la que se representa son

    distintos, tanto por como largo_cadena() cuenta el largo de la cadena, como porespacio_cadena del ejemplo

    anterior.

    Algo bastante usual es necesitar unir dos cadenas, veamos un ejemplo:

    bool unir_cadenas(char destino[], char origen[], int largo) { int largo_origen = largo_cadena(origen); int largo_destino = largo_cadena(destino); if ( largo_origen+largo_destino+1 > largo ) { return false; } for (int i=0; i

  • strcpy(descripcion, "Lapiz color "); strncat(descripcion, color, 1024); strncat(descripcion, " de trazo ", 1024); strncat(descripcion, grosor, 1024); // descripcion contiene "Lapiz color rojo de trazo grueso" ...

    void intercambiar(char vector[], int pos1, int pos2); void invierte_cadena(char cadena[]) { int largo = strlen(cadena); for (int i=0; i < (largo/2); i++) { intercambiar(cadena, i, (largo-1)-i); } } void intercambiar(char vector[], int pos1, int pos2) { char aux=vector[pos1]; vector[pos1]=vector[pos2]; vector[pos2]=aux; }

    Manejo de archivos As como hemos revisado la salida y entrada por pantalla y teclado respectivamente, veremos ahora la

    entrada y/o salida de datos utilizando ficheros, lo cual ser imprescindible para un gran nmero de

    aplicaciones que deseemos desarrollar.

    Ficheros

    El estndar de C contiene varias funciones para la edicin de ficheros, estas estn definidas en la

    cabecera stdio.h y por lo general empiezan con la letra f, haciendo referencia a file. Adicionalmente se agrega

    un tipo FILE, el cual se usar como apuntador a la informacin del fichero. La secuencia que usaremos para

    realizar operaciones ser la siguiente:

    Crear un apuntador del tipo FILE *

    Abrir el archivo utilizando la funcin fopen y asignndole el resultado de la llamada a nuestro

    apuntador.

    Hacer las diversas operaciones (lectura, escritura, etc).

    Cerrar el archivo utilizando la funcin fclose.

    fopen

    Esta funcin sirve para abrir y crear ficheros en disco.

    El prototipo correspondiente de fopen es:

    FILE * fopen (const char *filename, const char *opentype);

  • Los parmetros de entrada de fopen son:

    filename: una cadena que contiene un nombre de fichero vlido. opentype: especifica el tipo de fichero que

    se abrir o se crear.

    Una lista de parmetros opentype para la funcin fopen son:

    "r" : abrir un archivo para lectura, el fichero debe existir.

    "w" : abrir un archivo para escritura, se crea si no existe o se sobreescribe si existe.

    "a" : abrir un archivo para escritura al final del contenido, si no existe se crea.

    "rt" : abrir un archivo para lectura y escritura, el fichero debe existir.

    "wt" : crear un archivo para lectura y escritura, se crea si no existe o se sobreescribe si existe.

    "r+b rb+" : Abre un archivo en modo binario para actualizacin (lectura y escritura).

    "rb" : Abre un archivo en modo binario para lectura.

    Adicionalmente hay tipos utilizando "b" (binary) los cuales no sern mostrados por ahora y que solo se usan

    en los sistemas operativos que no pertenecen a la familia de unix.

    fclose

    Esta funcin sirve para poder cerrar un fichero que se ha abierto.

    El prototipo correspondiente de fclose es:

    int fclose (FILE *stream);

    Un valor de retorno cero indica que el fichero ha sido correctamente cerrado, si ha habido algn error, el

    valor de retorno es la constante EOF.

    Un ejemplo pequeo para abrir y cerrar el archivo llamado fichero.in en modo lectura:

    #include int main(int argc, char** argv) { FILE *fp; fp = fopen ( "fichero.in", "r" ); fclose ( fp ); return 0; }

    Como vemos, en el ejemplo se utiliz el opentype "r", que es para la lectura.

    Otra cosa importante es que el lenguaje C no tiene dentro de si una estructura para el manejo de

    excepciones o de errores, por eso es necesario comprobar que el archivo fue abierto con xito "if (fp ==

    NULL)". Si fopen pudo abrir el archivo con xito devuelve la referencia al archivo (FILE *), de lo contrario

    devuelve NULL y en este caso se debera revisar la direccion del archivo o los permisos del mismo. En estos

    ejemplos solo vamos a dar una salida con un retorno de 1 que sirve para sealar que el programa termino por

    un error.

    feof

  • Esta funcin sirve para determinar si el cursor dentro del archivo encontr el final (end of file). Existe otra

    forma de verificar el final del archivo que es comparar el caracter que trae fgetcdel archivo con el

    macro EOF declarado dentro de stdio.h, pero este mtodo no ofrece la misma seguridad (en especial al tratar

    con los archivos "binarios"). La funcin feof siempre devolver cero (Falso) si no es encontrado EOF en el

    archivo, de lo contrario regresar un valor distinto de cero (Verdadero).

    El prototipo correspondiente de feof es:

    int feof(FILE *fichero);

    rewind

    Literalmente significa "rebobinar", sita el cursor de lectura/escritura al principio del archivo.

    El prototipo correspondiente de rewind es:

    void rewind(FILE *fichero);

    Lectura

    Un archivo generalmente debe verse como un string (una cadena de caracteres) que esta guardado en el

    disco duro. Para trabajar con los archivos existen diferentes formas y diferentes funciones. Las funciones que

    podramos usar para leer un archivo son:

    char fgetc(FILE *archivo)

    char *fgets(char *buffer, int tamano, FILE *archivo)

    size_t fread(void *puntero, size_t tamano, size_t cantidad, FILE *archivo);

    int fscanf(FILE *fichero, const char *formato, argumento, ...);

    Las primeras dos de estas funciones son muy parecidas entre si. Pero la tercera, por el numero y el tipo de

    parmetros, nos podemos dar cuenta de que es muy diferente, por eso la trataremos aparte junto

    al fwrite que es su contraparte para escritura.

    fgetc

    Esta funcin lee un caracter a la vez del archivo que esta siendo sealado con el puntero *archivo. En caso de

    que la lectura sea exitosa devuelve el caracter ledo y en caso de que no lo sea o de encontrar el final del

    archivo devuelve EOF.

    El prototipo correspondiente de fgetc es:

    char fgetc(FILE *archivo);

    Esta funcin se usa generalmente para recorrer archivos de texto. A manera de ejemplo vamos a suponer que

    tenemos un archivo de texto llamado "prueba.txt" en el mismo directorio en que se encuentra el fuente de

    nuestro programa. Un pequeo programa que lea ese archivo ser:

    #include #include int main() { FILE *archivo; char caracter; archivo = fopen("prueba.txt","r");

  • if (archivo == NULL){ printf("\nError de apertura del archivo. \n\n"); }else{ printf("\nEl contenido del archivo de prueba es \n\n"); while (feof(archivo) == 0) { caracter = fgetc(archivo); printf("%c",caracter); } } fclose(archivo); return 0; }

    fgets

    Esta funcin est diseada para leer cadenas de caracteres. Leer hasta n-1 caracteres o hasta que lea un

    cambio de lnea '\n' o un final de archivo EOF. En este ltimo caso, el carcter de cambio de lnea '\n' tambin

    es ledo.

    El prototipo correspondiente de fgets es:

    char *fgets(char *buffer, int tamao, FILE *archivo);

    El primer parmetro buffer lo hemos llamado as porque es un puntero a un espacio de memoria del tipo char

    (podramos usar un arreglo de char). El segundo parmetro es tamao que es el limite en cantidad de

    caracteres a leer para la funcion fgets. Y por ultimo el puntero del archivo por supuesto que es la forma en

    que fgets sabra a que archivo debe leer.

    #include #include int main() { FILE *archivo; char caracteres[100]; archivo = fopen("prueba.txt","r"); if (archivo == NULL) exit(1); printf("\nEl contenido del archivo de prueba es \n\n"); while (feof(archivo) == 0) { fgets(caracteres,100,archivo); printf("%s",caracteres); } system("PAUSE");

  • fclose(archivo); return 0; }

    Este es el mismo ejemplo de antes con la diferencia de que este hace uso de fgets en lugar de fgetc. La

    funcin fgets se comporta de la siguiente manera, leer del archivo apuntado por archivo los caracteres que

    encuentre y a ponerlos en buffer hasta que lea un caracter menos que la cantidad de caracteres especificada

    en tamao o hasta que encuentre el final de una linea (\n) o hasta que encuentre el final del archivo (EOF). En

    este ejemplo no vamos a profundizar mas que para decir que caracteres es un buffer, los pormenores seran

    explicados en la seccin de manejo dinmico de memoria.

    El beneficio de esta funcin es que se puede obtener una linea completa a la vez. Y resulta muy til para

    algunos fines como la construccin de un parser de algn tipo de archivo de texto.

    fread

    size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

    Esta funcin lee un bloque de una "stream" de datos. Efecta la lectura de un arreglo de elementos "count",

    cada uno de los cuales tiene un tamao definido por "size". Luego los guarda en el bloque de memoria

    especificado por "ptr". El indicador de posicin de la cadena de caracteres avanza hasta leer la totalidad de

    bytes. Si esto es exitoso la cantidad de bytes ledos es (size*count).

    PARAMETROS:

    ptr : Puntero a un bloque de memoria con un tamao mnimo de (size*count) bytes.

    size : Tamao en bytes de cada elemento (de los que voy a leer).

    count : Nmero de elementos, los cuales tienen un tamao "size".

    stream: Puntero a objetos FILE, que especifica la cadena de entrada.

    fscanf

    La funcin fscanf funciona igual que scanf en cuanto a parmetros, pero la entrada se toma de un fichero en

    lugar del teclado.

    El prototipo correspondiente de fscanf es:

    int fscanf(FILE *fichero, const char *formato, argumento, ...);

    Podemos ver un ejemplo de su uso, abrimos el documento "fichero.txt" en modo lectura y leyendo dentro de

    el.

    #include int main ( int argc, char **argv ) { FILE *fp; char buffer[100]; fp = fopen ( "fichero.txt", "r" );

  • fscanf(fp, "%s" ,buffer); printf("%s",buffer); fclose ( fp ); return 0; }

    Escritura

    As como podemos leer datos desde un fichero, tambin se pueden crear y escribir ficheros con