358
PROGRAMACION ESTRUCTURADA Rodolfo Gallardo Rosales

Programacion Estructurada - gallardo.mx · y una salida, y poseen como características la combinación de las estructuras lógicas de control mencionadas anteriormente, y se les

  • Upload
    ngohanh

  • View
    220

  • Download
    1

Embed Size (px)

Citation preview

0

PROGRAMACION ESTRUCTURADA

Rodolfo Gallardo Rosales

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.

8

Unidad 1: Elementos del Lenguaje C.

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

46

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

82

>

Mayor o igual a

<

Menor o igual a

= =

Diferente de

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

89

Unidad 2: Estructuras de control.

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; }

156

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(); }

171

Unidad 3: Arreglos.

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.

251

RESULTADOS.

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

266

Unidad 4: Funciones definidas por el usuario.

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; }

286

287

El programa funcionando, debe darnos resultados como los que siguen:

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)

295

Enseguida, traducimos el diagrama a código en Lenguaje C.

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.

302

Unidad 5: Estructuras y archivos

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.