Upload
ngohanh
View
220
Download
1
Embed Size (px)
Citation preview
1
Índice
Introducción 5
1. Elementos del lenguaje C 8
1.1. Características del lenguaje 11
1.1.1. Ventajas 12
1.1.2. Ambiente de desarrollo 14
1.1.3. Versiones 22
1.1.4. Palabras reservadas 23
1.2. Estructura de un programa 27
1.3. Tipos de datos 34
1.3.1. Tipos básicos 34
1.3.2. Modificadores 38
1.3.3. Moldes 41
1.4. Declaración de variables y constantes 49
1.5. Operadores 58
1.5.1. Aritméticos, relacionales y lógicos 58
1.5.2. Sentencias de asignación 63
1.5.3. Operadores de incremento y decremento 65
Recapitulación 72
Actividades de confirmación de conocimientos 77
Autoevaluación 83
2
2. Estructuras de control 89
2.1.Sentencias para entrada y salida de datos 91
2.1.1. Entrada y salida estándar 91
2.1.2. Entrada y salida por consola 97
2.1.3. Entrada y salida con formato 98
2.2.Instrucciones de control de pantalla 110
2.2.1. clrscr() y delay() 110
2.2.2. gotoxy() 111
2.2.3. textcolor() y textbackground() 112
2.3.Sentencias de control selectivas 118
2.3.1. Sentencia if 118
2.3.2. Operador ‘?’ 127
2.3.3. switch() 128
2.4.Sentencias de control repetitivas 134
2.4.1. while 134
2.4.2. do-while 136
2.4.3. for 140
Recapitulación 146
Actividades de confirmación de conocimientos 157
Autoevaluación 160
3. Arreglos 171
3
3.1.Declaración e inicialización 173
3.2.Uso de arreglos unidimensionales 192
3.3.Las cadenas y sus funciones 205
3.4.Arreglos bidimensionales 211
3.5.Pilas y colas 215
3.6.Algoritmos de ordenación y búsqueda 225
3.6.1. Método de la burbuja 226
3.6.2. Búsqueda binaria 232
Recapitulación 239
Actividades de confirmación de conocimientos 252
Autoevaluación 255
4. Funciones definidas por el usuario 266
4.1.Definición y declaración 268
4.1.1. Programación modular 269
4.1.2. Sintaxis de una función 270
4.1.3. Invocación y ámbito 271
4.1.4. Retorno de valores 272
4.2.Paso de parámetros 276
4.2.1. Por valor 277
4.2.2. Por referencia 277
4.3.Recursividad 283
4
Recapitulación 290
Actividades de confirmación de conocimientos 298
Autoevaluación 300
5. Estructuras y archivos 302
5.1. Concepto, declaración y uso de estructuras 304
5.2. Tipos de archivos en C 317
5.2.1. Flujos de texto 317
5.2.2. Flujos binarios 317
5.3. Manejo de archivos 320
5.3.1. Modos de apertura 320
5.3.2. Funciones para lectura y escritura 321
5.3.3. Rutinas de acceso directo 325
Recapitulación 334
Actividades de confirmación de conocimientos 338
Autoevaluación 340
Actividades finales 342
Glosario 350
Bibliografía 356
5
Introducción.
El lenguaje C es un lenguaje importantísimo desde su creación, puesto que fue el lenguaje
que se desarrolló a partir de UNIX, (desarrollado en lenguaje ensamblador) uno de los
sistemas operativos más importantes para el desarrollo de a computación y las redes de
computadoras. Fue tanto el éxito y la facilidad desarrolladas en Lenguaje C, que
posteriormente todo el sistema operativo UNIX fue reescrito en Lenguaje C.
Hoy en día, Lenguaje C es la base de muchos de los lenguajes de programación más usados
en la programación en Internet, como PHP, Java, Perl, CGI, JavaScript, etc. Lenguajes en
los que tienes avanzado el conocimiento de un 40% si sabes programar en Lenguaje C.
Además, el programar en lenguajes como Visual Basic, o lenguajes de macros, de etiquetas
o pseudolenguajes como HTML, DHTML, XML, Flash, etc. se facilita porque se adquiere
una lógica sin comparación al aprender Lenguaje C.
El presente libro, sale a la luz pública con el propósito de ser un texto de ayuda en el
estudio de la asignatura de Programación Estructurada para los estudiantes de Bachillerato
Tecnológico con la especialidad de Computación o carreras afines.
Evidentemente no es un tratado completo del Lenguaje C, sino un acercamiento al mismo,
puesto que más adelante, ya en niveles de Licenciatura, tendrá el estudiante oportunidades
de incrementar su conocimiento y complementar su estudio de la programación.
Para empezar el estudio del Lenguaje C como lenguaje de programación, previamente
debes haber estudiado concienzudamente la asignatura de Fundamentos de programación.
En la Primera Unidad, cuyo nombre es Elementos del Lenguaje C, te presentamos las
características del mismo, las ventajas que ofrece frente a otros lenguajes de programación,
el ambiente de desarrollo en el que se desenvuelve Lenguaje C, un breve recuento de las
6
versiones que se conocen actualmente, y finalmente las palabras reservadas para el C. Se
muestra la estructura de un programa en C, con la forma general que debe guardar y las
características que debe tener para poder ser funcional, así como los tipos básicos de datos
que se pueden manejar en un programa en Lenguaje C y los modificadores que son
factibles de usar, además los moldes que pueden emplearse para tratar de manera más
eficiente los datos. Se verá la forma correcta en que debe realizarse la declaración de
variables y constantes y los operadores que se usan en Lenguaje C, (Aritméticos,
relacionales, lógicos, de asignación, de incremento y decremento).
En la Segunda Unidad, cuyo nombre es Estructuras de control, te mostramos las sentencias
para entrada y salida de datos, (entrada y salida estándar, la entrada y salida por consola, y
entrada y salida con formato). Se explican también las instrucciones de control de pantalla
(clrscr(), delay(), gotoxy(), chr(), textcolor(), textbackground()). Se verán además las
sentencias de control selectivas (if, ‘?’ y switch()), así como las sentencias de control
repetitivas (while, do-while y for).
En la Tercera Unidad, cuyo nombre es Arreglos, conocerás la forma en que son declarados
e inicializados los arreglos. Verás el uso que se da a los arreglos unidimensionales. Se
describe la forma en que se usan los arreglos unidimensionales de caracteres, llamados
cadenas de caracteres y las funciones que se aplican a las mismas. Se desarrollan los
arreglos bidimensionales, tablas o matrices y la forma de tratarse en Lenguaje C.
Posteriormente, se verán dos tipos de estructuras estáticas de datos llamadas pilas y colas.
Verás también los algoritmos de ordenación por el método de la burbuja y búsqueda
binaria.
En la Cuarta Unidad, cuyo nombre es Funciones definidas por el usuario, conocerás la
definición y declaración de esas funciones, aprenderás los conceptos de programación
modular, la sintaxis de una función, lo que es la invocación a la misma y el ámbito, así
como el retorno de valores. Verás también el concepto de paso de parámetros, tanto por
valor como por referencia. Aprenderás y harás ejercicios sobre la recursividad.
7
En la Quinta Unidad, cuyo nombre es Estructuras y archivos, te presentamos el Concepto,
la forma en que se declaran y cómo se usan las estructuras. Se muestran también los tipos
de archivos que pueden manejarse en Lenguaje C, lo que son los flujos de texto y los
binarios. Se verá la forma en que se manejan los archivos, el modo de apertura, las
funciones para la lectura y escritura de los mismos y algunas rutias para acceso directo,
tanto de lectura como de escritura.
9
PROPOSITO
¿QUÉ APRENDERÁS?
Las características principales del lenguaje C, como ventajas que ofrece, ambientes de
desarrollo, sus diferentes versiones y a distinguir las palabras reservadas; además a
describir la estructura general que debe tener un programa; a reconocer los diferentes tipos
de datos que se pueden manipular en un programa, y sus modificadores; También a aplicar
la sintaxis en la declaración de constantes y variables e identificar los diferentes tipos de
operadores y a aplicar su jerarquía a expresiones.
¿CÓMO LO APRENDERÁS?
Realizarás investigaciones sobre las palabras clave, los tipos de datos y sus modificadores;
y realizarás ejercicios prácticos en la computadora, capturando tus primeros programas.
Además estudiarás los tópicos necesarios para adquirir dominio sobre lo que se explica.
¿PARA QUÉ LO APRENDERÁS?
Para entender y adquirir la manera en que el desarrollar y compilar un programa en
Lenguaje C, puede ayudar a una persona a resolver un problema que se le presenta.
10
La programación estructurada es una técnica que utiliza, conforme al Teorema de Dijkstra,
de una forma clara y comprensible, el uso de tres estructuras lógicas de control:
a.- Secuencia.- El programa debe tener la continuidad de las operaciones que realiza.
b.- Selección.- El programa debe resolver una o más bifurcaciones en una toma de
decisiones.
c.- Iteración.- El programa debe ser capaz de repetir constantemente una operación hasta
que se cumpla la condición que le tiene ejecutándose.
¿Es comprensible el Teorema de Dijkstra? Si no lo fuera, se te sugiere que vuelvas a leer la
sección de “Estructuras de control” en tu libro de Fundamentos de Programación.
La combinación adecuada de estas estructuras lógicas conforman el programa que ha de
resolver un problema propuesto.
Un programa estructurado, está formado por segmentos, los cuales tienen una sola entrada
y una salida, y poseen como características la combinación de las estructuras lógicas de
control mencionadas anteriormente, y se les llama “programa propio”.
La programación estructurada, se basa en el Teorema de la Estructura, que dice que
cualquier programa propio equivale a un programa que contenga las tres estructuras lógicas
1. Elementos del Lenguaje C
11
de control. Un programa estructurado, es muy fácil de leer porque carece de una instrucción
que se use para desviar el flujo de control (caso del goto).
Uno de los lenguajes de programación que coincide con las características de la
programación estructurada, es el Lenguaje C, que por sus características inherentes se
consideró como el más adecuado para el dominio de los estudiantes de nivel Técnico.
Antes de comenzar a usarlo, es necesario que conozcamos algo de lo que es el Lenguaje C,
puesto que va a ser nuestra herramienta para programar y resolver problemas usando la
computadora, desde hoy hasta el término del curso.
Al analizar la manera en que se dan los problemas en el mundo real, nos damos cuenta de
que pueden ser simples o pueden ser complejos, sin embargo, los dos tipos, coinciden en
que están definidos. Para resolverlos, se requiere de una estrategia para visualizarlos,
métodos para solucionarlos y herramientas para materializar esa solución. Han de dividirse
los problemas en tres partes para solucionarlos: entrada, proceso y salida de datos.
La parte que estamos iniciando en este libro, es precisamente las herramientas, entre las
cuales, resalta por su poder el Lenguaje C.
1.1. Características del lenguaje
12
El Lenguaje C fue creado e implementado por Dennis Ritchie, usando UNIX como sistema
operativo, en una computadora DEC PDP-11; proviene de haber desarrollado anteriormente
un lenguaje llamado BPCL, creado por Martin Richards.
En 1963, se desarrolló un lenguaje llamado CPL (Combined Programming Language) que
intentaba simplificar el lenguaje ALGOL (lenguaje de alto nivel aparecido en las
computadoras de segunda generación, en 1958), pero era aún muy complicado, así que
Martin Richards lo simplificó aún más creando el BPCL (Basic CPL), y es el mismo que
Ken Tompson (quien es coautor de Lenguaje C) en 1970 simplificó aún más y llamó
Lenguaje B en 1970.
El Lenguaje C es un lenguaje muy elegante, compacto, rápido y sencillo
C es un lenguaje de nivel medio, pero no porque sea menos potente que uno de alto nivel
(como el PASCAL), o más poderoso que uno de bajo nivel (ensamblador), sino porque
realiza una fusión entre elementos de alto nivel y la funcionalidad del bajo nivel.
Siendo de nivel medio, permite que se realice la manipulación de bits, bytes y direcciones,
(elementos básicos con los que funciona la computadora) mientras que uno de alto nivel,
opera sobre una cadena para realizar muchas funciones.
1.1.1. Ventajas
13
Lenguaje C es un lenguaje estructurado, lo que significa que está diseñado y realizado de
manera tal que permita hacer programas que, divididos en partes (bloques), pueden ser
compilados de manera separada. El componente principal del lenguaje estructurado, es la
función, entendida como un bloque constructor en Lenguaje C, y que posteriormente se
tratarán.
Además, el Lenguaje C es un lenguaje portable, puesto que es independiente de las
plataformas en las que se desarrolle y/o ejecute. Para el LINUX, existen varios
compiladores, como el gcc, o el cc; para el DOS, el Turbo C/C++, y para el Windows, el
Borland C/C++ y el Dev-C++.
Ejemplo.
Los tres programas hacen exactamente lo mismo: muestran en la pantalla un texto que dice:
“Hola, Mundo!”.
Fig. 1.1. Ventana de resultado de programa “Hola, Mundo!”.
14
Bajo nivel (ensamblador
para DOS X86)
.model small
.stack
.data
Cadena1 DB 'Hola,
Mundo!.$'
.code
programa:
mov ax, @data
mov ds, ax
mov dx, offset Cadena1
mov ah, 9
int 21h
end programa
Nivel medio (Lenguaje C)
#include <stdio.h>
int main(int argc, char
**argv)
{
printf("Hola, Mundo!\n");
return 0;
}
Alto nivel (Pascal)
PROGRAM
Holamundo(output);
BEGIN
WriteLn('Hola, mundo!')
END.
Tabla 1.1. Cuadro comparativo de los tres niveles (bajo, medio y alto)
de lenguajes de programación.
Para desarrollar los programas en Lenguaje C, podemos encontrar diferentes ambientes
para el efecto.
1.1.2. Ambiente de desarrollo
15
¿Recuerdas lo que son los ambientes de desarrollo y su utilidad? Si no tienes muy claro el
concepto, revisa tu libro y/o los apuntes de la asignatura de Fundamentos de Programación.
Por ejemplo, bajo sistema operativo MS-DOS, podríamos encontrar el Turbo C (versión
2.0) el cual, en algunos casos, se encuentra ubicado en el directorio C:\TC>, así que para
ejecutar ese programa, es necesario escribir en el indicador del sistema operativo:
C:\TC> TC
(En caso de que cuentes con el Borland C++, entonces tendrías el directorio C:\BC\BIN>, y
lo ejecutarías con un C:\BC\BIN>BC)
Y entonces aparecerá la pantalla una serie de opciones, que son:
Fig. 1.2. Menú principal del Turbo C/C++ v.3.0.
File Edit Search Run Compile Debug Project Options Window Help
Así que para la edición y ejecución de un programa, entraremos al menú File, que
presentará un submenú, que contendrá
16
Fig. 1.3. Sub Menú Archivo de Turbo C/C++ v.3.0.
New Nuevo archivo
Open F3 elegir un archivo previamente grabado
Save F2 grabar el archivo en pantalla
Save as… guardar con un nombre diferente
Save all guardar todo
Change dir cambiar de directorio actual de trabajo
Print imprimir
DOS shell salir en forma temporal del Turbo C
Quit Alt-X salir en forma permanente del Turbo C
Y para la ejecución de un programa, se hará eligiendo el menú Run y el submenú Run ctrl-
F9 o simplemente, manteniendo presionada la tecla <Control> y presionando entonces la
tecla <F9>
17
Fig. 1.4. Sub Menú Run de Turbo C/C++ v.3.0.
Pudiera ser también que se esté usando el DEV-C++ (que lo podrás encontrar en la
dirección www.bloodshed.net ) y que opera bajo licencia GNU, es decir, es código abierto,
y que funciona bajo Windows, y tiene una interfaz muy intuitiva.
Fig. 1.5. Pantalla de edición del Dev-C++ v.4.9.9.2.
18
Una mención aparte merece tanto la edición como la compilación bajo el sistema operativo
LINUX.
Asumimos que cuando nos referimos a programar en Lenguaje C bajo LINUX (estoy
usando un Mandriva 2006), los programas se van a escribir usando el editor de pantalla
(vi), y se van a compilar y ejecutar desde la línea de comando.
Hagamos la primera prueba para dejar clara la manera en que vamos a manejarnos en
LINUX.
Y como todo programador que se precie ha de iniciar con un programa que ponga en
pantalla un “Hola, Mundo!” pues que no sea esta la excepción, así que vamos a hacerlo.
Escribe en tu línea de comando:
Fig. 1.6. Forma de acceder al editor de pantalla “vi” en LINUX
19
La parte de [gallardo@horus ~]$ es la manera como aparece el inductor o prompt de
LINUX en mi computadora, así que no va en la línea de comando. Ahora, a teclear el texto
de nuestro primer programa en C.
Fig. 1.7. Texto del programa.
Terminando de teclear el programa, y para salir del editor “vi”, pulsamos la tecla <esc> y
después las teclas <:><w><q> que significan write y quit para escribir el programa y salir.
El archivo ya está en nuestro directorio home, así que vamos a proceder a compilarlo. El
compilador va a permitirnos detectar errores si los hubo y además convertir nuestro código
fuente (lo que escribimos dentro del archivo, en este caso denominado ejemplo.c) en un
programa ejecutable.
Si lo compilamos de manera básica, se realizará de la siguiente manera:
[gallardo@horus ~]$ gcc ejemplo.c
20
Y así, obtendremos el archivo denominado a.out
Así que si queremos ejecutarlo, tendremos que hacerlo escribiendo en la línea de comando:
[gallardo@horus ~]$./a.out
Y obtendremos de regreso:
Hola, Mundo!
y el prompt del sistema operativo.
Si vemos el proceso completo, sería de la siguiente manera:
Fig. 1.8. proceso de edición, compilación y ejecución
de un programa en LINUX.
Debemos aclarar que por default se genera un archivo que se denomina ejemplo.o que es el
código objeto. Si queremos ver este archivo, lo podemos obtener mediante la orden:
21
[gallardo@horus ~]$ gcc -c ejemplo.c
El contenido no puede leerse, no es texto. Evidentemente, no genera por defecto un archivo
ejecutable con el nombre del archivo que contiene el código fuente. Para hacer ésto, es
necesario utilizar el comando cc de la manera siguiente:
[gallardo@horus ~]$ gcc -o ejemplo ejemplo.c
Así que el proceso completo, ya habiendo sido creado el archivo, sería también factible
usando:
Fig. 1.9. proceso para crear un archivo ejecutable
con nombre propio en LINUX
22
En 1972, se creó el Lenguaje C como un perfeccionamiento de uno anterior llamado B, por
parte de Dennis Ritchie, y el libro de “The C Programming Language” que se editó por
parte de Prentice Hall en 1978 tuvo un éxito impresionante.
En 1980, Bjarne Stroustrup diseñó una extensión de Lenguaje C y le llamó “C con clases”.
En 1984, el “C con clases” es rediseñado conjuntamente con un compilador y ahora es
denominado como C++; Addison-Wesley publicó el libro “C++ Programming Language”
en 1986. El término C++ se acuñó por ser un la Programación Orientada a Objetos (basada
en Simula 67) un valor agregado al C original, y en Lenguaje C el operador “++” es un
operador de incremento.
Tanto la ANSI (American National Standards Institute, Instituto Nacional Estadounidense
de Estándares) como la ISO (International Organization for Standardization, Organización
Internacional para la Estandarización) trabajaron conjuntamente y lograron la
estandarización del Lenguaje C desde 1989 hasta 1990.
Al día de hoy, la versión estandarizada de C (versión 3.0) es la que usan la mayoría de
fabricantes, como Microsoft, AT&T, Borland y Watcom.
1.1.3. Versiones
23
Bajo el sistema operativo LINUX, el gcc (GNU Compiler Collection) es el compilador de
la GNU para C, básicamente, aunque soporta varios lenguajes, como el ANSI C, el K&R C,
el C++ y el Objective C.
En la construcción de un programa en Lenguaje C, puedes usar como identificadores de
variables o de constantes cualquier palabra, o la combinación de todas las letras que gustes.
Sin embargo, hay palabras que sólo usa el compilador de C como funciones y que se llaman
Palabras Reservadas. Estas no las puedes utilizar como nombres de variables ni constantes.
Las 32 palabras reservadas de lenguaje C definidas por el estándar ANSI son:
auto break case
char const continue
default do double
else enum extern
float for goto
if int long
register return short
signed sizeof static
struct switch typedef
union unsigned void
volatile while
1.1.4. Palabras reservadas
24
Debiendo hacer notar que cada una de las palabras reservadas, son escritas en minúsculas.
Lenguaje C discrimina entre el uso de mayúsculas y minúsculas, pero aún así, los nombres
de las palabras reservadas, aún modificadas con mayúsculas, no es prudente usarlas como
nombres de variables, o de constantes en un programa.
25
Actividades de aprendizaje.
Con el propósito de reforzar lo aprendido hasta este momento, realiza las siguientes
actividades.
1.- Enumera las ventajas del Lenguaje C y define en qué consiste cada una de ellas.
2.- Observa atentamente las tres fracciones de código (de ensamblador, de Pascal y de
Lenguaje C) que están escritas en el subtema 1.1.1. y menciona cuáles son las diferencias, y
explica por qué consideras que se usa el Lenguaje C para la programación estructurada.
3.- Describe paso a paso el proceso que se sigue para editar, compilar y ejecutar un
programa desde LINUX.
4.- Contesta, si el compilador te genera un archivo de nombre a.out, y tu quieres que lleve
el nombre de programa01, ¿qué debes hacer?
5.- Haz un ejercicio de memoria, lee tres veces las palabras reservadas de C, y luego trata
de escribir todas las que recuerdes, las palabras fueron acomodadas en orden alfabético para
mayor facilidad de apropiación.
26
Resumen.
Para facilitar y posibilitar la comprensión de los conceptos aprendidos, así como la
apropiación del conocimiento, se te presenta el siguiente Mapa Conceptual.
27
Todos los programas en C consisten en una o más funciones. La única que debe estar
siempre presente es la función main( ), porque es la primera función que es llamada al
iniciar la ejecución del programa.
La forma general de un programa en C es la siguiente:
Directivas del preprocesador
declaraciones_globales
main( ){
variables_locales
/* Esta línea es un comentario */
/*
Estas son tres líneas que
Son un comentario también
Y pueden escribirse las que se deseen
*/
secuencia_de_sentencias
}
f1( ){
variables_locales
secuencia_de_sentencias
}
1.2 Estructura de un programa en C
28
En cuanto a la primera línea, “Directivas del preprocesador”, puede contener lo siguiente:
Ejemplo:
#include <stdio.h> que puede ser también #include “stdio.h”
/*se incluye el archivo de entrada y salida estándar */
#define CIERTO 1
/* cuando el programa encuentre CIERTO en su código, lo va a tomar como un 1*/
#define ES “error estándar de la salida\n”
/*ES será sustituida con la cadena de error en el lugar donde se encuentre*/
En la segunda línea, “declaraciones globales” contendrá las variables y/o constantes que
van a ser válidas a través de todo el código fuente.
Ejemplo:
int a,b,c;
#include <nombre_del_archivo_de_cabecera.h>
#define variable valor_de_la_variable
#define macro código_de_la_macro
29
Las declaraciones locales, se refieren a variables y/o constantes definidas solamente para la
fracción de código encerrada entre los delimitadores ‘{‘ y ‘}’ que conforman un bloque.
Por secuencia_de_sentencias, entenderemos a la serie de órdenes que se escriben en el
código fuente, y que conforman las acciones que la computadora tomará.
Además, hay una característica de Lenguaje C, y es que cada sentencia, termina con un
punto y coma, de la siguiente manera:
sentencia;
Y si llegara el caso de que escribamos varias sentencias, una tras otra en una sola línea
dentro del código, pues se van a ejecutar, porque el final de una sentencia no es el cambio
de línea, sino el punto y coma, así, podríamos escribir lo siguiente:
sentencia1; sentencia2; sentencia3;
y las tres serían ejecutadas en ese orden por el compilador.
En el transcurso del presente texto, hay términos que van a ser usados con cierta frecuencia, y que es
necesario que quede bien definidos que te familiarices con ellos.
Términos usuales
30
Código fuente: es el texto que el programador escribe usando el editor, también se conoce
como el programa. Es la entrada del compilador de Lenguaje C. e.g. ejemplo.c
Código objeto: es el resultado de traducir el código fuente a código máquina. Este es la
entrada al enlazador. e.g. ejemplo.o (en Linux), o ejemplo.obj (en MS-DOS o Windows).
Enlazador o encadenador: es un programa que enlaza el código objeto con la librería
estándar, y del que resulta el código ejecutable. e.g. ejemplo (en Linux), o ejemplo.exe (en
MS-DOS o Windows).
Librería o biblioteca: es un archivo que contiene todas las funciones estándar de entrada y
salida, y otras rutinas igualmente útiles. E.g. stdio.h, conio.h, string.h
Tiempo de compilación: son todos los eventos que tienen lugar en el momento de la
compilación del programa.
Tiempo de ejecución: son todos los eventos que tienen lugar en el momento de la ejecución
del programa.
Existe una relación entre estos términos, que intentaré ilustrar a continuación con una
analogía entre el proceso de creación de un programa y el de hacer vino.
31
[aquí va un auxiliar con imágenes para realizar una analogía sobre lo que está descrito
anteriormente]
[hoja de texto] - - - - - > [caja] - - - - > [hoja de texto] - - - - - > [caja] - - - - - > [icono]
Código compilador código enlazador programa
Fuente objeto ejecutable
Lo anterior sería algo parecido al proceso de elaboración del vino.
[racimo] - - - - - > [ caja] - - - - - - > [vaso] - - - - - - - - >[caja] - - - - - - > [botella]
Uvas molino jugo de uva cuba de vino
añejamiento
32
Actividades de aprendizaje.
Con el propósito de reforzar lo aprendido hasta este momento, realiza las siguientes
actividades.
1.- Escribe la forma que tiene el esqueleto completo de un programa en Lenguaje C, y
explica por qé la función main( ) debe estar siempre presente.
2.- En el Tema 1.2 hay una analogía del proceso que se lleva a cabo para convertir un
listado de código fuente en un programa ejecutable. La analogía es la de las uvas, que
sufren un proceso hasta convertirse en vino. Realiza otra analogía que se te ocurra, y
coméntala con tus compañeros. Esta actividad, se considera muy importante realizarla, pues
va a hacerte razonar para encontrar la analogía, y a reflexionar sobre el proceso para
encontrar uno que se le parezca.
33
Resumen.
Para que quede mejor comprendida la manera en que se crea el código fuente de un
programa en C, y para facilitar la aprehensión del conocimiento visto a lo largo de este
tema, se te presenta el siguiente Mapa Conceptual.
PROGRAMAO CÓDIGO FUENTE
directivas_del_preprocesadordeclaraciones_globalesmain( ){ variables_locales secuencia_de_sentencias}
Debe tener
f1( ){ variables_locales secuencia_de_sentencias}...fn( ){ variables_locales secuencia_de_sentencias}
Puede tener
COMPILADOR
ENLAZADOR
CÓDIGO OBJETO
PROGRAMA EJECUTABLE
Entra al
Produce
Entra al
Produce
34
Por dato, entendemos a esa mínima unidad que compone la información, de hecho es
carente de sentido por sí mismo, pero en conjunto con otros datos dan un significado lógico
y coherente que llamaremos información. Su nombre es una palabra latina y significa “lo
que se da”. En un sistema computacional, los datos son la entrada al sistema, en el cual son
procesados y convertidos en información.
Encontramos en el Lenguaje C cinco tipos básicos de datos, carácter (char), entero (int),
punto flotante (float), punto flotante de doble precisión (double) y vacío (void), cuyo
tamaño y rango están definidos enseguida.
Tipo Tamaño en bits Rango
char 8 0 a 255
int 16 -32768 a 32767
float 32 3.4E-38 a 3.4E+38
double 64 1.7E-308 a 1.7E+308
void 0 Sin valor
Veamos entonces la relación que guarda el tamaño en bits con el rango de valores que
puede guardar. Recordarás aquí el sistema de numeración binario, en donde cada dígito
1.3 Tipos de datos.
1.3.1. Tipos básicos
35
(que sólo puede ser 0 y 1), tiene un valor posicional, mediante el cual podríamos escribir
en un octeto, del tipo carácter (char) , desde el número 0 base diez, que equivaldría a 0 0 0
0 0 0 0 0 hasta el número 255 base diez, que equivaldría a 1 1 1 1 1 1 1 1 , pues su valor
posicional está dado por:
MSB 128 64 32 16 8 4 2 1 LSB
27 26 25 24 23 22 21 20
0 0 0 0 0 0 0 0 equivale a 0 decimal
1 1 1 1 1 1 1 1 equivale a 255 decimal
Debes notar que a un lado del bit cuyo valor es 128 (27) están las letras MSB (More
Significative Bit) que es el bit más significativo, es decir, el que tiene el mayor valor del
octeto. De la misma manera, a un lado del bit cuyo valor es 1 (20) , están las letras LSB
(Less Significative Bit) que es el bit menos significativo es decir, el que tiene el menor
valor de todo el octeto.
También por simple inspección, podemos darnos cuenta de cuánto suman cierta cantidad de
bits, por ejemplo, para saber cuánto suman 4 bits haríamos una fórmula muy sencilla:
Suma_de_n_bits = 2n -1
¿Es esto verdad? Veamos. Con cuatro bits, sería lo siguiente:
36
8 4 2 1
23 22 21 20
1 1 1 1 equivale a la suma de 8 + 4 + 2 + 1 = 15
Utilizando la fórmula:
Suma_de_4_bits= 24 – 1 = 16 – 1 = 15
Suma_de_8_bits = 28 – 1 = 256 – 1 = 255
Suma_de_16_bits= 216 -1 = 65536 – 1 = 65535
Entonces, ¿por qué el tipo de datos entero (int) va desde -32768 hasta 32767? La respuesta
es que de los 16 bits en los que se puede representar, el bit más significativo, se usa como
indicador de signo, si es un 1 es un signo negativo, y si es un 0 es un signo positivo, así que
las cantidades se están representando solamente con 15 bits, cuya suma sería 215 -1 = 32768
que pueden ser representados con esos 15 dígitos el número más bajo entonces sería:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 equivale a -32768, pues el primer bit está a uno,
el número más alto sería:
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 equivale a 32767, pues el primer bit está a cero.
El caso del tipo de punto flotante (float), se representa mediante un número llamado
mantisa, por una base elevada a una potencia entera, que se denomina exponente. La base
es fija y la mantisa y el exponente varían. Por ejemplo, para representar el número 123.45
se representaría como 12345 x 10-2. La mantisa es 12345 y el exponente es -2. En la
notación de punto flotante que estamos describiendo, la cantidad se representa mediante un
37
número de 32 bits. Los primeros 24 representan la mantisa, seguida de un exponente de 8
bits y su rango iría desde 3.4x10-38 hasta 3.4x1038.
En el caso del tipo punto flotante de doble precisión (double) ocurriría lo mismo, sólo que
con 64 bits, de los cuales 56 serían la mantisa y un exponente de 8 bits. Sus valores irían
desde 1.7x10-308 hasta 1.7x10308.
Para el tipo denominado vacío (void) se puede usar de tres maneras distintas, la primera, es
cuando se declara una función que no va a regresar ningún valor, por ejemplo:
Si no se declara void y se deja vacío el campo del tipo de la función, por default, es int.
Esto es en la primera línea de la función, “void suma( )” está indicando que es una función
denominada suma que no devuelve ningún valor.
La segunda manera, es cuando se declara una función que no va a usar argumentos, por
ejemplo:
void resta(void){
int a,b,c;
void suma( ){ int a,b,c; c=a+b; printf(«la suma de %d mas %d es igual a %d», a, b, c); }
38
c=a-b;
printf («la resta de %d menos %d, es igual a %d», a, b, c);
}
Donde se declara el void dentro del paréntesis del nombre de la función, y esto indica que
no se van a usar argumentos. Si se deja vacío el espacio que especifica los parámetros a
usar, por default, lo tomará el compilador de C como void.
La tercera manera, es para crear punteros genéricos.
Bien, pues existen diferentes modificadores, y para simplificarlos, vamos a verlos de tipo
en tipo, iniciando en el orden en que los vimos.
a. Tipo char: puede tomar dos valores: el “signed char” y el “unsigned char”.
El “unsigned char”, usará todos sus bits para representar las cantidades, desde
0 0 0 0 0 0 0 0 que equivale a cero decimal, hasta
1 1 1 1 1 1 1 1 que equivale al 255 decimal
El “signed char” usará el bit más significativo para indicador de signo, por lo que solamente
usará siete bits para representar cantidades, así que irá desde
1.3.2. Modificadores
39
1 1 1 1 1 1 1 1 que equivale al -128 decimal, hasta
0 1 1 1 1 1 1 1 que equivale al 127 decimal
b. Tipo int: puede tomar siete valores, “unsigned int”, “signed int”, “short int”, “unsigned
short int”, “signed short int”, “long int”, “signed long int”.
El “unsigned int” y el “unsigned short int”, usarán sus 16 bits para representar las
cantidades, que irán desde
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 que equivale a 0 decimal y el más alto
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 que equivale a 216 – 1 = 65535
El “signed int”, el “short int” y el “signed short int” usarán el primer bit para identificador
del signo, así que sólo usarán 15 bits para representar cantidades, luego entonces, su rango
más bajo será
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 que equivale a -32768 decimal y el más
alto sería
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 que equivale a 32767 decimal
El “long int” y el “signed long int” son enteros que usan el doble de bits, usan 32 bits para
ser representados, pero el más significativo se usa como indicador de signo, así que
quedarían 31 bits para representar cantidades, por lo que el número más bajo del rango,
sería:
40
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 que
equivale a la cantidad de -21474836648 decimal y el más alto
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 que
equivale a la cantidad de 21474836647 decimal
c. Tipo float: No tiene modificadores.
d. Tipo double: Puede tomar dos valores, “double” y “long double”, pero en ambos casos,
son números de 64 bits, representando 56 de ellos la mantisa y 8 el exponente.
e. Tipo void: No tiene modificadores.
Veamos la siguiente tabla que contiene los tipos básicos y subtipos generados por los
modificadores, su tamaño en bits y un ejemplo de un dato que coincida con el tipo.
Tipo Tamaño
En bits
Rango Ejemplo
char 8 -128 a 127 -45
unsigned char 8 0 a 255 210
signed char 8 -128 a 127 33
int 16 -32768 a 32767 -15432
unsigned int 16 0 a 65535 53987
signed int 16 -32768 a 32767 -23456
short int 16 -32768 a 32767 32335
41
unsigned short int 16 0 a 65535 61298
signed short int 16 -32768 a 32767 15677
long int 32 -2147483648 a 2147483647 1298754663
signed long int 32 -2147483648 a 2147483647 -2098374566
float 32 3.4E-38 a 3.4E+38 65443345.877
double 64 1.7E-308 a 1.7E+308 9999999999.9
long double 64 1.7E-308 a 1.7E+308 8976788788.1
void 0 Sin valor Sin valor
Tabla 1.2 Totalidad de las combinaciones de los tipos básicos de datos en C.
Si yo requiero que una expresión sea de un tipo específico, es posible que necesite forzarla,
y para eso, se usa una construcción que se suele llamar molde, y que tiene la forma general
de:
(tipo) expresión
Así, la expresión “expresión” tendrá como resultado forzoso el tipo “tipo”, lo cual quizás
quedará un poco mejor explicado con un ejemplo.
Ejemplo.
1.3.3 Moldes
42
Al ejecutarlo, obtenemos la siguiente respuesta:
1 / 3 = 0.333333
2 / 3 = 0.666667
3 / 3 = 1.000000
4 / 3 = 1.333333
5 / 3 = 1.666667
6 / 3 = 2.000000
7 / 3 = 2.333333
8 / 3 = 2.666667
9 / 3 = 3.000000
10 / 3 = 3.333333
Como en el ejemplo, estamos usando a la variable ‘a’ como la variable de control del ciclo
“for”, si hubiéramos dejado la expresión como: printf(“%d / 3 = %f \n”, a, a/3), se habría
#include “stdio.h” main( ){ int a; for (a=1; a<=10; a++) printf(“%d / 3 = %f \n”, a, (float) a/3); /* aquí se hace la impresión de a como entero y después a/3 como punto flotante*/ return 0; }
43
impreso en la pantalla el entero y la división entera, pero si queremos visualizar los
decimales, le aplicamos el molde para forzar la salida a que sea de punto flotante
44
Actividades de aprendizaje.
Con el propósito de reforzar lo aprendido hasta este momento, realiza las siguientes
actividades.
1.- Rellena esta pequeña tabla donde tengas dos columnas correspondiéndose, la una
conteniendo los cinco tipos básicos de datos de Lenguaje C, y la otra su tamaño en bits. Es
muy importante que se tenga presente el tamaño en bits de los tipos para conocer la
cantidad de memoria que estamos utilizando al reservar parte de la misma, en el momento
de declarar las variables.
Tipo Tamaño
2.- Basado en los valores posicionales que tienen los bits de un octeto o byte, escribe el
número 247.
45
128 64 32 16 8 4 2 1
3.- Usando 16 bits (dos bytes) para representar un número entero, representa el -13579.
Coloca primero a uno el signo del bit de signo, para indicar que es negativo. Luego busca
los números (partiendo del mayor más próximo y siguiendo con los menores) que sumen
13579, y colocando a uno el bit de cada casilla del número que se va usando.
signo 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1
4.- Explica cómo se usa el tipo de datos vacío en sus tres formas.
5.- Realiza la escritura de una tabla de dos columnas relacionadas, donde tengas, en la
primera los 15 tipos y subtipos de datos del Lenguaje C y en la otra, el tamaño
correspondiente.
Tipo o subtipo Tamaño
47
Resumen.
Se te presenta este resumen para que repases y reafirmes el conocimiento sobre los tipos de
datos básicos y los subtipos.
Encontramos que en el Lenguaje C, existen cinco tipos de datos básicos, que son carácter
(char), entero (int), punto flotante (float), punto flotante de doble precisión (double) y vacío
(void). Además, existen diferentes modificadores de tipo para los tipos básicos. En una
tabla que conjunta los tipos, subtipos, tamaño y rango de los mismos, quedaría de la
siguiente manera.
Tipo Tamaño Rango
En bits
char 8 -128 a 127
unsigned char 8 0 a 255
signed char 8 -128 a 127
int 16 -32768 a 32767
unsigned int 16 0 a 65535
signed int 16 -32768 a 32767
short int 16 -32768 a 32767
unsigned short int 16 0 a 65535
signed short int 16 -32768 a 32767
48
long int 32 -2147483648 a 2147483647
signed long int 32 -2147483648 a 2147483647
float 32 3.4E-38 a 3.4E+38
double 64 1.7E-308 a 1.7E+308
long double 64 1.7E-308 a 1.7E+308
void 0 Sin valor
En el caso de ser números sin signo (unsigned) usarán la totalidad de los bits que definen su
tamaño. Pero si son números que usan signo (signed) entonces usan el bit más significativo
como indicador de signo, y los restantes para representar las cantidades.
Sólo en el caso de punto flotante (float), se representa mediante un número llamado
mantisa, por una base elevada a una potencia entera, que se denomina exponente. La base
es fija y la mantisa y el exponente varían. Los primeros 24 bits representan la mantisa,
seguida de un exponente de 8 bits. Y para el caso de los datos de punto flotante de doble
precisión (double) son números de 64 bits, representando 56 de ellos la mantisa y 8 el
exponente.
Los moldes sirven para forzar la salida a un tipo de datos que nosotros deseamos, para lo
cual, podemos emplear su forma general y obtener el resultado deseado.
49
Una variable es un nombre que almacena un dato, y que puede conservar o variar su valor
en el transcurso del programa.
Todas las variables, para poder ser usadas, deben declararse mediante la forma
tipo variable; o si son varias,
tipo lista_de_variables;
donde “lista_de_variables” son los identificadores (nombres) de las diferentes variables,
separadas por una coma.
Ejemplo.
int j, k, l;
/*declara tres variables: j, k y l que son de tipo entero*/
float n;
/*declara una variable de nombre n que es de tipo de punto flotante*/
double cantidad, saldo;
/*declara dos variables: cantidad y saldo que son de tipo de punto flotante de doble
precisión*/
Existen tres sitios en donde pueden declararse las variables, que son:
1.4 Declaración de variables y constantes
50
- Dentro de las funciones (variables locales o automáticas)
- En los parámetros de una función (parámetros formales)
- Fuera de cualquier función (variables globales)
Ejemplo:
Debemos notar que cuando una función va a usar argumentos, se declaran como parámetros
formales, de la manera que se muestra en el ejemplo anterior “int suma (int a, int b)”, y así
en el cuerpo del programa, se llamará a la función, por ejemplo, mediante la orden:
suma(2,3);
Cuando se declara una variable, solamente es válida para la función que se declaró. Veamos
un ejemplo:
int producto; /*producto es una variable global*/ int suma(int a, int b){ /*a y b son parámetros formales*/ int resultado; /*resultado es una variable local*/ resultado=a+b; return resultado; }
51
Vamos a realizar la captura de un pequeño programa que muestra la ubicación de las
diferentes variables.
Capturamos pues, mediante el vi (si estás usando LINUX, y si no, mediante el editor del
compilador de tu preferencia), un nuevo código, mediante la orden:
[gallardo]$ vi prog01.c
y escribimos el código siguiente:
main( ){ codigo_de_main; } funcion1( ){ int a; /*a es válida solamente dentro de esta función*/ código_de_la_función_1 } funcion2(){ int a; /*esta variable ‘a’ es diferente de la de la función 1, y es válida solamente para esta función*/ código_de_la_función_2 }
52
lo terminamos con un
<Esc> :wq
y lo compilamos mediante el comando
[gallardo]$ cc -o prog01 prog01.c
y luego lo ejecutamos mediante el comando
./prog01.c
#include “stdio.h” void func1(void), func2(void); int cuenta; /*variable global*/ man( ){ cuenta=100; func1( ); printf(‘\n’); return 0; /*éxito del programa*/ } void func1( ){ int temp; temp=cuenta; func2(); printf(“cuenta es %d”, cuenta); } void func2( ){ int cuenta; /*cuenta es local, no es igual a la otra variable cuenta, aquí solamente es la variable de control para el ciclo for*/ for(cuenta=1;cuenta<10;cuenta++) putchar(‘.’); }
53
Todo lo anterior en caso de capturarse bajo LINUX, si no, compilar y ejecutar usando el
ctrl.-F9
obtendremos como resultado:
.........cuenta es 100
¿Es el resultado que obtuviste? Si no fue así, vuelve a revisar paso a paso desde la captura
del programa.
Constantes
Las constantes son valores fijos, que no pueden ser alterados a través de todo el programa.
Pueden ser de cualquier tipo de datos, veamos unos ejemplos
char ‘s’ ‘\n’ ‘9’
int 3 976 12987
float 1234.567
double 12345678.9
además, existen en C las constantes de cadena, por ejemplo como «Guadalajara Jalisco»
54
Una mención aparte tienen las constantes de barra invertida (backslash), que son las
siguientes:
Constante significado
\n new line línea nueva
\t horizontal tab tabulador horizontal
\v vertical tab tabulador vertical
\b backspace retroceso
\r carriage return salto de línea
\f form feed salto de página
\a alert alerta
\\ backslash diagonal (barra) invertida
\? Question mark signo de interrogación
\’ single quotation mark comilla simple
\” double quotation mark comillas dobles
\o octal number constante octal
\x hexadecimal number constante hexadecimal
\0 null character caracter nulo
Tabla 1.3 Constantes de barra invertida
55
Actividades de aprendizaje.
Con el propósito de reforzar lo aprendido hasta este momento, realiza las siguientes
actividades.
1.- Escribe los tres lugares donde pueden ser declaradas las variables.
2.- En la tabla que sigue, escribe las constantes de carácter que faltan.
Constante significado
\n
\t tabulador horizontal
\v tabulador vertical
\b
\r salto de línea
\f salto de página
\a alerta
\\
\? signo de interrogación
\’ comilla simple
\” comillas dobles
\o
\x
\0 caracter nulo
56
Resumen.
Con el propósito de facilitar el aprendizaje del tema que se acaba de ver, se presenta el
siguiente resumen.
Una variable es un nombre que almacena un dato, y que puede conservar o variar su valor
en el transcurso del programa. Todas las variables, para ser usadas, primero deben ser
declaradas, si es una sola, con la expresión “tipo variable” y si son más de una, con la
expresión “tipo lista_de_variables”.
Existen tres sitios en donde pueden declararse las variables, que son:
- Dentro de las funciones (variables locales o automáticas)
- En los parámetros de una función (parámetros formales)
- Fuera de cualquier función
Las constantes son valores fijos, que no pueden ser alterados a través de todo el programa.
Las constantes de barra invertida son las siguientes:
Constante significado
\n línea nueva
\t tabulador horizontal
\v tabulador vertical
\b retroceso
57
\r salto de línea
\f salto de página
\a alerta
\\ diagonal (barra) invertida
\? signo de interrogación
\’ comilla simple
\” comillas dobles
\o constante octal
\x constante hexadecimal
\0 caracter nulo
58
Los operadores son símbolos que indican al compilador que lleve a cabo ciertas
manipulaciones matemáticas o lógicas de los datos. Hay una variedad de ellos, pero los que
se consideran más importantes para el trabajo que se va a realizar con el estudiante en este
libro, solamente nos remitiremos a cuatro: Aritméticos, Relacionales, Lógicos, y de
Incremento/Decremento. A continuación se toman cada uno de ellos para su explicación
respectiva.
Operadores aritméticos son aquellos que nos permiten realizar básicamente cualquier
operación aritmética necesaria, como suma, resta, multiplicación, división, etc.:
Operador Acción
- resta, menos monario
+ suma
* multiplicación
/ división entera
% división en módulo
Ejemplo.
1.5 Operadores
1.5.1. Aritméticos, relacionales y lógicos.
59
a=10; b=3;
r = a - b; /* r vale 10 – 3 = 7*/
r = - a; /* r vale -10 */
r = a + b; /* r vale 10 + 3 = 13 */
r = a * b; /* r vale 10 * 3 = 30 */
r = a / b; /* r vale 10 / 3 = 3 */
r = a % b; /* r vale 10 % 3 = 1 */
La diferencia entre los operadores ’/’ y ‘%’ es el siguiente: la división empleada por el
operador ‘/’ es una división entera, es decir el entero, sin fracciones que resulta de dividir,
en el ejemplo, 10 entre 3, que es 3, no importa la fracción decimal. Sin embargo, el
operador ‘%’ se usa para realizar una división en módulo, que significa que arrojará como
resultado el residuo de la división, en el ejemplo, al hacer 10%3 el residuo de la división,
será 1, así que ese será el resultado de la misma.
Operadores relacionales son los que nos permiten evaluar las relaciones que existen entre
dos operandos, como la igualdad o desigualdad, el ser mayor o menor, etc.:
Operador Acción
> mayor que
>= mayor o igual a
< menor que
<= menor o igual a
60
= = igual a
! = diferente de
Ejemplo.
Capturemos el siguiente programa.
Devolverá los valores de 1 cuando sea verdadera, y 0 cuando sea falsa:
1 1 0 0 0 1
#include “stdio.h” main( ){ int a, b, r;
a=10; b=3; r=a > b; /* expresión verdadera */ printf(“%d\n”, r); r=a >= b; /* expresión verdadera */ printf(“%d\n”, r); r=a < b; /* expresión falsa */ printf(“%d\n”, r); r=a <= b; /* expresión falsa */ printf(“%d\n”, r); r=a = = b; /* expresión falsa */ printf(“%d\n”, r); r=a ! = b; /* expresión verdadera */ printf(“%d\n”, r); return 0;
}
61
Operadores lógicos son los que nos permiten conectar dos propiedades:
Por lo que se refiere a los operadores lógicos, la base que tenemos que tomar es el valor que
toman cuando son falsos, que es un 0, y cuando son verdaderos, que es cualquier número
diferente de 0. En el caso de ambos operadores, tanto relacionales como lógicos,
devolverán el valor de 0 cuando son falsos y de 1 cuando son verdaderos.
Operador Acción
&& and
| | or
! not
Si utilizamos un medio para entender las reglas que dominan sobre los operadores deberían
ser las tablas de verdad. Mediante ellas veremos cómo actúan los operadores lógicos: La
tabla de verdad para los operadores lógicos es la siguiente:
p q p && q p | | q !p
0 0 0 0 1
0 1 0 1 1
1 0 0 1 0
1 1 1 1 0
62
es decir, que para el operador AND (&&) el resultado será verdadero solamente cuando
ambos operandos sean verdaderos.
Para el operador OR ( | | ) el resultado solamente será falso, si ambos operandos son falsos.
Para el operador NOT ( ! ) la tabla de verdad es mucho más simple: NO FALSO =
VERDADERO y NO VERDADERO = FALSO.
Para ilustrar el uso de estos operadores, vamos a poner unos ejemplos, con el deseo de que
queden lo más claro posible.
Ejemplo.
Capturemos el siguiente programa
#include «stdio.h» main(){ int a, b, c; a=3; b=5; c=7; if (a<b && b<c) printf(«AND verdadero\n»); /* a<b es verdadero Y b<c también */ if (a<b | | b<c) printf(«OR verdadero\n»); /* a>b es falso, pero b<c es verdadero */ if (!(a>b)) printf («NOT verdadero»); /*como a>b es falso, con el NOT se hace verdadero*/ return 0; }
63
Después de compilar y ejecutar, obtendremos el siguiente resultado:
AND verdadero
OR verdadero
NOT verdadero
Debemos notar lo siguiente: en cada uno de los casos se usó la forma de
si (condición)
imprime (mensaje);
esto significa que sólo se imprimirá si el resultado del if es verdadero, esa es la razón por la
que en el caso del OR escribí una falsa y una verdadera, para que el resultado fuera
verdadero; recordemos que 0 || 1 = 1
A las órdenes o comandos que se escriben en el transcurso del código fuente de un
programa, se les llama sentencias. La forma general de la sentencia de asignación es la
siguiente:
Nombre_de_la_variable = expresión;
1.5.2. Sentencias de asignación.
64
Reforzaremos lo anterior, mencionando que a la izquierda siempre estará una variable,
luego un simple signo de igual ( = ) y a la derecha una expresión que pudiera ir desde una
simple constante hasta una expresión muy compleja. Lo que debemos aprender a interpretar
es lo siguiente: la variable de la izquierda toma el valor del resultado de la expresión de la
derecha.
Por ejemplo, cuando vemos la expresión:
limite = 100;
Significa que la variable de nombre limite, tomará a partir de este momento, el valor de
100.
Puede darse que cuando se hagan asignaciones, se mezclen variables de diferentes tipos, y
eso se soluciona mediante la conversión de tipos en las asignaciones. La regla de estas
conversiones, es sumamente sencilla: el valor de la expresión del lado derecho, se convierte
al tipo de la variable que recibe (la del lado izquierdo).
Sin embargo, no deben perderse de vista dos situaciones importantes:
65
a.- La conversión de un int (16 bits) a un float (32 bits), o de un float (32 bits) a un double
(64 bits), no agregará seguridad ni precisión, sólo cambiará la manera en que están
representados los números.
b.- Quizás tu compilador de C tratará a una variable char siempre como positiva, aunque se
convierta a un valor int o float. O tal vez tratará a los números mayores a 127 como si
fueran números negativos en el proceso de conversión, pues el bit más significativo estará
puesto a 1.
Operadores de incremento y decremento son los que permiten aumentar o disminuir en una
unidad el valor de una variable:
Operador Acción
-- decremento
++ incremento
Ejemplo.
a=10; b=3;
r = -- a; /* r vale 10 - - igual a 9 */
r = ++ a; /* r vale 10 + + igual a 11 */
1.5.3. Operadores de incremento y decremento
66
Los operadores “- -“ y “+ +”, pueden estar antes o después del operando, es decir, la
expresión
x=x+1 puede escribirse de dos formas
Como ++x y como x++
En el primer caso, cuando el operador está antes del operando, C lleva a cabo la operación
de incremento (o decremento en su caso), antes de utilizar el valor del operando. En el
segundo caso, cuando el operador está después del operando, C usa su valor antes de
incrementarlo (o decrementarlo).
Otro pequeño ejemplo, ilustraría mejor lo que se expresó antes. Supongamos que existe la
siguiente fracción de código:
x=7;
y=++x;
/*aquí, y toma el valor de 8*/
y=x++;
/*aquí, y toma el valor de 7 todavía*/
67
Actividades de aprendizaje.
Con el propósito de reforzar lo aprendido hasta este momento, realiza las siguientes
actividades.
1.- Complementa la siguiente tabla sobre los operadores aritméticos:
Operador Acción
-
+
*
/
%
2.- Complementa también la tabla siguiente, sobre los operadores relacionales:
Operador Acción
Mayor que
Mayor o igual a
Menor que
Menor o igual
Igual a
68
Diferente de
3.- La siguiente, es la tabla de verdad para los operadores lógicos, completa sus valores.
p q p & & q p | | q ! p
0 0 0 1
0 1 1
1 0 0 0
1 1 1
4.- ¿Cuál es la diferencia entre escribir ++i o escribir i++ ?
69
Resumen.
Con el propósito de facilitar el aprendizaje y la apropiación de los conceptos vertidos en
este tema, te presentamos el siguiente resumen.
Los operadores son símbolos que dicen al compilador que realice ciertas tareas matemáticas
o lógicas de los datos, y los hay de diversos tipos.
Operadores aritméticos
Operador Acción
- resta, menos monario
+ suma
* multiplicación
/ división entera
% división en módulo
Operadores Relacionales
Operador Acción
> mayor que
>= mayor o igual a
< menor que
<= menor o igual a
70
= = igual a
! = diferente de
Operadores Lógicos
Operador Acción
&& and
| | or
! not
Para los operadores lógicos, existe lo que se llama una “tabla de verdad” que concentra los
diferentes resultados obtenidos a partir de los tres operadores:
p q p && q p | | q !p
0 0 0 0 1
0 1 0 1 1
1 0 0 1 0
1 1 1 1 0
Sentencias de asignación
Nombre_de_la_variable = expresión;
Donde la variable toma el valor de la expresión de la derecha.
Operadores de incremento y decremento
Operador Acción
71
-- decremento
++ incremento
En donde decremento, disminuye en 1 el valor del operando al que se aplica, e incremento,
incrementa en 1 el valor del operando.
72
Recapitulación Unidad 1
Características del Lenguaje C.
Es de nivel medio, pues funde en sí elementos de alto nivel y funcionalidad de bajo nivel.
Es estructurado, porque su diseño le permite hacer programas (bloques) que pueden ser
compilados en forma separada. Es portable, toda vez que es independiente de la plataforma
en la que se desarrolle, compile o ejecute.
Podemos encontrar el Lenguaje C bajo diferentes entornos de desarrollo, bajo MS-DOS,
como el Turbo C; bajo Windows, como el DEV-C++; o bajo LINUX, como el gcc.
Las versiones que se encuentran del Lenguaje C, van desde el Lenguaje B [1972], el C con
clases [1980], el C++ [1984], el ANSI C [1990] que definió 32 palabras reservadas.
Estructura de un programa en C.
Un programa está conformado por funciones, de las cuales, solamente una de ellas estará
siempre presente. La forma general de un programa es en su formato más básico:
Directivas_del_procesador
Declaraciones_globales
73
main( ) {
Variables_locales
Secuencia_de_sentencias
}
El proceso inicia con el código fuente, que es el texto que el programador escribe, y es
introducido al compilador. Saliendo del compilador, se conoce como código objeto, y ahora
se enlaza con el código re-usable de las librerías o bibliotecas de Lenguaje C por medio del
enlazador, de donde ahora sale un programa ejecutable.
Tipos de datos.
Se encuentran en Lenguaje C, cinco tipos básicos de datos (char, int, float, double y void).
El char, usa 8 bits (un octeto) para representar cantidades, que van desde 0 hasta 255. El
tipo de dato llamado int, en cambio, usa 15 bits para representar cantidades y el bit más
significativo (el izquierdo) para simbolizar el signo, por lo que va desde -32767 hasta
32768. El tipo de dato de punto flotante, usa tres bytes para representar la mantisa y uno
para representar el exponente, razón por la que va su rango de valores desde 3.4 x 10-38
hasta 3.4 x 1038 . Para el tipo de datos de punto flotante de doble precisión, siete bytes los
usa para representar la mantisa, y uno para representar el exponente y así, su rango de
valores va desde 1.1 x 10-308 hasta 1.7 x 10308 .
74
Los tipos básicos tienen modificadores, de la siguiente manera: El char, lo encontramos con
dos posibles modificadores, como “unsigned char” y como “signed char”. El int puede
tener hasta siete modificadores, como “unsigned int”, “signed int”, “short int”, “unsigned
short int”, “signed short int”, “long int” y “signed long int”. El tipo float no tiene
modificadores. El ipo double puede tener hasta dos modificadores, que son “double” y
“long double”. El tipo void no tiene modificadores.
Cuando se requiere forzar a una expresión para que devuelva un tipo de dato , se usan unas
construcciones llamadas “moldes”.
Declaración de variables y constantes.
Una variable, es un identificador que almacena un dato y puede o no conservarlo a través
del programa. Pueden declararse dentro de las funciones y tomar el nombre de variables
locales o variables automáticas, pueden declararse en los parámetros de una función y
tomar el nombre de parámetros formales, o pueden declararse fuera de cualquier función y
tomar el nombre de variables globales.
Una constante, es un identificador al cual se le asigna un valor que no puede ser alterado en
el transcurso del programa, y que pueden ser empleadas para diferentes acciones dentro del
código. Hay también unas constantes llamadas de barra invertida, que permiten un control
mayor de las funciones del Lenguaje C.
75
Operadores.
Los operadores son símbolos que le indican al compilador que lleve a cabo ciertas
manipulaciones matemáticas o lógicas. Hay operadores denominados aritméticos, que
representan la resta y menos monario, suma, multiplicación, división entera y división en
módulo. Existen también los operadores denominados relacionales, que representan las
comparaciones “mayor que”, “mayor o igual a”, “menor que”, “menor o igual a”, “igual a”
y “diferente de”, que devolverán un 1 cuando el resultado de la comparación sea verdadera
y devolverán un 0 cuando el resultado de la comparación sea falsa. Los operadores lógicos
se explican de manera más expedita haciendo uso de lo que venimos llamando una “tabla
de verdad”, que señala que “para que un resultado AND sea verdadero, ambos operandos
deben ser verdaderos”; así como que “para que un resultado OR sea falso, ambos operandos
deben ser falsos” y finalmente, que para el operador NOT, “no falso es verdadero, y no
verdadero es falso”.
Una sentencia de asignación es aquella en donde una variable (a la izquierda del signo igual
a) tomará el valor de la constante o de la expresión de la derecha del mismo; y en caso de
ser de diferentes tipos de datos, la conversión sigue una sencilla regla: la expresión de la
derecha, tomará el tipo de dato que tiene la variable a la izquierda.
Existen dos operadores, denominados “de incremento” y “de decremento” que varían el
valor del operando en uno, ya sea en aumento o disminución. Pueden usarse antes o
76
después del operando, la diferencia es que cuando está antes del operando, C incrementa el
operando antes de ser utilizado, y cuando está después, lo incrementa después de ser usado.
77
Actividades de confirmación de conocimientos.
Resolviendo los problemas siguientes, afirmarás los conocimientos que ya has adquirido a
través de esta primera unidad.
1.- Complementa el siguiente cuadro sinóptico sobre las características del Lenguaje C,
luego analiza tu respuesta e indica cuál de estas características te da la oportunidad de hacer
programas en bloques.
Características
Del lenguaje C
2.- Anota en la columna de la derecha, el ambiente de compilación de lenguaje C para los
sistemas operativos que indica la columna de la izquierda, luego cita cuál es el más
conocido y cuál es el más natural a su plataforma (sistema operativo).
Nivel Medio: Estructurado: Portable:
78
Sistema Operativo Ambiente de
compilación
MS-DOS
Windows
LINUX
3.- Relaciona las diferentes fechas de la columna de la izquierda con los diferentes eventos
que ocurrieron alrededor de la creación y maduración del Lenguaje C.
Fecha Evento
Se crea el Lenguaje C perfeccionando el anterior “Lenguaje B”
Se edita el libro “The C programming language”
Bjarne Stroustrup diseñó “C con clases”
El “C con clases” se rediseña y nace el “C++”
Se edita el libro “The C++ programming language”
La ANSI y la ISO logran la estandarización del Lenguaje C
4.- Completa en la siguiente tabla, las palabras reservadas definidas por el estándar ANSI.
break
char continue
do
else extern
for
if long
return
signed static
79
switch
union void
while
5.- Anota en la forma más básica, el esquema de un programa en Lenguaje C, y anota qué
es lo que puedes variar o cambiar para que el programa pueda ser compilado correctamente.
6.- Completa la siguiente tabla de los tipos básicos de datos en Lenguaje C, y escribe cuál
es la importancia de conocer el tamaño que le corresponde a cada uno de los tipos.
Tipo Tamaño
en bits
Rango de valores
0 a 255
-32767 a 32768
3.4E-38 a 3.4E38
1.7E-308 a 1.7E308
Sin valor
7.- Complementa la siguiente tabla que involucra los cinco tipos básicos de datos y los diez
subtipos
Tipo Tamaño
en bits
Rango
80
char -128 a 127
unsigned char 0 a 255
signed char -128 a 127
int -32768 a 32767
unsigned int 0 a 65535
signed int -32768 a 32767
short int -32768 a 32767
unsigned short int 0 a 65535
signed short int -32768 a 32767
long int -2147483648 a 2147483647
signed long int -2147483648 a 2147483647
float 3.4E-38 a 3.4E+38
double 1.7E-308 a 1.7E+308
long double 1.7E-308 a 1.7E+308
void Sin valor
8.- Explica qué es una variable y qué es una constante.
9.- ¿Cuáles son los tres sitios donde se pueden declarar las variables?
81
10.- En la siguiente tabla, que contiene un listado parcial de las constantes de barra
invertida, complementa cuál es la que usa los significados que contiene la columna de la
derecha.
Constante Significado
New line
Backspace
Carriage return
Form feed
Alert
Backslash
Null character
11.- Complementa lo que le falta a la siguiente tabla de operadores aritméticos
Operador Acción
Resta, menos monario
+
Multiplicación
/
División en módulo
12.- Complementa la tabla siguiente, que contiene los operadores relacionales.
Operador Acción
83
Autoevaluación.
En las actividades de confirmación de conocimientos, se proponen 12 problemas para
afirmar los conocimientos que has adquirido al través de esta Unidad, y con el propósito de
que evalúes tu propio proceso de aprendizaje, se muestra la solución a los mismos.
1.- Para complementar el cuadro sinóptico sobre las características del Lenguaje C.
Características
Del lenguaje C
La característica llamada “Estructurado” es la que nos permite hacer programas en bloques,
puesto que puede inclusive ser compilado de manera separada.
2.- La siguiente, es la tabla completa que muestra el ambiente de compilación de lenguaje C
para los diferentes sistemas operativos.
Sistema Operativo Ambiente de
compilación
Nivel Medio: Realiza una fusión entre los elementos de alto nivel y la funcionalidad del bajo nivel. Estructurado: Está diseñado de manera que puedan escribirse programas que posteriormente se pueden compilar de manera separada. Portable: Significa que es independiente de la plataforma (sistema operativo) en el cual se desarrolle, compile y/o ejecute (MS-DOS, Windows o LINUX).
84
MS-DOS Turbo C
Windows DEV-C++
LINUX Gcc
El más conocido sin duda, es el Turbo C, que funciona bajo plataforma MS-DOS y puede
hacerse correr bajo Windows también. Por otro lado, el más natural para su plataforma es el
Gcc de Linux, que para capturar su código sólo se requiere del editor de pantalla vi que es
parte del sistema operativo y para compilarse, con sólo la orden gcc lo hace desde la línea
de comando.
3.- La siguiente tabla es una relación de las diferentes fechas con los diferentes eventos que
ocurrieron alrededor de la creación y maduración del Lenguaje C.
Fecha Evento
1972 Se crea el Lenguaje C perfeccionando el anterior “Lenguaje B”
1978 Se edita el libro “The C programming language”
1980 Bjarne Stroustrup diseñó “C con clases”
1984 El “C con clases” se rediseña y nace el “C++”
1986 Se edita el libro “The C++ programming language”
1990 La ANSI y la ISO logran la estandarización del Lenguaje C
4.- La siguiente tabla, es una relación de todas las palabras reservadas definidas por el
estándar ANSI.
auto break case
char const continue
85
default do double
else enum extern
float for goto
if int long
register return short
signed sizeof static
struct switch typedef
union unsigned void
volatile while
5.- En la forma más básica, el esquema de un programa en Lenguaje C es el siguiente.
directivas_del_preprocesador
declaraciones_globales
main( ) {
variables_locales
secuencia_de_sentencias
}
¿Qué puede ser cambiado? Nada. Si un programa carece de estas líneas que son
estrictamente necesarias, no va a ser compilado y por ende, no va a poder ser ejecutado.
6.- La siguiente tabla son los tipos básicos de datos en Lenguaje C.
Tipo Tamaño
en bits
Rango de valores
char 8 0 a 255
86
int 16 -32767 a 32768
float 32 3.4E-38 a 3.4E38
double 64 1.7E-308 a 1.7E308
void 0 Sin valor
Conocer el tamaño en bits (o en bytes) de cada uno de los tipos es muy importante, porque
así sabemos la cantidad de memoria ram que el programa está reservando para usarla en el
manejo de las variables que han sido declaradas, dependiendo de su tipo.
7.- La siguiente tabla involucra los cinco tipos básicos de datos y los diez subtipos
Tipo Tamaño
en bits
Rango
char 8 -128 a 127
unsigned char 8 0 a 255
signed char 8 -128 a 127
int 16 -32768 a 32767
unsigned int 16 0 a 65535
signed int 16 -32768 a 32767
short int 16 -32768 a 32767
unsigned short int 16 0 a 65535
signed short int 16 -32768 a 32767
long int 32 -2147483648 a 2147483647
signed long int 32 -2147483648 a 2147483647
float 32 3.4E-38 a 3.4E+38
double 64 1.7E-308 a 1.7E+308
87
long double 64 1.7E-308 a 1.7E+308
void 0 Sin valor
8.- Los siguientes son los conceptos de variable y constante.
Una variable es un identificador o nombre que tiene la capacidad de almacenar un valor que
puede variar o puede no hacerlo en el transcurso del programa.
Una constante, es un identificador que es capaz de almacenar un valor que permanece sin
cambio a través de todo el programa.
9.- ¿Cuáles son los tres sitios donde se pueden declarar las variables?
a.- dentro de las funciones (variables automáticas o locales)
b.- en los parámetros de una función (parámetros formales)
c.- fuera de cualquier función (variables globales)
10.- La siguiente tabla, es un listado parcial de las constantes de barra invertida que usa los
significados que contiene la columna de la derecha.
Constante Significado
\n New line
\b Backspace
\r Carriage return
\f Form feed
\a Alert
88
\\ Backslash
\0 Null character
11.- La siguiente tabla contiene los operadores aritméticos y sus acciones
Operador Acción
- Resta, menos monario
+ Suma
* Multiplicación
/ División entera
% División en módulo
12.- La tabla siguiente, muestra los operadores relacionales y sus acciones
Operador Acción
> Mayor que
>= Mayor o igual a
< Menor que
<= Menor o igual a
= = Igual a
! = Diferente de
90
PROPOSITO
¿QUÉ APRENDERÁS?
Las estructuras de control como las sentencias para entrada y salida de datos, instrucciones
de control de pantalla y sentencias de control selectivas, así como de control repetitivas.
¿CÓMO LO APRENDERÁS?
Realizarás ejercicios prácticos en la computadora, capturando los programas sugeridos en el
texto, los cuales se explican, y te apoyarás con el instructor en caso de duda sobre los
tópicos: sentencias para entrada y salida de datos, instrucciones de control de pantalla,
sentencias de control selectivas y sentencias de control repetitivas. Además estudiarás los
tópicos necesarios para adquirir dominio sobre lo que se explica.
¿PARA QUÉ LO APRENDERÁS?
Para resolver los problemas de la vida común que se presentan y que pueden ser resueltos
usando la herramienta de la computadora, diseñando y escribiendo programas para obtener
soluciones y los que puedas identificar y que necesiten del concurso de las sentencias que
se van a estudiar en este capítulo.
91
Por lo que se refiere al análisis de un problema, con la intención de solucionarlo, recordarás
de tu curso de “fundamentos de programación”, que su representación consiste en una
entrada de datos, un programa que realiza operaciones para procesarlos, y una salida de
información. Evidentemente, si logramos introducir datos para que sean procesados,
necesitamos sin discusión, mostrar los resultados de salida.
En realidad, la Entrada y Salida en C se clasifican solamente como E/S ANSI (llamadas
también “sistema de archivos con buffer”, “con formato” o “de alto nivel”) y tipo UNIX
(llamadas también “sin buffer” o “sin formato”), sin embargo, se intentará sub-clasificarlos
para mayor comprensión de los mismos. Por sentencias, vamos a entender las órdenes o
comandos que nos permiten establecer una comunicación en ambos sentidos con la
computadora.
La entrada y salida estándar, son las funciones que están dentro del dominio del archivo de
cabecera denominado “stdio.h” (Standard input/output header file) y de las cuales, veremos
las funciones de entrada y salida que siguen:
2. Estructuras de control
2.1. Sentencias para entrada y salida de datos
2.1.1. Entrada y salida estándar.
92
• La función getchar( )
El prototipo de esta función es int getchar(void), y su característica es que guarda en un
buffer la entrada (un carácter) hasta que se pulsa la tecla <Intro>, y es a causa de que en los
compiladores de C originales bajo UNIX, se requería hacer la captura de entradas por
consola con buffer de línea, por lo cual se podía escribir una línea completa y hasta pulsar
<Intro> no se ejecutaba.
Debe notarse que la función getchar( ) carece de argumentos, y el valor de retorno debe ser
tomado por medio de asignación, por ejemplo:
char car;
car=getchar();
que obtendrá un carácter desde el teclado y lo asignará a la variable de tipo carácter llamada
car.
• La función putchar( )
El prototipo de esta función es int putchar(int c), y escribe el carácter que está en el byte
menos significativo del entero ‘c’, aunque puede usarse un carácter como argumento sin
ningún problema. Al tener éxito, la función putchar( ) devuelve un carácter.
93
Para usarla, es necesario que se escriba aportando un carácter (entre comillas simples)
como argumento de esta función, a menos que esté imprimiendo el valor (carácter) de una
variable, por ejemplo:
putchar(‘A’);
Esta simple orden, imprimirá el carácter A en la pantalla. A continuación veremos un
pequeño ejemplo para el uso de estas funciones. Captúralo, bajo MS-DOS, Windows o
LINUX, compílalo y córrelo.
Ejemplo.
#include "stdio.h" main( ){ char car; /* car es la variable de tipo character que va a contener el que se capture con getchar( )*/ int i; /* i es la variable entera que será la variable de control para el ciclo for */ car=getchar(); /*obtiene un caracter de la pantalla, y un <Intro>*/ for(i=0;i<10;i++) putchar(car); /*imprime diez caracteres*/ putchar('\n'); /*imprime un salto de línea*/ return 0; }
94
El resultado que obtendrás será el siguiente:
*
* * * * * * * * * *
Si el resultado obtenido es diferente de esto, revisa el código de tu programa y vuélvelo a
compilar después de corregirlo.
• La función gets( )
El prototipo para esta función es char *gets(char *cad), lee caracteres de la entrada estándar
y los sitúa en un arreglo apuntado por cad. Al tener éxito, devuelve la cadena cad.
Cad es un arreglo de caracteres, o sea, una cadena de caracteres. De este modo, entonces
gets( ) realmente tiene el propósito de leer una cadena de caracteres desde el teclado, por
ejemplo usando:
char cad[80];
gets(cad);
La función puts( )
El prototipo para esta función es int puts(const char *cad), e imprime la cadena apuntada
por cad en la pantalla. Si tiene éxito, devuelve un salto de línea.
95
Puts( ) reconoce los mismos caracteres de código de barra invertida que usa el printf( ),
pero no imprime cantidades, sino solamente cadenas de caracteres, así que se pueden usar
los tabuladores, barra invertida, comilla simple, dobles, etc.
Obviamente, puede ser que se utilice para escribir una variable que contenga una cadena de
caracteres, como en la siguiente fracción de código:
char cad[80];
puts(cad);
Pero también suele utilizarse para escribir la cadena manifestada dentro del paréntesis, de la
manera como se presenta en la siguiente línea de código:
puts(“Esta es una cadena”);
A continuación veremos un pequeño ejemplo para el uso de las funciones gets( ) y puts( ).
Captúralo, bajo MS-DOS, Windows o LINUX, compílalo y córrelo.
Ejemplo.
96
strlen( ) es una función que devueve el tamaño de la cadena y pertenece al archivo de
cabecera “string.h”, esa es la razón por la que la escribimos al principio. Supongamos que
al correrlo, capturamos el nombre “Juan”, así que queda de la siguiente manera:
Escribe tu nombre:
Juan
Tu nombre es Juan y tiene 4 caracteres.
Si obtienes un resultado diferente, algo no estuvo correctamente capturado, inténtalo de
nuevo después de revisar y corregir.
#include "stdio.h"
#include "string.h"
main(){
char cad[80];
puts("Escribe tu nombre : ");
gets(cad);
printf("Tu nombre es %s y tiene %d caracteres",
cad, strlen(cad));
return 0;
}
97
Tomaremos en esta sub-clasificación, como consola, la unión de los dispositivos de entrada
estándar (teclado) y de salida estándar (monitor), así que se tomará la consola como un solo
dispositivo, para el cual estarán definidas en el archivo de cabecera “conio.h” (console
input/output header file) las funciones siguientes:
• La función getche( )
El prototipo para esta función es int getche(void), y devuelve el carácter leído por la
consola, además de mostrarlo por la pantalla. No está definida por el estándar ANSI C, por
lo que no funcionará para el compilador de C bajo LINUX.
La función getche( ) recibe entonces el valor de un carácter, y lo muestra de inmediato.
• La función getch( )
El prototipo de esta función es int getch(void), y devuelve el carácter leído por la consola,
pero no lo muestra en la pantalla. No está definida por el estándar ANSI C, por lo que no
funcionará para el compilador de C bajo LINUX.
2.1.2. Entrada y salida por consola
98
La función getch( ) recibe entonces el valor de un carácter, pero no lo muestra en pantalla.
Quizás por esa razón, es que se usa el getch( ) como un método para “congelar” la pantalla
antes de terminar la ejecución de un programa.
Las siguientes funciones, pese a pertenecer al archivo “stdio.h”, se van a estudiar aparte,
pues algo que las caracteriza precisamente es el uso de un formato tanto para adquirir los
datos como para mostrarlos.
• La función printf( )
El prototipo de esta función es int printf(const char *formato, lista_de_argumentos), y
escribe la lista de argumentos de que está formada “lista_de_argumentos”, adoptando el
control del formato que muestra *formato.
Entonces, la manera correcta en que debe usarse el comando printf( ) será usando una
cadena de caracteres entre comillas, en la que se incluye el formato con el cual van a ser
escritos en pantalla los argumentos posteriores, por ejemplo:
printf(“cadena de control”, lista_de_argumentos);
printf(“El precio del producto es de %d pesos”, precio);
2.1.3. Entrada y salida con formato
99
si la variable “precio” tiene un valor de 320, se sustituirá su valor por el especificador de
formato “%d” que es de un número entero, entonces el resultado en la pantalla será:
El precio del producto es de 320 pesos
Los especificadores de formato que pueden ser utilizados en la cadena de formato, son los
siguientes:
Código Formato
%c Un único carácter
%d Número decimal
%i Número decimal
%e Número en notación científica
%f Número decimal en punto flotante
%g Usar %e o %f, el más corto
%o Número en octal sin signo
%s Cadena de caracteres
%u Número decimal sin signo
%x Número hexadecimal sin signo
%% Signo %
%p Muestra un puntero
%n Representa un puntero a entero que guarda
el número de caracteres escritos
100
Podemos usar los códigos que se refieren a números para poder ver la diferencia en que
éstos pueden ser presentados por medio de la pantalla.
A continuación veremos un pequeño ejemplo para el uso de los códigos. Captúralo, bajo
MS-DOS, Windows o LINUX, compílalo y córrelo.
Ejemplo.
El resultado mostrado por medio de la pantalla, debe ser el siguiente:
Numero 350 en decimal con %d = 350
Numero 350 en decimal con %i = 350
Numero 350 en octal con %o = 536
Numero 350 en hexadecimal con %x = 15e
Numero 12345.67 en notacion cientifica con %e = 1.234567e+004
Numero 12345.67 en punto flotante con %f = 12345.669922
#include "stdio.h" main(){ int num=350; float fnum=12345.67; printf("Numero 350 en decimal con %%d = %d \n", num); printf("Numero 350 en decimal con %%i = %i \n", num); printf("Numero 350 en octal con %%o = %o \n", num); printf("Numero 350 en hexadecimal con %%x = %x \n", num); printf("Numero 12345.67 en notacion cientifica con %%e = %e \n", fnum); printf("Numero 12345.67 en punto flotante con %%f = %f \n", fnum); }
101
Si no coincide, posiblemente tuviste un pequeño error de captura. Rectifica y vuelve a
compilar.
Además de los códigos especificadores de formato, existen especificadores especiales para
definir con mucha mayor precisión el dato que deseamos que se presente en la pantalla de
salida, suelen llamarse también banderas (flags).
En las líneas de código siguiente:
float fnum=12345.67;
printf("Numero en punto flotante |%-+015f| \n", fnum);
Vamos a desglosarlas, en la primera línea, solamente definimos el número de punto flotante
12345.67. En la segunda, encontramos los siguientes símbolos:
símbolo significado
% símbolo de especificador (siempre se escribe)
- ajusta el resultado a su margen izquierdo
+ imprime por fuerza el signo del número a su salida
0 obliga a que los espacios en blanco se rellenen de ceros
15 longitud del campo
f especifica que es un número de punto flotante
102
lo que significa que escribirá esa línea como resultado del formato:
|+12345.66992200|
Así, por ejemplo, %09d rellenará de ceros para que el número entero tenga nueve dígitos de
longitud; %15.5f indica que será un número de punto flotante que tendrá una longitud de
quince dígitos, de los cuales, cinco serán decimales; %7.12s imprimirá una cadena de
caracteres de al menos siete caracteres, pero no más de doce.
Veamos un pequeño programa de ejemplo que muestre este tipo de modificadores.
Ejemplo.
El resultado para este programa será el siguiente:
Rellenando con ceros hasta nueve posiciones: 234
Numero de quince digitos de longitud y cinco decimales: 5432.22119
#include "stdio.h" main(){ int numero=234; float numerof=5432.221; char cadena[]="Guadalajara"; char cadena2[]="hola"; printf("Rellenando con ceros hasta nueve posiciones: %9d \n",numero); printf("Numero de quince digitos de longitud y cinco decimales: %15.5f \n", numerof); printf("Cadena de al menos siete caracteres y no mas de diez: %7.10s \n", cadena); printf("Cadena de al menos siete caracteres y no mas de diez: %7.10s \n", cadena2); }
103
Cadena de al menos siete caracteres de longitud y no mas de diez: Guadalajar
Cadena de al menos siete caracteres de longitud y no mas de diez: hola
Si han salido diferentes resultados, te sugiero que vuelvas a rectificar el código y corregirlo
para compilarlo de nuevo. Notarás que al capturar los programas, no se capturan acentos,
pues el compilador, va a mostrar otros símbolos en su lugar.
• La función scanf( )
El prototipo de esta función es int scanf(const char *formato, lista_de_argmentos), y lee del
teclado los argumentos que componen la “lista_de_argumentos” siendo controlados por el
formato de *formato.
Podríamos asegurar que la función scanf( ) es la función inversa de printf( ), leyendo todos
los datos que se puedan proveer al compilador.
Por lo que respecta a la cadena llamada “formato”, que va entre comillas, puede contener
tres tipos de elementos, los especificadores de formato, espacios en blanco o caracteres.
Los especificadores de formato para la función scanf( ) son los siguientes:
Código Formato
%c Un único carácter
104
%d Número decimal
%i Número decimal
%e Número decimal en punto flotante
%f Número decimal en punto flotante
%h Número entero corto
%o Número en octal sin signo
%s Cadena de caracteres
%u Número decimal sin signo
%x Número hexadecimal sin signo
%p Muestra un puntero
%n Recibe un valor entero que corresponde con
el número de caracteres
Si la cadena de formato tuviera un espacio en blanco, le indicará a scanf( ) que lea sin
guardar el número que sea de espacios en blanco hasta que encuentre un carácter diferente.
Si es un carácter diferente de espacio, entonces lo que va a descartar serán los caracteres
que coincidan con el.
Dado que todas las variables se pasan a través de sus direcciones, entonces los argumentos
deben ser tratados como punteros a esas variables, de tal modo que cuando se quiera
capturar la variable entera num, será de la siguiente manera:
105
scanf (“%d”, &num);
Con excepción de cuando se trata de una cadena de caracteres, pues ya es un apuntador a un
arreglo. Cuando se coloca un asterisco después del símbolo de formato ‘%’ y antes del
especificador, el compilador lee, pero no asigna el dato, por ejemplo:
scanf(“%d%*c%d”, &a, &b);
Y nosotros capturamos el número 15x30, a vale 15 y b vale 30, mientras que el carácter ‘x’
es ignorado por completo.
Una mención especial para el caso de scanf( ) corresponde al llamado “juego de
inspección” que es un conjunto de caracteres que el scanf( ) será capaz de leer, y que
cuando se introduzca otro carácter, terminará su captura, por ejemplo:
scanf(“%[0123456789]”, cad);
Permitirá escribir una cadena de caracteres que corresponda a números, y cesará su captura
en el momento en que se introduzca un carácter diferente.
Puede también usarse el juego de inspección por medio de la definición de un rango (que es
utilizando un guión para definirlo), por ejemplo:
%[A-Z] corresponde a las mayúsculas de la A a la Z.
106
%[0-9] corresponde a los números. %[a-zA-Z] corresponde a todas las letras, minúsculas y mayúsculas.
Usando rangos invertidos, se le puede decir al compilador que debe capturar lo que sa,
menos números, indicándole: scanf(“%[^0-9]”, cadena). Como ejemplo, hagamos un
programa que ilustre lo que se acaba de ver.
Ejemplo.
La salida sería de la siguiente manera:
Escriba un caracter : C
Escriba un numero entero : 123
#include "stdio.h" main(){ char car; int entero; float real; char apellido[80]; char cadena[80]; int dia, mes; printf("Escriba un caracter : "); scanf("%c", &car); printf("Escriba un numero entero : "); scanf("%d", &entero); printf("Escriba un numero de punto flotante : "); scanf("%f", &real); printf("Escriba su apellido : "); scanf("%s", apellido); printf("Escriba la fecha de hoy, en formato dd/mm : "); scanf("%d%*c%d", &dia, &mes); printf("Escriba una cadena con letras, y escriba un numero para terminar : "); scanf("%[^0-9]", cadena); printf("============================================\n"); printf("Usted capturo la letra \'%c\', el entero %d, el real %f, su apellido es %s, estamos en el dia %d y el mes %d, y su ultima cadena fue: %s ", car, entero, real, apellido, dia, mes, cadena); }
107
Escriba un numero de punto flotante: 123.456
Escriba su apellido : Gallardo
Escriba la fecha de hoy, en formato dd/mm : 26/4
Escriba una cadena con letras y escriba un numero para terminar : murcielago9
=================================
Usted capturo la letra C, el entero 123, el real 123.456, su apellido es Gallardo, estamos en
el dia 26 y el mes 4, y su ultima cadena fue : murcielago
Si no resultó de esta manera, entonces tienes algún error en la captura o compilación del
programa.
108
Actividades de aprendizaje.
Las siguientes actividades fueron diseñadas para que el estudiante reafirme su aprendizaje y
resuelva las dudas que pueden haberle surgido.
1.- Escribe un programa que imprima diez asteriscos (capturando el asterisco, por
supuesto), sólo que de forma vertical, usando solamente getchar( ) y putchar( ). Primero
realiza el programa con pseudocódigo y posteriormente codifica a Lenguaje C.
2.- En el siguiente código, analiza y explica:
a.- Paso a paso, ¿qué es lo que hace el código?
b.- ¿Cuáles son los comandos u órdenes principales?
c.- ¿Cuál es el propósito del programa?
3.- Escribe un programa que permita capturar un número en decimal, y te lo presente en las
tres bases: decimal, octal y hexadecimal. Primero realiza el diagrama de flujo y luego
codifica al Lenguaje C
#include “stdio.h” main( ){ char nom[25]; puts(“Escribe tu nombre : “); gets(nom); printf(“Hola, bienvenido al curso de Lenguaje C, %s”, nom); getch(); return 0; }
109
Resumen.
Con el propósito de asegurar la comprensión de los conceptos, así como la apropiación del
método seguido para usar las sentencias que fueron vistas en este tema, presentamos el
siguiente resumen. Las sentencias para entrada y salida de datos, ya sea las estándar, por
consola o con formato, son las primeras que debes aprender para ingresar al mundo de la
programación en Lenguaje C.
Sentencias para entrada y salida de
datos
Entrada y salida
estándar
Entrada y salida por consola
Entrada y salida con formato
putchar()
getche()
printf()getchar() scanf()gets() puts()
getch()
Captura un carácter y lo guarda en un buffer hasta pulsar <Intro>
Obtiene una cadena de caracteres a través del teclado
Escribe un carácter en la pantalla
Imprime una cadena de caracteres en la pantalla
Imprime usando una cadena de caracteres que usa un formato
Es la función inversa de printf() y lee los datos del teclado, con una cadena de formato
Recibe el valor de un carácter y lo muestra de inmediato
Recibe el valor de una carácter, pero no lo muestra en la pantalla
función función función función función función
función función
Son de
Son de
Son de
110
Cuando nos referimos a la pantalla, mayormente, nos estamos refiriendo a la pantalla de
texto, que se compone de 80 columnas de ancho por 24 líneas de altura. Las sentencias de
control de pantalla, nos van a permitir hacer muy maleable la presentación tanto del
programa como de los resultados que el mismo arroje.
• Función clrscr( )
El prototipo para esta función es void clrscr(void), se encuentra en el archivo de cabecera
denominado “conio.h” y su función es limpiar completamente una ventana de texto,
dejando el cursor en la esquina superior izquierda, o sea, en la posición (1,1) o sea, primera
columna, primera línea. No está definida por el estándar ANSI C, por lo cual, no funcionará
bajo LINUX.
La aplicación de esta función es simplemente en el cuerpo del código, por lo general al
principio:
clrscr( );
2.2. Instrucciones de control de pantalla
2.2.1. clrscr( ) y delay( )
111
• Función delay( )
El prototipo de esta función es void delay(unsigned tiempo) y se encuentra en el archivo de
cabecera llamado “dos.h”, y es para detener la ejecución del programa durante “tiempo”
milésimas de segundos, así un delay(1000) significará que se espera un segundo. No está
definida por el estándar ANSI C, por lo cual, no funcionará bajo LINUX.
• Función gotoxy( )
El prototipo de esta función es void gotoxy(int x, int y) y se encuentra en el archivo de
cabecera “conio.h”, y su utilidad es situar el cursor en la posición especificada por x e y en
la pantalla de texto. Hagamos un programa que muestre la utilidad de las funciones clrscr(),
delay() y gotoxy().
#include "stdio.h" #include "conio.h" #include "dos.h" main(){ int x,y; clrscr(); for(y=1;y<=24;y++) for(x=1;x<=80;x++){ gotoxy(x,y); putchar('X'); delay(100); clrscr() } return 0; }
2.2.2. gotoxy()
112
Este programa, debe dar como resultado un recorrido de la pantalla por una letra ‘X’ en
forma horizontal, primero el renglón uno, durando impresa la ‘X’ un décimo de segundo,
luego desaparece con el clrscr() y aparece un lugar más adelante. Luego sigue haciendo lo
mismo con el renglón 2 y así consecutivamente, hasta completar los 24 renglones de la
pantalla de texto.
• Función textcolor( )
El prototipo de esta función es void textcolor(int color) e indica al compilador, el color con
el que se van a mostrar los caracteres en la pantalla pertenece al archivo de cabecera
llamado “conio.h” y los colores, se pueden usar mediante el número de código de color, o
mediante la macro que lo sustituya, como se muestra enseguida.
Macro Código numérico
BLACK 0
BLUE 1
GREEN 2
CYAN 3
RED 4
MAGENTA 5
2.2.3. textcolor( ) y textbackground( )
113
BROWN 6
LIGHTGRAY 7
DARKGRAY 8
LIGHTBLUE 9
LIGHTGREEN 10
LIGHTCYAN 11
LIGHTRED 12
LIGHTMAGENTA 13
YELLOW 14
WHITE 15
BLINK 128
• Función textbackground( )
El prototipo de esta función es void textbackground(int color), se encuentra en el archivo de
cabecera llamado “conio.h” y asigna un color al fondo del texto que le sigue. Los colores,
se pueden usar mediante el código numérico de color o pueden usarse mediante la macro
que los define, como en la siguiente lista.
Macro Código numérico
BLACK 0
BLUE 1
114
GREEN 2
CYAN 3
RED 4
MAGENTA 5
BROWN 6
LIGHTGRAY 7
Realicemos un programa que muestre la utilidad de los comandos de textcolor() y
textbackground(), para poder verlos actuando.
Ejemplo.
#include “stdio.h” #include “conio.h” main(){ clrscr(); textbackground(BLUE); textcolor(CYAN); cprintf(“Texto en color cyan sobre fondo azul\n”); textbackground(GREEN); textcolor(BLUE); cprintf(“Texto en color azul sobre fondo verde\n”); textbackground(CYAN); textcolor(GREEN); cprintf(“Texto en color verde sobre fondo cyan\n”); getch(); return 0; }
115
El resultado del programa anterior es el siguiente:
Texto en color cyan sobre fondo azul
Texto en color azul sobre fondo verde
Texto en color verde sobre fondo cyan
en esos colores que se indica.
116
Actividades de aprendizaje.
Estas actividades, ayudaran al estudiante a integrar los conocimientos que ha adquirido a lo
largo de todo este tema, por lo que es sumamente importante que los realice.
1.- Realiza un programa que muestre la forma en que se manejan las funciones clrscr(),
gotoxy() y delay().
2.- Realiza un programa que muestre la utilidad de las funciones textbackground() y
textcolor().
3.- En el siguiente código, localiza las siete líneas que tienen errores, márcalos explicando
por qué son errores, y corrige el mismo después de comentarlo en equipo y consultar con tu
profesor.
#include stdio.h" #include "conio.h" #include dos.h main() clrscr() gotoxy(10,15); printf(“Hola, mundo!); delay(“1000”); return=0; }
117
Resumen.
Para permitir el dominio de estas instrucciones, sus funciones e incorporarlas al acervo de
programación que debes estar adquiriendo, se te presenta el siguiente resumen en forma de
mapa conceptual. Las instrucciones de borrar pantalla, detener la ejecución de un programa,
situar el cursor en determinadas coordenadas, dar color al texto o al fondo del mismo, son
partes muy importantes de embellecer la creación y ejecución de un programa.
Instrucciones de control de pantalla
clrscr()
Limpia la ventana de texto
delay(t)
Detiene la ejecución durante t milésimas de segundo
gotoxy(r,c)
Sitúa el cursor en el renglón r y la columna c
textcolor(c)
Indica al compilador el color c que va a tener el texto
textbackground(c)
Indica al compilador el color c que va a tener el fondo del texto
función función función función función
118
Estas también son llamadas sentencias condicionales, y C soporta las sentencias if y switch,
además de la alternativa ‘?’ que también va a verse. Estas sentencias nos van a permitir
realizar la toma de decisiones de manera automática en la computadora y la discriminación
de entradas para obtener diversos resultados.
La sintaxis de la sentencia if es la siguiente:
El hecho de que esté entre corchetes la segunda parte, significa que puede ser opcional, es
decir, que puede o no estar presente. Si estuviera presente solamente la primera parte,
podríamos reducirla al siguiente diagrama de flujo:
if (expresión) sentencia1;
[else sentencia2;]
2.3. Sentencias de control selectivas
2.3.1. La sentencia if
119
Fig. 2.1. Diagrama de flujo de la sentencia “if” simple.
La explicación para este diagrama es sumamente sencilla, el rombo, como tú sabes,
significa una toma de decisión, así que indica si existe tal condición, lo cual se indica
mediante la salida marcada con la “S”, entonces realiza la “sentencia1”, y si no cumple tal
condición, simplemente, continúa el flujo del programa.
De la segunda forma, es decir, estando presentes ambas partes de la sentencia, sería
representada por el siguiente diagrama de flujo:
120
Condición?
Sentencia1
No
Sentencia2
Si
Fig. 2.2. Diagrama de flujo de la sentencia “if-else”.
Explicando este diagrama, indicaría: Si se cumple la sentencia, (que es la flecha con la
opción “S”) entonces ejecuta “sentencia1”, y si no se cumple (que es la flecha con la opción
“N”) entonces ejecuta “sentencia2”.
Se ha hecho referencia a “si se cumple la sentencia”, y esto significa, si es que la expresión
es verdadera, es decir si es diferente de cero.
El siguiente, es un ejemplo del primer caso, desarróllalo en el editor de tu preferencia, para
correrlo.
121
Ejemplo:
El programa debe dar como resultado lo siguiente:
Escribe un número entero:
10
Número positivo.
En caso de introducir un número negativo, quedaría la respuesta de la siguiente manera:
Escribe un número entero:
-12
Finalizando sin indicar nada más
#include "stdio.h"
main(){
int num;
printf("Escribe un numero entero: \n");
scanf("%d", &num);
if (num>=0)
printf("Numero positive.");
return 0;
}
122
Si deseamos que indique si es positivo o negativo, entonces deberíamos realizar un
programa que tenga las dos opciones, hagámoslo:
Ejemplo.
Si es así, el programa se ejecutará de la siguiente manera:
Escribe un número entero:
10
Número positivo
Escribe un número entero:
#include "stdio.h"
main(){
int num;
printf("Escribe un numero entero \n");
scanf("%d", &num);
if (num>=0)
printf("Numero positivo");
else
printf("Numero negativo");
return 0;
}
123
-12
Número negativo
Debe quedar aclarado que “sentencia” puede ser una sentencia simple o una secuencia de
sentencias, encerrada entre llaves, indicando que es un solo bloque.
Otra forma de “if” son las sentencias “if anidadas” que tienen un “if” dentro de otro “if”, y
un caso típico sería el encontrar el mayor de tres números, como en el ejemplo que sigue:
Ejemplo.
En la ejecución, el resultado sería:
#include "stdio.h" main(){ int a, b, c; printf("Escriba tres numeros diferentes: \n"); scanf("%d %d %d", &a, &b, &c); if (a>b) if (a>c) printf("El mayor es el primero, que es %d", a); else printf("El mayor es el tercero, que es &d", c); else if (b>c) printf("El mayor es el segundo, que es %d", b); else printf("El mayor es el tercero, que es %d", c); return 0; }
124
Escriba tres números diferentes:
1 3 5
El mayor es el tercero, que es 5
Escriba tres números diferentes:
1 5 3
El mayor es el segundo, que es 5
Escriba tres números diferentes:
5 3 1
El mayor es el primero, que es 5
Para la misma sentencia “if” existe una tercera acepción, que se llama la “escala if-else-if”,
cuya sintaxis es:
if (condición1)
sentencia1;
else if (condición2)
sentencia2;
else if (condición3)
sentencia3;
else
sentencia_por_defecto;
125
si ponemos esta sentencia en la forma de un diagrama de flujo, sería de la siguiente manera:
Fig. 2.3. Diagrama de flujo de la sentencia compuesta “if-else-if”.
Claro que no se concretaría solamente a tres sentencias condicionales, sino que son
simplemente más de dos.
El siguiente es un ejemplo de un programa que deberá de decirte cuál es tu signo zodiacal
al introducir tu fecha de nacimiento en el formato de dia/mes, utilizando los conocimientos
que hasta el momento hemos adquirido de programación.
126
Ejemplo.
Por ejemplo, al hacerla correr, podría funcionar de la siguiente manera:
Introduce tu fecha de nacimiento en la forma dia/mes : 24/4
#include "stdio.h" main(){ int d, m; printf("Introduce tu fecha de nacimiento en la forma dia/mes : "); scanf("%d%*c%d", &d, &m); if ((m==12 && d>23)||(m==1 && d<=21)) printf("Tu signo es Capricornio."); else if ((m==1 && d>21)||(m==2 && d<=21)) printf("Tu signo es Acuario."); else if((m==2 && d>21)||(m==3 && d<=20)) printf("Tu signo es Piscis."); else if ((m==3 && d>20)||(m==4 && d<=20)) printf("Tu signo es Aries."); else if ((m==4 && d>20)||(m==5 && d<=20)) printf("Tu signo es Tauro."); else if ((m==5 && d>20)||(m==6 && d<=21)) printf("Tu signo es Geminis."); else if ((m==6 && d>21)||(m==7 && d<=22)) printf("Tu signo es Cancer."); else if ((m==7 && d>22)||(m==8 && d<=22)) printf("Tu signo es Leo."); else if ((m==8 && d>22)||(m==9 && d<=21)) printf("Tu signo es Virgo."); else if ((m==9 && d>21)||(m==10 && d<=22)) printf("Tu signo es Libra."); else if ((m==10 && d>22)||(m==11 && d<=21)) printf("Tu signo es Escorpion."); else if ((m==11 && d>21)||(m==12 && d<=22)) printf("Tu signo es Sagitario."); else printf("Tu fecha debe estar erronea..."); return 0; }
127
Tu signo es Tauro.
Y si se equivocara, por ejemplo el número de mes, sería:
Introduce tu fecha de nacimiento en la forma dia/mes : 24/40
Tu fecha debe estar erronea...
Puede ser posible reemplazar la sentencia “if” mediante el uso del operador ternario ‘?’
cuya sintaxis será:
Expresión1 es la expresión a evaluarse. Si resultara que expresión1 es verdadera, es decir,
que es diferente de cero, entonces se evalúa la expresión2. Si resultara que la expresión1 es
falsa, es decir, que vale cero, entonces se evaluará la expresión3.
Para ilustrar esta forma de Lenguaje C, realizaremos un ejemplo, para ver de manera más
clara cómo se aplica el operador ternario ‘?’. El ejemplo, lo tomaremos de aquél programa
que muestra si un número es positivo o negativo.
Ejemplo.
Expresión1? Expresión2: Expresión3;
2.3.2. Operador ‘?’
128
Y funciona perfectamente de la misma manera que el programa de donde se compulsó.
Para sustituir la sentencia “if-else-if” Lenguaje C ha sustituido ésta por una sentencia de
ramificación múltiple llamada “switch” cuya sintaxis es la siguiente:
#include "stdio.h" main(){ int num; printf("Escribe un numero entero \n"); scanf("%d", &num); (num>=0)? printf("Numero positivo"): printf("Numero negativo"); return 0; }
switch(var){ case const1: secuencia_de_sentencias1; break; case const2: secuencia_de_sentencias2; break; case const3: secuencia_de_sentencias3; break; . . . default: secuencia_de_sentencias_n; }
2.3.3. switch()
129
Si lo anterior lo pudiéramos en función de un diagrama de flujo, quedaría de la siguiente
manera:
Fig. 2.4. Diagrama de flujo de la sentencia “switch”.
La manera en que es sustituida, podemos ilustrarla mediante la escritura de un programa en
Lenguaje C, que encuentre el mes en que nació el usuario. Captúralo y compílalo.
Ejemplo.
130
#include "stdio.h" main(){ int m; printf("Introduce el mes de tu nacimiento : "); scanf("%d", &m); switch (m){ case 1: printf("Naciste en el mes de Enero."); break; case 2: printf("Naciste en el mes de Febrero."); break; case 3: printf("Naciste en el mes de Marzo."); break; case 4: printf("Naciste en el mes de Abril."); break; case 5: printf("Naciste en el mes de Mayo."); break; case 6: printf("Naciste en el mes de Junio."); break; case 7: printf("Naciste en el mes de Julio."); break; case 8: printf("Naciste en el mes de Agsto."); break; case 9: printf("Naciste en el mes de Septiembre."); break; case 10: printf("Naciste en el mes de Octubre."); break; case 11: printf("Naciste en el mes de Noviembre."); break; case 12: printf("Naciste en el mes de Diciembre."); break; default: printf("No es un mes valido"); } return 0; }
131
Así, si es ejecutado el programa de la siguiente manera, obtendrá los resultados previstos:
Introduce el mes de tu nacimiento : 4
Naciste en el mes de Abril.
132
Actividades de aprendizaje.
Con el propósito de que el estudiante integre los conocimientos que ha adquirido a lo largo
de este tema, se presentan las siguientes actividades, que es muy importante que se
desarrollen, pues permitirá mayor facilidad en el avance a la unidad siguiente. Dado que las
cuatro actividades sugeridas son desarrollar programas, es significativo que al final de cada
ejercicio, menciones con qué dificultades te enfrentaste para realizarlos
1.- Realiza un programa usando la sentencia “if-else” de la manera más simple, mediante el
cual, pueda capturarse un número y el programa pueda indicar si éste es un número par o
impar.
2.- Desarrolla un programa usando “if anidados” mediante el cual pueda conocerse ahora el
menor de tres números capturados.
3.- Desarrolla un programa usando la sentencia “if-else-if” que capture las edades de Juan y
María, y que indique si ambos pueden votar, si Juan puede votar y María no, si María puede
votar y Juan no, o si ninguno de los dos puede votar.
4.- Usando el operador ternario ‘?’, desarrolla el programa no. 1.
133
Resumen.
Estas sentencias de control selectivas son básicas para complementar los programas que
estamos desarrollando. Para eso, es necesario que te apropies del conocimiento de la
sintaxis y aplicación de cada una de las tres sentencias, por esa razón se te presenta este
resumen en forma de mapa conceptual.
Sentencias de control selectivas
Sentencia if
if (expresión) sentencia1;[else sentencia2;]
Operador ternario ‘?’ Sentencia switch()
expresión1?expresión2:expresión3;
switch(var){ case constante1: secuencia_de_sentencias1; break; case constante2: secuencia_de_sentencias2; break; . . . case constante_n: secuencia_de_sentencias_n; break; default: secuencia_de_sentencias;}
eses
es
Su sintaxis es Su sintaxis es Su sintaxis es
134
De manera imprescindible, en los lenguajes de programación actuales, se usan las
iteraciones, ciclos o bucles, de los cuales encontramos tres formas principales while, do-
while y for. Este tipo de sentencias, permiten tener un alto grado de control sobre las
variables que estamos manejando en nuestros programas.
La sintaxis de este ciclo, es la siguiente:
Es decir, mientras que “condición” sea verdadera (ya habíamos dicho que es mientras sea
diferente de cero), ejecutará “sentencia” hasta que la condición cese y entonces terminará el
ciclo. La forma que adoptará en un diagrama de flujo será la siguiente:
Fig. 2.5. Diagrama de flujo de la sentencia “while”.
while (condición) sentencia;
2.4. Sentencias de control repetitivas.
2.4.1. while( )
135
“condición” es cualquier expresión que se evaluará y cuando sea diferente de cero, se
tomará como verdadera. Mientras que “sentencia” puede ser una sentencia vacía, una
sentencia sola o un bloque de sentencias entre llaves.
Realicemos un programa que venga a ilustrar lo que acabamos de ver. Captúralo y
compílalo para ver la manera en que se usa esta sentencia.
Ejemplo.
El programa captura cinco números y al final, obtiene el promedio de los mismos,
realizándose la ejecución de la siguiente manera:
Escribe un número entero: 5
Escribe un número entero: 6
Escribe un número entero: 7
#include "stdio.h" main(){ int cont=0; int num; int suma=0; while (cont<5){ printf("Escribe un numero entero : "); scanf("%d", &num); suma=suma+num; cont++; } printf("El promedio de los numeros capturados es : %d", suma/5); }
136
Escribe un número entero: 8
Escribe un número entero: 9
El promedio de los números capturados es : 7
A diferencia de los ciclos “while” y “for”, que realiza el análisis de la condición al
principio, el ciclo “do-while” lo hace al final del mismo. Esto implica que la sentencia, se
va a ejecutar por lo menos una vez.
La sintaxis para esta sentencia es la siguiente:
Es decir, ejecutar (hacer) la secuencia_de_sentencias mientras que condición sea verdadera,
o sea, diferente de cero.
Para ponerlo en función de un diagrama de flujo, lo haremos de la siguiente manera:
do{ secuencia_de_sentencias } while (condición);
2.4.2. do-while
137
sentencia
condición
NoSi
Fig. 2.6. Diagrama de flujo de la sentencia “do-while”.
Si seguimos el flujo del diagrama, de arriba hacia abajo, por supuesto como lo indican las
flechas, primero se ejecuta “sentencia” una vez, luego evalúa si es que “condición” es
verdadera, si lo es, repite “sentencia” y vuelve a evaluar, hasta que la condición cesa, y
entonces termina el ciclo y el programa sigue su flujo.
Un ejemplo para ilustrar el presente ciclo, será el siguiente, en el cual se calcula el factorial
de un número, el cual se pide.
138
Ejemplo.
Cuando se ejecuta, quedará de la siguiente manera:
Escribe un numero del cual quieras conocer su factorial : 5
El factorial del numero 5 es : 120
El uso más común de la sentencia “do-while” es en un programa que presente un menú, en
combinación con la sentencia “switch”, escribamos un ejemplo que contenga ambas
sentencias.
#include "stdio.h" main(){ int numero, factorial, c; printf("Escribe un numero del cual quieras conocer su factorial : "); scanf ("%d", &numero); c=0; /*este es el contador*/ factorial=1; do{ c++; factorial=factorial*c; }while(c<numero); printf("El factorial del numero %d es : %d", numero, factorial); return 0; }
139
Ejemplo.
Este programa, solicita dos números, el primero mayor que el Segundo. Cuando se le
proporcionan, entonces entra en el ciclo de escribir el menú, que nos permitirá elegir suma,
resta, multiplicación, división o salir, y continuará repitiéndose en tanto no se elija salir.
#include "stdio.h" main(){ int a,b,opc; printf("Escribe dos numeros, el primero mayor que el segundo : "); scanf ("%d %d", &a,&b); do{ printf("1. Obtener suma de %d + %d \n", a,b); printf("2. Obtener resta de %d - %d \n", a,b); printf("3. Obtener multiplicación de %d * %d \n", a,b); printf("4. Obtener la division de %d / %d \n", a,b); printf("5. Salir \n"); printf("Elige tu opcion : "); scanf("%d", &opc); switch(opc){ case 1: printf("La suma de %d + %d es %d \n", a,b,a+b); break; case 2: printf("La resta de %d - %d es %d \n", a,b,a-b); break; case 3: printf("La multiplicacion de %d * %d es %d \n", a,b,a*b); break; case 4: printf("La division de %d / %d es %d \n", a,b,a/b); break; case 5: return 0; } /*switch*/ }while(opc!=5); }/*main*/
140
Veamos un ejemplo de cómo quedaría la ejecución de este programa:
Escribe dos números, el primero mayor que el segundo : 9 3
1. Obtener suma de 9 + 3
2. Obtener resta de 9 – 3
3. Obtener multiplicación de 9 * 3
4. Obtener división de 9 / 3
5. Salir
Elige tu opción : 1
La suma de 9 + 3 es 12
1. Obtener suma de 9 + 3
2. Obtener resta de 9 – 3
3. Obtener multiplicación de 9 * 3
4. Obtener división de 9 / 3
5. Salir
Elige tu opción : 5
La sintaxis para este ciclo, es el siguiente:
for(inicialización;condición;incremento) sentencia;
2.4.3. for
141
“Inicialización” es la condición inicial de la llamada “variable de control”, “condición”
marca cuándo termina el ciclo, e “incremento” (también llamado paso) define la manera en
que cambia la variable de control. Estas tres partes, llevan un ‘;’ (punto y coma) para
separarlas.
Para poner esto en un diagrama de flujo, podría ser de la siguiente manera:
Fig. 2.7. Diagrama de flujo de la sentencia “for”.
Un ejemplo sencillo es hacer la suma de los 50 primeros números.
142
Ejemplo.
Las líneas del programa, indican que se inicializa la variable “sum” a cero, luego hace la
inicialización de la variable de control ‘c’ a 1, y evalúa, mientras que ‘c’ sea menor o igual
a cincuenta, realizará la suma de la variable de control a la variable suma. Al ejecutar el
programa, el resultado obtenido será:
La suma de los primeros cincuenta números es : 1275
Hagamos otro programa, que, dado un número N a través del teclado, el programa escribirá
la tabla del N-1, la tabla del N y la tabla de N+1.
#include "stdio.h" main(){ int sum, c; sum=0; for(c=1;c<=50;c++) sum=sum+c; printf("La suma de los primeros cincuenta numeros es : %d", sum); }
143
Ejemplo.
Al ejecutarse, obtendremos los siguientes resultados:
Escribe un numero entero N : 5
La siguiente es la tabla del N-1, N y N+1
4 x 1 = 4 5 x 1 = 5 6 x 1 = 6
4 x 2 = 8 5 x 2 = 10 6 x 2 = 12
.
.
4 x 10 = 40 5 x 10 = 50 6 x 10 = 60
#include "stdio.h" main(){ int num,c; printf("Escribe un numero entero N : "); scanf("%d",&num); printf("La siguiente es la tabla del N-1, N y N+1 \n"); for(c=1;c<=10;c++) printf("%4d x %2d = %4d %10d x %2d = %4d %10d x %2d = %4d\n", num-1,c,((num-1)*c), num,c,num*c,num+1,c,(num+1)*c); return 0; }
144
Actividades de aprendizaje.
Se han propuesto estas actividades con el propósito de que reafirme el estudiante los
conocimientos adquiridos en el tema y es sumamente esencial que se desarrollen, para que
se asegure la apropiación del conocimiento. Utiliza lo que hayas aprendido hasta el
momento y no temas aventurarte en el uso de algún comando, sólo recuerda para qué
fueron hechos y úsalos con completa libertad. Se trata de practicar los conocimientos que se
han adquirido hasta el momento. Si cometieras algún error, revisa el procedimiento que
estás desarrollando y explica cuál fue el problema que te condujo a cometerlo.
1.- Escribe un programa, usando la sentencia “while”, que permita el acceso de cualesquier
letra del alfabeto, y que termine solo si se teclea la letra ‘S’.
2.- Escribir un programa, usando la sentencia “do-while”, que ponga en pantalla los
números de cinco en cinco, hasta el cien.
3.- Usando la combinación de las sentencias “do-while” y “switch( )”, realiza un programa
que presente un menú en pantalla, indicando los diferentes tipos de datos de Lenguaje C
una salida, y cuando se elija alguno de los tipos, que escriba tres ejemplos de dato de ese
tipo.
145
Resumen.
Las sentencias de control repetitivas, como el while, el do-while y el for, son básicas para
dar una forma profesional a nuestros programas, así se complementa el conocimiento que
previamente se ha adquirido sobre programación en lo que se vio en esta Unidad. Para
ayudar a la apropiación del conocimiento que se ha visto, se presenta aquí este Mapa
Conceptual adoptando la forma de resumen.
146
Un repaso sucinto de los temas que incluye la presente unidad, irán a reafirmar los
conocimientos que se han adquirido hasta el momento, como las muy importantes
sentencias por medio de las cuales nos comunicamos en ambos sentidos con la
computadora. Las instrucciones de control de pantalla que nos permitirán hacer muy
maleable la presentación tanto del programa como de sus resultados. Las sentencias de
control selectivas nos permitirán realizar la toma de decisiones de manera automática en la
computadora y la discriminación de entradas para obtener diversos resultados. Las
sentencias de control repetitivas nos permitirán tener un alto control sobre las variables que
estamos manejando en el transcurso de nuestros programas.
Sentencias para entrada y salida de datos.
Las funciones que determinan la entrada y salida estándar, y que están dentro del dominio
del archivo de cabecera llamado “stdio.h”, son las siguientes: getchar( ) guarda un carácter
pulsado desde el teclado y espera por un Intro; putchar(caracter) que escribe un carácter, ya
sea entre comillas o por medio de una variable, en la pantalla; gets(cadena) lee una cadena
desde el teclado; puts(cadena) escribe una cadena, ya sea manifiesta entre comillas dobles o
apuntada por una variable, en la pantalla.
Las funciones que involucran la entrada y salida por consola, dentro del dominio del
archivo “conio.h” son las siguientes: getche( ) que devuelve un carácter leído por el
Recapitulación Unidad 2.
147
teclado; getch( ) que recibe un carácter leído por el teclado, pero no lo muestra en la
pantalla.
Las funciones que involucran la entrada y salida con formato, y pertenecen al archivo de
cabecera “stdio.h”, son las siguientes: printf(formato,argumentos) donde formato indica la
manera en que deben ser expresados los argumentos, y su función es imprimir en la pantalla
cadenas y/o argumentos. Además de los especificadores de formato, encontraremos los
especificadores especiales, para definir con mayor precisión el dato que deseamos que se
presente en la pantalla, también se conocen como banderas ó “flags”; la función
scanf(formato,argumentos) lee del teclado los argumentos, controlados por el formato.
Instrucciones de control de pantalla.
Estas funciones son las siguientes: clrscr( ) que limpia completamente una ventana de texto;
delay(tiempo) que detiene la ejecución del programa “tiempo” milésimas de segundo;
gotoxy(x,y) sitúa el cursor en la posición especificada por columna x, renglón y;
textcolor(color) indica al compilador el color del texto que se va a mostrar en pantalla;
textbackground(color) indica al compilador el color del fondo del texto que se va a
presentar en la pantalla.
Sentencias de control selectivas.
148
Estas sentencias son las siguientes: la sentencia if, que revisa si existe una condición, si es
así, da una salida y si no otra, ya sea ejecutando una sentencia o una secuencia de
sentencias. La sentencia if puede ser simple, tener la forma de if-else, o la forma de ifs
anidados, y una tercera forma llamada escala if-else-if que evalúa múltiples posibilidades.
El operador ternario ‘?’ que puede reemplazar a la sentencia “if”. La sentencia de
ramificación múltiple “switch” que evalúa el valor que tiene una variable y le asigna una
salida diferente, dependiendo de su valor.
Sentencias de control repetitivas.
Estas sentencias que fueron estudiadas en este capítulo, son las siguientes: sentencia while()
que evalúa una condición, y si ésta es verdadera, ejecuta una sentencia (o secuencia de
sentencias). Sentencia do-while que ejecuta una sentencia (o secuencia de sentencias) y
después evalúa si la condición es verdadera, si lo es, repite la ejecución; esto implica que la
sentencia es ejecutada al menos una vez. Sentencia for, que pone una condición inicial de la
variable de control, luego una condición que indica cuándo terminará el ciclo, y finalmente
el paso o incremento de la variable de control.
149
PRÁCTICAS.
PRÁCTICA 1.- USO DEL printf() Y SUS MODIFICADORES.
OBJETIVO:
Realizar un programa que imprime la tabla del 17, usando solamente printf( ) y los
modificadores de longitud de campo.
INTRODUCCION.
Para realizar este programa, es necesario planificarlo. Primero, dice que debe hacerse
usando solamente printf() y sus modificadores de longitud, así que vemos que podemos
hacerlo mediante el uso del formato %d y un modificador simple de 4 dígitos de longitud.
No podemos usar un for, que sería lo más lógico, solamente usaremos el printf. Declaramos
solamente una variable, llamada “pausa” de tipo carácter para hacerle “congelar” la pantalla
al término del programa.
MATERIAL.
Computadora para capturar el programa y ejecutarlo.
PROCEDIMIENTO.
Capturar en el editor de C de tu preferencia, el siguiente código.
150
OBSERVACIONES.
Usaremos la librería “stdio.h” para usar la función printf. Usaremos la librería “conio.h”
para usar la función “getch()” que permitirá pausar la ejecución del programa y ver los
resultados antes de terminar. Usaremos %4d para usar cuatro espacios para escribir el
primero, segundo y tercer números.
#include “stdio.h” #include "conio.h" main(){ char pausa; printf("TABLA DEL 17 \n\n"); printf("%4d * %4d = %4d \n",17,1,17*1); printf("%4d * %4d = %4d \n",17,2,17*2); printf("%4d * %4d = %4d \n",17,3,17*3); printf("%4d * %4d = %4d \n",17,4,17*4); printf("%4d * %4d = %4d \n",17,5,17*5); printf("%4d * %4d = %4d \n",17,6,17*6); printf("%4d * %4d = %4d \n",17,7,17*7); printf("%4d * %4d = %4d \n",17,8,17*8); printf("%4d * %4d = %4d \n",17,9,17*9); printf("%4d * %4d = %4d \n",17,10,17*10); pausa=getch(); return 0; }
151
RESULTADOS.
PRÁCTICA 2.- USO DE LA SENTENCIA switch().
OBJETIVO:
Escribir un programa usando la sentencia “switch” que solicite el tipo de operación
aritmética que se desea realizar, y que escriba en pantalla, dependiendo de la elección:
eligió suma, resta, multiplicación, división entera o división en módulo.
INTRODUCCION.
Escribiremos un programa que permita visualizar primero un menú. En éste, dirá “Elige el
tipo de operación que deseas” y podrá en una lista números con el correspondiente símbolo
de operación aritmética. Entonces, solicitará que elijas una opción. Habiendo elegido una
opción, dependiendo de la elección, será el mensaje que enviará al usuario. Declaramos la
variable “pausa” de tipo carácter, para congelar la pantalla. Declaramos la variable “opc”
de tipo entero, para recibir la opción.
152
MATERIAL.
Hojas blancas para hacer el diagrama de flujo.
Computadora para capturar, compila y ejecutar el programa.
PROCEDIMIENTO.
Primero, realizamos el diagrama de flujo de los datos.
Inicio
Presenta menú
Solicita opc
Switch(opc)
Fin
suma resta multiplicación División entera División en módulo
1 2 3 4 5
6
153
Enseguida, traducimos el diagrama a código en Lenguaje C.
OBSERVACIONES.
Al escribir el código del programa, usamos la librería “stdio.h” porque vamos a usar las
funciones printf, scanf y switch. Usamos la librería “conio.h” porque vamos a usar la
#include "stdio.h" #include "conio.h" main(){ char pausa; int opc; printf("Elige el tipo de operación que deseas:\n"); printf("1. + \n"); printf("2. - \n"); printf("3. * \n"); printf("4. / \n"); printf("5. % \n"); printf("6. Salir \n"); printf("Elige tu opcion : "); scanf("%d", &opc); switch(opc){ case 1: printf("elegiste SUMA\n"); break; case 2: printf("elegiste RESTA\n"); break; case 3: printf("elegiste MULTIPLICACION\n"); break; case 4: printf("elegiste DIVISION ENTERA\n"); break; case 5: printf("elegiste DIVISION EN MODULO\n"); break; case 6: return 0; } /*switch*/ pausa=getch(); }/*main*/
154
instrucción getch() como “congelador” para poder ver el resultado antes de que se termine
de ejecutar el programa.
RESULTADOS.
PRÁCTICA 3.- USO DEL CICLO for().
OBJETIVO:
Escribir un programa usando un ciclo “for” para que ponga en pantalla todos los números
pares del 1 al 100.
INTRODUCCION.
Se va a realizar un programa que use un ciclo “for” y declararemos una variable de control
‘i’ que se va a usar también para imprimirlo si es que es un número par. El ciclo “for” hace
un recorrido completo del 0 al 100, y un ciclo “if” revisa si es par. ¿Cómo se hace esto?
Cuando realizamos una división en módulo entre dos, si el resultado es cero, significa que
155
es divisible entre dos, por lo tanto, es par. Se declara la variable “pausa” de tipo carácter
para hacer que congele la pantalla.
MATERIAL.
Computadora para editar, compilar y ejecutar el programa.
PROCEDIMIENTO.
Capturar el siguiente programa.
OBSERVACIONES.
Usamos la librería “stdio.h” para usar las sentencias printf, for e if. Usamos la librería
“conio.h” para usar el comando “getch()” como un congelador.
RESULTADOS.
#include "stdio.h" #include "conio.h" main(){ int i; char pausa; for(i=0;i<=100;i++){ if(i%2==0) printf("%4d",i); } pausa=getch(); return 0; }
157
Actividades de confirmación de conocimientos.
Si resuelves los siguientes problemas y capturas, compilas y ejecutas los programas
propuestos, vas a afirmar de manera muy recomendable los conocimientos que adquiriste
en el transcurso de este capítulo.
Analiza cada uno de los problemas planteados y explica brevemente el procedimiento que
seguiste para resolverlo.
1.- Usando getchar( ) escribe un programa en el que puedan ser capturados el número de
caracteres que sean, y que termine cuando en una línea nueva, escribimos la letra ‘q’ e
<Intro>. Recuerda que la función getchar carece de argumentos por lo que el valor de
retorno debe ser tomado por medio de asignación.
2.- Usando solamente las funciones gets() y puts() escribe un programa que solicite que
escribas los nombres de cinco de tus amigos, y después de capturarlos, los escriba en el
orden inverso.
3.- Usando printf() y scanf(), escribe un programa que convierta un número a radianes y
obtenga su seno, coseno y tangente. Ten cuidado de usar la librería “math.h” que contiene
las funciones “sen()”, “cos()” y “tan()”. Toma en cuenta que para convertir un número a
radianes, debes multiplicarlo por 0.017453292519943295769236907684886, puesto que las
funciones trigonométricas se aplican a números convertidos a radianes.
158
4.- Usando las funciones scanf() y printf() escribe un programa que solicite dos números a y
b y regrese el valor de a elevado a la b potencia. Para escribir la potencia de un número,
debemos usar la librería “math.h” y la función que le pertenece “pow(x,y)” que significa x
elevado a la y potencia.
5.- Usando las funciones textcolor(), textbackgruond(), clrscr() y delay() realiza un
programa que escriba en pantalla la palabra “P E L I G R O” en letras rojas sobre
fondo blanco, transcurriendo un segundo para escribir cada letra en la pantalla; después
tarde 3 segundos mostrando el letrero y posteriormente, regrese a los colores originales de
la pantalla y limpie la pantalla.
6.- Usando la sentencia if() realiza un programa donde solicite un primer número a, luego
un segundo número b, e indique si es que a es múltiplo de b.
7.- Usando la sentencia if-else-if, realiza un programa que contenga un menú con los
siguientes puntos:
Escribe en dónde usas la computadora.
1.- En la casa
2.- En la escuela
3.- En el trabajo
4.- En el cyber-café
159
5.- Terminar
Elige tu opción
Y que al dar las respuestas diferentes, realice:
1.- Vea la sección de ofertas de trabajo
2.- Vea la sección de tareas en línea
3.- Vea la sección de vacaciones de fines de semana"
4- Vea la sección de venta de equipo barato"
5.- [que termine el programa]
Para cualquier otro número introducido, escriba en la pantalla:
No es una opción valida, lo sentimos...
8.- Usando las sentencias do-while y switch() realiza un programa en el que solicite que se
anote una letra cualquiera, y al momento de pulsarla, el programa devuelva si se trata de
una letra vocal o consonante. Para salir, pulsar la letra ‘x’ e <Intro>.
9.- Usando el ciclo for() realiza un programa que solicite un número e imprima en la
pantalla la sumatoria desde 1 hasta el número.
160
Autoevaluación.
Si resuelves los siguientes problemas y capturas, compilas y ejecutas los programas
propuestos, vas a afirmar de manera muy recomendable los conocimientos que adquiriste
en el transcurso de este capítulo.
Analiza cada uno de los problemas planteados y explica brevemente el procedimiento que
seguiste para resolverlo.
1.- Usando getchar( ) escribe un programa en el que puedan ser capturados el número de
caracteres que sean, y que termine cuando en una línea nueva, escribimos la letra ‘q’ e
<Intro>. Recuerda que la función getchar carece de argumentos por lo que el valor de
retorno debe ser tomado por medio de asignación.
/* primero agregamos las dos líneas de cabeceras, stdio.h para las funciones estándar, y conio.h porque vamos a usar la función getchar() que pertenece a esta librería*/ #include "stdio.h" #include "conio.h" /*ahora escribimos la función principal, que inicia y termina con llaves*/ main(){ /* declaramos la variable a, de tipo carácter, para ser el recipiendario de la letra que reciba el programa desde el teclado*/ char a; /*usamos un ciclo do-while para que termine cuando coincida con la condición indicada que sea cuando a sea una q*/ do { /*hacemos que capture una letra a la vez con getchar()*/ a = getchar(); } while (a!='q'); /*dado que la función principal es integer, necesita un valor de retorno que indique que termina en forma correcta*/ return 0; }
161
Recuerda que antes de la palabra include va el signo de número o gato, y que el nombre de
las cabeceras, ya sea stdio.h, conio.h o la que se esté usando, va entre comillas o entre
“menor que” y “mayor que” así: “stdio.h” o <stdio.h> ; que todos los bloques inician y
terminan con llave, y finalmente, que todas las líneas de orden o comandos, deben terminar
con un punto y coma.
2.- Usando solamente las funciones gets() y puts() escribe un programa que solicite que
escribas los nombres de cinco de tus amigos, y después de capturarlos, los escriba en el
orden inverso.
/*primero, ponemos stdio.h para las funciones estándar de entrada y salida, luego conio.h porque vamos a usar puts() y gets()*/ #include "stdio.h" #include "conio.h" /* escribimos la función principal*/ main(){ /*declaramos cadenas de la 1 a la 5, de 80 caracteres para recibir las cadenas a capturar*/ char cad1[80], cad2[80], cad3[80], cad4[80], cad5[80]; /*declaramos e inicializamos las cadenas 6 y 7 */ char cad6[80]="Escribe cinco nombres de amigos"; char cad7[80]="==============================="; /*escribimos las cadenas 6 y 7*/ puts(cad6); puts(cad7); /*obtenemos las cadenas 1 a la 5*/ gets(cad1); gets(cad2); gets(cad3); gets(cad4); gets(cad5); /*escribe la cadena 7*/ puts(cad7); /*escribe la cadena indicada*/ puts("Tus amigos son: ");
162
Nótese que las cadenas cad1 a cad5 tienen la misma longitud, así que podemos declararlas
todas juntas, no así el caso de cad6 y cad7, que se van a inicializar, así que deben declararse
con todo y su valor inicial cada una por separado. La función getch(), pese a que está hecha
para capturar un carácter, se usa aquí para congelar la pantalla, pues cuando pulsamos
cualquier tecla, el programa continúa y concluye, y no nos permitiría ver los resultados. Lo
demás es la aplicación de las funciones gets() para obtener una cadena por el teclado y
puts() para escribir el contenido de esa cadena en la pantalla.
3.- Usando printf() y scanf(), escribe un programa que convierta un número a radianes y
obtenga su seno, coseno y tangente. Ten cuidado de usar la librería “math.h” que contiene
las funciones “sen()”, “cos()” y “tan()”. Toma en cuenta que para convertir un número a
radianes, debes multiplicarlo por 0.017453292519943295769236907684886, puesto que las
funciones trigonométricas se aplican a números convertidos a radianes.
/*imprime las cadenas 1 a 7, menos la 6, en diferente orden*/ puts(cad7); puts(cad5); puts(cad4); puts(cad3); puts(cad2); puts(cad1); puts(cad7); /*congela la pantalla */ getch(); /*regresa un valor porque main es integer*/ return 0; }
163
Como vamos a usar las funciones sin(), cos() y tan() (seno, coseno y tangente
respectivamente), agregaremos en los include el archivo de cabecera “math.h” que contiene
esas funciones. Para declarar num, seno, coseno, tangente y radianes, como todas son de
tipo double, se declaran juntas. La variable num no puede ser usada tal cual, porque
representa una cantidad en grados, debe ser convertida a radianes, haciendo precisamente
que la variable “radianes” tenga ese valor, y entonces sí se le aplican las funciones
trigonométricas.
/*escribimos los archivos de cabecera stdio.h por las funciones estándar de entrada y salida, conio.h por el getch() y math.h por las funciones sin(), cos() y tan()*/ #include "stdio.h" #include "conio.h" #include "math.h" /* se hace la funcion main()*/ main(){ /*se declaran las variables que van a recibir los valores a usar*/ double num, seno, coseno, tangente, radianes; /*se solicita y captura un número doble*/ printf("Ingrese un numero..."); scanf("%lf",&num); /* se convierte num a radianes y se deposita en la variable ‘radianes’*/ radianes = num*0.017453292519943295769236907684886; /*se obtienen las funciones seno, coseno y tangente*/ seno = sin(radianes); coseno = cos(radianes); tangente = tan(radianes); /*se imprimen los resultados*/ printf("%.4lf equivale a: \n",num); printf("%.4lf radianes\n",radianes); printf("%.4lf seno\n",seno); printf("%.4lf coseno\n",coseno); printf("%.4lf tangente\n",tangente); /*¨se congela la pantalla*/ getch(); /*retorna el valor entero, pues main es entero*/ return 0; }
164
4.- Usando las funciones scanf() y printf() escribe un programa que solicite dos números a y
b y regrese el valor de a elevado a la b potencia. Para escribir la potencia de un número,
debemos usar la librería “math.h” y la función que le pertenece “pow(x,y)” que significa x
elevado a la y potencia.
Va a usarse la función pow(x,y) que está incluida en el archivo de cabecera “math.h”, razón
por la cual, debemos de agregar el archivo. Se declaran las variables a, b y c que son del
mismo tipo (double) así que se declaran juntas. Se usan scanf() para recibir un valor del
teclado y printf() para escribir una cadena y variables en la pantalla.
5.- Usando las funciones textcolor(), textbackgruond(), clrscr() y delay() realiza un
programa que escriba en pantalla la palabra “P E L I G R O” en letras rojas sobre
fondo blanco, transcurriendo un segundo para escribir cada letra en la pantalla; después
/* se declaran las cabeceras stdio.h para funciones estándar de entrada y salida, conio.h para getch(), así como math.h para la function pow()*/ #include "stdio.h" #include "conio.h" #include "math.h" /*se indica la funcion main*/ main(){ /*se declaran las variables a, b y c dobles */ double a,b,c; /* se solicitan y capturan los dos números a y b*/ printf("Ingrese el 1er número..."); scanf("%lf",&a); printf("Ingrese el 2do número..."); scanf("%lf",&b); /*se haqce que c guarde el valor de a elevado a la b*/ c = pow(a,b); /se imprime el resultado*/ printf("El resultado de elevar %.2lf a %.2lf es... %.2lf",a,b,c); /*se congela la pantalla*/ getch(); /*regresa un valor entero puesto que main es entero*/ return 0; }
165
tarde 3 segundos mostrando el letrero y posteriormente, regrese a los colores originales de
la pantalla y limpie la pantalla.
Va a usarse la función delay() que está incluida en el archivo de cabecera “dos.h”, así que
lo debemos incluir. Las funciones clrscr() y getch() están incluidas en el archivo de
cabecera “conio.h”, por lo que debe utilizarse también. Los colores de texto y de fondo se
/*se declaran las cabeceras stdio.h para entrada y salida estándar, conio.h para el clrscr() y dos.h para el delay()*/ #include "stdio.h" #include "conio.h" #include "dos.h" /*se declara la funcion principal*/ main(){ /*limpia pantalla*/ clrscr(); /*se ponen los colores de texto y de fondo*/ textcolor(RED); textbackground(WHITE); /*se imprime la palabra PELIGRO con un delay de 1 seg para cada letra*/ cprintf("P "); delay(1000); cprintf("E "); delay(1000); cprintf("L "); delay(1000); cprintf("I "); delay(1000); cprintf("G "); delay(1000); cprintf("R "); delay(1000); cprintf("O"); delay(3000); /*se regresan los colores de texto y de fondo a su formato normal*/ textcolor(WHITE); textbackground(BLACK); /*limpia pantalla*/ clrscr(); /*regresa codigo entero de exito porque main es entero*/ return 0; }
166
anotan con mayúsculas. Para que las letras vayan poniéndose en colores en la pantalla, debe
utilizarse la función cprintf() que está dentro del archivo de cabecera “conio.h”, por lo que
debe incluirse. Al ir escribiendo cada letra, damos una dilación de un segundo, puesto que
la función delay(n) tiene como argumento n milisegundos, si escribimos delay(1000)
equivale a una dilación de un segundo.
6.- Usando la sentencia if() realiza un programa donde solicite un primer número a, luego
un segundo número b, e indique si es que a es múltiplo de b.
En este programa, es muy importante la utilización de la división en módulo, el módulo es
el residuo de la división, así que solamente dará como resultado a%b=0 si es que a es
múltiplo de b, por ejemplo 8%2=0, si esto fuera verdad, imprimirá en pantalla que a sí es
múltiplo de b, y si no lo fuera, imprimirá que no lo es.
/*se declaran las cabeceras stdio.h para entrada y salida estándar, y conio.h para el getch()*/ #include "stdio.h" #include "conio.h" /*se declara la función principal*/ main(){ /*se declaran los números a y b*/ int a,b; /*se ingresan los números*/ printf("Ingrese el 1er numero..."); scanf("%d",&a); printf("Ingrese el 2do numero..."); scanf("%d",&b); /*se revisa si la division en modulo de a entre b da cero, si es así, es múltiplo*/ if(a%b==0) printf("%d si es multiplo de %d",a,b); else printf("%d no es multiplo de %d",a,b); /*se congela la pantalla*/ getch(); }
167
7.- Usando la sentencia if-else-if, realiza un programa que contenga un menú con los
siguientes puntos:
Escribe en dónde usas la computadora.
1.- En la casa
2.- En la escuela
3.- En el trabajo
4.- En el cyber-café
5.- Terminar
Elige tu opción
Y que al dar las respuestas diferentes, realice:
1.- Vea la sección de ofertas de trabajo
2.- Vea la sección de tareas en línea
3.- Vea la sección de vacaciones de fines de semana"
4- Vea la sección de venta de equipo barato"
5.- [que termine el programa]
Para cualquier otro número introducido, escriba en la pantalla:
No es una opción valida, lo sentimos...
/*se declaran las cabeceras stdio.h para entrada y salida estándar, y conio.h para el getch()*/ #include "stdio.h" #include "conio.h" /*se declara la funcion principal*/ main(){ /*se declara la variable opc de tipo carácter*/ char opc;
168
En este programa, se declara opc de tipo carácter, que es la variable que va a contener la
opción elegida por el usuario. Mediante la función puts() se imprime el menú en la pantalla.
Nótese que la variable opc recibirá el valor que le de el usuario mediante un operador de
asignación, de la siguiente manera: opc=getch(). Se está solicitando un valor para que
coincida con alguna de las opciones del menú, pero como se está solicitando un carácter,
entonces la comparación debe ser hacia un carácter, sin importar que sea un número,
entonces será comparado con ‘1’, ‘2’, ‘3’, ‘4’ y ‘5’ que son caracteres, y no con 1, 2, 3, 4 y
5 que son números enteros. Si no coincidiera con ninguno de los valores, entonces mandará
un “warning” o mensaje de advertencia.
/*imprime el menú*/ puts("Escribe en donde usas la computadora."); puts("1. En la casa"); puts("2. En la escuela"); puts("3. En el trabajo"); puts("4. En el cyber-cafe"); puts("5. Terminar"); /*solicita elegir la opción, y pide el valor de opc*/ puts("Elige tu opcion"); opc=getch(); /*usa un if-else-if para tomar las 5 opciones*/ if(opc=='1') puts("Vea la seccion de ofertas de trabajo"); else if (opc=='2') puts("Vea la seccion de tareas en linea"); else if (opc=='3') puts("Vea la seccion de vacaciones de fines de semana"); else if (opc=='4') puts("Vea la seccion de venta de equipo barato"); else if (opc=='5') return 0; else puts("No es una opcion valida, lo sentimos..."); /*congela la pantalla después de la ejecución*/ getch(); }
169
8.- Usando las sentencias do-while y switch() realiza un programa en el que solicite que se
anote una letra cualquiera, y al momento de pulsarla, el programa devuelva si se trata de
una letra vocal o consonante. Para salir, pulsar la letra ‘x’ e <Intro>.
Se declara una variable entera llamada “vocal” que vamos a utilizar como bandera, es decir,
como una variable con valores boléanos, solamente 1 si es verdadero, 0 si es falso. Para
capturar las letras, usamos getche() para que sea la letra y espere por un “return”. El do-
/*se declaran las cabeceras, stdio.h para funciones estándar de entrada y salida*/ #include "stdio.h" #include "conio.h" /*se declara la funcion principal*/ main(){ /*se declara la variable letra de tipo caracter, vocal de tipo entero*/ char letra; int vocal; /*escribe las indicaciones*/ puts("Escribe una letra para identificar si es o no vocal. \nUna 'x' e <Intro> para terminar"); /*hace una repetición al solicitar una letra*/ do{ letra=getche(); switch(letra){ case 'a': case 'e': case 'i': case 'o': case 'u': vocal=1; break; default: vocal=0; } /*si es una vocal o una consonante, entonces escribirlo*/ if(vocal) puts(" : Es una Vocal"); else puts(" : Es una Consonante"); }while (letra!='x'); /*congela pantalla*/ getch(); }
170
while lo usamos para repetir las órdenes en tanto no se cumpla con el requisito que permite
que se termine con el ciclo, que es cuando la letra sea una ‘x’, como se indica al final del
do-while. Luego se hace un switch() que indica, si es a, e, i, o, u entonces la bandera es 1; si
es cualesquier otra letra, la bandera es 0. Lo último es evaluar: si la bandera es verdadera
entonces se trata de una vocal, si no lo es, se trata de una consonante.
9.- Usando el ciclo for() realiza un programa que solicite un número e imprima en la
pantalla la sumatoria desde 1 hasta el número.
Como i, num y suma son del mismo tipo, se declaran juntos. La variable suma va a tener el
valor de lo que vaya sumándose, así que necesita ser inicializada, mediante la asignación de
suma=0. Se captura primero el número límite num. El ciclo for() se usa para realizar la
sumatoria desde 1 hasta num que es el límite.
/*declara las cabeceras, stdio.h para entrada y salida estándar, conio.h para getch()*/ #include "stdio.h" #include "conio.h" /*se declara la función principal*/ main(){ /*se declaran i, num y suma como enteros*/ int i, num, suma; /*se inicializa suma a cero*/ suma=0; /*se solicita el número límite para la sumatoria*/ puts("Escribe un numero N para calcular la sumatoria desde 1 hasta N"); scanf("%d",&num); /*se realiza la sumatoria con cada número*/ for(i=1;i<=num;i++) suma=suma+i; printf("La sumatoria de 1 hasta %d es : %d",num,suma); /*se congela la pantalla*/ getch(); }
172
PROPOSITO
¿QUÉ APRENDERÁS?
Diferentes aspectos de los arreglos como a identificar la forma en que se declaran e
inicializan los arreglos. A usar tanto los arreglos unidimensionales como los
bidimensionales. Además a aplicar problemas que involucren algoritmos de ordenación y
búsqueda.
¿CÓMO LO APRENDERÁS?
Participarás activamente en las clases, y desarrollarás los ejemplos que el profesor te
indicará, y que están presentes en este libro. De la misma manera, desarrollarás las
prácticas diseñadas en esta unidad, para que aprendas el método que se usa para la
resolución de problemas reales.
¿PARA QUÉ LO APRENDERÁS?
Para adquirir la habilidad necesaria para resolver problemas que involucren estos tópicos y
con las habilidades desarrolladas después de estudiar las dos anteriores unidades, aplicando
todo el cúmulo de conocimientos que debes haber adquirido.
173
Puede ser que resulte muy útil pensar en lo que significa realizar un arreglo. Por ejemplo, si
en tu estudio necesitaras acomodar los libros de tu librero, ¿qué método seguirías? Si
además, tuvieras un librero disponible con cuatro entrepaños del mismo tamaño, ¿cómo
buscarías acomodarlos?
Quizás primero se deberían acomodar los libros por materia, y reunirlos: 15 de
computación, 10 de literatura, 8 de química 12 de un diccionario, etc. Entonces deberíamos
acomodarlos siguiendo el plan de optimizar el espacio, poniendo juntos los libros que
reunimos por materias. Algo parecido ocurre con un arreglo, que es cuando reunimos una
cierta cantidad de elementos del mismo tipo. Si además vamos acomodando en orden
alfabético los libros, tendríamos un algoritmo de ordenación. Para buscar entonces un autor,
usamos un algoritmo de búsqueda que discrimine a los que no cumplen con nuestra
exigencia.
Las estructuras de datos se clasifican en lineales y no lineales. Las lineales, que representan
el almacenamiento consecutivo de variables en memoria, reciben el nombre de arreglos
(arrays) en una primera forma de representación, otra se obtiene representando la relación
entre los elementos usando apuntadores (o punteros), y reciben el nombre de listas
3. Arreglos
3.1.- Declaración e inicialización
174
enlazadas, pero también pudieran ser pilas y colas. Las estructuras no lineales pueden ser
árboles o adoptar la forma de grafos.
En una estructura lineal, ya sea arreglo o lista enlazada, se pueden realizar diferentes
operaciones, que son las siguientes:
a.- Recorrido. Procesa cada elemento.
b.- Búsqueda. Localiza una posición.
c.- Inserción. Agrega un nuevo elemento.
d.- Borrado. Elimina un elemento.
e.- Ordenación. Organiza la lista.
f.- Mezcla. Combina dos listas.
Las estructuras de datos, también pudieran ser clasificadas como estáticas y dinámicas.
Las estructuras estáticas de datos son las siguientes:
Array (vector/matriz)
Estructuras
Archivo
Cadena de caracteres
Las estructuras dinámicas de datos son las siguientes:
Lista (pila/cola)
Lista enlazada
175
Arbol
Grafo
Se conoce como arreglo a un conjunto de variables que corresponden al mismo tipo, y que
comparten un nombre, aunque cada variable (que se denomina elemento) se diferencia de
otra por un índice que sirve para acceder a su contenido. Cuando se declara el arreglo, el
índice realmente está definiendo el tamaño y la dimensión del mismo, y esto significa que
es un número fijo de elementos el que lo compone.
La cantidad de memoria de la computadora, es el límite para la cantidad máxima de
variables que puede guardar un arreglo, y se guardará en forma contigua.
Las variables pueden ser de cualquiera de los tipos de datos, pero en un arreglo, todas
deben ser del mismo tipo. La característica principal de un arreglo es que al conocer el
índice, puede accederse a cualquier elemento del mismo.
La declaración de un arreglo tomará la sintaxis siguiente:
• Tipo_de_datos: será cualquier tipo de datos conocido en C, con excepción de void.
• identificador: es un nombre único para este arreglo, que servirá para referenciar a
los elementos que lo compongan.
tipo_de_datos identificador[no_de_elementos];
176
• no_de_elementos: será el tamaño del arreglo.
Por ejemplo:
int numeros[5];
char letras[10];
float sueldos[100];
Tomemos el primer ejemplo para desglosarlo:
int indica que todos los elementos (variables) que componen este arreglo son
números enteros
numeros es el identificador o nombre del arreglo
5 es el tamaño
numeros[0],
numeros[1],
numeros[2],
numeros[3],
numeros[4]
Estos son los elementos del arreglo. Aunque su tamaño es cinco, su índice
va de cero a cuatro, puesto que en C, el cero es el primer número. En un
arreglo de n elementos, el índice que los identificará va a ir siempre de 0 a
n-1.
177
Puedes declarar un arreglo en forma global o local. Si lo declaras en forma global, todos sus
elementos tendrán el valor de cero. Si lo declaras en forma local, puedes inicializarlo
(darles un valor inicial), como en los ejemplos siguientes:
int num[3]={3,5,7};
Aquí, se están inicializando todos los elementos del arreglo, es decir:
num[0]=3, num[1]=5 y num[2]=7
Aunque pudiera ser inicializado de manera parcial, por ejemplo:
int num[5]={3,5};
Aquí sólo se están inicializando los dos primeros elementos del arreglo, por lo tanto,
tendríamos:
num[0]=3, num[1]=5, num[2]=0, num[3]=0 y num[4]=0
Una tercera forma de inicializar un arreglo sería la siguiente:
int num[]={1,3,5,7,9};
178
En esta forma, se evita mencionar el tamaño del arreglo, pues es obvio que si se están
inicializando cinco elementos, el arreglo es de tamaño 5.
Si se tratara de un arreglo bidimensional, entonces se declaran como sigue:
Los elementos que componen esta declaración son:
tipo: es el tipo de datos que es aceptado por Lenguaje C, con excepción de void.
identificador: es el nombre único que servirá para identificar los elementos del arreglo
bidimensional.
indice1: en la representación de filas-columnas, indica las filas.
indice2: indica las columnas de la tabla.
Por ejemplo:
int num[3][4];
Indica que se trata de una tabla que tiene tres filas y cuatro columnas:
0 num[0][0] num[0][1] num[0][2] num[0][3]
1 num[1][0] num[1][1] num[1][2] num[1][3]
2 num[2][0] num[2][1] num[2][2] num[2][3]
0 1 2 3
tipo identificador[indice1][indice2];
179
Por ejemplo, para inicializar este arreglo, pudiera hacerse mediante la siguiente expresión:
int num[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
de esa manera, el orden sería primero recorriendo una fila, todas las columnas; la 0, todas
las columnas; luego la 1, todas las columnas; luego la 2, todas las columnas sería:
num[0][0]=1
num[0][1]=2
num[0][2]=3
num[0][3]=4
num[1][0]=5
num[1][1]=6
num[1][2]=7
num[1][3]=8
num[2][0]=9
num[2][1]=10
num[2][2]=11
num[2][3]=12
180
Cada una de las dimensiones, pueden representar a las estructuras de datos. Un arreglo
unidimensional (también llamado lista) representa un vector; un arreglo bidimensional
representa una tabla o matriz; un arreglo de tres o más dimensiones, entonces representa un
espacio vectorial de tres o más dimensiones.
Vamos a tomar un ejemplo para poder ilustrar lo que se refiere a las dimensiones.
Supongamos la lista de las calificaciones que un estudiante puede tener de la materia de
matemáticas, podríamos representarla mediante una pequeña lista que incluya los cuatro
períodos (cada pequeño cubo es un elemento):
Fig. 3.1. Los cuatro elementos del arreglo separados.
Y si los acomodamos en una sola lista, array o vector, quedaría así:
Fig. 3.2. El arreglo cal[4] con sus elementos unidos.
cal[0] cal[1] cal[2] cal[3]
0 1 2 3
cal
Períodos
Período
181
Podríamos declarar el arreglo UNIDIMENSIONAL como:
int cal[4];
/* 4 son los períodos */
Pero si llevara, además otras materias, tendríamos que pensar en hacer una tabla, es decir,
un arreglo unidimensional de arreglos unidimensionales, de períodos contra materias,
representando entonces con la tabla quedaría:
Fig. 3.3. Los cuatro arreglos unidimensionales cal[4].
0 1 2 3
cal 0 1 2 3
cal 0 1 2 3
cal 0 1 2 3
cal materia0
materia1
materia2
materia3
Período
182
Si lo juntamos, podría quedar como sigue:
Fig. 3.4. Arreglo bidimensional cal[4][4].
Podríamos declarar entonces este arreglo BIDIMENSIONAL como:
int cal[4][4];
/* el primer cuatro se refiere a cada materia (fila), y el segundo a cada período por
calificación (columna)*/
Asumamos entonces que la tabla esa, representa las calificaciones de los cuatro parciales de
las cuatro materias que un estudiante tiene, pero deberíamos pensar en que habrá en el
grupo, varios estudiantes más. Supongamos que es así, y que representamos cuatro
estudiantes con sus respectivas tablas cada uno, de la siguiente manera:
cal
0 1 2 3
0 1 2 3 Períodos
materias
183
Fig. 3.5. Los cuatro arreglos bidimensionales(tablas)
O sea, un arreglo unidimensional de arreglos bidimensionales, que si juntamos, quedaría de
la siguiente manera:
Períodos
cal
0 1 2 3
0 1 2 3
cal
0 1 2 3
0 1 2 3
cal
0 1 2 3
0 1 2 3
cal
0 1 2 3
0 1 2 3
materias
estudiante 3
estudiante 2
estudiante 1
estudiante 0
184
Fig. 3.6. Arreglo tridimensional cal[4][4][4].
Podríamos identificar como que cada tabla que va hacia atrás (hacia el eje z) represente un
nuevo estudiante, así, este cubo, representaría un grupo completo, de cuatro estudiantes
cada uno, y cada estudiante con cuatro parciales de cuatro materias.
Podríamos declarar entonces este arreglo TRIDIMENSIONAL como:
int cal[4][4][4];
/* El primer cuatro, representa cada materia, el segundo cada período y el tercero,
representa los cuatro estudiantes*/
0 1 2 3
0 1 2 3
32
10
cal
estudiantes
materias
Períodos
185
Podemos seguir creciendo en dimensiones, y para comprenderlo, podríamos representar
cada grupo con un cubo (ya sin que muestre las divisiones), así que, si representamos que
en nuestra escuela tenemos cuatro grupos, entonces tendríamos un arreglo unidimensional
de arreglos tridimensionales, pues el arreglo lo podríamos representar de la siguiente
manera:
Fig. 3.7. Los cuatro cubos representando los grupos
Si unimos los grupos, quedaría así:
Fig. 3.8. Arreglo unidimensional de cubos cal[4][4][4][4]
Y la declaración de este arreglo MULTIMENSIONAL DE CUATRO DIMENSIONES se
realizaría de la siguiente manera:
int cal[4][4][4][4];
grupos 0 1 2 3
grupos 0 1 2 3
cal
186
/* El primer cuatro, representa cada materia, el segundo cada período, el tercero representa
los cuatro estudiantes, y el último, el número de grupos que hay en la escuela*/
Entonces, si cada escuela quedara representada por esta arreglo de cubos, pensaríamos en
representar una dimensión más, que pudiera corresponder con la zona escolar, de la
siguiente manera, representando un arreglo unidimensional de arreglos de cuatro
dimensiones:
Fig. 3.9. Los tres arreglos lineales de cubos, representando tres escuelas
Que unidos, darían la zona escolar en donde tendríamos tres escuelas con cuatro grupos
cada una de ellas, o sea:
grupos 0 1 2 3
cal
grupos 0 1 2 3
cal
grupos 0 1 2 3
cal escuela 0
escuela 1
escuela 2
187
Fig. 3.10. Arreglo multimensional de 5 dimensiones cal[4][4][4][4][3]
Y la declaración de este arreglo MULTIMENSIONAL DE CINCO DIMENSIONES se
realizaría de la siguiente manera:
int cal[4][4][4][4][3];
/* El primer cuatro, representa cada materia, el segundo cada período, el tercero representa
los cuatro estudiantes, el cuarto, el número de grupos que hay en la escuela, y el tres, el
número de escuelas que hay en la zona escolar*/
Y todavía yendo más allá, podríamos pensar en que en nuestro Estado haya dos zonas
escolares de tres escuelas cada una, entonces podríamos representarlas así:
cal
0 1 2 3
escuelas
0 1 2
grupos
188
Fig. 3. 11. Los dos arreglos multidimensionales de cinco dimensiones,
representando cada uno de ellos una zona escolar
Y si las unimos para mostrar el arreglo unidimensional de arreglos de cinco dimensiones,
quedaría así:
Fig. 3.12. Arreglo multidimensional de seis dimensiones cal[4][4][4][4][3][2]
cal
0 1 2 3
escuelas
0 1 2
grupos
cal
0 1 2 3
escuelas
0 1 2
grupos
zona 0
zona 1
grupos
escuelas
10 cal
zonas
0 1 2
0 1 2 3
189
Y la declaración de este arreglo MULTIMENSIONAL DE SEIS DIMENSIONES se
realizaría de la siguiente manera:
int cal[4][4][4][4][3][2];
/* El primer cuatro, representa cada materia, el segundo cada período, el tercero representa
los tres estudiantes, el cuarto, el número de grupos que hay en la escuela, el tres, el número
de escuelas que hay en la zona escolar, y el dos, el número de zonas escolares que hay en el
estado*/
190
Actividades de aprendizaje
Las siguientes actividades, fueron diseñadas para permitir que te apropies de los conceptos
de arreglo y sus características inherentes, entendiendo previamente lo que son las
estructuras de datos y las operaciones que con ellas se pueden realizar.
1.- Escribe la clasificación de las estructuras de datos en las dos formas conocidas.
2.- Representa por medio de un dibujo o un esquema, las operaciones que se pueden
realizar en una estructura lineal, expresando en qué consiste cada una de ellas.
3.- Elabora un Mapa Conceptual que exprese qué es un arreglo y de qué partes está
compuesto.
4.- ¿Cuál es el límite para la cantidad máxima de variables que puede guardar un arreglo?
191
Resumen
Se te presenta el siguiente mapa conceptual en este resumen, para reafirmar los
conocimientos adquiridos.
Dentro de las estructuras de datos básicas, las más importantes, son los arreglos desde los
unidimensionales hasta los multidimensionales, y es importantísimo que adquieras los
conocimientos sobre la forma que tienen, la manera en que se declaran e inicializan.
Estructuras de datos
Lineales No lineales
arreglos Listas enlazadas pilas colas árboles grafos
operaciones
Pueden ser Pueden ser
Pueden realizar
recorrido borrado mezcla
búsqueda inserción
Estáticas Dinámicas
Pueden ser Pueden ser
lista
Lista enlazada
árbol
grafo
arreglos
estructuras
archivos
cadenas
192
Un arreglo unidimensional se definiría como un conjunto ordenado y finito de elementos
homogéneos. Ordenado significa que habrá un elemento en el elemento cero, otro en el
uno, y así consecutivamente. Finito significa que la cantidad de elementos en el arreglo es
específica. Homogéneo significa que todos los elementos son del mismo tipo.
La sintaxis para declarar un arreglo unidimensional, entonces es la siguiente:
El peso en bytes del arreglo, lo obtendremos mediante la fórmula:
Por ejemplo, si declaramos un arreglo de diez elementos enteros:
int num[10];
El peso en bytes lo obtendremos al multiplicar el tamaño de un elemento de tipo entero (16
bits, que equivalen a dos bytes) por su tamaño, veamos cómo:
Peso=sizeof(int)*10
Peso=2 bytes*10
Peso= 20 bytes
tipo identificador[tamaño];
Peso = sizeof(tipo)*tamaño
3.2.- Uso de arreglos unidimensionales.
193
Si se tratara de un arreglo de float serían 4 bytes, y si fuera double de 8 bytes.
Otro ejemplo es el siguiente:
Si se declara
char num[7]; su peso es de 7 bytes
int num[7]; su peso es de 14 bytes
float num[7]; su peso es de 28 bytes
double num[7]; su peso es de 56 bytes
Un arreglo, que fuera de nombre A y variara desde 0 hasta N su índice, es decir:
A[0], A[1], A[2] . . . A[N]
podríamos representarlo como el arreglo A[K];
A es la variable, o el nombre del arreglo, mientras que K es el índice (la k-ésima posición
del arreglo). 0 es el límite inferior (LI) y N es el límite superior (LS). La longitud del
arreglo está dado por la fórmula:
0 1 2 3 4 5 6
num
194
Longitud = LS – LI + 1
Tomemos el arreglo declarado como
int num[7];
Que descompuesto en sus elementos, sería:
num[0], un[1], num[2], num[3], num[4], num[5], num[6]
E identifiquemos sus partes.
A es el nombre num
K es el índice o tamaño 7
LI es el límite inferior 0 (en Lenguaje C siempre será cero)
LS es el límite superior 6
Longitud LS – LI + 1 = 6 – 0 + 1 = 7
El diagrama de flujo siguiente, muestra la forma en que se procesa un arreglo lineal (LA),
por medio de un ciclo “for”.
195
Fig. 3.13. Diagrama de flujo del procesamiento a un arreglo lineal.
El ciclo for por medio del cual se procesa un arreglo, inicia cuando se inicializa la variable
de control K, que se iguala al límite inferior (LI) que ya se dijo, será siempre cero en un
arreglo en C. Luego se supervisa si se cumple la condición de que K sea menor o igual que
el límite superior, y al comprobarse que lo es, se realiza un proceso que está simbolizado
solamente por la caja encerrado a LA[K], es decir, se procesa el arreglo lineal (LA) en la k-
ésima posición (en este caso, la posición cero). Después se hace el incremento de la
variable de control, y se regresa a evaluar hasta que cesa la condición por medio de la cual
puede continuar el ciclo.
196
Veamos un ejemplo que venga a ilustrar la manera en que se procesa un arreglo lineal.
Ejemplo.
#include "stdio.h" #include "conio.h" main(){ int i; int x[8] = {0,0,0,0,0,0,0,0}; /*arreglo de enteros inicializado*/ char car[6]; /*arreglo de caracteres*/ float num[5]; /*arreglo de numeros de punto flotante*/ char pausa; /*llena el arreglo de enteros*/ for (i=0;i<8;i++){ printf("\nLeer el entero de la posicion %d: ", i); scanf("%d", &x[i]); } /*muestra el contenido del arreglo de enteros*/ for (i=0;i<8;i++) printf("la posicion %d contiene: %d \n",i,x[i]); /*llena el arreglo flotante*/ float suma=0; for (i=0;i<5;i++){ printf("\nLeer el valor punto flotante de la posicion %d: ",i); scanf("%f", &num[i]); printf("\n\n\t Calculando suma ...\n"); suma=suma+num[i]; } /*muestra el contenido del arreglo de numeros de punto flotante*/ for(i=0;i<5;i++) printf("La posicion %d contiene: %f \n",i,num[i]); printf("\n La suma es: %f", suma); /*llenado del arreglo de caracteres*/ for (i=0;i<5;i++){ printf("\nproporciona un caracter"); car[i]=getch(); } /*muestra el contenido del arreglo de caracteres*/ for(i=0;i<5;i++) printf("\nLa posicion %d contiene: %c ",i,car[i]); pausa=getch(); }
197
Tomemos la primera parte, donde dice:
/*llena el arreglo de enteros*/
for (i=0;i<8;i++){
printf("\nLeer el entero de la posicion %d: ", i);
scanf("%d", &x[i]);
}
Podría ser en un diagrama de flujo:
i=0
i<8
i++
No
Si
Lee el entero x[i]
for(i=0;i<8;i++){
printf("\nLeer el entero de la posicion %d: ", i); scanf("%d", &x[i]);}
Fig. 3.14. Diagrama de flujo para resolver la lectura del arreglo x[i].
Lo mismo ocurre para la siguiente parte de código, donde imprime el contenido de cada
elemento del arreglo:
198
/*muestra el contenido del arreglo de enteros*/
for (i=0;i<8;i++)
printf("la posicion %d contiene: %d \n",i,x[i]);
Podría ser el diagrama de flujo:
i=0
i<8
i++
No
Si
for(i=0;i<8;i++)printf("la posicion %d contiene: %d \n",i,x[i]);}Imprime
posición i y contenido de
x[i]
Fig. 3.15. Diagrama de flujo para resolver la escritura del arreglo x[i].
Cuando corremos el ejemplo anterior, obtendremos como resultado lo siguiente:
199
Fig. 3.16. Resultado del programa después de ejecutarse.
Realicemos otro ejemplo para ver la manera que se resuelve el siguiente problema.
Ejemplo.
200
Dado un arreglo de ocho posiciones, capturar sus partes, mostrarlo, luego ir haciendo la
suma de sus extremos, es decir el elemento cero con el 7, el 1 con el 6, el 2 con el 5, y el 3
con el 4 y finalmente, mostrar el total de las sumas de los pares.
Ejemplo.
#include "stdio.h" #include "conio.h" main(){ int x[8]={0,0,0,0,0,0,0,0},i, j, tot, sub; char pausa; /*se declara e inicializa a cero el arreglo, y se declaran las variables de control i y j, asi como las variables enteras total (tot) y subtotal (sub)*/ for(i=0;i<8;i++){ /*en este ciclo for, se captura todo el arreglo lineal*/ printf("Escribe el elemento x[%d]: ",i); scanf("%d",&x[i]); } printf("\nEste es el vector que acabas de llenar \n\n"); /*la siguiente es una representación gráfica de un vector lineal, con sus valores*/ printf("|%d|%d|%d|%d|%d|%d|%d|%d|\n\n",x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7]); pausa=getch(); i=0; j=7; tot=0; sub=0; for(i=0;i<4;i++){ /*mediante este ciclo for, se hará la suma de los extremos y el resultado lo vamos sumando en la variable tot*/ printf("x[%d]: %d + x[%d]:%d = %d \n",i,x[i],j,x[j],sub=x[i]+x[j]); tot=tot+sub; j--; pausa=getch(); } printf("\nEl total de la suma de los pares es: %d",tot); pausa=getch(); return 0; }
201
Cuando corremos el presente programa, dándole las cantidades indicadas, obtendremos el
siguiente resultado:
Fig. 3.17. Resultado después de ejecutar el programa de la suma
de los extremos de un arreglo lineal de ocho posiciones.
Si se realizara este mismo programa en LINUX, obtendríamos el resultado siguiente:
Fig. 3.18. Resultado después de ejecutar el programa de la suma
de los extremos de un arreglo lineal de ocho posiciones en LINUX.
202
Actividades de aprendizaje
Después de ver este tema, es necesario que se refuerce la integración de los conocimientos
del estudiante, y es sumamente importante que se haga mediante las siguientes actividades.
1.- Elabora un mapa conceptual donde definas los siguientes conceptos: arreglo
unidimensional, ordenado, finito y homogéneo. Además incluye cual es la sintaxis para
declararlo.
2.- ¿Cómo se calcula el peso en bytes de un arreglo?
3.- ¿Cuál será el peso en bytes de un arreglo de 30 elementos de tipo: carácter, entero,
punto flotante y doble?
4.- ¿Cómo se calcula la longitud de un arreglo?
5.- ¿Cuál será la longitud de los siguientes arreglos? Aplica la fórmula para resolver.
int num[35];
float otro[100];
6.- En el arreglo siguiente, identifica las partes: float numeros[234];
nombre:
203
índice:
LI:
LS:
Longitud:
7.- ¿Qué ciclo se usa para procesar un arreglo lineal? Explica por qué.
204
Resumen
Con el propósito de que quede bien claro lo que se ha presentado en este tema, se te
presenta este resumen en un mapa conceptual.
En este tema, ya se ve la manera en que son definidos y tratados los arreglos
unidimensionales, pasando por conocer sus características y realizar el cálculo de su peso y
longitud, hasta realizar los recorridos –en lectura y escritura- de un arreglo unidimensional.
Arreglo Unidimensional A[K]A[0],A[1],A[2],…,A[N]
ordenado finito homogéneo
Peso (bytes)
peso=(sizeof)tipo*tamaño
Limites:LI=0, LS=NIndice: KNombre: ALongitud
longitud=LS-LI+1
es eses
tienetienetiene tiene tiene
Se calcula Se calcula
205
El uso más común de un arreglo unidimensional, es como una cadena de caracteres. Una
cadena, es un arreglo de caracteres de cualquier longitud, pero que siempre termina con un
carácter ‘\0’ (NULL). Por esta razón, deben declararse los arreglos de un carácter más de
los necesarios. O sea, para una cadena de 8 letras, declararemos un arreglo de 9. Si lo
definimos en función de su forma externa, una cadena de caracteres, sería una serie de uno
o más caracteres, limitados por comillas. Cada carácter ocupa un byte en memoria.
El número de caracteres pertenecientes a una cadena, se llama longitud. Una cadena sin
caracteres, toma el nombre de “cadena nula” o “cadena vacía”.
Las funciones de cadenas más comunes, pertenecientes al archivo de cabecera “string.h” y
que son las que vamos a ver, son las siguientes:
• función strcpy( )
Su sintaxis, es:
La función strcpy( ) copia la cadena apuntada por s2 en la cadena apuntada por s1.
strcpy(s1,s2);
3.3.- Las cadenas y sus funciones
206
• función strcat( )
Su sintaxis, es:
La función strcat( ) concatena (une) la cadena apuntada por s2 en la cadena apuntada por
s1. Devuelve s1.
• función strlen( )
Su sintaxis, es:
La función strlen( ) devuelve la longitud de la cadena s1.
• función strcmp( )
Su sintaxis, es:
La función strcmp( ) compara la cadena apuntada por s1 con la cadena apuntada por s2.
Devuelve cero si las dos cadenas son iguales; mayor que cero si la cadena s1 es mayor y
menor que cero si la cadena apuntada por s1 es menor.
strcat(s1,s2);
strlen(s1);
strcmp(s1,s2);
207
Veamos un ejemplo que venga a ilustrar las operaciones que se realizan con las cadenas.
#include "stdio.h" #include "conio.h" #include "string.h" main(){ char pausa; char cad1[80], cad2[80]; printf("Vamos a hacer una muestra de operaciones entre cadenas\n"); printf("Escribe la primer cadena: \n"); gets(cad1); printf("Escribe la segunda cadena: \n"); gets(cad2); printf("Las longitudes de las cadenas son: \nPara la primera, %d caracteres, y la segunda, %d caracteres.\n\n", strlen(cad1), strlen(cad2)); switch(strcmp(cad1,cad2)){ case 0: printf("Las cadenas son iguales\n\n"); break; case -1: printf("La primer cadena es mayor\n\n"); break; case 1: printf("La primer cadena es menor\n\n"); } printf("Las cadenas unidas con la funcion strcat() dan: \n%s y mide %d\n\n", strcat(cad1,cad2), (strlen(cad1)+strlen(cad2))); strcpy(cad1,cad2); printf("La copia de la cadena 2 en la 1 da como resultado: %s", cad1); pausa=getch(); }
208
Cuando corremos el programa, da como resultado:
Fig. 3.19. Resultado de la ejecución del programa de operaciones
con cadenas.
209
Actividades de aprendizaje
Se te presentan las siguientes actividades con el propósito de que reafirmes tus
conocimientos respecto a las cadenas de caracteres y las operaciones que se hacen entre
ellas. Contesta lo que has aprendido a este respecto, conforme tus propias palabras, y
realiza tu propia explicación, después compárala con la de tus compañeros y discute,
después de reflexionar, para llegar a una conclusión razonable.
1.- ¿Cuál es la característica común a todas las cadenas de caracteres?
2.- ¿Cuánto pesa (en bytes) una cadena de 256 caracteres de longitud?
3.- ¿Para qué sirven las funciones strcpy(), strcat(), strlen() y strcmp()y cuál es su sintaxis
correcta?
210
Resumen
Con el propósito de que se te facilite la comprensión de los temas aquí tratados, así como la
apropiación de los conocimientos que sobre las cadenas de caracteres y sus operaciones se
te han presentado, se te presenta este resumen en forma de mapa conceptual.
En el presente tema, se ven las cadenas como un caso especial de los arreglos
unidimensionales, y las funciones que pueden realizar operaciones con las mismas, viendo
también las características que distinguen a las cadenas de caracteres de otras formas.
cadenas
Arreglo unidimensional Funciones Características
strcpy()strcat()strlen()strcmp()
Siempre termina con un ‘\0’Cada carácter ocupa un byteEl no. De carateres es su longitud
esusa tiene
211
Un arreglo bidimensional, tabla o matriz, es un arreglo unidimensional de arreglos
unidimensionales. Este es el primero de los arreglos multidimensionales, y el más sencillo.
Se declaran usando la sintaxis siguiente:
Su peso en bytes a ocupar en la memoria la da la siguiente formula:
Por ejemplo, si tenemos un arreglo declarado así:
int numeros[8][10];
Obtendremos su peso aplicando la fórmula:
peso = 8 * 10 * 2 = 160 bytes.
El acceso a un arreglo bidimensional, se da mediante dos ciclos “for”. Por ejemplo, para
llenar de forma aleatoria una tabla con números entre 0 y 10, y posteriormente imprimirse
en orden, podrá hacerse así:
Ejemplo:
tipo identificador[tamaño dimension 2][tamaño dimension 1]
peso = dimensión2 * dimensión1 * sizeof(tipo)
3.4.- Arreglos bidimensionales
212
Sabemos que “stdio.h” estará presente para usar el “printf” y que “conio.h” lo usamos para
el “getch()”. Sin embargo, vemos otras dos librerías: “stdlib.h” lo usamos para la función
“random(n)” que genera un número aleatorio entre 0 y n; la otra es “time.h” que contiene
“randomize()” que genera la semilla aleatoria. El resultado debe ser así:
Fig. 3.20. Resultado después de ejecutar el programa
que muestra un arreglo bidimensional
#include "stdio.h" #include "conio.h" #include "stdlib.h" #include "time.h" main(){ int i,j; char pausa; int arreglo[3][5]; randomize(); for(i=0;i<3;i++) for(j=0;j<5;j++) arreglo[i][j]=random(11); for(i=0;i<3;i++){ for(j=0;j<5;j++){ printf("%4d", arreglo[i][j]); } printf("\n"); } pausa=getch(); return 0; }
213
Actividades de aprendizaje
La intención de presentarte estas actividades, es la de permitirte retomar los conocimientos
adquiridos a lo largo de esta unidad y afirmarlos.
1.- Escribe dos nombres más con los que se puede conocer a un arreglo bidimensional y
represéntalos mediante un esquema o dibujo.
2.- Con qué fórmula se obtiene el peso en bytes que ocupa un arreglo bidimensional?
3.- ¿Qué función usamos para acceder a un arreglo bidimensional?
214
Resumen
La intención de presentarte este resumen en forma de mapa conceptual, dado que se vieron
los arreglos bidimensionales, también llamados tablas o matrices, como arreglos
unidimensionales de arreglos unidimensionales, la forma de declararse, la forma de
calcularse el tamaño que ocupan en memoria (peso) y la forma de acceder a ellos, es
reafirmar estos conceptos y asegurar su apropiación.
Arreglo bidimensionalo matrizo tabla
Arreglo Unidimensional de
arreglos unidimensionales
tipo identificador[dimension2][dimension1]
peso=dimensio2*dimension1*sizeof(tipo)
esSe
declara
Se calcula
2 ciclos for
Se accede
215
Una cola es un concepto que a diario manejamos: hacemos cola en el supermercado para
pagar en la caja; hacemos cola en el banco, para ser atendidos en caja. Si somos ordenados,
y bajo condiciones normales, veremos que el primero que llegó a la caja, será el primero en
ser atendido por el empleado, el segundo irá enseguida, luego el tercero, y así
consecutivamente.
Una cola es una lista que contiene información y es lineal (esto significa que será un arreglo
unidimensional). La información se guarda en un orden, y en ese mismo orden se saca de
ella. No se puede acceder a los elementos en forma aleatoria, sino siguiendo ese orden.
También se conoce como FIFO (First Input, First Output) Primero que entra, primero que
sale.
Una forma más adecuada de ilustrar este concepto, es mediante un ejemplo. Realicemos un
programa que simule una cola de impresión, la cual mostrará en un principio vacía, es decir
con todos sus elementos equivalentes a cero, así como el dispositivo de impresión, así como
un menú que solicita 1 para agregar a la cola 2 para extraer de la cola y poner a imprimir, y
3 para salir.
Usamos un arreglo lineal para almacenar la cola. La manera en que vamos a acceder a ella
y a obtener su información es lo que la convierte en una cola.
3.5.- Pilas y Colas
216
#include "stdio.h" #include "conio.h" #include "stdlib.h" #include "dos.h" int desplegar(); int c[10]={0,0,0,0,0,0,0,0,0,0}; int aux=0; main(){ char pausa; int pos=0; int opc,i; randomize(); do{ clrscr(); desplegar(); printf("\n\n"); printf("1.- Introducir tarea \n"); printf("2.- Imprimir tarea \n"); printf("3.- Salir \n"); printf ("Elige tu opcion : "); scanf("%d",&opc); switch(opc){ case 1: c[pos]=random(9)+1; desplegar(); pos++; break; case 2: clrscr(); aux=c[0]; for(i=0;i<=8;++i) c[i]=c[i+1]; desplegar(); gotoxy(20,0); printf("Imprimiendo..."); delay(aux*500); pos--; break; case 3: return 0; } }while(opc!=3); return 0; }
217
Debemos notar que se usa “conio.h” para el “clrscr()” y para el “getch()”. Usamos también
“stdlib.h” para el “randomize()”, así como usamos el “dos.h” para el “delay()”.
Obtendremos el resultado siguiente:
Fig. 3.21. Resultado después de ejecutar el programa que simula
una cola.
int desplegar(){ printf(" -------------\n"); printf("--------------------- | |\n"); printf("|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d| | %d |\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9],aux); printf("--------------------- | |\n"); printf(" -------------\n"); printf(" IMPRESOR\n"); return 0; }
218
Cuando se hace una inserción a la cola, se asigna un número entre 1 y 9 al primer elemento
en forma aleatoria. Se usa la función “desplegar()” que lo único que hace, es mostrar el
contenido de la cola. La imagen que obtenemos es la siguiente:
Fig. 3.22. Resultado al insertar trabajos de impresión
a la cola.
Y cuando elegimos 2 para que se envíe a imprimir, luego hacemos un recorrido al arreglo,
haciendo que vaya recorriendo los valores hacia abajo y despliega el contenido. Obtenemos
lo siguiente:
Fig. 3.23. Resultado al mandar a imprimir (sacar de
la cola) un trabajo.
219
Una Pila, podríamos asegurar que es lo opuesto a una cola, porque el método de acceso que
se usa, lleva como nombre LIFO (Last Input First Output) lo que implica que el último que
entra es el primero que sale. Imaginemos una pila de platos que acabamos de lavar. Los
vamos poniendo en orden, el primero que lavamos en la mesa, luego el segundo encima,
luego el tercero y así consecutivamente. Cuando terminamos, si vamos a servir los
alimentos, tenemos que usar primero el último que pusimos, o sea, el que está en la cima de
la pila de platos.
Usaremos otra vez un arreglo lineal para guardar los datos de la pila, y para introducir y
sacar los datos.
Realicemos un ejemplo para ilustrar el concepto de pila.
#include "stdio.h" #include "conio.h" #include "stdlib.h" #include "dos.h" int desplegar(); int c[10]={0,0,0,0,0,0,0,0,0,0}; int aux=0; main(){ char pausa; int pos=0; int opc,i; randomize(); do{ clrscr(); desplegar(); printf("\n\n");
220
printf("1.- Introducir tarea en la pila\n"); printf("2.- Imprimir tarea \n"); printf("3.- Salir \n"); printf ("Elige tu opcion : "); scanf("%d",&opc); switch(opc){ case 1: for(i=9;i>=0;--i) c[i+1]=c[i]; c[pos]=random(9)+1; desplegar(); break; case 2: clrscr(); aux=c[0]; for(i=0;i<=8;++i) c[i]=c[i+1]; desplegar(); gotoxy(20,0); printf("Imprimiendo..."); delay(aux*500); pos--; break; case 3: return 0; } }while(opc!=3); return 0; } int desplegar(){ printf(" -------------\n"); printf("--------------------- | |\n"); printf("|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d| | %d |\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9],aux); printf("--------------------- | |\n"); printf(" -------------\n"); printf(" IMPRESOR\n"); return 0; }
221
Cuando se hace una inserción a la pila, se asigna un número entre 1 y 9 al primer elemento
en forma aleatoria. Se usa la función “desplegar()” que lo único que hace, es mostrar el
contenido de la pila. Cuando se vuelve a insertar un elemento, la pila hace un recorrido
hacia abajo, y permite que se inserte en la posición 0 de nuevo. Obtendremos como
resultado lo siguiente:
Fig. 3.24. Resultado de la ejecución del programa de simulación
de una pila para impresión.
Y después de introducir a la pila varios datos, obtendremos lo siguiente:
Fig. 3.25. Resultado después de introducir datos en la pila
222
Y cuando elegimos 2 para que se envíe a imprimir, luego hacemos un recorrido al arreglo,
haciendo que vaya recorriendo los valores hacia abajo y despliega el contenido. Obtenemos
un resultado como el que sigue:
Fig. 3.26. Resultado después de mandar a imprimir (sacar
de la pila) trabajos
223
Actividades de aprendizaje
El propósito de estas actividades, es el de permitirte retomar los conceptos que acabas de
aprender en el transcurso de esta unidad, y evaluar si es que has adquirido estos
conocimientos en forma firme y adecuada.
1.- Escribe tres ejemplos de colas que tú conozcas.
2.- Representa mediante un esquema o un dibujo, qué es el concepto de FIFO.
3.- ¿Una cola es un arreglo lineal?
4.- Ahora escribe tres ejemplos de pilas que conozcas.
5.- Representa con un dibujo o con un esquema, qué es el concepto de LIFO.
224
Resumen
El propósito de este resumen, presentado en forma de un mapa conceptual, es afirmar tus
conocimientos, ya que se vieron dos tipos de estructuras de datos: colas y pilas. Se vieron
los métodos de acceso que se usan, FIFO para las colas LIFO para las pilas. Se muestra,
mediante un ejemplo, la manera en que se debe acceder a una pila y a una cola, la manera
de introducir elementos y la manera en que se extraen y cómo se hace un recorrido de
elementos.
Estructuras de datos
Colas Pilas
Tiene información linealUsa el método FIFO
Tiene información linealUsa el método LIFO
225
Tanto los métodos de ordenación como los de búsqueda forman parte muy importante de un
lenguaje de programación, pues permiten la manipulación de los datos, como en base de
datos, compiladores, etc. Para realizar una búsqueda de manera exitosa y expedita, es
necesario que los datos estén ordenados, así que un método es consecuencia del otro.
Podríamos decir que la ordenación es la manera de disponer la información en un orden
creciente o decreciente, donde el primer elemento es menor o igual al segundo; el segundo
es menor o igual al tercero, y así consecutivamente.
Podemos encontrar tres formas diferentes de ordenación de arreglos:
• Por cambio.
• Por selección.
• Por inserción.
De estas tres formas, se desprenden varios algoritmos, como el método de la burbuja
(también llamado n-cuadrado), ordenación por selección, ordenación por inserción,
ordenación shell y ordenación rápida (quicksort).
3.6.- Algoritmos de ordenación y búsqueda
226
En cuanto a la búsqueda, la podríamos definir como la comparación de un patrón dado con
los elementos del arreglo ordenado. Existen también varios algoritmos de búsqueda, como
el método de búsqueda secuencial y búsqueda binaria.
En este tema, se verán solamente el método de ordenación de la burbuja y el método de
búsqueda llamado binario.
Este algoritmo usa la ordenación por cambio, se basa en la comparación repetida de
elementos adyacentes y en caso necesario, el intercambio entre los dos elementos en
cuestión, sólo en caso de que el primero sea mayor que el segundo.
Para ilustrar la manera en que trabaja el método, veamos un ejemplo corriendo sobre el
libro, no en la computadora. Supongamos un examen-concurso con 100 preguntas, de las
cuales, los participantes obtienen la siguiente puntuación= {32, 51, 27, 85, 66, 23, 13, 57}.
Deseamos hacer una lista ordenada de resultados y publicarla, con el auxilio de la
computadora. Se comparan por pares todos los elementos, en forma ordenada y se colocan
en el orden deseado; se va a acomodar el elemento N, por lo tanto serán N-1 pasadas.
Ejemplo, primera pasada…
32 51 27 85 66 23 13 57 #compara 32 con 51, los deja igual
32 27 51 85 66 23 13 57 #compara 51 con 27, los intercambia
3.6.1.- Método de la burbuja
227
32 27 51 85 66 23 13 57 #compara 51 con 85, los deja igual
32 27 51 66 85 23 13 57 #compara 85 con 66, los intercambia
32 27 51 66 23 85 13 57 #compara 85 con 23, los intercambia
32 27 51 66 23 13 85 57 #compara 85 con 13, los intercambia
32 27 51 66 23 13 57 85 #compara 85 con 57, los intercambia
Después de esta primera pasada, queda el mayor (85) a la derecha del arreglo y ya no se
compara en la segunda pasada.
Segunda pasada…
27 32 51 66 23 13 57 85 #compara 32 con 27, los intercambia
27 32 51 66 23 13 57 85 #compara 32 con 51, los deja igual
27 32 51 66 23 13 57 85 #compara 51 con 66, los deja igual
27 32 51 23 66 13 57 85 #compara 66 con 23, los intercambia
27 32 51 23 13 66 57 85 #compara 66 con 13, los intercambia
27 32 51 23 13 57 66 85 #compara 66 con 57, los intercambia
Después de esta segunda pasada, quedan los dos mayores (66, 85) a la derecha del arreglo y
éstos ya no se comparan en la tercera pasada.
Tercera pasada…
27 32 51 23 13 57 66 85 #compara 27 con 32, los deja igual
27 32 51 23 13 57 66 85 #compara 32 con 51, los deja igual
27 32 23 51 13 57 66 85 #compara 51 con 23, los intercambia
27 32 23 13 51 57 66 85 #compara 51 con 13, los intercambia
228
27 32 23 13 51 57 66 85 #compara 51 con 57, los deja igual
Después de esta tercera pasada, quedan los tres mayores (57, 66, 85) a la derecha del
arreglo y éstos ya no se comparan en la cuarta pasada.
Cuarta pasada…
27 32 23 13 51 57 66 85 #compara 27 con 32, los deja igual
27 23 32 13 51 57 66 85 #compara 32 con 23, los intercambia
27 23 13 32 51 57 66 85 #compara 32 con 13, los intercambia
27 23 13 32 51 57 66 85 #compara 32 con 51, los deja igual
Después de esta cuarta pasada, quedan los cinco mayores (51, 57, 66, 85) a la derecha del
arreglo y éstos ya no se comparan en la quinta pasada.
Quinta pasada..
23 27 13 32 51 57 66 85 #compara 27 con 23, los intercambia
23 13 27 32 51 57 66 85 #compara 27 con 13, los intercambia
23 13 27 32 51 57 66 85 #compara 27 con 32, los deja igual
Después de esta quinta pasada, quedan los seis mayores (32, 51, 57, 66, 85) a la derecha del
arreglo y éstos ya no se comparan en la sexta pasada.
Sexta pasada
13 23 27 32 51 57 66 85 #compara 23 con 13, los intercambia
13 23 27 32 51 57 66 85 #compara 23 con 27, los deja igual
229
Después de esta sexta pasada, quedan los seis mayores (27, 32, 51, 57, 66, 85) a la derecha
del arreglo y éstos ya no se comparan en la séptima pasada.
Séptima pasada
13 23 27 32 51 57 66 85 #compara 13 con 23, los deja igual
Después de esta séptima pasada, y al quedar los siete mayores (23, 27, 32, 51 57, 66, 85) a
la derecha del arreglo, el mismo está completamente ordenado.
Arreglo ordenado.
13 23 27 32 51 57 66 85
Para ilustrar este ejercicio, hagamos un programa que realice exactamente lo que acabamos
de explicar:
#include "stdio.h" #include "conio.h" main(){ int i, j, b, aux; char pausa; int n[8]={32,51,27,85,66,23,13,57}; clrscr(); printf("Arreglo original desordenado...\n"); for(i=0;i<8;i++) printf("%4d",n[i]); printf("\n"); getch(); for(i=0;i<7;i++) { clrscr(); printf("Pasada No. %d \n", i+1); for(j=0;j<8-i-1;j++){ if(n[j]>n[j+1]){ aux=n[j]; n[j]=n[j+1]; n[j+1]=aux; }
230
El resultado que obtendremos al ejecutarlo será el siguiente:
Fig. 3.27. Ejecución del programa. Arreglo original.
Y después, pasada por pasada:
Fig. 3.28. Resultado después de la primera pasada.
printf("\n"); for(b=0;b<8;b++) printf("%4d ",n[b]); printf("\n"); } getch(); } clrscr(); printf("El vector ordenado quedo asi: \n"); for(i=0;i<8;i++) printf("%4d",n[i]); printf("\n\n"); pausa=getch(); return 0; }
231
Fig. 3.29. Resultado después de la segunda pasada.
Fig. 3.30. Resultado después de la tercera pasada.
Fig. 3.31. Resultado después de la cuarta pasada.
Fig. 3.32. Resultado después de la quinta pasada.
232
Fig. 3.33. Resultado después de la sexta pasada.
Fig. 3.34. Resultado después de la séptima pasada.
Fig. 3.35. Resultado final: vector ordenado
Estando los datos ordenados, puede usarse un método de búsqueda que se llama “método
binario”. El método es muy sencillo de explicar.
Primero, establece que inicio es el límite inferior del arreglo, final es el límite superior del
arreglo, divide el arreglo en dos partes y al elemento central le llama mitad, es decir:
(principio+final)/2.
Luego, consulta si el número que se busca es igual, mayor o menor que el número mitad.
3.6.2.- Búsqueda binaria
233
• Si es igual, es el resultado esperado.
• Si es mayor, trabajará con la mitad superior del arreglo, lo que implica que hará que
principio tome como nuevo valor “mitad+1”.
• Si es menor, con la mitad inferior, lo que implica que hará que final tome como
nuevo valor “mitad-1”.
Luego, con la mitad que eligió, vuelve a cortarla a la mitad y entonces revisa si el número
mitad es mayor, menor o igual al buscado, y así consecutivamente.
Ilustremos lo anterior corriendo un ejemplo en el libro, para observar la manera como
funciona.
Supongamos un arreglo de 13 elementos, denominado “datos”, cuyo contenido es el
siguiente: {11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99}.
Para buscar el elemento “40”
0 1 2 3 4 5 6 7 8 9 10 11 12
1.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Se establece inicio=0, final=12, mitad=(inicio+final)/2= (0+12)/2=12/2=6 datos[mitad]=55
2.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Como 40<55, final=mitad-1=5, inicio=0, mitad=(0+5)/2=2, datos[mitad]=30
234
3.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Como 40>30, inicio=mitad+1=3, final=5, mitad=(3+5)/2=4, datos[mitad]=40
4.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Como 40=40, se encontró el elemento, en el lugar=5=mitad
Ahora para buscar 85…
0 1 2 3 4 5 6 7 8 9 10 11 12
1.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Se establece inicio=0, final=12, mitad=(inicio+final)/2= (0+12)/2=12/2=6 datos[mitad]=55
2.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Como 85>55, inicio=mitad+1=7, final=12, mitad=(7+12)/2=9, datos[mitad]=77
3.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Como 85>77, inicio=mitad+1=10, final=12, mitad=(10+12)/2=11
4.- 11, 22, 30, 33, 40, 44, 55, 60, 66, 77, 80, 88, 99
Como 85<77, inicio=10, final=mitad-1=10 por lo tanto inicio=final, signo de no
encontrado.
Para ilustrar el ejemplo que acabamos de ver, realicemos un programa que haga
exactamente lo mismo:
235
El resultado que obtendremos al ejecutarlo será el siguiente:
#include "stdio.h" #include "conio.h" main(){ int i, inicio, final, mitad, elemento; int datos[13]={11,22,30,33,40,44,55,60,66,77,80,88,99}; clrscr(); printf("Arreglo ordenado:\n"); for(i=0;i<13;i++) printf("%4d", datos[i]); printf("\n\n"); printf("Numero a buscar: "); scanf("%d", &elemento); inicio=0; final=12; while(inicio!=final&&datos[mitad]!=elemento){ mitad=(inicio+final)/2; if(elemento<datos[mitad]) final=mitad-1; else if(elemento>datos[mitad]) inicio=mitad+1; else printf("Elemento No. %d encontrado : %d \n", mitad, datos[mitad]); if(inicio==final) printf("Elemento no encontrado!\n"); } getch(); }
236
Fig. 3.36. Resultado después de ejecutar el programa con un
número válido, el cual encuentra
Fig. 3.37. Resultado después de ejecutar el programa con un
número no existente, y que no encuentra
237
Actividades de aprendizaje
La intención de promover estas actividades es que se retomen los conocimientos aprendidos
en esta unidad, y se reafirmen, asegurándose de que se ha apropiado el conocimiento,
mediante los ejercicios que se plantean.
1.- Define que es ordenación.
2.- Define qué es búsqueda binaria.
3.- ¿Cuántas y cuáles formas de ordenación existen?
4.- Explica de manera clara y sencilla, la manera en que opera el algoritmo de la ordenación
de burbuja.
5.- Ordena de manera manual el arreglo lineal {15, 8, 65, 9, 17, 26, 33, 1}
6.- Explica de modo sencillo y claro, el algoritmo para la búsqueda binaria.
7.- Haz un ejercicio de búsqueda binaria con el arreglo ordenado {1, 7, 9, 16, 21, 22, 38,
40} tanto para un número existente como para uno no existente.
238
Resumen
En este tema, se tocaron los conceptos tanto de ordenación como de búsqueda. En cuanto a
la ordenación por burbuja, que es la que se vio, se observaron sus características y la
manera como opera.
En lo que respecta a la búsqueda binaria, se estudiaron las características y operación de su
algoritmo.
Ordenación Y
Búsqueda
Ordenación por burbuja
Busca si es igual, menor o mayor que el elemento medio
Si es menor, hace final=mitad-1 Si es igual, encontrado Si es mayor, hace
inicio=mitad+1
Búsqueda binaria
Es por CambioCompara elementos
adyacentes. Si el primero es mayor, los intercambia
características funciona
< >=
239
Recapitulación Unidad 3
Se te invita a repasar esta recapitulación, donde se presentan los elementos más
significativos de esta unidad, con el propósito de que seas capaz de realizar un análisis y
síntesis de los aspectos más relevantes que se han visto.
Declaración e inicialización de arreglos
Encontramos dos clases diferentes de estructuras de datos: lineales (arreglos, listas
enlazadas, pilas y colas) o no lineales (árboles y grafos). En una estructura lineal, pueden
realizarse las operaciones de recorrido, búsqueda, inserción, borrado, ordenación y mezcla.
Pueden también clasificarse como estáticas (arreglos, estructuras, archivos, cadenas de
caracteres) y dinámicas (pila, cola, lista enlazada, árbol o grafo).
Por arreglo conocemos a un conjunto de variables del mismo tipo, compartiendo el mismo
nombre, y que tiene elementos que se diferencian entre sí por un índice. u declaración es:
Tipo_de_datos es cualquier tipo de datos conocido en C, con excepción de void.
Identificador: es un nombre único para este arreglo. No_de_elementos: será el tamaño del
arreglo. Puedes declarar un arreglo en forma global o local. Si lo declaras en forma global,
tipo_de_datos identificador[no_de_elementos];
240
todos sus elementos tendrán el valor de cero. Si lo declaras en forma local, puedes
inicializarlo. Aunque pudiera ser inicializado de manera parcial.
Si se tratara de un arreglo bidimensional, entonces se declaran como sigue:
tipo: es el tipo de datos que es aceptado por Lenguaje C, con excepción de void.
Identificador: es el nombre único que servirá para identificar los elementos del arreglo
bidimensional. Indice1: en la representación de filas-columnas, indica las filas. Indice2:
indica las columnas de la tabla.
Uso de arreglos unidimensionales.
Un arreglo unidimensional es un conjunto ordenado y finito de elementos del mismo tipo y
se declara de la manera siguiente:
El peso en bytes del arreglo, se obtiene con la fórmula:
Un arreglo, denominado A y que varía desde 0 hasta N : A[0], A[1], A[2] . . . A[N] puede
representarse como: A[K]. A es su nombre o identificador, K es el índice, = es el Límite
Inferior (LI) y N es el L´mite Superior (LS). Su Longitud = LS – LI + 1
tipo identificador[indice1][indice2];
tipo identificador[tamaño];
Peso = sizeof(tipo)*tamaño
241
Un arreglo lineal (LA) se procesa mediante un ciclo “for”, inicializando prmero la variable
de control K=LI, la condición de terminación será K<=LS, si lo es, procesa LA[K] y luego
se incrementa K++
Las cadenas y sus funciones
Una cadena es un arreglo de caracteres, de cualquier longitud, pero cuyo último elemento
es el carácter nulo ‘\0’, razón de lo cual, deben declararse siempre de un carácter más de los
necesarios. El número de sus caracteres, es su longitud en bytes. Las funciones más
comunes, son las siguientes:
función strcpy( ) que copia la cadena apuntada por s2 en la cadena apuntada por s1 y cuya
sintaxis, es:
función strcat( ) que concatena la cadena apuntada por s2 en la cadena apuntada por s1 y
además devuelve s1, y cuya sintaxis, es:
función strlen( ) que devuelve la longitud de la cadena s1 y cuya sintaxis, es:
strcpy(s1,s2);
strcat(s1,s2);
strlen(s1);
242
función strcmp( ) que compara la cadena apuntada por s1 con la cadena apuntada por s2;
devuelve un cero si las dos cadenas son iguales; positivo si la cadena s1 es mayor y
negativo si la cadena s1 es menor, y su sintaxis, es:
Arreglos bidimensionales
También se le conoce como tabla o matriz, y es un arreglo unidimensional de arreglos
unidimensionales siendo el más sencillo de los arreglos multidimensionales, la sintaxis es la
siguiente:
y su peso en bytes:
Colas y Pilas
Una cola es algo muy conocido por nosotros, como cuando hacemos fila en algún lugar
donde vamos a obtener algún bien o servicio. En el caso de la programación, es un vector
que contiene información guardada con un orden, y obtenida en ese mismo orden. Su
método de acceso se llama “primera entrada, primera salida”
strcmp(s1,s2);
tipo identificador[tamaño dimension 2][tamaño dimension 1]
peso = dimensión2 * dimensión1 * sizeof(tipo)
243
Una pila, es diferente porque el “primero que entra, último que sale”, como tiene su nombre
el método de acceso, y simula una pila de objetos. En programación, es un vector que
contiene información guardada en un orden, y obtenida en orden inverso.
Algoritmos de ordenación y búsqueda
En un lenguaje de programación, se lleva a cabo acciones muy importantes con los
algoritmos de ordenación (disposición de la información en orden creciente o decreciente,
ya sea por algoritmos de cambio, selección o inserción) y de búsqueda (comparación de un
patrón con los elementos del arreglo ya ordenado).
Método de la burbuja
Es un método por cambio, que compara dos elementos adyacentes, y si el primero es
mayor, los intercambia, de lo contrario, los deja en ese orden. Así va haciendo pasada tras
pasada, que el elemento mayor vaya hasta la parte “superior” del arreglo, como si duera una
burbuja.
Búsqueda binaria
Ya ordenados los datos, puede buscarse un patrón, realizando lo siguiente: se define como
inicio al índice del primer elemento, como final al índice del último, y como mitad al índice
del medio (inicio+final)/2, y se compara el patrón con el contenido del medio. Si es igual,
244
ha sido una búsqueda exitosa, si mitad es mayor, final=mitad-1; si mitad es menor, inicio es
mitad+1. Luego vuelve a hacer la comparación con la siguiente mitad, y así
consecutivamente hasta hallarlo o tener la condición de no encontrado.
245
Prácticas.
PRÁCTICA 1.- HACER UN PROGRAMA QUE CAPTURE DIEZ CANTIDADES, Y
LOCALICE EL MAYOR, ASÍ COMO LA DIFERENCIA DE CADA UNO DE ELLOS
CON EL MAYOR.
INTRODUCCION.
Para hacer este programa, debemos primero capturar las diez cantidades. Antes que nada,
capturamos una cantidad de referencia, y le damos ese valor la calidad del “mayor”. Cada
que vayamos haciendo la captura de una cantidad, recorriendo el arreglo lineal para leer las
cantidades, comparamos la cantidad que se va capturando, y si es mayor que el “mayor”,
entonces, esa cantidad pasa a ser “mayor”. Ahora escribe cuál es el número mayor.
Posteriormente escribimos, mediante un recorrido de escritura, cuál es la diferencia entre el
mayor y los demás.
MATERIAL.
Hojas blancas para hacer el diagrama de flujo.
Computadora para capturar, compilar y ejecutar el programa.
246
PROCEDIMIENTO.
Primero, realizamos el diagrama de flujo de los datos.
Inicio
Fin
Teclee la cantidad 1:
Leer numeros[0]
mayor=numeros[0]
i=1
i<=10
i++
Teclee la cantidad i
Leer numeros[i]
numeros[i] > mayor ?
mayor=numeros[i]
Si
No
El numero mayor es: mayor
Las diferencias son:
Si
No
i=0
i<=10
Imprime diferencia
i++
247
Enseguida, traducimos el diagrama a código en Lenguaje C.
OBSERVACIONES.
Al escribir el código del programa, usamos la librería “stdio.h” porque vamos a usar las
funciones printf y scanf. Se declaran las variables i (de control para los ciclos) y mayor que
contendrá la cantidad mayor. Se declara también el arreglo lineal numeros[ ].
RESULTADOS.
248
PRÁCTICA 2.- HACER UN PROGRAMA QUE CAPTURE LAS EDADES DE DIEZ DE
TUS COMPAÑEROS Y OBTENGA EL PROMEDIO.
INTRODUCCION.
Para resolver el programa, primero debemos capturar las edades, e ir sumando cada
cantidad capturada a la variable “suma”, que nos permitirá al término, calcular el promedio.
Aquí se presenta un problema al intentar mostrar el promedio (que es un número con punto
flotante), y estamos haciendo la captura de números enteros. Para solucionarlo, debemos
recurrir a la figura del “molde” que se vio en la Primera Unidad, y que sirve para forzar la
salida en un tipo de datos diferente.
MATERIAL.
Hojas blancas para hacer el diagrama de flujo.
Computadora para capturar, compilar y ejecutar el programa.
PROCEDIMIENTO.
Primero, realizaremos el diagrama de flujo.
249
Inicio
i=0
1<=10
i++
Fin
Teclee la edad de compañero
i+1
Lee edades[i]
suma=suma+edades[i]
Imprime promedio
Si
No
250
Ahora procederemos a capturar el código fuente:
OBSERVACIONES.
Lo primero a observar aquí, es la forma en que se declara la variable “suma”, y al mismo
tiempo se inicializa a cero. Se realiza el ciclo de captura, y se va incrementando la variable
“suma” con el contenido de cada uno de los elementos del arreglo lineal “edades[ ]”. Al
final, se despliega el promedio con un “%6.2f” que significa que va a ser un número de
punto flotante, y para que tenga lugar esto, debemos aplicar un “(float)” que es el molde,
antes de hacer la división de suma/10. Ahora el resultado será dado en forma de número de
punto flotante.
252
Actividades de confirmación de conocimientos
Si te esfuerzas para resolver los siguientes problemas, y además capturas, compilas y
ejecutas los programas que se proponen, vas a reafirmar lo que adquiriste en el transcurso
de este capítulo. Contesta a las respuestas directas de la misma manera, además analiza
cada uno de los problemas planteados y explica brevemente el procedimiento que seguiste
para resolverlo.
1.- Lista las características de un arreglo.
2.- Escribe un ejemplo de cómo se declararía un arreglo de diez variables de punto flotante.
3.- Inicializa el ejemplo anterior de las tres maneras conocidas.
4.- Representa y explica en forma gráfica la manera en que se declararía un arreglo si
quisiéramos representar el gasto de agua de una ciudad en los siete días de la semana,
cuatro semanas al mes, los doce meses del año, durante los últimos cinco años.
5.- Realiza un programa que lea 10 números enteros del teclado, y lo imprima de manera
horizontal del primero al último, y del último al primero. Luego de manera vertical, del
primero al último y del último al primero.
6.- Realizar un programa que pida password para acceder a él. Si a los tres intentos no se da
el password correcto, debe terminar y enviar un mensaje de advertencia. En caso de ser
correcto, permitir entrar, solamente para informar que el password fue el correcto.
253
7.- De las siguientes declaraciones de tablas, ¿cuáles son correctas? (elige dos).
int datos[8][10];
double salario(3,4);
int numeros[5,8];
float sueldo[4][3];
void cuenta[5][7];
8.- ¿Qué forma de programación se usa para acceder a una tabla y cómo lo harías,
suponiendo la siguiente?
23 12 67 54 34
65 21 98 70 45
63 43 28 48 43
10 40 9 33 66
9.- Supongamos que existe una cola, donde va llenándose de la manera en que se indica por
la flecha, es decir, el 22 llegó primero, luego el 54, luego el 3, y así consecutivamente.
Escribe en una línea el orden en que van a salir.
12 32 45 10 3 54 22
254
10.- Supongamos que existe una pila, donde va llenándose de la manera en que se indica
por la flecha, es decir, el 44 llegó primero, luego el 53, luego el 94, y así consecutivamente.
Escribe en una línea el orden en que van a salir.
54 32 90 67 37 94 53 44
11.- Dado el arreglo lineal {7,2,90,12,65,1,43,5}, realiza de manera manual la ordenación
usando el método de la burbuja y mostrando el estatus en cada pasada.
12.- Dado el arreglo anterior ordenado, realizar de manera manual la búsqueda del número
63, y luego el número 43 usando el método de búsqueda binaria.
255
Autoevaluación
1.- Lista las características de un arreglo.
a.- Comparten un nombre.
b.- Cada variable (que se denomina elemento) se diferencia de otra por un índice que sirve
para acceder a su contenido.
c.- Cuando se declara el arreglo, el índice realmente está definiendo el tamaño y la
dimensión del mismo.
d.- Es un número fijo de elementos el que lo compone.
2.- Escribe un ejemplo de cómo se declararía un arreglo de diez variables de punto flotante.
float numeros[10];
3.- Inicializa el ejemplo anterior de las tres maneras conocidas.
a.- La primera, es inicializando el arreglo completo:
float numeros[10]={1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 1.5, 2.8};
b.- La segunda, es inicializando parcialmente el arreglo:
float numeros[10]={1.2, 2.3, 3.4};
256
c.- La tercera, es obviando el tamaño:
float numeros[ ]={1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 1.5, 2.8};
4.- Representa y explica en forma gráfica la manera en que se declararía un arreglo si
quisiéramos representar el gasto de agua de una ciudad en los siete días de la semana,
cuatro semanas al mes, los doce meses del año, durante los últimos cinco años.
float gasto[7][4][12][5];
5.- Realiza un programa que lea 10 números enteros del teclado, y lo imprima de manera
horizontal del primero al último, y del último al primero. Luego de manera vertical, del
primero al último y del último al primero. Respuesta: Este es el código correcto, pero
deberás de realizar el diagrama de flujo que represente la solución, para que realices al
mismo tiempo, un ejercicio de reflexión sobre el método empleado para resolverlo.
/*se declara la cabecera stdio.h para entradas y salidas estándar*/ #include “stdio.h” /*se declara la función principal*/ main(){ /*se declaran las variables i y j enteras*/ int i,j; /*se declara el arreglo entero de diez elementos*/ int arreglo[10]; /*se llena el arreglo*/ for(i=0;i<10;i++){ printf(Escribe el número %d :”,i); scanf(“%d”,&arreglo[i]); } printf(“El arreglo original es el siguiente. \n”); for(i=0;i<10;i++) printf(“%4d”, arreglo[i]);
257
Se declaran i y j como variables enteras que van a servir como contadores. Luego se declara
el arreglo llamado “arreglo” de 10 elementos enteros. Usando un ciclo for() se hace el
llenado manual, es decir, se va pidiendo mediante el comando scanf() caa uno de los
valores que van a llenar los elementos del arreglo entero. la variable arreglo[i] variará
conforme el número de elementos, desde arreglo[0] hasta arreglo[9]. Usando un simple for,
hace la impresión de cada uno de los valores de los elementos en el orden en que fueron
capturados, desde arreglo[0] hasta arreglo[9] incrementando de uno en uno, es lo que
significa for(i=0, i<10; i++). Cuando hace la impresión del arreglo inverso, lo hará desde
arreglo[9] hasta arreglo[0] decrementando de uno en uno, es lo que significa for(i=9; i=0; i-
-). Para poder realizar la escritura de ambos vectores verticales, el primero ascendente y el
segundo descendente, lo mejor es usar doble contador, y hacer un for doble. El ciclo usado
es for(i=0, j=9; i<10&&j>=0;i++, j--), que se va a tomar en forma simultánea, iniciando el
valor de i en 0 y j en 9, terminarán cuando i=9 y j=0 incrementando i de uno en uno
mientras j decrementa de uno en uno.
printf(“\nEl arreglo inverso es el siguiente: \n”); for(i=9;i>=0;i--) printf(“%4d”, arreglo[i]); printf(“\nEl izquierdo, es el arreglo original vertical, el derecho es el inverso\n”); for(i=0,j=9;i<10&&j>=0;i++,j--) printf(“%4d - - - %4d\n”, arreglo[i], arreglo[j]); }
258
6.- Realizar un programa que pida password para acceder a él. Si a los tres intentos no se da
el password correcto, debe terminar y enviar un mensaje de advertencia. En caso de ser
correcto, permitir entrar, solamente para informar que el password fue el correcto.
Respuesta: Este es el código correcto pero debes, a partir de él, elaborar el diagrama de
flujo de la solución para que reflexiones sobre el proceso que se está efectuando.
/*se declaran las dos cabeceras, stdio.h para entradas y salidas estándar y string.h para la función strcmp()*/ #include “stdio.h” #include “string.h” main(){ /*se declara e inicializa la variable pass para dar el password correcto*/ char pass[10]=”1=8MA72vu”; /*se declara contra, que va a recibir el password proporcionado por el usuario*/ char contra[10]; /*se declara la variable ban, como contador de veces otorgado el password*/ int ban; /*se inicializa ban a 1*/ ban=1; /*se hace un ciclo para solicitar tres veces máximo el password*/ do{ /*solicita el password*/ printf(“password: “); scanf(“%s”,contra); /*si coinciden contra y pass, los deja pasar, en otro caso, incrementa ban*/ if(!strcmp(contra,pass)){ printf(“Acceso permitido!!!!\n\n”); return 0; } ban++; /*solo lo hará cuando sean tres o menos intentos*/ }while(ban<=3); /*si excede los tres intentos, manda un mensaje de advertencia y sale*/ printf(“No esta usted autorizado para acceder a este equipo\n”); printf(“Salga inmediatamente de el y retirese. \n\n”); /*regresa código de terminación normal de programa*/ return 0; }
259
Vamos a necesitar realizar la comparación entre el password predeterminado y el que se de
a través del teclado, en razón de lo cual, necesitaremos hacer uso de la orden strcmp() que
pertenece al archivo de cabecera “string.h”, así que debemos declararlo como incluido. Lo
primero, será declarar la cadena de caracteres llamada “pass” que es el password
predeterminado e inicializarlo con el valor que está en el código. Lueo se declara la cadena
de caracteres llamada “contra” que va a recibir el password que proporcione el usuario.
Se declara la variable “ban” que es un entero y usaremos como contador de oportunidades y
se inicializa ban a 1. Entonces se solicita que el usuario entre el password, y se captura
mediante un scanf() en la variable “contra”. Se hace una comparación, si “contra” es igual a
“pass” deja pasar el programa y sólo imprime “Acceso permitido!!!!”. En caso de que no
coincida, incrementa el contador y vuelve a preguntar.
Cuando el contador es mayor de tres, las oportunidades se terminaron, y en ese momento, el
programa sale del ciclo do-while, manda un “warning” o mensaje de advertencia y termina
su ejecución.
7.- De las siguientes, ¿cuáles declaraciones de tablas son correctas? (elige dos).
int datos[8][10];
double salario(3,4);
int numeros[5,8];
float sueldo[4][3];
void cuenta[5][7];
260
8.- ¿qué forma de programación se usa para acceder a una tabla y cómo lo harías,
suponiendo la siguiente?
23 12 67 54 34
65 21 98 70 45
63 43 28 48 43
10 40 9 33 66
Se usan dos ciclos “for” de la siguiente manera, suponiendo que el arreglo llevara el
número de “enteros”:
for(r=0;r<=4;++r)
for(c=0;c<=5;++c)
printf(“%4d \n”, enteros[r][c]);
9.- Supongamos que existe una cola, donde va llenándose de la manera en que se indica por
la flecha, es decir, el 22 llegó primero, luego el 54, luego el 3, y así consecutivamente.
Escribe en una línea el orden en que van a salir.
12 32 45 10 3 54 22
22, 54, 3, 10, 45, 32, 12
261
10.- Supongamos que existe una pila, donde va llenándose de la manera en que se indica
por la flecha, es decir, el 44 llegó primero, luego el 53, luego el 94, y así consecutivamente.
Escribe en una línea el orden en que van a salir.
54 32 90 67 37 94 53 44
54, 32, 90, 67, 37, 94, 53, 44
11.- Dado el arreglo lineal {7,2,90,12,65,1,43,5}, realiza de manera manual la ordenación
usando el método de la burbuja y mostrando el estatus en cada pasada.
Arreglo original desordenado:
7 2 90 12 65 1 43 5
Primera pasada:
2 7 90 12 65 1 43 5 #se compara 7 con 2, se intercambian
2 7 90 12 65 1 43 5 #se compara 7 con 90, se dejan igual
2 7 12 90 65 1 43 5 #se compara 90 con 12, se intercambian
2 7 12 65 90 1 43 5 #se compara 90 con 65, se intercambian
2 7 12 65 1 90 43 5 #se compara 90 con 1, se intercambian
2 7 12 65 1 43 90 5 #se compara 90 con 43, se intercambian
2 7 12 65 1 43 5 90 #se compara 90 con 5, se intercambian
262
Después de esta primera pasada, queda el mayor (90) a la derecha del arreglo y ya no se
compara en la segunda pasada.
Segunda pasada:
2 7 12 65 1 43 5 90 #se compara 2 con 7, se deja igual
2 7 12 65 1 43 5 90 #se compara 7 con 12, se deja igual
2 7 12 65 1 43 5 90 #se compara 12 con 65, se deja igual
2 7 12 1 65 43 5 90 #se compara 65 con 1, se intercambian
2 7 12 1 43 65 5 90 #se compara 65 con 43, se intercambian
2 7 12 1 43 5 65 90 #se compara 65 con 5, se intercambian
Después de esta segunda pasada, quedan los dos mayores (65, 90) a la derecha del arreglo y
ya no se comparan en la tercera pasada.
Tercera pasada:
2 7 12 1 43 5 65 90 #se compara 2 con 7, se deja igual
2 7 12 1 43 5 65 90 #se compara 7 con 12, se deja igual
2 7 1 12 43 5 65 90 #se compara 12 con 1, se intercambian
2 7 1 12 43 5 65 90 #se compara 12 con 43, se deja igual
2 7 1 12 5 43 65 90 #se compara 43 con 5, se intercambian
Después de esta tercera pasada, quedan los tres mayores (43, 65, 90) a la derecha del
arreglo y ya no se comparan en la cuarta pasada.
263
Cuarta pasada:
2 7 1 12 5 43 65 90 #se compara 2 con 7, se deja igual
2 1 7 12 5 43 65 90 #se compara 7 con 1, se intercambian
2 1 7 12 5 43 65 90 #se compara 7 con 12, se deja igual
2 1 7 5 12 43 65 90 #se compara 12 con 5, se intercambian
Después de esta cuarta pasada, quedan los cuatro mayores (12, 43, 65, 90) a la derecha del
arreglo y ya no se comparan en la quinta pasada.
Quinta pasada:
1 2 7 5 12 43 65 90 #se compara 2 con 1, se intercambian
1 2 7 5 12 43 65 90 #se compara 2 con 7, se deja igual
1 2 5 7 12 43 65 90 #se compara 7 con 5, se intercambian
Después de esta quinta pasada, quedan los cinco mayores (7, 12, 43, 65, 90) a la derecha
del arreglo y ya no se comparan en la sexta pasada.
Sexta pasada:
1 2 5 7 12 43 65 90 #se compara 1 con 2, se deja igual
1 2 5 7 12 43 65 90 #se compara 2 con 5, se deja igual
Después de esta sexta pasada, quedan los seis mayores (5, 7, 12, 43, 65, 90) a la derecha del
arreglo y ya no se comparan en la séptima pasada.
264
Séptima y última pasada:
1 2 5 7 12 43 65 90 #se compara 1 con 2, se deja igual
Después de esta séptima pasada, quedan los siete mayores (2, 5, 7, 12, 43, 65, 90) a la
derecha del arreglo y el arreglo queda ordenado.
Arreglo ordenado:
1 2 5 7 12 43 65 90 #arreglo ordenado
12.- Dado el arreglo anterior ordenado, realizar de manera manual la búsqueda del número
63, y luego el número 43 usando el método de búsqueda binaria.
Para buscar el elemento “63”
0 1 2 3 4 5 6 7
1.- 1, 2, 5, 7, 12, 43, 65, 90
Se establece inicio=0, final=7, mitad=(inicio+final)/2= (0+7)/2=7/2=3 datos[mitad]=7
2.- 1, 2, 5, 7, 12, 43, 65, 90
Como 63>7, inicio=mitad+1=4, final=7, mitad=(4+7)/2=5, datos[mitad]=43
3.- 1, 2, 5, 7, 12, 43, 65, 90
Como 63>43, inicio=mitad+1=5, final=7, mitad=(5+7)/2=6, datos[mitad]=65
4.- 1, 2, 5, 7, 12, 43, 65, 90
Como 63<65, inicio=5, final=mitad-1=5 por lo tanto inicio=final, signo de no encontrado
Ahora para buscar 43…
0 1 2 3 4 5 6 7
265
1.- 1, 2, 5, 7, 12, 43, 65, 90
Se establece inicio=0, final=7, mitad=(inicio+final)/2= (0+7)/2=7/2=3 datos[mitad]=7
2.- 1, 2, 5, 7, 12, 43, 65, 90
Como 43=43, se encontró el elemento, en el lugar=5=mitad
267
PROPOSITO
¿QUÉ APRENDERÁS?
Las diferentes funciones que pueden ser definidas por el usuario, su definición y su
declaración en aspectos como que es la programación modular; la sintaxis, cómo se invoca
y qué es el ámbito de una función; así como la forma de usar los valores de retorno. A
conocer cómo se aplica el paso de parámetros a una función, tanto por valor como por
referencia, así como lo que es y cómo se aplica la recursividad.
¿CÓMO LO APRENDERÁS?
Participarás activamente en las clases, por medio de las actividades de aprendizaje que se
proponen en esta unidad y desarrollarás los ejemplos que el profesor te indicará, y que están
presentes en este libro. De la misma manera, desarrollarás las prácticas diseñadas en esta
unidad, para que aprendas el método que se usa para la resolución de problemas reales.
¿PARA QUÉ LO APRENDERÁS?
Para adquirir la habilidad necesaria para resolver problemas que involucren estos tópicos y
con las habilidades desarrolladas después de estudiar las tres anteriores unidades, aplicando
todo el cúmulo de conocimientos que debes haber adquirido.
268
Recordarás que el diseño modular se basa en la forma de “divide y vencerás”, como lo viste
en tu libro de “Fundamentos de programación” y es la base del uso de las funciones, como
arte de un todo que te va a ayudar a resolver de manera más expedita y fácil el problema
propuesto.
Una función, siendo la estructura que compone el lenguaje C, es la parte más importante
del mismo, toda vez que siempre va a existir al menos una presente (main), y este módulo
nos permite separar un todo en sus partes, y cada parte hacerla como una función, para
darle mayor facilidad de entendimiento al código.
Ya a estas alturas, has usado varias funciones diferentes, y llegó el momento de analizar lo
que es una función y la manera en que podemos hacer una y usarla.
Una función es un bloque de código que realiza una actividad predeterminada. Contiene
declaraciones de datos a usarse, órdenes y comentarios. Tiene como componentes un
identificador o nombre, un tipo del dato que va a devolver la función o void si no devuelve
ningún valor, puede tener una lista de argumentos o no tenerla, y el contenido de la función.
4. Funciones definidas por el usuario.
4.1.- Definición y declaración.
269
La declaración de una función debe darse antes de la función main(), como en el siguiente
ejemplo:
Las palabras int, char o float antes de los identificadores o nombres (suma, menu y
division) indican el tipo de dato que van a devolver las funciones, dentro de la función
suma hay declaradas dos variables, (int a, int b) que son los argumentos, en el segundo
caso, no aparece nada, y por defecto, es vacía, en la tercera, se manifiesta que es vacía, es
decir, que no tiene argumentos.
Puede ser que hubiera varias funciones que devuelvan el mismo tipo de dato, entonces
pueden listarse como se listan las variables al ser declaradas, por ejemplo:
int suma( ), resta( ), producto( ), cociente( );
Cuando se tiene un problema por resolver, en programación se suele usar una técnica
llamada top-down, de “divide y vencerás” o programación descendente que consiste en
dividir el problema principal en varios sub-problemas más fáciles de resolver.
#include “stdio.h” int suma(int a, int b); char menu( ); float division(void); main( ){ . . . }
4.1.1. Programación modular
270
Si, evidentemente vamos a tratar con sub-problemas a resolver, lo haremos con sub-
programas que realizarán este trabajo. Los sub-programas tienen el nombre de módulos, y
de ahí toma su nombre la programación modular. En lenguaje C, los módulos tienen el
nombre de funciones.
La sintaxis de una función, es la siguiente:
Si la declaración no indica el tipo de la función, por defecto éste será “integer” (entero) y
deberá retornar un valor numérico, que podrá ser simplemente un “return 0” (devuelve
cero) lo que indicará terminación normal del programa. El siguiente es un ejemplo:
Esa primera línea:
error(void){
equivale a la siguiente, donde se expresa de manera explícita el tipo de dato que debe
devolver:
int error(void){
Tipo Identificador(Argumentos){ Cuerpo de la función }
error(void){ printf(“Usted tuvo un error… Repita el paso anterior.\n”); getch(); return 0; }
4.1.2. Sintaxis de una función
271
y equivale también a la siguiente, donde no se indica el tipo de dato, que por defecto es
integer, y tampoco se indica con la palabra “void” (vacío) que no hay argumentos:
error( ){
y a la siguiente, donde se expresa de manera explícita el tipo de dato (integer) que debe
devolver, y no se indica con la palabra “void” que no hay argumentos:
int error( ){
Asumamos que se hubo declarado la función “mensaje( )” de la siguiente manera:
void mensaje(void);
la forma correcta de invocarla desde el código será simplemente:
mensaje( );
Pero si se ha declarado con parámetros formales, de la siguiente manera:
int suma(int a, int b);
la forma adecuada de invocarla desde el código será:
a.- si se declararon variables y se hará uso de ellas como argumentos, por ejemplo haberse
declarado
int x, y;
se invocará como:
suma(x,y);
4.1.3. Invocación y ámbito
272
b.- si no se declararon variables, y se va a hacer uso de los argumentos tal cual, entonces se
invocará así:
suma(2,3);
Se conocen como “reglas de ámbito” aquellas que indican si una fracción de código puede
acceder a otro. Sólo puede accederse a una fracción de código de una función por medio de
una llamada a la misma, no usando, por ejemplo, la orden “goto”.
En una función no puede interactuar código o variables definidas en otra, porque tienen un
ámbito diferente. En el lenguaje C, todas las funciones, están en el mismo nivel de ámbito,
es decir, no puede declararse una función dentro de otra función.
Una función puede terminar simplemente cuando llega a la llave del final del bloque, lo que
indica el fin de la misma. Eso sería cuando la función no devuelve ningún valor al código
que la invocó, devolviéndole el control. Por ejemplo:
void gracias( ){ clrscr(); printf(“Gracias por acceder al sistema…\n\n”); }
4.1.4. Retorno de valores
273
Esto no es muy común, más bien lo es que una función envíe un “return” lo que especifica
el valor que ha de volver.
Podríamos decir que hay tres tipos diferentes de funciones:
a.- Computacionales. Son funciones que se basan en una operación realizada con los
argumentos y devuelven un valor de resultado.
b.- En el segundo tipo, solamente manipulan sus datos y devuelven un código de éxito o
error de la función.
c.- En el tercer tipo, no hay un valor de vuelta en especial. A esta función pudiera
considerarse simplemente un procedimiento, que no genera ningún valor.
274
Actividades de aprendizaje
Los siguientes ejercicios, son con el propósito de que el estudiante integre y fortifique los
conocimientos que ha adquirido al paso por este tema, razón por la cual se considera de
capital importancia que los desarrolle y resuelva, y así se prepare para continuar con la
unidad.
1.- ¿Qué es una función?
2.- Escribe un programa sencillo en el que puedas separar un proceso haciéndolo una
función aparte.
3.- Escribe un programa donde apliques la programación top-down y explica por qué.
4.- ¿De dónde toma su nombre la programación modular?
5.- ¿Cuál es la sintaxis de una función?
6.- Si se declaró a función llamada “int factorial(int r)”, ¿cómo debe ser invocada? Elige la
respuesta correcta.
a.- factorial( );
b.- factorial(5);
c.- factorial(4.6);
275
Resumen
Se presenta este resumen en forma de mapa conceptual para ayudar al estudiante a que
complemente el conocimiento adquirido en este tema, y asegure la correcta apropiación del
mismo, se sugiere ampliamente que se revise y se analice con propiedad.
ProgramaciónModular
Módulo oFunción
Tipo Identificador(Argumentos){ Cuerpo de la función}
bloque de código que realiza una actividad predeterminada
Devolver valores o no
Identificador(parámetros_formales);
#include “stdio.h”int suma(int a, int b);char menu( );float division(void);main( ){ . . .}
Se compone con
Su sintaxis es
Se define como
se declara
Se invoca con
Puede
276
Una función puede usar argumentos dentro del paréntesis que sigue a su identificador, y si
es éste el caso, debe declararse con sus respectivos parámetros formales, que tienen el
comportamiento de variables locales. Por paso de parámetros entenderemos el uso de
argumentos en una función.
El siguiente, es un ejemplo de una sencilla función que usa parámetros formales:
Para que esta función sea llamada, deberá hacerse siguiendo por ejemplo, la siguiente
lógica de programación:
4.2. Paso de parámetros
int suma(int a, int b){ int r; r=a+b; return r; }
#include “stdio.h” int suma(int a, int b); main(){ int x, y; /*se declaran las variables que actuarán como argumentos */ . . . suma(x,y); /*se llama mediante los argumentos que sustituirán a los parámetros formales*/ }
277
El uso de estos argumentos, o paso de parámetros, puede ser mediante dos métodos: por
valor o por referencia.
Este método, copia el valor del argumento directamente en el parámetro formal de la
función.
Un ejemplo de una función que utiliza este método, es la siguiente:
Este método, copia la dirección del argumento en el parámetro, y en el cuerpo de la
función, se usará la dirección para acceder al valor del argumento.
Un ejemplo de una función que utiliza este método, es la siguiente:
4.2.1. Por valor
4.2.2. Por referencia
int cubo(int x){ int r; r=x*x*x; return r; }
int cociente(int *x, int *y){ printf("La division de %d / %d es %d \n", *x,*y,(*x)/(*y)); }
278
Tomaremos un programa conocido, el que se realizó en la unidad 2, tema 2.4.2 do-while,
para sustituir las operaciones por funciones que las realicen.
#include "stdio.h" int suma(int x, int y), resta(int x, int y); /*declaración de funciones de paso de parámetros por valor*/ int producto(int *x, int *y), cociente(int *x, int *y); /*declaración de funciones de paso de parámetros por referencia*/ main(){ int a,b,opc; printf("Escribe dos numeros, el primero mayor que el segundo : "); scanf ("%d %d", &a,&b); do{ printf("1. Obtener suma de %d + %d \n", a,b); printf("2. Obtener resta de %d - %d \n", a,b); printf("3. Obtener multiplicación de %d * %d \n", a,b); printf("4. Obtener la division de %d / %d \n", a,b); printf("5. Salir \n"); printf("Elige tu opcion : "); scanf("%d", &opc); switch(opc){ case 1: suma(a,b); /*llamada a función de paso de parámetros por valor*/ break; case 2: resta(a,b); /*llamada a función de paso de parámetros por valor*/ break; case 3: producto(&a,&b); /*llamada a función de paso de parámetros por referencia*/ break; case 4: cociente(&a,&b); /*llamada a función de paso de parámetros por referencia*/ break; case 5: return 0; } /*switch*/ }while(opc!=5); }/*main*/
279
Aunque se le escribieron suficientes comentarios para explicar lo que ocurre, tratemos de
retomar.
Para declarar las funciones con paso de parámetros por valor, es diferente de cuando se usa
el paso de parámetros por referencia, en estos últimos, se declaran poniendo el operador ‘*’
antes del nombre de las variables.
int suma(int x, int y){ printf("La suma de %d + %d es %d \n", x,y,x+y); /*definición de función de paso de parámetros por valor*/ }/*suma*/ int resta(int x, int y){ printf("La resta de %d - %d es %d \n", x,y,x-y); /*definición de función de paso de parámetros por valor*/ }/*resta*/ int producto(int *x, int *y){ printf("La multiplicacion de %d * %d es %d \n", *x,*y,*x*(*y)); /*definición de función de paso de parámetros por referencia*/ }/*producto*/ int cociente(int *x, int *y){ printf("La division de %d / %d es %d \n", *x,*y,(*x)/(*y)); /*definición de función de paso de parámetros por referencia*/ }/*cociente*/
int suma(int x, int y), resta(int x, int y); /*declaración de funciones de paso de parámetros por valor*/ int producto(int *x, int *y), cociente(int *x, int *y); /*declaración de funciones de paso de parámetros por referencia*/
280
Para llamar a una función ocurre algo parecido, pues en la llamada a una función por
referencia, se debe utilizar el operador monario ‘&’ que referencia a la dirección de las
variable.
Cuando se definen las funciones, también es diferente, en el segundo caso, de la función
producto(), tanto en sus parámetros formales como en el uso de las variables locales, se
usará el operador ‘*’ antes de su nombre.
suma(a,b); /*llamada a función de paso de parámetros por valor*/ producto(&a,&b); /*llamada a función de paso de parámetros por referencia*/
int resta(int x, int y){ printf("La resta de %d - %d es %d \n", x,y,x-y); /*definición de función de paso de parámetros por valor*/ } int producto(int *x, int *y){ printf("La multiplicacion de %d * %d es %d \n", *x,*y,(*x)*(*y)); /*definición de función de paso de parámetros por referencia*/ }
281
Actividades de aprendizaje
Los siguientes ejercicios, tienen el propósito de que el estudiante retome los conocimientos
que ha adquirido al paso por este tema y los integre, y por esto, es de gran importancia que
los desarrolle, para avanzar en su conocimiento.
1.- Declara dos funciones: una con argumentos y otra sin ellos y explica por qué se opta por
cada una de las dos vertientes.
2.- ¿Qué hace el paso de parámetros por valor?
3.- ¿Qué hace el paso de parámetros por referencia?
4.- Escribe un ejemplo de funciones con paso de parámetros por valor y por referencia para
cada uno de estos momentos:
• declaración
• llamada
• definición
282
Resumen
Se presenta este resumen en forma de mapa conceptual para que el estudiante complemente
los conocimientos adquiridos en este tema, y así se refuerce y asegure la correcta
apropiación del mismo, se sugiere que se haga una revisión exhaustiva del mismo y se
revise si hay alguna duda.
Paso deparámetros
Por valor Por referencia
Declaración:int suma(int x, int y);
Llamada:suma(a,b);
Definición:int suma(int x, int y){ int r; r=x+y; return r;}
Declaración:int suma(int *x, int *y);
Llamada:suma(&a,&b);
Definición:int suma(int *x, int *y){ int r; r=*x+*y; return r;}
Pueden ser
Ejemplo: Ejemplo:
283
Si en el código de una función hay una llamada a sí misma, se le llama una “función
recursiva”.
La recursividad y la iteración (que es la ejecución de bucles o ciclos), tienen una fuerte
relación, puesto que cualquier solución implementada con iteración, puede implementarse
con recursividad, y viceversa.
¿Te han quedado claros ambos conceptos, recursividad e iteración? Si no es así, remítete a
tus apuntes y libro de Fundamentos de Programación, donde retomarás los conceptos.
Como una función recursiva no debe continuar ejecutándose infinitamente, debe de tener
dos características:
• Existirán argumentos (conocidos como valores base) para los que la función no se
refiere a sí misma.
• Cada vez que se haga una referencia a sí misma, el argumento de la función debe
acercarse al valor base.
Si la función tiene estas dos características, se ha de nombrar como una función “bien
definida”.
4.3. Recursividad.
284
Una función recursiva no debe generar una serie de llamadas infinitas a sí misma, y debe
definirse para un argumento o argumentos la función de manera que haya una manera de
salir de la función.
Usemos un ejemplo típico de la recursividad: el factorial de un número.
El factorial de un número es el producto de enteros de 1 a n
n! = 1* 2 * 3 . . . (n – 2) * (n – 1 ) * n
Definir 0! = 1
1! = 1
2! = 1 * 2 = 2
3! = 1 * 2 * 3 = 6
4! = 1 * 2 * 3 * 4 = 24
5! = 1 * 2 * 3 * 4 * 5 = 120
6! = 1 * 2 * 3 * 4 * 5 * 6 = 720
Lo anterior, lo podemos hacer mediante iteraciones, mediante una función como la que
sigue:
factorial(int a){ int i, r; r=1; /*r es la respuesta*/ for(i=1;i<=a;i++) r=r*i; return r; }
285
Si debemos hacer un algoritmo sobre lo que estamos haciendo al obtener el factorial de un
número, lo haremos de la siguiente manera:
SI n = 0 n! = 0
SI n > 0 n! = n * (n - 1)!
0! = 1
1! = 1 * 0! = 1 * 1 = 1
2! = 2 * 1! = 2 * 1 = 2
3! = 3 * 2! = 3 * 2 = 6
4! = 4 * 3! = 4 * 6 = 24
5! = 5 * 4! = 5 * 24 = 120
6! = 6 * 5! = 6 * 120 = 720
Por lo tanto, estableceremos una función factorial pero que use iteraciones, de la siguiente
manera:
Con el propósito de ilustrar correctamente el uso de la recursividad, se expone enseguida un
ejemplo en el cual se hace el factorial de un número por ambos métodos, el iterativo y el
recursivo.
factorial(int a){ int r; if(a= =1) return 1; r=factorial(a-1)*a; return r; }
288
Actividades de aprendizaje
Estas actividades, se presentan con el propósito de que, mediante la reflexión y el análisis,
respondas construyendo tus propias respuestas, y mediante la discusión en equipo, se logre
llegar a una definición satisfactoria que tenga las características del concepto, aunque
difieran en las expresiones y en las palabras. No temas expresarte libremente o equivocarte,
mediante la cooperación de todos, se llegará a un concepto definitorio.
1.- Define la recursividad.
2.- Responde amplia y detalladamente, ¿Qué relación existe entre la recursividad y la
iteración?
3.- Escribe las características que debe tener una función recursiva.
4.- Escribe una función recursiva basado en las características que debe tener.
289
Resumen
Se presenta en forma de mapa conceptual este resumen para que el estudiante complete los
conocimientos adquiridos en este tema, y así se asegure y refuerce la correcta apropiación
del mismo, se sugiere que se haga una revisión cuidadosa del mismo y se analice si hay
alguna duda.
290
Recapitulación Unidad 4
Se te invita a repasar esta recapitulación, en ella, se presentan los elementos más
significativos de esta unidad, con el propósito de que realices un análisis y síntesis de los
aspectos más relevantes que se han visto y obtengas de ello una conclusión razonable.
Funciones definidas por el usuario
La función es la parte más importante del Lenguaje C, y siempre estará presente al menos
una, llamada main( ).
Definición y declaración
Llamamos una función a una fracción de código que hace algo predeterminado, tiene un
nombre, un tipo de datos, y sus comandos y declaraciones, puede devolver un valor. Debe
declararse antes de la función main(). El tipo de dato de la función indica el tipo de dato o
datos que va a devolver la misma. Puede tener argumentos.
Para resolver un problema, podemos usar una técnica llamada “top-down” o descendente,
donde el problema es subdividido en sub-problemas más fáciles de resolver. Eso, lo
haremos con sub-programas o sub-rutinas, o módulos, y éstos en Lenguaje C se llaman
291
funciones. Si no se indica al inicio de la función el tipo de datos que devolverá, por defecto,
serán integer.
Para invocar una función, puede usarse sólo su nombre si no tiene parámetros formales, y si
no, con sus argumentos. Las llamadas “reglas de ámbito” indican si una fracción de código
puede acceder a otro. En el lenguaje C, todas las funciones, están en el mismo nivel de
ámbito, es decir, no puede declararse una función dentro de otra función. Puede una
función terminar simplemente donde termina la llave, pero lo más usual es que se envíe un
“return”, que especifica el valor de vuelta. Podemos encontrar funciones “computacionales”
que se basan en operaciones con sus argumentos, de un segundo tipo, que sólo devuelven
éxito o error, y de un tercer tipo, que no devuelve valores, sólo de tipo procedimental.
Paso de parámetros.
Los parámetros (declarados dentro del paréntesis de la función) se comportan como
variables locales. El uso de estos argumentos, o paso de parámetros, puede ser mediante
dos métodos: por valor o por referencia. Por valor, copia el valor del argumento
directamente en el parámetro formal de la función. Por referencia, copia la dirección del
argumento en el parámetro, y en el cuerpo de la función, se usará la dirección para acceder
al valor del argumento. Para declarar las funciones con paso de parámetros por valor, se
declaran poniendo el operador ‘*’ antes del nombre de las variables. Para llamarla ocurre
algo parecido, pues en la llamada a una función por referencia, se debe utilizar el operador
monario ‘&’ que referencia a la dirección de las variable. Cuando se definen las funciones,
292
tanto en sus parámetros formales como en el uso de las variables locales, se usará el
operador ‘*’ antes de su nombre.
Recursividad
Si en el código de una función hay una llamada a sí misma, se le llama una “función
recursiva”. Cualquier solución implementada con iteración, puede implementarse con
recursividad, y viceversa.
Como una función recursiva no debe continua ejecutándose infinitamente, (se llamará
entonces “bien definida”) debe de tener dos características:
• Existirán argumentos (conocidos como valores base) para los que la función no se
refiere a sí misma.
• Cada vez que se haga una referencia a sí misma, el argumento de la función debe
acercarse al valor base.
293
Prácticas.
PRÁCTICA 1.- HACER UN PROGRAMA QUE REALICE LA SERIE DE FIBONACCI
POR EL ALGORITMO TRADICIONAL Y PUEDA HACERLO TAMBIEN POR UN
ALGORITMO RECURSIVO
INTRODUCCION.
Antes que cualquier otra cosa, se explicará qué es una “serie de Fibonacci”. Esta serie, fue
un descubrimiento realizado por un matemático italiano, del Siglo XIII, cuyo nombre
precisamente era Fibonacci. En esta serie, cada número es el resultado de la suma de los
dos anteriores. El aspecto será el siguiente:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, etc.
Para hacer este programa, debemos primero mostrar un menú que solicite: Fibonacci
Tradicional, Fibonacci Recursivo y salida, y solicita la elección. Al elegir cualquiera de las
dos opciones, debe solicitar una cantidad entre 1 y 30, para realizar la serie de Fibonacci, y
realizarla por el método que se requiere.
MATERIAL.
Hojas blancas para hacer el diagrama de flujo.
Computadora para capturar, compilar y ejecutar el programa.
294
PROCEDIMIENTO.
Primero, realizamos el diagrama de flujo de los datos.
Inicio
Presenta menú
Solicita r
switch(r)
Fin
1 2
3
normal() recursivo(n)
normal()
Escribe un numero entre 1
y 30
n
N<=1?sn
nn2
1=2
i<=n?
aux=n1n1=n2
n2=aux+n1
i++
s
n
Fin de normal
recursivo(n)
n==0 || n==1?
return nx=recursivo(n-1)y=recursivo(n-2)
return(x+y)
Fin de recursivo(n)
296
OBSERVACIONES.
Al escribir el código del programa, usamos la librería “stdio.h” porque vamos a usar las
funciones printf y scanf. Se declaran las tres funciones que vamos a usar, llamadas
“normal( )”, “recursivo( )” y “menu( )”. Se declara la variable n.
Lo primero que se ejecuta, es la función menú( ) que manda los mensajes de:
1.- Fibonacci Tradicional
2.- Fibonacci Recursiva
3.- Exit
Solicita la variable que va a recibir la elección, que tiene por nombre ‘r’ y se usa mediante
el switch para asignarle diferentes actividades, dependiendo de su valor. En caso de que
valga 1, ejecutará la función llamada “normal( )”. En caso de que valga 2, ejecutará la
función llamada “recursivo( )”.
297
Al ejecutar la función “normal( )”, la función realizará una serie de Fibonacci por medio de
iteraciones. Cuando la que se ejecuta es la función “recursivo( )” se realiza una serie de
Fibonacci recursiva.
RESULTADOS.
298
Actividades de confirmación de conocimientos
Pese a que se ha terminado de estudiar esta Unidad 4, se te presentan estas actividades para
tener un mejor resultado en la apropiación del conocimiento toda vez que las mismas, serán
de gran utilidad para confirmar y reafirmar los conceptos anteriormente revisados.
1.- En la siguiente fracción de código, subraya la correcta declaración de una función.
#include “stdio.h”
int suma(int a, int b);
main( ){
int resta(int a, int b);
.
.
return 0;
}
2.- ¿Cómo se declaran 5 funciones que son las siguientes?
• int f1();
• float f2();
• int f3();
• float f4();
299
• float f5();
3.- Si se declaró una función como “float calculo(float salario)” ¿cómo debe invocarse?
Subraya la respuesta adecuada.
• float calculo( );
• calculo (num);
• calculo (float num);
• float calculo (foat num);
• calculo( );
300
Autoevaluación
1.- En la siguiente fracción de código, subraya la correcta declaración de una función.
#include “stdio.h”
int suma(int a, int b);
main( ){
int resta(int a, int b);
.
.
return 0;
}
Se ha subrayado la segunda línea porque precisamente después de la declaración de las
librerías, y antes de la función main() es donde se declaran las funciones.
2.- ¿Cómo se declaran 5 funciones que son las siguientes?
• int f1();
• float f2();
• int f3();
• float f4();
301
• float f5();
#include “stdio.h”
int f1(), f3();
float f2(), f4(), f5();
Se van a declarar por grupos, se elige indistintamente el primero y el segundo, ya que son
dos funciones de tipo entero y tres de tipo de punto flotante.
3.- Si se declaró una función como “float calculo(float salario)” ¿cómo debe invocarse?
Subraya la respuesta adecuada.
• float calculo( );
• calculo (num);
• calculo (float num);
• float calculo (float num);
• calculo( );
Sólo lleva el nombre de la función y el nombre del supuesto argumento, por eso se elige la
segunda.
303
PROPOSITO
¿QUÉ APRENDERÁS?
A identificar y manejar tanto estructuras como archivos en un nivel básico, formulando y
resolviendo problemas, y usándolos como plataforma de lanzamiento, o columna de apoyo
para entrar a temas más difíciles en la programación estructurada en Lenguaje C.
¿CÓMO LO APRENDERÁS?
Participarás activamente en las clases, y desarrollarás los ejemplos que el profesor te
indicará, y que están presentes en este libro. De la misma manera, desarrollarás las
prácticas diseñadas en esta unidad, para que aprendas el método que se usa para la
resolución de problemas reales.
¿PARA QUÉ LO APRENDERÁS?
Para adquirir la habilidad necesaria para resolver problemas que involucren estos tópicos y
con las habilidades desarrolladas después de estudiar las dos anteriores unidades, aplicando
todo el cúmulo de conocimientos que debes haber adquirido.
304
En Lenguaje C, se encuentran cinco formas de crear nuestros propios tipos de datos: La
estructura, el Campo de bits, la Unión, la Enumeración y el Typedef. En esta Unidad, se
van a estudiar solamente las estructuras, por considerarse además de muy útiles, muy
fáciles de entender y usar.
Los archivos son un elemento muy útil para completar el aprendizaje de Lenguaje C, puesto
que permite guardar los datos capturados, procesados o de salida de los programas que
hacemos, por lo que será la última parte de estudio de este Curso, lo que complementa toda
la información previamente obtenida, tanto de tu curso de “Fundamentos de programación”
como de las 4 unidades anteriores.
¿Qué se entiende por estructura?
Una estructura, es una serie de variables (elementos de la estructura) que reciben la
declaración bajo un mismo nombre, formando una especie de tarjeta de registro.
Pensemos que la información, por ejemplo, se guarde de manera manual en hojas de papel,
anotaríamos:
5. Estructuras y archivos
5.1.- Concepto, declaración y uso de estructuras.
305
Nombre: Irving
Dirección: Pavo, 181.
Ciudad: Guadalajara.
Estado: Jal.
Código Postal: 64000
Sueldo: 2345.23
Y continuaríamos con la lista de personas, direcciones, etc.
Pero si pensáramos en organizar mejor la información, pensaríamos en hacer unas pequeñas
tarjetas, denominadas “fichas”, identificarlas con su propio nombre y les mandaríamos
imprimir los nombres de los campos, por ejemplo:
Bien, ahora, bajo el número 001, se encuentra reunida toda la información del señor Irving.
A cada línea de éstas, la llamaríamos un “elemento de la estructura”.
001 Nombre: Irving
Dirección: Pavo, 181.
Ciudad: Guadalajara.
Estado: Jal.
Código Postal: 64000
Sueldo: 2345.23
306
Esto equivaldría, en un programa en Lenguaje C, a escribir el siguiente código:
Bien, ahora analicemos qué fue lo que se hizo en esta declaración. La declaración de una
estructura, tiene lugar al momento de ponerle un identificador único para todas las
variables, y al final, puede declararse la variable de estructura, que en realidad es la que se
va a usar. La sintaxis correcta para declararla es:
Ya en el transcurrir del código, para hacer referencia a cada uno de los elementos, podemos
hacerlo mediante el operador ‘.’ (punto), y usando la forma: estructura.elemento por
ejemplo, en el código declarativo de arriba, que es:
struct obrero{
struct obrero{ int numero; char nombre[25]; char direccion[30]; char ciudad[20]; char estado[4]; long int cpostal; float sueldo; }empleado;
struct identificador{ tipo variable1; tipo variable2; tipo variable3; . . . }variable_de_estructura;
307
int numero; char nombre[25]; char direccion[30]; char ciudad[20]; char estado[4]; long int cpostal; float sueldo; }empleado;
Si deseamos llenar un registro con los datos del primer ejemplo, lo haremos mediante la
operación:
empleado.numero=001;
empleado.nombre=”Irving”;
empleado.dirección=”Pavo,181”;
empleado.ciudad=”Guadalajara”;
empleado.estado=”Jal”;
empleado.cpostal=64000;
empleado.sueldo=2345.23;
Si deseamos por ejemplo, imprimir los campos, haremos referencia a los mismos utilizando
entonces el operador punto, de igual manera:
printf(“%d”, empleado.numero);
printf(“%s”, empleado.nombre);
printf(“%s”, empleado.dirección);
printf(“%s”, empleado.ciudad);
308
printf(“%s”, empleado.estado);
printf(“%d”, empleado.cpostal);
printf(“%6.2f”, empleado.sueldo);
O si deseamos capturar los campos, entonces mediante los comandos:
scanf(“%d”, &empleado.numero);
gets(empleado.nombre);
gets(empleado.dirección);
gets(empleado.ciudad);
gets(empleado.estado);
scanf(“%d”, &empleado.cpostal);
scanf(“%f”, &empleado.sueldo);
Podemos hacer uso de lo que se denomina un “arreglo de estructuras”. ¿Qué es un arreglo
de estructuras? Sería como si tuviéramos un tarjetero donde ubicaríamos una serie de
tarjetas, por ejemplo:
005 004
003 002
001 Nombre: Irving
Dirección: Pavo, 181.
Ciudad: Guadalajara.
Estado: Jal.
Código Postal: 64000
Sueldo: 2345.23
309
Y entonces, la declaración se modificaría un poco en la variable de estructura. ¿Qué es la
variable de estructura? ¿en qué se diferencia del identificador? El identificador sirve para
que el compilador reconozca la estructura, pero para usar la misma, debe ser mediante la
variable de estructura, de la manera siguiente:
struct obrero{ int numero; char nombre[25]; char direccion[30]; char ciudad[20]; char estado[4]; long int cpostal; float sueldo; }empleado[33];
En este formato, estaríamos guardando los datos del registro completo de los 33
trabajadores de nuestra pequeña empresa. Para ilustrar lo que se acaba de aprender, veamos
un ejemplo:
#include "stdio.h" #define MAX 100 struct obrero{ int numero; char nombre[25]; char direccion[30]; char ciudad[20]; char estado[4]; long int cpostal; float sueldo; }empleado[MAX]; void inicializa(void), agregar(void), quitar(void), mostrar(void); int menu(void), libre(void);
310
main(){ int opc; inicializa(); for(;;){ opc=menu(); switch(opc){ case 1: agregar(); break; case 2: quitar(); break; case 3: mostrar(); break; case 4: return 0; } } } void inicializa(void){ register int i; for(i=0;i<MAX;i++) empleado[i].numero=0; } int menu(void){ int op; printf("\n1. Agregar un registro\n"); printf("2. Remover un registro\n"); printf("3. Mostrar la agenda\n"); printf("4. Salir\n"); do{ printf("Elige tu opcion : "); scanf("%d",&op); }while(op<0||op>4); return op; } void agregar(void){ int lugar; lugar=libre(); if(lugar==-1){ printf("\nLa lista esta llena\n\n"); return; }
311
printf("\nIntroduzca el numero consecutivo : "); scanf("%d",&empleado[lugar].numero); printf("\nIntroduzca el nombre del empleado: "); scanf("%s", empleado[lugar].nombre); printf("\nIntroduzca la direccion (calle y numero) : "); scanf("%s",empleado[lugar].direccion); printf("\nIntroduzca la direccion (ciudad estado): "); scanf("%s",empleado[lugar].ciudad); scanf("%s",empleado[lugar].estado); printf("\nIntroduzca el codigo postal : "); scanf("%d",&empleado[lugar].cpostal); printf("\nIntroduzca el sueldo : "); scanf("%f",&empleado[lugar].sueldo); } int libre(void){ register int i; for(i=0;empleado[i].numero&&i<MAX;++i); if(i==MAX) return -1; return i; } void quitar(void){ int r; printf("Introduce el numero del registro : "); scanf("%d",&r); if(r>=0&&r<MAX) empleado[r-1].numero=0; } void mostrar(void){ register int i; for(i=0;i<MAX;++i){ if(empleado[i].numero>0){ printf("\nNumero: %d \n", empleado[i].numero); printf("Nombre: %s \n", empleado[i].nombre); printf("Direccion: %s \n", empleado[i].direccion); printf("Ciudad y Estado: %s, %s. \n", empleado[i].ciudad, empleado[i].estado); printf("Codigo Postal: %d \n", empleado[i].cpostal); printf("Sueldo: %6.2f \n", empleado[i].sueldo); } } printf("\n\n"); }
312
El resultado que vamos a obtener con este programa, al ejecutarlo, aparecerá un menú como
el siguiente:
Cuando se ejecuta la primera opción, para registrar un trabajador, se hará de la siguiente
manera:
313
Usando la opción 3 para mostrar los registros capturados, en este caso, uno solo, lo haremos
así:
Si ya tenemos, por ejemplo dos (o más) registros, se hará mediante la misma opción 3, y
nos dará un resultado como el siguiente:
314
Vamos a borrar un registro, y para eso, vamos a usar la opción 2, borrar el primer registro y
luego a listar de nuevo la agenda, para ver si se borró.
315
Actividades de aprendizaje
1.- ¿Cuáles son las cinco formas de crear nuestros propios tipos de datos?
2.- Define una estructura.
3.- Si se hace una analogía entre una ficha de registro de datos personales y una estructura,
¿qué serían los campos del registro? Explica por qué sería así.
4.- ¿Cuál es la diferencia entre el identificador y la variable de estructura?
5.- Referencia para lectura el elemento “edad” de la estructura siguiente, explica el
procedimiento:
struct estudiante{
char nombre[30];
int edad;
}alumno;
316
Resumen
Se hace la presentación de este resumen en forma de mapa conceptual para ayudar al
estudiante a que logre complementar el conocimiento adquirido en este tema, y asegurar la
correcta apropiación del mismo, es preferible y se sugiere que se revise y se realice un
análisis sucinto del mismo.
Estructuras
Concepto Declaración Uso
Una estructura, es una serie
de variables (elementos de la
estructura) que reciben la
declaración bajo un mismo
nombre, formando una
especie de tarjeta de registro.
struct identificador{ tipo variable1; tipo variable2; tipo variable3; . . .}variable_de_estructura;
Para hacer referencia a cada uno de los elementos, podemos hacerlo mediante el operador ‘.’ (punto), y usando la forma: estructura.elemento.
Podemos hacer uso de lo que se denomina un “arreglo de estructuras”, que sería como si tuviéramos un tarjetero donde ubicaríamos una serie de tarjetas
317
Antes de referirnos a los tipos de archivos, se considera correcto y necesario hacer una
diferenciación entre los conceptos de “archivo” y “flujo”.
Estando en un extremo el programador y en el otro el dispositivo al que se accede
(controladores de discos y cintas, etc.) hay un nivel de abstracción, o una interfaz a la cual
se denomina “flujo”. Todos los flujos son independientes del dispositivo y existen dos
tipos: de texto y binarios.
Al dispositivo real se le llama “archivo” en el sistema de entrada y salida de ANSI. Para
poder realizar un intercambio de información con un archivo, es necesario que se asocie
con un flujo, y a esta función se le llama “apertura”.
Es una secuencia de texto separado en líneas, que pueden tener cero o más caracteres
terminada con un carácter “nueva línea”.
Es un conjunto de bytes que se guardan en un dispositivo externo
5.2. Tipos de archivos en C.
5.2.1. Flujos de texto
5.2.2. Flujos binarios
318
Actividades de aprendizaje
Define con tus propias palabras los siguientes conceptos. Ayúdate de gráficos, objetos, etc.
para que puedas ejemplificar y dejar en claro lo que deseas expresar. Expón delante de tus
compañeros de equipo tus definiciones y defiéndelas cuando sean cuestionadas. Trata de
tener presente en la mente cuando realices estos ejercicios que no importa si lo que
construyes es equivocado, pues el aprendizaje cooperativo se basa precisamente en la
participación concurrente y objetiva de cada uno de los miembros del equipo para llegar a
conclusiones correctas.
1.- ¿Cuál es la diferencia entre “archivo” y “flujo”?
2.- ¿Qué es un flujo de texto?
3.- ¿Qué es un flujo binario y cuál es su diferencia con un flujo de texto?
319
Resumen
Se hace la presentación en forma de mapa conceptual de este resumen para ayudar al
estudiante a que logre asegurar la correcta apropiación del conocimiento adquirido en este
tema, y complementar el mismo, es preferible y se sugiere que se revise y analice
extensamente.
Flujos
De texto Binario
Es una secuencia de texto
separado en líneas, que
pueden tener cero o más
caracteres terminada con un
carácter “nueva línea”.
Es un conjunto de bytes que se
guardan en un dispositivo
externo.
320
Podría referirse el sistema de archivos como el de ANSI C, cuyas funciones se incluyen en
el archivo de encabezado llamado “stdio.h”. Para referir un archivo se usa un puntero que
contiene nombre, estado y posición.
Hay varios modos para abrir un archivo, y serán representados mediante la siguiente tabla:
Modo Tipo Acción
“r” texto abre para lectura
“w” texto crea para escritura
“a” texto abre para agregar
“rb” binario abre para lectura
“wb” binario crea para escritura
“ab” binario abre para agregar
“r+” texto abre para lectura/escritura
“w+” texto crea para lectura/escritura
“a+” texto abre o crea para lectura/escritura1
“r+b” binario abre para lectura/escritura
“w+b” binario crea para lectura/escritura
5.3. Manejo de archivos
5.3.1. Modos de apertura
321
“a+b” binario abre o crea para lectura/escritura
“rt” texto abre para lectura
“wt” texto crea para escritura
“at” texto abre para agregar
“r+t” texto abre para lectura/escritura
“w+t” texto crea para lectura/escritura
“a+t” texto abre o crea para lectura/escritura
Tabla 5.1. Valores para el modo.
• función fopen()
Esta función abre un flujo para que sea posible usarlo, asociándolo con un archivo. Su
sintaxis es la siguiente:
FILE *fopen(*nombre_del_archivo, *modo_de_apertura);
Por nombre_del_archivo nos referimos al identificador del mismo, y el modo es el que fue
anotado en la tabla 5.1., de manera que un ejemplo podría ser así:
flujo= fopen(“nombres.dat”, “a”);
5.3.2. Funciones para lectura y escritura
322
Lo anterior, estaría abriendo el archivo “nombres.dat” para agregar datos al final. Sin
embargo, no se usa normalmente así, sino usando un método para detectar cualquier error
al abrir el archivo (pudiera estar protegido contra lectura o escritura, por ejemplo).
La forma correcta entonces sería la siguiente:
flujo=fopen("nombres.dat", "a"); if (flujo == NULL){ printf("Error, no puede ser abierto el archivo\n"); }
fopen() devuelve un puntero de tipo FILE. Se utiliza un NULL que es 0 para significar el
fallo de la apertura, porque ningún archivo toma nunca ese valor de cero.
• función putc()
Esta función pone caracteres en un flujo que haya sido abierto para escritura, y su sintaxis
es la siguiente:
putc(caracter, *puntero_a_archivo);
Si la función putc() es exitosa, devuelve el carácter escrito, y si no, devuelve EOF;
Un ejemplo de la manera en que se puede usar, es la siguiente:
323
FILE *flujo;
char car;
…
putc(car, flujo);
• función getc()
Esta función obtiene caracteres en un flujo que haya sido abierto para lectura, y su sintaxis
es la siguiente:
getc(*puntero a archivo);
La función getc() regresa el carácter que lee, y cuando alcanza el fin de archivo, regresa un
EOF;
Un ejemplo de la manera en que se puede usar, es la siguiente:
FILE *flujo;
char car;
…
car=getc(flujo);
324
• función fclose()
Esta función cierra un flujo que fue previamente abierto, escribiendo a disco todo lo que
contenga el buffer, y su sintaxis es la siguiente:
fclose(*puntero_a_archivo);
Si devuelve un cero, significa que fue exitosa la operación de otra manera regresa un EOF.
Un ejemplo de la manera en que se puede usar, es la siguiente:
FILE *flujo;
char car;
…
fclose(flujo);
• función ferror()
Esta función indica si ha habido un error al realizarse una operación con un archivo, y tiene
la sintaxis siguiente:
ferror(*puntero_a_archivo);
325
Devuelve verdadero si se ha producido un error, y falso si ha sido exitosa la última
operación.
• función rewind()
Esta función inicializa el indicador de posición al inicio del archivo que indica su
argumento, y tiene la sintaxis siguiente:
rewind(*puntero_a_archivo);
El siguiente es un ejemplo de cómo se accede a un archivo en modo lectura. Asumimos que
el archivo de texto “ejemplo.txt” ya existe, así que lo que hace el presente programa es leer
el archivo del disco y presentarlo en la pantalla.
Después de la declaración del archivo de cabecera, ya dentro de la función main( ) se
declara un flujo de nombre “flujo” que es de tipo FILE (archivo) y la variable que nos va a
servir para leer los caracteres del interior del archivo de texto.
Se le asigna entonces al flujo la apertura en modo lectura ( r ) del archivo cuyo nombre es
“ejemplo.txt”. Luego se asegura el programa que no haya un error de apertura, si fuera así,
devuelve el mensaje de “error…”.
5.3.3. Rutinas de acceso directo
326
Si no hubiera error, entonces continúa, asignando en principio, el primer carácter leído del
flujo, a la variable car. Mientras car no alcance el valor de fin de archivo (EOF) va a
ponerlo en pantalla y leer el siguiente. Terminando de escribir todos los caracteres que
contiene el archivo, se cierra el flujo y termina.
De la compilación del presente programa, obtenemos el siguiente resultado:
#include "stdio.h" main(){ FILE *flujo; char car; flujo=fopen("ejemplo.txt", "r"); if (flujo == NULL){ printf("Error, no puede ser abierto el archivo\n"); } else{ /*se procesa*/ car=getc(flujo); while(car!=EOF){ putchar(car); car=getc(flujo); } /*al final se cierra*/ fclose(flujo); } return 0; }
327
La siguiente es una variación del programa anterior, porque ahora se hizo un programa que
lee cualquier archivo de texto, solamente dando el nombre del archivo a leer después del
nombre del programa ejecutándose. Las modificaciones están en color rojo.
#include "stdio.h" main(int argc, char *argv[]){ FILE *flujo; char car; if (argc!=2){ printf("Uso: %s archivo_a_ser_leido\n", argv[0]); return -1; } flujo=fopen(argv[1], "r"); if (flujo == NULL){ printf("Error, no puede ser abierto el archivo\n"); } else{ /*se procesa*/ car=getc(flujo); while(car!=EOF){ putchar(car); car=getc(flujo); } /*al final se cierra*/ fclose(flujo); } return 0; }
328
La primera modificación fue que ahora el main( ) tiene argumentos, tomando la forma de
“main(int argc, char *argv[])”. El primer argumento, es un entero (argc) que contiene el
número de argumentos escritos al momento de ejecutar el programa. El segundo
argumento, contiene las cadenas que se dieron en esos argumentos. El programa tiene como
nombre “prog49”, así que ejecutarlo simplemente como “./prog49” es un solo argumento,
argc vale 1 y argv[0] vale “./prog49”. Si escribimos para ejecutarlo “./prog49 texto.txt”
entonces argc vale 2, argv[0] vale “./prog49”, y argv[1] vale “texto.txt”.
La segunda modificación precisamente es para asegurarnos que se usen dos argumentos, el
nombre del programa y el nombre del archivo a ser abierto. Si la línea de comando que
ejecuta el programa tiene menos de dos palabras, o mas de dos palabras, entonces será un
error, y mandará un mensaje de error, indicado el uso que se da al programa.
La tercera modificación, es en función de la forma de abrir el archivo a leer, no se va a
escribir el nombre de manera constante, sino que va a corresponder con el argumento
argv[1].
Veamos cómo nos da el funcionamiento del programa ya en ejecución.
329
Después de ser escrito el programa, se compiló y se ejecuta en primera instancia, usando
solamente el nombre del programa “./prog49”. Nos manda el mensaje de error y termina.
Lo mismo ocurre cuando se intenta ejecutar con tres argumentos, “./prog49 texto.txt
ejemplo.txt”. Cuando se ejecuta el nombre del programa y el del archivo objeto, funciona
perfectamente “./prog49 texto.txt” y el otro caso es “./prog49 ejemplo.txt”.
Estos programas “leen” el contenido de un archivo, vamos a hacer ahora un programa que
“escriba” en un archivo de texto.
330
De nuevo el main( ) tiene argumentos, tomando la forma de “main(int argc, char *argv[])”.
El programa tiene como nombre “prog50”, así que ejecutarlo simplemente como “./prog50”
es un solo argumento, argc vale 1 y argv[0] vale “./prog50”. Si escribimos para ejecutarlo
“./prog50 prueba.txt” entonces argc vale 2, argv[0] vale “./prog50”, y argv[1] vale
“prueba.txt”.
Veamos cómo nos da el funcionamiento del programa ya en ejecución.
#include "stdio.h" main(int argc, char *argv[]){ FILE *flujo; char c; if(argc!=2){ printf("Uso: %s archivo_a_ser_creado\n",argv[0]); return -1; } flujo=fopen(argv[1], "w"); if(flujo == NULL){ printf("Error, no puede ser creado el archivo\n"); } do{ c=getchar(); putc(c, flujo); }while(c!='$'); fclose(flujo); return 0; }
331
Después de ser escrito el programa, se compiló y se ejecuta en primera instancia, usando
solamente el nombre del programa “./prog50”. Nos manda el mensaje de error y termina.
Cuando se ejecuta el nombre del programa y el del archivo objeto, funciona perfectamente
“./prog50 prueba.txt”.
332
Actividades de aprendizaje
1.- ¿Para qué sirve la función fopen()?
2.- ¿Qué significado tiene la siguiente expresión?
flujo=fopen(“nombres.dat”,”a”);
3.- Si se requiere en el transcurso del programa escribir caracteres a un flujo que ya está
abierto, ¿qué función usarías? ¿por qué?
a.- putc( )
b.- getc( )
4.- Escribiendo un programa, debe inicializarse el indicador de posición al inicio del
archivo, ¿qué función usarías? Indica el porqué de tu elección.
a.- fclose( )
b.- ferror( )
c.- rewind( )
5.- ¿Qué valor contiene la variable entera argc en el main()?
6.- ¿Qué valor contiene la variable de cadena argv[] en el main() y cuál es su diferencia con
el argc?
333
Resumen
Se hace la presentación de este resumen en forma de mapa conceptual para asegurar que el
estudiante logre apropiarse correctamente del conocimiento adquirido en este tema, y
complementarlo, se sugiere que se revise y analice extensamente.
Manejo de archivos
Funciones para lectura y escrituraModos de apertura Rutinas de acceso directo
fopen()putc()getc()fclose()ferror()rewind()
Lecturarwarbwbabr+w+a+r+bw+ba+brtwtatr+tw+ta+t
Escritura
334
Recapitulación Unidad 5
Concepto, declaración y uso de estructuras
Una estructura, es una serie de variables que reciben la declaración bajo un mismo nombre.
La declaración de una estructura, tiene lugar al momento de ponerle un identificador único
para todas las variables, y al final, puede declararse la variable de estructura, que en
realidad es la que se va a usar. La sintaxis correcta para declararla es:
Para hacer referencia a cada uno de los elementos, podemos hacerlo mediante el operador
‘.’ (punto), y usando la forma: estructura.elemento. Podemos hacer uso de lo que se
denomina un “arreglo de estructuras”.
Tipos de archivos en C
Diferenciemos entre los conceptos de “archivo” y “flujo”. Estando en un extremo el
programador y en el otro el dispositivo al que se accede hay un nivel de abstracción, o una
struct identificador{ tipo variable1; tipo variable2; tipo variable3; . . . }variable_de_estructura;
335
interfaz a la cual se denomina “flujo”. Todos los flujos son independientes del dispositivo y
existen dos tipos: de texto y binarios. Al dispositivo real se le llama “archivo” en el sistema
de entrada y salida de ANSI.
Manejo de archivos
Podría referirse el sistema de archivos como el de ANSI C, cuyas funciones se incluyen en
el archivo de encabezado llamado “stdio.h”. Para referir un archivo se usa un puntero que
contiene nombre, estado y posición.
Hay varios modos para abrir un archivo, y están representados mediante tabla 5.1:
Existen varias funciones para ejercer la lectura y/o escritura de un archivo, y se enumeran
en las siguientes:
• función fopen()
Esta función abre un flujo para que sea posible usarlo, asociándolo con un archivo. Su
sintaxis es la siguiente: FILE *fopen(*nombre_del_archivo, *modo_de_apertura);
336
• función putc()
Esta función pone caracteres en un flujo que haya sido abierto para escritura, y su sintaxis
es la siguiente: putc(caracter, *puntero_a_archivo); Si la función putc() es exitosa,
devuelve el carácter escrito, y si no, devuelve EOF;
• función getc()
Esta función obtiene caracteres en un flujo que haya sido abierto para lectura, y su sintaxis
es la siguiente: getc(*puntero a archivo); La función getc() regresa el carácter que lee, y
cuando alcanza el fin de archivo, regresa un EOF;
• función fclose()
Esta función cierra un flujo que fue previamente abierto, escribiendo a disco todo lo que
contenga el buffer, y su sintaxis es la siguiente: fclose(*puntero_a_archivo); Si devuelve un
cero, significa que fue exitosa la operación de otra manera regresa un EOF.
• función ferror()
Esta función indica si ha habido un error al realizarse una operación con un archivo, y tiene
la sintaxis siguiente: ferror(*puntero_a_archivo); Devuelve verdadero si se ha producido un
error, y falso si ha sido exitosa la última operación.
337
• función rewind()
Esta función inicializa el indicador de posición al inicio del archivo que indica su
argumento, y tiene la sintaxis siguiente: rewind(*puntero_a_archivo);
Se vieron también algunas rutinas de acceso directo, tanto de lectura como de escritura, con
ejemplos funcionales de código.
338
Actividades de confirmación de conocimientos
Resolviendo los problemas que se anotan a continuación, y por otro lado capturas, compilas
y ejecutas los programas que se sugieren, vas a adquirir los conocimientos que ya se han
proporcionado en el transcurso de este curso. Se te sugiere que analices cada uno de los
problemas planteados y expliques brevemente el procedimiento que seguiste para
resolverlo. Trata de resolverlo todo y comparar tus resultados con los de la autoevaluación.
1.- En la siguiente estructura:
struct estudiante{ long int nocontrol; char nombre[25]; char especialidad[15]; char grupo; }alumno[30];
Si deseamos asignar el grupo ‘G’ al estudiante 0, ¿cuál sería la manera correcta? Subraya la
respuesta que se ajuste.
• grupo.alumno=’G’;
• alumno.grupo=’G’;
• grupo.alumno[0]=’G’;
• alumno[0].grupo=’G’;
• ninguna de las anteriores.
339
2.- Interpreta línea por línea la siguiente fracción de código:
1. if(argc!=2){ 2. printf("Uso: %s archivo_a_ser_creado\n",argv[0]); 3. return -1; 4. } 5. flujo=fopen(argv[1], "w"); 6. if(flujo == NULL){ 7. printf("Error, no puede ser creado el archivo\n"); 8. }
340
Autoevaluación
1.- En la siguiente estructura:
struct estudiante{ long int nocontrol; char nombre[25]; char especialidad[15]; char grupo; }alumno[30];
Si deseamos asignar el grupo ‘G’ al estudiante 0, ¿cuál sería la manera correcta? Subraya la
respuesta que se ajuste.
Como para la utilización del operador ‘.’ para referenciar a un elemento de una estructura
se usa con el formato estructura.elemento, y siendo la estructura en este caso, un arreglo de
30 elementos, entonces eligiremos la respuesta 4, que corresponde con
estructura[No_de_alumno].elemento.
• grupo.alumno=’G’;
• alumno.grupo=’G’;
• grupo.alumno[0]=’G’;
• alumno[0].grupo=’G’;
• ninguna de las anteriores.
2.- Interpreta línea por línea la siguiente fracción de código:
1. if(argc!=2){ 2. printf("Uso: %s archivo_a_ser_creado\n",argv[0]); 3. return -1;
341
4. } 5. flujo=fopen(argv[1], "w"); 6. if(flujo == NULL){ 7. printf("Error, no puede ser creado el archivo\n"); 8. }
1. Si el número de argumentos que aparecen al ejecutarse el programa es diferente de dos, abre bloque de código a ejecutarse
2. Imprimir un mensaje que indica que debe ejecutarse con el nombre del programa seguido del nombre del archivo a ser creado
3. Regresar código de error 4. Cierra bloque de código 5. Asigna a “flujo” el apuntador al archivo que indica la segunda palabra del comando
a ejecutarse cuando se invoca al programa 6. Si el resultado del apuntador fuese cero (NULL) 7. Imprime un mensaje de error, que indica que no pudo ser abierto el archivo 8. Cierra bloque de código.
342
Actividades para evaluar el aprendizaje
Las actividades que en este apartado se encuentran, reasumen lo que se vio a lo largo de
este libro, y se te presentan con el propósito de que pongas en práctica los conocimientos
adquiridos, y compares tus resultados con los que encontrarás en la sección de
Autoevaluación. Elabora los diagramas de flujo que muestren el proceso a seguir y
desarrolla el programa completo.
1.- Modifica cada una de las funciones en las que sean necesarias las modificaciones, al
programa No. 47 para que los registros los haga y los deje grabados en el disco.
a. programa general
b. submódulo inicializa()
c. submódulo menú()
d. submódulo agregar()
e. submódulo libre()
f. submódulo quitar()
g. submódulo mostrar()
343
Autoevaluación
Esta sección, complementa la anterior de Actividades para evaluar el aprendizaje, para que
revises las respuestas que obtuviste en ella y que en base a las conclusiones que se
desprendan de ese análisis, afirmes completamente los conocimientos que adquiriste en el
libro completo.
1.- Modifica cada una de las funciones en las que sean necesarias las modificaciones, al
programa No. 47 para que los registros los haga y los deje grabados en el disco.
a. Programa general. El diagrama de flujo del programa en general, es el siguiente:
Define maxDeclara empleadoDeclara funciones
Declara FILE
Switch(opc)
Quitar()Agregar() Mostrar()
Termina
Menu()
1 2 3
4
Inicializa()
Inicia
344
b. submódulo inicializa(). Su diagrama de flujo es el siguiente:
c. submódulo menú(). Su diagrama de flujo es el siguiente:
345
d. submódulo agregar(). Su diagrama de flujo es el siguiente:
Agregar()
Abre datos.dat
Libre()
Lugar= -1? Lista llenas
Datos del registro
Escribe Datos y cierra
archivoTermina
e. submódulo libre(). Su diagrama de flujo es el siguiente:
346
f. submódulo quitar(). Su diagrama de flujo es el siguiente:
Quitar()
Abre y lee datos.dat
No. De registro
r
R>=0&&r<MAX
Emplearo[r-1].numero=0
s
Cierra archivo
Termina
347
g. submódulo mostrar(). Su diagrama de flujo es el siguiente:
Mostrar()
Abre y lee datos.dat
i=0
i<MAX?
++i
Empleado[i].numero>0?
Imprime registro
Cierra archivo
Termina
s
s
NOTA: Se ponen solamente los diagramas de flujo porque se confía en que tienes ya los
conocimientos suficientes como para desarrollar el programa completo.
348
Actividades de generalización
Se proponen las siguientes actividades, que te sugerimos realizar, para que relaciones el
contenido de este libro con la vida real.
1.- Realiza una investigación documental sobre las carreras que ofrecen las principales
universidades de nuestro país y el extranjero, así como los lenguajes de programación más
usados en las mismas, por ejemplo:
http://www.unam.mx
http://www.ucol.mx
http://www.udg.com.mx
2.- Realiza una investigación de campo con tus profesores que tengan la carrera de
Ingeniero en Sistemas, Licenciado en Informática, Maestro en Ciencias Computacionales, o
carreras afines, y pregunta sobre los lenguajes de programación que ellos han aprendido en
su preparación, y posteriormente, ya en el desarrollo de su carrera.
3.- Acude con el administrador de la red global de tu plantel, jefe del departamento de
sistemas, o del laboratorio de cómputo, o del centro de cómputo, pregunta sobre los
lenguajes de programación que se han usado en la institución y en qué plataformas
(sistemas operativos) funcionan.
349
4.- Entra a portales que ofrecen bolsa de trabajo y revisa los requisitos que se necesitan para
cubrir los puestos de programador, por ejemplo:
http://www.computrabajo.com.mx
http://www.alempleo.com.mx
5.- Investiga el papel de la programación estructurada, en la programación en Internet o en
la elaboración de páginas Web.
6.- Realiza una búsqueda usando google, o altavista para encontrar los cursos que se
ofrecen en portales de enseñanza gratuita, sobre lenguajes de programación y cuáles
lenguajes son, por ejemplo:
http://www.programacion.com
http://www.monografias.com
http://www.programacionfacil.com
http://www.lawebdeprogramacion.com
350
Glosario. ALGOL (Algorithmic Language / Lenguaje Algorítmico) Fue un
leguaje de programación muy usado en las universidades en los años 60’s, aunque su uso nunca fue adecuado para fines comerciales. Se considera que fue la base para el desarrollo posterior de lenguajes de programación de gran aceptación entre los programadores, como Lenguaje C o Lenguaje Pascal.
ANSI (American Nacional Standards Institute / Instituto
Nacional Americano de Estándares) Organización sin fin de lucro que supervisa los estándares para procesos, sistemas, productos y servicios en los Estados Unidos de América.
Bjarne Stroustrup Científico y catedrático Danés que inventó el C++, según
sus propias palabras: "inventé C++, escribiendo sus primeras definiciones, y produciendo la primera implementación... elegí y formulé los criterios de diseño para C++, confeccioné también sus principales utilidades, y fui responsable de elaborar extensas proposiciones en el comité de estándares de C++."
BCPL (Basic Combined Programming Language / Lenguaje de
programación básico combinado) Leguaje de programación creado por Martin Richards en 1966, posteriormente lo usaría Dennos Ritchie para escribir el Lenguaje B que a su vez daría como resultado más tarde el Lenguaje C.
Borland C/C++ Borland Software Corporation es una empresa creadora de
software famosa por sus productos como Turbo Pascal y Turbo C.
Buffer Un buffer de datos es una localidad en memoria que se
reserva para el almacenamiento temporal de información, que está esperando a ser procesada.
CGI (Common Gateway Interface / Interfaz común de
pasarela) Tecnología de la WWW para solicitar datos de un programa ejecutado directamente en el servidor de web, de manera dinámica.
351
CPL (Combined Programming Language / Lenguaje de
programación combinado) Lenguaje de programación, precursor del BCPL, usado durante la década de los 60’s que dio muchos problemas en su uso.
DEC PDP-11 (Digital Equipment Corporation) Primera mini
computadora fabricada en los 70’s por Digital que interconectaba memoria, procesador y periféricos. Fue de las primeras computadoras en las que corrió el Sistema Operativo UNIX.
Dennis Ritchie Dennis MacAlistair Ritchie, físico de origen
estadounidense que cooperó en la creación del sistema operativo UNIX y creó el lenguaje de programación C.
Dev-C++ Es un ambiente de desarrollo integrado (IDE) para la
programación en C/C++, de la compañía Bloodshed Software.
DHTML (Dynamic HTML / HTML dinámico) es un conjunto de
técnicas que permiten crear sitios web interactivos, utilizando una combinación del lenguaje HTML estático, un lenguaje interpretado del lado del cliente (como JavaScript) y el Lenguaje de hojas de estilo en cascada(CSS).
Dijkstra Edsger Wybe Dijkstra. Científico de origen neerlandés,
fue creador del algoritmo de camnos mínimos, también llamado Algoritmo de Dijkstra. Trabajó para desarrollar el primer compilador para Algol-60
DOS (MS-DOS) (Microsoft Disk Operating System / Sistema operativo de
disco de Microsoft) Sistema operativo diseñado para la IBM-PC
Etiqueta Es una marca con tipo que delimita una región en los
lenguajes basados en XML. Flash Adobe Flash, antes Macromedia Flash, es un programa de
edición multimedia cuyo producto puede ser visto en una página web a través de un navegador.
Gcc (GNU Compiler Collection / Colección de compiladores
de GNU), que es software libre, compilando C, C++,
352
Fortran, Ada y otros lenguajes. GNU (GNU is Not UNIX, lo que es un acrónimo recursivo)
Proyecto iniciado por Richard Stallman para "retornar al espíritu de cooperación que prevaleció en los tiempos iniciales de la comunidad de usuarios de computadoras".
HTML (Hyper Text Markup Language / Lenguaje de marcas de
hipertexto) Es un lenguaje de marcación diseñado para estructurar textos y presentarlos en forma de hipertexto, formato usado por las hojas web.
Internet Red mundial de computadoras interconectadas, basada en
un conjunto de protocolos, entre los que destaca la suite tcp/ip, y que proporciona diferentes servicios, como www, ssh, telnet, ftp, smtp, irc, etc.
ISO (Internacional Standarization Organization / Organización
internacional para la estandarización) Organización sin fines de lucro que produce normas industriales y comerciales.
Java Lenguaje de programación orientado a objetos
desarrollado por James Gosling y compañeros de Sun Microsystems al inicio de la década de los 90’s. Toma mucha de su sintaxis de C y C++, sin usar punteros.
JavaScript Es un lenguaje interpretado orientado a las paginas web,
basado en el paradigma prototipo, con una sintaxis parecida al lenguaje Java. Fue inventado por Brendan Eich.
Ken Thompson Uno de los creadores del Sistema Operativo UNIX,
creador también del lenguaje de programación B. Lenguaje B Lenguaje de programación predecesor del Lenguaje C,
creado por Ken Thompson y Dennis Ritchie. Esencialmente, es una simplificación del lenguaje BCPL. Sólo tenía un tipo de datos, que correspondía con una palabra de máquina.
Lenguaje C Lenguaje de programación estructurado creado por Ken
Thompson y Dennis M. Ritchie en los Laboratorios Bell como evolución del lenguaje B Está orientado a la creación de sistemas operativos. Es un lenguaje de nivel
353
medio, que dispone de las estructuras típicas del alto nivel y construcciones de bajo nivel.
Lenguaje Ensamblador También llamado “código simbólico” es una
representación del código máquina, y es específico de cada arquitectura de computadoras.
Lenguaje Pascal Lenguaje de programación creado por el profesor suizo
Niklaus Wirth a finales de los 60’s. Es un lenguaje de programación estructurado, cuyo código está dividido en porciones fácilmente legibles llamadas funciones o procedimientos. Su nombre fue elegido en honor al matemático Blaise Pascal.
LINUX Sistema operativo, tipo UNIX, iniciado por Linus
Torvalds, paradigma del software libre, donde todo el código está disponible públicamente y cualquier persona con conocimientos adecuados, puede libremente estudiarlo, usarlo, modificarlo y redistribuirlo.
Macro Grupo de instrucciones que tienen un seguimiento
cronológico, usadas para economizar tareas. Mandriva Empresa francesa de software creada por Gaël Duval
dedicada a ofrecer y hacerse cargo de su distribución Linux, Mandriva Linux.
Perl Lenguaje práctico para la extracción e informe. Lenguaje
de programación diseñado por Larry Wall en 1987 y que toma características de C, del shell de UNIX, AWK, sed, lisp y otros.
PHP Lenguaje de programación usado para la creación de
contenidos de sitios web, y tiene similitud con C y Perl. Su nombre es un acrónimo recursivo: PHP: Hypertext Preprocessor.
Prompt Interfaz implementada por el intérprete de comandos, o
shell, y es el indicador de la línea de comando de un sistema operativo basado en texto (Command Line Interface, CLI en oposición a la Graphic User Interface, GUI)
Pseudolenguaje Un pseudocódigo o falso lenguaje, es una serie de normas
léxicas y gramaticales parecidas a la mayoría de los
354
lenguajes de programación, pero sin llegar a la rigidez de sintaxis de estos ni a la fluidez del lenguaje coloquial. Esto permite codificar un programa con mayor agilidad que en cualquier lenguaje de programación, con la misma validez semántica, normalmente se utiliza en las fases de análisis o diseño de Software, o en el estudio de un algoritmo. Forma parte de las distintas herramientas de la ingeniería de software.
Simula 67 Primer lenguaje de programación orientada a objetos
(OOP). Varios años después de su desarrollo, casi todos los lenguajes modernos comenzaron a utilizar sus principios de orientación a objetos, . Así fue como se popularizaron términos como clases, objetos, instancias, herencia, polimorfismo, etc. Por otra parte Simula 67 fue lanzado oficialmente por sus autores Ole Johan Dahl y Kristen Nygaard en mayo de 1967, en la Conferencia de Trabajo en Lenguajes de Simulación IFIO TC 2, en Lysebu cerca de Oslo
Tabla de verdad Las tablas de valores de verdad son una herramienta
desarrollada por Charles Peirce en los años 1880, siendo sin embargo más popular el formato que Ludwig Wittgenstein desarrolló en su Tractatus logico-philosophico, publicado en 1918 por Bertrand Russell. Se emplean en la lógica para determinar si una expresión es cierta o si un argumento es válido. Sus unidades mínimas se denominan proposiciones atómicas, y en un sistema lógico bivalente tienen dos posible valores de verdad: lo verdadero y lo falso. Las tablas de valores de verdad muestran los valores, las relaciones y los resultados posibles de realizar operaciones lógicas a expresiones lógicas.
Turbo C/C++ IDE y compilador para programar en lenguaje C
desarrollado por Borland. Su primera versión es de 1987, a la que siguieron las versiones 1.5 y 2.0 de1989. Fue el compilador más popular para desarrollar en C en entornos MS-DOS. Se le considera el primer IDE para C disponible para dicha plataforma. Sustituido por el Turbo C++ en 1990, este a su vez por el Borland C++, disponible también para Windows. Tras el Borland C++ llegó el C++Builder.
UNIX Es un sistema operativo portable, multitarea y
355
multiusuario; desarrollado en principio por un grupo de empleados de los laboratorios Bell de AT&T, entre los que figuran Ken Thompson, Dennis Ritchie y Douglas McIlroy. Hoy día, la palabra UNIX se utiliza para denotar diferentes conceptos dependiendo del contexto en que es usada. Esto suele dar lugar a confusiones:
Visual Basic Es un lenguaje de programación, así como el único IDE
visual y compilador que existen para él, desarrollado por Alan Cooper para Microsoft. El lenguaje de programación es un dialecto de BASIC, con importantes añadidos. Su primera versión fue presentada en 1991 con la intención de simplificar la programación utilizando un ambiente de desarrollo completamente gráfico que facilitara la creación de interfaces gráficas y en cierta medida también la programación misma.
Windows Sistema operativo en modo gráfico y con una arquitectura
de 32 bits. Este Sistema Operativo no requiere tener instalado ningún otro previamente. Incluye en todas sus versiones un emulador de consola en modo texto. A modo de anécdota, Windows NT 4.0 en origen no era compatible con tarjetas gráficas AGP. Requería la instalación de un Service Pack o conjunto de parches (de la versión 3 en adelante), que permitían su detección y la instalación de sus controladores.
XML (Acrónimo en inglés de eXtensible Markup Language,
‘lenguaje de marcas extensible’) es un metalenguaje extensible de etiquetas desarrollado por el World Wide Web Consortium (W3C). Es una simplificación y adaptación del SGML y permite definir la gramática de lenguajes específicos (de la misma manera que HTML es a su vez un lenguaje definido por SGML). Por lo tanto XML no es realmente un lenguaje en particular, sino una manera de definir lenguajes para diferentes necesidades. Algunos de estos lenguajes que usan XML para su definición son XHTML, SVG, MathML.
356
Bibliografía Bowman, CharlesF. Algoritmos y estructuras de datos.
Aproximación en C. Oxford University Press. México. 1994. 333 pp.
Curiel, Román. et al. C Elementos esenciales. Pearson
Educación. México. 2005, 173 pp.
García-Badell, J. Javier. Turbo C. Programación y manejo
de archivos. Macrobit / Ra-Ma. México. 1991. 208 pp.
García-Badell, J. Javier. Turbo C++ 3. Programación y
manejo de archivos. Addison Wesley Iberoamericana, RA-MA. U.S.A. 1994.542 pp.
Jamsa, Kris. C++ Programación exitosa. Alfaomega Grupo
Editor. U.S.A. 1994. 529 pp. Joyanes A., Luis. Fundamentos de programación.
Algoritmos y estructuras de datos. McGraw-Hill. Colombia. 1996. 714 pp.
Joyanes A., Luis. et al. Fundamentos de programación,
Libro de problemas. McGraw-Hill. España. 1996. 392 pp.
Langsam, Yedidyah. et al. Estructuras de datos con C y
C++. Prentice Hall Hispanoamericana. México. 1997. 565 pp.
Lipschutz, Seymour. Estructura de datos. McGraw-Hill.
México. 1995. 390 pp. Martínez H., Luis. Fundamentos de programación. Fondo
de Cultura Económica – DGETI. México. 2006. 325 pp.
357
Savitch, Walter. Resolución de problemas con C++. El objetivo de la programación. Pearson Educación. México. 2000. 915 pp.
Schildt, Herbert. Programación en Lenguaje C. Osborne /
McGraw-Hill. España. 1987. 235 pp.
Schildt, Herbert. Turbo C/C++. Manual de referencia.
Osborne / McGraw-Hill. México. 1993. 678 pp.
Schildt, Herbert. Turbo C. Programación avanzada.
Borland-Osborne / McGraw-Hill. España. 1990. 265 pp.
Sedwick, Robert. Algoritmos en C++. Addison-Wesley.
U.S.A. 1995. 726 pp. United States MSDN. http://msdn2.microsoft.com/en-
US/library/ 6aw8xdf2(VS.80).aspx. Consultada en Mayo 2006.
Wikipedia, la enciclopedia libre. http://es.wikipedia.org/
wiki/Portada Consultada en varias fechas a lo largo de la creación del texto. Mayo a noviembre 2006.
Tutoriales. C. Arreglos. http://sacbeob.8m.com/tutoriales /C /arreglos.htm. Consultada en
Mayo de 2006.