Logo Studenta

Programacion_en_c (1)

¡Este material tiene más páginas!

Vista previa del material en texto

Programación en C/Texto completo
1 Prólogo
El avance de la tecnología y la concurrente entrega de
información, nos permite generar una edición, variable
y alternativa en la enseñanza del lenguaje de programa-
ción que más impacto social ha tenido en la historia de
la informática. Este libro ha sido forjado con la incansa-
ble 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, con-
tinú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 en-
señ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 quienes ya dominan
el lenguaje como una introducción sencilla para quienes
están empezando a conocerlo.
Viajaremos por la historia del lenguaje, veremos su pro-
pósito e indagaremos en la ciencia de la programación.
El fin es otorgar al lector una doctrina clara de la progra-
mación y el lenguaje C; lo induciremos a conseguir un
manejo importante del lenguaje.
1.1 ¿Para quién es este libro?
Este libro está dirigido a todos los que deseen obtener co-
nocimientos 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 en-
focamos 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 de su plan de estudios.
1.2 ¿Por qué otro manual de C?
Porque el lenguaje C es la base fundamental de la pro-
gramación. Para quienes están en el ambiente de la in-
formática es crucial tener por lo menos nociones de este
lenguaje. Varios sistemas operativos, cientos de bibliote-
cas, 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 no-
sotros disfrutamos hoy fueron construidos por personas
como nosotros, que empezaron con nuestro mismo po-
tencial 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 do-
cumentació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 per-
mita a los interesados aprender a programar en C.
2 Enlaces
Nociones básicas de programación (generales, indepen-
dientes del lenguaje):
• Fundamentos de programación
Wikilibro similar a éste en inglés
• C Programming
esquema de operadores y expresiones
•
3 Licencia y autores
• Copyright © 2004 Envite
• Copyright © 2005 Alejandro Moreno Calvo
• Copyright © 2006 Andreu Correa Casablanca
• Copyright © 2009 zerohours
Ver el historial de cada página para el resto de autores.
4 ¿Cómo contribuir a este WikiLi-
bro?
Contribuir con este libro es muy simple primero deberías
registrarte un usuario y/o entrar (esto no es necesario pe-
ro si muy conveniente) a Wikilibros, para que podamos
identificar tus ediciones. Luego, si nunca has contribuido
1
https://es.wikibooks.org/wiki/Fundamentos_de_programaci%C3%B3n
https://en.wikibooks.org/wiki/C%2520Programming
https://es.wikibooks.org/wiki/Usuario:Envite
https://es.wikibooks.org/wiki/Usuario:Almorca
https://es.wikibooks.org/wiki/Usuario:CaStarCo
https://es.wikibooks.org/wiki/Usuario:Zerohours
https://es.wikibooks.org/wiki/Especial:Entrar
2 9 PARA LOS MÁS AVANZADOS
en un proyecto de wikipedia o en otro wiki deberías leer
el manual de uso de wikilibros.
Una vez hecho esto todo lo que tienes que hacer es agre-
gar el contenido que consideres necesario para el libro.
Para editar cualquier sección basta con hacer click al link
que dice editar en la pestaña en la parte superior de la pa-
gina, seria bueno revisar (antes de editar cualquier cosa)
la pestaña de discusión que está ahí para ser usada. Ten
en cuenta que el material que ya está fue escrito por per-
sonas que deseaban contribuir igual que tú, así que trata
de respetarlo. Aunque con esto no me refiero a que si se
necesita alguna corrección, reorganización, quitar partes
que sean ambiguas, no dejes de hacerlo. Lo mejor sería
que todos contribuyéramos de cualquier manera al libro.
Además, es recomendable consultar la página de discu-
sión del libro y la del articulo en particular que quieras
modificar, ya que de esta manera se pueden coordinar es-
fuerzos.
Recuerda que todo el contenido que añadas al libro es
publicado bajo la licencia GFDL, por lo que no uses ma-
terial que no haya sido escrito por ti o que no esté ya pu-
blicado 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.
5 Objetivos
El objetivo principal de este Wikilibro es que cualquier
persona sin conocimientos previos de programación pue-
da 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 más com-
plejos que superen a los temas básicos. También les será
más o menos sencillo aprender cualquier otro lenguaje de
programación estructurada.
Sin embargo, este no es un libro que apunte únicamente
a programadores principiantes. También puede resultar
de interés para quienes ya tengan experiencia en el área
de programación. En esta introducción 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 pro-
gramación que emplea pocas instrucciones en lenguaje
máquina para traducir elementos del código. Esto reduce
los tiempos de ejecución de los programas.
6 Nota sobre la exactitud
Muchas de las cosas expresadas en este wikilibro, espe-
cialmente en los primeros capítulos, no son completa-
mente exactas, aunque son buenas aproximaciones. Los
detalles más exactos irán apareciendo posteriormente,
una vez que los materiales anteriores hayan sido correcta-
mente asimilados por el lector. En general, dadas dos de-
finiciones o datos contradictorios en este wikilibro, debe
considerarse siempre como más exacto al segundo, ha-
biendo aparecido el primero como una introducción más
general al tema.
7 Estándar utilizado
El lenguaje C fue creado en los años setenta, y a lo largo
de su historia ha pasado pormuchasmodificaciones, tanto
con respecto a la sintaxis como con respecto al código
incluido dentro de la biblioteca estándar. Es por ello que
se fueron desarrollando estándares, para que todos sepan
con qué versión del lenguaje se está trabajando.
Los distintos estándares del lenguaje C han sido: el C
de Kernighan y Ritchie, un estándar no-oficial que sur-
gió luego de la publicación de su libro en 1978; el C89 o
C90, el primer estándar oficial, posterior a la publicación
de los estándares ANSI en 1989 e ISO en 1990; y el C99,
publicado en 1999.
En este libro se utilizará el estándar C99, si bien por cues-
tiones de estilo y compatibilidad muchas veces se utiliza-
rá código compatible con el estándar C89.
8 Para los principiantes
Para quien no haya programado antes, es recomendable
seguir el orden del libro. Los temas están especialmen-
te organizados de manera incremental o acumulativa. Tal
vez, lo que se te va a hacermás útil en el camino del apren-
dizaje es la constancia; sé terco, no trastabilles, no te rin-
das, tal vez tu pregunta sea ¿cuántas veces tengo que in-
tentar?, las veces necesarias para lograr tu objetivo, sería
la respuesta.
Claro que el principal enemigo de nosotros los humanos
es el tiempo y por eso en caso de que de verdad estés
trancado en algo busca ayuda de alguien que sepa “másque tú". ¿Que no tienes a nadie a tu alrededor con esa
característica? Tal vez no buscaste bien y tal vez quieras
usar la red de redes. Utiliza los buscadores, pregunta en
IRC, en foros de programación, en listas de correo.
9 Para los más 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 sólo aquellos que te sean necesarios.
https://es.wikibooks.org/wiki/Wikilibros:Manual
https://es.wikibooks.org/wiki/Discusi%C3%B3n:Programaci%C3%B3n_en_C
https://es.wikibooks.org/wiki/Discusi%C3%B3n:Programaci%C3%B3n_en_C
https://es.wikipedia.org/wiki/Licencia%2520de%2520documentaci%C3%B3n%2520libre%2520de%2520GNU
http://creativecommons.org/licenses/by-sa/3.0/deed.es
http://creativecommons.org/licenses/by-sa/3.0/deed.es
https://es.wikipedia.org/wiki/Lenguaje%2520de%2520programaci%C3%B3n%2520C
https://es.wikipedia.org/wiki/Programaci%C3%B3n%2520estructurada
3
10 Requisitos
Se presupone que los lectores tienen conocimientos ele-
mentales de informática a nivel de usuario, y son capaces
de instalar un compilador del lenguaje C en sus sistema.
Los detalles sobre la instalación se verán en la sección
Herramientas.
Con respecto al Hardware, sólo será necesario contar con
una PC con sistema operativo, donde sea posible instalar
un compilador, y en lo posible un entorno de desarro-
llo. Cuanto mejor sea la computadora, más rápido será
el proceso de compilación y ejecución de los programas.
Sin embargo, cualquier PC sirve para aprender con los
ejemplos de este libro.
Para quienes no tengan conocimientos básicos de progra-
mación, puede ser una buena idea comenzar leyendo los
primeros capítulos del Wikilibro Fundamentos de pro-
gramación, ya que algunos temas explicados en ese libro
se asumen ya conocidos.
Finalmente, un requisito imprescindible en todo progra-
mador es tener sentido común. Muchas veces se pueden
adoptar mejores o peores soluciones ante los diversos
problemas, y la decisión de cuál elegir pasa por la apli-
cación del sentido común.
11 Herramientas
Para programar tanto en C, como en C++, Java o cual-
quier otro lenguaje de programación, necesitamos contar
con aplicaciones o herramientas que nos permitan poner
en funcionamiento nuestro programa.
El lenguaje de programación C es compilado, así que en
este caso necesitaremos un compilador, que será el en-
cargado de transformar nuestro código fuente en código
que la computadora pueda ejecutar.
Además, para facilitar la tarea de los programadores exis-
ten los denominados Entorno de desarrollo integrados
(IDE). Enmuchos casos, estos entornos incluyen un com-
pilador, un depurador, y otras herramientas.
Las herramientas a instalar dependerán del sistema ope-
rativo utilizado. A continuación se listan algunas posibili-
dades para el sistema operativo Windows o GNU/Linux,
no es imprescindible utilizar estas herramientas en parti-
cular, cualquier compilador puede servir.
12 Windows
Uno de los entornos de desarrollo más conocidos en-
tre los programadores de C sobre Windows, tanto no-
vatos como expertos, es el Bloodshed Dev-C++, que es
un entorno libre multiplataforma. Tal entorno de desa-
rrollo fue abandonado y retomado mejorándolo pasando
a llamarse WxDev-C++. Otro entorno libre y gratuito es
el Code::Blocks. Ambos entornos pueden utilizarse tanto
para C como para C++.
También hay otras alternativas privativas como los com-
piladores de Borland o de Microsoft (Microsoft Visual
C++).
13 GNU/Linux
En los sistemas GNU/Linux, será necesario tener insta-
ladas las herramientas gcc y make y la versión 6 de la
glibc con su documentación, que son las que permitirán
compilar los programas.
Para escribir y modificar el código, es posible utilizar
cualquier editor de texto plano (en lo posible que cuen-
te con resaltado de sintaxis), como son emacs, vim, kate,
gedit o geany.
Sin embargo, para quienes son novatos en la programa-
ción, es recomendable utilizar un entorno de desarrollo
como son el Anjuta DevStudio (para el entorno GNO-
ME) o KDevelop (para el entorno KDE), ya que inclu-
yen facilidades adicionales para la ejecución y solución
de problemas.
Los programas mencionados se incluyen dentro de la ins-
talación estándar de la mayoría de las distribuciones ac-
tuales de GNU/Linux, de modo que para instalarlos sólo
será necesario seguir el procedimiento usual de instala-
ción de aplicaciones para la distribución deseada.
El lenguaje de programación C fue creado por Dennis
Ritchie entre 1969 y 1973 cuando trabajaba en Bell La-
boratories de AT&T junto con Ken Thompson en el dise-
ño 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 código po-
día ser utilizado en las distintas plataformas, propician-
do la reutilización de código 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.
Además, con el paso del tiempo se han desarrollado cien-
tos de bibliotecas que permiten a los programadores de
C utilizar el código desarrollado por otros para la realiza-
ción de tareas comunes. Esto, a su vez, ha propiciado el
desarrollo de aplicaciones en lenguaje C.
Actualmente es imposible contar la cantidad de aplica-
ciones y herramientas desarrolladas en C.
https://es.wikibooks.org/wiki/Fundamentos_de_programaci%C3%B3n
https://es.wikibooks.org/wiki/Fundamentos_de_programaci%C3%B3n
http://wxdsgn.sourceforge.net/
http://www.codeblocks.org/
https://es.wikipedia.org/wiki/Glibc
https://es.wikipedia.org/wiki/Dennis%2520Ritchie
https://es.wikipedia.org/wiki/Dennis%2520Ritchie
4 16 DEFINICIONES
14 Evolución
A mediados de los años 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 recodificarUNIX (escrito
hasta ese momento en lenguaje ensamblador) usando un
lenguaje de alto nivel más portable y flexible.
Durante los siguientes años, Dennis Ritchie modificó el
lenguaje B, llegando a crear el lenguaje C y reescribiendo
el sistema UNIX en dicho lenguaje; añadió características
nuevas, como son el diseño de tipos y las estructuras de
datos.
En 1978, Dennis Ritchie y Brian Kernighan publicaron
la primera edición del libro El lenguaje de programación
C. Este libro fue durante años la especificación informal
del lenguaje. El lenguaje descrito en la primera edición
de este libro, fue conocido como “el C de Kernighan y
Ritchie” o simplemente “K&R C”. En este libro se in-
trodujeron nuevas características al lenguaje: los tipo de
datos struct, long int y unsigned int; los operadores =+ y
=- fueron sustituidos por += y -=.
Amediados de los años 80, Bjarne Stroustrup (también de
los laboratorios Bell), crea el lenguaje C++, un lenguaje
basado en C, con numerosas características 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 más asociado a C.
En los años siguientes a la publicación del C de Kernighan
y Ritchie, se añadieron al lenguaje muchas característi-
cas no oficiales, que estaban presentes en algunos com-
piladores y no en otros. Fue por ello que en 1989 ANSI
(American National Standards Institute) publicó el pri-
mer estándar oficial de C, que es conocido como ANSI
C.
En este estándar se tomaron muchas de las funcionali-
dades no oficiales y se agregaron funcionalidades nuevas
como los prototipos de función, y un preprocesador me-
jorado. También se cambió la sintaxis de la declaración
de parámetros de funciones, para que incluyeran el tipo
junto con el nombre.
Al año siguiente,en 1990 se publicó la estandarización
ISO del lenguaje. Este estándar es básicamente el estándar
ANSI, con unas pocas modificaciones de formato. A este
estándar se lo conoce, entonces, como C89, o C90, y se
trata del mismo lenguaje.
Basándose en el estándar ANSI que estaba en prepara-
ción, en 1988 Kernighan y Ritchie publicaron la segunda
edición de su libro, que es aún hoy utilizada como una de
las referencias principales del lenguaje.
Durante los siguientes años, el lenguaje C permaneció sin
demasiados cambios. Sin embargo, como había sucedi-
do antes, los distintos compiladores fueron incorporando
características adicionales, que otros compiladores no te-
nían, siendo C++ la principal influencia.
Fue por ello que a finales de los noventa se decidió revisar
el estándar de C, lo que llevó a la publicación del estándar
C99. Este estándar incluye varias nuevas características
como son: las funciones inline; la posibilidad de declarar
variables en cualquier parte del código; los comentarios
de una sola línea utilizando //; los tipos de datos long long
int, bool y complex, entre otras.
Aún hoy el proceso de evolución del lenguaje sigue avan-
zando, y desde 2007 se está trabajando en el armado de
un nuevo estándar.
15 Más información
• Lenguaje de programación BCPL
• Historia del lenguaje del programación C
• The Development of the C Language
En este capítulo veremos un resumido listado de concep-
tos básicos, esta información puede encontrarse en forma
más elaborada en el WikiLibro Fundamentos de progra-
mación.
16 Definiciones
• Se denomina algoritmo a una secuencia de instruc-
ciones que permiten obtener un resultado en parti-
cular. No necesariamente son programas de compu-
tadora, una receta de cocina, o las instrucciones para
cambiar un neumático son ejemplos de algoritmos
de la vida real.
• Las computadoras, son maquinas sin inteligencia
propia, cuya única finalidad es interpretar el código
que se les provee.
• El lenguaje de máquina es el único lenguaje que la
computadora “entiende” y es capaz de ejecutar.
• Los lenguajes de programación son el medio de
comunicación entre el programador y una compu-
tadora. El programador escribe en algún lenguaje
de programación y utiliza las herramientas provis-
tas por ese lenguaje para transformarlo en lenguaje
de máquina.
• Finalmente, denominamos programa a una secuen-
cia de órdenes a ser ejecutadas por una computado-
ra. Un programa debe estar escrito en algún lenguaje
de programación, y puede incluir uno o más algorit-
mos.
https://es.wikipedia.org/wiki/Martin%2520Richards
https://es.wikipedia.org/wiki/BCPL
https://es.wikipedia.org/wiki/Ken%2520Thompson
https://es.wikipedia.org/wiki/Lenguaje%2520de%2520programaci%C3%B3n%2520B
https://es.wikipedia.org/wiki/Bjarne%2520Stroustrup
https://es.wikipedia.org/wiki/C++
https://es.wikipedia.org/wiki/BCPL
https://es.wikipedia.org/wiki/Lenguaje%2520de%2520programaci%C3%B3n%2520C#Historia
http://cm.bell-labs.com/cm/cs/who/dmr/chist.html
https://es.wikibooks.org/wiki/Fundamentos_de_programaci%C3%B3n
https://es.wikibooks.org/wiki/Fundamentos_de_programaci%C3%B3n
https://es.wikipedia.org/wiki/Algoritmo
https://es.wikipedia.org/wiki/Computadora
https://es.wikipedia.org/wiki/Lenguaje%2520de%2520m%C3%A1quina
https://es.wikipedia.org/wiki/Lenguaje%2520de%2520programaci%C3%B3n
https://es.wikipedia.org/wiki/Programa_(computaci%C3%B3n)
5
17 Tipos de lenguajes
Existe una gran cantidad de lenguajes de programación,
que están pensados para distintas finalidades, siguen dis-
tintos paradigmas, y de una u otra forma se diferencian
de los demás.
17.1 Esquemas de programación
El esquema de programación llamado Programación
Imperativa, consiste en escribir una secuencia de ins-
trucciones una detrás de la otra, que se ejecutarán en or-
den. Algunas de esas instrucciones pueden hacer que la
máquina pase a una instrucción que no sea la siguiente,
tal vez porque se cumpla una condición que hayamos es-
tablecido.
En los últimos años ha tomado fuerza otro paradigma de
computación, llamado Programación Orientada a Ob-
jetos , en el cual se intentan modelar los sistemas creados
como extensiones de la realidad mediante la definición
de “objetos” que modelan entidades de la vida real y que
interactúan entre sí mediante “mensajes” llamadas méto-
dos.
El lenguaje C es un lenguaje imperativo, no orientado a
objetos.
17.2 Alto o bajo nivel
Por otro lado, los lenguajes de programación se clasifican
en niveles. Un lenguaje es de más bajo nivel cuanto más
cercano esté al código de máquina, y un lenguaje que es
de más alto nivel cuanto más lejano esté de la máquina y
más cercano al lenguaje humano.
C es un lenguaje de alto nivel aunque tiene muchas ca-
racterísticas de lenguaje de bajo nivel (como el uso que
permite hacer de la memoria). Estas características ha-
cen que C sea un lenguaje muy potente, ya que permite
optimizar al máximo los recursos de la máquina. Por en-
de, esto también 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 más 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.
17.3 Compilados o interpretados
Otra forma de clasificar a los lenguajes de programación
que es según la forma en que se ejecutan sus órdenes.
Existen los lenguajes que son interpretados, cuyas ór-
denes pasan a través de un intérprete que se encarga de
ejecutarlas (a partir del código fuente) en el mismo mo-
mento en que están siendo leídas. Algunos de los lengua-
jes interpretados son Python, Perl o Tcl, entre muchos
otros.
La contraparte de los lenguajes interpretados son los len-
guajes compilados (como el mismo C) que se diferen-
cian en que las órdenes son transformadas a lenguaje de
máquina que se almacena en un archivo ejecutable. Ese
archivo puede ejecutarse luego, sin recurrir al compila-
dor.
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 más alto nivel.
18 Estructura de la memoria
Parte de esta potencia de C viene de que permite acceder
con mucha libertad a la memoria de la máquina. Para en-
tender un poco cómo es posible, debemos entender cómo
se guardan los datos en la memoria.
Imaginemos que la memoria tiene un montón de casillas,
una enorme fila de casillas, cada una de las cuales contiene
un dígito binario (bit):
0101001010100001010101001010000100111010110010010101001011010110001101010110101010110111...
Es exactamente así, pero es más cómodo recordar que
esos bits se encuentran agrupados de ocho en ocho, for-
mando octetos (bytes):
Cada octeto puede contener 28 = 256 combinaciones
distintas de ceros y unos, es decir, cualquier número entre
0 y 255:
También podemos representar estos números en base he-
xadecimal:
O considerarlos caracteres, mediante alguna codificación:
Este es el tipo de datomás elemental que nos podemos en-
contrar en C: el caracter. Un caracter ocupa exactamente
un byte (8 bits) de memoria, y puede contener un número
entre 0 y 255, o entre −128 y 127, dependiendo si que-
remos considerarlo como sin signo o con él.
En el libro “El Lenguaje de Programación C”, Kernighan
y Ritchie introdujeron al lenguaje C utilizando un sencillo
programa que mostraba un saludo por la pantalla. Desde
entonces se hizo tradición empezar con cualquier lenguaje
de programación 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 programación en C.
Ejemplo: Hola mundo
/* Inclusión de archivos */ #include <stdio.h> /* Función
principal */ int main (int argc,char **argv) { /* Impre-
sión por pantalla y salida del programa*/ printf(“Hola
mundo\n”); return 0; }
Para poder editar y ejecutar este programa será necesa-
rio utilizar algún editor y luego un compilador, como se
https://es.wikipedia.org/wiki/Paradigma%2520de%2520programaci%C3%B3nhttps://es.wikipedia.org/wiki/Programaci%C3%B3n_imperativa
https://es.wikipedia.org/wiki/Programaci%C3%B3n_imperativa
https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos
https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos
https://es.wikipedia.org/wiki/Lenguaje_de_bajo_nivel
https://es.wikipedia.org/wiki/Lenguaje_de_alto_nivel
https://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_Java
https://es.wikipedia.org/wiki/C_Sharp
https://es.wikipedia.org/wiki/Python
https://es.wikipedia.org/wiki/Ruby
https://es.wikipedia.org/wiki/Lenguaje_interpretado
https://es.wikipedia.org/wiki/Python
https://es.wikipedia.org/wiki/Perl
https://es.wikipedia.org/wiki/Tcl
https://es.wikipedia.org/wiki/Lenguaje_compilado
https://es.wikipedia.org/wiki/Bit
https://es.wikipedia.org/wiki/Byte
https://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_caracteres
https://es.wikipedia.org/wiki/Hola%2520mundo
6 20 COMPILACIÓN DE PROGRAMAS SEGÚN LA PLATAFORMA
explicó en la sección Herramientas necesarias.
Si se tiene el compilador gcc en un entorno UNIX o
GNU/Linux, la forma sencilla de compilar y ejecutar se-
rá:
$ gcc holamundo.c $ ./a.out Hola Mundo $
Es decir que el compilador genera un archivo, en este ca-
so llamado a.out, y la salida generada por ese archivo es
“Hola mundo”. A continuación una explicación detallada
sobre el proceso de compilación del programa, y luego un
análisis línea por línea del contenido de este ejemplo.
19 Pre-requisitos para la compila-
ción de programas
Como ya se mencionó, será necesario tener instalado el
compilador y un editor o entorno de desarrollo que permi-
tan escribir el código a compilar. Para más información
ver la sección Herramientas necesarias.
El código a compilar debe guardarse con un nombre que
represente al programa en cuestión y la extensión .c. En
el caso del ejemplo del Hola mundo, el archivo puede lla-
marse hola.c.
En las explicaciones a continuación, se asume que se
cuenta con un compilador instalado y se ha editado un
archivo hola.c que se quiere compilar. Si tu sistema ope-
rativo no aparece en esta lista busca en internet, ya que
seguro que existe algún compilador para ese sistema.
20 Compilación de programas se-
gún la plataforma
20.1 Windows
Para compilar un programa C en entornos Windows, de-
bemos seguir una serie de pasos que varían según el com-
pilador de C que queramos utilizar. Antes que nada, se-
ría bueno que se revises la documentación del compilador
elegido para conocer los comandos exactos.
20.1.1 Compilación del código fuente
Si se utiliza un entorno de desarrollo, será posible com-
pilar directamente desde el entorno, mediante un botón o
una combinación de teclas.
Si se ejecuta el compilador desde la línea de comandos, la
línea será distinta según el compilador utilizado. A con-
tinuación algunos ejemplos de ciertos comandos según 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 código 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 fun-
ción, aunque es posible pedirles que no lo hagan mediante
parámetros adicionales.
Según el compilador y la configuración utilizada, se ob-
tendrán 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 có-
digo ejecutable, el programa en sí. Al ejecutarlo se pro-
ducirá la salida deseada en una ventana de consola.
20.1.2 Salida por pantalla
Si ejecutamos en entorno Windows el programa directa-
mente desde el navegador de archivos, o también desde
algunos entornos de desarrollo, lo que sucederá será que
apenas abierta la ventana de la consola, se mostrará la ca-
dena esperada y luego de terminada la función, la conso-
la se cerrará sin tener el tiempo suficiente de ver nuestro
mensaje en pantalla.
Para poder ver la salida por pantalla será necesario ejecu-
tar el programa desde la línea de comandos, o modificar
la configuración del entorno de desarrollo para que mues-
tre la salida por pantalla al ejecutar el programa.
Una posible solución es agregar una función adicional a
nuestro “hola.c":
/* Inclusión de archivos */ #include <stdio.h> #include
<stdlib.h> /* Función principal */ int main (int argc,char
**argv) { /* Impresión por pantalla y salida del progra-
ma*/ printf(“Hola mundo\n”); system (“pause”); return
0; }
Las dos líneas agregadas permiten que utilicemos la bi-
blioteca stdlib, que incluye la función system y que me-
diante esta función se ejecute el comando pause del siste-
ma, que evita que el programa siga hasta que se presione
una tecla.
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Herramientas
https://es.wikipedia.org/wiki/compilador
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Herramientas
7
Así es posible visualizar que la salida de hola.c se com-
pletó perfectamente.
20.2 GNU
Si bien existen otros compiladores, lo más usual y más
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 compilación
desde línea de comandos o desde el entorno gráfico.
Para realizarla desde línea de comandos, será necesa-
rio 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 código, este comando nos
creará un archivo ejecutable, que por omisión se llama
“a.out”, y que podemos ejecutar desde la línea de coman-
dos de la siguiente forma:
./a.out Hola mundo
Es una buena idea especificar el nombre que el archivo
ejecutable tendrá, pasando como parámetro al compila-
dor la opción -o, de la siguiente forma:
gcc hola.c -o hola
Con lo cual, el nombre del archivo creado será hola. Este
archivo no tiene extensión ya que es la forma usual de
llamar a los archivos ejecutables en los entornos UNIX y
GNU/Linux, sin embargo funcionaría de la misma forma
si se llamara hola.exe.
Para ejecutarlo, haremos los mismo que en el caso ante-
rior:
./hola Hola mundo
Existen otros parámetros que podemos especificar al
compilador en la línea de comandos, dependiendo del ti-
po de programa, y en función de la complejidad del mis-
mo. Por ejemplo, podemos agregar las siguientes opcio-
nes:
gcc hola.c -o hola -Wall -pedantic
La opción -Wall nos mostrará todos los avisos que pro-
duzca el compilador, no solamente los errores. Los avisos
nos indican dónde y/o porqué podría surgir algún error en
nuestro programa.
La opción -pedantic nos aporta más información sobre
los errores y los avisos mostrados por GCC.
21 Diseccionando el “Hola Mun-
do”
A continuación veremos cuál es la estructura básica de un
programa en C, para poder entender qué hace cada una
de las líneas de nuestro sencillo programa.
Es probable que lo primero que salte a la vista sea la línea:
printf(“Hola mundo\n”);
Esta es la línea que hace aparecer la cadena Hola Mundo
en nuestra pantalla. Notamos que en C la sentencia para
imprimir algo por pantalla es printf() y, además, hay que
colocar paréntesis alrededor de lo que queremos imprimir
para utilizarla.
Esto se debe a que en C, printf es una función, que impri-
me su argumento (la cadena Hola Mundo\n) en la pan-
talla. Se denomina invocar una función a la acción de
utilizarla para que realice una acción.
Podemos observar también que la cadena a imprimir ter-
mina con una extraña combinación: \n. La combinación
\n no representa a dos caracteres independientes, sino que
representa un único carácter no imprimible: el salto de
línea. Sin el salto de línea, el resultado al ejecutar el pro-
grama sería:
$ ./a.out Hola Mundo$
Es decir queno hay salto de línea entre la cadena impresa,
y la siguiente entrada de la línea de órdenes, que no es lo
que esperábamos.
Lo último a notar en la línea es que termina con un punto
y coma. En C, todas las sentencias terminan con un punto
y coma. Al principio puede parecer obvio dónde termina
una sentencia, pero ya veremos más 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 instrucción return dentro de la función main, el re-
sultado es que se finaliza el programa, comunicándole
al sistema operativo que el valor de retorno (un código
numérico que el sistema utiliza para saber si el progra-
ma 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 ejecutarán siempre de forma
correlativa.
¿Y qué es esa línea que precede (en realidad, que da nom-
bre) al bloque?
int main (int argc, char **argv)
8 24 ENTEROS
Pues es la definición de una función, en este caso llama-
da main. En C (y en general en todos los lenguajes de
programación estructurada) todo se hace a base de fun-
ciones, como main y printf.
La función main es especial, porque es el la que se invoca
cuando se ejecuta el programa. Todos los programas en C
comienzan su ejecución al principio de la función main,
y cuando ésta acaba, el programa también.
Veamos con más detalle la definición de la función:
int main (int argc, char **argv) { ... }
• El nombre de la función que viene a continuación,
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 argu-
mentos respectivamente).[1]
• La función devuelve como resultado un número en-
tero, int (que es el 0 de la instrucción return).[2]
Finalmente, y un tanto aparte (está separada del resto por
una línea en blanco), tenemos la línea:
#include <stdio.h>
Que parece bastante distinta al resto del programa, y que,
además, parece no tener sentido, puesto que ya hemos
definido la función main que hace todo el trabajo.
Efectivamente, esa línea no es parte del programa, aun-
que sea imprescindible. La línea es una instrucción del
preprocesador de C, como nos lo indica el símbolo #, 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 compilación. El fichero stdio.h es el que con-
tiene la definición de la función printf(), que antes utili-
zamos pero que no escribimos, ya que forma parte de la
biblioteca estándar de C.
22 Comentarios
Una vez escrito un código, tratar de entenderlo un año
más tarde solo con leerlo puede ser frustrante: no hay ma-
nera de saber (si el programa es medianamente compli-
cado) qué es cada variable, o qué hace cada bloque de
código. Por esto, en cualquier lenguaje de programación
son importantes los comentarios.
Un comentario en C es todo lo que se encuentre entre los
símbolos /* y */. Hay que tener en cuenta que los comen-
tarios 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 len-
guaje C++, e incorporadas al estándar de C a partir de
C99: //. Todo lo que esté después de estos signos, has-
ta el final de la línea, se considerará un comentario y el
compilador no lo tomará en cuenta.
En el ejemplo presentado pueden verse tres líneas con
comentarios, que documentan someramente las distin-
tas funcionalidades del código. En los próximos capítulos
podrán verse mejores usos de los comentarios dentro del
código.
También podría decirse que es una herramienta básica
basada en compilador
[1] En un capítulo posterior podrá ver un ejemplo del uso de
los parámetros que recibe main.
[2] Es importante señalar que el estándar dice que main de-
berá definirse como función que retorna un entero, o de
lo contrario el resultado queda indefinido.
23 Historia
En el lenguaje C estandarizado como C89, existían cuatro
tipos de datos básicos que son: los números enteros, los
números reales, los caracteres, y los punteros. A partir del
estándar C99 se agregan: los valores lógicos (verdadero
o falso) y los números complejos.
Estos tipos de datos son parte del lenguaje, y por ello se
los considera primitivos. Más adelante veremos que con
el uso de estructuras y uniones es posible crear tipos com-
puestos de datos a partir de estos tipos primitivos.
En este capítulo veremos los enteros, los reales y los ca-
racteres. Más adelante se verán otros tipos de datos más
complejos, como son los vectores, las cadenas de carac-
teres, y los punteros en general.
24 Enteros
Los enteros son el tipo de dato más primitivo en C. Se
usan para representar números enteros. Pero siempre se
pueden encontrar otras aplicaciones para los números en-
teros. En general se pueden usar para representar cual-
quier variable discreta.
Los tipos de datos enteros son: short, int, long y long long,
cada uno representando un número entero de un tamaño
o capacidad determinado. Según el compilador y la plata-
forma de hardware, cada uno de estos tipos de dato puede
ocupar desde 1 byte hasta 8 bytes en memoria (para más
detalles busca en la referencia).
Además, el lenguaje C hace la distinción 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:
https://es.wikipedia.org/wiki/Preprocesador
https://es.wikipedia.org/wiki/Biblioteca%2520est%C3%A1ndar%2520de%2520C
https://es.wikipedia.org/wiki/C++
https://es.wikipedia.org/wiki/Tipo%2520de%2520dato%2520l%C3%B3gico
https://es.wikipedia.org/wiki/Tipo%2520primitivo
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Estructuras_y_Uniones
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Referencia
9
int a; unsigned int a; signed long a; signed long long a =
10000000;
Todos los números son representados en memoria me-
diante una cadena de bits. En el caso de los números con
signo, el bit más significativo es el que se usa para re-
presentar el signo. La representación de los números ne-
gativos se realiza mediante el complemento a dos, que
es una técnica que permite operar con los números nega-
tivos de forma lógica.
A modo de ejemplo, la representación en memoria del
número −8 en una variable de 2 bytes, entera, con signo,
sería la siguiente:
1111111111111000
25 Flotantes
Se denomina flotantes a los tipos de datos que represen-
tan a los números reales, ya que utilizan un sistema de re-
presentación basado en la técnica de coma flotante, que
permite operar con números reales de diversas magnitu-
des, mediante un número decimal llamadomantisa y un
exponente que indica el orden de magnitud.
El tipo de dato flotante en lenguaje C sólo tiene dos ta-
maños: el float y el double, que son 4 bytes y 8 bytes res-
pectivamente. Se los puede utilizar tanto para representar
números decimales, como para representar números en-
teros con un orden de magnitud muy grande.
La forma de declarar una variable flotante es escribiendo
en una línea uno de los tipos de datos flotantes y a conti-
nuación el nombre de la variable y tal vez algún 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 más convenientes para algunas aplicaciones, hay ca-
sos en los que se prefieren los enteros. Esto se debe a que
los números flotantes no necesariamente tienen soporte
de hardware, en particular en las plataformas integradas.
Una alternativa que se utiliza en estas situaciones es in-
terpretar 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, 7 bitspara el exponente y 24 bits para el valor
del número. El procedimiento para almacenar un número
en una variable flotante es el siguiente:
1. Se convierte a binario la parte entera.
2. Se coloca el signo en el bit más significativo de la
misma manera que en los enteros (1 para el - y 0
para el +).
3. Se mueve la coma (en la representación binaria de
la parte entera) hasta que esté a la derecha del pri-
mer uno y éste se descarta (el uno más significativo).
El valor del exponente será el número de posiciones
que se movió la coma. El exponente usa la represen-
tación de un entero con complemento a dos.
4. Se convierte en binario la parte decimal del número.
Esto usando el peso de los bits. el bit decimal más
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 represen-
tado en memoria.
26 Caracteres
Los caracteres se representan utilizando el tipo char, que
tiene sólo 1 byte de tamaño. Este tipo se utiliza para re-
presentar los 256 caracteres de la tabla de caracteres del
sistema. El tipo char es también un tipo entero, ya que
puede tomar valores de 0 a 255. Por lo tanto también pue-
de 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 número a una
variable char, ya que se trata de un tipo entero. Enmuchas
situaciones se utiliza el tipo char para almacenar números
pequeños, ya que ocupa en memoria sólamente un byte.
Es importante notar que con la llegada de la codifica-
ción UTF-8, los caracteres de los diversos idiomas pue-
den ocupar 1, 2, 3 o 4 bytes, de modo que el tipo char ya
no alcanza para la representación de todos los caracteres
posibles. Por ello, el estándar C99 introduce el tipo wchar
que puede ocupar más de 1 byte, según sea necesario para
la codificación utilizada por el sistema.
En este capítulo veremos un poco más sobre como inter-
actuar con el usuario de nuestros programas desde la con-
sola, utilizando printf() como vimos en el primer ejem-
plo “Hola mundo”, así como scanf() para la lectura del
teclado.
27 Imprimir por pantalla
Como hemos visto hasta ahora en los ejemplos, hay una
función que utilizamos para sacar por pantalla textos ar-
bitrarios o el resultado de alguna operación: la función
printf().
Si miramos (en la documentación) su definición, no nos
aclarará demasiado:
https://es.wikipedia.org/wiki/Bit%2520m%C3%A1s%2520significativo
https://es.wikipedia.org/wiki/Complemento%2520a%2520dos
https://es.wikipedia.org/wiki/Coma%2520flotante
https://es.wikipedia.org/wiki/Mantisa
https://es.wikipedia.org/wiki/Orden%2520de%2520magnitud
https://es.wikipedia.org/wiki/Sistema%2520integrado
https://es.wikipedia.org/wiki/UTF-8
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Primer_programa_en_C
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Primer_programa_en_C
10 28 LECTURA DE DATOS DEL TECLADO
int printf (const char *TEMPLATE, ...)
...claro que por algo tiene una sección completa de la do-
cumentación para ella sola.
Veámosla poco a poco. Se trata de una función de la bi-
blioteca estándar, lo que quiere decir que para utilizarla
tenemos que incluir previamente su definición. La encon-
traremos en <stdio.h>.
Lo primero que vemos en la definición es que es una fun-
ción de tipo int, lo que quiere decir que devuelve un en-
tero. Ese entero es el número de caracteres impresos en
la pantalla, o un número negativo en caso de que se pro-
duzca algún 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 función (const), con lo
que puede ser una constante de cadena o una variable que
contenga una cadena, pero siempre debe acabar con el
carácter nulo \0.
Y luego vienen esos extraños puntos suspensivos. Esa
elipsis nos indica que como argumentos adicionales de
printf() podemos poner una serie ilimitada de otros ar-
gumentos, que se supone que la función sabrá qué hacer
con ellos. Y eso es justamente lo que hace tan fabulosa y
útil a printf().
Como hemos visto, el uso más simple de printf() es im-
primir una cadena de texto simple y corriente. Como ya
vimos:
printf(“Hola Mundo\n”); /*imprime la cadena*/
Y también hemos visto printf() también puede, con un
argumento extra y una sintaxis especial, imprimir un nú-
mero entero que hayamos almacenado en una variable:
char resultado;
resultado=5+2;
printf(“Resultado de la suma: %i\n”,resultado);
Aquí el punto de inserción es la secuencia %i. printf()
siempre trata las secuencias que comiencen por % como
secuencias de control que le dicen que debe imprimir al-
go 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 se-
cuencias %i:
int numero;
numero=3;
printf(“El doble de %i es %i y su cuadrado es
%i\n”,numero,numero*2,numero*numero);
28 Lectura de datos del teclado
La entrada de datos se puede hacer de muchas maneras
y entre ellas están desde el uso de dispositivos especiales
hasta nuestro simple teclado. La entrada de datos se re-
fiere 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 función scanf() que se
encuentra definida en <stdio.h> y que se usa para capturar
diferentes tipos de datos.
28.1 La función scanf()
scanf() es una de las funciones más usadas por los princi-
piantes para hacer entrada de datos en el lenguaje C. Tie-
ne 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 da-
tos de varias variables en una misma sentencia, en scanf
se pueden capturar varios datos en una sola sentencia.
#include <stdio.h> 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 demás sentencias, sólo la
que contiene scanf. En el código se ve lo siguiente:
scanf("%i”,&a);
Se observa que la funcion printf dejó en pantalla una pe-
tición 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 número entero. Luego se designa
a la variable a para contener a ese número. El símbolo
(&) que precede a a es para especificar que lo que se es-
tá enviando como argumento no es el valor que posee la
variable a sino la dirección de memoria en que se encuen-
tra. En este momento eso no tiene mucha relevancia, sólo
hay que recordar que se debe usar el símbolo & dentro
del scanf. En el momento en que hablemos de punteros
veremos más detalles de esto.
Otro ejemplo del uso de scanf:
#include <stdio.h> int main() { int a,b; printf (“in-
troduzca 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 código.
La cadena de formato, "%i,%i” especifica que el usuario
ingresará un número, seguido de una coma, y luego otro
número. El primer %i será capturado por la variable a y
el segundo por b.
Vamos a tratar ahora de que el ordenador haga un poco
11
de matemáticas para nosotros. Por ejemplo, que realice
unas pocas sumas, restas multiplicaciones y divisiones.
#include <stdio.h> int main(void) { int resulta-
do; 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 multiplicación: %i\n”,resultado);resultado=5/2;
printf(“Resultado de la división: %i\n”,resultado); re-
turn(0); }
Después de grabarlo (por ejemplo, con el nombre ejem-
plo.c), lo compilamos y ejecutamos, con (respectivamen-
te):
$ gcc ejemplo.c $ ./a.out Resultado de la suma: 7 Re-
sultado de la resta: 3 Resultado de la multiplicación: 10
Resultado de la división: 2 $
Fijémonos en la línea del principio de la función main:
int resultado;
Esta línea lo que hace es reservar un trozo de memoria,
del tamaño de un int (normalmente 4 bytes), y asignarle
el nombre resultado, para poder después 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 posterior-
mente.
Las líneas con printf() ya las conocemos, pero hay algo
en ellas que no habíamos visto antes. Esos %i y la parte
de resultado son nuevas para nosotros.
La función printf() no sólo sabe imprimir cadenas sim-
ples, como “Hola Mundo\n”, sino también imprimir va-
riables. 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 conversión de printf(). Estas ca-
denas siempre empiezan por %, siendo %i la cadena para
imprimir un entero, como es en nuestro caso int resul-
tado. Finalmente, printf() debe saber qué valor escribir,
por eso le damos otro argumento (u otros), usando , co-
mo separador, que contienen las variables cuyos valores
queremos mostrar.
En el resto del programa hemos visto cómo decirle al or-
denador que ejecute una suma, una resta, una multiplica-
ción y una división entera, con los operadores +, -, * y /.
Es de notar que el resultado de una operación como estas
entre números enteros será siempre otro entero, como se
puede observar en la división, en la que no obtenemos un
bonito decimal, sino un resultado entero. Además, hemos
visto que el resultado de esas operaciones, que llamamos
expresiones, puede ser asignado a una variable:
resultado = 7;
Esa asignación se hace mediante el operador de asigna-
ción: =. Con él, ya conocemos cinco operadores.
Pero, como = también es un operador, ¿cómo sabe el or-
denador qué operador debe ejecutar primero? Y si es un
operador, ¿por qué no da un resultado? ¿No crea una ex-
presión?
Empezando por las últimas preguntas, el operador de
asignación sí crea una expresión, como los operadores
de suma, resta, multiplicación y división, y esa expresión
tiene un resultado, que es el valor que obtiene el lado iz-
quierdo al realizar la operación. En cuanto a saber qué
se debe ejecutar primero, el ordenador tiene una lista de
precedencia, según la cual siempre ejecuta primero las
multiplicaciones y divisiones, de izquierda a derecha, a
continuación las sumas y restas, de izquierda a derecha,
y a continuación las asignaciones, de derecha a izquierda.
Para más detalles acerca de la precedencia de los opera-
dores ver el anexo de los operadores.
En cuanto a los caracteres de punto y coma, notamos aquí
que una expresión también puede ser una sentencia por sí
misma, sin necesidad de que haya ninguna función. De
hecho, una sentencia puede no tener siquiera una expre-
sión. La línea: ; es una sentencia perfectamente válida, la
sentencia vacía, que sera útil en puntos donde el lenguaje
requiera una sentencia pero no sea necesaria para nuestro
programa.
Como ya se ha mencionado, C es un ejemplo de
programación estructurada. En este tipo de programa-
ción, es necesario contar con ciertas estructuras que per-
mitan controlar el flujo del programa, es decir, tomar de-
cisiones y repetir acciones.
29 La estructura condicional if ...
else
En la gran mayoría de los programas será necesario to-
mar decisiones sobre qué acciones realizar. Esas decisio-
nes pueden depender de los datos que introduzca el usua-
rio, de si se ha producido algún error o de cualquier otra
cosa.
La estructura condicional if ... else es la que nos permite
tomar ese tipo de decisiones. Traducida literalmente del
inglés, se la podría llamar la estructura “si...si no”, es de-
cir, “si se cumple la condición, haz esto, y sino, haz esto
otro”.
Un ejemplo sencillo sería el siguiente (no se trata de un
programa completo, sino tan sólo una porción de código):
if (edad < 18) printf(“No puedes acceder.\n”); else
printf(“Bienvenido.\n”);
Este código de ejemplo dice que si el valor de la varia-
ble edad es menor que 18 se imprimirá “No puedes ac-
ceder.\n”, mientras que en caso contrario se imprimirá
“Bienvenido.\n”.
Como se ve en el ejemplo, la estructura de un condicional
https://es.wikipedia.org/wiki/Variable%2520(programaci%C3%B3n)
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Referencia#Operadores
https://es.wikipedia.org/wiki/Programaci%C3%B3n%2520Estructurada
12 29 LA ESTRUCTURA CONDICIONAL IF ... ELSE
es bastante simple:
if (condición) { sentencias_si_verdadero; } else {
sentencias_si_falso; }
La condición, encerrada entre paréntesis, es una expre-
sión que puede dar como resultado 0 (interpretado como
falso) o cualquier valor distinto de 0 (interpretado como
verdadero). Cuando la condición sea verdadera, se eje-
cutarán las sentencias dentro del primer bloque de código,
cuando la condición sea falsa, se ejecutarán las sentencias
del segundo bloque de código. Las expresiones y valores
de tipo verdadero/falso son también llamados valores ló-
gicos o booleanos.
La indentación o sangría (los espacios al comienzo de las
líneas) no es necesaria, pero ayuda a la claridad del códi-
go. La utilización de las llaves {...} es obligatoria cuando
se quiere utilizar más de una instrucción por bloque, y
optativa cuando sólo se quiere escribir una instrucción.
Por claridad, sin embargo, es recomendable utilizarlas
aún cuando sólo vaya a haber una instrucción.
El bloque del else es opcional. Si no se lo encuentra, sólo
se realizará la acción correspondiente al bloque if.
A continuación, un ejemplo con una función, que devuel-
ve el mayor de dos números:
int mayor(int a, int b) { if (b > a) { return b; }// No posee
especificación de la parte “else”, ya que no es necesaria.
return a; // Finaliza la función retornando el valor de “a”. }
29.1 Operadores de comparación
El símbolo > visto en el último ejemplo es un operador,
que en este caso compara dos números enteros y devuelve
verdadero si el primero es mayor, falso en caso contrario.
A continuación un listado de los posibles operadores de
comparación en C y su significado.
Teniendo en cuenta que en C se toma como falso el va-
lor 0, y como verdadero cualquier otro valor, una práctica
común es expresar condiciones sin utilizar ningún opera-
dor:
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 expresión (divisor) es equivalente a (di-
visor != 0).
29.2 Operadores lógicos
Los operadores && (“y”), || (“o”) y ! (“no”) son opera-
dores lógicos. Permiten operar con expresiones lógicas
para generar expresiones más complejas.
Por ejemplo: determinar si un año es bisiesto o no. Los
años son bisiestos si son divisibles por 4, pero no si son
divisibles por 100, a menos que también sean divisibles
por 400.
if ( (!(a % 4) && (a % 100)) || !(a % 400) ) { printf(“es
un año bisiesto.\n”); } else { printf(“no es un año
bisiesto.\n”); }
En realidad, teniendo en cuenta la prioridad de los ope-
radores utilizados, podemos simplificar la expresión an-
terior del siguiente modo:
if ( !(a % 4) && (a % 100) || !(a % 400) ) { printf(“es
un año bisiesto.\n”); } else { printf(“no es un año
bisiesto.\n”); }
Además, como a cada rama del if le sigue una única ins-
trucción, podemos expresar la expresión anterior del si-
guiente modo:
if ( !(a % 4) && (a % 100) || !(a % 400) ) printf(“es un
año bisiesto.\n”); else printf(“no es un año bisiesto.\n”);
En este caso, se utiliza el operador módulo (%), que ob-
tiene el resto de la división entera de un número por otro.
Cuando un número es divisible por otro, el resto de su
división 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 número es múltiplo de 4, de 100 o de 400.
29.3 Evaluación de cortocircuito
La evaluación en corto circuito es una característica del
lenguaje C que se utiliza para optimizar la ejecución de
programas. Consiste en que el programa puede verificar si
una expresión es verdadera o falsa antes de haber evaluado
toda condición.
Por ejemplo, si se tiene una condición 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 condición, ya que el resultado será de cualquier
modo verdadero.
De la misma forma, si la condición fuera:
if ((a > 2) && (b < 4)) { ... }
En este caso, si no se cumple que a > 2, no se evaluará
la siguiente condición, ya que el resultado será falso de
todos modos.
Esta característica no tiene demasiada importancia al co-
menzar a programar, pero facilitará ciertas operaciones y
optimizaciones en programas avanzados.
https://es.wikipedia.org/wiki/Indentaci%C3%B3n
https://es.wikipedia.org/wiki/Resto
13
30 La estructura condicional
abierta y cerrada 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 es-
tructura switch ... case, por su parte, nos permite elegir
entre muchas opciones. Ejemplo:
#include <stdio.h> #include <stdlib.h> int main(void) {
int dia; printf(“que número de día de la semana es?");
scanf("%i”,&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, Vier-
nes”); 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, ne-
cesitaría cuatro de ellas, resultando un enorme bloque
muy difícil de leer. En la mayoría de los casos, además, la
sentencia switch proporciona una ganancia en velocidad
del código, pues permite al compilador trabajar en base
a que se trata de una decisión múltiple para una única va-
riable, cosa que con sentencias if el 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 necesita-
mos llaves. Hay un caso especial, default, que se ejecuta
si ningún otro corresponde, y que no es necesario poner.
Es, en todo, equivalente al bloque else de una sentencia
if.
Las sentencias break sonmuy importantes, ya que el com-
portamiento normal de un bloque switch es ejecutarlo to-
do desde la etiqueta case que corresponda hasta el final.
Por ello, si no queremos que se nos ejecute más de un blo-
que, pondremos sentencias break al final de cada bloque
excepto el último.
Es decir, las etiquetas case son puntos de entrada de la
ejecución, y no implican que al acabarse el bloque case
la ejecución 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 ocasio-
nes, “dejar caer la cascada switch”.
31 El bucle while
El bucle while sirve para ejecutar código reiteradas veces.
while (/*condicion*/) { /* Código */ }
La condición debe de ser una expresión lógica, similar a
la de la sentencia if. Primero se evalúa la condición. Si
el resultado es verdadero, se ejecuta el bloque de código.
Luego se vuelve a evaluar la condición, y en caso de dar
verdadero se vuelve a ejecutar el bloque. El bucle se corta
cuando la condición da falso.
Ejemplo: imprimir los números de 0 a 99:
int i = 0; while (i < 100) { printf("%d\n”, i); i = i + 1; }
32 El bucle for
El bucle for es un bucle muy flexible y a la vez muy poten-
te ya que tiene varias formas interesantes de implemen-
tarlo, su forma más tradicional es la siguiente:
for (/* inicialización */; /* condición */; /* incremento
*/) { /* código a ejecutar */ }
Inicialización: en esta parte se inicia la variable que con-
trola el bucle y es la primera sentencia que ejecuta el bu-
cle. Sólo se ejecuta una vez ya que solo se necesita al prin-
cipio del bucle.
Expresión condicional: al igual que en el bucle while, esta
expresión determina si el bucle continuará ejecutándose
o no.
Incremento: es una sentencia que ejecuta al final de ca-
da iteración del bucle. Por lo general, se utiliza para in-
crementar la variable con que se inicio el ciclo. Luego
de ejecutar el incremento, el bucle revisa nuevamente la
condición, si es verdadera tiene lugar una ejecución más
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 más reducida como i++. Esta forma se utiliza más
comúnmente en el bucle for:
int i; for (i=0; i < 100; i++) { printf("%d\n”, i); }
33 El bucle do...while
El bucle do...while es un bucle que, por lo menos, se eje-
cuta una vez. Do significa literalmente “hacer”, y while
significa “mientras”
Su forma es esta:
do { /* CODIGO */ } while (/* Condición de ejecución
del bucle */)
14 35 FUNCIONES
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 ab-
surdo, pero es bastante intuitivo. El código del bucle asig-
na un valor aleatorio a la variable definida anteriormente,
y mientras esa variable no tenga el valor 25, el bucle sigue
ejecutándose.
34 La sentencia goto
La sentencia goto sirve para indicar al programa que con-
tinue ejecutándose desde la línea de código indicada. Su
sintaxis es más o menos así:
/* Código */ ETIQUETA: /* Código */ goto ETIQUE-
TA; /* Código */
Así, cuando se ejecute la sentencia goto, el programa “sal-
tará" y continuará su ejecución a partir de la etiqueta mar-
cada.
Como se puede observar se puede usar para crear un bu-
cle, o para ir a una parte del código u otra si se combi-
na con una sentencia if...else. Pero por lo general puede
obtenerse el mismo efecto utilizando los bucles anterior-
mente vistos.
Por eso, la sentencia goto es poco aceptada por la comuni-
dad de programadores, pues puede provocar que se hagan
programas un poco “sucios” y confusos. Sólo en ocasio-
nes muy excepcionales será recomendado el uso del goto
al crear iteraciones muy complejas. Sin embargo, con el
pasar de los años este comando ya ha quedado práctica-
mente descartado del lenguaje de los programadores.
35 Funciones
Como vimos anteriormente C tiene como bloque bási-
co la función main() , también hemos visto la sentencia
printf() que es otra función, y de igual forma hay mu-
chas más funciones predefinidas, pero nosotros mismos
también podemos definir nuestras propias funciones. De
hecho, es fundamental hacerlo.
Podemos definir una función cualquiera de la misma ma-
nera en que definimos la función main(). Basta con poner
su tipo, su nombre, sus argumentos entre paréntesis y lue-
go, entre llaves, su código:
/* Inclusión de archivos */ #include <stdio.h> void
holamundo(void) /* Función donde se ejecuta la ló-
gica del programa */ { printf(“Hola Mundo\n”); /*
imprime la cadena */ return; /* sale de la función */
} int main(void) /* Función principal del programa */
{ holamundo(); /* llamada a la función holamundo */
return 0; /* sale del programa con código 0 (correcto) */ }
Este código es en todo equivalente al “Hola Mundo” ori-
ginal, sólo que nos muestra cómo escribir y cómo utilizar
una función. Y además nos muestra un principio de buena
programación: meter las sentencias que “hacen el traba-
jo” en otras funciones específicas para sacarlas demain(),
dejando en ésta tan sólo un guión general de lo que hace
el programa, no las órdenes específicas. De esta mane-
ra se facilita la comprensión del programa, y por tanto el
futuro trabajo de modificarlo.
35.1 La sentencia return
La sentencia return puede utilizarse dentro de una función
para terminar su ejecución.
En el ejemplo anterior, la función holamundo fue decla-
rada con valor de retorno de tipo void (es decir, valor de
retorno nulo). En ese caso, la sentencia return no lleva
ningún parámetro adicional, ya que la función no debe
devolver ningún valor a la función que la llama.
En cambio, la función main tiene un valor de retorno de
tipo int, por lo que return debe ir seguido de un valor en-
tero (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 algún tipo de error.
La instrucción return no es una función, se trata de una
sentencia que lo que hace es retornar como valor de la
función el valor que se le proporciona como argumento.
35.2 Argumentos
Las funciones también pueden recibir argumentos o pará-
metros, para modificar su comportamiento. Por ejemplo,
la definición de una función para sumar dos números sería
de la siguiente manera:
35.3 Declaración y definición
En el ejemplo anterior podemos notar que la función su-
mar figura en el código antes que main. ¿Qué pasaría si
las escribiéramos en distinto orden?
#include <stdio.h> int main(void) { int suma = su-
mar(5, 3); /* ERROR, sumar no ha sido declarada aún
*/ printf(“La suma es: %d ", suma); return 0; } int
sumar(int numero1, int numero2) { return numero1 +
numero2; }
En este caso el programa es erróneo y no compila, ya que
en la línea donde se llama a la función sumar, el compi-
https://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Primer_programa_en_C#Diseccionando_el_%2522Hola_Mundo%2522
35.5 Variables Locales y Globales 15
lador aún no conoce ninguna función con ese nombre, y
cuáles son sus argumentos y valor de retorno.
Una posible solución es declarar el prototipo de la fun-
ción al principio, para informar al compilador que existe,
y luego definir el cuerpo de la misma en cualquier lugar
del programa:
#include <stdio.h> /* Declaración */ int sumar(int
numero1, int numero2); int main(void) { int suma =
sumar(5, 3); printf(“La suma es: %d ", suma); return 0;
} /* Definición */ int sumar(int numero1, int numero2)
{ return numero1 + numero2; }
35.4 Paso de Parámetros
Las funciones pueden recibir datos como lo hemos obser-
vado, pero existen dos formas de enviar los datos hacia
una función por valor y por referencia, las cuales mo-
difican en diferente forma el comportamiento de el pro-
grama.
35.4.1 Por Valor
El paso por valor envía una copia de los parámetros a
la función por lo tanto los cambios que se hagan en ella
no son tomados en cuenta dentro de la función main().
Ejemplo:
/* * por_valor.c * * Julio César Brizuela <brizue-
laalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado
del Dominio Público */ #include <stdio.h> void su-
mar_valor(int numero); /* prototipo de la función */
int main(void) { int numero = 57; /* definimos numero
con valor de 57*/ sumar_valor(numero); /* enviamos
numero a la función */ printf(“Valor de numero dentro
de main() es: %d\n”, numero); /* podemos notar que
el valor de numero se modifica * sólo dentro de la
función sumar_valor pero en la principal * número sigue
valiendo 57 */ return 0; } void sumar_valor(int numero)
{ numero++; /* le sumamos 1 al numero */ /* el valor de
número recibido se aumenta en 1 * y se modifica dentro
de la función sumar_valor() */ printf(“Valor de numero
dentro sumar_valor() es: %d\n”, numero); return; }
35.4.2 Por Referencia
El paso por referencia se hace utilizando apuntadores. Se
envía la dirección de memoria de la variable, por lo tanto
los cambios que haga la función si afectan el valor de la
variable. Ejemplo:
/* * por_referencia.c * * Julio César Brizuela <bri-
zuelaalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado
del Dominio Público */ #include <stdio.h> void su-
mar_referencia(int *numero); /* prototipo de la función
*/ int main(void) { int numero = 57; /* definimos
numero con valor de 57*/ sumar_referencia(&numero);
/* enviamos numero a la función */ 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() también se ha modificado * aunque la
función no haya retornado ningún 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 función */
printf("\nValor de numero dentro sumar_referencia() es:
%d”, *numero); return; }
35.5 Variables Locales y Globales
Además de pasar valores a una función, también se pue-
den declarar tipos de datos dentro de las funciones, estos
tipos de datos declarados dentro de una función solo son
accesibles dentro de esta misma función y se les conocen
como variables locales, así pues podemos definir los mis-
mos nombres de variables en diferentes funciones, ya que
estas variables solo son accesibles dentro de esas funcio-
nes. Ejemplo:
/* * locales.c * * Julio César Brizuela <brizuelaal-
varado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado del
Dominio Público */ #include <stdio.h> 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 ca-
da 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 función
principal main() y fuera de cualquier otra función 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 función creada por nosotros.
Ejemplo:
/* * global.c * * Julio César Brizuela <brizuelaalvara-
do@gmail.com> 2009 * * para el wikilibro “Programa-
ción en C” * bajo licencia FDL, adaptado del Dominio
Público */ #include <stdio.h> int variable_global = 99;
/* inicializamos la variable global */ void funcion(); int
16 36 FUNCIONES RECURSIVAS
main(void) { /* imprimimos el valor*/ printf(“main(),
acceso a variable_global %d\n”, variable_global); /*
llamamos a la función */ funcion(); return 0; } void
funcion() { /* imprimimos el valor*/ printf(“funcion(),
acceso a variable_global %d\n”, variable_global); return;
}
36 Funciones Recursivas
La recursividad (recursión) es la propiedad por la cual una
función se llama a sí misma directa o indirectamente.
La recursión indirecta implica utilizar más de una fun-
ción.
Se puede considerar la recursividad como una alternativa
a la iteración. La recursión permite especificar soluciones
naturales, sencillas, que serían, en caso contrario, difíci-
les de resolver. Toda función recursiva debe contemplar
un caso base o condición de salida, para terminar, o la
recursividad no podrá terminar nunca.
Una función recursiva podría definirse así:
funcion_recursiva( /* parámetros recibidos por la fun-
ción */ ) { /* Código */ funcion_recursiva( ); /* llamada
a la función misma */ /* Código */ }
Uno de los ejemplos más representativos en la recursivi-
dad es el factorial de un numero ( n! ):
n! =
n∏
k=1
k ∀n ∈ N
la definición de recursividad del factoriales:
n! =
{
1 Si n = 0
n(n− 1)! Si n > 0
∀n ∈ N.
En esta definición, n = 0, es nuestro caso base, que le da
fin a la recursividad.
Entonces nuestro programa que calcula el factorial es:
/* *factorial.c * * Julio César Brizuela <brizue-
laalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado del
Dominio Público */ #include <stdio.h> 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 función */ } int main(void) { /* en este
caso se llama a la función y se imprime directamente*/
printf("%ld ", factorial(5)); return 0; }
También existen otros tipos de funciones recursivas como
lo es el producto de dos números. El producto de a × b,
donde a y b son números enteros positivos seria:
Solución iterativa:
a× b =
a+ a+ · · ·+ a
︸ ︷︷ ︸
b veces
=
∑
b
i=1
a
Solución recursiva:
a× b =
{
0 Si b = 0
a+ a× (b− 1) Si b > 0
Así pues 7× 3 es:
7×3 = 7+7×2 = 7+7+7×1 = 7+7+7+0 = 21
Podemos ver que la multiplicación de dos números a, b se
puede transformar en otro problema más pequeño multi-
plicar a por (b-1), el caso base se produce cuando b = 0
y el producto es 0. Ejemplo:
/* * producto.c * * Julio César Brizuela <brizue-
laalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado del
Dominio Público */ #include <stdio.h> 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 función */ } int main(void)
{ /* en este caso se llama a la función y se imprime
directamente*/ printf("%i ", producto( 7, 3)); return 0; }
36.1 Recursividad indirecta o recursión
mutua
Esta se produce cuando una función llama a otra, que esta
a su vez terminará llamando de nuevo a la primera fun-
ción. El siguiente programa visualiza el alfabeto utilizan-
do recursión indirecta o mutua:
/* * elalfabeto.c * * Julio César Brizuela <brizue-
laalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado
del Dominio Público */ #include <stdio.h> void fun-
cionA(char c); /* se declara el prototipo de la función
para que el llamado */ void funcionB(char c); /* a la
misma en la función no sea implícita */ 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' */ }
36.2 Recursión versus Iteración
Tanto la iteración como la recursión se basan en estructu-
ra de control: la iteración utiliza una estructura repetitiva
y la recursión una estructura de selección. La iteración
36.2 Recursión versus Iteración 17
utiliza explícitamente una estructura repetitiva mientras
que la recursión consigue la repetición mediante llamadas
repetitivas a funciones.
La iteración termina si la condición del bucle no se cum-
ple, mientras que la recursión termina cuando se reconoce
un caso base.
La recursión puede presentar desventajas ante la iteración
ya que se invoca repetidas veces al mecanismo de llamada
de funciones y se necesita un tiempo mayor para realizar
cada llamada.
La razón por la cual se puede elegir u optar por usar re-
cursividad es que existen muchos problemas complejos
que poseen naturaleza recursiva y, en consecuencia, son
mas fáciles de implementar.
36.2.1 Ejemplo Iterativo
/* * iterativo.c * * Julio César Brizuela <brizue-
laalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado del
Dominio Público */ #include <stdio.h> long factorial(int
numero); int main(int argc, char** argv) { int contador
= 0; /* calcula el factorial de 0 a 10 */ for ( contador =
0; contador <= 10; contador++ ) printf("%d! = %ld\n”,
contador, factorial( contador )); return 0; } /* funcion
factorial iterativa */ long factorial( int numero ) { long
resultado = 1; int i = 0; /* declaracion de la función
factorial iterativa */ for ( i = numero; i >= 1; i-- )
resultado *= i; return resultado; }
36.2.2 Ejemplo Recursivo
/* * recursivo.c * * Julio César Brizuela <brizue-
laalvarado@gmail.com> 2009 * * para el wikilibro
“Programación en C” * bajo licencia FDL, adaptado del
Dominio Público */ #include <stdio.h> long factorial(int
numero); int main(int argc, char** argv) { int contador
= 0; /* calcula el factorial de 0 a 10 */ for ( contador =
0; contador <= 10; contador++ ) printf("%d! = %ld\n”,
contador, factorial( contador )); return 0; } /* función
factorial recursiva */ long factorial( int numero ) { if (
numero <= 0 ) /* caso base */ return 1; /* casos bases:
0! = 1 y 1! = 1 */ else /* llamada recursiva */ return
numero * factorial( numero - 1 ); /* llamada a la función
factorial */ }
Los vectores son una forma de almacenar datos que per-
miten contener una serie de valores del mismo tipo, cada
uno de los valores contenidos tiene una posición asociada
que se usará para accederlos. Está posición o índice será
siempre un número entero positivo.
En C la cantidad de elementos que podrá contener un vec-
tor es fijo, y en principio se define cuando se declara el
vector. Los vectores se pueden declarar de la siguiente
forma:
tipo_elemento nombre[largo];
Esto declara la variable nombre como un vector de ti-
po_elementos que podrá contener largo cantidad de ele-
mentos, y cada uno de estos elemento podrá contener un
valor de tipo tipo_elemento.
Por ejemplo:
double valores[128];
En este ejemplo declaramos un vector de 128 elementos
del tipo double, los índices de los elementos irían 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 también se pueden declarar:
tipo_elemento nombre[largo]={valor_0, valor_1, va-
lor_2};
En caso estamos asignadole valores a los primeros 3 ele-
mentos del vector nombre. Notar que largo debe ser ma-
yor o igual a la cantidad de valores que le estamos asig-
nando al vector, en el caso de ser la misma cantidad no
aporta información, 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 través de su
posición. Es decir:
tipo_elemento elemento; ... elemento = nombre[2];
Asumiendo que tenemos el vector anterior definido esta-
ríamos guardando valor_2 en elemento.
Veamos algunos ejemplos:
/* * Ejemplo : El producto escalar de dos vectores */
#include <stdio.h> 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[], dou-
ble 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 re-
presentar vectores matemáticos y calcular el producto es-
18 36 FUNCIONES RECURSIVAS
calar entre ellos. Una peculiaridad que se puede notar es
que al recibir un arreglo en una función no se especifica
el largo, volveremos a esto en un capítulo posterior.
Otra función clásica es la búsqueda de un máximo o mí-
nimo, 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

Continuar navegando

Materiales relacionados

195 pag.
C - Curso de C

User badge image

Iara Echegaray